Coverage Report

Created: 2026-04-05 07:22

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