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