/src/wolfssl-openssl-api/wolfcrypt/src/evp_pk.c
Line | Count | Source |
1 | | /* evp_pk.c |
2 | | * |
3 | | * Copyright (C) 2006-2026 wolfSSL Inc. |
4 | | * |
5 | | * This file is part of wolfSSL. |
6 | | * |
7 | | * wolfSSL is free software; you can redistribute it and/or modify |
8 | | * it under the terms of the GNU General Public License as published by |
9 | | * the Free Software Foundation; either version 3 of the License, or |
10 | | * (at your option) any later version. |
11 | | * |
12 | | * wolfSSL is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | * GNU General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU General Public License |
18 | | * along with this program; if not, write to the Free Software |
19 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA |
20 | | */ |
21 | | |
22 | | #include <wolfssl/wolfcrypt/libwolfssl_sources.h> |
23 | | |
24 | | #if !defined(WOLFSSL_EVP_PK_INCLUDED) |
25 | | #ifndef WOLFSSL_IGNORE_FILE_WARN |
26 | | #warning evp_pk.c does not need to be compiled separately from ssl.c |
27 | | #endif |
28 | | #elif defined(WOLFCRYPT_ONLY) |
29 | | #else |
30 | | |
31 | | /******************************************************************************* |
32 | | * START OF d2i APIs |
33 | | ******************************************************************************/ |
34 | | |
35 | | #ifndef NO_CERTS |
36 | | |
37 | | #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) |
38 | | /** |
39 | | * Make an EVP PKEY and put data and type in. |
40 | | * |
41 | | * @param [in, out] out On in, an EVP PKEY or NULL. |
42 | | * On out, an EVP PKEY or NULL. |
43 | | * @param [in] mem Memory containing key data. |
44 | | * @param [in] memSz Size of key data in bytes. |
45 | | * @param [in] priv 1 means private key, 0 means public key. |
46 | | * @param [in] type The type of public/private key. |
47 | | * @return 1 on success. |
48 | | * @return 0 otherwise. |
49 | | */ |
50 | | static int d2i_make_pkey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, |
51 | | word32 memSz, int priv, int type) |
52 | 1.52k | { |
53 | 1.52k | WOLFSSL_EVP_PKEY* pkey; |
54 | 1.52k | int ret = 1; |
55 | | |
56 | | /* Get or create the EVP PKEY object. */ |
57 | 1.52k | if (*out != NULL) { |
58 | 0 | pkey = *out; |
59 | 0 | } |
60 | 1.52k | else { |
61 | 1.52k | pkey = wolfSSL_EVP_PKEY_new(); |
62 | 1.52k | if (pkey == NULL) { |
63 | 0 | WOLFSSL_MSG("wolfSSL_EVP_PKEY_new error"); |
64 | 0 | return 0; |
65 | 0 | } |
66 | 1.52k | } |
67 | | |
68 | | /* Set the size and allocate memory for key data to be copied into. */ |
69 | 1.52k | pkey->pkey_sz = (int)memSz; |
70 | 1.52k | if (memSz > 0) { |
71 | 1.52k | pkey->pkey.ptr = (char*)XMALLOC((size_t)memSz, NULL, |
72 | 1.52k | priv ? DYNAMIC_TYPE_PRIVATE_KEY : DYNAMIC_TYPE_PUBLIC_KEY); |
73 | 1.52k | if (pkey->pkey.ptr == NULL) { |
74 | 0 | ret = 0; |
75 | 0 | } |
76 | 1.52k | if (ret == 1) { |
77 | | /* Copy in key data. */ |
78 | 1.52k | XMEMCPY(pkey->pkey.ptr, mem, memSz); |
79 | 1.52k | } |
80 | 1.52k | } |
81 | 1.52k | if (ret == 1) { |
82 | | /* Set key type passed in and return object. */ |
83 | 1.52k | pkey->type = type; |
84 | 1.52k | *out = pkey; |
85 | 1.52k | } |
86 | 1.52k | if ((ret == 0) && (*out == NULL)) { |
87 | | /* Dispose of object allocated in this function. */ |
88 | 0 | wolfSSL_EVP_PKEY_free(pkey); |
89 | 0 | } |
90 | | |
91 | 1.52k | return ret; |
92 | 1.52k | } |
93 | | |
94 | | #if !defined(NO_RSA) |
95 | | /** |
96 | | * Try to make an RSA EVP PKEY from data. |
97 | | * |
98 | | * @param [in, out] out On in, an EVP PKEY or NULL. |
99 | | * On out, an EVP PKEY or NULL. |
100 | | * @param [in] mem Memory containing key data. |
101 | | * @param [in] memSz Size of key data in bytes. |
102 | | * @param [in] priv 1 means private key, 0 means public key. |
103 | | * @return 1 on success. |
104 | | * @return 0 otherwise. |
105 | | */ |
106 | | static int d2iTryRsaKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, |
107 | | long memSz, int priv) |
108 | 3.00k | { |
109 | 3.00k | WOLFSSL_RSA* rsaObj = NULL; |
110 | 3.00k | word32 keyIdx = 0; |
111 | 3.00k | int isRsaKey; |
112 | 3.00k | int ret = 1; |
113 | 3.00k | WC_DECLARE_VAR(rsa, RsaKey, 1, NULL); |
114 | | |
115 | 3.00k | WC_ALLOC_VAR_EX(rsa, RsaKey, 1, NULL, DYNAMIC_TYPE_RSA, return 0); |
116 | | |
117 | 3.00k | XMEMSET(rsa, 0, sizeof(RsaKey)); |
118 | | |
119 | 3.00k | if (wc_InitRsaKey(rsa, NULL) != 0) { |
120 | 0 | WC_FREE_VAR_EX(rsa, NULL, DYNAMIC_TYPE_RSA); |
121 | 0 | return 0; |
122 | 0 | } |
123 | | /* Try decoding data as an RSA private/public key. */ |
124 | 3.00k | if (priv) { |
125 | 0 | isRsaKey = |
126 | 0 | (wc_RsaPrivateKeyDecode(mem, &keyIdx, rsa, (word32)memSz) == 0); |
127 | 0 | } |
128 | 3.00k | else { |
129 | 3.00k | isRsaKey = |
130 | 3.00k | (wc_RsaPublicKeyDecode(mem, &keyIdx, rsa, (word32)memSz) == 0); |
131 | 3.00k | } |
132 | 3.00k | wc_FreeRsaKey(rsa); |
133 | 3.00k | WC_FREE_VAR_EX(rsa, NULL, DYNAMIC_TYPE_RSA); |
134 | | |
135 | 3.00k | if (!isRsaKey) { |
136 | 2.29k | return WOLFSSL_FATAL_ERROR; |
137 | 2.29k | } |
138 | | |
139 | | /* Create RSA key object from data. */ |
140 | 713 | rsaObj = wolfssl_rsa_d2i(NULL, mem, keyIdx, |
141 | 713 | priv ? WOLFSSL_RSA_LOAD_PRIVATE : WOLFSSL_RSA_LOAD_PUBLIC); |
142 | 713 | if (rsaObj == NULL) { |
143 | 36 | ret = 0; |
144 | 36 | } |
145 | 713 | if (ret == 1) { |
146 | | /* Create an EVP PKEY object. */ |
147 | 677 | ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_RSA); |
148 | 677 | } |
149 | 713 | if (ret == 1) { |
150 | | /* Put RSA key object into EVP PKEY object. */ |
151 | 677 | (*out)->ownRsa = 1; |
152 | 677 | (*out)->rsa = rsaObj; |
153 | 677 | } |
154 | 713 | if (ret == 0) { |
155 | 36 | wolfSSL_RSA_free(rsaObj); |
156 | 36 | } |
157 | | |
158 | 713 | return ret; |
159 | 3.00k | } |
160 | | #endif /* !NO_RSA */ |
161 | | |
162 | | #if defined(HAVE_ECC) && defined(OPENSSL_EXTRA) |
163 | | /** |
164 | | * Try to make an ECC EVP PKEY from data. |
165 | | * |
166 | | * @param [in, out] out On in, an EVP PKEY or NULL. |
167 | | * On out, an EVP PKEY or NULL. |
168 | | * @param [in] mem Memory containing key data. |
169 | | * @param [in] memSz Size of key data in bytes. |
170 | | * @param [in] priv 1 means private key, 0 means public key. |
171 | | * @return 1 on success. |
172 | | * @return 0 otherwise. |
173 | | */ |
174 | | static int d2iTryEccKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, |
175 | | long memSz, int priv) |
176 | 2.29k | { |
177 | 2.29k | WOLFSSL_EC_KEY* ec = NULL; |
178 | 2.29k | word32 keyIdx = 0; |
179 | 2.29k | int isEccKey; |
180 | 2.29k | int ret = 1; |
181 | 2.29k | WC_DECLARE_VAR(ecc, ecc_key, 1, NULL); |
182 | | |
183 | 2.29k | WC_ALLOC_VAR_EX(ecc, ecc_key, 1, NULL, DYNAMIC_TYPE_ECC, return 0); |
184 | | |
185 | 2.29k | XMEMSET(ecc, 0, sizeof(ecc_key)); |
186 | | |
187 | 2.29k | if (wc_ecc_init(ecc) != 0) { |
188 | 0 | WC_FREE_VAR_EX(ecc, NULL, DYNAMIC_TYPE_ECC); |
189 | 0 | return 0; |
190 | 0 | } |
191 | | |
192 | | /* Try decoding data as an ECC private/public key. */ |
193 | 2.29k | if (priv) { |
194 | 0 | isEccKey = |
195 | 0 | (wc_EccPrivateKeyDecode(mem, &keyIdx, ecc, (word32)memSz) == 0); |
196 | 0 | } |
197 | 2.29k | else { |
198 | 2.29k | isEccKey = |
199 | 2.29k | (wc_EccPublicKeyDecode(mem, &keyIdx, ecc, (word32)memSz) == 0); |
200 | 2.29k | } |
201 | 2.29k | wc_ecc_free(ecc); |
202 | 2.29k | WC_FREE_VAR_EX(ecc, NULL, DYNAMIC_TYPE_ECC); |
203 | | |
204 | 2.29k | if (!isEccKey) { |
205 | 1.29k | return WOLFSSL_FATAL_ERROR; |
206 | 1.29k | } |
207 | | |
208 | | /* Create EC key object from data. */ |
209 | 998 | ec = wolfSSL_EC_KEY_new(); |
210 | 998 | if (ec == NULL) { |
211 | 0 | ret = 0; |
212 | 0 | } |
213 | 998 | if ((ret == 1) && (wolfSSL_EC_KEY_LoadDer_ex(ec, mem, keyIdx, |
214 | 998 | priv ? WOLFSSL_RSA_LOAD_PRIVATE : WOLFSSL_RSA_LOAD_PUBLIC) != 1)) { |
215 | 201 | ret = 0; |
216 | 201 | } |
217 | 998 | if (ret == 1) { |
218 | | /* Create an EVP PKEY object. */ |
219 | 797 | ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_EC); |
220 | 797 | } |
221 | 998 | if (ret == 1) { |
222 | | /* Put RSA key object into EVP PKEY object. */ |
223 | 797 | (*out)->ownEcc = 1; |
224 | 797 | (*out)->ecc = ec; |
225 | 797 | } |
226 | 998 | if (ret == 0) { |
227 | 201 | wolfSSL_EC_KEY_free(ec); |
228 | 201 | } |
229 | | |
230 | 998 | return ret; |
231 | 2.29k | } |
232 | | #endif /* HAVE_ECC && OPENSSL_EXTRA */ |
233 | | |
234 | | #if !defined(NO_DSA) |
235 | | /** |
236 | | * Try to make a DSA EVP PKEY from data. |
237 | | * |
238 | | * @param [in, out] out On in, an EVP PKEY or NULL. |
239 | | * On out, an EVP PKEY or NULL. |
240 | | * @param [in] mem Memory containing key data. |
241 | | * @param [in] memSz Size of key data in bytes. |
242 | | * @param [in] priv 1 means private key, 0 means public key. |
243 | | * @return 1 on success. |
244 | | * @return 0 otherwise. |
245 | | */ |
246 | | static int d2iTryDsaKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, |
247 | | long memSz, int priv) |
248 | | { |
249 | | WOLFSSL_DSA* dsaObj; |
250 | | word32 keyIdx = 0; |
251 | | int isDsaKey; |
252 | | int ret = 1; |
253 | | WC_DECLARE_VAR(dsa, DsaKey, 1, NULL); |
254 | | |
255 | | WC_ALLOC_VAR_EX(dsa, DsaKey, 1, NULL, DYNAMIC_TYPE_DSA, return 0); |
256 | | |
257 | | XMEMSET(dsa, 0, sizeof(DsaKey)); |
258 | | |
259 | | if (wc_InitDsaKey(dsa) != 0) { |
260 | | WC_FREE_VAR_EX(dsa, NULL, DYNAMIC_TYPE_DSA); |
261 | | return 0; |
262 | | } |
263 | | |
264 | | /* Try decoding data as a DSA private/public key. */ |
265 | | if (priv) { |
266 | | isDsaKey = |
267 | | (wc_DsaPrivateKeyDecode(mem, &keyIdx, dsa, (word32)memSz) == 0); |
268 | | } |
269 | | else { |
270 | | isDsaKey = |
271 | | (wc_DsaPublicKeyDecode(mem, &keyIdx, dsa, (word32)memSz) == 0); |
272 | | } |
273 | | wc_FreeDsaKey(dsa); |
274 | | WC_FREE_VAR_EX(dsa, NULL, DYNAMIC_TYPE_DSA); |
275 | | |
276 | | /* test if DSA key */ |
277 | | if (!isDsaKey) { |
278 | | return WOLFSSL_FATAL_ERROR; |
279 | | } |
280 | | |
281 | | /* Create DSA key object from data. */ |
282 | | dsaObj = wolfSSL_DSA_new(); |
283 | | if (dsaObj == NULL) { |
284 | | ret = 0; |
285 | | } |
286 | | if ((ret == 1) && (wolfSSL_DSA_LoadDer_ex(dsaObj, mem, keyIdx, |
287 | | priv ? WOLFSSL_RSA_LOAD_PRIVATE : WOLFSSL_RSA_LOAD_PUBLIC) != 1)) { |
288 | | ret = 0; |
289 | | } |
290 | | if (ret == 1) { |
291 | | /* Create an EVP PKEY object. */ |
292 | | ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_DSA); |
293 | | } |
294 | | if (ret == 1) { |
295 | | /* Put RSA key object into EVP PKEY object. */ |
296 | | (*out)->ownDsa = 1; |
297 | | (*out)->dsa = dsaObj; |
298 | | } |
299 | | if (ret == 0) { |
300 | | wolfSSL_DSA_free(dsaObj); |
301 | | } |
302 | | |
303 | | return ret; |
304 | | } |
305 | | #endif /* NO_DSA */ |
306 | | |
307 | | #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) |
308 | | #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ |
309 | | (HAVE_FIPS_VERSION > 2)) |
310 | | /** |
311 | | * Try to make a DH EVP PKEY from data. |
312 | | * |
313 | | * @param [in, out] out On in, an EVP PKEY or NULL. |
314 | | * On out, an EVP PKEY or NULL. |
315 | | * @param [in] mem Memory containing key data. |
316 | | * @param [in] memSz Size of key data in bytes. |
317 | | * @param [in] priv 1 means private key, 0 means public key. |
318 | | * @return 1 on success. |
319 | | * @return 0 otherwise. |
320 | | */ |
321 | | static int d2iTryDhKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, |
322 | | long memSz, int priv) |
323 | 1.28k | { |
324 | 1.28k | WOLFSSL_DH* dhObj; |
325 | 1.28k | int isDhKey; |
326 | 1.28k | word32 keyIdx = 0; |
327 | 1.28k | int ret = 1; |
328 | 1.28k | WC_DECLARE_VAR(dh, DhKey, 1, NULL); |
329 | | |
330 | 1.28k | WC_ALLOC_VAR_EX(dh, DhKey, 1, NULL, DYNAMIC_TYPE_DH, return 0); |
331 | | |
332 | 1.28k | XMEMSET(dh, 0, sizeof(DhKey)); |
333 | | |
334 | 1.28k | if (wc_InitDhKey(dh) != 0) { |
335 | 0 | WC_FREE_VAR_EX(dh, NULL, DYNAMIC_TYPE_DH); |
336 | 0 | return 0; |
337 | 0 | } |
338 | | |
339 | | /* Try decoding data as a DH public key. */ |
340 | 1.28k | isDhKey = (wc_DhKeyDecode(mem, &keyIdx, dh, (word32)memSz) == 0); |
341 | 1.28k | wc_FreeDhKey(dh); |
342 | 1.28k | WC_FREE_VAR_EX(dh, NULL, DYNAMIC_TYPE_DH); |
343 | | |
344 | | /* test if DH key */ |
345 | 1.28k | if (!isDhKey) { |
346 | 955 | return WOLFSSL_FATAL_ERROR; |
347 | 955 | } |
348 | | |
349 | | /* Create DH key object from data. */ |
350 | 333 | dhObj = wolfSSL_DH_new(); |
351 | 333 | if (dhObj == NULL) { |
352 | 0 | ret = 0; |
353 | 0 | } |
354 | 333 | if ((ret == 1) && (wolfSSL_DH_LoadDer(dhObj, mem, keyIdx) != 1)) { |
355 | 287 | ret = 0; |
356 | 287 | } |
357 | 333 | if (ret == 1) { |
358 | | /* Create an EVP PKEY object. */ |
359 | 46 | ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_DH); |
360 | 46 | } |
361 | 333 | if (ret == 1) { |
362 | | /* Put RSA key object into EVP PKEY object. */ |
363 | 46 | (*out)->ownDh = 1; |
364 | 46 | (*out)->dh = dhObj; |
365 | 46 | } |
366 | 333 | if (ret == 0) { |
367 | 287 | wolfSSL_DH_free(dhObj); |
368 | 287 | } |
369 | | |
370 | 333 | return ret; |
371 | 1.28k | } |
372 | | #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ |
373 | | #endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */ |
374 | | |
375 | | #if !defined(NO_DH) && defined(OPENSSL_EXTRA) && defined(WOLFSSL_DH_EXTRA) |
376 | | #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ |
377 | | (HAVE_FIPS_VERSION > 2)) |
378 | | /** |
379 | | * Try to make a DH EVP PKEY from data. |
380 | | * |
381 | | * @param [in, out] out On in, an EVP PKEY or NULL. |
382 | | * On out, an EVP PKEY or NULL. |
383 | | * @param [in] mem Memory containing key data. |
384 | | * @param [in] memSz Size of key data in bytes. |
385 | | * @param [in] priv 1 means private key, 0 means public key. |
386 | | * @return 1 on success. |
387 | | * @return 0 otherwise. |
388 | | */ |
389 | | static int d2iTryAltDhKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, |
390 | | long memSz, int priv) |
391 | 955 | { |
392 | 955 | WOLFSSL_DH* dhObj; |
393 | 955 | word32 keyIdx = 0; |
394 | 955 | DhKey* key = NULL; |
395 | 955 | int elements; |
396 | 955 | int ret = 1; |
397 | | |
398 | | /* Create DH key object from data. */ |
399 | 955 | dhObj = wolfSSL_DH_new(); |
400 | 955 | if (dhObj == NULL) { |
401 | 0 | return 0; |
402 | 0 | } |
403 | | |
404 | 955 | key = (DhKey*)dhObj->internal; |
405 | | /* Try decoding data as a DH public key. */ |
406 | 955 | if (wc_DhKeyDecode(mem, &keyIdx, key, (word32)memSz) != 0) { |
407 | 955 | ret = 0; |
408 | 955 | } |
409 | 955 | if (ret == 1) { |
410 | | /* DH key has data and is external to DH object. */ |
411 | 0 | elements = ELEMENT_P | ELEMENT_G | ELEMENT_Q | ELEMENT_PUB; |
412 | 0 | if (priv) { |
413 | 0 | elements |= ELEMENT_PRV; |
414 | 0 | } |
415 | 0 | if (SetDhExternal_ex(dhObj, elements) != WOLFSSL_SUCCESS ) { |
416 | 0 | ret = 0; |
417 | 0 | } |
418 | 0 | } |
419 | 955 | if (ret == 1) { |
420 | | /* Create an EVP PKEY object. */ |
421 | 0 | ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_DH); |
422 | 0 | } |
423 | 955 | if (ret == 1) { |
424 | | /* Put RSA key object into EVP PKEY object. */ |
425 | 0 | (*out)->ownDh = 1; |
426 | 0 | (*out)->dh = dhObj; |
427 | 0 | } |
428 | 955 | if (ret == 0) { |
429 | 955 | wolfSSL_DH_free(dhObj); |
430 | 955 | } |
431 | | |
432 | 955 | return ret; |
433 | 955 | } |
434 | | #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ |
435 | | #endif /* !NO_DH && OPENSSL_EXTRA && WOLFSSL_DH_EXTRA */ |
436 | | |
437 | | #ifdef HAVE_FALCON |
438 | | /** |
439 | | * Attempt to import a private Falcon key at a specified level. |
440 | | * |
441 | | * @param [in] falcon Falcon key object. |
442 | | * @param [in] level Level of Falcon key. |
443 | | * @param [in] mem Memory containing key data. |
444 | | * @param [in] memSz Size of key data in bytes. |
445 | | * @return 1 on success. |
446 | | * @return 0 otherwise. |
447 | | */ |
448 | | static int d2i_falcon_priv_key_level(falcon_key* falcon, byte level, |
449 | | const unsigned char* mem, long memSz) |
450 | | { |
451 | | return (wc_falcon_set_level(falcon, level) == 0) && |
452 | | (wc_falcon_import_private_only(mem, (word32)memSz, falcon) == 0); |
453 | | } |
454 | | |
455 | | /** |
456 | | * Attempt to import a public Falcon key at a specified level. |
457 | | * |
458 | | * @param [in] falcon Falcon key object. |
459 | | * @param [in] level Level of Falcon key. |
460 | | * @param [in] mem Memory containing key data. |
461 | | * @param [in] memSz Size of key data in bytes. |
462 | | * @return 1 on success. |
463 | | * @return 0 otherwise. |
464 | | */ |
465 | | static int d2i_falcon_pub_key_level(falcon_key* falcon, byte level, |
466 | | const unsigned char* mem, long memSz) |
467 | | { |
468 | | return (wc_falcon_set_level(falcon, level) == 0) && |
469 | | (wc_falcon_import_public(mem, (word32)memSz, falcon) == 0); |
470 | | } |
471 | | |
472 | | /** |
473 | | * Try to make a Falcon EVP PKEY from data. |
474 | | * |
475 | | * @param [in, out] out On in, an EVP PKEY or NULL. |
476 | | * On out, an EVP PKEY or NULL. |
477 | | * @param [in] mem Memory containing key data. |
478 | | * @param [in] memSz Size of key data in bytes. |
479 | | * @param [in] priv 1 means private key, 0 means public key. |
480 | | * @return 1 on success. |
481 | | * @return 0 otherwise. |
482 | | */ |
483 | | static int d2iTryFalconKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, |
484 | | long memSz, int priv) |
485 | | { |
486 | | int isFalcon = 0; |
487 | | WC_DECLARE_VAR(falcon, falcon_key, 1, NULL); |
488 | | |
489 | | WC_ALLOC_VAR_EX(falcon, falcon_key, 1, NULL, DYNAMIC_TYPE_FALCON, |
490 | | return 0); |
491 | | |
492 | | if (wc_falcon_init(falcon) != 0) { |
493 | | WC_FREE_VAR_EX(falcon, NULL, DYNAMIC_TYPE_FALCON); |
494 | | return 0; |
495 | | } |
496 | | |
497 | | /* Try decoding data as a Falcon private/public key. */ |
498 | | if (priv) { |
499 | | /* Try level 1 */ |
500 | | isFalcon = d2i_falcon_priv_key_level(falcon, 1, mem, memSz); |
501 | | if (!isFalcon) { |
502 | | /* Try level 5 */ |
503 | | isFalcon = d2i_falcon_priv_key_level(falcon, 5, mem, memSz); |
504 | | } |
505 | | } |
506 | | else { |
507 | | /* Try level 1 */ |
508 | | isFalcon = d2i_falcon_pub_key_level(falcon, 1, mem, memSz); |
509 | | if (!isFalcon) { |
510 | | /* Try level 5 */ |
511 | | isFalcon = d2i_falcon_pub_key_level(falcon, 5, mem, memSz); |
512 | | } |
513 | | } |
514 | | /* Dispose of any Falcon key created. */ |
515 | | wc_falcon_free(falcon); |
516 | | WC_FREE_VAR_EX(falcon, NULL, DYNAMIC_TYPE_FALCON); |
517 | | |
518 | | if (!isFalcon) { |
519 | | return WOLFSSL_FATAL_ERROR; |
520 | | } |
521 | | |
522 | | /* Create an EVP PKEY object. */ |
523 | | return d2i_make_pkey(out, NULL, 0, priv, WC_EVP_PKEY_FALCON); |
524 | | } |
525 | | #endif /* HAVE_FALCON */ |
526 | | |
527 | | #ifdef HAVE_DILITHIUM |
528 | | /** |
529 | | * Attempt to import a private Dilithium key at a specified level. |
530 | | * |
531 | | * @param [in] dilithium Dilithium key object. |
532 | | * @param [in] level Level of Dilithium key. |
533 | | * @param [in] mem Memory containing key data. |
534 | | * @param [in] memSz Size of key data in bytes. |
535 | | * @return 1 on success. |
536 | | * @return 0 otherwise. |
537 | | */ |
538 | | static int d2i_dilithium_priv_key_level(dilithium_key* dilithium, byte level, |
539 | | const unsigned char* mem, long memSz) |
540 | | { |
541 | | return (wc_dilithium_set_level(dilithium, level) == 0) && |
542 | | (wc_dilithium_import_private(mem, (word32)memSz, dilithium) == 0); |
543 | | } |
544 | | |
545 | | /** |
546 | | * Attempt to import a public Dilithium key at a specified level. |
547 | | * |
548 | | * @param [in] dilithium Dilithium key object. |
549 | | * @param [in] level Level of Dilithium key. |
550 | | * @param [in] mem Memory containing key data. |
551 | | * @param [in] memSz Size of key data in bytes. |
552 | | * @return 1 on success. |
553 | | * @return 0 otherwise. |
554 | | */ |
555 | | static int d2i_dilithium_pub_key_level(dilithium_key* dilithium, byte level, |
556 | | const unsigned char* mem, long memSz) |
557 | | { |
558 | | return (wc_dilithium_set_level(dilithium, level) == 0) && |
559 | | (wc_dilithium_import_public(mem, (word32)memSz, dilithium) == 0); |
560 | | } |
561 | | |
562 | | /** |
563 | | * Try to make a Dilithium EVP PKEY from data. |
564 | | * |
565 | | * @param [in, out] out On in, an EVP PKEY or NULL. |
566 | | * On out, an EVP PKEY or NULL. |
567 | | * @param [in] mem Memory containing key data. |
568 | | * @param [in] memSz Size of key data in bytes. |
569 | | * @param [in] priv 1 means private key, 0 means public key. |
570 | | * @return 1 on success. |
571 | | * @return 0 otherwise. |
572 | | */ |
573 | | static int d2iTryDilithiumKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, |
574 | | long memSz, int priv) |
575 | | { |
576 | | int isDilithium = 0; |
577 | | WC_DECLARE_VAR(dilithium, dilithium_key, 1, NULL); |
578 | | |
579 | | WC_ALLOC_VAR_EX(dilithium, dilithium_key, 1, NULL, DYNAMIC_TYPE_DILITHIUM, |
580 | | return 0); |
581 | | |
582 | | if (wc_dilithium_init(dilithium) != 0) { |
583 | | WC_FREE_VAR_EX(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM); |
584 | | return 0; |
585 | | } |
586 | | |
587 | | /* Try decoding data as a Dilithium private/public key. */ |
588 | | if (priv) { |
589 | | isDilithium = d2i_dilithium_priv_key_level(dilithium, WC_ML_DSA_44, |
590 | | mem, memSz); |
591 | | if (!isDilithium) { |
592 | | isDilithium = d2i_dilithium_priv_key_level(dilithium, WC_ML_DSA_65, |
593 | | mem, memSz); |
594 | | } |
595 | | if (!isDilithium) { |
596 | | isDilithium = d2i_dilithium_priv_key_level(dilithium, WC_ML_DSA_87, |
597 | | mem, memSz); |
598 | | } |
599 | | } |
600 | | else { |
601 | | isDilithium = d2i_dilithium_pub_key_level(dilithium, WC_ML_DSA_44, |
602 | | mem, memSz); |
603 | | if (!isDilithium) { |
604 | | isDilithium = d2i_dilithium_pub_key_level(dilithium, WC_ML_DSA_65, |
605 | | mem, memSz); |
606 | | } |
607 | | if (!isDilithium) { |
608 | | isDilithium = d2i_dilithium_pub_key_level(dilithium, WC_ML_DSA_87, |
609 | | mem, memSz); |
610 | | } |
611 | | } |
612 | | /* Dispose of any Dilithium key created. */ |
613 | | wc_dilithium_free(dilithium); |
614 | | WC_FREE_VAR_EX(dilithium, NULL, DYNAMIC_TYPE_DILITHIUM); |
615 | | |
616 | | if (!isDilithium) { |
617 | | return WOLFSSL_FATAL_ERROR; |
618 | | } |
619 | | |
620 | | /* Create an EVP PKEY object. */ |
621 | | return d2i_make_pkey(out, NULL, 0, priv, WC_EVP_PKEY_DILITHIUM); |
622 | | } |
623 | | #endif /* HAVE_DILITHIUM */ |
624 | | |
625 | | /** |
626 | | * Try to make a WOLFSSL_EVP_PKEY from data. |
627 | | * |
628 | | * @param [in, out] out On in, an EVP PKEY or NULL. |
629 | | * On out, an EVP PKEY or NULL. |
630 | | * @param [in] mem Memory containing key data. |
631 | | * @param [in] memSz Size of key data in bytes. |
632 | | * @param [in] priv 1 means private key, 0 means public key. |
633 | | * @return 1 on success. |
634 | | * @return 0 otherwise. |
635 | | */ |
636 | | static WOLFSSL_EVP_PKEY* d2i_evp_pkey_try(WOLFSSL_EVP_PKEY** out, |
637 | | const unsigned char** in, long inSz, int priv) |
638 | 0 | { |
639 | 0 | WOLFSSL_EVP_PKEY* pkey = NULL; |
640 | |
|
641 | 0 | WOLFSSL_ENTER("d2i_evp_pkey_try"); |
642 | |
|
643 | 0 | if (in == NULL || *in == NULL || inSz < 0) { |
644 | 0 | WOLFSSL_MSG("Bad argument"); |
645 | 0 | return NULL; |
646 | 0 | } |
647 | | |
648 | 0 | if ((out != NULL) && (*out != NULL)) { |
649 | 0 | pkey = *out; |
650 | 0 | } |
651 | |
|
652 | 0 | #if !defined(NO_RSA) |
653 | 0 | if (d2iTryRsaKey(&pkey, *in, inSz, priv) >= 0) { |
654 | 0 | ; |
655 | 0 | } |
656 | 0 | else |
657 | 0 | #endif /* NO_RSA */ |
658 | 0 | #if defined(HAVE_ECC) && defined(OPENSSL_EXTRA) |
659 | 0 | if (d2iTryEccKey(&pkey, *in, inSz, priv) >= 0) { |
660 | 0 | ; |
661 | 0 | } |
662 | 0 | else |
663 | 0 | #endif /* HAVE_ECC && OPENSSL_EXTRA */ |
664 | | #if !defined(NO_DSA) |
665 | | if (d2iTryDsaKey(&pkey, *in, inSz, priv) >= 0) { |
666 | | ; |
667 | | } |
668 | | else |
669 | | #endif /* NO_DSA */ |
670 | 0 | #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) |
671 | 0 | #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ |
672 | 0 | (HAVE_FIPS_VERSION > 2)) |
673 | 0 | if (d2iTryDhKey(&pkey, *in, inSz, priv) >= 0) { |
674 | 0 | ; |
675 | 0 | } |
676 | 0 | else |
677 | 0 | #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ |
678 | 0 | #endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */ |
679 | | |
680 | 0 | #if !defined(NO_DH) && defined(OPENSSL_EXTRA) && defined(WOLFSSL_DH_EXTRA) |
681 | 0 | #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ |
682 | 0 | (HAVE_FIPS_VERSION > 2)) |
683 | 0 | if (d2iTryAltDhKey(&pkey, *in, inSz, priv) >= 0) { |
684 | 0 | ; |
685 | 0 | } |
686 | 0 | else |
687 | 0 | #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ |
688 | 0 | #endif /* !NO_DH && OPENSSL_EXTRA && WOLFSSL_DH_EXTRA */ |
689 | | |
690 | | #ifdef HAVE_FALCON |
691 | | if (d2iTryFalconKey(&pkey, *in, inSz, priv) >= 0) { |
692 | | ; |
693 | | } |
694 | | else |
695 | | #endif /* HAVE_FALCON */ |
696 | | #ifdef HAVE_DILITHIUM |
697 | | if (d2iTryDilithiumKey(&pkey, *in, inSz, priv) >= 0) { |
698 | | ; |
699 | | } |
700 | | else |
701 | | #endif /* HAVE_DILITHIUM */ |
702 | 0 | { |
703 | 0 | WOLFSSL_MSG("d2i_evp_pkey_try couldn't determine key type"); |
704 | 0 | } |
705 | |
|
706 | 0 | if ((pkey != NULL) && (out != NULL)) { |
707 | 0 | *out = pkey; |
708 | 0 | } |
709 | 0 | return pkey; |
710 | 0 | } |
711 | | #endif /* OPENSSL_EXTRA || WPA_SMALL */ |
712 | | |
713 | | #ifdef OPENSSL_EXTRA |
714 | | /* Converts a DER encoded public key to a WOLFSSL_EVP_PKEY structure. |
715 | | * |
716 | | * @param [in, out] out Pointer to new WOLFSSL_EVP_PKEY structure. |
717 | | * Can be NULL. |
718 | | * @param [in, out] in DER buffer to convert. |
719 | | * @param [in] inSz Size of in buffer. |
720 | | * @return Pointer to a new WOLFSSL_EVP_PKEY structure on success. |
721 | | * @return NULL on failure. |
722 | | */ |
723 | | WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY(WOLFSSL_EVP_PKEY** out, |
724 | | const unsigned char** in, long inSz) |
725 | 3.00k | { |
726 | 3.00k | WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY"); |
727 | 3.00k | return d2i_evp_pkey_try(out, in, inSz, 0); |
728 | 3.00k | } |
729 | | |
730 | | #ifndef NO_BIO |
731 | | /* Converts a DER encoded public key in a BIO to a WOLFSSL_EVP_PKEY structure. |
732 | | * |
733 | | * @param [in] bio BIO to read DER from. |
734 | | * @param [out] out New WOLFSSL_EVP_PKEY pointer when not NULL. |
735 | | * @return Pointer to a new WOLFSSL_EVP_PKEY structure on success. |
736 | | * @return NULL on failure. |
737 | | */ |
738 | | WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio, |
739 | | WOLFSSL_EVP_PKEY** out) |
740 | 0 | { |
741 | 0 | unsigned char* mem; |
742 | 0 | long memSz; |
743 | 0 | WOLFSSL_EVP_PKEY* pkey = NULL; |
744 | |
|
745 | 0 | WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY_bio"); |
746 | | |
747 | | /* Validate parameters. */ |
748 | 0 | if (bio == NULL) { |
749 | 0 | return NULL; |
750 | 0 | } |
751 | | |
752 | | /* Get length of data in BIO. */ |
753 | 0 | memSz = wolfSSL_BIO_get_len(bio); |
754 | 0 | if (memSz <= 0) { |
755 | 0 | return NULL; |
756 | 0 | } |
757 | | /* Allocate memory to read all of BIO data into. */ |
758 | 0 | mem = (unsigned char*)XMALLOC((size_t)memSz, bio->heap, |
759 | 0 | DYNAMIC_TYPE_TMP_BUFFER); |
760 | 0 | if (mem == NULL) { |
761 | 0 | return NULL; |
762 | 0 | } |
763 | | /* Read all data into allocated buffer. */ |
764 | 0 | if (wolfSSL_BIO_read(bio, mem, (int)memSz) == memSz) { |
765 | | /* Create a WOLFSSL_EVP_PKEY from data. */ |
766 | 0 | pkey = wolfSSL_d2i_PUBKEY(NULL, (const unsigned char**)&mem, memSz); |
767 | 0 | if (out != NULL && pkey != NULL) { |
768 | | /* Return new WOLFSSL_EVP_PKEY through parameter. */ |
769 | 0 | *out = pkey; |
770 | 0 | } |
771 | 0 | } |
772 | | |
773 | | /* Dispose of memory holding BIO data. */ |
774 | 0 | XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); |
775 | 0 | return pkey; |
776 | 0 | } |
777 | | #endif /* !NO_BIO */ |
778 | | #endif /* OPENSSL_EXTRA */ |
779 | | |
780 | | #if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || \ |
781 | | defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX) || \ |
782 | | defined(WOLFSSL_QT) || defined(WOLFSSL_WPAS_SMALL) |
783 | | /* Converts a DER encoded private key to a WOLFSSL_EVP_PKEY structure. |
784 | | * |
785 | | * @param [in, out] out Pointer to new WOLFSSL_EVP_PKEY structure. |
786 | | * Can be NULL. |
787 | | * @param [in, out] in DER buffer to convert. |
788 | | * @param [in] inSz Size of in buffer. |
789 | | * @return Pointer to a new WOLFSSL_EVP_PKEY structure on success. |
790 | | * @return NULL on failure. |
791 | | */ |
792 | | WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_EVP(WOLFSSL_EVP_PKEY** out, |
793 | | unsigned char** in, long inSz) |
794 | 0 | { |
795 | 0 | WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_EVP"); |
796 | 0 | return d2i_evp_pkey_try(out, (const unsigned char**)in, inSz, 1); |
797 | 0 | } |
798 | | #endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_QT || |
799 | | * WOLFSSL_WPAS_SMALL*/ |
800 | | |
801 | | #if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || \ |
802 | | defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT) |
803 | | |
804 | | #ifndef NO_BIO |
805 | | /* Converts a DER encoded private key in a BIO to a WOLFSSL_EVP_PKEY structure. |
806 | | * |
807 | | * @param [in] bio BIO to read DER from. |
808 | | * @param [out] out New WOLFSSL_EVP_PKEY pointer when not NULL. |
809 | | * @return Pointer to a new WOLFSSL_EVP_PKEY structure on success. |
810 | | * @return NULL on failure. |
811 | | */ |
812 | | WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_bio(WOLFSSL_BIO* bio, |
813 | | WOLFSSL_EVP_PKEY** out) |
814 | 0 | { |
815 | 0 | unsigned char* mem = NULL; |
816 | 0 | int memSz = 0; |
817 | 0 | WOLFSSL_EVP_PKEY* key = NULL; |
818 | |
|
819 | 0 | WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_bio"); |
820 | | |
821 | | /* Validate parameters. */ |
822 | 0 | if (bio == NULL) { |
823 | 0 | return NULL; |
824 | 0 | } |
825 | | |
826 | | /* Get length of data in BIO. */ |
827 | 0 | memSz = wolfSSL_BIO_get_len(bio); |
828 | 0 | if (memSz <= 0) { |
829 | 0 | WOLFSSL_MSG("wolfSSL_BIO_get_len() failure"); |
830 | 0 | return NULL; |
831 | 0 | } |
832 | | /* Allocate memory to read all of BIO data into. */ |
833 | 0 | mem = (unsigned char*)XMALLOC((size_t)memSz, bio->heap, |
834 | 0 | DYNAMIC_TYPE_TMP_BUFFER); |
835 | 0 | if (mem == NULL) { |
836 | 0 | WOLFSSL_MSG("Malloc failure"); |
837 | 0 | return NULL; |
838 | 0 | } |
839 | | |
840 | | /* Read all of data. */ |
841 | 0 | if (wolfSSL_BIO_read(bio, (unsigned char*)mem, memSz) == memSz) { |
842 | | /* Determines key type and returns the new private EVP_PKEY object */ |
843 | 0 | if ((key = wolfSSL_d2i_PrivateKey_EVP(NULL, &mem, (long)memSz)) == |
844 | 0 | NULL) { |
845 | 0 | WOLFSSL_MSG("wolfSSL_d2i_PrivateKey_EVP() failure"); |
846 | 0 | XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); |
847 | 0 | return NULL; |
848 | 0 | } |
849 | | |
850 | | /* Write extra data back into bio object if necessary. */ |
851 | 0 | if (memSz > key->pkey_sz) { |
852 | 0 | wolfSSL_BIO_write(bio, mem + key->pkey_sz, memSz - key->pkey_sz); |
853 | 0 | if (wolfSSL_BIO_get_len(bio) <= 0) { |
854 | 0 | WOLFSSL_MSG("Failed to write memory to bio"); |
855 | 0 | XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); |
856 | 0 | return NULL; |
857 | 0 | } |
858 | 0 | } |
859 | | |
860 | | /* Return key through parameter if required. */ |
861 | 0 | if (out != NULL) { |
862 | 0 | *out = key; |
863 | 0 | } |
864 | 0 | } |
865 | | |
866 | | /* Dispose of memory holding BIO data. */ |
867 | 0 | XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); |
868 | 0 | return key; |
869 | 0 | } |
870 | | #endif /* !NO_BIO */ |
871 | | |
872 | | #endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_NGINX || |
873 | | * WOLFSSL_QT */ |
874 | | |
875 | | #ifdef OPENSSL_EXTRA |
876 | | /* Reads in a DER format key. If PKCS8 headers are found they are stripped off. |
877 | | * |
878 | | * @param [in] type Type of key. |
879 | | * @param [in, out] out Newly created WOLFSSL_EVP_PKEY structure. |
880 | | * @param [in, out] in Pointer to input key DER. |
881 | | * Pointer is advanced the same number of bytes read on |
882 | | * success. |
883 | | * @param [in] inSz Size of in buffer. |
884 | | * @return A non null pointer on success. |
885 | | * @return NULL on failure. |
886 | | */ |
887 | | static WOLFSSL_EVP_PKEY* d2i_evp_pkey(int type, WOLFSSL_EVP_PKEY** out, |
888 | | const unsigned char **in, long inSz, int priv) |
889 | 0 | { |
890 | 0 | int ret = 0; |
891 | 0 | word32 idx = 0, algId; |
892 | 0 | word16 pkcs8HeaderSz = 0; |
893 | 0 | WOLFSSL_EVP_PKEY* local; |
894 | 0 | const unsigned char* p; |
895 | 0 | int opt; |
896 | |
|
897 | 0 | (void)opt; |
898 | | |
899 | | /* Validate parameters. */ |
900 | 0 | if (in == NULL || inSz < 0) { |
901 | 0 | WOLFSSL_MSG("Bad argument"); |
902 | 0 | return NULL; |
903 | 0 | } |
904 | | |
905 | 0 | if (priv == 1) { |
906 | | /* Check if input buffer has PKCS8 header. In the case that it does not |
907 | | * have a PKCS8 header then do not error out. */ |
908 | 0 | if ((ret = ToTraditionalInline_ex((const byte*)(*in), &idx, |
909 | 0 | (word32)inSz, &algId)) >= 0) { |
910 | 0 | WOLFSSL_MSG("Found PKCS8 header"); |
911 | 0 | pkcs8HeaderSz = (word16)idx; |
912 | | |
913 | | /* Check header algorithm id matches algorithm type passed in. */ |
914 | 0 | if ((type == WC_EVP_PKEY_RSA && algId != RSAk |
915 | 0 | #ifdef WC_RSA_PSS |
916 | 0 | && algId != RSAPSSk |
917 | 0 | #endif |
918 | 0 | ) || |
919 | 0 | (type == WC_EVP_PKEY_EC && algId != ECDSAk) || |
920 | 0 | (type == WC_EVP_PKEY_DSA && algId != DSAk) || |
921 | 0 | (type == WC_EVP_PKEY_DH && algId != DHk)) { |
922 | 0 | WOLFSSL_MSG("PKCS8 does not match EVP key type"); |
923 | 0 | return NULL; |
924 | 0 | } |
925 | | |
926 | 0 | (void)idx; /* not used */ |
927 | 0 | } |
928 | | /* Ensure no error occurred try to remove any PKCS#8 header. */ |
929 | 0 | else if (ret != WC_NO_ERR_TRACE(ASN_PARSE_E)) { |
930 | 0 | WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 header"); |
931 | 0 | return NULL; |
932 | 0 | } |
933 | 0 | } |
934 | | |
935 | | /* Dispose of any WOLFSSL_EVP_PKEY passed in. */ |
936 | 0 | if (out != NULL && *out != NULL) { |
937 | 0 | wolfSSL_EVP_PKEY_free(*out); |
938 | 0 | *out = NULL; |
939 | 0 | } |
940 | | /* Create a new WOLFSSL_EVP_PKEY and populate. */ |
941 | 0 | local = wolfSSL_EVP_PKEY_new(); |
942 | 0 | if (local == NULL) { |
943 | 0 | return NULL; |
944 | 0 | } |
945 | 0 | local->type = type; |
946 | 0 | local->pkey_sz = (int)inSz; |
947 | 0 | local->pkcs8HeaderSz = pkcs8HeaderSz; |
948 | 0 | local->pkey.ptr = (char*)XMALLOC((size_t)inSz, NULL, |
949 | 0 | DYNAMIC_TYPE_PUBLIC_KEY); |
950 | 0 | if (local->pkey.ptr == NULL) { |
951 | 0 | wolfSSL_EVP_PKEY_free(local); |
952 | 0 | return NULL; |
953 | 0 | } |
954 | 0 | XMEMCPY(local->pkey.ptr, *in, (size_t)inSz); |
955 | 0 | p = (const unsigned char*)local->pkey.ptr; |
956 | | |
957 | | /* Create an algorithm specific object into WOLFSSL_EVP_PKEY. */ |
958 | 0 | switch (type) { |
959 | 0 | #ifndef NO_RSA |
960 | 0 | case WC_EVP_PKEY_RSA: |
961 | | /* Create a WOLFSSL_RSA object. */ |
962 | 0 | local->ownRsa = 1; |
963 | 0 | opt = priv ? WOLFSSL_RSA_LOAD_PRIVATE : WOLFSSL_RSA_LOAD_PUBLIC; |
964 | 0 | local->rsa = wolfssl_rsa_d2i(NULL, p, local->pkey_sz, opt); |
965 | 0 | if (local->rsa == NULL) { |
966 | 0 | wolfSSL_EVP_PKEY_free(local); |
967 | 0 | return NULL; |
968 | 0 | } |
969 | 0 | break; |
970 | 0 | #endif /* NO_RSA */ |
971 | 0 | #ifdef HAVE_ECC |
972 | 0 | case WC_EVP_PKEY_EC: |
973 | | /* Create a WOLFSSL_EC object. */ |
974 | 0 | local->ownEcc = 1; |
975 | 0 | local->ecc = wolfSSL_EC_KEY_new(); |
976 | 0 | if (local->ecc == NULL) { |
977 | 0 | wolfSSL_EVP_PKEY_free(local); |
978 | 0 | return NULL; |
979 | 0 | } |
980 | 0 | opt = priv ? WOLFSSL_EC_KEY_LOAD_PRIVATE : |
981 | 0 | WOLFSSL_EC_KEY_LOAD_PUBLIC; |
982 | 0 | if (wolfSSL_EC_KEY_LoadDer_ex(local->ecc, p, local->pkey_sz, opt) != |
983 | 0 | WOLFSSL_SUCCESS) { |
984 | 0 | wolfSSL_EVP_PKEY_free(local); |
985 | 0 | return NULL; |
986 | 0 | } |
987 | 0 | break; |
988 | 0 | #endif /* HAVE_ECC */ |
989 | 0 | #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH) |
990 | | #ifndef NO_DSA |
991 | | case WC_EVP_PKEY_DSA: |
992 | | /* Create a WOLFSSL_DSA object. */ |
993 | | local->ownDsa = 1; |
994 | | local->dsa = wolfSSL_DSA_new(); |
995 | | if (local->dsa == NULL) { |
996 | | wolfSSL_EVP_PKEY_free(local); |
997 | | return NULL; |
998 | | } |
999 | | opt = priv ? WOLFSSL_DSA_LOAD_PRIVATE : WOLFSSL_DSA_LOAD_PUBLIC; |
1000 | | if (wolfSSL_DSA_LoadDer_ex(local->dsa, p, local->pkey_sz, opt) != |
1001 | | WOLFSSL_SUCCESS) { |
1002 | | wolfSSL_EVP_PKEY_free(local); |
1003 | | return NULL; |
1004 | | } |
1005 | | break; |
1006 | | #endif /* NO_DSA */ |
1007 | 0 | #ifndef NO_DH |
1008 | 0 | #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2)) |
1009 | 0 | case WC_EVP_PKEY_DH: |
1010 | | /* Create a WOLFSSL_DH object. */ |
1011 | 0 | local->ownDh = 1; |
1012 | 0 | local->dh = wolfSSL_DH_new(); |
1013 | 0 | if (local->dh == NULL) { |
1014 | 0 | wolfSSL_EVP_PKEY_free(local); |
1015 | 0 | return NULL; |
1016 | 0 | } |
1017 | 0 | if (wolfSSL_DH_LoadDer(local->dh, p, local->pkey_sz) != |
1018 | 0 | WOLFSSL_SUCCESS) { |
1019 | 0 | wolfSSL_EVP_PKEY_free(local); |
1020 | 0 | return NULL; |
1021 | 0 | } |
1022 | 0 | break; |
1023 | 0 | #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ |
1024 | 0 | #endif /* HAVE_DH */ |
1025 | 0 | #endif /* WOLFSSL_QT || OPENSSL_ALL || WOLFSSL_OPENSSH */ |
1026 | 0 | default: |
1027 | 0 | WOLFSSL_MSG("Unsupported key type"); |
1028 | 0 | wolfSSL_EVP_PKEY_free(local); |
1029 | 0 | return NULL; |
1030 | 0 | } |
1031 | | |
1032 | | /* Advance pointer and return through parameter when required on success. */ |
1033 | 0 | if (local != NULL) { |
1034 | 0 | if (local->pkey_sz <= (int)inSz) { |
1035 | 0 | *in += local->pkey_sz; |
1036 | 0 | } |
1037 | 0 | if (out != NULL) { |
1038 | 0 | *out = local; |
1039 | 0 | } |
1040 | 0 | } |
1041 | | |
1042 | | /* Return newly allocated WOLFSSL_EVP_PKEY structure. */ |
1043 | 0 | return local; |
1044 | 0 | } |
1045 | | |
1046 | | /* Reads in a DER format key. |
1047 | | * |
1048 | | * @param [in] type Type of key. |
1049 | | * @param [in, out] out Newly created WOLFSSL_EVP_PKEY structure. |
1050 | | * @param [in, out] in Pointer to input key DER. |
1051 | | * Pointer is advanced the same number of bytes read on |
1052 | | * success. |
1053 | | * @param [in] inSz Size of in buffer. |
1054 | | * @return A non null pointer on success. |
1055 | | * @return NULL on failure. |
1056 | | */ |
1057 | | WOLFSSL_EVP_PKEY* wolfSSL_d2i_PublicKey(int type, WOLFSSL_EVP_PKEY** out, |
1058 | | const unsigned char **in, long inSz) |
1059 | 0 | { |
1060 | 0 | WOLFSSL_ENTER("wolfSSL_d2i_PublicKey"); |
1061 | |
|
1062 | 0 | return d2i_evp_pkey(type, out, in, inSz, 0); |
1063 | 0 | } |
1064 | | |
1065 | | /* Reads in a DER format key. If PKCS8 headers are found they are stripped off. |
1066 | | * |
1067 | | * @param [in] type Type of key. |
1068 | | * @param [in, out] out Newly created WOLFSSL_EVP_PKEY structure. |
1069 | | * @param [in, out] in Pointer to input key DER. |
1070 | | * Pointer is advanced the same number of bytes read on |
1071 | | * success. |
1072 | | * @param [in] inSz Size of in buffer. |
1073 | | * @return A non null pointer on success. |
1074 | | * @return NULL on failure. |
1075 | | */ |
1076 | | WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out, |
1077 | | const unsigned char **in, long inSz) |
1078 | 0 | { |
1079 | 0 | WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey"); |
1080 | |
|
1081 | 0 | return d2i_evp_pkey(type, out, in, inSz, 1); |
1082 | 0 | } |
1083 | | #endif /* OPENSSL_EXTRA */ |
1084 | | |
1085 | | #ifdef OPENSSL_ALL |
1086 | | /* Detect RSA or EC key and decode private key DER. |
1087 | | * |
1088 | | * @param [in, out] pkey Newly created WOLFSSL_EVP_PKEY structure. |
1089 | | * @param [in, out] pp Pointer to private key DER data. |
1090 | | * @param [in] length Length in bytes of DER data. |
1091 | | */ |
1092 | | WOLFSSL_EVP_PKEY* wolfSSL_d2i_AutoPrivateKey(WOLFSSL_EVP_PKEY** pkey, |
1093 | | const unsigned char** pp, long length) |
1094 | 0 | { |
1095 | 0 | int ret; |
1096 | 0 | WOLFSSL_EVP_PKEY* key = NULL; |
1097 | 0 | const byte* der = *pp; |
1098 | 0 | word32 idx = 0; |
1099 | 0 | int len = 0; |
1100 | 0 | int cnt = 0; |
1101 | 0 | word32 algId; |
1102 | 0 | word32 keyLen = (word32)length; |
1103 | | |
1104 | | /* Take off PKCS#8 wrapper if found. */ |
1105 | 0 | if ((len = ToTraditionalInline_ex(der, &idx, keyLen, &algId)) >= 0) { |
1106 | 0 | der += idx; |
1107 | 0 | keyLen = (word32)len; |
1108 | 0 | } |
1109 | |
|
1110 | 0 | idx = 0; |
1111 | 0 | len = 0; |
1112 | | /* Use the number of elements in the outer sequence to determine key type. |
1113 | | */ |
1114 | 0 | ret = GetSequence(der, &idx, &len, keyLen); |
1115 | 0 | if (ret >= 0) { |
1116 | 0 | word32 end = idx + (word32)len; |
1117 | 0 | while (ret >= 0 && idx < end) { |
1118 | | /* Skip type */ |
1119 | 0 | idx++; |
1120 | | /* Get length and skip over - keeping count */ |
1121 | 0 | len = 0; |
1122 | 0 | ret = GetLength(der, &idx, &len, keyLen); |
1123 | 0 | if (ret >= 0) { |
1124 | 0 | if (idx + (word32)len > end) { |
1125 | 0 | ret = ASN_PARSE_E; |
1126 | 0 | } |
1127 | 0 | else { |
1128 | 0 | idx += (word32)len; |
1129 | 0 | cnt++; |
1130 | 0 | } |
1131 | 0 | } |
1132 | 0 | } |
1133 | 0 | } |
1134 | |
|
1135 | 0 | if (ret >= 0) { |
1136 | 0 | int type; |
1137 | | /* ECC includes version, private[, curve][, public key] */ |
1138 | 0 | if (cnt >= 2 && cnt <= 4) { |
1139 | 0 | type = WC_EVP_PKEY_EC; |
1140 | 0 | } |
1141 | 0 | else { |
1142 | 0 | type = WC_EVP_PKEY_RSA; |
1143 | 0 | } |
1144 | | |
1145 | | /* Decode the detected type of private key. */ |
1146 | 0 | key = wolfSSL_d2i_PrivateKey(type, pkey, &der, keyLen); |
1147 | | /* Update the pointer to after the DER data. */ |
1148 | 0 | *pp = der; |
1149 | 0 | } |
1150 | |
|
1151 | 0 | return key; |
1152 | 0 | } |
1153 | | |
1154 | | #if !defined(NO_BIO) && !defined(NO_PWDBASED) && defined(HAVE_PKCS8) |
1155 | | /* Read all of the BIO data into a newly allocated buffer. |
1156 | | * |
1157 | | * @param [in] bio BIO to read from. |
1158 | | * @param [out] data Allocated buffer holding all BIO data. |
1159 | | * @return Number of bytes allocated and read. |
1160 | | * @return MEMORY_E on dynamic memory allocation failure. |
1161 | | * @return Other negative on error. |
1162 | | */ |
1163 | | static int bio_get_data(WOLFSSL_BIO* bio, byte** data) |
1164 | 0 | { |
1165 | 0 | int ret = 0; |
1166 | 0 | byte* mem = NULL; |
1167 | | |
1168 | | /* Get length of data in BIO. */ |
1169 | 0 | ret = wolfSSL_BIO_get_len(bio); |
1170 | 0 | if (ret > 0) { |
1171 | | /* Allocate memory big enough to hold data in BIO. */ |
1172 | 0 | mem = (byte*)XMALLOC((size_t)ret, bio->heap, DYNAMIC_TYPE_OPENSSL); |
1173 | 0 | if (mem == NULL) { |
1174 | 0 | WOLFSSL_MSG("Memory error"); |
1175 | 0 | ret = MEMORY_E; |
1176 | 0 | } |
1177 | 0 | if (ret >= 0) { |
1178 | | /* Read data from BIO. */ |
1179 | 0 | if ((ret = wolfSSL_BIO_read(bio, mem, ret)) <= 0) { |
1180 | 0 | XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL); |
1181 | 0 | ret = MEMORY_E; |
1182 | 0 | mem = NULL; |
1183 | 0 | } |
1184 | 0 | } |
1185 | 0 | } |
1186 | | |
1187 | | /* Return allocated buffer with data from BIO. */ |
1188 | 0 | *data = mem; |
1189 | 0 | return ret; |
1190 | 0 | } |
1191 | | |
1192 | | /* Convert the algorithm id to a key type. |
1193 | | * |
1194 | | * @param [in] algId Algorithm Id. |
1195 | | * @return Key type on success. |
1196 | | * @return WC_EVP_PKEY_NONE when algorithm id not supported. |
1197 | | */ |
1198 | | static int wolfssl_i_alg_id_to_key_type(word32 algId) |
1199 | 0 | { |
1200 | 0 | int type; |
1201 | | |
1202 | | /* Convert algorithm id into EVP PKEY id. */ |
1203 | 0 | switch (algId) { |
1204 | 0 | #ifndef NO_RSA |
1205 | 0 | case RSAk: |
1206 | 0 | #ifdef WC_RSA_PSS |
1207 | 0 | case RSAPSSk: |
1208 | 0 | #endif |
1209 | 0 | type = WC_EVP_PKEY_RSA; |
1210 | 0 | break; |
1211 | 0 | #endif |
1212 | 0 | #ifdef HAVE_ECC |
1213 | 0 | case ECDSAk: |
1214 | 0 | type = WC_EVP_PKEY_EC; |
1215 | 0 | break; |
1216 | 0 | #endif |
1217 | | #ifndef NO_DSA |
1218 | | case DSAk: |
1219 | | type = WC_EVP_PKEY_DSA; |
1220 | | break; |
1221 | | #endif |
1222 | 0 | #ifndef NO_DH |
1223 | 0 | case DHk: |
1224 | 0 | type = WC_EVP_PKEY_DH; |
1225 | 0 | break; |
1226 | 0 | #endif |
1227 | 0 | default: |
1228 | 0 | WOLFSSL_MSG("PKEY algorithm, from PKCS#8 header, not supported"); |
1229 | 0 | type = WC_EVP_PKEY_NONE; |
1230 | 0 | break; |
1231 | 0 | } |
1232 | | |
1233 | 0 | return type; |
1234 | 0 | } |
1235 | | |
1236 | | /* Creates an WOLFSSL_EVP_PKEY from PKCS#8 encrypted private DER in a BIO. |
1237 | | * |
1238 | | * Uses the PEM default password callback when cb is NULL. |
1239 | | * |
1240 | | * @param [in] bio BIO to read DER from. |
1241 | | * @param [in, out] pkey Newly created WOLFSSL_EVP_PKEY structure. |
1242 | | * @param [in] cb Password callback. May be NULL. |
1243 | | * @param [in] ctx Password callback context. May be NULL. |
1244 | | * @return A non null pointer on success. |
1245 | | * @return NULL on failure. |
1246 | | */ |
1247 | | WOLFSSL_EVP_PKEY* wolfSSL_d2i_PKCS8PrivateKey_bio(WOLFSSL_BIO* bio, |
1248 | | WOLFSSL_EVP_PKEY** pkey, wc_pem_password_cb* cb, void* ctx) |
1249 | 0 | { |
1250 | 0 | int ret; |
1251 | 0 | const byte* p; |
1252 | 0 | byte* der = NULL; |
1253 | 0 | int len; |
1254 | 0 | word32 algId; |
1255 | 0 | WOLFSSL_EVP_PKEY* key; |
1256 | 0 | int type; |
1257 | 0 | char password[NAME_SZ]; |
1258 | 0 | int passwordSz; |
1259 | | |
1260 | | /* Get the data from the BIO into a newly allocated buffer. */ |
1261 | 0 | if ((len = bio_get_data(bio, &der)) < 0) |
1262 | 0 | return NULL; |
1263 | | |
1264 | | /* Use the PEM default callback if none supplied. */ |
1265 | 0 | if (cb == NULL) { |
1266 | 0 | cb = wolfSSL_PEM_def_callback; |
1267 | 0 | } |
1268 | | /* Get the password. */ |
1269 | 0 | passwordSz = cb(password, sizeof(password), PEM_PASS_READ, ctx); |
1270 | 0 | if (passwordSz < 0) { |
1271 | 0 | XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL); |
1272 | 0 | return NULL; |
1273 | 0 | } |
1274 | | #ifdef WOLFSSL_CHECK_MEM_ZERO |
1275 | | wc_MemZero_Add("wolfSSL_d2i_PKCS8PrivateKey_bio password", password, |
1276 | | passwordSz); |
1277 | | #endif |
1278 | | |
1279 | | /* Decrypt the PKCS#8 encrypted private key and get algorithm. */ |
1280 | 0 | ret = ToTraditionalEnc(der, (word32)len, password, passwordSz, &algId); |
1281 | 0 | ForceZero(password, (word32)passwordSz); |
1282 | | #ifdef WOLFSSL_CHECK_MEM_ZERO |
1283 | | wc_MemZero_Check(password, passwordSz); |
1284 | | #endif |
1285 | 0 | if (ret < 0) { |
1286 | 0 | XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL); |
1287 | 0 | return NULL; |
1288 | 0 | } |
1289 | | |
1290 | | /* Get the key type from the algorithm id of the PKCS#8 header. */ |
1291 | 0 | if ((type = wolfssl_i_alg_id_to_key_type(algId)) == WC_EVP_PKEY_NONE) { |
1292 | 0 | XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL); |
1293 | 0 | return NULL; |
1294 | 0 | } |
1295 | | |
1296 | | /* Decode private key with the known type. */ |
1297 | 0 | p = der; |
1298 | 0 | key = d2i_evp_pkey(type, pkey, &p, len, 1); |
1299 | | |
1300 | | /* Dispose of memory holding BIO data. */ |
1301 | 0 | XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL); |
1302 | 0 | return key; |
1303 | 0 | } |
1304 | | #endif /* !NO_BIO && !NO_PWDBASED && HAVE_PKCS8 */ |
1305 | | #endif /* OPENSSL_ALL */ |
1306 | | |
1307 | | #ifdef OPENSSL_EXTRA |
1308 | | /* Reads in a PKCS#8 DER format key. |
1309 | | * |
1310 | | * @param [in, out] pkey Newly created WOLFSSL_PKCS8_PRIV_KEY_INFO structure. |
1311 | | * @param [in, out] keyBuf Pointer to input key DER. |
1312 | | * Pointer is advanced the same number of bytes read on |
1313 | | * success. |
1314 | | * @param [in] keyLen Number of bytes in keyBuf. |
1315 | | * @return A non null pointer on success. |
1316 | | * @return NULL on failure. |
1317 | | */ |
1318 | | WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY( |
1319 | | WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey, const unsigned char** keyBuf, |
1320 | | long keyLen) |
1321 | 0 | { |
1322 | 0 | WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL; |
1323 | 0 | #ifdef WOLFSSL_PEM_TO_DER |
1324 | 0 | int ret; |
1325 | 0 | DerBuffer* pkcs8Der = NULL; |
1326 | 0 | DerBuffer rawDer; |
1327 | 0 | EncryptedInfo info; |
1328 | 0 | int advanceLen = 0; |
1329 | | |
1330 | | /* Clear the encryption information and DER buffer. */ |
1331 | 0 | XMEMSET(&info, 0, sizeof(info)); |
1332 | 0 | XMEMSET(&rawDer, 0, sizeof(rawDer)); |
1333 | | |
1334 | | /* Validate parameters. */ |
1335 | 0 | if ((keyBuf == NULL) || (*keyBuf == NULL) || (keyLen <= 0)) { |
1336 | 0 | WOLFSSL_MSG("Bad key PEM/DER args"); |
1337 | 0 | return NULL; |
1338 | 0 | } |
1339 | | |
1340 | | /* Try to decode the PEM into DER. */ |
1341 | 0 | ret = PemToDer(*keyBuf, keyLen, PRIVATEKEY_TYPE, &pkcs8Der, NULL, &info, |
1342 | 0 | NULL); |
1343 | 0 | if (ret >= 0) { |
1344 | | /* Cache the amount of data in PEM formatted private key. */ |
1345 | 0 | advanceLen = (int)info.consumed; |
1346 | 0 | } |
1347 | 0 | else { |
1348 | | /* Not PEM - create a DerBuffer with the PKCS#8 DER data. */ |
1349 | 0 | WOLFSSL_MSG("Not PEM format"); |
1350 | 0 | ret = AllocDer(&pkcs8Der, (word32)keyLen, PRIVATEKEY_TYPE, NULL); |
1351 | 0 | if (ret == 0) { |
1352 | 0 | XMEMCPY(pkcs8Der->buffer, *keyBuf, keyLen); |
1353 | 0 | } |
1354 | 0 | } |
1355 | |
|
1356 | 0 | if (ret == 0) { |
1357 | | /* Verify this is PKCS8 Key */ |
1358 | 0 | word32 inOutIdx = 0; |
1359 | 0 | word32 algId; |
1360 | |
|
1361 | 0 | ret = ToTraditionalInline_ex(pkcs8Der->buffer, &inOutIdx, |
1362 | 0 | pkcs8Der->length, &algId); |
1363 | 0 | if (ret >= 0) { |
1364 | 0 | if (advanceLen == 0) { |
1365 | | /* Set only if not PEM */ |
1366 | 0 | advanceLen = (int)inOutIdx + ret; |
1367 | 0 | } |
1368 | 0 | if (algId == DHk) { |
1369 | | /* Special case for DH as we expect the DER buffer to be always |
1370 | | * be in PKCS8 format */ |
1371 | 0 | rawDer.buffer = pkcs8Der->buffer; |
1372 | 0 | rawDer.length = inOutIdx + (word32)ret; |
1373 | 0 | } |
1374 | 0 | else { |
1375 | 0 | rawDer.buffer = pkcs8Der->buffer + inOutIdx; |
1376 | 0 | rawDer.length = (word32)ret; |
1377 | 0 | } |
1378 | 0 | ret = 0; /* good DER */ |
1379 | 0 | } |
1380 | 0 | } |
1381 | |
|
1382 | 0 | if (ret == 0) { |
1383 | | /* Create a WOLFSSL_EVP_PKEY for a WOLFSSL_PKCS8_PRIV_KEY_INFO. */ |
1384 | 0 | pkcs8 = wolfSSL_EVP_PKEY_new(); |
1385 | 0 | if (pkcs8 == NULL) { |
1386 | 0 | ret = MEMORY_E; |
1387 | 0 | } |
1388 | 0 | } |
1389 | 0 | if (ret == 0) { |
1390 | | /* Allocate memory to hold DER. */ |
1391 | 0 | pkcs8->pkey.ptr = (char*)XMALLOC(rawDer.length, NULL, |
1392 | 0 | DYNAMIC_TYPE_PUBLIC_KEY); |
1393 | 0 | if (pkcs8->pkey.ptr == NULL) { |
1394 | 0 | ret = MEMORY_E; |
1395 | 0 | } |
1396 | 0 | } |
1397 | 0 | if (ret == 0) { |
1398 | | /* Copy in DER data and size. */ |
1399 | 0 | XMEMCPY(pkcs8->pkey.ptr, rawDer.buffer, rawDer.length); |
1400 | 0 | pkcs8->pkey_sz = (int)rawDer.length; |
1401 | 0 | } |
1402 | | |
1403 | | /* Dispose of PKCS#8 DER data - raw DER reference data in pkcs8Der. */ |
1404 | 0 | FreeDer(&pkcs8Der); |
1405 | 0 | if (ret != 0) { |
1406 | | /* Dispose of WOLFSSL_PKCS8_PRIV_KEY_INFO object on error. */ |
1407 | 0 | wolfSSL_EVP_PKEY_free(pkcs8); |
1408 | 0 | pkcs8 = NULL; |
1409 | 0 | } |
1410 | 0 | else { |
1411 | | /* Advance the buffer past the key on success. */ |
1412 | 0 | *keyBuf += advanceLen; |
1413 | 0 | } |
1414 | 0 | if (pkey != NULL) { |
1415 | | /* Return the WOLFSSL_PKCS8_PRIV_KEY_INFO object through parameter. */ |
1416 | 0 | *pkey = pkcs8; |
1417 | 0 | } |
1418 | | #else |
1419 | | (void)pkey; |
1420 | | (void)keyBuf; |
1421 | | (void)keyLen; |
1422 | | #endif /* WOLFSSL_PEM_TO_DER */ |
1423 | | |
1424 | | /* Return new WOLFSSL_PKCS8_PRIV_KEY_INFO object. */ |
1425 | 0 | return pkcs8; |
1426 | 0 | } |
1427 | | |
1428 | | #ifndef NO_BIO |
1429 | | /* Converts a DER format key read from BIO to a PKCS#8 structure. |
1430 | | * |
1431 | | * @param [in] bio Input BIO to read DER from. |
1432 | | * @param [out] pkey If not NULL then this pointer will be overwritten with a |
1433 | | * new PKCS8 structure. |
1434 | | * @return A WOLFSSL_PKCS8_PRIV_KEY_INFO pointer on success |
1435 | | * @return NULL on failure. |
1436 | | */ |
1437 | | WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY_bio(WOLFSSL_BIO* bio, |
1438 | | WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey) |
1439 | 0 | { |
1440 | 0 | WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL; |
1441 | 0 | #ifdef WOLFSSL_PEM_TO_DER |
1442 | 0 | unsigned char* mem = NULL; |
1443 | 0 | int memSz; |
1444 | |
|
1445 | 0 | WOLFSSL_ENTER("wolfSSL_d2i_PKCS8_PKEY_bio"); |
1446 | | |
1447 | | /* Validate parameters. */ |
1448 | 0 | if (bio == NULL) { |
1449 | 0 | return NULL; |
1450 | 0 | } |
1451 | | |
1452 | | /* Get the memory buffer from the BIO. */ |
1453 | 0 | if ((memSz = wolfSSL_BIO_get_mem_data(bio, &mem)) < 0) { |
1454 | 0 | return NULL; |
1455 | 0 | } |
1456 | | |
1457 | | /* Decode the PKCS#8 key into a WOLFSSL_PKCS8_PRIV_KEY_INFO object. */ |
1458 | 0 | pkcs8 = wolfSSL_d2i_PKCS8_PKEY(pkey, (const unsigned char**)&mem, memSz); |
1459 | | #else |
1460 | | (void)bio; |
1461 | | (void)pkey; |
1462 | | #endif /* WOLFSSL_PEM_TO_DER */ |
1463 | | |
1464 | | /* Return new WOLFSSL_PKCS8_PRIV_KEY_INFO object. */ |
1465 | 0 | return pkcs8; |
1466 | 0 | } |
1467 | | #endif /* !NO_BIO */ |
1468 | | |
1469 | | #ifdef WOLF_PRIVATE_KEY_ID |
1470 | | /* Create an EVP structure for use with crypto callbacks. |
1471 | | * |
1472 | | * @param [in] type Type of private key. |
1473 | | * @param [out] out WOLFSSL_EVP_PKEY object created. |
1474 | | * @param [in] heap Heap hint for dynamic memory allocation. |
1475 | | * @param [in] devId Device id. |
1476 | | * @return A new WOLFSSL_EVP_PKEY object on success. |
1477 | | * @return NULL on failure. |
1478 | | */ |
1479 | | WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_id(int type, WOLFSSL_EVP_PKEY** out, |
1480 | | void* heap, int devId) |
1481 | 0 | { |
1482 | 0 | WOLFSSL_EVP_PKEY* local; |
1483 | | |
1484 | | /* Dispose of any object passed in through out. */ |
1485 | 0 | if (out != NULL && *out != NULL) { |
1486 | 0 | wolfSSL_EVP_PKEY_free(*out); |
1487 | 0 | *out = NULL; |
1488 | 0 | } |
1489 | | |
1490 | | /* Create a local WOLFSSL_EVP_PKEY to be decoded into. */ |
1491 | 0 | local = wolfSSL_EVP_PKEY_new_ex(heap); |
1492 | 0 | if (local == NULL) { |
1493 | 0 | return NULL; |
1494 | 0 | } |
1495 | 0 | local->type = type; |
1496 | 0 | local->pkey_sz = 0; |
1497 | 0 | local->pkcs8HeaderSz = 0; |
1498 | |
|
1499 | 0 | switch (type) { |
1500 | 0 | #ifndef NO_RSA |
1501 | 0 | case WC_EVP_PKEY_RSA: |
1502 | 0 | { |
1503 | | /* Create a WOLFSSL_RSA object into WOLFSSL_EVP_PKEY. */ |
1504 | 0 | local->rsa = wolfSSL_RSA_new_ex(heap, devId); |
1505 | 0 | if (local->rsa == NULL) { |
1506 | 0 | wolfSSL_EVP_PKEY_free(local); |
1507 | 0 | return NULL; |
1508 | 0 | } |
1509 | 0 | local->ownRsa = 1; |
1510 | | /* Algorithm specific object set into WOLFSL_EVP_PKEY. */ |
1511 | 0 | local->rsa->inSet = 1; |
1512 | 0 | #ifdef WOLF_CRYPTO_CB |
1513 | 0 | ((RsaKey*)local->rsa->internal)->devId = devId; |
1514 | 0 | #endif |
1515 | 0 | break; |
1516 | 0 | } |
1517 | 0 | #endif /* !NO_RSA */ |
1518 | 0 | #ifdef HAVE_ECC |
1519 | 0 | case WC_EVP_PKEY_EC: |
1520 | 0 | { |
1521 | 0 | ecc_key* key; |
1522 | | |
1523 | | /* Create a WOLFSSL_EC object into WOLFSSL_EVP_PKEY. */ |
1524 | 0 | local->ecc = wolfSSL_EC_KEY_new_ex(heap, devId); |
1525 | 0 | if (local->ecc == NULL) { |
1526 | 0 | wolfSSL_EVP_PKEY_free(local); |
1527 | 0 | return NULL; |
1528 | 0 | } |
1529 | 0 | local->ownEcc = 1; |
1530 | | /* Algorithm specific object set into WOLFSL_EVP_PKEY. */ |
1531 | 0 | local->ecc->inSet = 1; |
1532 | | |
1533 | | /* Get wolfSSL EC key and set fields. */ |
1534 | 0 | key = (ecc_key*)local->ecc->internal; |
1535 | 0 | #ifdef WOLF_CRYPTO_CB |
1536 | 0 | key->devId = devId; |
1537 | 0 | #endif |
1538 | 0 | key->type = ECC_PRIVATEKEY; |
1539 | | /* key is required to have a key size / curve set, although |
1540 | | * actual one used is determined by devId callback function. */ |
1541 | 0 | wc_ecc_set_curve(key, ECDHE_SIZE, ECC_CURVE_DEF); |
1542 | 0 | break; |
1543 | 0 | } |
1544 | 0 | #endif /* HAVE_ECC */ |
1545 | 0 | default: |
1546 | 0 | WOLFSSL_MSG("Unsupported private key id type"); |
1547 | 0 | wolfSSL_EVP_PKEY_free(local); |
1548 | 0 | return NULL; |
1549 | 0 | } |
1550 | | |
1551 | | /* Return new WOLFSSL_EVP_PKEY through parameter if required. */ |
1552 | 0 | if (local != NULL && out != NULL) { |
1553 | 0 | *out = local; |
1554 | 0 | } |
1555 | | /* Return new WOLFSSL_EVP_PKEY. */ |
1556 | 0 | return local; |
1557 | 0 | } |
1558 | | #endif /* WOLF_PRIVATE_KEY_ID */ |
1559 | | #endif /* OPENSSL_EXTRA */ |
1560 | | |
1561 | | /******************************************************************************* |
1562 | | * END OF d2i APIs |
1563 | | ******************************************************************************/ |
1564 | | |
1565 | | /******************************************************************************* |
1566 | | * START OF i2d APIs |
1567 | | ******************************************************************************/ |
1568 | | |
1569 | | #ifdef OPENSSL_ALL |
1570 | | /* Encode PKCS#8 key as DER data. |
1571 | | * |
1572 | | * @param [in] key PKCS#8 private key to encode. |
1573 | | * @param [out] pp Pointer to buffer of encoded data. |
1574 | | * @return Length of DER encoded data on success. |
1575 | | * @return Less than zero on failure. |
1576 | | */ |
1577 | | int wolfSSL_i2d_PKCS8_PKEY(WOLFSSL_PKCS8_PRIV_KEY_INFO* key, unsigned char** pp) |
1578 | 0 | { |
1579 | 0 | word32 keySz = 0; |
1580 | 0 | unsigned char* out; |
1581 | 0 | int len; |
1582 | |
|
1583 | 0 | WOLFSSL_ENTER("wolfSSL_i2d_PKCS8_PKEY"); |
1584 | | |
1585 | | /* Validate parameters. */ |
1586 | 0 | if (key == NULL) { |
1587 | 0 | return WOLFSSL_FATAL_ERROR; |
1588 | 0 | } |
1589 | | |
1590 | | /* Get the length of DER encoding. */ |
1591 | 0 | if (pkcs8_encode(key, NULL, &keySz) != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { |
1592 | 0 | return WOLFSSL_FATAL_ERROR; |
1593 | 0 | } |
1594 | 0 | len = (int)keySz; |
1595 | | |
1596 | | /* Return the length when output parameter is NULL. */ |
1597 | 0 | if ((pp == NULL) || (len == 0)) { |
1598 | 0 | return len; |
1599 | 0 | } |
1600 | | |
1601 | | /* Allocate memory for DER encoding if NULL passed in for output buffer. */ |
1602 | 0 | if (*pp == NULL) { |
1603 | 0 | out = (unsigned char*)XMALLOC((size_t)len, NULL, DYNAMIC_TYPE_ASN1); |
1604 | 0 | if (out == NULL) { |
1605 | 0 | return WOLFSSL_FATAL_ERROR; |
1606 | 0 | } |
1607 | 0 | } |
1608 | 0 | else { |
1609 | | /* Use buffer passed in - assume it is big enough. */ |
1610 | 0 | out = *pp; |
1611 | 0 | } |
1612 | | |
1613 | | /* Encode the PKCS#8 key into the output buffer. */ |
1614 | 0 | if (pkcs8_encode(key, out, &keySz) != len) { |
1615 | 0 | if (*pp == NULL) { |
1616 | 0 | XFREE(out, NULL, DYNAMIC_TYPE_ASN1); |
1617 | 0 | } |
1618 | 0 | return WOLFSSL_FATAL_ERROR; |
1619 | 0 | } |
1620 | | |
1621 | | /* Return new output buffer or move pointer passed encoded data. */ |
1622 | 0 | if (*pp == NULL) { |
1623 | 0 | *pp = out; |
1624 | 0 | } |
1625 | 0 | else { |
1626 | 0 | *pp += len; |
1627 | 0 | } |
1628 | |
|
1629 | 0 | return len; |
1630 | 0 | } |
1631 | | #endif |
1632 | | |
1633 | | #ifdef OPENSSL_EXTRA |
1634 | | |
1635 | | #if !defined(NO_ASN) && !defined(NO_PWDBASED) |
1636 | | /* Get raw pointer to DER buffer from WOLFSSL_EVP_PKEY. |
1637 | | * |
1638 | | * Assumes der is large enough if passed in. |
1639 | | * |
1640 | | * @param [in] key WOLFSSL_EVP_PKEY to get DER buffer for. |
1641 | | * @param [out] der Buffer holding DER encoding. May be NULL. |
1642 | | * @return Size of DER encoding on success. |
1643 | | * @return Less than 0 on failure. |
1644 | | */ |
1645 | | static int wolfssl_i_evp_pkey_get_der(const WOLFSSL_EVP_PKEY* key, |
1646 | | unsigned char** der) |
1647 | 0 | { |
1648 | 0 | int sz; |
1649 | 0 | word16 pkcs8HeaderSz; |
1650 | | |
1651 | | /* Validate parameters. */ |
1652 | 0 | if ((key == NULL) || (key->pkey_sz == 0)) { |
1653 | 0 | return WOLFSSL_FATAL_ERROR; |
1654 | 0 | } |
1655 | | |
1656 | | /* If pkcs8HeaderSz is invalid, return all of the DER encoding. */ |
1657 | 0 | pkcs8HeaderSz = 0; |
1658 | 0 | if (key->pkey_sz > key->pkcs8HeaderSz) { |
1659 | 0 | pkcs8HeaderSz = key->pkcs8HeaderSz; |
1660 | 0 | } |
1661 | | /* Calculate the size of the DER encoding to return. */ |
1662 | 0 | sz = key->pkey_sz - pkcs8HeaderSz; |
1663 | | /* Returning encoding when DER is not NULL. */ |
1664 | 0 | if (der != NULL) { |
1665 | 0 | unsigned char* pt = (unsigned char*)key->pkey.ptr; |
1666 | 0 | int bufferPassedIn = ((*der) != NULL); |
1667 | |
|
1668 | 0 | if (!bufferPassedIn) { |
1669 | | /* Allocate buffer to hold DER encoding. */ |
1670 | 0 | *der = (unsigned char*)XMALLOC((size_t)sz, NULL, |
1671 | 0 | DYNAMIC_TYPE_OPENSSL); |
1672 | 0 | if (*der == NULL) { |
1673 | 0 | return WOLFSSL_FATAL_ERROR; |
1674 | 0 | } |
1675 | 0 | } |
1676 | | /* Copy in non-PKCS#8 DER encoding. */ |
1677 | 0 | XMEMCPY(*der, pt + pkcs8HeaderSz, (size_t)sz); |
1678 | | /* Step past encoded key when buffer provided. */ |
1679 | 0 | if (bufferPassedIn) { |
1680 | 0 | *der += sz; |
1681 | 0 | } |
1682 | 0 | } |
1683 | | |
1684 | | /* Return size of DER encoded data. */ |
1685 | 0 | return sz; |
1686 | 0 | } |
1687 | | |
1688 | | /* Encode key as unencrypted DER data. |
1689 | | * |
1690 | | * @param [in] key PKCS#8 private key to encode. |
1691 | | * @param [out] der Pointer to buffer of encoded data. |
1692 | | * @return Length of DER encoded data on success. |
1693 | | * @return Less than zero on failure. |
1694 | | */ |
1695 | | int wolfSSL_i2d_PrivateKey(const WOLFSSL_EVP_PKEY* key, unsigned char** der) |
1696 | 0 | { |
1697 | 0 | return wolfssl_i_evp_pkey_get_der(key, der); |
1698 | 0 | } |
1699 | | |
1700 | | #ifndef NO_BIO |
1701 | | /* Encode key as unencrypted DER data and write to BIO. |
1702 | | * |
1703 | | * @param [in] bio BIO to write data to. |
1704 | | * @param [in] key PKCS#8 private key to encode. |
1705 | | * @return Length of DER encoded data on success. |
1706 | | * @return Less than zero on failure. |
1707 | | */ |
1708 | | int wolfSSL_i2d_PrivateKey_bio(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key) |
1709 | 0 | { |
1710 | 0 | int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE); |
1711 | 0 | int derSz = 0; |
1712 | 0 | byte* der = NULL; |
1713 | |
|
1714 | 0 | if (bio == NULL || key == NULL) { |
1715 | 0 | return WOLFSSL_FAILURE; |
1716 | 0 | } |
1717 | | |
1718 | 0 | derSz = wolfSSL_i2d_PrivateKey(key, &der); |
1719 | 0 | if (derSz <= 0) { |
1720 | 0 | WOLFSSL_MSG("wolfSSL_i2d_PrivateKey (for getting size) failed"); |
1721 | 0 | return WOLFSSL_FAILURE; |
1722 | 0 | } |
1723 | | |
1724 | 0 | if (wolfSSL_BIO_write(bio, der, derSz) != derSz) { |
1725 | 0 | goto cleanup; |
1726 | 0 | } |
1727 | | |
1728 | 0 | ret = WOLFSSL_SUCCESS; |
1729 | |
|
1730 | 0 | cleanup: |
1731 | 0 | XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL); |
1732 | 0 | return ret; |
1733 | 0 | } |
1734 | | #endif |
1735 | | |
1736 | | #ifdef HAVE_ECC |
1737 | | /* Encode EC key as public key DER. |
1738 | | * |
1739 | | * @param [in] key WOLFSSL_EVP_KEY object to encode. |
1740 | | * @param [in] ec WOLFSSL_EC_KEY object to encode. |
1741 | | * @param [out] der Buffer with DER encoding of EC public key. |
1742 | | * @return Public key DER encoding size on success. |
1743 | | * @return WOLFSSL_FATAL_ERROR when dynamic memory allocation fails. |
1744 | | * @return WOLFSSL_FATAL_ERROR when encoding fails. |
1745 | | */ |
1746 | | static int wolfssl_i_i2d_ecpublickey(const WOLFSSL_EVP_PKEY* key, |
1747 | | const WOLFSSL_EC_KEY *ec, unsigned char **der) |
1748 | 0 | { |
1749 | 0 | word32 pub_derSz = 0; |
1750 | 0 | int ret; |
1751 | 0 | unsigned char *local_der = NULL; |
1752 | 0 | word32 local_derSz = 0; |
1753 | 0 | unsigned char *pub_der = NULL; |
1754 | 0 | ecc_key *eccKey = NULL; |
1755 | 0 | word32 inOutIdx = 0; |
1756 | | |
1757 | | /* We need to get the DER, then convert it to a public key. But what we get |
1758 | | * might be a buffered private key so we need to decode it and then encode |
1759 | | * the public part. */ |
1760 | 0 | ret = wolfssl_i_evp_pkey_get_der(key, &local_der); |
1761 | 0 | if (ret <= 0) { |
1762 | | /* In this case, there was no buffered DER at all. This could be the |
1763 | | * case where the key that was passed in was generated. So now we |
1764 | | * have to create the local DER. */ |
1765 | 0 | local_derSz = (word32)wolfSSL_i2d_ECPrivateKey(ec, &local_der); |
1766 | 0 | if (local_derSz == 0) { |
1767 | 0 | ret = WOLFSSL_FATAL_ERROR; |
1768 | 0 | } |
1769 | 0 | } else { |
1770 | 0 | local_derSz = (word32)ret; |
1771 | 0 | ret = 0; |
1772 | 0 | } |
1773 | |
|
1774 | 0 | if (ret == 0) { |
1775 | 0 | eccKey = (ecc_key *)XMALLOC(sizeof(*eccKey), NULL, DYNAMIC_TYPE_ECC); |
1776 | 0 | if (eccKey == NULL) { |
1777 | 0 | WOLFSSL_MSG("Failed to allocate key buffer."); |
1778 | 0 | ret = WOLFSSL_FATAL_ERROR; |
1779 | 0 | } |
1780 | 0 | } |
1781 | | |
1782 | | /* Initialize a wolfCrypt ECC key. */ |
1783 | 0 | if (ret == 0) { |
1784 | 0 | ret = wc_ecc_init(eccKey); |
1785 | 0 | } |
1786 | 0 | if (ret == 0) { |
1787 | | /* Decode the DER data with wolfCrypt ECC key. */ |
1788 | 0 | ret = wc_EccPublicKeyDecode(local_der, &inOutIdx, eccKey, local_derSz); |
1789 | 0 | if (ret < 0) { |
1790 | | /* We now try again as x.963 [point type][x][opt y]. */ |
1791 | 0 | ret = wc_ecc_import_x963(local_der, local_derSz, eccKey); |
1792 | 0 | } |
1793 | 0 | } |
1794 | |
|
1795 | 0 | if (ret == 0) { |
1796 | | /* Get the size of the encoding of the public key DER. */ |
1797 | 0 | pub_derSz = (word32)wc_EccPublicKeyDerSize(eccKey, 1); |
1798 | 0 | if ((int)pub_derSz <= 0) { |
1799 | 0 | ret = WOLFSSL_FAILURE; |
1800 | 0 | } |
1801 | 0 | } |
1802 | |
|
1803 | 0 | if (ret == 0) { |
1804 | | /* Allocate memory for public key DER encoding. */ |
1805 | 0 | pub_der = (unsigned char*)XMALLOC(pub_derSz, NULL, |
1806 | 0 | DYNAMIC_TYPE_PUBLIC_KEY); |
1807 | 0 | if (pub_der == NULL) { |
1808 | 0 | WOLFSSL_MSG("Failed to allocate output buffer."); |
1809 | 0 | ret = WOLFSSL_FATAL_ERROR; |
1810 | 0 | } |
1811 | 0 | } |
1812 | |
|
1813 | 0 | if (ret == 0) { |
1814 | | /* Encode public key as DER. */ |
1815 | 0 | pub_derSz = (word32)wc_EccPublicKeyToDer(eccKey, pub_der, pub_derSz, 1); |
1816 | 0 | if ((int)pub_derSz <= 0) { |
1817 | 0 | ret = WOLFSSL_FATAL_ERROR; |
1818 | 0 | } |
1819 | 0 | } |
1820 | | |
1821 | | /* This block is for actually returning the DER of the public key */ |
1822 | 0 | if ((ret == 0) && (der != NULL)) { |
1823 | 0 | int bufferPassedIn = ((*der) != NULL); |
1824 | 0 | if (!bufferPassedIn) { |
1825 | 0 | *der = (unsigned char*)XMALLOC(pub_derSz, NULL, |
1826 | 0 | DYNAMIC_TYPE_PUBLIC_KEY); |
1827 | 0 | if (*der == NULL) { |
1828 | 0 | WOLFSSL_MSG("Failed to allocate output buffer."); |
1829 | 0 | ret = WOLFSSL_FATAL_ERROR; |
1830 | 0 | } |
1831 | 0 | } |
1832 | 0 | if (ret == 0) { |
1833 | 0 | XMEMCPY(*der, pub_der, pub_derSz); |
1834 | 0 | if (bufferPassedIn) { |
1835 | 0 | *der += pub_derSz; |
1836 | 0 | } |
1837 | 0 | } |
1838 | 0 | } |
1839 | | |
1840 | | /* Dispose of allocated objects. */ |
1841 | 0 | XFREE(pub_der, NULL, DYNAMIC_TYPE_PUBLIC_KEY); |
1842 | 0 | XFREE(local_der, NULL, DYNAMIC_TYPE_OPENSSL); |
1843 | 0 | wc_ecc_free(eccKey); |
1844 | 0 | XFREE(eccKey, NULL, DYNAMIC_TYPE_ECC); |
1845 | | |
1846 | | /* Return error or the size of the DER encoded public key. */ |
1847 | 0 | if (ret == 0) { |
1848 | 0 | ret = (int)pub_derSz; |
1849 | 0 | } |
1850 | 0 | return ret; |
1851 | 0 | } |
1852 | | #endif |
1853 | | |
1854 | | /* Encode the WOLFSSL_EVP_PKEY object as public key DER. |
1855 | | * |
1856 | | * @param [in] key WOLFSLS_EVP_PKEY object to encode. |
1857 | | * @param [out] der Buffer with DER encoding of public key. |
1858 | | * @return Public key DER encoding size on success. |
1859 | | * @return WOLFSSL_FATAL_ERROR when key is NULL. |
1860 | | * @return WOLFSSL_FATAL_ERROR when key type not supported. |
1861 | | * @return WOLFSSL_FATAL_ERROR when dynamic memory allocation fails. |
1862 | | */ |
1863 | | int wolfSSL_i2d_PublicKey(const WOLFSSL_EVP_PKEY *key, unsigned char **der) |
1864 | 0 | { |
1865 | 0 | int ret; |
1866 | | |
1867 | | /* Validate parameters. */ |
1868 | 0 | if (key == NULL) { |
1869 | 0 | return WOLFSSL_FATAL_ERROR; |
1870 | 0 | } |
1871 | | |
1872 | | /* Encode based on key type. */ |
1873 | 0 | switch (key->type) { |
1874 | 0 | #ifndef NO_RSA |
1875 | 0 | case WC_EVP_PKEY_RSA: |
1876 | 0 | return wolfSSL_i2d_RSAPublicKey(key->rsa, der); |
1877 | 0 | #endif |
1878 | 0 | #ifdef HAVE_ECC |
1879 | 0 | case WC_EVP_PKEY_EC: |
1880 | 0 | return wolfssl_i_i2d_ecpublickey(key, key->ecc, der); |
1881 | 0 | #endif |
1882 | 0 | default: |
1883 | 0 | ret = WOLFSSL_FATAL_ERROR; |
1884 | 0 | break; |
1885 | 0 | } |
1886 | | |
1887 | 0 | return ret; |
1888 | 0 | } |
1889 | | |
1890 | | /* Encode the WOLFSSL_EVP_PKEY object as public key DER. |
1891 | | * |
1892 | | * @param [in] key WOLFSLS_EVP_PKEY object to encode. |
1893 | | * @param [out] der Buffer with DER encoding of public key. |
1894 | | * @return Public key DER encoding size on success. |
1895 | | * @return WOLFSSL_FATAL_ERROR when key is NULL. |
1896 | | * @return WOLFSSL_FATAL_ERROR when key type not supported. |
1897 | | * @return WOLFSSL_FATAL_ERROR when dynamic memory allocation fails. |
1898 | | */ |
1899 | | int wolfSSL_i2d_PUBKEY(const WOLFSSL_EVP_PKEY *key, unsigned char **der) |
1900 | 0 | { |
1901 | 0 | return wolfSSL_i2d_PublicKey(key, der); |
1902 | 0 | } |
1903 | | #endif /* !NO_ASN && !NO_PWDBASED */ |
1904 | | |
1905 | | #endif /* OPENSSL_EXTRA */ |
1906 | | |
1907 | | #endif /* !NO_CERTS */ |
1908 | | |
1909 | | /******************************************************************************* |
1910 | | * END OF i2d APIs |
1911 | | ******************************************************************************/ |
1912 | | |
1913 | | #endif /* !WOLFSSL_EVP_PK_INCLUDED */ |
1914 | | |