remove @EAP_LDFLAGS@, no longer exists
[mech_eap.orig] / libeap / src / tls / pkcs8.c
1 /*
2  * PKCS #8 (Private-key information syntax)
3  * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "includes.h"
16
17 #include "common.h"
18 #include "asn1.h"
19 #include "bignum.h"
20 #include "rsa.h"
21 #include "pkcs5.h"
22 #include "pkcs8.h"
23
24
25 struct crypto_private_key * pkcs8_key_import(const u8 *buf, size_t len)
26 {
27         struct asn1_hdr hdr;
28         const u8 *pos, *end;
29         struct bignum *zero;
30         struct asn1_oid oid;
31         char obuf[80];
32
33         /* PKCS #8, Chapter 6 */
34
35         /* PrivateKeyInfo ::= SEQUENCE */
36         if (asn1_get_next(buf, len, &hdr) < 0 ||
37             hdr.class != ASN1_CLASS_UNIVERSAL ||
38             hdr.tag != ASN1_TAG_SEQUENCE) {
39                 wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 "
40                            "header (SEQUENCE); assume PKCS #8 not used");
41                 return NULL;
42         }
43         pos = hdr.payload;
44         end = pos + hdr.length;
45
46         /* version Version (Version ::= INTEGER) */
47         if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
48             hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) {
49                 wpa_printf(MSG_DEBUG, "PKCS #8: Expected INTEGER - found "
50                            "class %d tag 0x%x; assume PKCS #8 not used",
51                            hdr.class, hdr.tag);
52                 return NULL;
53         }
54
55         zero = bignum_init();
56         if (zero == NULL)
57                 return NULL;
58
59         if (bignum_set_unsigned_bin(zero, hdr.payload, hdr.length) < 0) {
60                 wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse INTEGER");
61                 bignum_deinit(zero);
62                 return NULL;
63         }
64         pos = hdr.payload + hdr.length;
65
66         if (bignum_cmp_d(zero, 0) != 0) {
67                 wpa_printf(MSG_DEBUG, "PKCS #8: Expected zero INTEGER in the "
68                            "beginning of private key; not found; assume "
69                            "PKCS #8 not used");
70                 bignum_deinit(zero);
71                 return NULL;
72         }
73         bignum_deinit(zero);
74
75         /* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier
76          * (PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier) */
77         if (asn1_get_next(pos, len, &hdr) < 0 ||
78             hdr.class != ASN1_CLASS_UNIVERSAL ||
79             hdr.tag != ASN1_TAG_SEQUENCE) {
80                 wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE "
81                            "(AlgorithmIdentifier) - found class %d tag 0x%x; "
82                            "assume PKCS #8 not used",
83                            hdr.class, hdr.tag);
84                 return NULL;
85         }
86
87         if (asn1_get_oid(hdr.payload, hdr.length, &oid, &pos)) {
88                 wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse OID "
89                            "(algorithm); assume PKCS #8 not used");
90                 return NULL;
91         }
92
93         asn1_oid_to_str(&oid, obuf, sizeof(obuf));
94         wpa_printf(MSG_DEBUG, "PKCS #8: algorithm=%s", obuf);
95
96         if (oid.len != 7 ||
97             oid.oid[0] != 1 /* iso */ ||
98             oid.oid[1] != 2 /* member-body */ ||
99             oid.oid[2] != 840 /* us */ ||
100             oid.oid[3] != 113549 /* rsadsi */ ||
101             oid.oid[4] != 1 /* pkcs */ ||
102             oid.oid[5] != 1 /* pkcs-1 */ ||
103             oid.oid[6] != 1 /* rsaEncryption */) {
104                 wpa_printf(MSG_DEBUG, "PKCS #8: Unsupported private key "
105                            "algorithm %s", obuf);
106                 return NULL;
107         }
108
109         pos = hdr.payload + hdr.length;
110
111         /* privateKey PrivateKey (PrivateKey ::= OCTET STRING) */
112         if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
113             hdr.class != ASN1_CLASS_UNIVERSAL ||
114             hdr.tag != ASN1_TAG_OCTETSTRING) {
115                 wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING "
116                            "(privateKey) - found class %d tag 0x%x",
117                            hdr.class, hdr.tag);
118                 return NULL;
119         }
120         wpa_printf(MSG_DEBUG, "PKCS #8: Try to parse RSAPrivateKey");
121
122         return (struct crypto_private_key *)
123                 crypto_rsa_import_private_key(hdr.payload, hdr.length);
124 }
125
126
127 struct crypto_private_key *
128 pkcs8_enc_key_import(const u8 *buf, size_t len, const char *passwd)
129 {
130         struct asn1_hdr hdr;
131         const u8 *pos, *end, *enc_alg;
132         size_t enc_alg_len;
133         u8 *data;
134         size_t data_len;
135
136         if (passwd == NULL)
137                 return NULL;
138
139         /*
140          * PKCS #8, Chapter 7
141          * EncryptedPrivateKeyInfo ::= SEQUENCE {
142          *   encryptionAlgorithm EncryptionAlgorithmIdentifier,
143          *   encryptedData EncryptedData }
144          * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
145          * EncryptedData ::= OCTET STRING
146          */
147
148         if (asn1_get_next(buf, len, &hdr) < 0 ||
149             hdr.class != ASN1_CLASS_UNIVERSAL ||
150             hdr.tag != ASN1_TAG_SEQUENCE) {
151                 wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 "
152                            "header (SEQUENCE); assume encrypted PKCS #8 not "
153                            "used");
154                 return NULL;
155         }
156         pos = hdr.payload;
157         end = pos + hdr.length;
158
159         /* encryptionAlgorithm EncryptionAlgorithmIdentifier */
160         if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
161             hdr.class != ASN1_CLASS_UNIVERSAL ||
162             hdr.tag != ASN1_TAG_SEQUENCE) {
163                 wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE "
164                            "(AlgorithmIdentifier) - found class %d tag 0x%x; "
165                            "assume encrypted PKCS #8 not used",
166                            hdr.class, hdr.tag);
167                 return NULL;
168         }
169         enc_alg = hdr.payload;
170         enc_alg_len = hdr.length;
171         pos = hdr.payload + hdr.length;
172
173         /* encryptedData EncryptedData */
174         if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
175             hdr.class != ASN1_CLASS_UNIVERSAL ||
176             hdr.tag != ASN1_TAG_OCTETSTRING) {
177                 wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING "
178                            "(encryptedData) - found class %d tag 0x%x",
179                            hdr.class, hdr.tag);
180                 return NULL;
181         }
182
183         data = pkcs5_decrypt(enc_alg, enc_alg_len, hdr.payload, hdr.length,
184                              passwd, &data_len);
185         if (data) {
186                 struct crypto_private_key *key;
187                 key = pkcs8_key_import(data, data_len);
188                 os_free(data);
189                 return key;
190         }
191
192         return NULL;
193 }