/src/opensc/src/libopensc/pkcs15-prkey.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * pkcs15-prkey.c: PKCS #15 private key functions |
3 | | * |
4 | | * Copyright (C) 2001, 2002 Juha Yrjölä <juha.yrjola@iki.fi> |
5 | | * |
6 | | * This library is free software; you can redistribute it and/or |
7 | | * modify it under the terms of the GNU Lesser General Public |
8 | | * License as published by the Free Software Foundation; either |
9 | | * version 2.1 of the License, or (at your option) any later version. |
10 | | * |
11 | | * This library is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | | * Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public |
17 | | * License along with this library; if not, write to the Free Software |
18 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | | */ |
20 | | |
21 | | #ifdef HAVE_CONFIG_H |
22 | | #include "config.h" |
23 | | #endif |
24 | | |
25 | | #include <stdlib.h> |
26 | | #include <string.h> |
27 | | #include <stdio.h> |
28 | | #include <assert.h> |
29 | | |
30 | | #ifdef ENABLE_OPENSSL |
31 | | #include <openssl/opensslv.h> |
32 | | #include <openssl/bn.h> |
33 | | #include <openssl/x509.h> |
34 | | #include <openssl/x509v3.h> |
35 | | #include <openssl/err.h> |
36 | | #include <openssl/evp.h> |
37 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
38 | | # include <openssl/core_names.h> |
39 | | # include <openssl/param_build.h> |
40 | | #endif |
41 | | #ifndef OPENSSL_NO_EC |
42 | | #include <openssl/ec.h> |
43 | | #endif |
44 | | #endif |
45 | | |
46 | | #include "internal.h" |
47 | | #include "asn1.h" |
48 | | #include "pkcs15.h" |
49 | | #include "common/compat_strlcpy.h" |
50 | | #include "aux-data.h" |
51 | | |
52 | | /* |
53 | | * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS defined as 16 |
54 | | */ |
55 | | #define C_ASN1_SUPPORTED_ALGORITHMS_SIZE (SC_MAX_SUPPORTED_ALGORITHMS + 1) |
56 | | static const struct sc_asn1_entry c_asn1_supported_algorithms[C_ASN1_SUPPORTED_ALGORITHMS_SIZE] = { |
57 | | { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
58 | | { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
59 | | { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
60 | | { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
61 | | { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
62 | | { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
63 | | { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
64 | | { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
65 | | { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
66 | | { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
67 | | { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
68 | | { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
69 | | { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
70 | | { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
71 | | { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
72 | | { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
73 | | { NULL, 0, 0, 0, NULL, NULL } |
74 | | }; |
75 | | |
76 | | #define C_ASN1_COM_KEY_ATTR_SIZE 7 |
77 | | static const struct sc_asn1_entry c_asn1_com_key_attr[C_ASN1_COM_KEY_ATTR_SIZE] = { |
78 | | { "iD", SC_ASN1_PKCS15_ID, SC_ASN1_TAG_OCTET_STRING, 0, NULL, NULL }, |
79 | | { "usage", SC_ASN1_BIT_FIELD, SC_ASN1_TAG_BIT_STRING, 0, NULL, NULL }, |
80 | | { "native", SC_ASN1_BOOLEAN, SC_ASN1_TAG_BOOLEAN, SC_ASN1_OPTIONAL, NULL, NULL }, |
81 | | { "accessFlags", SC_ASN1_BIT_FIELD, SC_ASN1_TAG_BIT_STRING, SC_ASN1_OPTIONAL, NULL, NULL }, |
82 | | { "keyReference",SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
83 | | /* Absent in PKCS#15-v1.1 but present in ISO 7816-15(2004-01-15)*/ |
84 | | { "algReference", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_CTX | 1, SC_ASN1_OPTIONAL, NULL, NULL }, |
85 | | { NULL, 0, 0, 0, NULL, NULL } |
86 | | }; |
87 | | |
88 | | #define C_ASN1_COM_PRKEY_ATTR_SIZE 2 |
89 | | static const struct sc_asn1_entry c_asn1_com_prkey_attr[C_ASN1_COM_PRKEY_ATTR_SIZE] = { |
90 | | { "subjectName", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, |
91 | | SC_ASN1_EMPTY_ALLOWED | SC_ASN1_ALLOC | SC_ASN1_OPTIONAL, NULL, NULL }, |
92 | | { NULL, 0, 0, 0, NULL, NULL } |
93 | | }; |
94 | | |
95 | | #define C_ASN1_RSAKEY_ATTR_SIZE 4 |
96 | | static const struct sc_asn1_entry c_asn1_rsakey_attr[] = { |
97 | | { "value", SC_ASN1_PATH, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_EMPTY_ALLOWED, NULL, NULL }, |
98 | | { "modulusLength", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL }, |
99 | | { "keyInfo", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
100 | | { NULL, 0, 0, 0, NULL, NULL } |
101 | | }; |
102 | | |
103 | | #define C_ASN1_PRK_RSA_ATTR_SIZE 2 |
104 | | static const struct sc_asn1_entry c_asn1_prk_rsa_attr[C_ASN1_PRK_RSA_ATTR_SIZE] = { |
105 | | { "privateRSAKeyAttributes", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, |
106 | | { NULL, 0, 0, 0, NULL, NULL } |
107 | | }; |
108 | | |
109 | | #define C_ASN1_GOSTR3410KEY_ATTR_SIZE 5 |
110 | | static const struct sc_asn1_entry c_asn1_gostr3410key_attr[C_ASN1_GOSTR3410KEY_ATTR_SIZE] = { |
111 | | { "value", SC_ASN1_PATH, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, |
112 | | { "params_r3410", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL }, |
113 | | { "params_r3411", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
114 | | { "params_28147", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
115 | | { NULL, 0, 0, 0, NULL, NULL } |
116 | | }; |
117 | | |
118 | | #define C_ASN1_PRK_GOSTR3410_ATTR_SIZE 2 |
119 | | static const struct sc_asn1_entry c_asn1_prk_gostr3410_attr[C_ASN1_PRK_GOSTR3410_ATTR_SIZE] = { |
120 | | { "privateGOSTR3410KeyAttributes", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, |
121 | | { NULL, 0, 0, 0, NULL, NULL } |
122 | | }; |
123 | | |
124 | | /* |
125 | | * The element fieldSize is a proprietary extension to ISO 7816-15, providing to the middleware |
126 | | * the size of the underlying ECC field. This value is required for determine a proper size for |
127 | | * buffer allocations. The field follows the definition for modulusLength in RSA keys |
128 | | */ |
129 | | #define C_ASN1_ECCKEY_ATTR 5 |
130 | | static const struct sc_asn1_entry c_asn1_ecckey_attr[C_ASN1_ECCKEY_ATTR] = { |
131 | | { "value", SC_ASN1_PATH, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_EMPTY_ALLOWED, NULL, NULL }, |
132 | | { "fieldSize", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
133 | | { "keyInfo", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
134 | | /* Slovenian eID card also specifies ECC curve OID */ |
135 | | { "ecDomain", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL}, |
136 | | { NULL, 0, 0, 0, NULL, NULL } |
137 | | }; |
138 | | |
139 | | #define C_ASN1_PRK_ECC_ATTR 2 |
140 | | static const struct sc_asn1_entry c_asn1_prk_ecc_attr[C_ASN1_PRK_ECC_ATTR] = { |
141 | | { "privateECCKeyAttributes", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL }, |
142 | | { NULL, 0, 0, 0, NULL, NULL } |
143 | | }; |
144 | | |
145 | | #define C_ASN1_PRKEY_SIZE 4 |
146 | | static const struct sc_asn1_entry c_asn1_prkey[C_ASN1_PRKEY_SIZE] = { |
147 | | { "privateRSAKey", SC_ASN1_PKCS15_OBJECT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, |
148 | | { "privateECCKey", SC_ASN1_PKCS15_OBJECT, 0 | SC_ASN1_CTX | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, |
149 | | { "privateGOSTR3410Key", SC_ASN1_PKCS15_OBJECT, 4 | SC_ASN1_CTX | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL }, |
150 | | { NULL, 0, 0, 0, NULL, NULL } |
151 | | }; |
152 | | |
153 | | |
154 | | int sc_pkcs15_decode_prkdf_entry(struct sc_pkcs15_card *p15card, |
155 | | struct sc_pkcs15_object *obj, |
156 | | const u8 ** buf, size_t *buflen) |
157 | 5.01k | { |
158 | 5.01k | sc_context_t *ctx = p15card->card->ctx; |
159 | 5.01k | struct sc_pkcs15_prkey_info info; |
160 | 5.01k | int r, i, gostr3410_params[3]; |
161 | 5.01k | struct sc_pkcs15_keyinfo_gostparams *keyinfo_gostparams; |
162 | 5.01k | size_t usage_len = sizeof(info.usage); |
163 | 5.01k | size_t af_len = sizeof(info.access_flags); |
164 | 5.01k | struct sc_asn1_entry asn1_com_key_attr[C_ASN1_COM_KEY_ATTR_SIZE]; |
165 | 5.01k | struct sc_asn1_entry asn1_com_prkey_attr[C_ASN1_COM_PRKEY_ATTR_SIZE]; |
166 | 5.01k | struct sc_asn1_entry asn1_rsakey_attr[C_ASN1_RSAKEY_ATTR_SIZE]; |
167 | 5.01k | struct sc_asn1_entry asn1_prk_rsa_attr[C_ASN1_PRK_RSA_ATTR_SIZE]; |
168 | 5.01k | struct sc_asn1_entry asn1_gostr3410key_attr[C_ASN1_GOSTR3410KEY_ATTR_SIZE]; |
169 | 5.01k | struct sc_asn1_entry asn1_prk_gostr3410_attr[C_ASN1_PRK_GOSTR3410_ATTR_SIZE]; |
170 | 5.01k | struct sc_asn1_entry asn1_ecckey_attr[C_ASN1_ECCKEY_ATTR]; |
171 | 5.01k | struct sc_asn1_entry asn1_prk_ecc_attr[C_ASN1_PRK_ECC_ATTR]; |
172 | 5.01k | struct sc_asn1_entry asn1_prkey[C_ASN1_PRKEY_SIZE]; |
173 | 5.01k | struct sc_asn1_entry asn1_supported_algorithms[C_ASN1_SUPPORTED_ALGORITHMS_SIZE]; |
174 | 5.01k | struct sc_asn1_pkcs15_object rsa_prkey_obj = {obj, asn1_com_key_attr, asn1_com_prkey_attr, asn1_prk_rsa_attr}; |
175 | 5.01k | struct sc_asn1_pkcs15_object gostr3410_prkey_obj = {obj, asn1_com_key_attr, asn1_com_prkey_attr, asn1_prk_gostr3410_attr}; |
176 | 5.01k | struct sc_asn1_pkcs15_object ecc_prkey_obj = { obj, asn1_com_key_attr, asn1_com_prkey_attr, asn1_prk_ecc_attr }; |
177 | 5.01k | u8 ec_domain[32]; |
178 | 5.01k | size_t ec_domain_len = sizeof(ec_domain); |
179 | | |
180 | 5.01k | sc_copy_asn1_entry(c_asn1_prkey, asn1_prkey); |
181 | 5.01k | sc_copy_asn1_entry(c_asn1_supported_algorithms, asn1_supported_algorithms); |
182 | | |
183 | 5.01k | sc_copy_asn1_entry(c_asn1_prk_rsa_attr, asn1_prk_rsa_attr); |
184 | 5.01k | sc_copy_asn1_entry(c_asn1_rsakey_attr, asn1_rsakey_attr); |
185 | 5.01k | sc_copy_asn1_entry(c_asn1_prk_gostr3410_attr, asn1_prk_gostr3410_attr); |
186 | 5.01k | sc_copy_asn1_entry(c_asn1_gostr3410key_attr, asn1_gostr3410key_attr); |
187 | 5.01k | sc_copy_asn1_entry(c_asn1_prk_ecc_attr, asn1_prk_ecc_attr); |
188 | 5.01k | sc_copy_asn1_entry(c_asn1_ecckey_attr, asn1_ecckey_attr); |
189 | | |
190 | 5.01k | sc_copy_asn1_entry(c_asn1_com_prkey_attr, asn1_com_prkey_attr); |
191 | 5.01k | sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr); |
192 | | |
193 | 5.01k | sc_format_asn1_entry(asn1_prkey + 0, &rsa_prkey_obj, NULL, 0); |
194 | 5.01k | sc_format_asn1_entry(asn1_prkey + 1, &ecc_prkey_obj, NULL, 0); |
195 | 5.01k | sc_format_asn1_entry(asn1_prkey + 2, &gostr3410_prkey_obj, NULL, 0); |
196 | | |
197 | 5.01k | sc_format_asn1_entry(asn1_prk_rsa_attr + 0, asn1_rsakey_attr, NULL, 0); |
198 | 5.01k | sc_format_asn1_entry(asn1_prk_gostr3410_attr + 0, asn1_gostr3410key_attr, NULL, 0); |
199 | 5.01k | sc_format_asn1_entry(asn1_prk_ecc_attr + 0, asn1_ecckey_attr, NULL, 0); |
200 | | |
201 | 5.01k | sc_format_asn1_entry(asn1_rsakey_attr + 0, &info.path, NULL, 0); |
202 | 5.01k | sc_format_asn1_entry(asn1_rsakey_attr + 1, &info.modulus_length, NULL, 0); |
203 | | |
204 | 5.01k | sc_format_asn1_entry(asn1_gostr3410key_attr + 0, &info.path, NULL, 0); |
205 | 5.01k | sc_format_asn1_entry(asn1_gostr3410key_attr + 1, &gostr3410_params[0], NULL, 0); |
206 | 5.01k | sc_format_asn1_entry(asn1_gostr3410key_attr + 2, &gostr3410_params[1], NULL, 0); |
207 | 5.01k | sc_format_asn1_entry(asn1_gostr3410key_attr + 3, &gostr3410_params[2], NULL, 0); |
208 | | |
209 | 5.01k | sc_format_asn1_entry(asn1_ecckey_attr + 0, &info.path, NULL, 0); |
210 | 5.01k | sc_format_asn1_entry(asn1_ecckey_attr + 1, &info.field_length, NULL, 0); |
211 | 5.01k | sc_format_asn1_entry(asn1_ecckey_attr + 3, ec_domain, &ec_domain_len, 0); |
212 | | |
213 | 5.01k | sc_format_asn1_entry(asn1_com_key_attr + 0, &info.id, NULL, 0); |
214 | 5.01k | sc_format_asn1_entry(asn1_com_key_attr + 1, &info.usage, &usage_len, 0); |
215 | 5.01k | sc_format_asn1_entry(asn1_com_key_attr + 2, &info.native, NULL, 0); |
216 | 5.01k | sc_format_asn1_entry(asn1_com_key_attr + 3, &info.access_flags, &af_len, 0); |
217 | 5.01k | sc_format_asn1_entry(asn1_com_key_attr + 4, &info.key_reference, NULL, 0); |
218 | | |
219 | 85.2k | for (i=0; i<SC_MAX_SUPPORTED_ALGORITHMS && (asn1_supported_algorithms + i)->name; i++) |
220 | 80.2k | sc_format_asn1_entry(asn1_supported_algorithms + i, &info.algo_refs[i], NULL, 0); |
221 | 5.01k | sc_format_asn1_entry(asn1_com_key_attr + 5, asn1_supported_algorithms, NULL, 0); |
222 | | |
223 | 5.01k | sc_format_asn1_entry(asn1_com_prkey_attr + 0, &info.subject.value, &info.subject.len, 0); |
224 | | |
225 | | /* Fill in defaults */ |
226 | 5.01k | memset(&info, 0, sizeof(info)); |
227 | 5.01k | info.key_reference = -1; |
228 | 5.01k | info.native = 1; |
229 | 5.01k | memset(gostr3410_params, 0, sizeof(gostr3410_params)); |
230 | | |
231 | 5.01k | r = sc_asn1_decode_choice(ctx, asn1_prkey, *buf, *buflen, buf, buflen); |
232 | 5.01k | if (r == SC_ERROR_ASN1_END_OF_CONTENTS) |
233 | 1.08k | goto err; |
234 | 3.92k | LOG_TEST_GOTO_ERR(ctx, r, "PrKey DF ASN.1 decoding failed"); |
235 | 1.72k | if (asn1_prkey[0].flags & SC_ASN1_PRESENT) { |
236 | 457 | obj->type = SC_PKCS15_TYPE_PRKEY_RSA; |
237 | 457 | } |
238 | 1.26k | else if (asn1_prkey[1].flags & SC_ASN1_PRESENT) { |
239 | 97 | obj->type = SC_PKCS15_TYPE_PRKEY_EC; |
240 | 97 | #ifdef ENABLE_OPENSSL |
241 | 97 | if (!(asn1_ecckey_attr[1].flags & SC_ASN1_PRESENT) && (asn1_ecckey_attr[3].flags & SC_ASN1_PRESENT)) { |
242 | 8 | const unsigned char *p = ec_domain; |
243 | 8 | ASN1_OBJECT *object = d2i_ASN1_OBJECT(NULL, &p, ec_domain_len); |
244 | 8 | int nid; |
245 | 8 | EC_GROUP *group; |
246 | 8 | if (!object) { |
247 | 3 | r = SC_ERROR_INVALID_ASN1_OBJECT; |
248 | 3 | goto err; |
249 | 3 | } |
250 | 5 | nid = OBJ_obj2nid(object); |
251 | 5 | ASN1_OBJECT_free(object); |
252 | 5 | if (nid == NID_undef) { |
253 | 1 | sc_log_openssl(ctx); |
254 | 1 | r = SC_ERROR_OBJECT_NOT_FOUND; |
255 | 1 | goto err; |
256 | 1 | } |
257 | 4 | group = EC_GROUP_new_by_curve_name(nid); |
258 | 4 | if (!group) { |
259 | 1 | sc_log_openssl(ctx); |
260 | 1 | r = SC_ERROR_INVALID_DATA; |
261 | 1 | goto err; |
262 | 1 | } |
263 | 3 | info.field_length = EC_GROUP_order_bits(group); |
264 | 3 | EC_GROUP_free(group); |
265 | 3 | if (!info.field_length) { |
266 | 0 | sc_log_openssl(ctx); |
267 | 0 | r = SC_ERROR_CORRUPTED_DATA; |
268 | 0 | goto err; |
269 | 0 | } |
270 | 3 | } |
271 | 97 | #endif |
272 | 97 | } |
273 | 1.16k | else if (asn1_prkey[2].flags & SC_ASN1_PRESENT) { |
274 | | /* FIXME proper handling of gost parameters without the need of |
275 | | * allocating data here. this would also make sc_pkcs15_free_key_params |
276 | | * obsolete */ |
277 | 30 | obj->type = SC_PKCS15_TYPE_PRKEY_GOSTR3410; |
278 | 30 | if (info.modulus_length != 0 || info.params.len != 0) { |
279 | 0 | r = SC_ERROR_INVALID_ASN1_OBJECT; |
280 | 0 | goto err; |
281 | 0 | } |
282 | 30 | info.modulus_length = SC_PKCS15_GOSTR3410_KEYSIZE; |
283 | 30 | info.params.len = sizeof(struct sc_pkcs15_keyinfo_gostparams); |
284 | 30 | info.params.data = malloc(info.params.len); |
285 | 30 | if (info.params.data == NULL) { |
286 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
287 | 0 | goto err; |
288 | 0 | } |
289 | 30 | keyinfo_gostparams = info.params.data; |
290 | 30 | keyinfo_gostparams->gostr3410 = gostr3410_params[0]; |
291 | 30 | keyinfo_gostparams->gostr3411 = gostr3410_params[1]; |
292 | 30 | keyinfo_gostparams->gost28147 = gostr3410_params[2]; |
293 | 30 | } |
294 | 1.13k | else { |
295 | 1.13k | r = SC_ERROR_INVALID_ASN1_OBJECT; |
296 | 1.13k | LOG_TEST_GOTO_ERR(ctx, r, "Neither RSA or GOSTR3410 or ECC key in PrKDF entry."); |
297 | 1.13k | } |
298 | | |
299 | 579 | if (!p15card->app || !p15card->app->ddo.aid.len) { |
300 | 548 | if (!p15card->file_app) { |
301 | 16 | r = SC_ERROR_INTERNAL; |
302 | 16 | goto err; |
303 | 16 | } |
304 | 532 | r = sc_pkcs15_make_absolute_path(&p15card->file_app->path, &info.path); |
305 | 532 | if (r < 0) { |
306 | 0 | goto err; |
307 | 0 | } |
308 | 532 | } |
309 | 31 | else { |
310 | 31 | info.path.aid = p15card->app->ddo.aid; |
311 | 31 | } |
312 | 563 | sc_log(ctx, "PrivKey path '%s'", sc_print_path(&info.path)); |
313 | | |
314 | | /* OpenSC 0.11.4 and older encoded "keyReference" as a negative value. |
315 | | * Fixed in 0.11.5 we need to add a hack, so old cards continue to work. */ |
316 | 563 | if (info.key_reference < -1) |
317 | 104 | info.key_reference += 256; |
318 | | |
319 | | /* Check the auth_id - if not present, try and find it in access rules */ |
320 | 563 | if ((obj->flags & SC_PKCS15_CO_FLAG_PRIVATE) && (obj->auth_id.len == 0)) { |
321 | 265 | sc_log(ctx, "Private key %s has no auth ID - checking AccessControlRules", |
322 | 265 | sc_pkcs15_print_id(&info.id)); |
323 | | |
324 | | /* Search in the access_rules for an appropriate auth ID */ |
325 | 2.38k | for (i = 0; i < SC_PKCS15_MAX_ACCESS_RULES; i++) { |
326 | | /* If access_mode is one of the private key usage modes */ |
327 | 2.12k | if (obj->access_rules[i].access_mode & |
328 | 2.12k | (SC_PKCS15_ACCESS_RULE_MODE_EXECUTE | |
329 | 2.12k | SC_PKCS15_ACCESS_RULE_MODE_PSO_CDS | |
330 | 2.12k | SC_PKCS15_ACCESS_RULE_MODE_PSO_DECRYPT | |
331 | 2.12k | SC_PKCS15_ACCESS_RULE_MODE_INT_AUTH)) { |
332 | 0 | if (obj->access_rules[i].auth_id.len != 0) { |
333 | | /* Found an auth ID to use for private key access */ |
334 | 0 | obj->auth_id = obj->access_rules[i].auth_id; |
335 | 0 | sc_log(ctx, "Auth ID found - %s", |
336 | 0 | sc_pkcs15_print_id(&obj->auth_id)); |
337 | 0 | break; |
338 | 0 | } |
339 | 0 | } |
340 | 2.12k | } |
341 | | |
342 | | /* No auth ID found */ |
343 | 265 | if (i == SC_PKCS15_MAX_ACCESS_RULES) |
344 | 265 | sc_log(ctx, "Warning: No auth ID found"); |
345 | 265 | } |
346 | | |
347 | 563 | obj->data = malloc(sizeof(info)); |
348 | 563 | if (obj->data == NULL) { |
349 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
350 | 0 | goto err; |
351 | 0 | } |
352 | 563 | memcpy(obj->data, &info, sizeof(info)); |
353 | | |
354 | 563 | sc_log(ctx, "Key Subject %s", sc_dump_hex(info.subject.value, info.subject.len)); |
355 | 563 | sc_log(ctx, "Key path %s", sc_print_path(&info.path)); |
356 | | |
357 | 563 | r = SC_SUCCESS; |
358 | | |
359 | 5.01k | err: |
360 | 5.01k | if (r < 0) { |
361 | | /* This might have allocated something. If so, clear it now */ |
362 | 4.45k | free(info.subject.value); |
363 | 4.45k | sc_pkcs15_free_key_params(&info.params); |
364 | 4.45k | } |
365 | | |
366 | 5.01k | return r; |
367 | 563 | } |
368 | | |
369 | | int sc_pkcs15_encode_prkdf_entry(sc_context_t *ctx, const struct sc_pkcs15_object *obj, |
370 | | u8 **buf, size_t *buflen) |
371 | 1.75k | { |
372 | 1.75k | struct sc_asn1_entry asn1_com_key_attr[C_ASN1_COM_KEY_ATTR_SIZE]; |
373 | 1.75k | struct sc_asn1_entry asn1_com_prkey_attr[C_ASN1_COM_PRKEY_ATTR_SIZE]; |
374 | 1.75k | struct sc_asn1_entry asn1_rsakey_attr[C_ASN1_RSAKEY_ATTR_SIZE]; |
375 | 1.75k | struct sc_asn1_entry asn1_prk_rsa_attr[C_ASN1_PRK_RSA_ATTR_SIZE]; |
376 | 1.75k | struct sc_asn1_entry asn1_gostr3410key_attr[C_ASN1_GOSTR3410KEY_ATTR_SIZE]; |
377 | 1.75k | struct sc_asn1_entry asn1_prk_gostr3410_attr[C_ASN1_PRK_GOSTR3410_ATTR_SIZE]; |
378 | 1.75k | struct sc_asn1_entry asn1_ecckey_attr[C_ASN1_ECCKEY_ATTR]; |
379 | 1.75k | struct sc_asn1_entry asn1_prk_ecc_attr[C_ASN1_PRK_ECC_ATTR]; |
380 | 1.75k | struct sc_asn1_entry asn1_prkey[C_ASN1_PRKEY_SIZE]; |
381 | 1.75k | struct sc_asn1_entry asn1_supported_algorithms[C_ASN1_SUPPORTED_ALGORITHMS_SIZE]; |
382 | 1.75k | struct sc_asn1_pkcs15_object rsa_prkey_obj = { |
383 | 1.75k | (struct sc_pkcs15_object *) obj, asn1_com_key_attr, |
384 | 1.75k | asn1_com_prkey_attr, asn1_prk_rsa_attr |
385 | 1.75k | }; |
386 | 1.75k | struct sc_asn1_pkcs15_object gostr3410_prkey_obj = { |
387 | 1.75k | (struct sc_pkcs15_object *) obj, |
388 | 1.75k | asn1_com_key_attr, asn1_com_prkey_attr, |
389 | 1.75k | asn1_prk_gostr3410_attr |
390 | 1.75k | }; |
391 | 1.75k | struct sc_asn1_pkcs15_object ecc_prkey_obj = { |
392 | 1.75k | (struct sc_pkcs15_object *) obj, |
393 | 1.75k | asn1_com_key_attr, asn1_com_prkey_attr, |
394 | 1.75k | asn1_prk_ecc_attr |
395 | 1.75k | }; |
396 | 1.75k | struct sc_pkcs15_prkey_info *prkey = (struct sc_pkcs15_prkey_info *) obj->data; |
397 | 1.75k | struct sc_pkcs15_keyinfo_gostparams *keyinfo_gostparams; |
398 | 1.75k | int r, i; |
399 | 1.75k | size_t af_len, usage_len; |
400 | | |
401 | 1.75k | sc_copy_asn1_entry(c_asn1_prkey, asn1_prkey); |
402 | 1.75k | sc_copy_asn1_entry(c_asn1_supported_algorithms, asn1_supported_algorithms); |
403 | | |
404 | 1.75k | sc_copy_asn1_entry(c_asn1_prk_rsa_attr, asn1_prk_rsa_attr); |
405 | 1.75k | sc_copy_asn1_entry(c_asn1_rsakey_attr, asn1_rsakey_attr); |
406 | 1.75k | sc_copy_asn1_entry(c_asn1_prk_gostr3410_attr, asn1_prk_gostr3410_attr); |
407 | 1.75k | sc_copy_asn1_entry(c_asn1_gostr3410key_attr, asn1_gostr3410key_attr); |
408 | 1.75k | sc_copy_asn1_entry(c_asn1_prk_ecc_attr, asn1_prk_ecc_attr); |
409 | 1.75k | sc_copy_asn1_entry(c_asn1_ecckey_attr, asn1_ecckey_attr); |
410 | | |
411 | 1.75k | sc_copy_asn1_entry(c_asn1_com_prkey_attr, asn1_com_prkey_attr); |
412 | 1.75k | sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr); |
413 | | |
414 | 1.75k | switch (obj->type) { |
415 | 1.65k | case SC_PKCS15_TYPE_PRKEY_RSA: |
416 | 1.65k | sc_format_asn1_entry(asn1_prkey + 0, &rsa_prkey_obj, NULL, 1); |
417 | 1.65k | sc_format_asn1_entry(asn1_prk_rsa_attr + 0, asn1_rsakey_attr, NULL, 1); |
418 | 1.65k | sc_format_asn1_entry(asn1_rsakey_attr + 0, &prkey->path, NULL, 1); |
419 | 1.65k | sc_format_asn1_entry(asn1_rsakey_attr + 1, &prkey->modulus_length, NULL, 1); |
420 | 1.65k | break; |
421 | 96 | case SC_PKCS15_TYPE_PRKEY_EC: |
422 | 96 | sc_format_asn1_entry(asn1_prkey + 1, &ecc_prkey_obj, NULL, 1); |
423 | 96 | sc_format_asn1_entry(asn1_prk_ecc_attr + 0, asn1_ecckey_attr, NULL, 1); |
424 | 96 | sc_format_asn1_entry(asn1_ecckey_attr + 0, &prkey->path, NULL, 1); |
425 | 96 | sc_format_asn1_entry(asn1_ecckey_attr + 1, &prkey->field_length, NULL, 1); |
426 | 96 | break; |
427 | 0 | case SC_PKCS15_TYPE_PRKEY_GOSTR3410: |
428 | 0 | sc_format_asn1_entry(asn1_prkey + 2, &gostr3410_prkey_obj, NULL, 1); |
429 | 0 | sc_format_asn1_entry(asn1_prk_gostr3410_attr + 0, asn1_gostr3410key_attr, NULL, 1); |
430 | 0 | sc_format_asn1_entry(asn1_gostr3410key_attr + 0, &prkey->path, NULL, 1); |
431 | 0 | if (prkey->params.len == sizeof(*keyinfo_gostparams)) { |
432 | 0 | keyinfo_gostparams = prkey->params.data; |
433 | 0 | sc_format_asn1_entry(asn1_gostr3410key_attr + 1, &keyinfo_gostparams->gostr3410, NULL, 1); |
434 | 0 | sc_format_asn1_entry(asn1_gostr3410key_attr + 2, &keyinfo_gostparams->gostr3411, NULL, 1); |
435 | 0 | sc_format_asn1_entry(asn1_gostr3410key_attr + 3, &keyinfo_gostparams->gost28147, NULL, 1); |
436 | 0 | } |
437 | 0 | break; |
438 | 0 | default: |
439 | 0 | sc_log(ctx, "Invalid private key type: %X", obj->type); |
440 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL); |
441 | 0 | break; |
442 | 1.75k | } |
443 | 1.75k | sc_format_asn1_entry(asn1_com_key_attr + 0, &prkey->id, NULL, 1); |
444 | 1.75k | usage_len = sizeof(prkey->usage); |
445 | 1.75k | sc_format_asn1_entry(asn1_com_key_attr + 1, &prkey->usage, &usage_len, 1); |
446 | 1.75k | if (prkey->native == 0) |
447 | 0 | sc_format_asn1_entry(asn1_com_key_attr + 2, &prkey->native, NULL, 1); |
448 | 1.75k | if (prkey->access_flags) { |
449 | 1.38k | af_len = sizeof(prkey->access_flags); |
450 | 1.38k | sc_format_asn1_entry(asn1_com_key_attr + 3, &prkey->access_flags, &af_len, 1); |
451 | 1.38k | } |
452 | 1.75k | if (prkey->key_reference >= 0) |
453 | 1.57k | sc_format_asn1_entry(asn1_com_key_attr + 4, &prkey->key_reference, NULL, 1); |
454 | | |
455 | 1.75k | for (i=0; i<SC_MAX_SUPPORTED_ALGORITHMS && prkey->algo_refs[i]; i++) { |
456 | 0 | sc_log(ctx, "Encode algorithm(%i) %i", i, prkey->algo_refs[i]); |
457 | 0 | sc_format_asn1_entry(asn1_supported_algorithms + i, &prkey->algo_refs[i], NULL, 1); |
458 | 0 | } |
459 | 1.75k | sc_format_asn1_entry(asn1_com_key_attr + 5, asn1_supported_algorithms, NULL, prkey->algo_refs[0] != 0); |
460 | | |
461 | 1.75k | if (prkey->subject.value && prkey->subject.len) |
462 | 0 | sc_format_asn1_entry(asn1_com_prkey_attr + 0, prkey->subject.value, &prkey->subject.len, 1); |
463 | 1.75k | else |
464 | 1.75k | memset(asn1_com_prkey_attr, 0, sizeof(asn1_com_prkey_attr)); |
465 | | |
466 | 1.75k | r = sc_asn1_encode(ctx, asn1_prkey, buf, buflen); |
467 | | |
468 | 1.75k | sc_log(ctx, "Key path %s", sc_print_path(&prkey->path)); |
469 | 1.75k | return r; |
470 | 1.75k | } |
471 | | |
472 | | int |
473 | | sc_pkcs15_prkey_attrs_from_cert(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *cert_object, |
474 | | struct sc_pkcs15_object **out_key_object) |
475 | 651 | { |
476 | 651 | struct sc_context *ctx = p15card->card->ctx; |
477 | 651 | #ifdef ENABLE_OPENSSL |
478 | 651 | struct sc_pkcs15_object *key_object = NULL; |
479 | 651 | struct sc_pkcs15_prkey_info *key_info = NULL; |
480 | 651 | X509 *x = NULL; |
481 | 651 | BIO *mem = NULL; |
482 | 651 | unsigned char *buff = NULL, *ptr = NULL; |
483 | 651 | int rv; |
484 | | |
485 | 651 | LOG_FUNC_CALLED(ctx); |
486 | 651 | if (out_key_object) |
487 | 651 | *out_key_object = NULL; |
488 | | |
489 | 651 | rv = sc_pkcs15_find_prkey_by_id(p15card, &((struct sc_pkcs15_cert_info *)cert_object->data)->id, &key_object); |
490 | 651 | if (rv == SC_ERROR_OBJECT_NOT_FOUND) |
491 | 651 | LOG_FUNC_RETURN(ctx, SC_SUCCESS); |
492 | 296 | LOG_TEST_RET(ctx, rv, "Find private key error"); |
493 | | |
494 | 296 | key_info = (struct sc_pkcs15_prkey_info *) key_object->data; |
495 | | |
496 | 296 | sc_log(ctx, "CertValue(%"SC_FORMAT_LEN_SIZE_T"u) %p", |
497 | 296 | cert_object->content.len, cert_object->content.value); |
498 | 296 | mem = BIO_new_mem_buf(cert_object->content.value, (int)cert_object->content.len); |
499 | 296 | if (!mem) { |
500 | 296 | sc_log_openssl(ctx); |
501 | 296 | LOG_TEST_RET(ctx, SC_ERROR_INTERNAL, "MEM buffer allocation error"); |
502 | 296 | } |
503 | | |
504 | 0 | x = d2i_X509_bio(mem, NULL); |
505 | 0 | if (!x) { |
506 | 0 | sc_log_openssl(ctx); |
507 | 0 | LOG_TEST_RET(ctx, SC_ERROR_INTERNAL, "x509 parse error"); |
508 | 0 | } |
509 | 0 | buff = OPENSSL_malloc(i2d_X509(x,NULL) + EVP_MAX_MD_SIZE); |
510 | 0 | if (!buff) { |
511 | 0 | sc_log_openssl(ctx); |
512 | 0 | LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "OpenSSL allocation error"); |
513 | 0 | } |
514 | | |
515 | 0 | ptr = buff; |
516 | 0 | rv = i2d_X509_NAME(X509_get_subject_name(x), &ptr); |
517 | 0 | if (rv <= 0) { |
518 | 0 | sc_log_openssl(ctx); |
519 | 0 | LOG_TEST_RET(ctx, SC_ERROR_INTERNAL, "Get subject name error"); |
520 | 0 | } |
521 | | |
522 | 0 | key_info->subject.value = malloc(rv); |
523 | 0 | if (!key_info->subject.value) |
524 | 0 | LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Subject allocation error"); |
525 | | |
526 | 0 | memcpy(key_info->subject.value, buff, rv); |
527 | 0 | key_info->subject.len = rv; |
528 | |
|
529 | 0 | strlcpy(key_object->label, cert_object->label, sizeof(key_object->label)); |
530 | |
|
531 | 0 | rv = 0; |
532 | |
|
533 | 0 | if (x) |
534 | 0 | X509_free(x); |
535 | 0 | if (mem) |
536 | 0 | BIO_free(mem); |
537 | 0 | if (buff) |
538 | 0 | OPENSSL_free(buff); |
539 | |
|
540 | 0 | ERR_clear_error(); |
541 | |
|
542 | 0 | if (out_key_object) |
543 | 0 | *out_key_object = key_object; |
544 | |
|
545 | 0 | sc_log(ctx, "Subject %s", sc_dump_hex(key_info->subject.value, key_info->subject.len)); |
546 | 0 | LOG_FUNC_RETURN(ctx, rv); |
547 | | #else |
548 | | LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); |
549 | | #endif |
550 | 0 | } |
551 | | |
552 | | |
553 | | void |
554 | | sc_pkcs15_erase_prkey(struct sc_pkcs15_prkey *key) |
555 | 9.52k | { |
556 | 9.52k | if (!key) |
557 | 0 | return; |
558 | 9.52k | switch (key->algorithm) { |
559 | 4.76k | case SC_ALGORITHM_RSA: |
560 | 4.76k | free(key->u.rsa.modulus.data); |
561 | 4.76k | free(key->u.rsa.exponent.data); |
562 | 4.76k | free(key->u.rsa.d.data); |
563 | 4.76k | free(key->u.rsa.p.data); |
564 | 4.76k | free(key->u.rsa.q.data); |
565 | 4.76k | free(key->u.rsa.iqmp.data); |
566 | 4.76k | free(key->u.rsa.dmp1.data); |
567 | 4.76k | free(key->u.rsa.dmq1.data); |
568 | 4.76k | break; |
569 | 0 | case SC_ALGORITHM_GOSTR3410: |
570 | 0 | free(key->u.gostr3410.d.data); |
571 | 0 | break; |
572 | 4.76k | case SC_ALGORITHM_EC: |
573 | 4.76k | case SC_ALGORITHM_EDDSA: |
574 | 4.76k | case SC_ALGORITHM_XEDDSA: |
575 | | /* EC, Edwards and Montgomery use common ec params */ |
576 | 4.76k | sc_clear_ec_params(&key->u.ec.params); |
577 | 4.76k | free(key->u.ec.privateD.data); |
578 | 4.76k | free(key->u.ec.ecpointQ.value); |
579 | 4.76k | break; |
580 | 9.52k | } |
581 | 9.52k | sc_mem_clear(key, sizeof(*key)); |
582 | 9.52k | } |
583 | | |
584 | | void |
585 | | sc_pkcs15_free_prkey(struct sc_pkcs15_prkey *key) |
586 | 7 | { |
587 | 7 | if (!key) |
588 | 7 | return; |
589 | 0 | sc_pkcs15_erase_prkey(key); |
590 | 0 | free(key); |
591 | 0 | } |
592 | | |
593 | | void sc_pkcs15_free_prkey_info(sc_pkcs15_prkey_info_t *key) |
594 | 18.1k | { |
595 | 18.1k | if (!key) |
596 | 19 | return; |
597 | | |
598 | 18.1k | if (key->subject.value) |
599 | 175 | free(key->subject.value); |
600 | | |
601 | 18.1k | sc_pkcs15_free_key_params(&key->params); |
602 | | |
603 | 18.1k | sc_aux_data_free(&key->aux_data); |
604 | | |
605 | 18.1k | free(key); |
606 | 18.1k | } |
607 | | |
608 | | int |
609 | | sc_pkcs15_convert_bignum(sc_pkcs15_bignum_t *dst, const void *src) |
610 | 0 | { |
611 | 0 | #ifdef ENABLE_OPENSSL |
612 | 0 | const BIGNUM *bn = (const BIGNUM *)src; |
613 | |
|
614 | 0 | if (bn == 0) |
615 | 0 | return 0; |
616 | 0 | dst->len = BN_num_bytes(bn); |
617 | 0 | dst->data = malloc(dst->len); |
618 | 0 | if (!dst->data) |
619 | 0 | return 0; |
620 | 0 | BN_bn2bin(bn, dst->data); |
621 | 0 | return 1; |
622 | | #else |
623 | | return 0; |
624 | | #endif |
625 | 0 | } |
626 | | |
627 | | int |
628 | | sc_pkcs15_convert_prkey(struct sc_pkcs15_prkey *pkcs15_key, void *evp_key) |
629 | 0 | { |
630 | 0 | #ifdef ENABLE_OPENSSL |
631 | 0 | EVP_PKEY *pk = (EVP_PKEY *)evp_key; |
632 | 0 | int pk_type; |
633 | 0 | pk_type = EVP_PKEY_base_id(pk); |
634 | |
|
635 | 0 | switch (pk_type) { |
636 | 0 | case EVP_PKEY_RSA: { |
637 | 0 | struct sc_pkcs15_prkey_rsa *dst = &pkcs15_key->u.rsa; |
638 | |
|
639 | 0 | #if OPENSSL_VERSION_NUMBER < 0x30000000L |
640 | 0 | const BIGNUM *src_n, *src_e, *src_d, *src_p, *src_q, *src_iqmp, *src_dmp1, *src_dmq1; |
641 | 0 | RSA *src = NULL; |
642 | 0 | if (!(src = EVP_PKEY_get1_RSA(pk))) |
643 | 0 | return SC_ERROR_INCOMPATIBLE_KEY; |
644 | | |
645 | 0 | RSA_get0_key(src, &src_n, &src_e, &src_d); |
646 | 0 | RSA_get0_factors(src, &src_p, &src_q); |
647 | 0 | RSA_get0_crt_params(src, &src_dmp1, &src_dmq1, &src_iqmp); |
648 | | #else |
649 | | BIGNUM *src_n = NULL, *src_e = NULL, *src_d = NULL, *src_p = NULL, *src_q = NULL; |
650 | | BIGNUM *src_iqmp = NULL, *src_dmp1 = NULL, *src_dmq1 = NULL; |
651 | | if (EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_RSA_N, &src_n) != 1 || |
652 | | EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_RSA_E, &src_e) != 1 || |
653 | | EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_RSA_D, &src_d) != 1 || |
654 | | EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_RSA_FACTOR1, &src_p) != 1 || |
655 | | EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_RSA_FACTOR2, &src_q) != 1 || |
656 | | EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_RSA_EXPONENT1, &src_dmp1) != 1 || |
657 | | EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_RSA_EXPONENT2, &src_dmq1) != 1 || |
658 | | EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_RSA_COEFFICIENT1, &src_iqmp) != 1) { |
659 | | BN_free(src_n); |
660 | | BN_free(src_e); |
661 | | BN_free(src_d); |
662 | | BN_free(src_p); |
663 | | BN_free(src_q); |
664 | | BN_free(src_dmp1); BN_free(src_dmq1); |
665 | | return SC_ERROR_UNKNOWN; |
666 | | } |
667 | | #endif |
668 | 0 | pkcs15_key->algorithm = SC_ALGORITHM_RSA; |
669 | 0 | if (!sc_pkcs15_convert_bignum(&dst->modulus, src_n) || |
670 | 0 | !sc_pkcs15_convert_bignum(&dst->exponent, src_e) || |
671 | 0 | !sc_pkcs15_convert_bignum(&dst->d, src_d) || |
672 | 0 | !sc_pkcs15_convert_bignum(&dst->p, src_p) || |
673 | 0 | !sc_pkcs15_convert_bignum(&dst->q, src_q)) { |
674 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
675 | | BN_free(src_n); |
676 | | BN_free(src_e); |
677 | | BN_free(src_d); |
678 | | BN_free(src_p); |
679 | | BN_free(src_q); |
680 | | BN_free(src_iqmp); |
681 | | BN_free(src_dmp1); |
682 | | BN_free(src_dmq1); |
683 | | #else |
684 | 0 | RSA_free(src); |
685 | 0 | #endif |
686 | 0 | return SC_ERROR_NOT_SUPPORTED; |
687 | 0 | } |
688 | 0 | if (src_iqmp && src_dmp1 && src_dmq1) { |
689 | 0 | sc_pkcs15_convert_bignum(&dst->iqmp, src_iqmp); |
690 | 0 | sc_pkcs15_convert_bignum(&dst->dmp1, src_dmp1); |
691 | 0 | sc_pkcs15_convert_bignum(&dst->dmq1, src_dmq1); |
692 | 0 | } |
693 | 0 | #if OPENSSL_VERSION_NUMBER < 0x30000000L |
694 | 0 | RSA_free(src); |
695 | | #else |
696 | | BN_free(src_n); |
697 | | BN_free(src_e); |
698 | | BN_free(src_d); |
699 | | BN_free(src_p); |
700 | | BN_free(src_q); |
701 | | BN_free(src_iqmp); |
702 | | BN_free(src_dmp1); |
703 | | BN_free(src_dmq1); |
704 | | #endif |
705 | 0 | break; |
706 | 0 | } |
707 | | |
708 | 0 | #if !defined(OPENSSL_NO_EC) |
709 | 0 | case NID_id_GostR3410_2001: { |
710 | 0 | struct sc_pkcs15_prkey_gostr3410 *dst = &pkcs15_key->u.gostr3410; |
711 | 0 | pkcs15_key->algorithm = SC_ALGORITHM_GOSTR3410; |
712 | |
|
713 | 0 | #if OPENSSL_VERSION_NUMBER < 0x30000000L |
714 | 0 | const BIGNUM *src_priv_key = NULL; |
715 | 0 | EC_KEY *src = NULL; |
716 | 0 | if (!(src = EVP_PKEY_get0(pk))) |
717 | 0 | return SC_ERROR_INCOMPATIBLE_KEY; |
718 | 0 | if (!(src_priv_key = EC_KEY_get0_private_key(src))) |
719 | 0 | return SC_ERROR_INTERNAL; |
720 | | #else |
721 | | BIGNUM *src_priv_key = NULL; |
722 | | if (EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_PRIV_KEY, &src_priv_key) != 1) { |
723 | | return SC_ERROR_UNKNOWN; |
724 | | } |
725 | | #endif |
726 | 0 | sc_pkcs15_convert_bignum(&dst->d, src_priv_key); |
727 | 0 | #if OPENSSL_VERSION_NUMBER < 0x30000000L |
728 | 0 | EC_KEY_free(src); |
729 | | #else |
730 | | BN_free(src_priv_key); |
731 | | #endif |
732 | 0 | break; |
733 | 0 | } |
734 | | |
735 | 0 | case EVP_PKEY_EC: { |
736 | 0 | struct sc_pkcs15_prkey_ec *dst = &pkcs15_key->u.ec; |
737 | 0 | unsigned char buf[255]; |
738 | 0 | size_t buflen = 255; |
739 | 0 | int nid; |
740 | 0 | pkcs15_key->algorithm = SC_ALGORITHM_EC; |
741 | 0 | #if OPENSSL_VERSION_NUMBER < 0x30000000L |
742 | 0 | const EC_KEY *src = NULL; |
743 | 0 | const EC_GROUP *grp = NULL; |
744 | 0 | const BIGNUM *src_priv_key = NULL; |
745 | 0 | const EC_POINT *src_pub_key = NULL; |
746 | 0 | if (!(src = EVP_PKEY_get0_EC_KEY(pk))) |
747 | 0 | return SC_ERROR_INCOMPATIBLE_KEY; |
748 | 0 | if (!(src_priv_key = EC_KEY_get0_private_key(src)) || |
749 | 0 | !(src_pub_key = EC_KEY_get0_public_key(src)) || |
750 | 0 | !(grp = EC_KEY_get0_group(src))) |
751 | 0 | return SC_ERROR_INCOMPATIBLE_KEY; |
752 | 0 | nid = EC_GROUP_get_curve_name(grp); |
753 | | #else |
754 | | EC_GROUP *grp = NULL; |
755 | | BIGNUM *src_priv_key = NULL; |
756 | | char grp_name[256]; |
757 | | |
758 | | if (EVP_PKEY_get_bn_param(pk, OSSL_PKEY_PARAM_PRIV_KEY, &src_priv_key) != 1) { |
759 | | return SC_ERROR_UNKNOWN; |
760 | | } |
761 | | |
762 | | if (EVP_PKEY_get_group_name(pk, grp_name, sizeof(grp_name), NULL) != 1) { |
763 | | BN_free(src_priv_key); |
764 | | return SC_ERROR_UNKNOWN; |
765 | | } |
766 | | if ((nid = OBJ_sn2nid(grp_name)) == 0) { |
767 | | BN_free(src_priv_key); |
768 | | return SC_ERROR_UNKNOWN; |
769 | | } |
770 | | if ((grp = EC_GROUP_new_by_curve_name(nid)) == NULL) { |
771 | | BN_free(src_priv_key); |
772 | | return SC_ERROR_UNKNOWN; |
773 | | } |
774 | | #endif |
775 | |
|
776 | 0 | if (!sc_pkcs15_convert_bignum(&dst->privateD, src_priv_key)) { |
777 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
778 | | BN_free(src_priv_key); |
779 | | EC_GROUP_free(grp); |
780 | | #endif |
781 | 0 | return SC_ERROR_INCOMPATIBLE_KEY; |
782 | 0 | } |
783 | | |
784 | 0 | #if OPENSSL_VERSION_NUMBER < 0x30000000L |
785 | 0 | if(nid != 0) { |
786 | 0 | const char *sn = OBJ_nid2sn(nid); |
787 | 0 | if (sn) |
788 | 0 | dst->params.named_curve = strdup(sn); |
789 | 0 | } |
790 | | #else |
791 | | dst->params.named_curve = strdup(grp_name); |
792 | | BN_free(src_priv_key); |
793 | | #endif |
794 | |
|
795 | 0 | #if OPENSSL_VERSION_NUMBER < 0x30000000L |
796 | | /* Decode EC_POINT from a octet string */ |
797 | 0 | buflen = EC_POINT_point2oct(grp, src_pub_key, |
798 | 0 | POINT_CONVERSION_UNCOMPRESSED, buf, buflen, NULL); |
799 | 0 | if (!buflen) |
800 | 0 | return SC_ERROR_INCOMPATIBLE_KEY; |
801 | | #else |
802 | | /* Decode EC_POINT from a octet string */ |
803 | | if (EVP_PKEY_get_octet_string_param(pk, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, buf, buflen, &buflen) != 1) { |
804 | | return SC_ERROR_INCOMPATIBLE_KEY; |
805 | | } |
806 | | #endif |
807 | | /* copy the public key */ |
808 | 0 | dst->ecpointQ.value = malloc(buflen); |
809 | 0 | if (!dst->ecpointQ.value) |
810 | 0 | return SC_ERROR_OUT_OF_MEMORY; |
811 | 0 | memcpy(dst->ecpointQ.value, buf, buflen); |
812 | 0 | dst->ecpointQ.len = buflen; |
813 | | |
814 | | /* |
815 | | * In OpenSC the field_length is in bits. Not all curves are a multiple of 8. |
816 | | * EC_POINT_point2oct handles this and returns octstrings that can handle |
817 | | * these curves. Get real field_length from OpenSSL. |
818 | | */ |
819 | 0 | dst->params.field_length = EC_GROUP_get_degree(grp); |
820 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
821 | | EC_GROUP_free(grp); |
822 | | #endif |
823 | | |
824 | | /* Octetstring may need leading zeros if BN is to short */ |
825 | 0 | if (dst->privateD.len < BYTES4BITS(dst->params.field_length)) { |
826 | 0 | size_t d = BYTES4BITS(dst->params.field_length) - dst->privateD.len; |
827 | |
|
828 | 0 | dst->privateD.data = realloc(dst->privateD.data, dst->privateD.len + d); |
829 | 0 | if (!dst->privateD.data) |
830 | 0 | return SC_ERROR_OUT_OF_MEMORY; |
831 | | |
832 | 0 | memmove(dst->privateD.data + d, dst->privateD.data, dst->privateD.len); |
833 | 0 | memset(dst->privateD.data, 0, d); |
834 | |
|
835 | 0 | dst->privateD.len += d; |
836 | 0 | } |
837 | | |
838 | 0 | break; |
839 | 0 | } |
840 | 0 | #endif /* !defined(OPENSSL_NO_EC) */ |
841 | 0 | #ifdef EVP_PKEY_ED25519 |
842 | 0 | case EVP_PKEY_ED25519: { |
843 | | /* TODO */ |
844 | 0 | break; |
845 | 0 | } |
846 | 0 | #endif /* EVP_PKEY_ED25519 */ |
847 | | |
848 | 0 | default: |
849 | 0 | return SC_ERROR_NOT_SUPPORTED; |
850 | 0 | } |
851 | | |
852 | 0 | return SC_SUCCESS; |
853 | | #else |
854 | | return SC_ERROR_NOT_IMPLEMENTED; |
855 | | #endif |
856 | 0 | } |