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 || !asn1_is_sequence(&hdr)) {
459 		asn1_unexpected(&hdr, "PKCS #12: Expected SEQUENCE (CertBag)");
460 		return -1;
461 	}
462 
463 	pos = hdr.payload;
464 	end = hdr.payload + hdr.length;
465 
466 	if (asn1_get_oid(pos, end - pos, &oid, &pos)) {
467 		wpa_printf(MSG_DEBUG,
468 			   "PKCS #12: Failed to parse OID (certId)");
469 		return -1;
470 	}
471 
472 	asn1_oid_to_str(&oid, obuf, sizeof(obuf));
473 	wpa_printf(MSG_DEBUG, "PKCS #12: certId %s", obuf);
474 
475 	if (!is_oid_pkcs9_x509_cert(&oid)) {
476 		wpa_printf(MSG_DEBUG,
477 			   "PKCS #12: Ignored unsupported certificate type (certId %s)",
478 			   obuf);
479 	}
480 
481 	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed ||
482 	    !asn1_is_cs_tag(&hdr, 0)) {
483 		asn1_unexpected(&hdr,
484 				"PKCS #12: Expected [0] EXPLICIT (certValue)");
485 		return -1;
486 	}
487 
488 	if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
489 	    !asn1_is_octetstring(&hdr)) {
490 		asn1_unexpected(&hdr,
491 				"PKCS #12: Expected OCTET STRING (x509Certificate)");
492 		return -1;
493 	}
494 
495 	wpa_hexdump(MSG_DEBUG, "PKCS #12: x509Certificate",
496 		    hdr.payload, hdr.length);
497 	if (cred->cert) {
498 		struct x509_certificate *cert;
499 
500 		wpa_printf(MSG_DEBUG, "PKCS #12: Ignore extra certificate");
501 		cert = x509_certificate_parse(hdr.payload, hdr.length);
502 		if (!cert) {
503 			wpa_printf(MSG_DEBUG,
504 				   "PKCS #12: Failed to parse x509Certificate");
505 			return 0;
506 		}
507 		x509_certificate_chain_free(cert);
508 
509 		return 0;
510 	}
511 	return tlsv1_set_cert(cred, NULL, hdr.payload, hdr.length);
512 }
513 
514 
pkcs12_parse_attr_friendly_name(const u8 * pos,const u8 * end)515 static int pkcs12_parse_attr_friendly_name(const u8 *pos, const u8 *end)
516 {
517 	struct asn1_hdr hdr;
518 
519 	/*
520 	 * RFC 2985, 5.5.1:
521 	 * friendlyName ATTRIBUTE ::= {
522 	 *         WITH SYNTAX BMPString (SIZE(1..pkcs-9-ub-friendlyName))
523 	 *         EQUALITY MATCHING RULE caseIgnoreMatch
524 	 *         SINGLE VALUE TRUE
525 	 *          ID pkcs-9-at-friendlyName
526 	 * }
527 	 */
528 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
529 	    !asn1_is_bmpstring(&hdr)) {
530 		asn1_unexpected(&hdr,
531 				"PKCS #12: Expected BMPSTRING (friendlyName)");
532 		return 0;
533 	}
534 	wpa_hexdump_ascii(MSG_DEBUG, "PKCS #12: friendlyName",
535 			  hdr.payload, hdr.length);
536 	return 0;
537 }
538 
539 
pkcs12_parse_attr_local_key_id(const u8 * pos,const u8 * end)540 static int pkcs12_parse_attr_local_key_id(const u8 *pos, const u8 *end)
541 {
542 	struct asn1_hdr hdr;
543 
544 	/*
545 	 * RFC 2985, 5.5.2:
546 	 * localKeyId ATTRIBUTE ::= {
547 	 *         WITH SYNTAX OCTET STRING
548 	 *         EQUALITY MATCHING RULE octetStringMatch
549 	 *         SINGLE VALUE TRUE
550 	 *         ID pkcs-9-at-localKeyId
551 	 * }
552 	 */
553 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
554 	    !asn1_is_octetstring(&hdr)) {
555 		asn1_unexpected(&hdr,
556 				"PKCS #12: Expected OCTET STRING (localKeyID)");
557 		return -1;
558 	}
559 	wpa_hexdump_key(MSG_DEBUG, "PKCS #12: localKeyID",
560 			hdr.payload, hdr.length);
561 	return 0;
562 }
563 
564 
pkcs12_parse_attr(const u8 * pos,size_t len)565 static int pkcs12_parse_attr(const u8 *pos, size_t len)
566 {
567 	const u8 *end = pos + len;
568 	struct asn1_hdr hdr;
569 	struct asn1_oid a_oid;
570 	char obuf[80];
571 
572 	/*
573 	 * PKCS12Attribute ::= SEQUENCE {
574 	 * attrId      ATTRIBUTE.&id ({PKCS12AttrSet}),
575 	 * attrValues  SET OF ATTRIBUTE.&Type ({PKCS12AttrSet}{@attrId})
576 	 * }
577 	 */
578 
579 	if (asn1_get_oid(pos, end - pos, &a_oid, &pos)) {
580 		wpa_printf(MSG_DEBUG, "PKCS #12: Failed to parse OID (attrId)");
581 		return -1;
582 	}
583 
584 	asn1_oid_to_str(&a_oid, obuf, sizeof(obuf));
585 	wpa_printf(MSG_DEBUG, "PKCS #12: attrId %s", obuf);
586 
587 	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_set(&hdr)) {
588 		asn1_unexpected(&hdr, "PKCS #12: Expected SET (attrValues)");
589 		return -1;
590 	}
591 	wpa_hexdump_key(MSG_MSGDUMP, "PKCS #12: attrValues",
592 			hdr.payload, hdr.length);
593 	pos = hdr.payload;
594 	end = hdr.payload + hdr.length;
595 
596 	if (is_oid_pkcs9_friendly_name(&a_oid))
597 		return pkcs12_parse_attr_friendly_name(pos, end);
598 	if (is_oid_pkcs9_local_key_id(&a_oid))
599 		return pkcs12_parse_attr_local_key_id(pos, end);
600 
601 	wpa_printf(MSG_DEBUG, "PKCS #12: Ignore unknown attribute");
602 	return 0;
603 }
604 
605 
pkcs12_safebag(struct tlsv1_credentials * cred,const u8 * buf,size_t len,const char * passwd)606 static int pkcs12_safebag(struct tlsv1_credentials *cred,
607 			  const u8 *buf, size_t len, const char *passwd)
608 {
609 	struct asn1_hdr hdr;
610 	struct asn1_oid oid;
611 	char obuf[80];
612 	const u8 *pos = buf, *end = buf + len;
613 	const u8 *value;
614 	size_t value_len;
615 
616 	wpa_hexdump_key(MSG_MSGDUMP, "PKCS #12: SafeBag", buf, len);
617 
618 	/* BAG-TYPE ::= TYPE-IDENTIFIER */
619 	if (asn1_get_oid(pos, end - pos, &oid, &pos)) {
620 		wpa_printf(MSG_DEBUG,
621 			   "PKCS #12: Failed to parse OID (BAG-TYPE)");
622 		return -1;
623 	}
624 
625 	asn1_oid_to_str(&oid, obuf, sizeof(obuf));
626 	wpa_printf(MSG_DEBUG, "PKCS #12: BAG-TYPE %s", obuf);
627 
628 	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed ||
629 	    !asn1_is_cs_tag(&hdr, 0)) {
630 		asn1_unexpected(&hdr,
631 				"PKCS #12: Expected [0] EXPLICIT (bagValue)");
632 		return 0;
633 	}
634 	value = hdr.payload;
635 	value_len = hdr.length;
636 	wpa_hexdump_key(MSG_MSGDUMP, "PKCS #12: bagValue", value, value_len);
637 	pos = hdr.payload + hdr.length;
638 
639 	if (pos < end) {
640 		/* bagAttributes  SET OF PKCS12Attribute OPTIONAL */
641 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
642 		    !asn1_is_set(&hdr)) {
643 			asn1_unexpected(&hdr,
644 					"PKCS #12: Expected SET (bagAttributes)");
645 			return -1;
646 		}
647 		wpa_hexdump_key(MSG_MSGDUMP, "PKCS #12: bagAttributes",
648 				hdr.payload, hdr.length);
649 
650 		pos = hdr.payload;
651 		end = hdr.payload + hdr.length;
652 		while (pos < end) {
653 			/* PKCS12Attribute ::= SEQUENCE */
654 			if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
655 			    !asn1_is_sequence(&hdr)) {
656 				asn1_unexpected(&hdr,
657 						"PKCS #12: Expected SEQUENCE (PKCS12Attribute)");
658 				return -1;
659 			}
660 			if (pkcs12_parse_attr(hdr.payload, hdr.length) < 0)
661 				return -1;
662 			pos = hdr.payload + hdr.length;
663 		}
664 	}
665 
666 	if (pkcs12_is_bagtype_oid(&oid, 1))
667 		return pkcs12_keybag(cred, value, value_len);
668 	if (pkcs12_is_bagtype_oid(&oid, 2))
669 		return pkcs12_pkcs8_keybag(cred, value, value_len, passwd);
670 	if (pkcs12_is_bagtype_oid(&oid, 3))
671 		return pkcs12_certbag(cred, value, value_len);
672 
673 	wpa_printf(MSG_DEBUG, "PKCS #12: Ignore unsupported BAG-TYPE");
674 	return 0;
675 }
676 
677 
pkcs12_safecontents(struct tlsv1_credentials * cred,const u8 * buf,size_t len,const char * passwd)678 static int pkcs12_safecontents(struct tlsv1_credentials *cred,
679 			       const u8 *buf, size_t len,
680 			       const char *passwd)
681 {
682 	struct asn1_hdr hdr;
683 	const u8 *pos, *end;
684 
685 	/* SafeContents ::= SEQUENCE OF SafeBag */
686 	if (asn1_get_next(buf, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
687 		asn1_unexpected(&hdr,
688 				"PKCS #12: Expected SEQUENCE (SafeContents)");
689 		return -1;
690 	}
691 	pos = hdr.payload;
692 	end = hdr.payload + hdr.length;
693 
694 	/*
695 	 * SafeBag ::= SEQUENCE {
696 	 *   bagId          BAG-TYPE.&id ({PKCS12BagSet})
697 	 *   bagValue       [0] EXPLICIT BAG-TYPE.&Type({PKCS12BagSet}{@bagId}),
698 	 *   bagAttributes  SET OF PKCS12Attribute OPTIONAL
699 	 * }
700 	 */
701 
702 	while (pos < end) {
703 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
704 		    !asn1_is_sequence(&hdr)) {
705 			asn1_unexpected(&hdr,
706 					"PKCS #12: Expected SEQUENCE (SafeBag)");
707 			return -1;
708 		}
709 		if (pkcs12_safebag(cred, hdr.payload, hdr.length, passwd) < 0)
710 			return -1;
711 		pos = hdr.payload + hdr.length;
712 	}
713 
714 	return 0;
715 }
716 
717 
pkcs12_parse_content_data(struct tlsv1_credentials * cred,const u8 * pos,const u8 * end,const char * passwd)718 static int pkcs12_parse_content_data(struct tlsv1_credentials *cred,
719 				     const u8 *pos, const u8 *end,
720 				     const char *passwd)
721 {
722 	struct asn1_hdr hdr;
723 
724 	/* Data ::= OCTET STRING */
725 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
726 	    !asn1_is_octetstring(&hdr)) {
727 		asn1_unexpected(&hdr, "PKCS #12: Expected OCTET STRING (Data)");
728 		return -1;
729 	}
730 
731 	wpa_hexdump(MSG_MSGDUMP, "PKCS #12: Data", hdr.payload, hdr.length);
732 
733 	return pkcs12_safecontents(cred, hdr.payload, hdr.length, passwd);
734 }
735 
736 
pkcs12_parse_content_enc_data(struct tlsv1_credentials * cred,const u8 * pos,const u8 * end,const char * passwd)737 static int pkcs12_parse_content_enc_data(struct tlsv1_credentials *cred,
738 					 const u8 *pos, const u8 *end,
739 					 const char *passwd)
740 {
741 	struct asn1_hdr hdr;
742 	struct asn1_oid oid;
743 	char buf[80];
744 	const u8 *enc_alg;
745 	u8 *data;
746 	size_t enc_alg_len, data_len;
747 	int res = -1;
748 
749 	/*
750 	 * EncryptedData ::= SEQUENCE {
751 	 *   version Version,
752 	 *   encryptedContentInfo EncryptedContentInfo }
753 	 */
754 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
755 	    !asn1_is_sequence(&hdr)) {
756 		asn1_unexpected(&hdr,
757 				"PKCS #12: Expected SEQUENCE (EncryptedData)");
758 		return 0;
759 	}
760 	pos = hdr.payload;
761 
762 	/* Version ::= INTEGER */
763 	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_integer(&hdr)) {
764 		asn1_unexpected(&hdr,
765 				"PKCS #12: No INTEGER tag found for version");
766 		return -1;
767 	}
768 	if (hdr.length != 1 || hdr.payload[0] != 0) {
769 		wpa_printf(MSG_DEBUG, "PKCS #12: Unrecognized PKCS #7 version");
770 		return -1;
771 	}
772 	pos = hdr.payload + hdr.length;
773 
774 	wpa_hexdump(MSG_MSGDUMP, "PKCS #12: EncryptedContentInfo",
775 		    pos, end - pos);
776 
777 	/*
778 	 * EncryptedContentInfo ::= SEQUENCE {
779 	 *   contentType ContentType,
780 	 *   contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
781 	 *   encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL }
782 	 */
783 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
784 	    !asn1_is_sequence(&hdr)) {
785 		asn1_unexpected(&hdr,
786 				"PKCS #12: Expected SEQUENCE (EncryptedContentInfo)");
787 		return -1;
788 	}
789 
790 	pos = hdr.payload;
791 	end = pos + hdr.length;
792 
793 	/* ContentType ::= OBJECT IDENTIFIER */
794 	if (asn1_get_oid(pos, end - pos, &oid, &pos)) {
795 		wpa_printf(MSG_DEBUG,
796 			   "PKCS #12: Could not find OBJECT IDENTIFIER (contentType)");
797 		return -1;
798 	}
799 	asn1_oid_to_str(&oid, buf, sizeof(buf));
800 	wpa_printf(MSG_DEBUG, "PKCS #12: EncryptedContentInfo::contentType %s",
801 		   buf);
802 
803 	if (!is_oid_pkcs7_data(&oid)) {
804 		wpa_printf(MSG_DEBUG,
805 			   "PKCS #12: Unsupported EncryptedContentInfo::contentType %s",
806 			   buf);
807 		return 0;
808 	}
809 
810 	/* ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier */
811 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
812 	    !asn1_is_sequence(&hdr)) {
813 		asn1_unexpected(&hdr,
814 				"PKCS #12: Expected SEQUENCE (ContentEncryptionAlgorithmIdentifier)");
815 		return -1;
816 	}
817 	enc_alg = hdr.payload;
818 	enc_alg_len = hdr.length;
819 	pos = hdr.payload + hdr.length;
820 
821 	if (asn1_get_next(pos, end - pos, &hdr) < 0 || hdr.constructed ||
822 	    !asn1_is_cs_tag(&hdr, 0)) {
823 		asn1_unexpected(&hdr,
824 				"PKCS #12: Expected [0] IMPLICIT (encryptedContent)");
825 		return -1;
826 	}
827 
828 	/* EncryptedContent ::= OCTET STRING */
829 	data = pkcs5_decrypt(enc_alg, enc_alg_len, hdr.payload, hdr.length,
830 			     passwd, &data_len);
831 	if (data) {
832 		wpa_hexdump_key(MSG_MSGDUMP,
833 				"PKCS #12: Decrypted encryptedContent",
834 				data, data_len);
835 		res = pkcs12_safecontents(cred, data, data_len, passwd);
836 		os_free(data);
837 	}
838 
839 	return res;
840 }
841 
842 
pkcs12_parse_content(struct tlsv1_credentials * cred,const u8 * buf,size_t len,const char * passwd)843 static int pkcs12_parse_content(struct tlsv1_credentials *cred,
844 				const u8 *buf, size_t len,
845 				const char *passwd)
846 {
847 	const u8 *pos = buf;
848 	const u8 *end = buf + len;
849 	struct asn1_oid oid;
850 	char txt[80];
851 	struct asn1_hdr hdr;
852 
853 	wpa_hexdump(MSG_MSGDUMP, "PKCS #12: ContentInfo", buf, len);
854 
855 	if (asn1_get_oid(pos, end - pos, &oid, &pos)) {
856 		wpa_printf(MSG_DEBUG,
857 			   "PKCS #12: Could not find OBJECT IDENTIFIER (contentType)");
858 		return 0;
859 	}
860 
861 	asn1_oid_to_str(&oid, txt, sizeof(txt));
862 	wpa_printf(MSG_DEBUG, "PKCS #12: contentType %s", txt);
863 
864 	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed ||
865 	    !asn1_is_cs_tag(&hdr, 0)) {
866 		asn1_unexpected(&hdr,
867 				"PKCS #12: Expected [0] EXPLICIT (content)");
868 		return 0;
869 	}
870 	pos = hdr.payload;
871 
872 	if (is_oid_pkcs7_data(&oid))
873 		return pkcs12_parse_content_data(cred, pos, end, passwd);
874 	if (is_oid_pkcs7_enc_data(&oid))
875 		return pkcs12_parse_content_enc_data(cred, pos, end, passwd);
876 
877 	wpa_printf(MSG_DEBUG, "PKCS #12: Ignored unsupported contentType %s",
878 		   txt);
879 
880 	return 0;
881 }
882 
883 
pkcs12_parse(struct tlsv1_credentials * cred,const u8 * key,size_t len,const char * passwd)884 static int pkcs12_parse(struct tlsv1_credentials *cred,
885 			const u8 *key, size_t len, const char *passwd)
886 {
887 	struct asn1_hdr hdr;
888 	const u8 *pos, *end;
889 	struct asn1_oid oid;
890 	char buf[80];
891 
892 	/*
893 	 * PFX ::= SEQUENCE {
894 	 *     version     INTEGER {v3(3)}(v3,...),
895 	 *     authSafe    ContentInfo,
896 	 *     macData     MacData OPTIONAL
897 	 * }
898 	 */
899 
900 	if (asn1_get_next(key, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
901 		asn1_unexpected(&hdr,
902 				"PKCS #12: Expected SEQUENCE (PFX); assume PKCS #12 not used");
903 		return -1;
904 	}
905 
906 	pos = hdr.payload;
907 	end = pos + hdr.length;
908 
909 	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_integer(&hdr)) {
910 		asn1_unexpected(&hdr,
911 				"PKCS #12: No INTEGER tag found for version");
912 		return -1;
913 	}
914 	if (hdr.length != 1 || hdr.payload[0] != 3) {
915 		wpa_printf(MSG_DEBUG, "PKCS #12: Unrecognized version");
916 		return -1;
917 	}
918 	pos = hdr.payload + hdr.length;
919 
920 	/*
921 	 * ContentInfo ::= SEQUENCE {
922 	 *   contentType ContentType,
923 	 *   content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
924 	 */
925 
926 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
927 	    !asn1_is_sequence(&hdr)) {
928 		asn1_unexpected(&hdr,
929 				"PKCS #12: Expected SEQUENCE (authSafe); assume PKCS #12 not used");
930 		return -1;
931 	}
932 
933 	pos = hdr.payload;
934 	end = pos + hdr.length;
935 
936 	/* ContentType ::= OBJECT IDENTIFIER */
937 	if (asn1_get_oid(pos, end - pos, &oid, &pos)) {
938 		wpa_printf(MSG_DEBUG,
939 			   "PKCS #12: Could not find OBJECT IDENTIFIER (contentType); assume PKCS #12 not used");
940 		return -1;
941 	}
942 	asn1_oid_to_str(&oid, buf, sizeof(buf));
943 	wpa_printf(MSG_DEBUG, "PKCS #12: contentType %s", buf);
944 	if (!is_oid_pkcs7_data(&oid)) {
945 		wpa_printf(MSG_DEBUG, "PKCS #12: Unsupported contentType %s",
946 			   buf);
947 		return -1;
948 	}
949 
950 	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed ||
951 	    !asn1_is_cs_tag(&hdr, 0)) {
952 		asn1_unexpected(&hdr,
953 				"PKCS #12: Expected [0] EXPLICIT (content); assume PKCS #12 not used");
954 		return -1;
955 	}
956 
957 	pos = hdr.payload;
958 
959 	/* Data ::= OCTET STRING */
960 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
961 	    !asn1_is_octetstring(&hdr)) {
962 		asn1_unexpected(&hdr,
963 				"PKCS #12: Expected OCTET STRING (Data); assume PKCS #12 not used");
964 		return -1;
965 	}
966 
967 	/*
968 	 * AuthenticatedSafe ::= SEQUENCE OF ContentInfo
969 	 *     -- Data if unencrypted
970 	 *     -- EncryptedData if password-encrypted
971 	 *     -- EnvelopedData if public key-encrypted
972 	 */
973 	wpa_hexdump(MSG_MSGDUMP, "PKCS #12: Data content",
974 		    hdr.payload, hdr.length);
975 
976 	if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
977 	    !asn1_is_sequence(&hdr)) {
978 		asn1_unexpected(&hdr,
979 				"PKCS #12: Expected SEQUENCE within Data content; assume PKCS #12 not used");
980 		return -1;
981 	}
982 
983 	pos = hdr.payload;
984 	end = pos + hdr.length;
985 
986 	while (end > pos) {
987 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
988 		    !asn1_is_sequence(&hdr)) {
989 			asn1_unexpected(&hdr,
990 					"PKCS #12: Expected SEQUENCE (ContentInfo); assume PKCS #12 not used");
991 			return -1;
992 		}
993 		if (pkcs12_parse_content(cred, hdr.payload, hdr.length,
994 					 passwd) < 0)
995 			return -1;
996 
997 		pos = hdr.payload + hdr.length;
998 	}
999 
1000 	return 0;
1001 }
1002 
1003 #endif /* PKCS12_FUNCS */
1004 
1005 
tlsv1_set_key(struct tlsv1_credentials * cred,const u8 * key,size_t len,const char * passwd)1006 static int tlsv1_set_key(struct tlsv1_credentials *cred,
1007 			 const u8 *key, size_t len, const char *passwd)
1008 {
1009 	cred->key = crypto_private_key_import(key, len, passwd);
1010 	if (cred->key == NULL)
1011 		cred->key = tlsv1_set_key_pem(key, len);
1012 	if (cred->key == NULL)
1013 		cred->key = tlsv1_set_key_enc_pem(key, len, passwd);
1014 #ifdef PKCS12_FUNCS
1015 	if (!cred->key)
1016 		pkcs12_parse(cred, key, len, passwd);
1017 #endif /* PKCS12_FUNCS */
1018 	if (cred->key == NULL) {
1019 		wpa_printf(MSG_INFO, "TLSv1: Failed to parse private key");
1020 		return -1;
1021 	}
1022 	return 0;
1023 }
1024 
1025 
1026 /**
1027  * tlsv1_set_private_key - Set private key
1028  * @cred: TLSv1 credentials from tlsv1_cred_alloc()
1029  * @private_key: File or reference name for the key in PEM or DER format
1030  * @private_key_passwd: Passphrase for decrypted private key, %NULL if no
1031  * passphrase is used.
1032  * @private_key_blob: private_key as inlined data or %NULL if not used
1033  * @private_key_blob_len: private_key_blob length
1034  * Returns: 0 on success, -1 on failure
1035  */
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)1036 int tlsv1_set_private_key(struct tlsv1_credentials *cred,
1037 			  const char *private_key,
1038 			  const char *private_key_passwd,
1039 			  const u8 *private_key_blob,
1040 			  size_t private_key_blob_len)
1041 {
1042 	crypto_private_key_free(cred->key);
1043 	cred->key = NULL;
1044 
1045 	if (private_key_blob)
1046 		return tlsv1_set_key(cred, private_key_blob,
1047 				     private_key_blob_len,
1048 				     private_key_passwd);
1049 
1050 	if (private_key) {
1051 		u8 *buf;
1052 		size_t len;
1053 		int ret;
1054 
1055 		buf = (u8 *) os_readfile(private_key, &len);
1056 		if (buf == NULL) {
1057 			wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'",
1058 				   private_key);
1059 			return -1;
1060 		}
1061 
1062 		ret = tlsv1_set_key(cred, buf, len, private_key_passwd);
1063 		os_free(buf);
1064 		return ret;
1065 	}
1066 
1067 	return 0;
1068 }
1069 
1070 
tlsv1_set_dhparams_der(struct tlsv1_credentials * cred,const u8 * dh,size_t len)1071 static int tlsv1_set_dhparams_der(struct tlsv1_credentials *cred,
1072 				  const u8 *dh, size_t len)
1073 {
1074 	struct asn1_hdr hdr;
1075 	const u8 *pos, *end;
1076 
1077 	pos = dh;
1078 	end = dh + len;
1079 
1080 	/*
1081 	 * DHParameter ::= SEQUENCE {
1082 	 *   prime INTEGER, -- p
1083 	 *   base INTEGER, -- g
1084 	 *   privateValueLength INTEGER OPTIONAL }
1085 	 */
1086 
1087 	/* DHParamer ::= SEQUENCE */
1088 	if (asn1_get_next(pos, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
1089 		asn1_unexpected(&hdr,
1090 				"DH: DH parameters did not start with a valid SEQUENCE");
1091 		return -1;
1092 	}
1093 	pos = hdr.payload;
1094 
1095 	/* prime INTEGER */
1096 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
1097 	    !asn1_is_integer(&hdr)) {
1098 		asn1_unexpected(&hdr, "DH: No INTEGER tag found for p");
1099 		return -1;
1100 	}
1101 
1102 	wpa_hexdump(MSG_MSGDUMP, "DH: prime (p)", hdr.payload, hdr.length);
1103 	if (hdr.length == 0)
1104 		return -1;
1105 	os_free(cred->dh_p);
1106 	cred->dh_p = os_memdup(hdr.payload, hdr.length);
1107 	if (cred->dh_p == NULL)
1108 		return -1;
1109 	cred->dh_p_len = hdr.length;
1110 	pos = hdr.payload + hdr.length;
1111 
1112 	/* base INTEGER */
1113 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
1114 	    !asn1_is_integer(&hdr)) {
1115 		asn1_unexpected(&hdr, "DH: No INTEGER tag found for g");
1116 		return -1;
1117 	}
1118 
1119 	wpa_hexdump(MSG_MSGDUMP, "DH: base (g)", hdr.payload, hdr.length);
1120 	if (hdr.length == 0)
1121 		return -1;
1122 	os_free(cred->dh_g);
1123 	cred->dh_g = os_memdup(hdr.payload, hdr.length);
1124 	if (cred->dh_g == NULL)
1125 		return -1;
1126 	cred->dh_g_len = hdr.length;
1127 
1128 	return 0;
1129 }
1130 
1131 
1132 static const char *pem_dhparams_begin = "-----BEGIN DH PARAMETERS-----";
1133 static const char *pem_dhparams_end = "-----END DH PARAMETERS-----";
1134 
1135 
tlsv1_set_dhparams_blob(struct tlsv1_credentials * cred,const u8 * buf,size_t len)1136 static int tlsv1_set_dhparams_blob(struct tlsv1_credentials *cred,
1137 				   const u8 *buf, size_t len)
1138 {
1139 	const u8 *pos, *end;
1140 	unsigned char *der;
1141 	size_t der_len;
1142 
1143 	pos = search_tag(pem_dhparams_begin, buf, len);
1144 	if (!pos) {
1145 		wpa_printf(MSG_DEBUG, "TLSv1: No PEM dhparams tag found - "
1146 			   "assume DER format");
1147 		return tlsv1_set_dhparams_der(cred, buf, len);
1148 	}
1149 
1150 	wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format dhparams into DER "
1151 		   "format");
1152 
1153 	pos += os_strlen(pem_dhparams_begin);
1154 	end = search_tag(pem_dhparams_end, pos, buf + len - pos);
1155 	if (end == NULL) {
1156 		wpa_printf(MSG_INFO, "TLSv1: Could not find PEM dhparams end "
1157 			   "tag (%s)", pem_dhparams_end);
1158 		return -1;
1159 	}
1160 
1161 	der = base64_decode((const char *) pos, end - pos, &der_len);
1162 	if (der == NULL) {
1163 		wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM dhparams");
1164 		return -1;
1165 	}
1166 
1167 	if (tlsv1_set_dhparams_der(cred, der, der_len) < 0) {
1168 		wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM dhparams "
1169 			   "DER conversion");
1170 		os_free(der);
1171 		return -1;
1172 	}
1173 
1174 	os_free(der);
1175 
1176 	return 0;
1177 }
1178 
1179 
1180 /**
1181  * tlsv1_set_dhparams - Set Diffie-Hellman parameters
1182  * @cred: TLSv1 credentials from tlsv1_cred_alloc()
1183  * @dh_file: File or reference name for the DH params in PEM or DER format
1184  * @dh_blob: DH params as inlined data or %NULL if not used
1185  * @dh_blob_len: dh_blob length
1186  * Returns: 0 on success, -1 on failure
1187  */
tlsv1_set_dhparams(struct tlsv1_credentials * cred,const char * dh_file,const u8 * dh_blob,size_t dh_blob_len)1188 int tlsv1_set_dhparams(struct tlsv1_credentials *cred, const char *dh_file,
1189 		       const u8 *dh_blob, size_t dh_blob_len)
1190 {
1191 	if (dh_blob)
1192 		return tlsv1_set_dhparams_blob(cred, dh_blob, dh_blob_len);
1193 
1194 	if (dh_file) {
1195 		u8 *buf;
1196 		size_t len;
1197 		int ret;
1198 
1199 		buf = (u8 *) os_readfile(dh_file, &len);
1200 		if (buf == NULL) {
1201 			wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'",
1202 				   dh_file);
1203 			return -1;
1204 		}
1205 
1206 		ret = tlsv1_set_dhparams_blob(cred, buf, len);
1207 		os_free(buf);
1208 		return ret;
1209 	}
1210 
1211 	return 0;
1212 }
1213