• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * TLSv1 credentials
3  * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "includes.h"
10 
11 #include "common.h"
12 #include "base64.h"
13 #include "crypto/crypto.h"
14 #include "crypto/sha1.h"
15 #include "pkcs5.h"
16 #include "pkcs8.h"
17 #include "x509v3.h"
18 #include "tlsv1_cred.h"
19 
20 
tlsv1_cred_alloc(void)21 struct tlsv1_credentials * tlsv1_cred_alloc(void)
22 {
23 	struct tlsv1_credentials *cred;
24 	cred = os_zalloc(sizeof(*cred));
25 	return cred;
26 }
27 
28 
tlsv1_cred_free(struct tlsv1_credentials * cred)29 void tlsv1_cred_free(struct tlsv1_credentials *cred)
30 {
31 	if (cred == NULL)
32 		return;
33 
34 	x509_certificate_chain_free(cred->trusted_certs);
35 	x509_certificate_chain_free(cred->cert);
36 	crypto_private_key_free(cred->key);
37 	os_free(cred->dh_p);
38 	os_free(cred->dh_g);
39 	os_free(cred->ocsp_stapling_response);
40 	os_free(cred->ocsp_stapling_response_multi);
41 	os_free(cred);
42 }
43 
44 
tlsv1_add_cert_der(struct x509_certificate ** chain,const u8 * buf,size_t len)45 static int tlsv1_add_cert_der(struct x509_certificate **chain,
46 			      const u8 *buf, size_t len)
47 {
48 	struct x509_certificate *cert, *p;
49 	char name[128];
50 
51 	cert = x509_certificate_parse(buf, len);
52 	if (cert == NULL) {
53 		wpa_printf(MSG_INFO, "TLSv1: %s - failed to parse certificate",
54 			   __func__);
55 		return -1;
56 	}
57 
58 	p = *chain;
59 	while (p && p->next)
60 		p = p->next;
61 	if (p && x509_name_compare(&cert->subject, &p->issuer) == 0) {
62 		/*
63 		 * The new certificate is the issuer of the last certificate in
64 		 * the chain - add the new certificate to the end.
65 		 */
66 		p->next = cert;
67 	} else {
68 		/* Add to the beginning of the chain */
69 		cert->next = *chain;
70 		*chain = cert;
71 	}
72 
73 	x509_name_string(&cert->subject, name, sizeof(name));
74 	wpa_printf(MSG_DEBUG, "TLSv1: Added certificate: %s", name);
75 
76 	return 0;
77 }
78 
79 
80 static const char *pem_cert_begin = "-----BEGIN CERTIFICATE-----";
81 static const char *pem_cert_end = "-----END CERTIFICATE-----";
82 static const char *pem_key_begin = "-----BEGIN RSA PRIVATE KEY-----";
83 static const char *pem_key_end = "-----END RSA PRIVATE KEY-----";
84 static const char *pem_key2_begin = "-----BEGIN PRIVATE KEY-----";
85 static const char *pem_key2_end = "-----END PRIVATE KEY-----";
86 static const char *pem_key_enc_begin = "-----BEGIN ENCRYPTED PRIVATE KEY-----";
87 static const char *pem_key_enc_end = "-----END ENCRYPTED PRIVATE KEY-----";
88 
89 
search_tag(const char * tag,const u8 * buf,size_t len)90 static const u8 * search_tag(const char *tag, const u8 *buf, size_t len)
91 {
92 	size_t i, plen;
93 
94 	plen = os_strlen(tag);
95 	if (len < plen)
96 		return NULL;
97 
98 	for (i = 0; i < len - plen; i++) {
99 		if (os_memcmp(buf + i, tag, plen) == 0)
100 			return buf + i;
101 	}
102 
103 	return NULL;
104 }
105 
106 
tlsv1_add_cert(struct x509_certificate ** chain,const u8 * buf,size_t len)107 static int tlsv1_add_cert(struct x509_certificate **chain,
108 			  const u8 *buf, size_t len)
109 {
110 	const u8 *pos, *end;
111 	unsigned char *der;
112 	size_t der_len;
113 
114 	pos = search_tag(pem_cert_begin, buf, len);
115 	if (!pos) {
116 		wpa_printf(MSG_DEBUG, "TLSv1: No PEM certificate tag found - "
117 			   "assume DER format");
118 		return tlsv1_add_cert_der(chain, buf, len);
119 	}
120 
121 	wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format certificate into "
122 		   "DER format");
123 
124 	while (pos) {
125 		pos += os_strlen(pem_cert_begin);
126 		end = search_tag(pem_cert_end, pos, buf + len - pos);
127 		if (end == NULL) {
128 			wpa_printf(MSG_INFO, "TLSv1: Could not find PEM "
129 				   "certificate end tag (%s)", pem_cert_end);
130 			return -1;
131 		}
132 
133 		der = base64_decode((const char *) pos, end - pos, &der_len);
134 		if (der == NULL) {
135 			wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM "
136 				   "certificate");
137 			return -1;
138 		}
139 
140 		if (tlsv1_add_cert_der(chain, der, der_len) < 0) {
141 			wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM "
142 				   "certificate after DER conversion");
143 			os_free(der);
144 			return -1;
145 		}
146 
147 		os_free(der);
148 
149 		end += os_strlen(pem_cert_end);
150 		pos = search_tag(pem_cert_begin, end, buf + len - end);
151 	}
152 
153 	return 0;
154 }
155 
156 
tlsv1_set_cert_chain(struct x509_certificate ** chain,const char * cert,const u8 * cert_blob,size_t cert_blob_len)157 static int tlsv1_set_cert_chain(struct x509_certificate **chain,
158 				const char *cert, const u8 *cert_blob,
159 				size_t cert_blob_len)
160 {
161 	if (cert_blob)
162 		return tlsv1_add_cert(chain, cert_blob, cert_blob_len);
163 
164 	if (cert) {
165 		u8 *buf;
166 		size_t len;
167 		int ret;
168 
169 		buf = (u8 *) os_readfile(cert, &len);
170 		if (buf == NULL) {
171 			wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'",
172 				   cert);
173 			return -1;
174 		}
175 
176 		ret = tlsv1_add_cert(chain, buf, len);
177 		os_free(buf);
178 		return ret;
179 	}
180 
181 	return 0;
182 }
183 
184 
185 /**
186  * tlsv1_set_ca_cert - Set trusted CA certificate(s)
187  * @cred: TLSv1 credentials from tlsv1_cred_alloc()
188  * @cert: File or reference name for X.509 certificate in PEM or DER format
189  * @cert_blob: cert as inlined data or %NULL if not used
190  * @cert_blob_len: ca_cert_blob length
191  * @path: Path to CA certificates (not yet supported)
192  * Returns: 0 on success, -1 on failure
193  */
tlsv1_set_ca_cert(struct tlsv1_credentials * cred,const char * cert,const u8 * cert_blob,size_t cert_blob_len,const char * path)194 int tlsv1_set_ca_cert(struct tlsv1_credentials *cred, const char *cert,
195 		      const u8 *cert_blob, size_t cert_blob_len,
196 		      const char *path)
197 {
198 	if (cert && os_strncmp(cert, "hash://", 7) == 0) {
199 		const char *pos = cert + 7;
200 		if (os_strncmp(pos, "server/sha256/", 14) != 0) {
201 			wpa_printf(MSG_DEBUG,
202 				   "TLSv1: Unsupported ca_cert hash value '%s'",
203 				   cert);
204 			return -1;
205 		}
206 		pos += 14;
207 		if (os_strlen(pos) != 32 * 2) {
208 			wpa_printf(MSG_DEBUG,
209 				   "TLSv1: Unexpected SHA256 hash length in ca_cert '%s'",
210 				   cert);
211 			return -1;
212 		}
213 		if (hexstr2bin(pos, cred->srv_cert_hash, 32) < 0) {
214 			wpa_printf(MSG_DEBUG,
215 				   "TLSv1: Invalid SHA256 hash value in ca_cert '%s'",
216 				   cert);
217 			return -1;
218 		}
219 		cred->server_cert_only = 1;
220 		cred->ca_cert_verify = 0;
221 		wpa_printf(MSG_DEBUG,
222 			   "TLSv1: Checking only server certificate match");
223 		return 0;
224 	}
225 
226 	if (cert && os_strncmp(cert, "probe://", 8) == 0) {
227 		cred->cert_probe = 1;
228 		cred->ca_cert_verify = 0;
229 		wpa_printf(MSG_DEBUG, "TLSv1: Only probe server certificate");
230 		return 0;
231 	}
232 
233 	cred->ca_cert_verify = cert || cert_blob || path;
234 
235 	if (tlsv1_set_cert_chain(&cred->trusted_certs, cert,
236 				 cert_blob, cert_blob_len) < 0)
237 		return -1;
238 
239 	if (path) {
240 		/* TODO: add support for reading number of certificate files */
241 		wpa_printf(MSG_INFO, "TLSv1: Use of CA certificate directory "
242 			   "not yet supported");
243 		return -1;
244 	}
245 
246 	return 0;
247 }
248 
249 
250 /**
251  * tlsv1_set_cert - Set certificate
252  * @cred: TLSv1 credentials from tlsv1_cred_alloc()
253  * @cert: File or reference name for X.509 certificate in PEM or DER format
254  * @cert_blob: cert as inlined data or %NULL if not used
255  * @cert_blob_len: cert_blob length
256  * Returns: 0 on success, -1 on failure
257  */
tlsv1_set_cert(struct tlsv1_credentials * cred,const char * cert,const u8 * cert_blob,size_t cert_blob_len)258 int tlsv1_set_cert(struct tlsv1_credentials *cred, const char *cert,
259 		   const u8 *cert_blob, size_t cert_blob_len)
260 {
261 	return tlsv1_set_cert_chain(&cred->cert, cert,
262 				    cert_blob, cert_blob_len);
263 }
264 
265 
tlsv1_set_key_pem(const u8 * key,size_t len)266 static struct crypto_private_key * tlsv1_set_key_pem(const u8 *key, size_t len)
267 {
268 	const u8 *pos, *end;
269 	unsigned char *der;
270 	size_t der_len;
271 	struct crypto_private_key *pkey;
272 
273 	pos = search_tag(pem_key_begin, key, len);
274 	if (!pos) {
275 		pos = search_tag(pem_key2_begin, key, len);
276 		if (!pos)
277 			return NULL;
278 		pos += os_strlen(pem_key2_begin);
279 		end = search_tag(pem_key2_end, pos, key + len - pos);
280 		if (!end)
281 			return NULL;
282 	} else {
283 		const u8 *pos2;
284 		pos += os_strlen(pem_key_begin);
285 		end = search_tag(pem_key_end, pos, key + len - pos);
286 		if (!end)
287 			return NULL;
288 		pos2 = search_tag("Proc-Type: 4,ENCRYPTED", pos, end - pos);
289 		if (pos2) {
290 			wpa_printf(MSG_DEBUG, "TLSv1: Unsupported private key "
291 				   "format (Proc-Type/DEK-Info)");
292 			return NULL;
293 		}
294 	}
295 
296 	der = base64_decode((const char *) pos, end - pos, &der_len);
297 	if (!der)
298 		return NULL;
299 	pkey = crypto_private_key_import(der, der_len, NULL);
300 	os_free(der);
301 	return pkey;
302 }
303 
304 
tlsv1_set_key_enc_pem(const u8 * key,size_t len,const char * passwd)305 static struct crypto_private_key * tlsv1_set_key_enc_pem(const u8 *key,
306 							 size_t len,
307 							 const char *passwd)
308 {
309 	const u8 *pos, *end;
310 	unsigned char *der;
311 	size_t der_len;
312 	struct crypto_private_key *pkey;
313 
314 	if (passwd == NULL)
315 		return NULL;
316 	pos = search_tag(pem_key_enc_begin, key, len);
317 	if (!pos)
318 		return NULL;
319 	pos += os_strlen(pem_key_enc_begin);
320 	end = search_tag(pem_key_enc_end, pos, key + len - pos);
321 	if (!end)
322 		return NULL;
323 
324 	der = base64_decode((const char *) pos, end - pos, &der_len);
325 	if (!der)
326 		return NULL;
327 	pkey = crypto_private_key_import(der, der_len, passwd);
328 	os_free(der);
329 	return pkey;
330 }
331 
332 
333 #ifdef PKCS12_FUNCS
334 
oid_is_rsadsi(struct asn1_oid * oid)335 static int oid_is_rsadsi(struct asn1_oid *oid)
336 {
337 	return oid->len >= 4 &&
338 		oid->oid[0] == 1 /* iso */ &&
339 		oid->oid[1] == 2 /* member-body */ &&
340 		oid->oid[2] == 840 /* us */ &&
341 		oid->oid[3] == 113549 /* rsadsi */;
342 }
343 
344 
pkcs12_is_bagtype_oid(struct asn1_oid * oid,unsigned long type)345 static int pkcs12_is_bagtype_oid(struct asn1_oid *oid, unsigned long type)
346 {
347 	return oid->len == 9 &&
348 		oid_is_rsadsi(oid) &&
349 		oid->oid[4] == 1 /* pkcs */ &&
350 		oid->oid[5] == 12 /* pkcs-12 */ &&
351 		oid->oid[6] == 10 &&
352 		oid->oid[7] == 1 /* bagtypes */ &&
353 		oid->oid[8] == type;
354 }
355 
356 
is_oid_pkcs7(struct asn1_oid * oid)357 static int is_oid_pkcs7(struct asn1_oid *oid)
358 {
359 	return oid->len == 7 &&
360 		oid->oid[0] == 1 /* iso */ &&
361 		oid->oid[1] == 2 /* member-body */ &&
362 		oid->oid[2] == 840 /* us */ &&
363 		oid->oid[3] == 113549 /* rsadsi */ &&
364 		oid->oid[4] == 1 /* pkcs */ &&
365 		oid->oid[5] == 7 /* pkcs-7 */;
366 }
367 
368 
is_oid_pkcs7_data(struct asn1_oid * oid)369 static int is_oid_pkcs7_data(struct asn1_oid *oid)
370 {
371 	return is_oid_pkcs7(oid) && oid->oid[6] == 1 /* data */;
372 }
373 
374 
is_oid_pkcs7_enc_data(struct asn1_oid * oid)375 static int is_oid_pkcs7_enc_data(struct asn1_oid *oid)
376 {
377 	return is_oid_pkcs7(oid) && oid->oid[6] == 6 /* encryptedData */;
378 }
379 
380 
is_oid_pkcs9(struct asn1_oid * oid)381 static int is_oid_pkcs9(struct asn1_oid *oid)
382 {
383 	return oid->len >= 6 &&
384 		oid->oid[0] == 1 /* iso */ &&
385 		oid->oid[1] == 2 /* member-body */ &&
386 		oid->oid[2] == 840 /* us */ &&
387 		oid->oid[3] == 113549 /* rsadsi */ &&
388 		oid->oid[4] == 1 /* pkcs */ &&
389 		oid->oid[5] == 9 /* pkcs-9 */;
390 }
391 
392 
is_oid_pkcs9_friendly_name(struct asn1_oid * oid)393 static int is_oid_pkcs9_friendly_name(struct asn1_oid *oid)
394 {
395 	return oid->len == 7 && is_oid_pkcs9(oid) &&
396 		oid->oid[6] == 20;
397 }
398 
399 
is_oid_pkcs9_local_key_id(struct asn1_oid * oid)400 static int is_oid_pkcs9_local_key_id(struct asn1_oid *oid)
401 {
402 	return oid->len == 7 && is_oid_pkcs9(oid) &&
403 		oid->oid[6] == 21;
404 }
405 
406 
is_oid_pkcs9_x509_cert(struct asn1_oid * oid)407 static int is_oid_pkcs9_x509_cert(struct asn1_oid *oid)
408 {
409 	return oid->len == 8 && is_oid_pkcs9(oid) &&
410 		oid->oid[6] == 22 /* certTypes */ &&
411 		oid->oid[7] == 1 /* x509Certificate */;
412 }
413 
414 
pkcs12_keybag(struct tlsv1_credentials * cred,const u8 * buf,size_t len)415 static int pkcs12_keybag(struct tlsv1_credentials *cred,
416 			 const u8 *buf, size_t len)
417 {
418 	/* TODO */
419 	return 0;
420 }
421 
422 
pkcs12_pkcs8_keybag(struct tlsv1_credentials * cred,const u8 * buf,size_t len,const char * passwd)423 static int pkcs12_pkcs8_keybag(struct tlsv1_credentials *cred,
424 			       const u8 *buf, size_t len,
425 			       const char *passwd)
426 {
427 	struct crypto_private_key *key;
428 
429 	/* PKCS8ShroudedKeyBag ::= EncryptedPrivateKeyInfo */
430 	key = pkcs8_enc_key_import(buf, len, passwd);
431 	if (!key)
432 		return -1;
433 
434 	wpa_printf(MSG_DEBUG,
435 		   "PKCS #12: Successfully decrypted PKCS8ShroudedKeyBag");
436 	crypto_private_key_free(cred->key);
437 	cred->key = key;
438 
439 	return 0;
440 }
441 
442 
pkcs12_certbag(struct tlsv1_credentials * cred,const u8 * buf,size_t len)443 static int pkcs12_certbag(struct tlsv1_credentials *cred,
444 			  const u8 *buf, size_t len)
445 {
446 	struct asn1_hdr hdr;
447 	struct asn1_oid oid;
448 	char obuf[80];
449 	const u8 *pos, *end;
450 
451 	/*
452 	 * CertBag ::= SEQUENCE {
453 	 *     certId      BAG-TYPE.&id   ({CertTypes}),
454 	 *     certValue   [0] EXPLICIT BAG-TYPE.&Type ({CertTypes}{@certId})
455 	 * }
456 	 */
457 
458 	if (asn1_get_next(buf, len, &hdr) < 0 ||
459 	    hdr.class != ASN1_CLASS_UNIVERSAL ||
460 	    hdr.tag != ASN1_TAG_SEQUENCE) {
461 		wpa_printf(MSG_DEBUG,
462 			   "PKCS #12: Expected SEQUENCE (CertBag) - found class %d tag 0x%x",
463 			   hdr.class, hdr.tag);
464 		return -1;
465 	}
466 
467 	pos = hdr.payload;
468 	end = hdr.payload + hdr.length;
469 
470 	if (asn1_get_oid(pos, end - pos, &oid, &pos)) {
471 		wpa_printf(MSG_DEBUG,
472 			   "PKCS #12: Failed to parse OID (certId)");
473 		return -1;
474 	}
475 
476 	asn1_oid_to_str(&oid, obuf, sizeof(obuf));
477 	wpa_printf(MSG_DEBUG, "PKCS #12: certId %s", obuf);
478 
479 	if (!is_oid_pkcs9_x509_cert(&oid)) {
480 		wpa_printf(MSG_DEBUG,
481 			   "PKCS #12: Ignored unsupported certificate type (certId %s)",
482 			   obuf);
483 	}
484 
485 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
486 	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
487 	    hdr.tag != 0) {
488 		wpa_printf(MSG_DEBUG,
489 			   "PKCS #12: Expected [0] EXPLICIT (certValue) - found class %d tag 0x%x",
490 			   hdr.class, hdr.tag);
491 		return -1;
492 	}
493 
494 	if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
495 	    hdr.class != ASN1_CLASS_UNIVERSAL ||
496 	    hdr.tag != ASN1_TAG_OCTETSTRING) {
497 		wpa_printf(MSG_DEBUG,
498 			   "PKCS #12: Expected OCTET STRING (x509Certificate) - found class %d tag 0x%x",
499 			   hdr.class, hdr.tag);
500 		return -1;
501 	}
502 
503 	wpa_hexdump(MSG_DEBUG, "PKCS #12: x509Certificate",
504 		    hdr.payload, hdr.length);
505 	if (cred->cert) {
506 		struct x509_certificate *cert;
507 
508 		wpa_printf(MSG_DEBUG, "PKCS #12: Ignore extra certificate");
509 		cert = x509_certificate_parse(hdr.payload, hdr.length);
510 		if (!cert) {
511 			wpa_printf(MSG_DEBUG,
512 				   "PKCS #12: Failed to parse x509Certificate");
513 			return 0;
514 		}
515 		x509_certificate_chain_free(cert);
516 
517 		return 0;
518 	}
519 	return tlsv1_set_cert(cred, NULL, hdr.payload, hdr.length);
520 }
521 
522 
pkcs12_parse_attr_friendly_name(const u8 * pos,const u8 * end)523 static int pkcs12_parse_attr_friendly_name(const u8 *pos, const u8 *end)
524 {
525 	struct asn1_hdr hdr;
526 
527 	/*
528 	 * RFC 2985, 5.5.1:
529 	 * friendlyName ATTRIBUTE ::= {
530 	 *         WITH SYNTAX BMPString (SIZE(1..pkcs-9-ub-friendlyName))
531 	 *         EQUALITY MATCHING RULE caseIgnoreMatch
532 	 *         SINGLE VALUE TRUE
533 	 *          ID pkcs-9-at-friendlyName
534 	 * }
535 	 */
536 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
537 	    hdr.class != ASN1_CLASS_UNIVERSAL ||
538 	    hdr.tag != ASN1_TAG_BMPSTRING) {
539 		wpa_printf(MSG_DEBUG,
540 			   "PKCS #12: Expected BMPSTRING (friendlyName) - found class %d tag 0x%x",
541 			   hdr.class, hdr.tag);
542 		return 0;
543 	}
544 	wpa_hexdump_ascii(MSG_DEBUG, "PKCS #12: friendlyName",
545 			  hdr.payload, hdr.length);
546 	return 0;
547 }
548 
549 
pkcs12_parse_attr_local_key_id(const u8 * pos,const u8 * end)550 static int pkcs12_parse_attr_local_key_id(const u8 *pos, const u8 *end)
551 {
552 	struct asn1_hdr hdr;
553 
554 	/*
555 	 * RFC 2985, 5.5.2:
556 	 * localKeyId ATTRIBUTE ::= {
557 	 *         WITH SYNTAX OCTET STRING
558 	 *         EQUALITY MATCHING RULE octetStringMatch
559 	 *         SINGLE VALUE TRUE
560 	 *         ID pkcs-9-at-localKeyId
561 	 * }
562 	 */
563 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
564 	    hdr.class != ASN1_CLASS_UNIVERSAL ||
565 	    hdr.tag != ASN1_TAG_OCTETSTRING) {
566 		wpa_printf(MSG_DEBUG,
567 			   "PKCS #12: Expected OCTET STRING (localKeyID) - found class %d tag 0x%x",
568 			   hdr.class, hdr.tag);
569 		return -1;
570 	}
571 	wpa_hexdump_key(MSG_DEBUG, "PKCS #12: localKeyID",
572 			hdr.payload, hdr.length);
573 	return 0;
574 }
575 
576 
pkcs12_parse_attr(const u8 * pos,size_t len)577 static int pkcs12_parse_attr(const u8 *pos, size_t len)
578 {
579 	const u8 *end = pos + len;
580 	struct asn1_hdr hdr;
581 	struct asn1_oid a_oid;
582 	char obuf[80];
583 
584 	/*
585 	 * PKCS12Attribute ::= SEQUENCE {
586 	 * attrId      ATTRIBUTE.&id ({PKCS12AttrSet}),
587 	 * attrValues  SET OF ATTRIBUTE.&Type ({PKCS12AttrSet}{@attrId})
588 	 * }
589 	 */
590 
591 	if (asn1_get_oid(pos, end - pos, &a_oid, &pos)) {
592 		wpa_printf(MSG_DEBUG, "PKCS #12: Failed to parse OID (attrId)");
593 		return -1;
594 	}
595 
596 	asn1_oid_to_str(&a_oid, obuf, sizeof(obuf));
597 	wpa_printf(MSG_DEBUG, "PKCS #12: attrId %s", obuf);
598 
599 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
600 	    hdr.class != ASN1_CLASS_UNIVERSAL ||
601 	    hdr.tag != ASN1_TAG_SET) {
602 		wpa_printf(MSG_DEBUG,
603 			   "PKCS #12: Expected SET (attrValues) - found class %d tag 0x%x",
604 			   hdr.class, hdr.tag);
605 		return -1;
606 	}
607 	wpa_hexdump_key(MSG_MSGDUMP, "PKCS #12: attrValues",
608 			hdr.payload, hdr.length);
609 	pos = hdr.payload;
610 	end = hdr.payload + hdr.length;
611 
612 	if (is_oid_pkcs9_friendly_name(&a_oid))
613 		return pkcs12_parse_attr_friendly_name(pos, end);
614 	if (is_oid_pkcs9_local_key_id(&a_oid))
615 		return pkcs12_parse_attr_local_key_id(pos, end);
616 
617 	wpa_printf(MSG_DEBUG, "PKCS #12: Ignore unknown attribute");
618 	return 0;
619 }
620 
621 
pkcs12_safebag(struct tlsv1_credentials * cred,const u8 * buf,size_t len,const char * passwd)622 static int pkcs12_safebag(struct tlsv1_credentials *cred,
623 			  const u8 *buf, size_t len, const char *passwd)
624 {
625 	struct asn1_hdr hdr;
626 	struct asn1_oid oid;
627 	char obuf[80];
628 	const u8 *pos = buf, *end = buf + len;
629 	const u8 *value;
630 	size_t value_len;
631 
632 	wpa_hexdump_key(MSG_MSGDUMP, "PKCS #12: SafeBag", buf, len);
633 
634 	/* BAG-TYPE ::= TYPE-IDENTIFIER */
635 	if (asn1_get_oid(pos, end - pos, &oid, &pos)) {
636 		wpa_printf(MSG_DEBUG,
637 			   "PKCS #12: Failed to parse OID (BAG-TYPE)");
638 		return -1;
639 	}
640 
641 	asn1_oid_to_str(&oid, obuf, sizeof(obuf));
642 	wpa_printf(MSG_DEBUG, "PKCS #12: BAG-TYPE %s", obuf);
643 
644 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
645 	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
646 	    hdr.tag != 0) {
647 		wpa_printf(MSG_DEBUG,
648 			   "PKCS #12: Expected [0] EXPLICIT (bagValue) - found class %d tag 0x%x",
649 			   hdr.class, hdr.tag);
650 		return 0;
651 	}
652 	value = hdr.payload;
653 	value_len = hdr.length;
654 	wpa_hexdump_key(MSG_MSGDUMP, "PKCS #12: bagValue", value, value_len);
655 	pos = hdr.payload + hdr.length;
656 
657 	if (pos < end) {
658 		/* bagAttributes  SET OF PKCS12Attribute OPTIONAL */
659 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
660 		    hdr.class != ASN1_CLASS_UNIVERSAL ||
661 		    hdr.tag != ASN1_TAG_SET) {
662 			wpa_printf(MSG_DEBUG,
663 				   "PKCS #12: Expected SET (bagAttributes) - found class %d tag 0x%x",
664 				   hdr.class, hdr.tag);
665 			return -1;
666 		}
667 		wpa_hexdump_key(MSG_MSGDUMP, "PKCS #12: bagAttributes",
668 				hdr.payload, hdr.length);
669 
670 		pos = hdr.payload;
671 		end = hdr.payload + hdr.length;
672 		while (pos < end) {
673 			/* PKCS12Attribute ::= SEQUENCE */
674 			if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
675 			    hdr.class != ASN1_CLASS_UNIVERSAL ||
676 			    hdr.tag != ASN1_TAG_SEQUENCE) {
677 				wpa_printf(MSG_DEBUG,
678 					   "PKCS #12: Expected SEQUENCE (PKCS12Attribute) - found class %d tag 0x%x",
679 					   hdr.class, hdr.tag);
680 				return -1;
681 			}
682 			if (pkcs12_parse_attr(hdr.payload, hdr.length) < 0)
683 				return -1;
684 			pos = hdr.payload + hdr.length;
685 		}
686 	}
687 
688 	if (pkcs12_is_bagtype_oid(&oid, 1))
689 		return pkcs12_keybag(cred, value, value_len);
690 	if (pkcs12_is_bagtype_oid(&oid, 2))
691 		return pkcs12_pkcs8_keybag(cred, value, value_len, passwd);
692 	if (pkcs12_is_bagtype_oid(&oid, 3))
693 		return pkcs12_certbag(cred, value, value_len);
694 
695 	wpa_printf(MSG_DEBUG, "PKCS #12: Ignore unsupported BAG-TYPE");
696 	return 0;
697 }
698 
699 
pkcs12_safecontents(struct tlsv1_credentials * cred,const u8 * buf,size_t len,const char * passwd)700 static int pkcs12_safecontents(struct tlsv1_credentials *cred,
701 			       const u8 *buf, size_t len,
702 			       const char *passwd)
703 {
704 	struct asn1_hdr hdr;
705 	const u8 *pos, *end;
706 
707 	/* SafeContents ::= SEQUENCE OF SafeBag */
708 	if (asn1_get_next(buf, len, &hdr) < 0 ||
709 	    hdr.class != ASN1_CLASS_UNIVERSAL ||
710 	    hdr.tag != ASN1_TAG_SEQUENCE) {
711 		wpa_printf(MSG_DEBUG,
712 			   "PKCS #12: Expected SEQUENCE (SafeContents) - found class %d tag 0x%x",
713 			   hdr.class, hdr.tag);
714 		return -1;
715 	}
716 	pos = hdr.payload;
717 	end = hdr.payload + hdr.length;
718 
719 	/*
720 	 * SafeBag ::= SEQUENCE {
721 	 *   bagId          BAG-TYPE.&id ({PKCS12BagSet})
722 	 *   bagValue       [0] EXPLICIT BAG-TYPE.&Type({PKCS12BagSet}{@bagId}),
723 	 *   bagAttributes  SET OF PKCS12Attribute OPTIONAL
724 	 * }
725 	 */
726 
727 	while (pos < end) {
728 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
729 		    hdr.class != ASN1_CLASS_UNIVERSAL ||
730 		    hdr.tag != ASN1_TAG_SEQUENCE) {
731 			wpa_printf(MSG_DEBUG,
732 				   "PKCS #12: Expected SEQUENCE (SafeBag) - found class %d tag 0x%x",
733 				   hdr.class, hdr.tag);
734 			return -1;
735 		}
736 		if (pkcs12_safebag(cred, hdr.payload, hdr.length, passwd) < 0)
737 			return -1;
738 		pos = hdr.payload + hdr.length;
739 	}
740 
741 	return 0;
742 }
743 
744 
pkcs12_parse_content_data(struct tlsv1_credentials * cred,const u8 * pos,const u8 * end,const char * passwd)745 static int pkcs12_parse_content_data(struct tlsv1_credentials *cred,
746 				     const u8 *pos, const u8 *end,
747 				     const char *passwd)
748 {
749 	struct asn1_hdr hdr;
750 
751 	/* Data ::= OCTET STRING */
752 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
753 	    hdr.class != ASN1_CLASS_UNIVERSAL ||
754 	    hdr.tag != ASN1_TAG_OCTETSTRING) {
755 		wpa_printf(MSG_DEBUG,
756 			   "PKCS #12: Expected OCTET STRING (Data) - found class %d tag 0x%x",
757 			   hdr.class, hdr.tag);
758 		return -1;
759 	}
760 
761 	wpa_hexdump(MSG_MSGDUMP, "PKCS #12: Data", hdr.payload, hdr.length);
762 
763 	return pkcs12_safecontents(cred, hdr.payload, hdr.length, passwd);
764 }
765 
766 
pkcs12_parse_content_enc_data(struct tlsv1_credentials * cred,const u8 * pos,const u8 * end,const char * passwd)767 static int pkcs12_parse_content_enc_data(struct tlsv1_credentials *cred,
768 					 const u8 *pos, const u8 *end,
769 					 const char *passwd)
770 {
771 	struct asn1_hdr hdr;
772 	struct asn1_oid oid;
773 	char buf[80];
774 	const u8 *enc_alg;
775 	u8 *data;
776 	size_t enc_alg_len, data_len;
777 	int res = -1;
778 
779 	/*
780 	 * EncryptedData ::= SEQUENCE {
781 	 *   version Version,
782 	 *   encryptedContentInfo EncryptedContentInfo }
783 	 */
784 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
785 	    hdr.class != ASN1_CLASS_UNIVERSAL ||
786 	    hdr.tag != ASN1_TAG_SEQUENCE) {
787 		wpa_printf(MSG_DEBUG,
788 			   "PKCS #12: Expected SEQUENCE (EncryptedData) - found class %d tag 0x%x",
789 			   hdr.class, hdr.tag);
790 		return 0;
791 	}
792 	pos = hdr.payload;
793 
794 	/* Version ::= INTEGER */
795 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
796 	    hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
797 		wpa_printf(MSG_DEBUG,
798 			   "PKCS #12: No INTEGER tag found for version; class=%d tag=0x%x",
799 			   hdr.class, hdr.tag);
800 		return -1;
801 	}
802 	if (hdr.length != 1 || hdr.payload[0] != 0) {
803 		wpa_printf(MSG_DEBUG, "PKCS #12: Unrecognized PKCS #7 version");
804 		return -1;
805 	}
806 	pos = hdr.payload + hdr.length;
807 
808 	wpa_hexdump(MSG_MSGDUMP, "PKCS #12: EncryptedContentInfo",
809 		    pos, end - pos);
810 
811 	/*
812 	 * EncryptedContentInfo ::= SEQUENCE {
813 	 *   contentType ContentType,
814 	 *   contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
815 	 *   encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL }
816 	 */
817 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
818 	    hdr.class != ASN1_CLASS_UNIVERSAL ||
819 	    hdr.tag != ASN1_TAG_SEQUENCE) {
820 		wpa_printf(MSG_DEBUG,
821 			   "PKCS #12: Expected SEQUENCE (EncryptedContentInfo) - found class %d tag 0x%x",
822 			   hdr.class, hdr.tag);
823 		return -1;
824 	}
825 
826 	pos = hdr.payload;
827 	end = pos + hdr.length;
828 
829 	/* ContentType ::= OBJECT IDENTIFIER */
830 	if (asn1_get_oid(pos, end - pos, &oid, &pos)) {
831 		wpa_printf(MSG_DEBUG,
832 			   "PKCS #12: Could not find OBJECT IDENTIFIER (contentType)");
833 		return -1;
834 	}
835 	asn1_oid_to_str(&oid, buf, sizeof(buf));
836 	wpa_printf(MSG_DEBUG, "PKCS #12: EncryptedContentInfo::contentType %s",
837 		   buf);
838 
839 	if (!is_oid_pkcs7_data(&oid)) {
840 		wpa_printf(MSG_DEBUG,
841 			   "PKCS #12: Unsupported EncryptedContentInfo::contentType %s",
842 			   buf);
843 		return 0;
844 	}
845 
846 	/* ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier */
847 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
848 	    hdr.class != ASN1_CLASS_UNIVERSAL ||
849 	    hdr.tag != ASN1_TAG_SEQUENCE) {
850 		wpa_printf(MSG_DEBUG, "PKCS #12: Expected SEQUENCE (ContentEncryptionAlgorithmIdentifier) - found class %d tag 0x%x",
851 			   hdr.class, hdr.tag);
852 		return -1;
853 	}
854 	enc_alg = hdr.payload;
855 	enc_alg_len = hdr.length;
856 	pos = hdr.payload + hdr.length;
857 
858 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
859 	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
860 	    hdr.tag != 0) {
861 		wpa_printf(MSG_DEBUG,
862 			   "PKCS #12: Expected [0] IMPLICIT (encryptedContent) - found class %d tag 0x%x",
863 			   hdr.class, hdr.tag);
864 		return -1;
865 	}
866 
867 	/* EncryptedContent ::= OCTET STRING */
868 	data = pkcs5_decrypt(enc_alg, enc_alg_len, hdr.payload, hdr.length,
869 			     passwd, &data_len);
870 	if (data) {
871 		wpa_hexdump_key(MSG_MSGDUMP,
872 				"PKCS #12: Decrypted encryptedContent",
873 				data, data_len);
874 		res = pkcs12_safecontents(cred, data, data_len, passwd);
875 		os_free(data);
876 	}
877 
878 	return res;
879 }
880 
881 
pkcs12_parse_content(struct tlsv1_credentials * cred,const u8 * buf,size_t len,const char * passwd)882 static int pkcs12_parse_content(struct tlsv1_credentials *cred,
883 				const u8 *buf, size_t len,
884 				const char *passwd)
885 {
886 	const u8 *pos = buf;
887 	const u8 *end = buf + len;
888 	struct asn1_oid oid;
889 	char txt[80];
890 	struct asn1_hdr hdr;
891 
892 	wpa_hexdump(MSG_MSGDUMP, "PKCS #12: ContentInfo", buf, len);
893 
894 	if (asn1_get_oid(pos, end - pos, &oid, &pos)) {
895 		wpa_printf(MSG_DEBUG,
896 			   "PKCS #12: Could not find OBJECT IDENTIFIER (contentType)");
897 		return 0;
898 	}
899 
900 	asn1_oid_to_str(&oid, txt, sizeof(txt));
901 	wpa_printf(MSG_DEBUG, "PKCS #12: contentType %s", txt);
902 
903 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
904 	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
905 	    hdr.tag != 0) {
906 		wpa_printf(MSG_DEBUG,
907 			   "PKCS #12: Expected [0] EXPLICIT (content) - found class %d tag 0x%x",
908 			   hdr.class, hdr.tag);
909 		return 0;
910 	}
911 	pos = hdr.payload;
912 
913 	if (is_oid_pkcs7_data(&oid))
914 		return pkcs12_parse_content_data(cred, pos, end, passwd);
915 	if (is_oid_pkcs7_enc_data(&oid))
916 		return pkcs12_parse_content_enc_data(cred, pos, end, passwd);
917 
918 	wpa_printf(MSG_DEBUG, "PKCS #12: Ignored unsupported contentType %s",
919 		   txt);
920 
921 	return 0;
922 }
923 
924 
pkcs12_parse(struct tlsv1_credentials * cred,const u8 * key,size_t len,const char * passwd)925 static int pkcs12_parse(struct tlsv1_credentials *cred,
926 			const u8 *key, size_t len, const char *passwd)
927 {
928 	struct asn1_hdr hdr;
929 	const u8 *pos, *end;
930 	struct asn1_oid oid;
931 	char buf[80];
932 
933 	/*
934 	 * PFX ::= SEQUENCE {
935 	 *     version     INTEGER {v3(3)}(v3,...),
936 	 *     authSafe    ContentInfo,
937 	 *     macData     MacData OPTIONAL
938 	 * }
939 	 */
940 
941 	if (asn1_get_next(key, len, &hdr) < 0 ||
942 	    hdr.class != ASN1_CLASS_UNIVERSAL ||
943 	    hdr.tag != ASN1_TAG_SEQUENCE) {
944 		wpa_printf(MSG_DEBUG,
945 			   "PKCS #12: Expected SEQUENCE (PFX) - found class %d tag 0x%x; assume PKCS #12 not used",
946 			   hdr.class, hdr.tag);
947 		return -1;
948 	}
949 
950 	pos = hdr.payload;
951 	end = pos + hdr.length;
952 
953 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
954 	    hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
955 		wpa_printf(MSG_DEBUG,
956 			   "PKCS #12: No INTEGER tag found for version; class=%d tag=0x%x",
957 			   hdr.class, hdr.tag);
958 		return -1;
959 	}
960 	if (hdr.length != 1 || hdr.payload[0] != 3) {
961 		wpa_printf(MSG_DEBUG, "PKCS #12: Unrecognized version");
962 		return -1;
963 	}
964 	pos = hdr.payload + hdr.length;
965 
966 	/*
967 	 * ContentInfo ::= SEQUENCE {
968 	 *   contentType ContentType,
969 	 *   content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
970 	 */
971 
972 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
973 	    hdr.class != ASN1_CLASS_UNIVERSAL ||
974 	    hdr.tag != ASN1_TAG_SEQUENCE) {
975 		wpa_printf(MSG_DEBUG,
976 			   "PKCS #12: Expected SEQUENCE (authSafe) - found class %d tag 0x%x; assume PKCS #12 not used",
977 			   hdr.class, hdr.tag);
978 		return -1;
979 	}
980 
981 	pos = hdr.payload;
982 	end = pos + hdr.length;
983 
984 	/* ContentType ::= OBJECT IDENTIFIER */
985 	if (asn1_get_oid(pos, end - pos, &oid, &pos)) {
986 		wpa_printf(MSG_DEBUG,
987 			   "PKCS #12: Could not find OBJECT IDENTIFIER (contentType); assume PKCS #12 not used");
988 		return -1;
989 	}
990 	asn1_oid_to_str(&oid, buf, sizeof(buf));
991 	wpa_printf(MSG_DEBUG, "PKCS #12: contentType %s", buf);
992 	if (!is_oid_pkcs7_data(&oid)) {
993 		wpa_printf(MSG_DEBUG, "PKCS #12: Unsupported contentType %s",
994 			   buf);
995 		return -1;
996 	}
997 
998 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
999 	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
1000 	    hdr.tag != 0) {
1001 		wpa_printf(MSG_DEBUG,
1002 			   "PKCS #12: Expected [0] EXPLICIT (content) - found class %d tag 0x%x; assume PKCS #12 not used",
1003 			   hdr.class, hdr.tag);
1004 		return -1;
1005 	}
1006 
1007 	pos = hdr.payload;
1008 
1009 	/* Data ::= OCTET STRING */
1010 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
1011 	    hdr.class != ASN1_CLASS_UNIVERSAL ||
1012 	    hdr.tag != ASN1_TAG_OCTETSTRING) {
1013 		wpa_printf(MSG_DEBUG,
1014 			   "PKCS #12: Expected OCTET STRING (Data) - found class %d tag 0x%x; assume PKCS #12 not used",
1015 			   hdr.class, hdr.tag);
1016 		return -1;
1017 	}
1018 
1019 	/*
1020 	 * AuthenticatedSafe ::= SEQUENCE OF ContentInfo
1021 	 *     -- Data if unencrypted
1022 	 *     -- EncryptedData if password-encrypted
1023 	 *     -- EnvelopedData if public key-encrypted
1024 	 */
1025 	wpa_hexdump(MSG_MSGDUMP, "PKCS #12: Data content",
1026 		    hdr.payload, hdr.length);
1027 
1028 	if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
1029 	    hdr.class != ASN1_CLASS_UNIVERSAL ||
1030 	    hdr.tag != ASN1_TAG_SEQUENCE) {
1031 		wpa_printf(MSG_DEBUG,
1032 			   "PKCS #12: Expected SEQUENCE within Data content - found class %d tag 0x%x; assume PKCS #12 not used",
1033 			   hdr.class, hdr.tag);
1034 		return -1;
1035 	}
1036 
1037 	pos = hdr.payload;
1038 	end = pos + hdr.length;
1039 
1040 	while (end > pos) {
1041 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
1042 		    hdr.class != ASN1_CLASS_UNIVERSAL ||
1043 		    hdr.tag != ASN1_TAG_SEQUENCE) {
1044 			wpa_printf(MSG_DEBUG,
1045 				   "PKCS #12: Expected SEQUENCE (ContentInfo) - found class %d tag 0x%x; assume PKCS #12 not used",
1046 				   hdr.class, hdr.tag);
1047 			return -1;
1048 		}
1049 		if (pkcs12_parse_content(cred, hdr.payload, hdr.length,
1050 					 passwd) < 0)
1051 			return -1;
1052 
1053 		pos = hdr.payload + hdr.length;
1054 	}
1055 
1056 	return 0;
1057 }
1058 
1059 #endif /* PKCS12_FUNCS */
1060 
1061 
tlsv1_set_key(struct tlsv1_credentials * cred,const u8 * key,size_t len,const char * passwd)1062 static int tlsv1_set_key(struct tlsv1_credentials *cred,
1063 			 const u8 *key, size_t len, const char *passwd)
1064 {
1065 	cred->key = crypto_private_key_import(key, len, passwd);
1066 	if (cred->key == NULL)
1067 		cred->key = tlsv1_set_key_pem(key, len);
1068 	if (cred->key == NULL)
1069 		cred->key = tlsv1_set_key_enc_pem(key, len, passwd);
1070 #ifdef PKCS12_FUNCS
1071 	if (!cred->key)
1072 		pkcs12_parse(cred, key, len, passwd);
1073 #endif /* PKCS12_FUNCS */
1074 	if (cred->key == NULL) {
1075 		wpa_printf(MSG_INFO, "TLSv1: Failed to parse private key");
1076 		return -1;
1077 	}
1078 	return 0;
1079 }
1080 
1081 
1082 /**
1083  * tlsv1_set_private_key - Set private key
1084  * @cred: TLSv1 credentials from tlsv1_cred_alloc()
1085  * @private_key: File or reference name for the key in PEM or DER format
1086  * @private_key_passwd: Passphrase for decrypted private key, %NULL if no
1087  * passphrase is used.
1088  * @private_key_blob: private_key as inlined data or %NULL if not used
1089  * @private_key_blob_len: private_key_blob length
1090  * Returns: 0 on success, -1 on failure
1091  */
tlsv1_set_private_key(struct tlsv1_credentials * cred,const char * private_key,const char * private_key_passwd,const u8 * private_key_blob,size_t private_key_blob_len)1092 int tlsv1_set_private_key(struct tlsv1_credentials *cred,
1093 			  const char *private_key,
1094 			  const char *private_key_passwd,
1095 			  const u8 *private_key_blob,
1096 			  size_t private_key_blob_len)
1097 {
1098 	crypto_private_key_free(cred->key);
1099 	cred->key = NULL;
1100 
1101 	if (private_key_blob)
1102 		return tlsv1_set_key(cred, private_key_blob,
1103 				     private_key_blob_len,
1104 				     private_key_passwd);
1105 
1106 	if (private_key) {
1107 		u8 *buf;
1108 		size_t len;
1109 		int ret;
1110 
1111 		buf = (u8 *) os_readfile(private_key, &len);
1112 		if (buf == NULL) {
1113 			wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'",
1114 				   private_key);
1115 			return -1;
1116 		}
1117 
1118 		ret = tlsv1_set_key(cred, buf, len, private_key_passwd);
1119 		os_free(buf);
1120 		return ret;
1121 	}
1122 
1123 	return 0;
1124 }
1125 
1126 
tlsv1_set_dhparams_der(struct tlsv1_credentials * cred,const u8 * dh,size_t len)1127 static int tlsv1_set_dhparams_der(struct tlsv1_credentials *cred,
1128 				  const u8 *dh, size_t len)
1129 {
1130 	struct asn1_hdr hdr;
1131 	const u8 *pos, *end;
1132 
1133 	pos = dh;
1134 	end = dh + len;
1135 
1136 	/*
1137 	 * DHParameter ::= SEQUENCE {
1138 	 *   prime INTEGER, -- p
1139 	 *   base INTEGER, -- g
1140 	 *   privateValueLength INTEGER OPTIONAL }
1141 	 */
1142 
1143 	/* DHParamer ::= SEQUENCE */
1144 	if (asn1_get_next(pos, len, &hdr) < 0 ||
1145 	    hdr.class != ASN1_CLASS_UNIVERSAL ||
1146 	    hdr.tag != ASN1_TAG_SEQUENCE) {
1147 		wpa_printf(MSG_DEBUG, "DH: DH parameters did not start with a "
1148 			   "valid SEQUENCE - found class %d tag 0x%x",
1149 			   hdr.class, hdr.tag);
1150 		return -1;
1151 	}
1152 	pos = hdr.payload;
1153 
1154 	/* prime INTEGER */
1155 	if (asn1_get_next(pos, end - pos, &hdr) < 0)
1156 		return -1;
1157 
1158 	if (hdr.class != ASN1_CLASS_UNIVERSAL ||
1159 	    hdr.tag != ASN1_TAG_INTEGER) {
1160 		wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for p; "
1161 			   "class=%d tag=0x%x", hdr.class, hdr.tag);
1162 		return -1;
1163 	}
1164 
1165 	wpa_hexdump(MSG_MSGDUMP, "DH: prime (p)", hdr.payload, hdr.length);
1166 	if (hdr.length == 0)
1167 		return -1;
1168 	os_free(cred->dh_p);
1169 	cred->dh_p = os_memdup(hdr.payload, hdr.length);
1170 	if (cred->dh_p == NULL)
1171 		return -1;
1172 	cred->dh_p_len = hdr.length;
1173 	pos = hdr.payload + hdr.length;
1174 
1175 	/* base INTEGER */
1176 	if (asn1_get_next(pos, end - pos, &hdr) < 0)
1177 		return -1;
1178 
1179 	if (hdr.class != ASN1_CLASS_UNIVERSAL ||
1180 	    hdr.tag != ASN1_TAG_INTEGER) {
1181 		wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for g; "
1182 			   "class=%d tag=0x%x", hdr.class, hdr.tag);
1183 		return -1;
1184 	}
1185 
1186 	wpa_hexdump(MSG_MSGDUMP, "DH: base (g)", hdr.payload, hdr.length);
1187 	if (hdr.length == 0)
1188 		return -1;
1189 	os_free(cred->dh_g);
1190 	cred->dh_g = os_memdup(hdr.payload, hdr.length);
1191 	if (cred->dh_g == NULL)
1192 		return -1;
1193 	cred->dh_g_len = hdr.length;
1194 
1195 	return 0;
1196 }
1197 
1198 
1199 static const char *pem_dhparams_begin = "-----BEGIN DH PARAMETERS-----";
1200 static const char *pem_dhparams_end = "-----END DH PARAMETERS-----";
1201 
1202 
tlsv1_set_dhparams_blob(struct tlsv1_credentials * cred,const u8 * buf,size_t len)1203 static int tlsv1_set_dhparams_blob(struct tlsv1_credentials *cred,
1204 				   const u8 *buf, size_t len)
1205 {
1206 	const u8 *pos, *end;
1207 	unsigned char *der;
1208 	size_t der_len;
1209 
1210 	pos = search_tag(pem_dhparams_begin, buf, len);
1211 	if (!pos) {
1212 		wpa_printf(MSG_DEBUG, "TLSv1: No PEM dhparams tag found - "
1213 			   "assume DER format");
1214 		return tlsv1_set_dhparams_der(cred, buf, len);
1215 	}
1216 
1217 	wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format dhparams into DER "
1218 		   "format");
1219 
1220 	pos += os_strlen(pem_dhparams_begin);
1221 	end = search_tag(pem_dhparams_end, pos, buf + len - pos);
1222 	if (end == NULL) {
1223 		wpa_printf(MSG_INFO, "TLSv1: Could not find PEM dhparams end "
1224 			   "tag (%s)", pem_dhparams_end);
1225 		return -1;
1226 	}
1227 
1228 	der = base64_decode((const char *) pos, end - pos, &der_len);
1229 	if (der == NULL) {
1230 		wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM dhparams");
1231 		return -1;
1232 	}
1233 
1234 	if (tlsv1_set_dhparams_der(cred, der, der_len) < 0) {
1235 		wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM dhparams "
1236 			   "DER conversion");
1237 		os_free(der);
1238 		return -1;
1239 	}
1240 
1241 	os_free(der);
1242 
1243 	return 0;
1244 }
1245 
1246 
1247 /**
1248  * tlsv1_set_dhparams - Set Diffie-Hellman parameters
1249  * @cred: TLSv1 credentials from tlsv1_cred_alloc()
1250  * @dh_file: File or reference name for the DH params in PEM or DER format
1251  * @dh_blob: DH params as inlined data or %NULL if not used
1252  * @dh_blob_len: dh_blob length
1253  * Returns: 0 on success, -1 on failure
1254  */
tlsv1_set_dhparams(struct tlsv1_credentials * cred,const char * dh_file,const u8 * dh_blob,size_t dh_blob_len)1255 int tlsv1_set_dhparams(struct tlsv1_credentials *cred, const char *dh_file,
1256 		       const u8 *dh_blob, size_t dh_blob_len)
1257 {
1258 	if (dh_blob)
1259 		return tlsv1_set_dhparams_blob(cred, dh_blob, dh_blob_len);
1260 
1261 	if (dh_file) {
1262 		u8 *buf;
1263 		size_t len;
1264 		int ret;
1265 
1266 		buf = (u8 *) os_readfile(dh_file, &len);
1267 		if (buf == NULL) {
1268 			wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'",
1269 				   dh_file);
1270 			return -1;
1271 		}
1272 
1273 		ret = tlsv1_set_dhparams_blob(cred, buf, len);
1274 		os_free(buf);
1275 		return ret;
1276 	}
1277 
1278 	return 0;
1279 }
1280