xref: /aosp_15_r20/external/wpa_supplicant_8/src/tls/pkcs1.c (revision 03f9172ca588f91df233974f4258bab95191f931)
1*03f9172cSAndroid Build Coastguard Worker /*
2*03f9172cSAndroid Build Coastguard Worker  * PKCS #1 (RSA Encryption)
3*03f9172cSAndroid Build Coastguard Worker  * Copyright (c) 2006-2014, Jouni Malinen <[email protected]>
4*03f9172cSAndroid Build Coastguard Worker  *
5*03f9172cSAndroid Build Coastguard Worker  * This software may be distributed under the terms of the BSD license.
6*03f9172cSAndroid Build Coastguard Worker  * See README for more details.
7*03f9172cSAndroid Build Coastguard Worker  */
8*03f9172cSAndroid Build Coastguard Worker 
9*03f9172cSAndroid Build Coastguard Worker #include "includes.h"
10*03f9172cSAndroid Build Coastguard Worker 
11*03f9172cSAndroid Build Coastguard Worker #include "common.h"
12*03f9172cSAndroid Build Coastguard Worker #include "crypto/crypto.h"
13*03f9172cSAndroid Build Coastguard Worker #include "rsa.h"
14*03f9172cSAndroid Build Coastguard Worker #include "asn1.h"
15*03f9172cSAndroid Build Coastguard Worker #include "pkcs1.h"
16*03f9172cSAndroid Build Coastguard Worker 
17*03f9172cSAndroid Build Coastguard Worker 
pkcs1_generate_encryption_block(u8 block_type,size_t modlen,const u8 * in,size_t inlen,u8 * out,size_t * outlen)18*03f9172cSAndroid Build Coastguard Worker static int pkcs1_generate_encryption_block(u8 block_type, size_t modlen,
19*03f9172cSAndroid Build Coastguard Worker 					   const u8 *in, size_t inlen,
20*03f9172cSAndroid Build Coastguard Worker 					   u8 *out, size_t *outlen)
21*03f9172cSAndroid Build Coastguard Worker {
22*03f9172cSAndroid Build Coastguard Worker 	size_t ps_len;
23*03f9172cSAndroid Build Coastguard Worker 	u8 *pos;
24*03f9172cSAndroid Build Coastguard Worker 
25*03f9172cSAndroid Build Coastguard Worker 	/*
26*03f9172cSAndroid Build Coastguard Worker 	 * PKCS #1 v1.5, 8.1:
27*03f9172cSAndroid Build Coastguard Worker 	 *
28*03f9172cSAndroid Build Coastguard Worker 	 * EB = 00 || BT || PS || 00 || D
29*03f9172cSAndroid Build Coastguard Worker 	 * BT = 00 or 01 for private-key operation; 02 for public-key operation
30*03f9172cSAndroid Build Coastguard Worker 	 * PS = k-3-||D||; at least eight octets
31*03f9172cSAndroid Build Coastguard Worker 	 * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero)
32*03f9172cSAndroid Build Coastguard Worker 	 * k = length of modulus in octets (modlen)
33*03f9172cSAndroid Build Coastguard Worker 	 */
34*03f9172cSAndroid Build Coastguard Worker 
35*03f9172cSAndroid Build Coastguard Worker 	if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) {
36*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer "
37*03f9172cSAndroid Build Coastguard Worker 			   "lengths (modlen=%lu outlen=%lu inlen=%lu)",
38*03f9172cSAndroid Build Coastguard Worker 			   __func__, (unsigned long) modlen,
39*03f9172cSAndroid Build Coastguard Worker 			   (unsigned long) *outlen,
40*03f9172cSAndroid Build Coastguard Worker 			   (unsigned long) inlen);
41*03f9172cSAndroid Build Coastguard Worker 		return -1;
42*03f9172cSAndroid Build Coastguard Worker 	}
43*03f9172cSAndroid Build Coastguard Worker 
44*03f9172cSAndroid Build Coastguard Worker 	pos = out;
45*03f9172cSAndroid Build Coastguard Worker 	*pos++ = 0x00;
46*03f9172cSAndroid Build Coastguard Worker 	*pos++ = block_type; /* BT */
47*03f9172cSAndroid Build Coastguard Worker 	ps_len = modlen - inlen - 3;
48*03f9172cSAndroid Build Coastguard Worker 	switch (block_type) {
49*03f9172cSAndroid Build Coastguard Worker 	case 0:
50*03f9172cSAndroid Build Coastguard Worker 		os_memset(pos, 0x00, ps_len);
51*03f9172cSAndroid Build Coastguard Worker 		pos += ps_len;
52*03f9172cSAndroid Build Coastguard Worker 		break;
53*03f9172cSAndroid Build Coastguard Worker 	case 1:
54*03f9172cSAndroid Build Coastguard Worker 		os_memset(pos, 0xff, ps_len);
55*03f9172cSAndroid Build Coastguard Worker 		pos += ps_len;
56*03f9172cSAndroid Build Coastguard Worker 		break;
57*03f9172cSAndroid Build Coastguard Worker 	case 2:
58*03f9172cSAndroid Build Coastguard Worker 		if (os_get_random(pos, ps_len) < 0) {
59*03f9172cSAndroid Build Coastguard Worker 			wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get "
60*03f9172cSAndroid Build Coastguard Worker 				   "random data for PS", __func__);
61*03f9172cSAndroid Build Coastguard Worker 			return -1;
62*03f9172cSAndroid Build Coastguard Worker 		}
63*03f9172cSAndroid Build Coastguard Worker 		while (ps_len--) {
64*03f9172cSAndroid Build Coastguard Worker 			if (*pos == 0x00)
65*03f9172cSAndroid Build Coastguard Worker 				*pos = 0x01;
66*03f9172cSAndroid Build Coastguard Worker 			pos++;
67*03f9172cSAndroid Build Coastguard Worker 		}
68*03f9172cSAndroid Build Coastguard Worker 		break;
69*03f9172cSAndroid Build Coastguard Worker 	default:
70*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type "
71*03f9172cSAndroid Build Coastguard Worker 			   "%d", __func__, block_type);
72*03f9172cSAndroid Build Coastguard Worker 		return -1;
73*03f9172cSAndroid Build Coastguard Worker 	}
74*03f9172cSAndroid Build Coastguard Worker 	*pos++ = 0x00;
75*03f9172cSAndroid Build Coastguard Worker 	os_memcpy(pos, in, inlen); /* D */
76*03f9172cSAndroid Build Coastguard Worker 
77*03f9172cSAndroid Build Coastguard Worker 	return 0;
78*03f9172cSAndroid Build Coastguard Worker }
79*03f9172cSAndroid Build Coastguard Worker 
80*03f9172cSAndroid Build Coastguard Worker 
pkcs1_encrypt(int block_type,struct crypto_rsa_key * key,int use_private,const u8 * in,size_t inlen,u8 * out,size_t * outlen)81*03f9172cSAndroid Build Coastguard Worker int pkcs1_encrypt(int block_type, struct crypto_rsa_key *key,
82*03f9172cSAndroid Build Coastguard Worker 		  int use_private, const u8 *in, size_t inlen,
83*03f9172cSAndroid Build Coastguard Worker 		  u8 *out, size_t *outlen)
84*03f9172cSAndroid Build Coastguard Worker {
85*03f9172cSAndroid Build Coastguard Worker 	size_t modlen;
86*03f9172cSAndroid Build Coastguard Worker 
87*03f9172cSAndroid Build Coastguard Worker 	modlen = crypto_rsa_get_modulus_len(key);
88*03f9172cSAndroid Build Coastguard Worker 
89*03f9172cSAndroid Build Coastguard Worker 	if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen,
90*03f9172cSAndroid Build Coastguard Worker 					    out, outlen) < 0)
91*03f9172cSAndroid Build Coastguard Worker 		return -1;
92*03f9172cSAndroid Build Coastguard Worker 
93*03f9172cSAndroid Build Coastguard Worker 	return crypto_rsa_exptmod(out, modlen, out, outlen, key, use_private);
94*03f9172cSAndroid Build Coastguard Worker }
95*03f9172cSAndroid Build Coastguard Worker 
96*03f9172cSAndroid Build Coastguard Worker 
pkcs1_v15_private_key_decrypt(struct crypto_rsa_key * key,const u8 * in,size_t inlen,u8 * out,size_t * outlen)97*03f9172cSAndroid Build Coastguard Worker int pkcs1_v15_private_key_decrypt(struct crypto_rsa_key *key,
98*03f9172cSAndroid Build Coastguard Worker 				  const u8 *in, size_t inlen,
99*03f9172cSAndroid Build Coastguard Worker 				  u8 *out, size_t *outlen)
100*03f9172cSAndroid Build Coastguard Worker {
101*03f9172cSAndroid Build Coastguard Worker 	int res;
102*03f9172cSAndroid Build Coastguard Worker 	u8 *pos, *end;
103*03f9172cSAndroid Build Coastguard Worker 
104*03f9172cSAndroid Build Coastguard Worker 	res = crypto_rsa_exptmod(in, inlen, out, outlen, key, 1);
105*03f9172cSAndroid Build Coastguard Worker 	if (res)
106*03f9172cSAndroid Build Coastguard Worker 		return res;
107*03f9172cSAndroid Build Coastguard Worker 
108*03f9172cSAndroid Build Coastguard Worker 	if (*outlen < 2 || out[0] != 0 || out[1] != 2)
109*03f9172cSAndroid Build Coastguard Worker 		return -1;
110*03f9172cSAndroid Build Coastguard Worker 
111*03f9172cSAndroid Build Coastguard Worker 	/* Skip PS (pseudorandom non-zero octets) */
112*03f9172cSAndroid Build Coastguard Worker 	pos = out + 2;
113*03f9172cSAndroid Build Coastguard Worker 	end = out + *outlen;
114*03f9172cSAndroid Build Coastguard Worker 	while (*pos && pos < end)
115*03f9172cSAndroid Build Coastguard Worker 		pos++;
116*03f9172cSAndroid Build Coastguard Worker 	if (pos == end)
117*03f9172cSAndroid Build Coastguard Worker 		return -1;
118*03f9172cSAndroid Build Coastguard Worker 	if (pos - out - 2 < 8) {
119*03f9172cSAndroid Build Coastguard Worker 		/* PKCS #1 v1.5, 8.1: At least eight octets long PS */
120*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "LibTomCrypt: Too short padding");
121*03f9172cSAndroid Build Coastguard Worker 		return -1;
122*03f9172cSAndroid Build Coastguard Worker 	}
123*03f9172cSAndroid Build Coastguard Worker 	pos++;
124*03f9172cSAndroid Build Coastguard Worker 
125*03f9172cSAndroid Build Coastguard Worker 	*outlen -= pos - out;
126*03f9172cSAndroid Build Coastguard Worker 
127*03f9172cSAndroid Build Coastguard Worker 	/* Strip PKCS #1 header */
128*03f9172cSAndroid Build Coastguard Worker 	os_memmove(out, pos, *outlen);
129*03f9172cSAndroid Build Coastguard Worker 
130*03f9172cSAndroid Build Coastguard Worker 	return 0;
131*03f9172cSAndroid Build Coastguard Worker }
132*03f9172cSAndroid Build Coastguard Worker 
133*03f9172cSAndroid Build Coastguard Worker 
pkcs1_decrypt_public_key(struct crypto_rsa_key * key,const u8 * crypt,size_t crypt_len,u8 * plain,size_t * plain_len)134*03f9172cSAndroid Build Coastguard Worker int pkcs1_decrypt_public_key(struct crypto_rsa_key *key,
135*03f9172cSAndroid Build Coastguard Worker 			     const u8 *crypt, size_t crypt_len,
136*03f9172cSAndroid Build Coastguard Worker 			     u8 *plain, size_t *plain_len)
137*03f9172cSAndroid Build Coastguard Worker {
138*03f9172cSAndroid Build Coastguard Worker 	size_t len;
139*03f9172cSAndroid Build Coastguard Worker 	u8 *pos;
140*03f9172cSAndroid Build Coastguard Worker 
141*03f9172cSAndroid Build Coastguard Worker 	len = *plain_len;
142*03f9172cSAndroid Build Coastguard Worker 	if (crypto_rsa_exptmod(crypt, crypt_len, plain, &len, key, 0) < 0)
143*03f9172cSAndroid Build Coastguard Worker 		return -1;
144*03f9172cSAndroid Build Coastguard Worker 
145*03f9172cSAndroid Build Coastguard Worker 	/*
146*03f9172cSAndroid Build Coastguard Worker 	 * PKCS #1 v1.5, 8.1:
147*03f9172cSAndroid Build Coastguard Worker 	 *
148*03f9172cSAndroid Build Coastguard Worker 	 * EB = 00 || BT || PS || 00 || D
149*03f9172cSAndroid Build Coastguard Worker 	 * BT = 00 or 01
150*03f9172cSAndroid Build Coastguard Worker 	 * PS = k-3-||D|| times (00 if BT=00) or (FF if BT=01)
151*03f9172cSAndroid Build Coastguard Worker 	 * k = length of modulus in octets
152*03f9172cSAndroid Build Coastguard Worker 	 *
153*03f9172cSAndroid Build Coastguard Worker 	 * Based on 10.1.3, "The block type shall be 01" for a signature.
154*03f9172cSAndroid Build Coastguard Worker 	 */
155*03f9172cSAndroid Build Coastguard Worker 
156*03f9172cSAndroid Build Coastguard Worker 	if (len < 3 + 8 + 16 /* min hash len */ ||
157*03f9172cSAndroid Build Coastguard Worker 	    plain[0] != 0x00 || plain[1] != 0x01) {
158*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
159*03f9172cSAndroid Build Coastguard Worker 			   "structure");
160*03f9172cSAndroid Build Coastguard Worker 		wpa_hexdump_key(MSG_DEBUG, "Signature EB", plain, len);
161*03f9172cSAndroid Build Coastguard Worker 		return -1;
162*03f9172cSAndroid Build Coastguard Worker 	}
163*03f9172cSAndroid Build Coastguard Worker 
164*03f9172cSAndroid Build Coastguard Worker 	pos = plain + 3;
165*03f9172cSAndroid Build Coastguard Worker 	/* BT = 01 */
166*03f9172cSAndroid Build Coastguard Worker 	if (plain[2] != 0xff) {
167*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature "
168*03f9172cSAndroid Build Coastguard Worker 			   "PS (BT=01)");
169*03f9172cSAndroid Build Coastguard Worker 		wpa_hexdump_key(MSG_DEBUG, "Signature EB", plain, len);
170*03f9172cSAndroid Build Coastguard Worker 		return -1;
171*03f9172cSAndroid Build Coastguard Worker 	}
172*03f9172cSAndroid Build Coastguard Worker 	while (pos < plain + len && *pos == 0xff)
173*03f9172cSAndroid Build Coastguard Worker 		pos++;
174*03f9172cSAndroid Build Coastguard Worker 
175*03f9172cSAndroid Build Coastguard Worker 	if (pos - plain - 2 < 8) {
176*03f9172cSAndroid Build Coastguard Worker 		/* PKCS #1 v1.5, 8.1: At least eight octets long PS */
177*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature "
178*03f9172cSAndroid Build Coastguard Worker 			   "padding");
179*03f9172cSAndroid Build Coastguard Worker 		wpa_hexdump_key(MSG_DEBUG, "Signature EB", plain, len);
180*03f9172cSAndroid Build Coastguard Worker 		return -1;
181*03f9172cSAndroid Build Coastguard Worker 	}
182*03f9172cSAndroid Build Coastguard Worker 
183*03f9172cSAndroid Build Coastguard Worker 	if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) {
184*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB "
185*03f9172cSAndroid Build Coastguard Worker 			   "structure (2)");
186*03f9172cSAndroid Build Coastguard Worker 		wpa_hexdump_key(MSG_DEBUG, "Signature EB", plain, len);
187*03f9172cSAndroid Build Coastguard Worker 		return -1;
188*03f9172cSAndroid Build Coastguard Worker 	}
189*03f9172cSAndroid Build Coastguard Worker 	pos++;
190*03f9172cSAndroid Build Coastguard Worker 	len -= pos - plain;
191*03f9172cSAndroid Build Coastguard Worker 
192*03f9172cSAndroid Build Coastguard Worker 	/* Strip PKCS #1 header */
193*03f9172cSAndroid Build Coastguard Worker 	os_memmove(plain, pos, len);
194*03f9172cSAndroid Build Coastguard Worker 	*plain_len = len;
195*03f9172cSAndroid Build Coastguard Worker 
196*03f9172cSAndroid Build Coastguard Worker 	return 0;
197*03f9172cSAndroid Build Coastguard Worker }
198*03f9172cSAndroid Build Coastguard Worker 
199*03f9172cSAndroid Build Coastguard Worker 
pkcs1_v15_sig_ver(struct crypto_public_key * pk,const u8 * s,size_t s_len,const struct asn1_oid * hash_alg,const u8 * hash,size_t hash_len)200*03f9172cSAndroid Build Coastguard Worker int pkcs1_v15_sig_ver(struct crypto_public_key *pk,
201*03f9172cSAndroid Build Coastguard Worker 		      const u8 *s, size_t s_len,
202*03f9172cSAndroid Build Coastguard Worker 		      const struct asn1_oid *hash_alg,
203*03f9172cSAndroid Build Coastguard Worker 		      const u8 *hash, size_t hash_len)
204*03f9172cSAndroid Build Coastguard Worker {
205*03f9172cSAndroid Build Coastguard Worker 	int res;
206*03f9172cSAndroid Build Coastguard Worker 	u8 *decrypted;
207*03f9172cSAndroid Build Coastguard Worker 	size_t decrypted_len;
208*03f9172cSAndroid Build Coastguard Worker 	const u8 *pos, *end, *next, *da_end;
209*03f9172cSAndroid Build Coastguard Worker 	struct asn1_hdr hdr;
210*03f9172cSAndroid Build Coastguard Worker 	struct asn1_oid oid;
211*03f9172cSAndroid Build Coastguard Worker 
212*03f9172cSAndroid Build Coastguard Worker 	decrypted = os_malloc(s_len);
213*03f9172cSAndroid Build Coastguard Worker 	if (decrypted == NULL)
214*03f9172cSAndroid Build Coastguard Worker 		return -1;
215*03f9172cSAndroid Build Coastguard Worker 	decrypted_len = s_len;
216*03f9172cSAndroid Build Coastguard Worker 	res = crypto_public_key_decrypt_pkcs1(pk, s, s_len, decrypted,
217*03f9172cSAndroid Build Coastguard Worker 					      &decrypted_len);
218*03f9172cSAndroid Build Coastguard Worker 	if (res < 0) {
219*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "PKCS #1: RSA decrypt failed");
220*03f9172cSAndroid Build Coastguard Worker 		os_free(decrypted);
221*03f9172cSAndroid Build Coastguard Worker 		return -1;
222*03f9172cSAndroid Build Coastguard Worker 	}
223*03f9172cSAndroid Build Coastguard Worker 	wpa_hexdump(MSG_DEBUG, "Decrypted(S)", decrypted, decrypted_len);
224*03f9172cSAndroid Build Coastguard Worker 
225*03f9172cSAndroid Build Coastguard Worker 	/*
226*03f9172cSAndroid Build Coastguard Worker 	 * PKCS #1 v1.5, 10.1.2:
227*03f9172cSAndroid Build Coastguard Worker 	 *
228*03f9172cSAndroid Build Coastguard Worker 	 * DigestInfo ::= SEQUENCE {
229*03f9172cSAndroid Build Coastguard Worker 	 *     digestAlgorithm DigestAlgorithmIdentifier,
230*03f9172cSAndroid Build Coastguard Worker 	 *     digest Digest
231*03f9172cSAndroid Build Coastguard Worker 	 * }
232*03f9172cSAndroid Build Coastguard Worker 	 *
233*03f9172cSAndroid Build Coastguard Worker 	 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
234*03f9172cSAndroid Build Coastguard Worker 	 *
235*03f9172cSAndroid Build Coastguard Worker 	 * Digest ::= OCTET STRING
236*03f9172cSAndroid Build Coastguard Worker 	 *
237*03f9172cSAndroid Build Coastguard Worker 	 */
238*03f9172cSAndroid Build Coastguard Worker 	if (asn1_get_next(decrypted, decrypted_len, &hdr) < 0 ||
239*03f9172cSAndroid Build Coastguard Worker 	    !asn1_is_sequence(&hdr)) {
240*03f9172cSAndroid Build Coastguard Worker 		asn1_unexpected(&hdr,
241*03f9172cSAndroid Build Coastguard Worker 				"PKCS #1: Expected SEQUENCE (DigestInfo)");
242*03f9172cSAndroid Build Coastguard Worker 		os_free(decrypted);
243*03f9172cSAndroid Build Coastguard Worker 		return -1;
244*03f9172cSAndroid Build Coastguard Worker 	}
245*03f9172cSAndroid Build Coastguard Worker 	wpa_hexdump(MSG_MSGDUMP, "PKCS #1: DigestInfo",
246*03f9172cSAndroid Build Coastguard Worker 		    hdr.payload, hdr.length);
247*03f9172cSAndroid Build Coastguard Worker 
248*03f9172cSAndroid Build Coastguard Worker 	pos = hdr.payload;
249*03f9172cSAndroid Build Coastguard Worker 	end = pos + hdr.length;
250*03f9172cSAndroid Build Coastguard Worker 
251*03f9172cSAndroid Build Coastguard Worker 	/*
252*03f9172cSAndroid Build Coastguard Worker 	 * X.509:
253*03f9172cSAndroid Build Coastguard Worker 	 * AlgorithmIdentifier ::= SEQUENCE {
254*03f9172cSAndroid Build Coastguard Worker 	 *     algorithm            OBJECT IDENTIFIER,
255*03f9172cSAndroid Build Coastguard Worker 	 *     parameters           ANY DEFINED BY algorithm OPTIONAL
256*03f9172cSAndroid Build Coastguard Worker 	 * }
257*03f9172cSAndroid Build Coastguard Worker 	 */
258*03f9172cSAndroid Build Coastguard Worker 
259*03f9172cSAndroid Build Coastguard Worker 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
260*03f9172cSAndroid Build Coastguard Worker 	    !asn1_is_sequence(&hdr)) {
261*03f9172cSAndroid Build Coastguard Worker 		asn1_unexpected(&hdr,
262*03f9172cSAndroid Build Coastguard Worker 				"PKCS #1: Expected SEQUENCE (AlgorithmIdentifier)");
263*03f9172cSAndroid Build Coastguard Worker 		os_free(decrypted);
264*03f9172cSAndroid Build Coastguard Worker 		return -1;
265*03f9172cSAndroid Build Coastguard Worker 	}
266*03f9172cSAndroid Build Coastguard Worker 	wpa_hexdump(MSG_MSGDUMP, "PKCS #1: DigestAlgorithmIdentifier",
267*03f9172cSAndroid Build Coastguard Worker 		    hdr.payload, hdr.length);
268*03f9172cSAndroid Build Coastguard Worker 	da_end = hdr.payload + hdr.length;
269*03f9172cSAndroid Build Coastguard Worker 
270*03f9172cSAndroid Build Coastguard Worker 	if (asn1_get_oid(hdr.payload, hdr.length, &oid, &next)) {
271*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG,
272*03f9172cSAndroid Build Coastguard Worker 			   "PKCS #1: Failed to parse digestAlgorithm");
273*03f9172cSAndroid Build Coastguard Worker 		os_free(decrypted);
274*03f9172cSAndroid Build Coastguard Worker 		return -1;
275*03f9172cSAndroid Build Coastguard Worker 	}
276*03f9172cSAndroid Build Coastguard Worker 	wpa_hexdump(MSG_MSGDUMP, "PKCS #1: Digest algorithm parameters",
277*03f9172cSAndroid Build Coastguard Worker 		    next, da_end - next);
278*03f9172cSAndroid Build Coastguard Worker 
279*03f9172cSAndroid Build Coastguard Worker 	/*
280*03f9172cSAndroid Build Coastguard Worker 	 * RFC 5754: The correct encoding for the SHA2 algorithms would be to
281*03f9172cSAndroid Build Coastguard Worker 	 * omit the parameters, but there are implementation that encode these
282*03f9172cSAndroid Build Coastguard Worker 	 * as a NULL element. Allow these two cases and reject anything else.
283*03f9172cSAndroid Build Coastguard Worker 	 */
284*03f9172cSAndroid Build Coastguard Worker 	if (da_end > next &&
285*03f9172cSAndroid Build Coastguard Worker 	    (asn1_get_next(next, da_end - next, &hdr) < 0 ||
286*03f9172cSAndroid Build Coastguard Worker 	     !asn1_is_null(&hdr) ||
287*03f9172cSAndroid Build Coastguard Worker 	     hdr.payload + hdr.length != da_end)) {
288*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG,
289*03f9172cSAndroid Build Coastguard Worker 			   "PKCS #1: Unexpected digest algorithm parameters");
290*03f9172cSAndroid Build Coastguard Worker 		os_free(decrypted);
291*03f9172cSAndroid Build Coastguard Worker 		return -1;
292*03f9172cSAndroid Build Coastguard Worker 	}
293*03f9172cSAndroid Build Coastguard Worker 
294*03f9172cSAndroid Build Coastguard Worker 	if (!asn1_oid_equal(&oid, hash_alg)) {
295*03f9172cSAndroid Build Coastguard Worker 		char txt[100], txt2[100];
296*03f9172cSAndroid Build Coastguard Worker 		asn1_oid_to_str(&oid, txt, sizeof(txt));
297*03f9172cSAndroid Build Coastguard Worker 		asn1_oid_to_str(hash_alg, txt2, sizeof(txt2));
298*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_DEBUG,
299*03f9172cSAndroid Build Coastguard Worker 			   "PKCS #1: Hash alg OID mismatch: was %s, expected %s",
300*03f9172cSAndroid Build Coastguard Worker 			   txt, txt2);
301*03f9172cSAndroid Build Coastguard Worker 		os_free(decrypted);
302*03f9172cSAndroid Build Coastguard Worker 		return -1;
303*03f9172cSAndroid Build Coastguard Worker 	}
304*03f9172cSAndroid Build Coastguard Worker 
305*03f9172cSAndroid Build Coastguard Worker 	/* Digest ::= OCTET STRING */
306*03f9172cSAndroid Build Coastguard Worker 	pos = da_end;
307*03f9172cSAndroid Build Coastguard Worker 
308*03f9172cSAndroid Build Coastguard Worker 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
309*03f9172cSAndroid Build Coastguard Worker 	    !asn1_is_octetstring(&hdr)) {
310*03f9172cSAndroid Build Coastguard Worker 		asn1_unexpected(&hdr,
311*03f9172cSAndroid Build Coastguard Worker 				"PKCS #1: Expected OCTETSTRING (Digest)");
312*03f9172cSAndroid Build Coastguard Worker 		os_free(decrypted);
313*03f9172cSAndroid Build Coastguard Worker 		return -1;
314*03f9172cSAndroid Build Coastguard Worker 	}
315*03f9172cSAndroid Build Coastguard Worker 	wpa_hexdump(MSG_MSGDUMP, "PKCS #1: Decrypted Digest",
316*03f9172cSAndroid Build Coastguard Worker 		    hdr.payload, hdr.length);
317*03f9172cSAndroid Build Coastguard Worker 
318*03f9172cSAndroid Build Coastguard Worker 	if (hdr.length != hash_len ||
319*03f9172cSAndroid Build Coastguard Worker 	    os_memcmp_const(hdr.payload, hash, hdr.length) != 0) {
320*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO, "PKCS #1: Digest value does not match calculated hash");
321*03f9172cSAndroid Build Coastguard Worker 		os_free(decrypted);
322*03f9172cSAndroid Build Coastguard Worker 		return -1;
323*03f9172cSAndroid Build Coastguard Worker 	}
324*03f9172cSAndroid Build Coastguard Worker 
325*03f9172cSAndroid Build Coastguard Worker 	if (hdr.payload + hdr.length != decrypted + decrypted_len) {
326*03f9172cSAndroid Build Coastguard Worker 		wpa_printf(MSG_INFO,
327*03f9172cSAndroid Build Coastguard Worker 			   "PKCS #1: Extra data after signature - reject");
328*03f9172cSAndroid Build Coastguard Worker 
329*03f9172cSAndroid Build Coastguard Worker 		wpa_hexdump(MSG_DEBUG, "PKCS #1: Extra data",
330*03f9172cSAndroid Build Coastguard Worker 			    hdr.payload + hdr.length,
331*03f9172cSAndroid Build Coastguard Worker 			    decrypted + decrypted_len - hdr.payload -
332*03f9172cSAndroid Build Coastguard Worker 			    hdr.length);
333*03f9172cSAndroid Build Coastguard Worker 
334*03f9172cSAndroid Build Coastguard Worker 		os_free(decrypted);
335*03f9172cSAndroid Build Coastguard Worker 		return -1;
336*03f9172cSAndroid Build Coastguard Worker 	}
337*03f9172cSAndroid Build Coastguard Worker 
338*03f9172cSAndroid Build Coastguard Worker 	os_free(decrypted);
339*03f9172cSAndroid Build Coastguard Worker 
340*03f9172cSAndroid Build Coastguard Worker 	return 0;
341*03f9172cSAndroid Build Coastguard Worker }
342