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