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