Coverage Report

Created: 2026-09-20 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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