/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 | 318 | { |
53 | 318 | WOLFSSL_EVP_PKEY* pkey; |
54 | 318 | char* prevData = NULL; |
55 | 318 | int prevSz = 0; |
56 | 318 | int ret = 1; |
57 | | |
58 | 318 | (void)priv; |
59 | | |
60 | | /* Get or create the EVP PKEY object. */ |
61 | 318 | if (*out != NULL) { |
62 | 0 | pkey = *out; |
63 | | /* Hold on to the data of the key this object held before. It is |
64 | | * disposed of once the new key data has been copied in, as the caller |
65 | | * may be decoding out of it. */ |
66 | 0 | prevData = pkey->pkey.ptr; |
67 | 0 | prevSz = pkey->pkey_sz; |
68 | 0 | pkey->pkey.ptr = NULL; |
69 | 0 | pkey->pkey_sz = 0; |
70 | 0 | #ifdef OPENSSL_EXTRA |
71 | | /* Dispose of the key object of the key this object held before. The |
72 | | * type is about to change and wolfSSL_EVP_PKEY_free() only disposes of |
73 | | * the object matching the type set. */ |
74 | 0 | clearEVPPkeyKeys(pkey); |
75 | 0 | #endif |
76 | | /* Drop metadata describing the key this object held before, so a |
77 | | * reused object decodes to the same state as a new one. A failure |
78 | | * below must not leave the object advertising the old type. */ |
79 | 0 | pkey->type = WC_EVP_PKEY_NONE; |
80 | 0 | pkey->pkcs8HeaderSz = 0; |
81 | 0 | pkey->save_type = 0; |
82 | 0 | #ifdef HAVE_ECC |
83 | 0 | pkey->pkey_curve = 0; |
84 | 0 | #endif |
85 | | #ifdef WOLFSSL_HAVE_MLDSA |
86 | | WOLFSSL_ATOMIC_STORE(pkey->mldsaOID, 0); |
87 | | #endif |
88 | 0 | } |
89 | 318 | else { |
90 | 318 | pkey = wolfSSL_EVP_PKEY_new(); |
91 | 318 | if (pkey == NULL) { |
92 | 0 | WOLFSSL_MSG("wolfSSL_EVP_PKEY_new error"); |
93 | 0 | return 0; |
94 | 0 | } |
95 | 318 | } |
96 | | |
97 | | /* Set the size and allocate memory for key data to be copied into. |
98 | | * Heap hint and DYNAMIC_TYPE must match the frees of pkey.ptr. */ |
99 | 318 | pkey->pkey_sz = (int)memSz; |
100 | 318 | if (memSz > 0) { |
101 | 318 | pkey->pkey.ptr = (char*)XMALLOC((size_t)memSz, pkey->heap, |
102 | 318 | DYNAMIC_TYPE_PUBLIC_KEY); |
103 | 318 | if (pkey->pkey.ptr == NULL) { |
104 | | /* No encoding held - do not describe one. */ |
105 | 0 | pkey->pkey_sz = 0; |
106 | 0 | ret = 0; |
107 | 0 | } |
108 | 318 | if (ret == 1) { |
109 | | /* Copy in key data. */ |
110 | 318 | XMEMCPY(pkey->pkey.ptr, mem, memSz); |
111 | 318 | } |
112 | 318 | } |
113 | | /* The data of the key held before is no longer referenced. */ |
114 | 318 | if (prevData != NULL) { |
115 | 0 | if (prevSz > 0) { |
116 | 0 | ForceZero(prevData, (word32)prevSz); |
117 | 0 | } |
118 | 0 | XFREE(prevData, pkey->heap, DYNAMIC_TYPE_PUBLIC_KEY); |
119 | 0 | } |
120 | 318 | if (ret == 1) { |
121 | | /* Set key type passed in and return object. */ |
122 | 318 | pkey->type = type; |
123 | 318 | *out = pkey; |
124 | 318 | } |
125 | 318 | if ((ret == 0) && (*out == NULL)) { |
126 | | /* Dispose of object allocated in this function. */ |
127 | 0 | wolfSSL_EVP_PKEY_free(pkey); |
128 | 0 | } |
129 | | |
130 | 318 | return ret; |
131 | 318 | } |
132 | | |
133 | | #if !defined(NO_RSA) |
134 | | /** |
135 | | * Try to make an RSA EVP PKEY from data. |
136 | | * |
137 | | * @param [in, out] out On in, an EVP PKEY or NULL. |
138 | | * On out, an EVP PKEY or NULL. |
139 | | * @param [in] mem Memory containing key data. |
140 | | * @param [in] memSz Size of key data in bytes. |
141 | | * @param [in] priv 1 means private key, 0 means public key. |
142 | | * @return 1 on success. |
143 | | * @return 0 when input was recognized as this key type but |
144 | | * object creation/import failed. |
145 | | * @return WOLFSSL_FATAL_ERROR when input is not this key type. |
146 | | */ |
147 | | static int d2iTryRsaKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, |
148 | | long memSz, int priv) |
149 | 1.53k | { |
150 | 1.53k | WOLFSSL_RSA* rsaObj = NULL; |
151 | 1.53k | word32 keyIdx = 0; |
152 | 1.53k | int isRsaKey; |
153 | 1.53k | int ret = 1; |
154 | 1.53k | WC_DECLARE_VAR(rsa, RsaKey, 1, NULL); |
155 | | |
156 | 1.53k | WC_ALLOC_VAR_EX(rsa, RsaKey, 1, NULL, DYNAMIC_TYPE_RSA, return 0); |
157 | | |
158 | 1.53k | XMEMSET(rsa, 0, sizeof(RsaKey)); |
159 | | |
160 | 1.53k | if (wc_InitRsaKey(rsa, NULL) != 0) { |
161 | 0 | WC_FREE_VAR_EX(rsa, NULL, DYNAMIC_TYPE_RSA); |
162 | 0 | return 0; |
163 | 0 | } |
164 | | /* Try decoding data as an RSA private/public key. */ |
165 | 1.53k | if (priv) { |
166 | 0 | isRsaKey = |
167 | 0 | (wc_RsaPrivateKeyDecode(mem, &keyIdx, rsa, (word32)memSz) == 0); |
168 | 0 | } |
169 | 1.53k | else { |
170 | 1.53k | isRsaKey = |
171 | 1.53k | (wc_RsaPublicKeyDecode(mem, &keyIdx, rsa, (word32)memSz) == 0); |
172 | 1.53k | } |
173 | 1.53k | wc_FreeRsaKey(rsa); |
174 | 1.53k | WC_FREE_VAR_EX(rsa, NULL, DYNAMIC_TYPE_RSA); |
175 | | |
176 | 1.53k | if (!isRsaKey) { |
177 | 1.46k | return WOLFSSL_FATAL_ERROR; |
178 | 1.46k | } |
179 | | |
180 | | /* Create RSA key object from data. */ |
181 | 70 | rsaObj = wolfssl_rsa_d2i(NULL, mem, keyIdx, |
182 | 70 | priv ? WOLFSSL_RSA_LOAD_PRIVATE : WOLFSSL_RSA_LOAD_PUBLIC); |
183 | 70 | if (rsaObj == NULL) { |
184 | 0 | ret = 0; |
185 | 0 | } |
186 | 70 | if (ret == 1) { |
187 | | /* Create an EVP PKEY object. */ |
188 | 70 | ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_RSA); |
189 | 70 | } |
190 | 70 | if (ret == 1) { |
191 | | /* Put RSA key object into EVP PKEY object. */ |
192 | 70 | (*out)->ownRsa = 1; |
193 | 70 | (*out)->rsa = rsaObj; |
194 | 70 | } |
195 | 70 | if (ret == 0) { |
196 | 0 | wolfSSL_RSA_free(rsaObj); |
197 | 0 | } |
198 | | |
199 | 70 | return ret; |
200 | 1.53k | } |
201 | | #endif /* !NO_RSA */ |
202 | | |
203 | | #if defined(HAVE_ECC) && defined(OPENSSL_EXTRA) |
204 | | /** |
205 | | * Try to make an ECC EVP PKEY from data. |
206 | | * |
207 | | * @param [in, out] out On in, an EVP PKEY or NULL. |
208 | | * On out, an EVP PKEY or NULL. |
209 | | * @param [in] mem Memory containing key data. |
210 | | * @param [in] memSz Size of key data in bytes. |
211 | | * @param [in] priv 1 means private key, 0 means public key. |
212 | | * @return 1 on success. |
213 | | * @return 0 when input was recognized as this key type but |
214 | | * object creation/import failed. |
215 | | * @return WOLFSSL_FATAL_ERROR when input is not this key type. |
216 | | */ |
217 | | static int d2iTryEccKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, |
218 | | long memSz, int priv) |
219 | 1.46k | { |
220 | 1.46k | WOLFSSL_EC_KEY* ec = NULL; |
221 | 1.46k | word32 keyIdx = 0; |
222 | 1.46k | int isEccKey; |
223 | 1.46k | int ret = 1; |
224 | 1.46k | WC_DECLARE_VAR(ecc, ecc_key, 1, NULL); |
225 | | |
226 | 1.46k | WC_ALLOC_VAR_EX(ecc, ecc_key, 1, NULL, DYNAMIC_TYPE_ECC, return 0); |
227 | | |
228 | 1.46k | XMEMSET(ecc, 0, sizeof(ecc_key)); |
229 | | |
230 | 1.46k | if (wc_ecc_init(ecc) != 0) { |
231 | 0 | WC_FREE_VAR_EX(ecc, NULL, DYNAMIC_TYPE_ECC); |
232 | 0 | return 0; |
233 | 0 | } |
234 | | |
235 | | /* Try decoding data as an ECC private/public key. */ |
236 | 1.46k | if (priv) { |
237 | 0 | isEccKey = |
238 | 0 | (wc_EccPrivateKeyDecode(mem, &keyIdx, ecc, (word32)memSz) == 0); |
239 | 0 | } |
240 | 1.46k | else { |
241 | 1.46k | isEccKey = |
242 | 1.46k | (wc_EccPublicKeyDecode(mem, &keyIdx, ecc, (word32)memSz) == 0); |
243 | 1.46k | } |
244 | 1.46k | wc_ecc_free(ecc); |
245 | 1.46k | WC_FREE_VAR_EX(ecc, NULL, DYNAMIC_TYPE_ECC); |
246 | | |
247 | 1.46k | if (!isEccKey) { |
248 | 1.44k | return WOLFSSL_FATAL_ERROR; |
249 | 1.44k | } |
250 | | |
251 | | /* Create EC key object from data. */ |
252 | 26 | ec = wolfSSL_EC_KEY_new(); |
253 | 26 | if (ec == NULL) { |
254 | 0 | ret = 0; |
255 | 0 | } |
256 | 26 | if ((ret == 1) && (wolfSSL_EC_KEY_LoadDer_ex(ec, mem, keyIdx, |
257 | 26 | priv ? WOLFSSL_RSA_LOAD_PRIVATE : WOLFSSL_RSA_LOAD_PUBLIC) != 1)) { |
258 | 0 | ret = 0; |
259 | 0 | } |
260 | 26 | if (ret == 1) { |
261 | | /* Create an EVP PKEY object. */ |
262 | 26 | ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_EC); |
263 | 26 | } |
264 | 26 | if (ret == 1) { |
265 | | /* Put RSA key object into EVP PKEY object. */ |
266 | 26 | (*out)->ownEcc = 1; |
267 | 26 | (*out)->ecc = ec; |
268 | 26 | } |
269 | 26 | if (ret == 0) { |
270 | 0 | wolfSSL_EC_KEY_free(ec); |
271 | 0 | } |
272 | | |
273 | 26 | return ret; |
274 | 1.46k | } |
275 | | #endif /* HAVE_ECC && OPENSSL_EXTRA */ |
276 | | |
277 | | #if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT) |
278 | | /** |
279 | | * Try to make an Ed25519 EVP PKEY from data. |
280 | | * |
281 | | * @param [in, out] out On in, an EVP PKEY or NULL. |
282 | | * On out, an EVP PKEY or NULL. |
283 | | * @param [in] mem Memory containing key data. |
284 | | * @param [in] memSz Size of key data in bytes. |
285 | | * @param [in] priv 1 means private key, 0 means public key. |
286 | | * @param [in] prePopulated 1 means *out already holds the input bytes |
287 | | * so the d2i_make_pkey allocate/copy is skipped. |
288 | | * @return 1 on success. |
289 | | * @return 0 when input was recognized as this key type but object |
290 | | * creation/import failed. |
291 | | * @return WOLFSSL_FATAL_ERROR when input is not this key type. |
292 | | */ |
293 | | static int d2iTryEd25519Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, |
294 | | long memSz, int priv, int prePopulated) |
295 | 740 | { |
296 | 740 | ed25519_key* edKey = NULL; |
297 | 740 | word32 keyIdx = 0; |
298 | 740 | int isEdKey; |
299 | 740 | int ret = 1; |
300 | 740 | void* heap = NULL; |
301 | | |
302 | 740 | if (*out != NULL) { |
303 | 0 | heap = (*out)->heap; |
304 | 0 | } |
305 | | |
306 | 740 | edKey = wolfSSL_ED25519_new(heap, INVALID_DEVID); |
307 | 740 | if (edKey == NULL) { |
308 | 0 | return 0; |
309 | 0 | } |
310 | | |
311 | | /* Decode data as an Ed25519 key in DER form (SubjectPublicKeyInfo for |
312 | | * public keys, PKCS#8 PrivateKeyInfo for private keys). */ |
313 | 740 | if (priv) { |
314 | 0 | isEdKey = (wc_Ed25519PrivateKeyDecode(mem, &keyIdx, edKey, |
315 | 0 | (word32)memSz) == 0); |
316 | 0 | } |
317 | 740 | else { |
318 | 740 | isEdKey = (wc_Ed25519PublicKeyDecode(mem, &keyIdx, edKey, |
319 | 740 | (word32)memSz) == 0); |
320 | 740 | } |
321 | | |
322 | 740 | if (!isEdKey) { |
323 | 740 | wolfSSL_ED25519_free(edKey); |
324 | 740 | return WOLFSSL_FATAL_ERROR; |
325 | 740 | } |
326 | | |
327 | 0 | #ifdef HAVE_ED25519_MAKE_KEY |
328 | | /* A PKCS#8 v1 PrivateKeyInfo carries only the private seed, so the |
329 | | * decoded key has no public part. Derive it (deterministic from the |
330 | | * seed; wc_ed25519_make_public also stores it in the key) so the |
331 | | * resulting EVP_PKEY is complete and callers can later export/embed the |
332 | | * public key. Best-effort: on failure the key is left private-only. */ |
333 | 0 | if (priv && !edKey->pubKeySet) { |
334 | 0 | byte pub[ED25519_PUB_KEY_SIZE]; |
335 | |
|
336 | 0 | if (wc_ed25519_make_public(edKey, pub, sizeof(pub)) != 0) { |
337 | 0 | WOLFSSL_MSG("wc_ed25519_make_public failed; " |
338 | 0 | "EVP_PKEY has no public part"); |
339 | 0 | } |
340 | 0 | } |
341 | 0 | #endif /* HAVE_ED25519_MAKE_KEY */ |
342 | | |
343 | | /* Copy the consumed DER into pkey->pkey.ptr, unless the caller |
344 | | * pre-filled the EVP PKEY with the input bytes (d2i_evp_pkey()). |
345 | | * A reused key must be re-populated here. */ |
346 | 0 | if (!prePopulated) { |
347 | 0 | ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_ED25519); |
348 | 0 | } |
349 | 0 | if (ret == 1) { |
350 | 0 | (*out)->ownEd25519 = 1; |
351 | 0 | (*out)->ed25519 = edKey; |
352 | 0 | } |
353 | 0 | else { |
354 | 0 | wolfSSL_ED25519_free(edKey); |
355 | 0 | } |
356 | |
|
357 | 0 | return ret; |
358 | 740 | } |
359 | | #endif /* HAVE_ED25519i && HAVE_ED25519_KEY_IMPORT */ |
360 | | |
361 | | #if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT) |
362 | | /** |
363 | | * Try to make an Ed448 EVP PKEY from data. |
364 | | * |
365 | | * @param [in, out] out On in, an EVP PKEY or NULL. |
366 | | * On out, an EVP PKEY or NULL. |
367 | | * @param [in] mem Memory containing key data. |
368 | | * @param [in] memSz Size of key data in bytes. |
369 | | * @param [in] priv 1 means private key, 0 means public key. |
370 | | * @param [in] prePopulated 1 means *out already holds the input bytes |
371 | | * so the d2i_make_pkey allocate/copy is skipped. |
372 | | * @return 1 on success. |
373 | | * @return 0 when input was recognized as this key type but object |
374 | | * creation/import failed. |
375 | | * @return WOLFSSL_FATAL_ERROR when input is not this key type. |
376 | | */ |
377 | | static int d2iTryEd448Key(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, |
378 | | long memSz, int priv, int prePopulated) |
379 | 740 | { |
380 | 740 | ed448_key* edKey = NULL; |
381 | 740 | word32 keyIdx = 0; |
382 | 740 | int isEdKey; |
383 | 740 | int ret = 1; |
384 | 740 | void* heap = NULL; |
385 | | |
386 | 740 | if (*out != NULL) { |
387 | 0 | heap = (*out)->heap; |
388 | 0 | } |
389 | | |
390 | 740 | edKey = wolfSSL_ED448_new(heap, INVALID_DEVID); |
391 | 740 | if (edKey == NULL) { |
392 | 0 | return 0; |
393 | 0 | } |
394 | | |
395 | | /* Decode data as an Ed448 key in DER form (SubjectPublicKeyInfo for |
396 | | * public keys, PKCS#8 PrivateKeyInfo for private keys). */ |
397 | 740 | if (priv) { |
398 | 0 | isEdKey = (wc_Ed448PrivateKeyDecode(mem, &keyIdx, edKey, |
399 | 0 | (word32)memSz) == 0); |
400 | 0 | } |
401 | 740 | else { |
402 | 740 | isEdKey = (wc_Ed448PublicKeyDecode(mem, &keyIdx, edKey, |
403 | 740 | (word32)memSz) == 0); |
404 | 740 | } |
405 | | |
406 | 740 | if (!isEdKey) { |
407 | 740 | wolfSSL_ED448_free(edKey); |
408 | 740 | return WOLFSSL_FATAL_ERROR; |
409 | 740 | } |
410 | | |
411 | | /* Copy the consumed DER into pkey->pkey.ptr, unless the caller |
412 | | * pre-filled the EVP PKEY with the input bytes (d2i_evp_pkey()). |
413 | | * A reused key must be re-populated here. */ |
414 | 0 | if (!prePopulated) { |
415 | 0 | ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_ED448); |
416 | 0 | } |
417 | 0 | if (ret == 1) { |
418 | 0 | (*out)->ownEd448 = 1; |
419 | 0 | (*out)->ed448 = edKey; |
420 | 0 | } |
421 | 0 | else { |
422 | 0 | wolfSSL_ED448_free(edKey); |
423 | 0 | } |
424 | |
|
425 | 0 | return ret; |
426 | 740 | } |
427 | | #endif /* HAVE_ED448 */ |
428 | | |
429 | | /* Create a new EVP_PKEY from raw Ed25519 or Ed448 key material. |
430 | | * |
431 | | * Used for for callers who already have the raw key bytes and shouldn't need |
432 | | * to rewrap them in an SPKI just to decode. |
433 | | * |
434 | | * @param [in] type WC_EVP_PKEY_ED25519 or WC_EVP_PKEY_ED448. |
435 | | * @param [in] e Engine. Ignored; accepted for OpenSSL API parity. |
436 | | * @param [in] pub Raw public key bytes. |
437 | | * @param [in] len Length of pub. Must match the curve's public key size |
438 | | * (ED25519_PUB_KEY_SIZE or ED448_PUB_KEY_SIZE). |
439 | | * @return WOLFSSL_EVP_PKEY on success, NULL on failure. |
440 | | */ |
441 | | WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_raw_public_key(int type, |
442 | | WOLFSSL_ENGINE* e, const unsigned char* pub, size_t len) |
443 | 2 | { |
444 | 2 | WOLFSSL_EVP_PKEY* pkey; |
445 | 2 | int ok = 0; |
446 | | |
447 | 2 | (void)e; |
448 | 2 | WOLFSSL_ENTER("wolfSSL_EVP_PKEY_new_raw_public_key"); |
449 | | |
450 | 2 | if (pub == NULL || len == 0) { |
451 | 0 | return NULL; |
452 | 0 | } |
453 | | |
454 | 2 | pkey = wolfSSL_EVP_PKEY_new(); |
455 | 2 | if (pkey == NULL) { |
456 | 0 | return NULL; |
457 | 0 | } |
458 | | |
459 | 2 | switch (type) { |
460 | 0 | #if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT) |
461 | 1 | case WC_EVP_PKEY_ED25519: { |
462 | 1 | ed25519_key* edKey; |
463 | 1 | if (len != ED25519_PUB_KEY_SIZE) { |
464 | 1 | break; |
465 | 1 | } |
466 | 0 | edKey = wolfSSL_ED25519_new(pkey->heap, INVALID_DEVID); |
467 | 0 | if (edKey == NULL) { |
468 | 0 | break; |
469 | 0 | } |
470 | 0 | if (wc_ed25519_import_public(pub, (word32)len, edKey) != 0) { |
471 | 0 | wolfSSL_ED25519_free(edKey); |
472 | 0 | break; |
473 | 0 | } |
474 | 0 | pkey->type = WC_EVP_PKEY_ED25519; |
475 | 0 | pkey->ed25519 = edKey; |
476 | 0 | pkey->ownEd25519 = 1; |
477 | 0 | ok = 1; |
478 | 0 | break; |
479 | 0 | } |
480 | 0 | #endif |
481 | 0 | #if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT) |
482 | 1 | case WC_EVP_PKEY_ED448: { |
483 | 1 | ed448_key* edKey; |
484 | 1 | if (len != ED448_PUB_KEY_SIZE) { |
485 | 1 | break; |
486 | 1 | } |
487 | 0 | edKey = wolfSSL_ED448_new(pkey->heap, INVALID_DEVID); |
488 | 0 | if (edKey == NULL) { |
489 | 0 | break; |
490 | 0 | } |
491 | 0 | if (wc_ed448_import_public(pub, (word32)len, edKey) != 0) { |
492 | 0 | wolfSSL_ED448_free(edKey); |
493 | 0 | break; |
494 | 0 | } |
495 | 0 | pkey->type = WC_EVP_PKEY_ED448; |
496 | 0 | pkey->ed448 = edKey; |
497 | 0 | pkey->ownEd448 = 1; |
498 | 0 | ok = 1; |
499 | 0 | break; |
500 | 0 | } |
501 | 0 | #endif |
502 | 0 | #ifdef HAVE_CURVE25519 |
503 | 0 | case WC_EVP_PKEY_X25519: { |
504 | 0 | curve25519_key* cKey; |
505 | 0 | if (len != CURVE25519_PUB_KEY_SIZE) { |
506 | 0 | break; |
507 | 0 | } |
508 | 0 | cKey = (curve25519_key*)XMALLOC(sizeof(curve25519_key), pkey->heap, |
509 | 0 | DYNAMIC_TYPE_CURVE25519); |
510 | 0 | if (cKey == NULL) { |
511 | 0 | break; |
512 | 0 | } |
513 | 0 | if (wc_curve25519_init_ex(cKey, pkey->heap, INVALID_DEVID) != 0) { |
514 | 0 | XFREE(cKey, pkey->heap, DYNAMIC_TYPE_CURVE25519); |
515 | 0 | break; |
516 | 0 | } |
517 | | /* Raw X25519 keys are little-endian (RFC 7748). */ |
518 | 0 | if (wc_curve25519_import_public_ex(pub, (word32)len, cKey, |
519 | 0 | EC25519_LITTLE_ENDIAN) != 0) { |
520 | 0 | wc_curve25519_free(cKey); |
521 | 0 | XFREE(cKey, pkey->heap, DYNAMIC_TYPE_CURVE25519); |
522 | 0 | break; |
523 | 0 | } |
524 | 0 | pkey->type = WC_EVP_PKEY_X25519; |
525 | 0 | pkey->curve25519 = cKey; |
526 | 0 | pkey->ownCurve25519 = 1; |
527 | 0 | ok = 1; |
528 | 0 | break; |
529 | 0 | } |
530 | 0 | #endif |
531 | 0 | #ifdef HAVE_CURVE448 |
532 | 0 | case WC_EVP_PKEY_X448: { |
533 | 0 | curve448_key* cKey; |
534 | 0 | if (len != CURVE448_PUB_KEY_SIZE) { |
535 | 0 | break; |
536 | 0 | } |
537 | 0 | cKey = (curve448_key*)XMALLOC(sizeof(curve448_key), pkey->heap, |
538 | 0 | DYNAMIC_TYPE_CURVE448); |
539 | 0 | if (cKey == NULL) { |
540 | 0 | break; |
541 | 0 | } |
542 | 0 | if (wc_curve448_init_ex(cKey, pkey->heap, INVALID_DEVID) != 0) { |
543 | 0 | XFREE(cKey, pkey->heap, DYNAMIC_TYPE_CURVE448); |
544 | 0 | break; |
545 | 0 | } |
546 | | /* Raw X448 keys are little-endian (RFC 7748). */ |
547 | 0 | if (wc_curve448_import_public_ex(pub, (word32)len, cKey, |
548 | 0 | EC448_LITTLE_ENDIAN) != 0) { |
549 | 0 | wc_curve448_free(cKey); |
550 | 0 | XFREE(cKey, pkey->heap, DYNAMIC_TYPE_CURVE448); |
551 | 0 | break; |
552 | 0 | } |
553 | 0 | pkey->type = WC_EVP_PKEY_X448; |
554 | 0 | pkey->curve448 = cKey; |
555 | 0 | pkey->ownCurve448 = 1; |
556 | 0 | ok = 1; |
557 | 0 | break; |
558 | 0 | } |
559 | 0 | #endif |
560 | 0 | default: |
561 | 0 | break; |
562 | 2 | } |
563 | | |
564 | 2 | if (!ok) { |
565 | 2 | wolfSSL_EVP_PKEY_free(pkey); |
566 | 2 | return NULL; |
567 | 2 | } |
568 | | |
569 | | /* Stash the raw bytes so callers that later serialize the EVP_PKEY see |
570 | | * consistent state. */ |
571 | 0 | pkey->pkey.ptr = (char*)XMALLOC(len, pkey->heap, DYNAMIC_TYPE_PUBLIC_KEY); |
572 | 0 | if (pkey->pkey.ptr == NULL) { |
573 | 0 | wolfSSL_EVP_PKEY_free(pkey); |
574 | 0 | return NULL; |
575 | 0 | } |
576 | 0 | XMEMCPY(pkey->pkey.ptr, pub, len); |
577 | 0 | pkey->pkey_sz = (int)len; |
578 | |
|
579 | 0 | return pkey; |
580 | 0 | } |
581 | | |
582 | | /* Private-key counterpart to wolfSSL_EVP_PKEY_new_raw_public_key. The raw |
583 | | * input is the 32-byte seed (Ed25519) or 57-byte seed (Ed448). |
584 | | */ |
585 | | WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_raw_private_key(int type, |
586 | | WOLFSSL_ENGINE* e, const unsigned char* priv, size_t len) |
587 | 0 | { |
588 | 0 | WOLFSSL_EVP_PKEY* pkey; |
589 | 0 | int ok = 0; |
590 | |
|
591 | 0 | (void)e; |
592 | 0 | WOLFSSL_ENTER("wolfSSL_EVP_PKEY_new_raw_private_key"); |
593 | |
|
594 | 0 | if (priv == NULL || len == 0) { |
595 | 0 | return NULL; |
596 | 0 | } |
597 | | |
598 | 0 | pkey = wolfSSL_EVP_PKEY_new(); |
599 | 0 | if (pkey == NULL) { |
600 | 0 | return NULL; |
601 | 0 | } |
602 | | |
603 | 0 | switch (type) { |
604 | 0 | #if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT) |
605 | 0 | case WC_EVP_PKEY_ED25519: { |
606 | 0 | ed25519_key* edKey; |
607 | 0 | #ifdef HAVE_ED25519_MAKE_KEY |
608 | 0 | byte edPub[ED25519_PUB_KEY_SIZE]; |
609 | 0 | #endif |
610 | 0 | if (len != ED25519_KEY_SIZE) { |
611 | 0 | break; |
612 | 0 | } |
613 | 0 | edKey = wolfSSL_ED25519_new(pkey->heap, INVALID_DEVID); |
614 | 0 | if (edKey == NULL) { |
615 | 0 | break; |
616 | 0 | } |
617 | 0 | if (wc_ed25519_import_private_only(priv, (word32)len, edKey) |
618 | 0 | != 0) { |
619 | 0 | wolfSSL_ED25519_free(edKey); |
620 | 0 | break; |
621 | 0 | } |
622 | 0 | #ifdef HAVE_ED25519_MAKE_KEY |
623 | | /* The raw input is the seed alone, so the imported key has no |
624 | | * public half. Derive it (wc_ed25519_make_public stores it in the |
625 | | * key) so a key built this way is interchangeable with one decoded |
626 | | * from PKCS#8: i2d_PUBKEY, EVP_PKEY_cmp and signing all need it. */ |
627 | 0 | if (wc_ed25519_make_public(edKey, edPub, sizeof(edPub)) != 0) { |
628 | 0 | wolfSSL_ED25519_free(edKey); |
629 | 0 | break; |
630 | 0 | } |
631 | 0 | #endif |
632 | 0 | pkey->type = WC_EVP_PKEY_ED25519; |
633 | 0 | pkey->ed25519 = edKey; |
634 | 0 | pkey->ownEd25519 = 1; |
635 | 0 | ok = 1; |
636 | 0 | break; |
637 | 0 | } |
638 | 0 | #endif |
639 | 0 | #if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT) |
640 | 0 | case WC_EVP_PKEY_ED448: { |
641 | 0 | ed448_key* edKey; |
642 | 0 | if (len != ED448_KEY_SIZE) { |
643 | 0 | break; |
644 | 0 | } |
645 | 0 | edKey = wolfSSL_ED448_new(pkey->heap, INVALID_DEVID); |
646 | 0 | if (edKey == NULL) { |
647 | 0 | break; |
648 | 0 | } |
649 | 0 | if (wc_ed448_import_private_only(priv, (word32)len, edKey) != 0) { |
650 | 0 | wolfSSL_ED448_free(edKey); |
651 | 0 | break; |
652 | 0 | } |
653 | 0 | pkey->type = WC_EVP_PKEY_ED448; |
654 | 0 | pkey->ed448 = edKey; |
655 | 0 | pkey->ownEd448 = 1; |
656 | 0 | ok = 1; |
657 | 0 | break; |
658 | 0 | } |
659 | 0 | #endif |
660 | 0 | #ifdef HAVE_CURVE25519 |
661 | 0 | case WC_EVP_PKEY_X25519: { |
662 | 0 | curve25519_key* cKey; |
663 | 0 | if (len != CURVE25519_KEYSIZE) { |
664 | 0 | break; |
665 | 0 | } |
666 | 0 | cKey = (curve25519_key*)XMALLOC(sizeof(curve25519_key), pkey->heap, |
667 | 0 | DYNAMIC_TYPE_CURVE25519); |
668 | 0 | if (cKey == NULL) { |
669 | 0 | break; |
670 | 0 | } |
671 | 0 | if (wc_curve25519_init_ex(cKey, pkey->heap, INVALID_DEVID) != 0) { |
672 | 0 | XFREE(cKey, pkey->heap, DYNAMIC_TYPE_CURVE25519); |
673 | 0 | break; |
674 | 0 | } |
675 | 0 | #ifdef WOLFSSL_CURVE25519_BLINDING |
676 | | /* Use the EVP_PKEY's RNG for scalar blinding on shared-secret. */ |
677 | 0 | (void)wc_curve25519_set_rng(cKey, &pkey->rng); |
678 | 0 | #endif |
679 | | /* Raw X25519 keys are little-endian (RFC 7748). */ |
680 | 0 | if (wc_curve25519_import_private_ex(priv, (word32)len, cKey, |
681 | 0 | EC25519_LITTLE_ENDIAN) != 0) { |
682 | 0 | wc_curve25519_free(cKey); |
683 | 0 | XFREE(cKey, pkey->heap, DYNAMIC_TYPE_CURVE25519); |
684 | 0 | break; |
685 | 0 | } |
686 | 0 | pkey->type = WC_EVP_PKEY_X25519; |
687 | 0 | pkey->curve25519 = cKey; |
688 | 0 | pkey->ownCurve25519 = 1; |
689 | 0 | ok = 1; |
690 | 0 | break; |
691 | 0 | } |
692 | 0 | #endif |
693 | 0 | #ifdef HAVE_CURVE448 |
694 | 0 | case WC_EVP_PKEY_X448: { |
695 | 0 | curve448_key* cKey; |
696 | 0 | if (len != CURVE448_KEY_SIZE) { |
697 | 0 | break; |
698 | 0 | } |
699 | 0 | cKey = (curve448_key*)XMALLOC(sizeof(curve448_key), pkey->heap, |
700 | 0 | DYNAMIC_TYPE_CURVE448); |
701 | 0 | if (cKey == NULL) { |
702 | 0 | break; |
703 | 0 | } |
704 | 0 | if (wc_curve448_init_ex(cKey, pkey->heap, INVALID_DEVID) != 0) { |
705 | 0 | XFREE(cKey, pkey->heap, DYNAMIC_TYPE_CURVE448); |
706 | 0 | break; |
707 | 0 | } |
708 | | /* Raw X448 keys are little-endian (RFC 7748). */ |
709 | 0 | if (wc_curve448_import_private_ex(priv, (word32)len, cKey, |
710 | 0 | EC448_LITTLE_ENDIAN) != 0) { |
711 | 0 | wc_curve448_free(cKey); |
712 | 0 | XFREE(cKey, pkey->heap, DYNAMIC_TYPE_CURVE448); |
713 | 0 | break; |
714 | 0 | } |
715 | 0 | pkey->type = WC_EVP_PKEY_X448; |
716 | 0 | pkey->curve448 = cKey; |
717 | 0 | pkey->ownCurve448 = 1; |
718 | 0 | ok = 1; |
719 | 0 | break; |
720 | 0 | } |
721 | 0 | #endif |
722 | 0 | default: |
723 | 0 | break; |
724 | 0 | } |
725 | | |
726 | 0 | if (!ok) { |
727 | 0 | wolfSSL_EVP_PKEY_free(pkey); |
728 | 0 | return NULL; |
729 | 0 | } |
730 | | |
731 | 0 | pkey->pkey.ptr = (char*)XMALLOC(len, pkey->heap, DYNAMIC_TYPE_PUBLIC_KEY); |
732 | 0 | if (pkey->pkey.ptr == NULL) { |
733 | 0 | wolfSSL_EVP_PKEY_free(pkey); |
734 | 0 | return NULL; |
735 | 0 | } |
736 | 0 | XMEMCPY(pkey->pkey.ptr, priv, len); |
737 | 0 | pkey->pkey_sz = (int)len; |
738 | |
|
739 | 0 | return pkey; |
740 | 0 | } |
741 | | |
742 | | #if !defined(NO_DSA) |
743 | | /** |
744 | | * Try to make a DSA EVP PKEY from data. |
745 | | * |
746 | | * @param [in, out] out On in, an EVP PKEY or NULL. |
747 | | * On out, an EVP PKEY or NULL. |
748 | | * @param [in] mem Memory containing key data. |
749 | | * @param [in] memSz Size of key data in bytes. |
750 | | * @param [in] priv 1 means private key, 0 means public key. |
751 | | * @return 1 on success. |
752 | | * @return 0 when input was recognized as this key type but |
753 | | * object creation/import failed. |
754 | | * @return WOLFSSL_FATAL_ERROR when input is not this key type. |
755 | | */ |
756 | | static int d2iTryDsaKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, |
757 | | long memSz, int priv) |
758 | | { |
759 | | WOLFSSL_DSA* dsaObj; |
760 | | word32 keyIdx = 0; |
761 | | int isDsaKey; |
762 | | int ret = 1; |
763 | | WC_DECLARE_VAR(dsa, DsaKey, 1, NULL); |
764 | | |
765 | | WC_ALLOC_VAR_EX(dsa, DsaKey, 1, NULL, DYNAMIC_TYPE_DSA, return 0); |
766 | | |
767 | | XMEMSET(dsa, 0, sizeof(DsaKey)); |
768 | | |
769 | | if (wc_InitDsaKey(dsa) != 0) { |
770 | | WC_FREE_VAR_EX(dsa, NULL, DYNAMIC_TYPE_DSA); |
771 | | return 0; |
772 | | } |
773 | | |
774 | | /* Try decoding data as a DSA private/public key. */ |
775 | | if (priv) { |
776 | | isDsaKey = |
777 | | (wc_DsaPrivateKeyDecode(mem, &keyIdx, dsa, (word32)memSz) == 0); |
778 | | } |
779 | | else { |
780 | | isDsaKey = |
781 | | (wc_DsaPublicKeyDecode(mem, &keyIdx, dsa, (word32)memSz) == 0); |
782 | | } |
783 | | wc_FreeDsaKey(dsa); |
784 | | WC_FREE_VAR_EX(dsa, NULL, DYNAMIC_TYPE_DSA); |
785 | | |
786 | | /* test if DSA key */ |
787 | | if (!isDsaKey) { |
788 | | return WOLFSSL_FATAL_ERROR; |
789 | | } |
790 | | |
791 | | /* Create DSA key object from data. */ |
792 | | dsaObj = wolfSSL_DSA_new(); |
793 | | if (dsaObj == NULL) { |
794 | | ret = 0; |
795 | | } |
796 | | if ((ret == 1) && (wolfSSL_DSA_LoadDer_ex(dsaObj, mem, keyIdx, |
797 | | priv ? WOLFSSL_RSA_LOAD_PRIVATE : WOLFSSL_RSA_LOAD_PUBLIC) != 1)) { |
798 | | ret = 0; |
799 | | } |
800 | | if (ret == 1) { |
801 | | /* Create an EVP PKEY object. */ |
802 | | ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_DSA); |
803 | | } |
804 | | if (ret == 1) { |
805 | | /* Put RSA key object into EVP PKEY object. */ |
806 | | (*out)->ownDsa = 1; |
807 | | (*out)->dsa = dsaObj; |
808 | | } |
809 | | if (ret == 0) { |
810 | | wolfSSL_DSA_free(dsaObj); |
811 | | } |
812 | | |
813 | | return ret; |
814 | | } |
815 | | #endif /* NO_DSA */ |
816 | | |
817 | | #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) |
818 | | #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ |
819 | | (HAVE_FIPS_VERSION > 2)) |
820 | | /** |
821 | | * Try to make a DH EVP PKEY from data. |
822 | | * |
823 | | * @param [in, out] out On in, an EVP PKEY or NULL. |
824 | | * On out, an EVP PKEY or NULL. |
825 | | * @param [in] mem Memory containing key data. |
826 | | * @param [in] memSz Size of key data in bytes. |
827 | | * @param [in] priv 1 means private key, 0 means public key. |
828 | | * @return 1 on success. |
829 | | * @return 0 when input was recognized as this key type but |
830 | | * object creation/import failed. |
831 | | * @return WOLFSSL_FATAL_ERROR when input is not this key type. |
832 | | */ |
833 | | static int d2iTryDhKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, |
834 | | long memSz, int priv) |
835 | 1.42k | { |
836 | 1.42k | WOLFSSL_DH* dhObj; |
837 | 1.42k | int isDhKey; |
838 | 1.42k | word32 keyIdx = 0; |
839 | 1.42k | int ret = 1; |
840 | 1.42k | WC_DECLARE_VAR(dh, DhKey, 1, NULL); |
841 | | |
842 | 1.42k | WC_ALLOC_VAR_EX(dh, DhKey, 1, NULL, DYNAMIC_TYPE_DH, return 0); |
843 | | |
844 | 1.42k | XMEMSET(dh, 0, sizeof(DhKey)); |
845 | | |
846 | 1.42k | if (wc_InitDhKey(dh) != 0) { |
847 | 0 | WC_FREE_VAR_EX(dh, NULL, DYNAMIC_TYPE_DH); |
848 | 0 | return 0; |
849 | 0 | } |
850 | | |
851 | | /* Try decoding data as a DH public key. */ |
852 | 1.42k | isDhKey = (wc_DhKeyDecode(mem, &keyIdx, dh, (word32)memSz) == 0); |
853 | 1.42k | wc_FreeDhKey(dh); |
854 | 1.42k | WC_FREE_VAR_EX(dh, NULL, DYNAMIC_TYPE_DH); |
855 | | |
856 | | /* test if DH key */ |
857 | 1.42k | if (!isDhKey) { |
858 | 740 | return WOLFSSL_FATAL_ERROR; |
859 | 740 | } |
860 | | |
861 | | /* Create DH key object from data. */ |
862 | 689 | dhObj = wolfSSL_DH_new(); |
863 | 689 | if (dhObj == NULL) { |
864 | 0 | ret = 0; |
865 | 0 | } |
866 | 689 | if ((ret == 1) && (wolfSSL_DH_LoadDer(dhObj, mem, keyIdx) != 1)) { |
867 | 474 | ret = 0; |
868 | 474 | } |
869 | 689 | if (ret == 1) { |
870 | | /* Create an EVP PKEY object. */ |
871 | 215 | ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_DH); |
872 | 215 | } |
873 | 689 | if (ret == 1) { |
874 | | /* Put RSA key object into EVP PKEY object. */ |
875 | 215 | (*out)->ownDh = 1; |
876 | 215 | (*out)->dh = dhObj; |
877 | 215 | } |
878 | 689 | if (ret == 0) { |
879 | 474 | wolfSSL_DH_free(dhObj); |
880 | 474 | } |
881 | | |
882 | 689 | return ret; |
883 | 1.42k | } |
884 | | #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ |
885 | | #endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */ |
886 | | |
887 | | #if !defined(NO_DH) && defined(OPENSSL_EXTRA) && defined(WOLFSSL_DH_EXTRA) |
888 | | #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ |
889 | | (HAVE_FIPS_VERSION > 2)) |
890 | | /** |
891 | | * Try to make a DH EVP PKEY from data. |
892 | | * |
893 | | * @param [in, out] out On in, an EVP PKEY or NULL. |
894 | | * On out, an EVP PKEY or NULL. |
895 | | * @param [in] mem Memory containing key data. |
896 | | * @param [in] memSz Size of key data in bytes. |
897 | | * @param [in] priv 1 means private key, 0 means public key. |
898 | | * @return 1 on success. |
899 | | * @return 0 when input was recognized as this key type but |
900 | | * object creation/import failed. |
901 | | * @return WOLFSSL_FATAL_ERROR when input is not this key type. |
902 | | */ |
903 | | static int d2iTryAltDhKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, |
904 | | long memSz, int priv) |
905 | 740 | { |
906 | 740 | WOLFSSL_DH* dhObj = NULL; |
907 | 740 | word32 keyIdx = 0; |
908 | 740 | DhKey* key = NULL; |
909 | 740 | int elements; |
910 | 740 | int ret = 1; |
911 | | |
912 | | /* Create DH key object from data. */ |
913 | 740 | dhObj = wolfSSL_DH_new(); |
914 | 740 | if (dhObj == NULL) { |
915 | 0 | ret = WOLFSSL_FATAL_ERROR; |
916 | 0 | } |
917 | | |
918 | 740 | if (ret == 1) { |
919 | 740 | key = (DhKey*)dhObj->internal; |
920 | | /* Try decoding data as a DH public key. */ |
921 | 740 | if (wc_DhKeyDecode(mem, &keyIdx, key, (word32)memSz) != 0) { |
922 | 740 | ret = WOLFSSL_FATAL_ERROR; |
923 | 740 | } |
924 | 740 | } |
925 | 740 | if (ret == 1) { |
926 | | /* DH key has data and is external to DH object. */ |
927 | 0 | elements = ELEMENT_P | ELEMENT_G | ELEMENT_Q | ELEMENT_PUB; |
928 | 0 | if (priv) { |
929 | 0 | elements |= ELEMENT_PRV; |
930 | 0 | } |
931 | 0 | if (SetDhExternal_ex(dhObj, elements) != WOLFSSL_SUCCESS) { |
932 | 0 | ret = 0; |
933 | 0 | } |
934 | 0 | } |
935 | 740 | if (ret == 1) { |
936 | | /* Create an EVP PKEY object. */ |
937 | 0 | ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_DH); |
938 | 0 | } |
939 | 740 | if (ret == 1) { |
940 | | /* Put DH key object into EVP PKEY object. */ |
941 | 0 | (*out)->ownDh = 1; |
942 | 0 | (*out)->dh = dhObj; |
943 | 0 | } |
944 | 740 | else if (dhObj != NULL) { |
945 | 740 | wolfSSL_DH_free(dhObj); |
946 | 740 | } |
947 | | |
948 | 740 | return ret; |
949 | 740 | } |
950 | | #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ |
951 | | #endif /* !NO_DH && OPENSSL_EXTRA && WOLFSSL_DH_EXTRA */ |
952 | | |
953 | | #ifdef HAVE_FALCON |
954 | | /** |
955 | | * Attempt to import a private Falcon key at a specified level. |
956 | | * |
957 | | * @param [in] falcon Falcon key object. |
958 | | * @param [in] level Level of Falcon key. |
959 | | * @param [in] mem Memory containing key data. |
960 | | * @param [in] memSz Size of key data in bytes. |
961 | | * @return 1 on success. |
962 | | * @return 0 otherwise. |
963 | | */ |
964 | | static int d2i_falcon_priv_key_level(falcon_key* falcon, byte level, |
965 | | const unsigned char* mem, long memSz) |
966 | | { |
967 | | word32 idx = 0; |
968 | | return (wc_falcon_set_level(falcon, level) == 0) && |
969 | | (wc_Falcon_PrivateKeyDecode(mem, &idx, falcon, |
970 | | (word32)memSz) == 0); |
971 | | } |
972 | | |
973 | | /** |
974 | | * Attempt to import a public Falcon key at a specified level. |
975 | | * |
976 | | * @param [in] falcon Falcon key object. |
977 | | * @param [in] level Level of Falcon key. |
978 | | * @param [in] mem Memory containing key data. |
979 | | * @param [in] memSz Size of key data in bytes. |
980 | | * @return 1 on success. |
981 | | * @return 0 otherwise. |
982 | | */ |
983 | | static int d2i_falcon_pub_key_level(falcon_key* falcon, byte level, |
984 | | const unsigned char* mem, long memSz) |
985 | | { |
986 | | return (wc_falcon_set_level(falcon, level) == 0) && |
987 | | (wc_falcon_import_public(mem, (word32)memSz, falcon) == 0); |
988 | | } |
989 | | |
990 | | /** |
991 | | * Try to make a Falcon EVP PKEY from data. |
992 | | * |
993 | | * @param [in, out] out On in, an EVP PKEY or NULL. |
994 | | * On out, an EVP PKEY or NULL. |
995 | | * @param [in] mem Memory containing key data. |
996 | | * @param [in] memSz Size of key data in bytes. |
997 | | * @param [in] priv 1 means private key, 0 means public key. |
998 | | * @return 1 on success. |
999 | | * @return 0 when input was recognized as this key type but |
1000 | | * object creation/import failed. |
1001 | | * @return WOLFSSL_FATAL_ERROR when input is not this key type. |
1002 | | */ |
1003 | | static int d2iTryFalconKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, |
1004 | | long memSz, int priv) |
1005 | | { |
1006 | | int isFalcon = 0; |
1007 | | WC_DECLARE_VAR(falcon, falcon_key, 1, NULL); |
1008 | | |
1009 | | WC_ALLOC_VAR_EX(falcon, falcon_key, 1, NULL, DYNAMIC_TYPE_FALCON, |
1010 | | return 0); |
1011 | | |
1012 | | if (wc_falcon_init(falcon) != 0) { |
1013 | | WC_FREE_VAR_EX(falcon, NULL, DYNAMIC_TYPE_FALCON); |
1014 | | return 0; |
1015 | | } |
1016 | | |
1017 | | /* Try decoding data as a Falcon private/public key. */ |
1018 | | if (priv) { |
1019 | | /* Try level 1 */ |
1020 | | isFalcon = d2i_falcon_priv_key_level(falcon, 1, mem, memSz); |
1021 | | if (!isFalcon) { |
1022 | | /* Try level 5 */ |
1023 | | isFalcon = d2i_falcon_priv_key_level(falcon, 5, mem, memSz); |
1024 | | } |
1025 | | } |
1026 | | else { |
1027 | | /* Try level 1 */ |
1028 | | isFalcon = d2i_falcon_pub_key_level(falcon, 1, mem, memSz); |
1029 | | if (!isFalcon) { |
1030 | | /* Try level 5 */ |
1031 | | isFalcon = d2i_falcon_pub_key_level(falcon, 5, mem, memSz); |
1032 | | } |
1033 | | } |
1034 | | /* Dispose of any Falcon key created. */ |
1035 | | wc_falcon_free(falcon); |
1036 | | WC_FREE_VAR_EX(falcon, NULL, DYNAMIC_TYPE_FALCON); |
1037 | | |
1038 | | if (!isFalcon) { |
1039 | | return WOLFSSL_FATAL_ERROR; |
1040 | | } |
1041 | | |
1042 | | /* Create an EVP PKEY object. */ |
1043 | | return d2i_make_pkey(out, NULL, 0, priv, WC_EVP_PKEY_FALCON); |
1044 | | } |
1045 | | #endif /* HAVE_FALCON */ |
1046 | | |
1047 | | #ifdef WOLFSSL_HAVE_MLDSA |
1048 | | /** |
1049 | | * Try to make an ML-DSA EVP PKEY from data. |
1050 | | * |
1051 | | * Accepts either raw key bytes or DER (PKCS#8 / SPKI). Raw bytes are |
1052 | | * size-keyed, so each level is tried in turn. DER input is decoded once, |
1053 | | * letting the decoder auto-detect the level from the OID. |
1054 | | * |
1055 | | * Under WOLFSSL_MLDSA_NO_ASN1 there is no PKCS#8 decoder, so a DER private |
1056 | | * key is always treated as not this key type; only raw bytes are accepted. |
1057 | | * |
1058 | | * @param [in, out] out On in, an EVP PKEY or NULL. |
1059 | | * On out, an EVP PKEY or NULL. |
1060 | | * @param [in] mem Memory containing key data. |
1061 | | * @param [in] memSz Size of key data in bytes. |
1062 | | * @param [in] priv 1 means private key, 0 means public key. |
1063 | | * @param [in] prePopulated 1 means *out already holds the input bytes |
1064 | | * so the d2i_make_pkey allocate/copy is skipped. |
1065 | | * @param [in] allowRaw 1 means size-keyed raw key bytes are accepted |
1066 | | * in addition to DER (auto-detect path only). |
1067 | | * @return 1 on success. |
1068 | | * @return 0 when input was recognized as this key type but |
1069 | | * object creation/import failed. |
1070 | | * @return WOLFSSL_FATAL_ERROR when input is not this key type. |
1071 | | */ |
1072 | | static int d2iTryMlDsaKey(WOLFSSL_EVP_PKEY** out, const unsigned char* mem, |
1073 | | long memSz, int priv, int prePopulated, int allowRaw) |
1074 | | { |
1075 | | static const byte levels[] = { WC_ML_DSA_44, WC_ML_DSA_65, WC_ML_DSA_87 }; |
1076 | | word32 inSz = (word32)memSz; |
1077 | | word32 keyIdx = 0; |
1078 | | int isMlDsa = 0; |
1079 | | int i, numLevels, rc; |
1080 | | int oidSum = 0; |
1081 | | int ret; |
1082 | | WC_DECLARE_VAR(mldsa, wc_MlDsaKey, 1, NULL); |
1083 | | |
1084 | | #if !defined(WOLFSSL_MLDSA_PRIVATE_KEY) |
1085 | | if (priv) { |
1086 | | return WOLFSSL_FATAL_ERROR; |
1087 | | } |
1088 | | #endif |
1089 | | |
1090 | | WC_ALLOC_VAR_EX(mldsa, wc_MlDsaKey, 1, NULL, DYNAMIC_TYPE_MLDSA, |
1091 | | return 0); |
1092 | | |
1093 | | if (wc_MlDsaKey_Init(mldsa, NULL, INVALID_DEVID) != 0) { |
1094 | | WC_FREE_VAR_EX(mldsa, NULL, DYNAMIC_TYPE_MLDSA); |
1095 | | return 0; |
1096 | | } |
1097 | | |
1098 | | /* Raw key bytes are size-keyed, try each level. Only the auto-detect |
1099 | | * path accepts raw bytes; the typed d2i entry points are DER APIs. */ |
1100 | | numLevels = allowRaw ? (int)(sizeof(levels) / sizeof(levels[0])) : 0; |
1101 | | for (i = 0; i < numLevels && !isMlDsa; i++) { |
1102 | | if (wc_MlDsaKey_SetParams(mldsa, levels[i]) != 0) { |
1103 | | continue; |
1104 | | } |
1105 | | #if defined(WOLFSSL_MLDSA_PRIVATE_KEY) |
1106 | | if (priv) { |
1107 | | rc = wc_MlDsaKey_ImportPrivRaw(mldsa, mem, inSz); |
1108 | | } |
1109 | | else |
1110 | | #endif |
1111 | | { |
1112 | | rc = wc_MlDsaKey_ImportPubRaw(mldsa, mem, inSz); |
1113 | | } |
1114 | | if (rc == 0) { |
1115 | | isMlDsa = 1; |
1116 | | } |
1117 | | } |
1118 | | |
1119 | | /* DER input includes auto level detection */ |
1120 | | if (!isMlDsa) { |
1121 | | wc_MlDsaKey_Free(mldsa); |
1122 | | if (wc_MlDsaKey_Init(mldsa, NULL, INVALID_DEVID) != 0) { |
1123 | | WC_FREE_VAR_EX(mldsa, NULL, DYNAMIC_TYPE_MLDSA); |
1124 | | return 0; |
1125 | | } |
1126 | | #if defined(WOLFSSL_MLDSA_PRIVATE_KEY) && !defined(WOLFSSL_MLDSA_NO_ASN1) |
1127 | | if (priv) { |
1128 | | rc = wc_MlDsaKey_PrivateKeyDecode(mldsa, mem, inSz, &keyIdx); |
1129 | | } |
1130 | | else |
1131 | | #elif defined(WOLFSSL_MLDSA_PRIVATE_KEY) && defined(WOLFSSL_MLDSA_NO_ASN1) |
1132 | | if (priv) { |
1133 | | /* No PrivateKeyDecode without ASN.1 support. */ |
1134 | | rc = NOT_COMPILED_IN; |
1135 | | } |
1136 | | else |
1137 | | #endif |
1138 | | { |
1139 | | rc = wc_MlDsaKey_PublicKeyDecode(mldsa, mem, inSz, &keyIdx); |
1140 | | } |
1141 | | if (rc == 0) { |
1142 | | isMlDsa = 1; |
1143 | | } |
1144 | | } |
1145 | | |
1146 | | if (isMlDsa) { |
1147 | | /* Level is already known from the successful import/decode above - |
1148 | | * grab the OID now so callers don't need to re-decode the key |
1149 | | * later just to recover it (e.g. wolfSSL_X509_verify()). */ |
1150 | | int keyFormat = 0; |
1151 | | if (mldsa_get_oid_sum(mldsa, &keyFormat) == 0) { |
1152 | | oidSum = keyFormat; |
1153 | | } |
1154 | | } |
1155 | | |
1156 | | wc_MlDsaKey_Free(mldsa); |
1157 | | WC_FREE_VAR_EX(mldsa, NULL, DYNAMIC_TYPE_MLDSA); |
1158 | | |
1159 | | if (!isMlDsa) { |
1160 | | return WOLFSSL_FATAL_ERROR; |
1161 | | } |
1162 | | |
1163 | | /* Copy the consumed DER into pkey->pkey.ptr, unless the caller |
1164 | | * pre-filled the EVP PKEY with the input bytes (d2i_evp_pkey()). |
1165 | | * A reused key must be re-populated here. */ |
1166 | | ret = 1; |
1167 | | if (!prePopulated) { |
1168 | | ret = d2i_make_pkey(out, mem, keyIdx, priv, WC_EVP_PKEY_DILITHIUM); |
1169 | | } |
1170 | | if ((ret == 1) && (out != NULL) && (*out != NULL) && (oidSum != 0)) { |
1171 | | WOLFSSL_ATOMIC_STORE((*out)->mldsaOID, oidSum); |
1172 | | } |
1173 | | return ret; |
1174 | | } |
1175 | | #endif /* WOLFSSL_HAVE_MLDSA */ |
1176 | | |
1177 | | /** |
1178 | | * Try to make a WOLFSSL_EVP_PKEY from data. |
1179 | | * |
1180 | | * @param [in, out] out On in, an EVP PKEY or NULL. |
1181 | | * On out, an EVP PKEY or NULL. |
1182 | | * @param [in] mem Memory containing key data. |
1183 | | * @param [in] memSz Size of key data in bytes. |
1184 | | * @param [in] priv 1 means private key, 0 means public key. |
1185 | | * @return Non-NULL WOLFSSL_EVP_PKEY* on success. |
1186 | | * @return NULL on bad arguments or unrecognized input type. |
1187 | | */ |
1188 | | static WOLFSSL_EVP_PKEY* d2i_evp_pkey_try(WOLFSSL_EVP_PKEY** out, |
1189 | | const unsigned char** in, long inSz, int priv) |
1190 | | { |
1191 | | WOLFSSL_EVP_PKEY* pkey = NULL; |
1192 | | int found = 0; |
1193 | | |
1194 | | WOLFSSL_ENTER("d2i_evp_pkey_try"); |
1195 | | |
1196 | | if (in == NULL || *in == NULL || inSz < 0) { |
1197 | | WOLFSSL_MSG("Bad argument"); |
1198 | | return NULL; |
1199 | | } |
1200 | | |
1201 | | if ((out != NULL) && (*out != NULL)) { |
1202 | | pkey = *out; |
1203 | | } |
1204 | | |
1205 | | #if !defined(NO_RSA) |
1206 | | if (d2iTryRsaKey(&pkey, *in, inSz, priv) >= 0) { |
1207 | | found = 1; |
1208 | | } |
1209 | | else |
1210 | | #endif /* NO_RSA */ |
1211 | | #if defined(HAVE_ECC) && defined(OPENSSL_EXTRA) |
1212 | | if (d2iTryEccKey(&pkey, *in, inSz, priv) >= 0) { |
1213 | | found = 1; |
1214 | | } |
1215 | | else |
1216 | | #endif /* HAVE_ECC && OPENSSL_EXTRA */ |
1217 | | #if !defined(NO_DSA) |
1218 | | if (d2iTryDsaKey(&pkey, *in, inSz, priv) >= 0) { |
1219 | | found = 1; |
1220 | | } |
1221 | | else |
1222 | | #endif /* NO_DSA */ |
1223 | | #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) |
1224 | | #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ |
1225 | | (HAVE_FIPS_VERSION > 2)) |
1226 | | if (d2iTryDhKey(&pkey, *in, inSz, priv) >= 0) { |
1227 | | found = 1; |
1228 | | } |
1229 | | else |
1230 | | #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ |
1231 | | #endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */ |
1232 | | |
1233 | | #if !defined(NO_DH) && defined(OPENSSL_EXTRA) && defined(WOLFSSL_DH_EXTRA) |
1234 | | #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ |
1235 | | (HAVE_FIPS_VERSION > 2)) |
1236 | | if (d2iTryAltDhKey(&pkey, *in, inSz, priv) >= 0) { |
1237 | | found = 1; |
1238 | | } |
1239 | | else |
1240 | | #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ |
1241 | | #endif /* !NO_DH && OPENSSL_EXTRA && WOLFSSL_DH_EXTRA */ |
1242 | | |
1243 | | #if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT) |
1244 | | if (d2iTryEd25519Key(&pkey, *in, inSz, priv, 0) >= 0) { |
1245 | | found = 1; |
1246 | | } |
1247 | | else |
1248 | | #endif /* HAVE_ED25519 && HAVE_ED25519_KEY_IMPORT */ |
1249 | | #if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT) |
1250 | | if (d2iTryEd448Key(&pkey, *in, inSz, priv, 0) >= 0) { |
1251 | | found = 1; |
1252 | | } |
1253 | | else |
1254 | | #endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT */ |
1255 | | #ifdef HAVE_FALCON |
1256 | | if (d2iTryFalconKey(&pkey, *in, inSz, priv) >= 0) { |
1257 | | found = 1; |
1258 | | } |
1259 | | else |
1260 | | #endif /* HAVE_FALCON */ |
1261 | | #ifdef WOLFSSL_HAVE_MLDSA |
1262 | | if (d2iTryMlDsaKey(&pkey, *in, inSz, priv, 0, 1) >= 0) { |
1263 | | found = 1; |
1264 | | } |
1265 | | else |
1266 | | #endif /* WOLFSSL_HAVE_MLDSA */ |
1267 | | { |
1268 | | WOLFSSL_MSG("d2i_evp_pkey_try couldn't determine key type"); |
1269 | | } |
1270 | | |
1271 | | if (!found) { |
1272 | | return NULL; |
1273 | | } |
1274 | | |
1275 | | if ((pkey != NULL) && (out != NULL)) { |
1276 | | *out = pkey; |
1277 | | } |
1278 | | return pkey; |
1279 | | } |
1280 | | #endif /* OPENSSL_EXTRA || WPA_SMALL */ |
1281 | | |
1282 | | #ifdef OPENSSL_EXTRA |
1283 | | /* Converts a DER encoded public key to a WOLFSSL_EVP_PKEY structure. |
1284 | | * |
1285 | | * @param [in, out] out Pointer to new WOLFSSL_EVP_PKEY structure. |
1286 | | * Can be NULL. |
1287 | | * @param [in, out] in DER buffer to convert. |
1288 | | * @param [in] inSz Size of in buffer. |
1289 | | * @return Pointer to a new WOLFSSL_EVP_PKEY structure on success. |
1290 | | * @return NULL on failure. *out is left unchanged on failure; caller |
1291 | | * retains ownership of any pre-existing key passed via *out. |
1292 | | */ |
1293 | | WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY(WOLFSSL_EVP_PKEY** out, |
1294 | | const unsigned char** in, long inSz) |
1295 | 1.53k | { |
1296 | 1.53k | WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY"); |
1297 | 1.53k | return d2i_evp_pkey_try(out, in, inSz, 0); |
1298 | 1.53k | } |
1299 | | |
1300 | | #ifndef NO_BIO |
1301 | | /* Converts a DER encoded public key in a BIO to a WOLFSSL_EVP_PKEY structure. |
1302 | | * |
1303 | | * @param [in] bio BIO to read DER from. |
1304 | | * @param [out] out New WOLFSSL_EVP_PKEY pointer when not NULL. |
1305 | | * @return Pointer to a new WOLFSSL_EVP_PKEY structure on success. |
1306 | | * @return NULL on failure. |
1307 | | */ |
1308 | | WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio, |
1309 | | WOLFSSL_EVP_PKEY** out) |
1310 | 0 | { |
1311 | 0 | unsigned char* mem; |
1312 | 0 | long memSz; |
1313 | 0 | WOLFSSL_EVP_PKEY* pkey = NULL; |
1314 | |
|
1315 | 0 | WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY_bio"); |
1316 | | |
1317 | | /* Validate parameters. */ |
1318 | 0 | if (bio == NULL) { |
1319 | 0 | return NULL; |
1320 | 0 | } |
1321 | | |
1322 | | /* Get length of data in BIO. */ |
1323 | 0 | memSz = wolfSSL_BIO_get_len(bio); |
1324 | 0 | if (memSz <= 0) { |
1325 | 0 | return NULL; |
1326 | 0 | } |
1327 | | /* Allocate memory to read all of BIO data into. */ |
1328 | 0 | mem = (unsigned char*)XMALLOC((size_t)memSz, bio->heap, |
1329 | 0 | DYNAMIC_TYPE_TMP_BUFFER); |
1330 | 0 | if (mem == NULL) { |
1331 | 0 | return NULL; |
1332 | 0 | } |
1333 | | /* Read all data into allocated buffer. */ |
1334 | 0 | if (wolfSSL_BIO_read(bio, mem, (int)memSz) == memSz) { |
1335 | | /* Create a WOLFSSL_EVP_PKEY from data. */ |
1336 | 0 | pkey = wolfSSL_d2i_PUBKEY(NULL, (const unsigned char**)&mem, memSz); |
1337 | 0 | if (out != NULL && pkey != NULL) { |
1338 | | /* Return new WOLFSSL_EVP_PKEY through parameter. */ |
1339 | 0 | *out = pkey; |
1340 | 0 | } |
1341 | 0 | } |
1342 | | |
1343 | | /* Dispose of memory holding BIO data. */ |
1344 | 0 | XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); |
1345 | 0 | return pkey; |
1346 | 0 | } |
1347 | | #endif /* !NO_BIO */ |
1348 | | #endif /* OPENSSL_EXTRA */ |
1349 | | |
1350 | | #if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || \ |
1351 | | defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX) || \ |
1352 | | defined(WOLFSSL_QT) || defined(WOLFSSL_WPAS_SMALL) |
1353 | | /* Converts a DER encoded private key to a WOLFSSL_EVP_PKEY structure. |
1354 | | * |
1355 | | * @param [in, out] out Pointer to new WOLFSSL_EVP_PKEY structure. |
1356 | | * Can be NULL. |
1357 | | * @param [in, out] in DER buffer to convert. |
1358 | | * @param [in] inSz Size of in buffer. |
1359 | | * @return Pointer to a new WOLFSSL_EVP_PKEY structure on success. |
1360 | | * @return NULL on failure. *out is left unchanged on failure; caller |
1361 | | * retains ownership of any pre-existing key passed via *out. |
1362 | | */ |
1363 | | WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_EVP(WOLFSSL_EVP_PKEY** out, |
1364 | | unsigned char** in, long inSz) |
1365 | 0 | { |
1366 | 0 | WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_EVP"); |
1367 | 0 | return d2i_evp_pkey_try(out, (const unsigned char**)in, inSz, 1); |
1368 | 0 | } |
1369 | | #endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_QT || |
1370 | | * WOLFSSL_WPAS_SMALL*/ |
1371 | | |
1372 | | #if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || \ |
1373 | | defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT) |
1374 | | |
1375 | | #ifndef NO_BIO |
1376 | | /* Converts a DER encoded private key in a BIO to a WOLFSSL_EVP_PKEY structure. |
1377 | | * |
1378 | | * @param [in] bio BIO to read DER from. |
1379 | | * @param [out] out New WOLFSSL_EVP_PKEY pointer when not NULL. |
1380 | | * @return Pointer to a new WOLFSSL_EVP_PKEY structure on success. |
1381 | | * @return NULL on failure. |
1382 | | */ |
1383 | | WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_bio(WOLFSSL_BIO* bio, |
1384 | | WOLFSSL_EVP_PKEY** out) |
1385 | 0 | { |
1386 | 0 | unsigned char* mem = NULL; |
1387 | 0 | int memSz = 0; |
1388 | 0 | WOLFSSL_EVP_PKEY* key = NULL; |
1389 | |
|
1390 | 0 | WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_bio"); |
1391 | | |
1392 | | /* Validate parameters. */ |
1393 | 0 | if (bio == NULL) { |
1394 | 0 | return NULL; |
1395 | 0 | } |
1396 | | |
1397 | | /* Get length of data in BIO. */ |
1398 | 0 | memSz = wolfSSL_BIO_get_len(bio); |
1399 | 0 | if (memSz <= 0) { |
1400 | 0 | WOLFSSL_MSG("wolfSSL_BIO_get_len() failure"); |
1401 | 0 | return NULL; |
1402 | 0 | } |
1403 | | /* Allocate memory to read all of BIO data into. */ |
1404 | 0 | mem = (unsigned char*)XMALLOC((size_t)memSz, bio->heap, |
1405 | 0 | DYNAMIC_TYPE_TMP_BUFFER); |
1406 | 0 | if (mem == NULL) { |
1407 | 0 | WOLFSSL_MSG("Malloc failure"); |
1408 | 0 | return NULL; |
1409 | 0 | } |
1410 | | |
1411 | | /* Read all of data. */ |
1412 | 0 | if (wolfSSL_BIO_read(bio, (unsigned char*)mem, memSz) == memSz) { |
1413 | | /* Determines key type and returns the new private EVP_PKEY object */ |
1414 | 0 | if ((key = wolfSSL_d2i_PrivateKey_EVP(NULL, &mem, (long)memSz)) == |
1415 | 0 | NULL) { |
1416 | 0 | WOLFSSL_MSG("wolfSSL_d2i_PrivateKey_EVP() failure"); |
1417 | 0 | XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); |
1418 | 0 | return NULL; |
1419 | 0 | } |
1420 | | |
1421 | | /* Write extra data back into bio object if necessary. */ |
1422 | 0 | if (memSz > key->pkey_sz) { |
1423 | 0 | wolfSSL_BIO_write(bio, mem + key->pkey_sz, memSz - key->pkey_sz); |
1424 | 0 | if (wolfSSL_BIO_get_len(bio) <= 0) { |
1425 | 0 | WOLFSSL_MSG("Failed to write memory to bio"); |
1426 | 0 | XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); |
1427 | 0 | wolfSSL_EVP_PKEY_free(key); |
1428 | 0 | return NULL; |
1429 | 0 | } |
1430 | 0 | } |
1431 | | |
1432 | | /* Return key through parameter if required. */ |
1433 | 0 | if (out != NULL) { |
1434 | 0 | *out = key; |
1435 | 0 | } |
1436 | 0 | } |
1437 | | |
1438 | | /* Dispose of memory holding BIO data. */ |
1439 | 0 | XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); |
1440 | 0 | return key; |
1441 | 0 | } |
1442 | | #endif /* !NO_BIO */ |
1443 | | |
1444 | | #endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_NGINX || |
1445 | | * WOLFSSL_QT */ |
1446 | | |
1447 | | #ifdef OPENSSL_EXTRA |
1448 | | /* Reads in a DER format key. If PKCS8 headers are found they are stripped off. |
1449 | | * |
1450 | | * @param [in] type Type of key. |
1451 | | * @param [in, out] out Newly created WOLFSSL_EVP_PKEY structure. |
1452 | | * @param [in, out] in Pointer to input key DER. |
1453 | | * Pointer is advanced the same number of bytes read on |
1454 | | * success. |
1455 | | * @param [in] inSz Size of in buffer. |
1456 | | * @return A non null pointer on success. |
1457 | | * @return NULL on failure. |
1458 | | */ |
1459 | | static WOLFSSL_EVP_PKEY* d2i_evp_pkey(int type, WOLFSSL_EVP_PKEY** out, |
1460 | | const unsigned char **in, long inSz, int priv) |
1461 | 0 | { |
1462 | 0 | int ret = 0; |
1463 | 0 | word32 idx = 0, algId; |
1464 | 0 | word16 pkcs8HeaderSz = 0; |
1465 | 0 | WOLFSSL_EVP_PKEY* local; |
1466 | 0 | const unsigned char* p; |
1467 | 0 | int opt; |
1468 | |
|
1469 | 0 | (void)opt; |
1470 | | |
1471 | | /* Validate parameters. */ |
1472 | 0 | if (in == NULL || *in == NULL || inSz <= 0) { |
1473 | 0 | WOLFSSL_MSG("Bad argument"); |
1474 | 0 | return NULL; |
1475 | 0 | } |
1476 | | |
1477 | 0 | if (priv == 1) { |
1478 | | /* Check if input buffer has PKCS8 header. In the case that it does not |
1479 | | * have a PKCS8 header then do not error out. */ |
1480 | 0 | if ((ret = ToTraditionalInline_ex((const byte*)(*in), &idx, |
1481 | 0 | (word32)inSz, &algId)) >= 0) { |
1482 | 0 | WOLFSSL_MSG("Found PKCS8 header"); |
1483 | 0 | pkcs8HeaderSz = (word16)idx; |
1484 | | |
1485 | | /* Check header algorithm id matches algorithm type passed in. */ |
1486 | 0 | if ((type == WC_EVP_PKEY_RSA && algId != RSAk |
1487 | 0 | #ifdef WC_RSA_PSS |
1488 | 0 | && algId != RSAPSSk |
1489 | 0 | #endif |
1490 | 0 | ) || |
1491 | 0 | (type == WC_EVP_PKEY_EC && algId != ECDSAk) || |
1492 | 0 | (type == WC_EVP_PKEY_DSA && algId != DSAk) || |
1493 | 0 | (type == WC_EVP_PKEY_DH && algId != DHk) |
1494 | 0 | #ifdef HAVE_ED25519 |
1495 | 0 | || (type == WC_EVP_PKEY_ED25519 && algId != ED25519k) |
1496 | 0 | #endif |
1497 | 0 | #ifdef HAVE_ED448 |
1498 | 0 | || (type == WC_EVP_PKEY_ED448 && algId != ED448k) |
1499 | 0 | #endif |
1500 | | #ifdef WOLFSSL_HAVE_MLDSA |
1501 | | || (type == WC_EVP_PKEY_DILITHIUM && |
1502 | | algId != ML_DSA_44k && algId != ML_DSA_65k && |
1503 | | algId != ML_DSA_87k |
1504 | | #ifdef WOLFSSL_MLDSA_FIPS204_DRAFT |
1505 | | && algId != DILITHIUM_LEVEL2k |
1506 | | && algId != DILITHIUM_LEVEL3k |
1507 | | && algId != DILITHIUM_LEVEL5k |
1508 | | #endif |
1509 | | ) |
1510 | | #endif |
1511 | 0 | ) { |
1512 | 0 | WOLFSSL_MSG("PKCS8 does not match EVP key type"); |
1513 | 0 | return NULL; |
1514 | 0 | } |
1515 | | |
1516 | | #ifdef WOLFSSL_HAVE_MLDSA |
1517 | | /* Keep the full PKCS#8 wrapper for ML-DSA so i2d retains the |
1518 | | * parameter set held in the AlgorithmIdentifier. */ |
1519 | | if (type == WC_EVP_PKEY_DILITHIUM) { |
1520 | | pkcs8HeaderSz = 0; |
1521 | | } |
1522 | | #endif |
1523 | | |
1524 | 0 | (void)idx; /* not used */ |
1525 | 0 | } |
1526 | | /* Ensure no error occurred try to remove any PKCS#8 header. */ |
1527 | 0 | else if (ret != WC_NO_ERR_TRACE(ASN_PARSE_E)) { |
1528 | 0 | WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 header"); |
1529 | 0 | return NULL; |
1530 | 0 | } |
1531 | 0 | } |
1532 | | |
1533 | | /* Create a new WOLFSSL_EVP_PKEY and populate. Any WOLFSSL_EVP_PKEY |
1534 | | * passed in is replaced only on success. */ |
1535 | 0 | local = wolfSSL_EVP_PKEY_new(); |
1536 | 0 | if (local == NULL) { |
1537 | 0 | return NULL; |
1538 | 0 | } |
1539 | 0 | local->type = type; |
1540 | 0 | local->pkey_sz = (int)inSz; |
1541 | 0 | local->pkcs8HeaderSz = pkcs8HeaderSz; |
1542 | 0 | local->pkey.ptr = (char*)XMALLOC((size_t)inSz, NULL, |
1543 | 0 | DYNAMIC_TYPE_PUBLIC_KEY); |
1544 | 0 | if (local->pkey.ptr == NULL) { |
1545 | 0 | wolfSSL_EVP_PKEY_free(local); |
1546 | 0 | return NULL; |
1547 | 0 | } |
1548 | 0 | XMEMCPY(local->pkey.ptr, *in, (size_t)inSz); |
1549 | 0 | p = (const unsigned char*)local->pkey.ptr; |
1550 | | |
1551 | | /* Create an algorithm specific object into WOLFSSL_EVP_PKEY. */ |
1552 | 0 | switch (type) { |
1553 | 0 | #ifndef NO_RSA |
1554 | 0 | case WC_EVP_PKEY_RSA: |
1555 | | /* Create a WOLFSSL_RSA object. */ |
1556 | 0 | local->ownRsa = 1; |
1557 | 0 | opt = priv ? WOLFSSL_RSA_LOAD_PRIVATE : WOLFSSL_RSA_LOAD_PUBLIC; |
1558 | 0 | local->rsa = wolfssl_rsa_d2i(NULL, p, local->pkey_sz, opt); |
1559 | 0 | if (local->rsa == NULL) { |
1560 | 0 | wolfSSL_EVP_PKEY_free(local); |
1561 | 0 | return NULL; |
1562 | 0 | } |
1563 | 0 | break; |
1564 | 0 | #endif /* NO_RSA */ |
1565 | 0 | #ifdef HAVE_ECC |
1566 | 0 | case WC_EVP_PKEY_EC: |
1567 | | /* Create a WOLFSSL_EC object. */ |
1568 | 0 | local->ownEcc = 1; |
1569 | 0 | local->ecc = wolfSSL_EC_KEY_new(); |
1570 | 0 | if (local->ecc == NULL) { |
1571 | 0 | wolfSSL_EVP_PKEY_free(local); |
1572 | 0 | return NULL; |
1573 | 0 | } |
1574 | 0 | opt = priv ? WOLFSSL_EC_KEY_LOAD_PRIVATE : |
1575 | 0 | WOLFSSL_EC_KEY_LOAD_PUBLIC; |
1576 | 0 | if (wolfSSL_EC_KEY_LoadDer_ex(local->ecc, p, local->pkey_sz, opt) != |
1577 | 0 | WOLFSSL_SUCCESS) { |
1578 | 0 | wolfSSL_EVP_PKEY_free(local); |
1579 | 0 | return NULL; |
1580 | 0 | } |
1581 | 0 | break; |
1582 | 0 | #endif /* HAVE_ECC */ |
1583 | 0 | #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH) |
1584 | | #ifndef NO_DSA |
1585 | | case WC_EVP_PKEY_DSA: |
1586 | | /* Create a WOLFSSL_DSA object. */ |
1587 | | local->ownDsa = 1; |
1588 | | local->dsa = wolfSSL_DSA_new(); |
1589 | | if (local->dsa == NULL) { |
1590 | | wolfSSL_EVP_PKEY_free(local); |
1591 | | return NULL; |
1592 | | } |
1593 | | opt = priv ? WOLFSSL_DSA_LOAD_PRIVATE : WOLFSSL_DSA_LOAD_PUBLIC; |
1594 | | if (wolfSSL_DSA_LoadDer_ex(local->dsa, p, local->pkey_sz, opt) != |
1595 | | WOLFSSL_SUCCESS) { |
1596 | | wolfSSL_EVP_PKEY_free(local); |
1597 | | return NULL; |
1598 | | } |
1599 | | break; |
1600 | | #endif /* NO_DSA */ |
1601 | 0 | #ifndef NO_DH |
1602 | 0 | #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2)) |
1603 | 0 | case WC_EVP_PKEY_DH: |
1604 | | /* Create a WOLFSSL_DH object. */ |
1605 | 0 | local->ownDh = 1; |
1606 | 0 | local->dh = wolfSSL_DH_new(); |
1607 | 0 | if (local->dh == NULL) { |
1608 | 0 | wolfSSL_EVP_PKEY_free(local); |
1609 | 0 | return NULL; |
1610 | 0 | } |
1611 | 0 | if (wolfSSL_DH_LoadDer(local->dh, p, local->pkey_sz) != |
1612 | 0 | WOLFSSL_SUCCESS) { |
1613 | 0 | wolfSSL_EVP_PKEY_free(local); |
1614 | 0 | return NULL; |
1615 | 0 | } |
1616 | 0 | break; |
1617 | 0 | #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ |
1618 | 0 | #endif /* HAVE_DH */ |
1619 | 0 | #endif /* WOLFSSL_QT || OPENSSL_ALL || WOLFSSL_OPENSSH */ |
1620 | 0 | #if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT) |
1621 | 0 | case WC_EVP_PKEY_ED25519: |
1622 | | /* local already holds the input bytes: prePopulated=1. */ |
1623 | 0 | if (d2iTryEd25519Key(&local, p, local->pkey_sz, priv, 1) != 1) { |
1624 | 0 | wolfSSL_EVP_PKEY_free(local); |
1625 | 0 | return NULL; |
1626 | 0 | } |
1627 | 0 | break; |
1628 | 0 | #endif /* HAVE_ED25519 */ |
1629 | 0 | #if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT) |
1630 | 0 | case WC_EVP_PKEY_ED448: |
1631 | | /* See WC_EVP_PKEY_ED25519 case above. */ |
1632 | 0 | if (d2iTryEd448Key(&local, p, local->pkey_sz, priv, 1) != 1) { |
1633 | 0 | wolfSSL_EVP_PKEY_free(local); |
1634 | 0 | return NULL; |
1635 | 0 | } |
1636 | 0 | break; |
1637 | 0 | #endif /* HAVE_ED448 */ |
1638 | | #if defined(WOLFSSL_HAVE_MLDSA) |
1639 | | case WC_EVP_PKEY_DILITHIUM: |
1640 | | /* local already holds the input bytes: prePopulated=1. */ |
1641 | | if (d2iTryMlDsaKey(&local, p, local->pkey_sz, priv, 1, 0) != 1) { |
1642 | | wolfSSL_EVP_PKEY_free(local); |
1643 | | return NULL; |
1644 | | } |
1645 | | break; |
1646 | | #endif /* WOLFSSL_HAVE_MLDSA */ |
1647 | 0 | default: |
1648 | 0 | WOLFSSL_MSG("Unsupported key type"); |
1649 | 0 | wolfSSL_EVP_PKEY_free(local); |
1650 | 0 | return NULL; |
1651 | 0 | } |
1652 | | |
1653 | | /* Advance pointer and return through parameter when required on success. */ |
1654 | 0 | if (local != NULL) { |
1655 | 0 | if (local->pkey_sz <= (int)inSz) { |
1656 | 0 | *in += local->pkey_sz; |
1657 | 0 | } |
1658 | 0 | if (out != NULL) { |
1659 | | /* Dispose of any WOLFSSL_EVP_PKEY passed in. */ |
1660 | 0 | wolfSSL_EVP_PKEY_free(*out); |
1661 | 0 | *out = local; |
1662 | 0 | } |
1663 | 0 | } |
1664 | | |
1665 | | /* Return newly allocated WOLFSSL_EVP_PKEY structure. */ |
1666 | 0 | return local; |
1667 | 0 | } |
1668 | | |
1669 | | /* Reads in a DER format key. |
1670 | | * |
1671 | | * @param [in] type Type of key. |
1672 | | * @param [in, out] out Newly created WOLFSSL_EVP_PKEY structure. |
1673 | | * @param [in, out] in Pointer to input key DER. |
1674 | | * Pointer is advanced the same number of bytes read on |
1675 | | * success. |
1676 | | * @param [in] inSz Size of in buffer. |
1677 | | * @return A non null pointer on success. |
1678 | | * @return NULL on failure. |
1679 | | */ |
1680 | | WOLFSSL_EVP_PKEY* wolfSSL_d2i_PublicKey(int type, WOLFSSL_EVP_PKEY** out, |
1681 | | const unsigned char **in, long inSz) |
1682 | 0 | { |
1683 | 0 | WOLFSSL_ENTER("wolfSSL_d2i_PublicKey"); |
1684 | |
|
1685 | 0 | return d2i_evp_pkey(type, out, in, inSz, 0); |
1686 | 0 | } |
1687 | | |
1688 | | /* Reads in a DER format key. If PKCS8 headers are found they are stripped off. |
1689 | | * |
1690 | | * @param [in] type Type of key. |
1691 | | * @param [in, out] out Newly created WOLFSSL_EVP_PKEY structure. |
1692 | | * @param [in, out] in Pointer to input key DER. |
1693 | | * Pointer is advanced the same number of bytes read on |
1694 | | * success. |
1695 | | * @param [in] inSz Size of in buffer. |
1696 | | * @return A non null pointer on success. |
1697 | | * @return NULL on failure. |
1698 | | */ |
1699 | | WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out, |
1700 | | const unsigned char **in, long inSz) |
1701 | 0 | { |
1702 | 0 | WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey"); |
1703 | |
|
1704 | 0 | return d2i_evp_pkey(type, out, in, inSz, 1); |
1705 | 0 | } |
1706 | | #endif /* OPENSSL_EXTRA */ |
1707 | | |
1708 | | #ifdef OPENSSL_ALL |
1709 | | /* Detect RSA or EC key and decode private key DER. |
1710 | | * |
1711 | | * @param [in, out] pkey Newly created WOLFSSL_EVP_PKEY structure. |
1712 | | * @param [in, out] pp Pointer to private key DER data. |
1713 | | * @param [in] length Length in bytes of DER data. |
1714 | | */ |
1715 | | WOLFSSL_EVP_PKEY* wolfSSL_d2i_AutoPrivateKey(WOLFSSL_EVP_PKEY** pkey, |
1716 | | const unsigned char** pp, long length) |
1717 | 0 | { |
1718 | 0 | int ret; |
1719 | 0 | WOLFSSL_EVP_PKEY* key = NULL; |
1720 | 0 | const byte* der; |
1721 | 0 | word32 idx = 0; |
1722 | 0 | int len = 0; |
1723 | 0 | int cnt = 0; |
1724 | 0 | word32 algId; |
1725 | 0 | word32 keyLen; |
1726 | |
|
1727 | 0 | if (pp == NULL || *pp == NULL || length <= 0) |
1728 | 0 | return NULL; |
1729 | | |
1730 | 0 | der = *pp; |
1731 | 0 | keyLen = (word32)length; |
1732 | | |
1733 | | /* Take off PKCS#8 wrapper if found. */ |
1734 | 0 | if ((len = ToTraditionalInline_ex(der, &idx, keyLen, &algId)) >= 0) { |
1735 | 0 | #if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT) |
1736 | 0 | if (algId == ED25519k) { |
1737 | 0 | word32 seqIdx = 0; |
1738 | 0 | int seqLen = 0; |
1739 | | |
1740 | | /* Ed25519's inner key is an OCTET STRING, not a SEQUENCE, so the |
1741 | | * RSA/ECC element-count heuristic below cannot classify it. |
1742 | | * Decode the full PKCS#8 PrivateKeyInfo directly (keeps the |
1743 | | * cached DER complete so the key can be re-loaded later). Pass |
1744 | | * the size of the whole PrivateKeyInfo, taken from its outer |
1745 | | * SEQUENCE header: ToTraditionalInline_ex() reports the offset and |
1746 | | * length of the inner privateKey OCTET STRING only, and RFC 5958 |
1747 | | * allows optional attributes and a publicKey to follow it - the |
1748 | | * form wolfSSL's own wc_Ed25519KeyToDer() emits - which that offset |
1749 | | * would cut off. With the object size, *pp advances by exactly one |
1750 | | * object and no trailing bytes are cached. */ |
1751 | 0 | if (GetSequence(der, &seqIdx, &seqLen, keyLen) < 0) { |
1752 | 0 | return NULL; |
1753 | 0 | } |
1754 | 0 | return wolfSSL_d2i_PrivateKey(WC_EVP_PKEY_ED25519, pkey, pp, |
1755 | 0 | (long)seqIdx + (long)seqLen); |
1756 | 0 | } |
1757 | 0 | #endif |
1758 | 0 | der += idx; |
1759 | 0 | keyLen = (word32)len; |
1760 | 0 | } |
1761 | | |
1762 | 0 | idx = 0; |
1763 | 0 | len = 0; |
1764 | | /* Use the number of elements in the outer sequence to determine key type. |
1765 | | */ |
1766 | 0 | ret = GetSequence(der, &idx, &len, keyLen); |
1767 | 0 | if (ret >= 0) { |
1768 | 0 | word32 end = idx + (word32)len; |
1769 | 0 | while (ret >= 0 && idx < end) { |
1770 | | /* Skip type */ |
1771 | 0 | idx++; |
1772 | | /* Get length and skip over - keeping count */ |
1773 | 0 | len = 0; |
1774 | 0 | ret = GetLength(der, &idx, &len, keyLen); |
1775 | 0 | if (ret >= 0) { |
1776 | 0 | if (idx + (word32)len > end) { |
1777 | 0 | ret = ASN_PARSE_E; |
1778 | 0 | } |
1779 | 0 | else { |
1780 | 0 | idx += (word32)len; |
1781 | 0 | cnt++; |
1782 | 0 | } |
1783 | 0 | } |
1784 | 0 | } |
1785 | 0 | } |
1786 | |
|
1787 | 0 | if (ret >= 0) { |
1788 | 0 | int type; |
1789 | | /* ECC includes version, private[, curve][, public key] */ |
1790 | 0 | if (cnt >= 2 && cnt <= 4) { |
1791 | 0 | type = WC_EVP_PKEY_EC; |
1792 | 0 | } |
1793 | 0 | else { |
1794 | 0 | type = WC_EVP_PKEY_RSA; |
1795 | 0 | } |
1796 | | |
1797 | | /* Decode the detected type of private key. */ |
1798 | 0 | key = wolfSSL_d2i_PrivateKey(type, pkey, &der, keyLen); |
1799 | | /* Update the pointer to after the DER data. */ |
1800 | 0 | *pp = der; |
1801 | 0 | } |
1802 | |
|
1803 | 0 | return key; |
1804 | 0 | } |
1805 | | |
1806 | | #if !defined(NO_BIO) && !defined(NO_PWDBASED) && defined(HAVE_PKCS8) |
1807 | | /* Read all of the BIO data into a newly allocated buffer. |
1808 | | * |
1809 | | * @param [in] bio BIO to read from. |
1810 | | * @param [out] data Allocated buffer holding all BIO data. |
1811 | | * @return Number of bytes allocated and read. |
1812 | | * @return MEMORY_E on dynamic memory allocation failure. |
1813 | | * @return Other negative on error. |
1814 | | */ |
1815 | | static int bio_get_data(WOLFSSL_BIO* bio, byte** data) |
1816 | 0 | { |
1817 | 0 | int ret = 0; |
1818 | 0 | byte* mem = NULL; |
1819 | | |
1820 | | /* Get length of data in BIO. */ |
1821 | 0 | ret = wolfSSL_BIO_get_len(bio); |
1822 | 0 | if (ret > 0) { |
1823 | | /* Allocate memory big enough to hold data in BIO. */ |
1824 | 0 | mem = (byte*)XMALLOC((size_t)ret, bio->heap, DYNAMIC_TYPE_OPENSSL); |
1825 | 0 | if (mem == NULL) { |
1826 | 0 | WOLFSSL_MSG("Memory error"); |
1827 | 0 | ret = MEMORY_E; |
1828 | 0 | } |
1829 | 0 | if (ret >= 0) { |
1830 | | /* Read data from BIO. */ |
1831 | 0 | if ((ret = wolfSSL_BIO_read(bio, mem, ret)) <= 0) { |
1832 | 0 | XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL); |
1833 | 0 | ret = MEMORY_E; |
1834 | 0 | mem = NULL; |
1835 | 0 | } |
1836 | 0 | } |
1837 | 0 | } |
1838 | | |
1839 | | /* Return allocated buffer with data from BIO. */ |
1840 | 0 | *data = mem; |
1841 | 0 | return ret; |
1842 | 0 | } |
1843 | | |
1844 | | /* Convert the algorithm id to a key type. |
1845 | | * |
1846 | | * @param [in] algId Algorithm Id. |
1847 | | * @return Key type on success. |
1848 | | * @return WC_EVP_PKEY_NONE when algorithm id not supported. |
1849 | | */ |
1850 | | static int wolfssl_i_alg_id_to_key_type(word32 algId) |
1851 | 0 | { |
1852 | 0 | int type; |
1853 | | |
1854 | | /* Convert algorithm id into EVP PKEY id. */ |
1855 | 0 | switch (algId) { |
1856 | 0 | #ifndef NO_RSA |
1857 | 0 | case RSAk: |
1858 | 0 | #ifdef WC_RSA_PSS |
1859 | 0 | case RSAPSSk: |
1860 | 0 | #endif |
1861 | 0 | type = WC_EVP_PKEY_RSA; |
1862 | 0 | break; |
1863 | 0 | #endif |
1864 | 0 | #ifdef HAVE_ECC |
1865 | 0 | case ECDSAk: |
1866 | 0 | type = WC_EVP_PKEY_EC; |
1867 | 0 | break; |
1868 | 0 | #endif |
1869 | | #ifndef NO_DSA |
1870 | | case DSAk: |
1871 | | type = WC_EVP_PKEY_DSA; |
1872 | | break; |
1873 | | #endif |
1874 | 0 | #ifndef NO_DH |
1875 | 0 | case DHk: |
1876 | 0 | type = WC_EVP_PKEY_DH; |
1877 | 0 | break; |
1878 | 0 | #endif |
1879 | 0 | default: |
1880 | 0 | WOLFSSL_MSG("PKEY algorithm, from PKCS#8 header, not supported"); |
1881 | 0 | type = WC_EVP_PKEY_NONE; |
1882 | 0 | break; |
1883 | 0 | } |
1884 | | |
1885 | 0 | return type; |
1886 | 0 | } |
1887 | | |
1888 | | /* Creates an WOLFSSL_EVP_PKEY from PKCS#8 encrypted private DER in a BIO. |
1889 | | * |
1890 | | * Uses the PEM default password callback when cb is NULL. |
1891 | | * |
1892 | | * @param [in] bio BIO to read DER from. |
1893 | | * @param [in, out] pkey Newly created WOLFSSL_EVP_PKEY structure. |
1894 | | * @param [in] cb Password callback. May be NULL. |
1895 | | * @param [in] ctx Password callback context. May be NULL. |
1896 | | * @return A non null pointer on success. |
1897 | | * @return NULL on failure. |
1898 | | */ |
1899 | | WOLFSSL_EVP_PKEY* wolfSSL_d2i_PKCS8PrivateKey_bio(WOLFSSL_BIO* bio, |
1900 | | WOLFSSL_EVP_PKEY** pkey, wc_pem_password_cb* cb, void* ctx) |
1901 | 0 | { |
1902 | 0 | int ret; |
1903 | 0 | const byte* p; |
1904 | 0 | byte* der = NULL; |
1905 | 0 | int len; |
1906 | 0 | word32 algId; |
1907 | 0 | WOLFSSL_EVP_PKEY* key; |
1908 | 0 | int type; |
1909 | 0 | char password[NAME_SZ]; |
1910 | 0 | int passwordSz; |
1911 | | |
1912 | | /* Get the data from the BIO into a newly allocated buffer. */ |
1913 | 0 | if ((len = bio_get_data(bio, &der)) < 0) |
1914 | 0 | return NULL; |
1915 | | |
1916 | | /* Use the PEM default callback if none supplied. */ |
1917 | 0 | if (cb == NULL) { |
1918 | 0 | cb = wolfSSL_PEM_def_callback; |
1919 | 0 | } |
1920 | | /* Get the password. */ |
1921 | 0 | passwordSz = cb(password, sizeof(password), PEM_PASS_READ, ctx); |
1922 | 0 | if (passwordSz < 0) { |
1923 | 0 | XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL); |
1924 | 0 | return NULL; |
1925 | 0 | } |
1926 | | #ifdef WOLFSSL_CHECK_MEM_ZERO |
1927 | | wc_MemZero_Add("wolfSSL_d2i_PKCS8PrivateKey_bio password", password, |
1928 | | passwordSz); |
1929 | | #endif |
1930 | | |
1931 | | /* Decrypt the PKCS#8 encrypted private key and get algorithm. */ |
1932 | 0 | ret = ToTraditionalEnc(der, (word32)len, password, passwordSz, &algId); |
1933 | 0 | ForceZero(password, (word32)passwordSz); |
1934 | | #ifdef WOLFSSL_CHECK_MEM_ZERO |
1935 | | wc_MemZero_Check(password, passwordSz); |
1936 | | #endif |
1937 | 0 | if (ret < 0) { |
1938 | 0 | XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL); |
1939 | 0 | return NULL; |
1940 | 0 | } |
1941 | | |
1942 | | /* Get the key type from the algorithm id of the PKCS#8 header. */ |
1943 | 0 | if ((type = wolfssl_i_alg_id_to_key_type(algId)) == WC_EVP_PKEY_NONE) { |
1944 | 0 | XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL); |
1945 | 0 | return NULL; |
1946 | 0 | } |
1947 | | |
1948 | | /* Decode private key with the known type. */ |
1949 | 0 | p = der; |
1950 | 0 | key = d2i_evp_pkey(type, pkey, &p, len, 1); |
1951 | | |
1952 | | /* Dispose of memory holding BIO data. */ |
1953 | 0 | XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL); |
1954 | 0 | return key; |
1955 | 0 | } |
1956 | | #endif /* !NO_BIO && !NO_PWDBASED && HAVE_PKCS8 */ |
1957 | | #endif /* OPENSSL_ALL */ |
1958 | | |
1959 | | #ifdef OPENSSL_EXTRA |
1960 | | /* Reads in a PKCS#8 DER format key. |
1961 | | * |
1962 | | * @param [in, out] pkey Newly created WOLFSSL_PKCS8_PRIV_KEY_INFO structure. |
1963 | | * @param [in, out] keyBuf Pointer to input key DER. |
1964 | | * Pointer is advanced the same number of bytes read on |
1965 | | * success. |
1966 | | * @param [in] keyLen Number of bytes in keyBuf. |
1967 | | * @return A non null pointer on success. |
1968 | | * @return NULL on failure. |
1969 | | */ |
1970 | | WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY( |
1971 | | WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey, const unsigned char** keyBuf, |
1972 | | long keyLen) |
1973 | 0 | { |
1974 | 0 | WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL; |
1975 | 0 | #ifdef WOLFSSL_PEM_TO_DER |
1976 | 0 | int ret; |
1977 | 0 | DerBuffer* pkcs8Der = NULL; |
1978 | 0 | DerBuffer rawDer; |
1979 | 0 | EncryptedInfo info; |
1980 | 0 | int advanceLen = 0; |
1981 | | #ifdef HAVE_DILITHIUM |
1982 | | word32 outerIdx = 0; |
1983 | | int outerLen = 0; |
1984 | | #endif |
1985 | | |
1986 | | /* Clear the encryption information and DER buffer. */ |
1987 | 0 | XMEMSET(&info, 0, sizeof(info)); |
1988 | 0 | XMEMSET(&rawDer, 0, sizeof(rawDer)); |
1989 | | |
1990 | | /* Validate parameters. */ |
1991 | 0 | if ((keyBuf == NULL) || (*keyBuf == NULL) || (keyLen <= 0)) { |
1992 | 0 | WOLFSSL_MSG("Bad key PEM/DER args"); |
1993 | 0 | return NULL; |
1994 | 0 | } |
1995 | | |
1996 | | /* Try to decode the PEM into DER. */ |
1997 | 0 | ret = PemToDer(*keyBuf, keyLen, PRIVATEKEY_TYPE, &pkcs8Der, NULL, &info, |
1998 | 0 | NULL); |
1999 | 0 | if (ret >= 0) { |
2000 | | /* Cache the amount of data in PEM formatted private key. */ |
2001 | 0 | advanceLen = (int)info.consumed; |
2002 | 0 | } |
2003 | 0 | else { |
2004 | | /* Not PEM - create a DerBuffer with the PKCS#8 DER data. */ |
2005 | 0 | WOLFSSL_MSG("Not PEM format"); |
2006 | 0 | ret = AllocDer(&pkcs8Der, (word32)keyLen, PRIVATEKEY_TYPE, NULL); |
2007 | 0 | if (ret == 0) { |
2008 | 0 | XMEMCPY(pkcs8Der->buffer, *keyBuf, keyLen); |
2009 | 0 | } |
2010 | 0 | } |
2011 | |
|
2012 | 0 | if (ret == 0) { |
2013 | | /* Verify this is PKCS8 Key */ |
2014 | 0 | word32 inOutIdx = 0; |
2015 | 0 | word32 algId; |
2016 | |
|
2017 | 0 | ret = ToTraditionalInline_ex(pkcs8Der->buffer, &inOutIdx, |
2018 | 0 | pkcs8Der->length, &algId); |
2019 | 0 | if (ret >= 0) { |
2020 | 0 | if (advanceLen == 0) { |
2021 | | /* Set only if not PEM */ |
2022 | 0 | advanceLen = (int)inOutIdx + ret; |
2023 | 0 | } |
2024 | 0 | if (algId == DHk) { |
2025 | | /* Special case for DH as we expect the DER buffer to be always |
2026 | | * in PKCS8 format */ |
2027 | 0 | rawDer.buffer = pkcs8Der->buffer; |
2028 | 0 | rawDer.length = inOutIdx + (word32)ret; |
2029 | 0 | } |
2030 | | #ifdef HAVE_DILITHIUM |
2031 | | else if ( |
2032 | | #ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT |
2033 | | (algId == DILITHIUM_LEVEL2k) || |
2034 | | (algId == DILITHIUM_LEVEL3k) || |
2035 | | (algId == DILITHIUM_LEVEL5k) || |
2036 | | #endif |
2037 | | (algId == ML_DSA_44k) || |
2038 | | (algId == ML_DSA_65k) || |
2039 | | (algId == ML_DSA_87k)) { |
2040 | | |
2041 | | /* Keep full PKCS#8 wrapper for level recovery from |
2042 | | * AlgorithmIdentifier parameters */ |
2043 | | rawDer.buffer = pkcs8Der->buffer; |
2044 | | if (GetSequence(pkcs8Der->buffer, &outerIdx, &outerLen, |
2045 | | pkcs8Der->length) < 0) { |
2046 | | ret = ASN_PARSE_E; |
2047 | | } |
2048 | | else { |
2049 | | rawDer.length = outerIdx + (word32)outerLen; |
2050 | | } |
2051 | | } |
2052 | | #endif |
2053 | 0 | else { |
2054 | 0 | rawDer.buffer = pkcs8Der->buffer + inOutIdx; |
2055 | 0 | rawDer.length = (word32)ret; |
2056 | 0 | } |
2057 | 0 | if (ret > 0) { |
2058 | 0 | ret = 0; /* good DER */ |
2059 | 0 | } |
2060 | 0 | } |
2061 | 0 | } |
2062 | |
|
2063 | 0 | if (ret == 0) { |
2064 | | /* Create a WOLFSSL_EVP_PKEY for a WOLFSSL_PKCS8_PRIV_KEY_INFO. */ |
2065 | 0 | pkcs8 = wolfSSL_EVP_PKEY_new(); |
2066 | 0 | if (pkcs8 == NULL) { |
2067 | 0 | ret = MEMORY_E; |
2068 | 0 | } |
2069 | 0 | } |
2070 | 0 | if (ret == 0) { |
2071 | | /* Allocate memory to hold DER. */ |
2072 | 0 | pkcs8->pkey.ptr = (char*)XMALLOC(rawDer.length, NULL, |
2073 | 0 | DYNAMIC_TYPE_PUBLIC_KEY); |
2074 | 0 | if (pkcs8->pkey.ptr == NULL) { |
2075 | 0 | ret = MEMORY_E; |
2076 | 0 | } |
2077 | 0 | } |
2078 | 0 | if (ret == 0) { |
2079 | | /* Copy in DER data and size. */ |
2080 | 0 | XMEMCPY(pkcs8->pkey.ptr, rawDer.buffer, rawDer.length); |
2081 | 0 | pkcs8->pkey_sz = (int)rawDer.length; |
2082 | 0 | } |
2083 | | |
2084 | | /* Dispose of PKCS#8 DER data - raw DER reference data in pkcs8Der. */ |
2085 | 0 | FreeDer(&pkcs8Der); |
2086 | 0 | if (ret != 0) { |
2087 | | /* Dispose of WOLFSSL_PKCS8_PRIV_KEY_INFO object on error. */ |
2088 | 0 | wolfSSL_EVP_PKEY_free(pkcs8); |
2089 | 0 | pkcs8 = NULL; |
2090 | 0 | } |
2091 | 0 | else { |
2092 | | /* Advance the buffer past the key on success. */ |
2093 | 0 | *keyBuf += advanceLen; |
2094 | 0 | } |
2095 | 0 | if (pkey != NULL) { |
2096 | | /* Return the WOLFSSL_PKCS8_PRIV_KEY_INFO object through parameter. */ |
2097 | 0 | *pkey = pkcs8; |
2098 | 0 | } |
2099 | | #else |
2100 | | (void)pkey; |
2101 | | (void)keyBuf; |
2102 | | (void)keyLen; |
2103 | | #endif /* WOLFSSL_PEM_TO_DER */ |
2104 | | |
2105 | | /* Return new WOLFSSL_PKCS8_PRIV_KEY_INFO object. */ |
2106 | 0 | return pkcs8; |
2107 | 0 | } |
2108 | | |
2109 | | #ifndef NO_BIO |
2110 | | /* Converts a DER format key read from BIO to a PKCS#8 structure. |
2111 | | * |
2112 | | * @param [in] bio Input BIO to read DER from. |
2113 | | * @param [out] pkey If not NULL then this pointer will be overwritten with a |
2114 | | * new PKCS8 structure. |
2115 | | * @return A WOLFSSL_PKCS8_PRIV_KEY_INFO pointer on success |
2116 | | * @return NULL on failure. |
2117 | | */ |
2118 | | WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY_bio(WOLFSSL_BIO* bio, |
2119 | | WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey) |
2120 | 0 | { |
2121 | 0 | WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL; |
2122 | 0 | #ifdef WOLFSSL_PEM_TO_DER |
2123 | 0 | unsigned char* mem = NULL; |
2124 | 0 | int memSz; |
2125 | |
|
2126 | 0 | WOLFSSL_ENTER("wolfSSL_d2i_PKCS8_PKEY_bio"); |
2127 | | |
2128 | | /* Validate parameters. */ |
2129 | 0 | if (bio == NULL) { |
2130 | 0 | return NULL; |
2131 | 0 | } |
2132 | | |
2133 | | /* Get the memory buffer from the BIO. */ |
2134 | 0 | if ((memSz = wolfSSL_BIO_get_mem_data(bio, &mem)) < 0) { |
2135 | 0 | return NULL; |
2136 | 0 | } |
2137 | | |
2138 | | /* Decode the PKCS#8 key into a WOLFSSL_PKCS8_PRIV_KEY_INFO object. */ |
2139 | 0 | pkcs8 = wolfSSL_d2i_PKCS8_PKEY(pkey, (const unsigned char**)&mem, memSz); |
2140 | | #else |
2141 | | (void)bio; |
2142 | | (void)pkey; |
2143 | | #endif /* WOLFSSL_PEM_TO_DER */ |
2144 | | |
2145 | | /* Return new WOLFSSL_PKCS8_PRIV_KEY_INFO object. */ |
2146 | 0 | return pkcs8; |
2147 | 0 | } |
2148 | | #endif /* !NO_BIO */ |
2149 | | |
2150 | | #ifdef WOLF_PRIVATE_KEY_ID |
2151 | | /* Create an EVP structure for use with crypto callbacks. |
2152 | | * |
2153 | | * @param [in] type Type of private key. |
2154 | | * @param [out] out WOLFSSL_EVP_PKEY object created. |
2155 | | * @param [in] heap Heap hint for dynamic memory allocation. |
2156 | | * @param [in] devId Device id. |
2157 | | * @return A new WOLFSSL_EVP_PKEY object on success. |
2158 | | * @return NULL on failure. |
2159 | | */ |
2160 | | WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_id(int type, WOLFSSL_EVP_PKEY** out, |
2161 | | void* heap, int devId) |
2162 | 0 | { |
2163 | 0 | WOLFSSL_EVP_PKEY* local; |
2164 | | |
2165 | | /* Dispose of any object passed in through out. */ |
2166 | 0 | if (out != NULL && *out != NULL) { |
2167 | 0 | wolfSSL_EVP_PKEY_free(*out); |
2168 | 0 | *out = NULL; |
2169 | 0 | } |
2170 | | |
2171 | | /* Create a local WOLFSSL_EVP_PKEY to be decoded into. */ |
2172 | 0 | local = wolfSSL_EVP_PKEY_new_ex(heap); |
2173 | 0 | if (local == NULL) { |
2174 | 0 | return NULL; |
2175 | 0 | } |
2176 | 0 | local->type = type; |
2177 | 0 | local->pkey_sz = 0; |
2178 | 0 | local->pkcs8HeaderSz = 0; |
2179 | |
|
2180 | 0 | switch (type) { |
2181 | 0 | #ifndef NO_RSA |
2182 | 0 | case WC_EVP_PKEY_RSA: |
2183 | 0 | { |
2184 | | /* Create a WOLFSSL_RSA object into WOLFSSL_EVP_PKEY. */ |
2185 | 0 | local->rsa = wolfSSL_RSA_new_ex(heap, devId); |
2186 | 0 | if (local->rsa == NULL) { |
2187 | 0 | wolfSSL_EVP_PKEY_free(local); |
2188 | 0 | return NULL; |
2189 | 0 | } |
2190 | 0 | local->ownRsa = 1; |
2191 | | /* Algorithm specific object set into WOLFSL_EVP_PKEY. */ |
2192 | 0 | local->rsa->inSet = 1; |
2193 | 0 | #ifdef WOLF_CRYPTO_CB |
2194 | 0 | ((RsaKey*)local->rsa->internal)->devId = devId; |
2195 | 0 | #endif |
2196 | 0 | break; |
2197 | 0 | } |
2198 | 0 | #endif /* !NO_RSA */ |
2199 | 0 | #ifdef HAVE_ECC |
2200 | 0 | case WC_EVP_PKEY_EC: |
2201 | 0 | { |
2202 | 0 | ecc_key* key; |
2203 | | |
2204 | | /* Create a WOLFSSL_EC object into WOLFSSL_EVP_PKEY. */ |
2205 | 0 | local->ecc = wolfSSL_EC_KEY_new_ex(heap, devId); |
2206 | 0 | if (local->ecc == NULL) { |
2207 | 0 | wolfSSL_EVP_PKEY_free(local); |
2208 | 0 | return NULL; |
2209 | 0 | } |
2210 | 0 | local->ownEcc = 1; |
2211 | | /* Algorithm specific object set into WOLFSL_EVP_PKEY. */ |
2212 | 0 | local->ecc->inSet = 1; |
2213 | | |
2214 | | /* Get wolfSSL EC key and set fields. */ |
2215 | 0 | key = (ecc_key*)local->ecc->internal; |
2216 | 0 | #ifdef WOLF_CRYPTO_CB |
2217 | 0 | key->devId = devId; |
2218 | 0 | #endif |
2219 | 0 | key->type = ECC_PRIVATEKEY; |
2220 | | /* key is required to have a key size / curve set, although |
2221 | | * actual one used is determined by devId callback function. */ |
2222 | 0 | wc_ecc_set_curve(key, ECDHE_SIZE, ECC_CURVE_DEF); |
2223 | 0 | break; |
2224 | 0 | } |
2225 | 0 | #endif /* HAVE_ECC */ |
2226 | 0 | default: |
2227 | 0 | WOLFSSL_MSG("Unsupported private key id type"); |
2228 | 0 | wolfSSL_EVP_PKEY_free(local); |
2229 | 0 | return NULL; |
2230 | 0 | } |
2231 | | |
2232 | | /* Return new WOLFSSL_EVP_PKEY through parameter if required. */ |
2233 | 0 | if (local != NULL && out != NULL) { |
2234 | 0 | *out = local; |
2235 | 0 | } |
2236 | | /* Return new WOLFSSL_EVP_PKEY. */ |
2237 | 0 | return local; |
2238 | 0 | } |
2239 | | #endif /* WOLF_PRIVATE_KEY_ID */ |
2240 | | #endif /* OPENSSL_EXTRA */ |
2241 | | |
2242 | | /******************************************************************************* |
2243 | | * END OF d2i APIs |
2244 | | ******************************************************************************/ |
2245 | | |
2246 | | /******************************************************************************* |
2247 | | * START OF i2d APIs |
2248 | | ******************************************************************************/ |
2249 | | |
2250 | | #ifdef OPENSSL_ALL |
2251 | | /* Encode PKCS#8 key as DER data. |
2252 | | * |
2253 | | * @param [in] key PKCS#8 private key to encode. |
2254 | | * @param [out] pp Pointer to buffer of encoded data. |
2255 | | * @return Length of DER encoded data on success. |
2256 | | * @return Less than zero on failure. |
2257 | | */ |
2258 | | int wolfSSL_i2d_PKCS8_PKEY(WOLFSSL_PKCS8_PRIV_KEY_INFO* key, unsigned char** pp) |
2259 | 0 | { |
2260 | 0 | word32 keySz = 0; |
2261 | 0 | unsigned char* out; |
2262 | 0 | int len; |
2263 | |
|
2264 | 0 | WOLFSSL_ENTER("wolfSSL_i2d_PKCS8_PKEY"); |
2265 | | |
2266 | | /* Validate parameters. */ |
2267 | 0 | if (key == NULL) { |
2268 | 0 | return WOLFSSL_FATAL_ERROR; |
2269 | 0 | } |
2270 | | |
2271 | | /* Get the length of DER encoding. */ |
2272 | 0 | if (pkcs8_encode(key, NULL, &keySz) != WC_NO_ERR_TRACE(LENGTH_ONLY_E)) { |
2273 | 0 | return WOLFSSL_FATAL_ERROR; |
2274 | 0 | } |
2275 | 0 | len = (int)keySz; |
2276 | | |
2277 | | /* Return the length when output parameter is NULL. */ |
2278 | 0 | if ((pp == NULL) || (len == 0)) { |
2279 | 0 | return len; |
2280 | 0 | } |
2281 | | |
2282 | | /* Allocate memory for DER encoding if NULL passed in for output buffer. */ |
2283 | 0 | if (*pp == NULL) { |
2284 | 0 | out = (unsigned char*)XMALLOC((size_t)len, NULL, DYNAMIC_TYPE_ASN1); |
2285 | 0 | if (out == NULL) { |
2286 | 0 | return WOLFSSL_FATAL_ERROR; |
2287 | 0 | } |
2288 | 0 | } |
2289 | 0 | else { |
2290 | | /* Use buffer passed in - assume it is big enough. */ |
2291 | 0 | out = *pp; |
2292 | 0 | } |
2293 | | |
2294 | | /* Encode the PKCS#8 key into the output buffer. */ |
2295 | 0 | if (pkcs8_encode(key, out, &keySz) != len) { |
2296 | 0 | if (*pp == NULL) { |
2297 | 0 | XFREE(out, NULL, DYNAMIC_TYPE_ASN1); |
2298 | 0 | } |
2299 | 0 | return WOLFSSL_FATAL_ERROR; |
2300 | 0 | } |
2301 | | |
2302 | | /* Return new output buffer or move pointer passed encoded data. */ |
2303 | 0 | if (*pp == NULL) { |
2304 | 0 | *pp = out; |
2305 | 0 | } |
2306 | 0 | else { |
2307 | 0 | *pp += len; |
2308 | 0 | } |
2309 | |
|
2310 | 0 | return len; |
2311 | 0 | } |
2312 | | #endif |
2313 | | |
2314 | | #ifdef OPENSSL_EXTRA |
2315 | | |
2316 | | #if !defined(NO_ASN) && !defined(NO_PWDBASED) |
2317 | | /* Get raw pointer to DER buffer from WOLFSSL_EVP_PKEY. |
2318 | | * |
2319 | | * Assumes der is large enough if passed in. |
2320 | | * |
2321 | | * @param [in] key WOLFSSL_EVP_PKEY to get DER buffer for. |
2322 | | * @param [out] der Buffer holding DER encoding. May be NULL. |
2323 | | * @return Size of DER encoding on success. |
2324 | | * @return Less than 0 on failure. |
2325 | | */ |
2326 | | static int wolfssl_i_evp_pkey_get_der(const WOLFSSL_EVP_PKEY* key, |
2327 | | unsigned char** der) |
2328 | 0 | { |
2329 | 0 | int sz; |
2330 | 0 | word16 pkcs8HeaderSz; |
2331 | | |
2332 | | /* Validate parameters. */ |
2333 | 0 | if ((key == NULL) || (key->pkey_sz == 0)) { |
2334 | 0 | return WOLFSSL_FATAL_ERROR; |
2335 | 0 | } |
2336 | | |
2337 | | /* If pkcs8HeaderSz is invalid, return all of the DER encoding. */ |
2338 | 0 | pkcs8HeaderSz = 0; |
2339 | 0 | if (key->pkey_sz > key->pkcs8HeaderSz) { |
2340 | 0 | pkcs8HeaderSz = key->pkcs8HeaderSz; |
2341 | 0 | } |
2342 | | /* Calculate the size of the DER encoding to return. */ |
2343 | 0 | sz = key->pkey_sz - pkcs8HeaderSz; |
2344 | | /* Returning encoding when DER is not NULL. */ |
2345 | 0 | if (der != NULL) { |
2346 | 0 | unsigned char* pt = (unsigned char*)key->pkey.ptr; |
2347 | 0 | int bufferPassedIn = ((*der) != NULL); |
2348 | |
|
2349 | 0 | if (!bufferPassedIn) { |
2350 | | /* Allocate buffer to hold DER encoding. */ |
2351 | 0 | *der = (unsigned char*)XMALLOC((size_t)sz, NULL, |
2352 | 0 | DYNAMIC_TYPE_OPENSSL); |
2353 | 0 | if (*der == NULL) { |
2354 | 0 | return WOLFSSL_FATAL_ERROR; |
2355 | 0 | } |
2356 | 0 | } |
2357 | | /* Copy in non-PKCS#8 DER encoding. */ |
2358 | 0 | XMEMCPY(*der, pt + pkcs8HeaderSz, (size_t)sz); |
2359 | | /* Step past encoded key when buffer provided. */ |
2360 | 0 | if (bufferPassedIn) { |
2361 | 0 | *der += sz; |
2362 | 0 | } |
2363 | 0 | } |
2364 | | |
2365 | | /* Return size of DER encoded data. */ |
2366 | 0 | return sz; |
2367 | 0 | } |
2368 | | |
2369 | | /* Encode key as unencrypted DER data. |
2370 | | * |
2371 | | * @param [in] key PKCS#8 private key to encode. |
2372 | | * @param [out] der Pointer to buffer of encoded data. |
2373 | | * @return Length of DER encoded data on success. |
2374 | | * @return Less than zero on failure. |
2375 | | */ |
2376 | | int wolfSSL_i2d_PrivateKey(const WOLFSSL_EVP_PKEY* key, unsigned char** der) |
2377 | 0 | { |
2378 | 0 | return wolfssl_i_evp_pkey_get_der(key, der); |
2379 | 0 | } |
2380 | | |
2381 | | #ifndef NO_BIO |
2382 | | /* Encode key as unencrypted DER data and write to BIO. |
2383 | | * |
2384 | | * @param [in] bio BIO to write data to. |
2385 | | * @param [in] key PKCS#8 private key to encode. |
2386 | | * @return Length of DER encoded data on success. |
2387 | | * @return Less than zero on failure. |
2388 | | */ |
2389 | | int wolfSSL_i2d_PrivateKey_bio(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key) |
2390 | 0 | { |
2391 | 0 | int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE); |
2392 | 0 | int derSz = 0; |
2393 | 0 | byte* der = NULL; |
2394 | |
|
2395 | 0 | if (bio == NULL || key == NULL) { |
2396 | 0 | return WOLFSSL_FAILURE; |
2397 | 0 | } |
2398 | | |
2399 | 0 | derSz = wolfSSL_i2d_PrivateKey(key, &der); |
2400 | 0 | if (derSz <= 0) { |
2401 | 0 | WOLFSSL_MSG("wolfSSL_i2d_PrivateKey (for getting size) failed"); |
2402 | 0 | return WOLFSSL_FAILURE; |
2403 | 0 | } |
2404 | | |
2405 | 0 | if (wolfSSL_BIO_write(bio, der, derSz) != derSz) { |
2406 | 0 | goto cleanup; |
2407 | 0 | } |
2408 | | |
2409 | 0 | ret = WOLFSSL_SUCCESS; |
2410 | |
|
2411 | 0 | cleanup: |
2412 | 0 | XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL); |
2413 | 0 | return ret; |
2414 | 0 | } |
2415 | | #endif |
2416 | | |
2417 | | #ifdef HAVE_ECC |
2418 | | /* Encode EC key as public key DER. |
2419 | | * |
2420 | | * @param [in] key WOLFSSL_EVP_KEY object to encode. |
2421 | | * @param [in] ec WOLFSSL_EC_KEY object to encode. |
2422 | | * @param [out] der Buffer with DER encoding of EC public key. |
2423 | | * @return Public key DER encoding size on success. |
2424 | | * @return WOLFSSL_FATAL_ERROR when dynamic memory allocation fails. |
2425 | | * @return WOLFSSL_FATAL_ERROR when encoding fails. |
2426 | | */ |
2427 | | static int wolfssl_i_i2d_ecpublickey(const WOLFSSL_EVP_PKEY* key, |
2428 | | const WOLFSSL_EC_KEY *ec, unsigned char **der) |
2429 | 0 | { |
2430 | 0 | word32 pub_derSz = 0; |
2431 | 0 | int ret; |
2432 | 0 | unsigned char *local_der = NULL; |
2433 | 0 | word32 local_derSz = 0; |
2434 | 0 | unsigned char *pub_der = NULL; |
2435 | 0 | ecc_key *eccKey = NULL; |
2436 | 0 | word32 inOutIdx = 0; |
2437 | | |
2438 | | /* We need to get the DER, then convert it to a public key. But what we get |
2439 | | * might be a buffered private key so we need to decode it and then encode |
2440 | | * the public part. */ |
2441 | 0 | ret = wolfssl_i_evp_pkey_get_der(key, &local_der); |
2442 | 0 | if (ret <= 0) { |
2443 | | /* In this case, there was no buffered DER at all. This could be the |
2444 | | * case where the key that was passed in was generated. So now we |
2445 | | * have to create the local DER. */ |
2446 | 0 | local_derSz = (word32)wolfSSL_i2d_ECPrivateKey(ec, &local_der); |
2447 | 0 | if (local_derSz == 0) { |
2448 | 0 | ret = WOLFSSL_FATAL_ERROR; |
2449 | 0 | } |
2450 | 0 | } else { |
2451 | 0 | local_derSz = (word32)ret; |
2452 | 0 | ret = 0; |
2453 | 0 | } |
2454 | |
|
2455 | 0 | if (ret == 0) { |
2456 | 0 | eccKey = (ecc_key *)XMALLOC(sizeof(*eccKey), NULL, DYNAMIC_TYPE_ECC); |
2457 | 0 | if (eccKey == NULL) { |
2458 | 0 | WOLFSSL_MSG("Failed to allocate key buffer."); |
2459 | 0 | ret = WOLFSSL_FATAL_ERROR; |
2460 | 0 | } |
2461 | 0 | } |
2462 | | |
2463 | | /* Initialize a wolfCrypt ECC key. */ |
2464 | 0 | if (ret == 0) { |
2465 | 0 | ret = wc_ecc_init(eccKey); |
2466 | 0 | } |
2467 | 0 | if (ret == 0) { |
2468 | | /* Decode the DER data with wolfCrypt ECC key. */ |
2469 | 0 | ret = wc_EccPublicKeyDecode(local_der, &inOutIdx, eccKey, local_derSz); |
2470 | 0 | if (ret < 0) { |
2471 | | /* We now try again as x.963 [point type][x][opt y]. */ |
2472 | 0 | ret = wc_ecc_import_x963(local_der, local_derSz, eccKey); |
2473 | 0 | } |
2474 | 0 | } |
2475 | |
|
2476 | 0 | if (ret == 0) { |
2477 | | /* Get the size of the encoding of the public key DER. */ |
2478 | 0 | pub_derSz = (word32)wc_EccPublicKeyDerSize(eccKey, 1); |
2479 | 0 | if ((int)pub_derSz <= 0) { |
2480 | 0 | ret = WOLFSSL_FAILURE; |
2481 | 0 | } |
2482 | 0 | } |
2483 | |
|
2484 | 0 | if (ret == 0) { |
2485 | | /* Allocate memory for public key DER encoding. */ |
2486 | 0 | pub_der = (unsigned char*)XMALLOC(pub_derSz, NULL, |
2487 | 0 | DYNAMIC_TYPE_PUBLIC_KEY); |
2488 | 0 | if (pub_der == NULL) { |
2489 | 0 | WOLFSSL_MSG("Failed to allocate output buffer."); |
2490 | 0 | ret = WOLFSSL_FATAL_ERROR; |
2491 | 0 | } |
2492 | 0 | } |
2493 | |
|
2494 | 0 | if (ret == 0) { |
2495 | | /* Encode public key as DER. */ |
2496 | 0 | pub_derSz = (word32)wc_EccPublicKeyToDer(eccKey, pub_der, pub_derSz, 1); |
2497 | 0 | if ((int)pub_derSz <= 0) { |
2498 | 0 | ret = WOLFSSL_FATAL_ERROR; |
2499 | 0 | } |
2500 | 0 | } |
2501 | | |
2502 | | /* This block is for actually returning the DER of the public key */ |
2503 | 0 | if ((ret == 0) && (der != NULL)) { |
2504 | 0 | int bufferPassedIn = ((*der) != NULL); |
2505 | 0 | if (!bufferPassedIn) { |
2506 | 0 | *der = (unsigned char*)XMALLOC(pub_derSz, NULL, |
2507 | 0 | DYNAMIC_TYPE_PUBLIC_KEY); |
2508 | 0 | if (*der == NULL) { |
2509 | 0 | WOLFSSL_MSG("Failed to allocate output buffer."); |
2510 | 0 | ret = WOLFSSL_FATAL_ERROR; |
2511 | 0 | } |
2512 | 0 | } |
2513 | 0 | if (ret == 0) { |
2514 | 0 | XMEMCPY(*der, pub_der, pub_derSz); |
2515 | 0 | if (bufferPassedIn) { |
2516 | 0 | *der += pub_derSz; |
2517 | 0 | } |
2518 | 0 | } |
2519 | 0 | } |
2520 | | |
2521 | | /* Dispose of allocated objects. */ |
2522 | 0 | XFREE(pub_der, NULL, DYNAMIC_TYPE_PUBLIC_KEY); |
2523 | 0 | XFREE(local_der, NULL, DYNAMIC_TYPE_OPENSSL); |
2524 | 0 | wc_ecc_free(eccKey); |
2525 | 0 | XFREE(eccKey, NULL, DYNAMIC_TYPE_ECC); |
2526 | | |
2527 | | /* Return error or the size of the DER encoded public key. */ |
2528 | 0 | if (ret == 0) { |
2529 | 0 | ret = (int)pub_derSz; |
2530 | 0 | } |
2531 | 0 | return ret; |
2532 | 0 | } |
2533 | | #endif |
2534 | | |
2535 | | #if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT) |
2536 | | /* Encode an Ed25519 public key as DER SubjectPublicKeyInfo. Follows the |
2537 | | * i2d output convention: der == NULL returns the size only; *der == NULL |
2538 | | * allocates the buffer (caller frees); otherwise writes into *der and |
2539 | | * advances it. Returns the DER size or WOLFSSL_FATAL_ERROR. */ |
2540 | | static int wolfssl_i_i2d_ed25519_pubkey(const ed25519_key* key, |
2541 | | unsigned char **der) |
2542 | 0 | { |
2543 | 0 | int derSz; |
2544 | 0 | unsigned char* buf; |
2545 | |
|
2546 | 0 | if (key == NULL) { |
2547 | 0 | return WOLFSSL_FATAL_ERROR; |
2548 | 0 | } |
2549 | | |
2550 | | /* withAlg = 1 -> wrap the raw key in a SubjectPublicKeyInfo. */ |
2551 | 0 | derSz = wc_Ed25519PublicKeyToDer(key, NULL, 0, 1); |
2552 | 0 | if (derSz <= 0) { |
2553 | 0 | return WOLFSSL_FATAL_ERROR; |
2554 | 0 | } |
2555 | 0 | if (der == NULL) { |
2556 | 0 | return derSz; |
2557 | 0 | } |
2558 | | |
2559 | 0 | if (*der != NULL) { |
2560 | | /* Caller supplied the buffer: the size is known up front, so encode |
2561 | | * straight into it and advance past the encoding. */ |
2562 | 0 | if (wc_Ed25519PublicKeyToDer(key, *der, (word32)derSz, 1) != derSz) { |
2563 | 0 | return WOLFSSL_FATAL_ERROR; |
2564 | 0 | } |
2565 | 0 | *der += derSz; |
2566 | 0 | return derSz; |
2567 | 0 | } |
2568 | | |
2569 | 0 | buf = (unsigned char*)XMALLOC((size_t)derSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); |
2570 | 0 | if (buf == NULL) { |
2571 | 0 | return WOLFSSL_FATAL_ERROR; |
2572 | 0 | } |
2573 | 0 | if (wc_Ed25519PublicKeyToDer(key, buf, (word32)derSz, 1) |
2574 | 0 | != derSz) { |
2575 | 0 | XFREE(buf, NULL, DYNAMIC_TYPE_PUBLIC_KEY); |
2576 | 0 | return WOLFSSL_FATAL_ERROR; |
2577 | 0 | } |
2578 | | /* Hand the buffer to the caller (no advance, per the i2d convention). */ |
2579 | 0 | *der = buf; |
2580 | |
|
2581 | 0 | return derSz; |
2582 | 0 | } |
2583 | | #endif /* HAVE_ED25519 && HAVE_ED25519_KEY_EXPORT */ |
2584 | | |
2585 | | /* Encode the WOLFSSL_EVP_PKEY object as public key DER. |
2586 | | * |
2587 | | * @param [in] key WOLFSLS_EVP_PKEY object to encode. |
2588 | | * @param [out] der Buffer with DER encoding of public key. |
2589 | | * @return Public key DER encoding size on success. |
2590 | | * @return WOLFSSL_FATAL_ERROR when key is NULL. |
2591 | | * @return WOLFSSL_FATAL_ERROR when key type not supported. |
2592 | | * @return WOLFSSL_FATAL_ERROR when dynamic memory allocation fails. |
2593 | | */ |
2594 | | int wolfSSL_i2d_PublicKey(const WOLFSSL_EVP_PKEY *key, unsigned char **der) |
2595 | 0 | { |
2596 | 0 | int ret; |
2597 | | |
2598 | | /* Validate parameters. */ |
2599 | 0 | if (key == NULL) { |
2600 | 0 | return WOLFSSL_FATAL_ERROR; |
2601 | 0 | } |
2602 | | |
2603 | | /* Encode based on key type. */ |
2604 | 0 | switch (key->type) { |
2605 | 0 | #ifndef NO_RSA |
2606 | 0 | case WC_EVP_PKEY_RSA: |
2607 | 0 | return wolfSSL_i2d_RSAPublicKey(key->rsa, der); |
2608 | 0 | #endif |
2609 | 0 | #ifdef HAVE_ECC |
2610 | 0 | case WC_EVP_PKEY_EC: |
2611 | 0 | return wolfssl_i_i2d_ecpublickey(key, key->ecc, der); |
2612 | 0 | #endif |
2613 | 0 | #if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT) |
2614 | | /* Emit a SubjectPublicKeyInfo (withAlg=1) rather than the bare key: |
2615 | | * wolfSSL_i2d_PUBKEY aliases to this function (below), so the SPKI is |
2616 | | * what wolfSSL_d2i_PUBKEY has to be able to read back. Matches the |
2617 | | * adjacent EC case, which encodes with withAlg=1 for the same reason. |
2618 | | * (Note this differs from OpenSSL, where i2d_PublicKey emits the raw |
2619 | | * key for Ed25519 and only i2d_PUBKEY emits the SPKI.) */ |
2620 | 0 | case WC_EVP_PKEY_ED25519: |
2621 | 0 | return wolfssl_i_i2d_ed25519_pubkey(key->ed25519, der); |
2622 | 0 | #endif |
2623 | 0 | default: |
2624 | 0 | ret = WOLFSSL_FATAL_ERROR; |
2625 | 0 | break; |
2626 | 0 | } |
2627 | | |
2628 | 0 | return ret; |
2629 | 0 | } |
2630 | | |
2631 | | /* Encode the WOLFSSL_EVP_PKEY object as public key DER. |
2632 | | * |
2633 | | * @param [in] key WOLFSLS_EVP_PKEY object to encode. |
2634 | | * @param [out] der Buffer with DER encoding of public key. |
2635 | | * @return Public key DER encoding size on success. |
2636 | | * @return WOLFSSL_FATAL_ERROR when key is NULL. |
2637 | | * @return WOLFSSL_FATAL_ERROR when key type not supported. |
2638 | | * @return WOLFSSL_FATAL_ERROR when dynamic memory allocation fails. |
2639 | | */ |
2640 | | int wolfSSL_i2d_PUBKEY(const WOLFSSL_EVP_PKEY *key, unsigned char **der) |
2641 | 0 | { |
2642 | 0 | return wolfSSL_i2d_PublicKey(key, der); |
2643 | 0 | } |
2644 | | |
2645 | | #ifndef NO_BIO |
2646 | | /* Encode public key as DER data and write to BIO. |
2647 | | * |
2648 | | * @param [in] bio BIO to write data to. |
2649 | | * @param [in] key Public key to encode. |
2650 | | * @return WOLFSSL_SUCCESS on success. |
2651 | | * @return WOLFSSL_FAILURE on failure. |
2652 | | */ |
2653 | | int wolfSSL_i2d_PUBKEY_bio(WOLFSSL_BIO* bio, const WOLFSSL_EVP_PKEY* key) |
2654 | 0 | { |
2655 | 0 | int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE); |
2656 | 0 | int derSz = 0; |
2657 | 0 | byte* der = NULL; |
2658 | 0 | byte* derPtr = NULL; |
2659 | |
|
2660 | 0 | WOLFSSL_ENTER("wolfSSL_i2d_PUBKEY_bio"); |
2661 | |
|
2662 | 0 | if (bio == NULL || key == NULL) { |
2663 | 0 | return WOLFSSL_FAILURE; |
2664 | 0 | } |
2665 | | |
2666 | 0 | derSz = wolfSSL_i2d_PUBKEY(key, NULL); |
2667 | 0 | if (derSz <= 0) { |
2668 | 0 | WOLFSSL_MSG("wolfSSL_i2d_PUBKEY size query failed"); |
2669 | 0 | return WOLFSSL_FAILURE; |
2670 | 0 | } |
2671 | | |
2672 | 0 | der = (byte*)XMALLOC((size_t)derSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); |
2673 | 0 | if (der == NULL) { |
2674 | 0 | WOLFSSL_MSG("XMALLOC failed"); |
2675 | 0 | return WOLFSSL_FAILURE; |
2676 | 0 | } |
2677 | | |
2678 | 0 | derPtr = der; |
2679 | 0 | derSz = wolfSSL_i2d_PUBKEY(key, &derPtr); |
2680 | 0 | if (derSz <= 0) { |
2681 | 0 | WOLFSSL_MSG("wolfSSL_i2d_PUBKEY failed"); |
2682 | 0 | goto cleanup; |
2683 | 0 | } |
2684 | | |
2685 | | /* A short write is reported as failure but is not rolled back: whatever |
2686 | | * reached the BIO stays there, like OpenSSL's i2d_PUBKEY_bio. */ |
2687 | 0 | if (wolfSSL_BIO_write(bio, der, derSz) != derSz) { |
2688 | 0 | WOLFSSL_MSG("wolfSSL_BIO_write failed; partial data may remain in BIO"); |
2689 | 0 | goto cleanup; |
2690 | 0 | } |
2691 | | |
2692 | 0 | ret = WOLFSSL_SUCCESS; |
2693 | |
|
2694 | 0 | cleanup: |
2695 | 0 | XFREE(der, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); |
2696 | 0 | return ret; |
2697 | 0 | } |
2698 | | #endif /* !NO_BIO */ |
2699 | | |
2700 | | #endif /* !NO_ASN && !NO_PWDBASED */ |
2701 | | |
2702 | | #endif /* OPENSSL_EXTRA */ |
2703 | | |
2704 | | #endif /* !NO_CERTS */ |
2705 | | |
2706 | | /******************************************************************************* |
2707 | | * END OF i2d APIs |
2708 | | ******************************************************************************/ |
2709 | | |
2710 | | #endif /* !WOLFSSL_EVP_PK_INCLUDED */ |
2711 | | |