Updated to hostap_2_6
[mech_eap.git] / libeap / src / tls / tlsv1_cred.c
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
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
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
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
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
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(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
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  */
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  */
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
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(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
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(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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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  */
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
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_malloc(hdr.length);
1170         if (cred->dh_p == NULL)
1171                 return -1;
1172         os_memcpy(cred->dh_p, hdr.payload, hdr.length);
1173         cred->dh_p_len = hdr.length;
1174         pos = hdr.payload + hdr.length;
1175
1176         /* base INTEGER */
1177         if (asn1_get_next(pos, end - pos, &hdr) < 0)
1178                 return -1;
1179
1180         if (hdr.class != ASN1_CLASS_UNIVERSAL ||
1181             hdr.tag != ASN1_TAG_INTEGER) {
1182                 wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for g; "
1183                            "class=%d tag=0x%x", hdr.class, hdr.tag);
1184                 return -1;
1185         }
1186
1187         wpa_hexdump(MSG_MSGDUMP, "DH: base (g)", hdr.payload, hdr.length);
1188         if (hdr.length == 0)
1189                 return -1;
1190         os_free(cred->dh_g);
1191         cred->dh_g = os_malloc(hdr.length);
1192         if (cred->dh_g == NULL)
1193                 return -1;
1194         os_memcpy(cred->dh_g, hdr.payload, hdr.length);
1195         cred->dh_g_len = hdr.length;
1196
1197         return 0;
1198 }
1199
1200
1201 static const char *pem_dhparams_begin = "-----BEGIN DH PARAMETERS-----";
1202 static const char *pem_dhparams_end = "-----END DH PARAMETERS-----";
1203
1204
1205 static int tlsv1_set_dhparams_blob(struct tlsv1_credentials *cred,
1206                                    const u8 *buf, size_t len)
1207 {
1208         const u8 *pos, *end;
1209         unsigned char *der;
1210         size_t der_len;
1211
1212         pos = search_tag(pem_dhparams_begin, buf, len);
1213         if (!pos) {
1214                 wpa_printf(MSG_DEBUG, "TLSv1: No PEM dhparams tag found - "
1215                            "assume DER format");
1216                 return tlsv1_set_dhparams_der(cred, buf, len);
1217         }
1218
1219         wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format dhparams into DER "
1220                    "format");
1221
1222         pos += os_strlen(pem_dhparams_begin);
1223         end = search_tag(pem_dhparams_end, pos, buf + len - pos);
1224         if (end == NULL) {
1225                 wpa_printf(MSG_INFO, "TLSv1: Could not find PEM dhparams end "
1226                            "tag (%s)", pem_dhparams_end);
1227                 return -1;
1228         }
1229
1230         der = base64_decode(pos, end - pos, &der_len);
1231         if (der == NULL) {
1232                 wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM dhparams");
1233                 return -1;
1234         }
1235
1236         if (tlsv1_set_dhparams_der(cred, der, der_len) < 0) {
1237                 wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM dhparams "
1238                            "DER conversion");
1239                 os_free(der);
1240                 return -1;
1241         }
1242
1243         os_free(der);
1244
1245         return 0;
1246 }
1247
1248
1249 /**
1250  * tlsv1_set_dhparams - Set Diffie-Hellman parameters
1251  * @cred: TLSv1 credentials from tlsv1_cred_alloc()
1252  * @dh_file: File or reference name for the DH params in PEM or DER format
1253  * @dh_blob: DH params as inlined data or %NULL if not used
1254  * @dh_blob_len: dh_blob length
1255  * Returns: 0 on success, -1 on failure
1256  */
1257 int tlsv1_set_dhparams(struct tlsv1_credentials *cred, const char *dh_file,
1258                        const u8 *dh_blob, size_t dh_blob_len)
1259 {
1260         if (dh_blob)
1261                 return tlsv1_set_dhparams_blob(cred, dh_blob, dh_blob_len);
1262
1263         if (dh_file) {
1264                 u8 *buf;
1265                 size_t len;
1266                 int ret;
1267
1268                 buf = (u8 *) os_readfile(dh_file, &len);
1269                 if (buf == NULL) {
1270                         wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'",
1271                                    dh_file);
1272                         return -1;
1273                 }
1274
1275                 ret = tlsv1_set_dhparams_blob(cred, buf, len);
1276                 os_free(buf);
1277                 return ret;
1278         }
1279
1280         return 0;
1281 }