1  /*
2   * PKCS #8 (Private-key information syntax)
3   * Copyright (c) 2006-2009, 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 "asn1.h"
13  #include "bignum.h"
14  #include "rsa.h"
15  #include "pkcs5.h"
16  #include "pkcs8.h"
17  
18  
pkcs8_key_import(const u8 * buf,size_t len)19  struct crypto_private_key * pkcs8_key_import(const u8 *buf, size_t len)
20  {
21  	struct asn1_hdr hdr;
22  	const u8 *pos, *end;
23  	struct bignum *zero;
24  	struct asn1_oid oid;
25  	char obuf[80];
26  
27  	/* PKCS #8, Chapter 6 */
28  
29  	/* PrivateKeyInfo ::= SEQUENCE */
30  	if (asn1_get_next(buf, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
31  		asn1_unexpected(&hdr,
32  				"PKCS #8: Does not start with PKCS #8 header (SEQUENCE)");
33  		return NULL;
34  	}
35  	pos = hdr.payload;
36  	end = pos + hdr.length;
37  
38  	/* version Version (Version ::= INTEGER) */
39  	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !asn1_is_integer(&hdr)) {
40  		asn1_unexpected(&hdr, "PKCS #8: Expected INTEGER");
41  		return NULL;
42  	}
43  
44  	zero = bignum_init();
45  	if (zero == NULL)
46  		return NULL;
47  
48  	if (bignum_set_unsigned_bin(zero, hdr.payload, hdr.length) < 0) {
49  		wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse INTEGER");
50  		bignum_deinit(zero);
51  		return NULL;
52  	}
53  	pos = hdr.payload + hdr.length;
54  
55  	if (bignum_cmp_d(zero, 0) != 0) {
56  		wpa_printf(MSG_DEBUG, "PKCS #8: Expected zero INTEGER in the "
57  			   "beginning of private key; not found; assume "
58  			   "PKCS #8 not used");
59  		bignum_deinit(zero);
60  		return NULL;
61  	}
62  	bignum_deinit(zero);
63  
64  	/* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier
65  	 * (PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier) */
66  	if (asn1_get_next(pos, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
67  		asn1_unexpected(&hdr,
68  				"PKCS #8: Expected SEQUENCE (AlgorithmIdentifier); assume PKCS #8 not used");
69  		return NULL;
70  	}
71  
72  	if (asn1_get_oid(hdr.payload, hdr.length, &oid, &pos)) {
73  		wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse OID "
74  			   "(algorithm); assume PKCS #8 not used");
75  		return NULL;
76  	}
77  
78  	asn1_oid_to_str(&oid, obuf, sizeof(obuf));
79  	wpa_printf(MSG_DEBUG, "PKCS #8: algorithm=%s", obuf);
80  
81  	if (oid.len != 7 ||
82  	    oid.oid[0] != 1 /* iso */ ||
83  	    oid.oid[1] != 2 /* member-body */ ||
84  	    oid.oid[2] != 840 /* us */ ||
85  	    oid.oid[3] != 113549 /* rsadsi */ ||
86  	    oid.oid[4] != 1 /* pkcs */ ||
87  	    oid.oid[5] != 1 /* pkcs-1 */ ||
88  	    oid.oid[6] != 1 /* rsaEncryption */) {
89  		wpa_printf(MSG_DEBUG, "PKCS #8: Unsupported private key "
90  			   "algorithm %s", obuf);
91  		return NULL;
92  	}
93  
94  	pos = hdr.payload + hdr.length;
95  
96  	/* privateKey PrivateKey (PrivateKey ::= OCTET STRING) */
97  	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
98  	    !asn1_is_octetstring(&hdr)) {
99  		asn1_unexpected(&hdr,
100  				"PKCS #8: Expected OCTETSTRING (privateKey)");
101  		return NULL;
102  	}
103  	wpa_printf(MSG_DEBUG, "PKCS #8: Try to parse RSAPrivateKey");
104  
105  	return (struct crypto_private_key *)
106  		crypto_rsa_import_private_key(hdr.payload, hdr.length);
107  }
108  
109  
110  struct crypto_private_key *
pkcs8_enc_key_import(const u8 * buf,size_t len,const char * passwd)111  pkcs8_enc_key_import(const u8 *buf, size_t len, const char *passwd)
112  {
113  	struct asn1_hdr hdr;
114  	const u8 *pos, *end, *enc_alg;
115  	size_t enc_alg_len;
116  	u8 *data;
117  	size_t data_len;
118  
119  	if (passwd == NULL)
120  		return NULL;
121  
122  	/*
123  	 * PKCS #8, Chapter 7
124  	 * EncryptedPrivateKeyInfo ::= SEQUENCE {
125  	 *   encryptionAlgorithm EncryptionAlgorithmIdentifier,
126  	 *   encryptedData EncryptedData }
127  	 * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
128  	 * EncryptedData ::= OCTET STRING
129  	 */
130  
131  	if (asn1_get_next(buf, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
132  		asn1_unexpected(&hdr,
133  				"PKCS #8: Does not start with PKCS #8 header (SEQUENCE); assume encrypted PKCS #8 not used");
134  		return NULL;
135  	}
136  	pos = hdr.payload;
137  	end = pos + hdr.length;
138  
139  	/* encryptionAlgorithm EncryptionAlgorithmIdentifier */
140  	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
141  	    !asn1_is_sequence(&hdr)) {
142  		asn1_unexpected(&hdr,
143  				"PKCS #8: Expected SEQUENCE (AlgorithmIdentifier); assume encrypted PKCS #8 not used");
144  		return NULL;
145  	}
146  	enc_alg = hdr.payload;
147  	enc_alg_len = hdr.length;
148  	pos = hdr.payload + hdr.length;
149  
150  	/* encryptedData EncryptedData */
151  	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
152  	    !asn1_is_octetstring(&hdr)) {
153  		asn1_unexpected(&hdr,
154  				"PKCS #8: Expected OCTETSTRING (encryptedData)");
155  		return NULL;
156  	}
157  
158  	data = pkcs5_decrypt(enc_alg, enc_alg_len, hdr.payload, hdr.length,
159  			     passwd, &data_len);
160  	if (data) {
161  		struct crypto_private_key *key;
162  		key = pkcs8_key_import(data, data_len);
163  		os_free(data);
164  		return key;
165  	}
166  
167  	return NULL;
168  }
169