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