Coverage Report

Created: 2026-11-12 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl/src/ssl_load.c
Line
Count
Source
1
/* ssl_load.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
/*
25
 * WOLFSSL_SYS_CA_CERTS
26
 *     Enables ability to load system CA certs from the OS via
27
 *     wolfSSL_CTX_load_system_CA_certs.
28
 */
29
30
#ifdef WOLFSSL_SYS_CA_CERTS
31
/* Will be turned off automatically when NO_FILESYSTEM is defined
32
 * for non Mac/Windows systems */
33
34
#ifdef _WIN32
35
    #define _WINSOCKAPI_ /* block inclusion of winsock.h header file */
36
    #include <windows.h>
37
    #include <wincrypt.h>
38
    #undef _WINSOCKAPI_ /* undefine it for MINGW winsock2.h header file */
39
40
    /* mingw gcc does not support pragma comment, and the
41
     * linking with crypt32 is handled in configure.ac */
42
    #if !defined(__MINGW32__) && !defined(__MINGW64__)
43
        #pragma comment(lib, "crypt32")
44
    #endif
45
#endif
46
47
#if defined(__APPLE__)
48
#if defined(HAVE_SECURITY_SECTRUSTSETTINGS_H)
49
#include <Security/SecTrustSettings.h>
50
#endif /* HAVE_SECURITY_SECTRUSTSETTINGS_H */
51
#ifdef WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION
52
#include <CoreFoundation/CoreFoundation.h>
53
#endif /* WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION */
54
#endif /* __APPLE__ */
55
56
#endif /* WOLFSSL_SYS_CA_CERTS */
57
58
#if !defined(WOLFSSL_SSL_LOAD_INCLUDED)
59
    #ifndef WOLFSSL_IGNORE_FILE_WARN
60
        #warning ssl_load.c does not need to be compiled separately from ssl.c
61
    #endif
62
#else
63
64
#include <wolfssl/wolfcrypt/logging.h>
65
66
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
67
    /* PSK field of context when it exists. */
68
    #define CTX_HAVE_PSK(ctx)   (ctx)->havePSK
69
    /* PSK field of ssl when it exists. */
70
    #define SSL_HAVE_PSK(ssl)   (ssl)->options.havePSK
71
#else
72
    /* Have PSK value when no field. */
73
0
    #define CTX_HAVE_PSK(ctx)   0
74
    /* Have PSK value when no field. */
75
0
    #define SSL_HAVE_PSK(ssl)   0
76
#endif
77
#ifdef NO_RSA
78
    /* Boolean for RSA available. */
79
    #define WOLFSSL_HAVE_RSA    0
80
#else
81
    /* Boolean for RSA available. */
82
0
    #define WOLFSSL_HAVE_RSA    1
83
#endif
84
#ifndef NO_CERTS
85
    /* Private key size from ssl. */
86
0
    #define SSL_KEY_SZ(ssl)     (ssl)->buffers.keySz
87
#else
88
    /* Private key size not available. */
89
    #define SSL_KEY_SZ(ssl)     0
90
#endif
91
#ifdef HAVE_ANON
92
    /* Anonymous ciphersuite allowed field in context. */
93
    #define CTX_USE_ANON(ctx)   (ctx)->useAnon
94
#else
95
    /* Anonymous ciphersuite allowed field not in context. */
96
0
    #define CTX_USE_ANON(ctx)   0
97
#endif
98
99
#ifdef HAVE_PK_CALLBACKS
100
    #define WOLFSSL_IS_PRIV_PK_SET(ctx, ssl)                            \
101
        wolfSSL_CTX_IsPrivatePkSet(((ssl) == NULL) ? (ctx) : (ssl)->ctx)
102
#else
103
    #define WOLFSSL_IS_PRIV_PK_SET(ctx, ssl)    0
104
#endif
105
106
/* Get the heap from the context or the ssl depending on which is available. */
107
#define WOLFSSL_HEAP(ctx, ssl)                                              \
108
0
    (((ctx) != NULL) ? (ctx)->heap : (((ssl) != NULL) ? (ssl)->heap : NULL))
109
110
111
#ifndef NO_CERTS
112
113
/* Get DER encoding from data in a buffer as a DerBuffer.
114
 *
115
 * @param [in]      buff    Buffer containing data.
116
 * @param [in]      len     Length of data in buffer.
117
 * @param [in]      format  Format of data:
118
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
119
 * @param [in]      type    Type of data:
120
 *                            CERT_TYPE, CA_TYPE, TRUSTED_PEER_TYPE,
121
 *                            PRIVATEKEY_TYPE or ALT_PRIVATEKEY_TYPE.
122
 * @param [in, out] info    Info for encryption.
123
 * @param [in]      heap    Dynamic memory allocation hint.
124
 * @param [out]     der     Holds DER encoded data.
125
 * @param [out]     algId   Algorithm identifier for private keys.
126
 * @return  0 on success.
127
 * @return  NOT_COMPILED_IN when format is PEM and PEM not supported.
128
 * @return  ASN_PARSE_E when format is ASN.1 and invalid DER encoding.
129
 * @return  MEMORY_E when dynamic memory allocation fails.
130
 */
131
static int DataToDerBuffer(const unsigned char* buff, word32 len, int format,
132
    int type, EncryptedInfo* info, void* heap, DerBuffer** der, int* algId)
133
0
{
134
0
    int ret;
135
136
0
    info->consumed = 0;
137
138
    /* Data in buffer has PEM format - extract DER data. */
139
0
    if (format == WOLFSSL_FILETYPE_PEM) {
140
0
    #ifdef WOLFSSL_PEM_TO_DER
141
0
        ret = PemToDer(buff, (long)(len), type, der, heap, info, algId);
142
0
        if (ret != 0) {
143
0
            FreeDer(der);
144
0
        }
145
    #else
146
        (void)algId;
147
        ret = NOT_COMPILED_IN;
148
    #endif
149
0
    }
150
    /* Data in buffer is ASN.1 format - get first SEQ or OCT into der. */
151
0
    else {
152
        /* Get length of SEQ including header. */
153
0
        if ((info->consumed = wolfssl_der_length(buff, (int)len)) > 0) {
154
0
            ret = 0;
155
0
        }
156
0
        else {
157
0
            ret = ASN_PARSE_E;
158
0
        }
159
160
0
        if (info->consumed > (int)len) {
161
0
            ret = ASN_PARSE_E;
162
0
        }
163
0
        if (ret == 0) {
164
0
            ret = AllocCopyDer(der, buff, (word32)info->consumed, type, heap);
165
0
        }
166
0
    }
167
168
0
    return ret;
169
0
}
170
171
/* Process a user's certificate.
172
 *
173
 * Puts the 3-byte length before certificate data as required for TLS.
174
 * CA certificates are added to the certificate manager.
175
 *
176
 * @param [in]      cm           Certificate manager.
177
 * @param [in, out] pDer         DER encoded data.
178
 * @param [in]      type         Type of data. Valid values:
179
 *                                 CERT_TYPE, CA_TYPE or TRUSTED_PEER_TYPE.
180
 * @param [in]      verify       How to verify certificate.
181
 * @param [out]     chainBuffer  Buffer to hold chain of certificates.
182
 * @param [in, out] pIdx         On in, current index into chainBuffer.
183
 *                               On out, index after certificate added.
184
 * @param [in]      bufferSz     Size of buffer in bytes.
185
 * @return  0 on success.
186
 * @return  BUFFER_E if chain buffer not big enough to hold certificate.
187
 */
188
static int ProcessUserCert(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer,
189
    int type, int verify, byte* chainBuffer, word32* pIdx, word32 bufferSz)
190
0
{
191
0
    int ret = 0;
192
0
    word32 idx = *pIdx;
193
0
    DerBuffer* der = *pDer;
194
195
    /* Check there is space for certificate in chainBuffer. */
196
0
    if ((ret == 0) && ((idx + der->length + CERT_HEADER_SZ) > bufferSz)) {
197
0
        WOLFSSL_MSG("   Cert Chain bigger than buffer. "
198
0
                    "Consider increasing MAX_CHAIN_DEPTH");
199
0
        ret = BUFFER_E;
200
0
    }
201
0
    if (ret == 0) {
202
        /* 3-byte length. */
203
0
        c32to24(der->length, &chainBuffer[idx]);
204
0
        idx += CERT_HEADER_SZ;
205
        /* Add complete DER encoded certificate. */
206
0
        XMEMCPY(&chainBuffer[idx], der->buffer, der->length);
207
0
        idx += der->length;
208
209
0
        if (type == CA_TYPE) {
210
            /* Add CA to certificate manager */
211
0
            ret = AddCA(cm, pDer, WOLFSSL_USER_CA, verify);
212
0
            if (ret == 1) {
213
0
                ret = 0;
214
0
            }
215
0
        }
216
0
    }
217
218
    /* Update the index into chainBuffer. */
219
0
    *pIdx = idx;
220
0
    return ret;
221
0
}
222
223
/* Store the certificate chain buffer aganst WOLFSSL_CTX or WOLFSSL object.
224
 *
225
 * @param [in, out] ctx          SSL context object.
226
 * @param [in, out] ssl          SSL object.
227
 * @param [in]      chainBuffer  Buffer containing chain of certificates.
228
 * @param [in]      len          Length, in bytes, of data in buffer.
229
 * @param [in]      cnt          Number of certificates in chain.
230
 * @param [in]      type         Type of data. Valid values:
231
 *                                 CERT_TYPE, CA_TYPE or CHAIN_CERT_TYPE.
232
 * @param [in]      heap         Dynamic memory allocation hint.
233
 * @return  0 on success.
234
 * @return  MEMORY_E when dynamic memory allocation fails.
235
 */
236
static int ProcessUserChainRetain(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
237
    const byte* chainBuffer, word32 len, int cnt, int type, void* heap)
238
0
{
239
0
    int ret = 0;
240
241
0
    (void)cnt;
242
243
    /* Store in SSL object if available. */
244
0
    if (ssl != NULL) {
245
        /* Dispose of old chain if not reference to context's. */
246
0
        if (ssl->buffers.weOwnCertChain) {
247
0
            FreeDer(&ssl->buffers.certChain);
248
0
        }
249
        /* Allocate and copy the buffer into SSL object. */
250
0
        ret = AllocCopyDer(&ssl->buffers.certChain, chainBuffer, len, type,
251
0
            heap);
252
0
        ssl->buffers.weOwnCertChain = (ret == 0);
253
        /* Update count of certificates in chain. */
254
0
        ssl->buffers.certChainCnt = cnt;
255
0
    }
256
    /* Store in SSL context object if available. */
257
0
    else if (ctx != NULL) {
258
        /* Dispose of old chain and allocate and copy in new chain. */
259
0
        FreeDer(&ctx->certChain);
260
        /* Allocate and copy the buffer into SSL context object. */
261
0
        ret = AllocCopyDer(&ctx->certChain, chainBuffer, len, type, heap);
262
        /* Update count of certificates in chain. */
263
0
        ctx->certChainCnt = cnt;
264
0
    }
265
266
0
    return ret;
267
0
}
268
269
/* Process user cert chain to pass during the TLS handshake.
270
 *
271
 * If not a certificate type then data is ignored.
272
 *
273
 * @param [in, out] ctx     SSL context object.
274
 * @param [in, out] ssl     SSL object.
275
 * @param [in]      buff    Buffer holding certificates.
276
 * @param [in]      sz      Length of data in buffer.
277
 * @param [in]      format  Format of the certificate:
278
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1
279
 * @param [in]      type    Type of certificate:
280
 *                            CA_TYPE, CERT_TYPE or CHAIN_CERT_TYPE
281
 * @param [out]     used    Number of bytes from buff used.
282
 * @param [in, out] info    Encryption information.
283
 * @param [in]      verify  How to verify certificate.
284
 * @return  0 on success.
285
 * @return  BAD_FUNC_ARG when type is CA_TYPE and ctx is NULL.
286
 * @return  MEMORY_E when dynamic memory allocation fails.
287
 */
288
static int ProcessUserChain(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
289
    const unsigned char* buff, long sz, int format, int type, long* used,
290
    EncryptedInfo* info, int verify)
291
0
{
292
0
    int ret = 0;
293
0
    void* heap = WOLFSSL_HEAP(ctx, ssl);
294
295
0
    WOLFSSL_ENTER("ProcessUserChain");
296
297
    /* Check we haven't consumed all the data. */
298
0
    if (info->consumed >= sz) {
299
0
        WOLFSSL_MSG("Already consumed data");
300
0
    }
301
0
    else {
302
0
    #ifndef WOLFSSL_SMALL_STACK
303
0
        byte stackBuffer[FILE_BUFFER_SIZE];
304
0
    #endif
305
0
        StaticBuffer chain;
306
0
        long   consumed = info->consumed;
307
0
        word32 idx = 0;
308
0
        int    gotOne = 0;
309
0
        int    cnt = 0;
310
        /* Calculate max possible size, including max headers */
311
0
        long   maxSz = (sz - consumed) + (CERT_HEADER_SZ * MAX_CHAIN_DEPTH);
312
313
        /* Setup buffer to hold chain. */
314
    #ifdef WOLFSSL_SMALL_STACK
315
        static_buffer_init(&chain);
316
    #else
317
0
        static_buffer_init(&chain, stackBuffer, FILE_BUFFER_SIZE);
318
0
    #endif
319
        /* Make buffer big enough to support maximum size. */
320
0
        ret = static_buffer_set_size(&chain, (word32)maxSz, heap,
321
0
            DYNAMIC_TYPE_FILE);
322
323
0
        WOLFSSL_MSG("Processing Cert Chain");
324
        /* Keep parsing certificates will data available. */
325
0
        while ((ret == 0) && (consumed < sz)) {
326
0
            DerBuffer* part = NULL;
327
328
            /* Get a certificate as DER. */
329
0
            ret = DataToDerBuffer(buff + consumed, (word32)(sz - consumed),
330
0
                format, type, info, heap, &part, NULL);
331
0
            if (ret == 0) {
332
                /* Enforce maximum chain depth once a real cert is parsed. */
333
0
                if (cnt >= MAX_CHAIN_DEPTH) {
334
0
                    WOLFSSL_MSG("Chain depth limit reached");
335
0
                    FreeDer(&part);
336
0
                    ret = MAX_CHAIN_ERROR;
337
0
                    break;
338
0
                }
339
                /* Process the user certificate. */
340
0
                ret = ProcessUserCert(ctx->cm, &part, type, verify,
341
0
                   chain.buffer, &idx, (word32)maxSz);
342
0
            }
343
            /* PEM may have trailing data that can be ignored. */
344
0
            if ((ret == WC_NO_ERR_TRACE(ASN_NO_PEM_HEADER)) && gotOne) {
345
0
                WOLFSSL_MSG("We got one good cert, so stuff at end ok");
346
0
                ret = 0;
347
0
                break;
348
0
            }
349
            /* Certificate data handled. */
350
0
            FreeDer(&part);
351
352
0
            if (ret == 0) {
353
                /* Update consumed length. */
354
0
                consumed += info->consumed;
355
0
                WOLFSSL_MSG("   Consumed another Cert in Chain");
356
                /* Update whether we got a user certificate. */
357
0
                gotOne |= (type != CA_TYPE);
358
                /* Update count of certificates added to chain. */
359
0
                cnt++;
360
0
            }
361
0
        }
362
0
        if (used != NULL) {
363
            /* Return the total consumed length. */
364
0
            *used = consumed;
365
0
        }
366
367
        /* Check whether there is data in the chain buffer. */
368
0
        if ((ret == 0) && (idx > 0)) {
369
            /* Put the chain buffer against the SSL or SSL context object. */
370
0
            ret = ProcessUserChainRetain(ctx, ssl, chain.buffer, idx, cnt, type,
371
0
                heap);
372
0
        }
373
374
        /* Dispose of chain buffer. */
375
0
        static_buffer_free(&chain, heap, DYNAMIC_TYPE_FILE);
376
0
    }
377
378
0
    WOLFSSL_LEAVE("ProcessUserChain", ret);
379
0
    return ret;
380
0
}
381
382
#ifndef NO_RSA
383
#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \
384
    (HAVE_FIPS_VERSION > 2))
385
/* See if DER data is an RSA private key.
386
 *
387
 * Checks size meets minimum RSA key size.
388
 * This implementation uses less dynamic memory.
389
 *
390
 * @param [in, out] ctx        SSL context object.
391
 * @param [in, out] ssl        SSL object.
392
 * @param [in]      der        DER encoding.
393
 * @param [in, out] keyFormat  On in, expected format. 0 means unknown.
394
 * @param [in]      devId      Device identifier.
395
 * @param [out]     keyType    Type of key.
396
 * @param [out]     keySize    Size of key.
397
 * @return  0 on success or not an RSA key and format unknown.
398
 * @return  RSA_KEY_SIZE_E when key size doesn't meet minimum required.
399
 */
400
static int ProcessBufferTryDecodeRsa(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
401
    DerBuffer* der, int* keyFormat, int devId, byte* keyType, int* keySize)
402
0
{
403
0
    int ret;
404
0
    word32 idx;
405
0
    int keySz = 0;
406
407
0
    (void)devId;
408
409
    /* Validate we have an RSA private key and get key size. */
410
0
    idx = 0;
411
0
    ret = wc_RsaPrivateKeyValidate(der->buffer, &idx, &keySz, der->length);
412
#ifdef WOLF_PRIVATE_KEY_ID
413
    /* If that didn't work then maybe a public key if device ID or callback. */
414
    if ((ret != 0) && ((devId != INVALID_DEVID) ||
415
            WOLFSSL_IS_PRIV_PK_SET(ctx, ssl))) {
416
        word32 nSz;
417
418
        /* Decode as an RSA public key. */
419
        idx = 0;
420
        ret = wc_RsaPublicKeyDecode_ex(der->buffer, &idx, der->length, NULL,
421
            &nSz, NULL, NULL);
422
        if (ret == 0) {
423
            keySz = (int)nSz;
424
        }
425
    }
426
#endif
427
0
    if (ret == 0) {
428
        /* Get the minimum RSA key size from SSL or SSL context object. */
429
0
        int minRsaSz = ssl ? ssl->options.minRsaKeySz : ctx->minRsaKeySz;
430
431
        /* Format, type and size are known. */
432
0
        *keyFormat = RSAk;
433
0
        *keyType = rsa_sa_algo;
434
0
        *keySize = keySz;
435
436
        /* Check that the size of the RSA key is enough. */
437
0
        if (keySz < minRsaSz) {
438
0
            WOLFSSL_MSG("Private Key size too small");
439
0
            ret = RSA_KEY_SIZE_E;
440
0
        }
441
         /* No static ECC key possible. */
442
0
        if ((ssl != NULL) && (ssl->options.side == WOLFSSL_SERVER_END)) {
443
0
             ssl->options.haveStaticECC = 0;
444
0
        }
445
0
    }
446
    /* Not an RSA key but check whether we know what it is. */
447
0
    else if (*keyFormat == 0) {
448
0
        WOLFSSL_MSG("Not an RSA key");
449
        /* Format unknown so keep trying. */
450
0
        ret = 0;
451
0
    }
452
453
0
    return ret;
454
0
}
455
#else
456
/* See if DER data is an RSA private key.
457
 *
458
 * Checks size meets minimum RSA key size.
459
 * This implementation uses more dynamic memory but supports older FIPS.
460
 *
461
 * @param [in, out] ctx        SSL context object.
462
 * @param [in, out] ssl        SSL object.
463
 * @param [in]      der        DER encoding.
464
 * @param [in, out] keyFormat  On in, expected format. 0 means unknown.
465
 * @param [in]      heap       Dynamic memory allocation hint.
466
 * @param [in]      devId      Device identifier.
467
 * @param [out]     keyType    Type of key.
468
 * @param [out]     keySize    Size of key.
469
 * @return  0 on success or not an RSA key and format unknown.
470
 * @return  RSA_KEY_SIZE_E when key size doesn't meet minimum required.
471
 */
472
static int ProcessBufferTryDecodeRsa(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
473
    DerBuffer* der, int* keyFormat, void* heap, int devId, byte* keyType,
474
    int* keySize)
475
{
476
    int ret;
477
    word32 idx;
478
    /* make sure RSA key can be used */
479
    WC_DECLARE_VAR(key, RsaKey, 1, 0);
480
481
    /* Allocate an RSA key to parse into so we can get size. */
482
    WC_ALLOC_VAR_EX(key, RsaKey, 1, heap, DYNAMIC_TYPE_RSA,
483
        return MEMORY_E);
484
485
    /* Initialize the RSA key. */
486
    ret = wc_InitRsaKey_ex(key, heap, devId);
487
    if (ret == 0) {
488
        /* Check we have an RSA private key. */
489
        idx = 0;
490
        ret = wc_RsaPrivateKeyDecode(der->buffer, &idx, key, der->length);
491
    #ifdef WOLF_PRIVATE_KEY_ID
492
        /* If that didn't work then maybe a public key if device ID or callback.
493
         */
494
        if ((ret != 0) && ((devId != INVALID_DEVID) ||
495
                WOLFSSL_IS_PRIV_PK_SET(ctx, ssl))) {
496
            /* If that didn't work then maybe a public key if device ID or
497
             * callback. */
498
            idx = 0;
499
            ret = wc_RsaPublicKeyDecode(der->buffer, &idx, key, der->length);
500
        }
501
    #endif
502
        if (ret == 0) {
503
            /* Get the minimum RSA key size from SSL or SSL context object. */
504
            int minRsaSz = ssl ? ssl->options.minRsaKeySz : ctx->minRsaKeySz;
505
            int keySz = wc_RsaEncryptSize((RsaKey*)key);
506
507
            /* Format is known. */
508
            *keyFormat = RSAk;
509
            *keyType = rsa_sa_algo;
510
            *keySize = keySz;
511
512
            /* Check that the size of the RSA key is enough. */
513
            if (keySz < minRsaSz) {
514
                WOLFSSL_MSG("Private Key size too small");
515
                ret = RSA_KEY_SIZE_E;
516
            }
517
            /* No static ECC key possible. */
518
            if ((ssl != NULL) && (ssl->options.side == WOLFSSL_SERVER_END)) {
519
                 ssl->options.haveStaticECC = 0;
520
            }
521
        }
522
        /* Not an RSA key but check whether we know what it is. */
523
        else if (*keyFormat == 0) {
524
            WOLFSSL_MSG("Not an RSA key");
525
            /* Format unknown so keep trying. */
526
            ret = 0;
527
        }
528
529
        /* Free dynamically allocated data in key. */
530
        wc_FreeRsaKey(key);
531
    }
532
533
    WC_FREE_VAR_EX(key, heap, DYNAMIC_TYPE_RSA);
534
535
    return ret;
536
}
537
#endif
538
#endif /* !NO_RSA */
539
540
#ifdef HAVE_ECC
541
/* See if DER data is an ECC private key.
542
 *
543
 * Checks size meets minimum ECC key size.
544
 *
545
 * @param [in, out] ctx        SSL context object.
546
 * @param [in, out] ssl        SSL object.
547
 * @param [in]      der        DER encoding.
548
 * @param [in, out] keyFormat  On in, expected format. 0 means unknown.
549
 * @param [in]      heap       Dynamic memory allocation hint.
550
 * @param [in]      devId      Device identifier.
551
 * @param [out]     keyType    Type of key.
552
 * @param [out]     keySize    Size of key.
553
 * @return  0 on success or not an ECC key and format unknown.
554
 * @return  ECC_KEY_SIZE_E when ECC key size doesn't meet minimum required.
555
 */
556
static int ProcessBufferTryDecodeEcc(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
557
    DerBuffer* der, int* keyFormat, void* heap, int devId, byte* keyType,
558
    int* keySize)
559
0
{
560
0
    int ret = 0;
561
0
    word32 idx;
562
    /* make sure ECC key can be used */
563
0
    WC_DECLARE_VAR(key, ecc_key, 1, 0);
564
565
    /* Allocate an ECC key to parse into. */
566
0
    WC_ALLOC_VAR_EX(key, ecc_key, 1, heap, DYNAMIC_TYPE_ECC,
567
0
        return MEMORY_E);
568
569
    /* Initialize ECC key. */
570
0
    if (wc_ecc_init_ex(key, heap, devId) == 0) {
571
        /* Decode as an ECC private key. */
572
0
        idx = 0;
573
0
        ret = wc_EccPrivateKeyDecode(der->buffer, &idx, key, der->length);
574
    #ifdef WOLF_PRIVATE_KEY_ID
575
        /* If that didn't work then maybe a public key if device ID or callback.
576
         */
577
        if ((ret != 0) && ((devId != INVALID_DEVID) ||
578
                WOLFSSL_IS_PRIV_PK_SET(ctx, ssl))) {
579
            /* Decode as an ECC public key. */
580
            idx = 0;
581
            ret = wc_EccPublicKeyDecode(der->buffer, &idx, key, der->length);
582
        }
583
    #endif
584
    #ifdef WOLFSSL_SM2
585
        if (*keyFormat == SM2k) {
586
            ret = wc_ecc_set_curve(key, WOLFSSL_SM2_KEY_BITS / 8,
587
                ECC_SM2P256V1);
588
        }
589
    #endif
590
0
        if (ret == 0) {
591
            /* Get the minimum ECC key size from SSL or SSL context object. */
592
0
            int minKeySz = ssl ? ssl->options.minEccKeySz : ctx->minEccKeySz;
593
0
            int keySz = wc_ecc_size(key);
594
595
            /* Format is known. */
596
0
            *keyFormat = ECDSAk;
597
        #ifdef WOLFSSL_SM2
598
            if (key->dp->id == ECC_SM2P256V1) {
599
                *keyType = sm2_sa_algo;
600
            }
601
            else
602
        #endif
603
0
            {
604
0
                *keyType = ecc_dsa_sa_algo;
605
0
            }
606
0
            *keySize = keySz;
607
608
            /* Check that the size of the ECC key is enough. */
609
0
            if (keySz < minKeySz) {
610
0
                WOLFSSL_MSG("ECC private key too small");
611
0
                ret = ECC_KEY_SIZE_E;
612
0
            }
613
            /* Static ECC key possible. */
614
0
            if (ssl) {
615
0
                ssl->options.haveStaticECC = 1;
616
0
            }
617
0
            else {
618
0
                ctx->haveStaticECC = 1;
619
0
            }
620
0
        }
621
        /* Not an ECC key but check whether we know what it is. */
622
0
        else if (*keyFormat == 0) {
623
0
            WOLFSSL_MSG("Not an ECC key");
624
            /* Format unknown so keep trying. */
625
0
            ret = 0;
626
0
        }
627
628
        /* Free dynamically allocated data in key. */
629
0
        wc_ecc_free(key);
630
0
    }
631
632
0
    WC_FREE_VAR_EX(key, heap, DYNAMIC_TYPE_ECC);
633
0
    return ret;
634
0
}
635
#endif /* HAVE_ECC */
636
637
#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT)
638
/* See if DER data is an Ed25519 private key.
639
 *
640
 * Checks size meets minimum ECC key size.
641
 *
642
 * @param [in, out] ctx        SSL context object.
643
 * @param [in, out] ssl        SSL object.
644
 * @param [in]      der        DER encoding.
645
 * @param [in, out] keyFormat  On in, expected format. 0 means unknown.
646
 * @param [in]      heap       Dynamic memory allocation hint.
647
 * @param [in]      devId      Device identifier.
648
 * @param [out]     keyType    Type of key.
649
 * @param [out]     keySize    Size of key.
650
 * @return  0 on success or not an Ed25519 key and format unknown.
651
 * @return  ECC_KEY_SIZE_E when key size doesn't meet minimum required.
652
 */
653
static int ProcessBufferTryDecodeEd25519(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
654
    DerBuffer* der, int* keyFormat, void* heap, int devId, byte* keyType,
655
    int* keySize)
656
{
657
    int ret;
658
    word32 idx;
659
    /* make sure Ed25519 key can be used */
660
    WC_DECLARE_VAR(key, ed25519_key, 1, 0);
661
662
    /* Allocate an Ed25519 key to parse into. */
663
    WC_ALLOC_VAR_EX(key, ed25519_key, 1, heap, DYNAMIC_TYPE_ED25519,
664
        return MEMORY_E);
665
666
    /* Initialize Ed25519 key. */
667
    ret = wc_ed25519_init_ex(key, heap, devId);
668
    if (ret == 0) {
669
        /* Decode as an Ed25519 private key. */
670
        idx = 0;
671
        ret = wc_Ed25519PrivateKeyDecode(der->buffer, &idx, key, der->length);
672
    #ifdef WOLF_PRIVATE_KEY_ID
673
        /* If that didn't work then maybe a public key if device ID or callback.
674
         */
675
        if ((ret != 0) && ((devId != INVALID_DEVID) ||
676
                WOLFSSL_IS_PRIV_PK_SET(ctx, ssl))) {
677
            /* Decode as an Ed25519 public key. */
678
            idx = 0;
679
            ret = wc_Ed25519PublicKeyDecode(der->buffer, &idx, key,
680
                der->length);
681
        }
682
    #endif
683
        if (ret == 0) {
684
            /* Get the minimum ECC key size from SSL or SSL context object. */
685
            int minKeySz = ssl ? ssl->options.minEccKeySz : ctx->minEccKeySz;
686
687
            /* Format is known. */
688
            *keyFormat = ED25519k;
689
            *keyType = ed25519_sa_algo;
690
            *keySize = ED25519_KEY_SIZE;
691
692
            /* Check that the size of the ECC key is enough. */
693
            if (ED25519_KEY_SIZE < minKeySz) {
694
                WOLFSSL_MSG("ED25519 private key too small");
695
                ret = ECC_KEY_SIZE_E;
696
            }
697
            if (ssl != NULL) {
698
#if !defined(WOLFSSL_NO_CLIENT_AUTH) && !defined(NO_ED25519_CLIENT_AUTH)
699
                /* Ed25519 requires caching enabled for tracking message
700
                 * hash used in EdDSA_Update for signing */
701
                ssl->options.cacheMessages = 1;
702
#endif
703
            }
704
        }
705
        /* Not an Ed25519 key but check whether we know what it is. */
706
        else if (*keyFormat == 0) {
707
            WOLFSSL_MSG("Not an Ed25519 key");
708
            /* Format unknown so keep trying. */
709
            ret = 0;
710
        }
711
712
        /* Free dynamically allocated data in key. */
713
        wc_ed25519_free(key);
714
    }
715
716
    WC_FREE_VAR_EX(key, heap, DYNAMIC_TYPE_ED25519);
717
    return ret;
718
}
719
#endif /* HAVE_ED25519 && HAVE_ED25519_KEY_IMPORT */
720
721
#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT)
722
/* See if DER data is an Ed448 private key.
723
 *
724
 * Checks size meets minimum ECC key size.
725
 *
726
 * @param [in, out] ctx        SSL context object.
727
 * @param [in, out] ssl        SSL object.
728
 * @param [in]      der        DER encoding.
729
 * @param [in, out] keyFormat  On in, expected format. 0 means unknown.
730
 * @param [in]      heap       Dynamic memory allocation hint.
731
 * @param [in]      devId      Device identifier.
732
 * @param [out]     keyType    Type of key.
733
 * @param [out]     keySize    Size of key.
734
 * @return  0 on success or not an Ed448 key and format unknown.
735
 * @return  ECC_KEY_SIZE_E when key size doesn't meet minimum required.
736
 */
737
static int ProcessBufferTryDecodeEd448(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
738
    DerBuffer* der, int* keyFormat, void* heap, int devId, byte* keyType,
739
    int* keySize)
740
{
741
    int ret;
742
    word32 idx;
743
    /* make sure Ed448 key can be used */
744
    WC_DECLARE_VAR(key, ed448_key, 1, 0);
745
746
    /* Allocate an Ed448 key to parse into. */
747
    WC_ALLOC_VAR_EX(key, ed448_key, 1, heap, DYNAMIC_TYPE_ED448,
748
        return MEMORY_E);
749
750
    /* Initialize Ed448 key. */
751
    ret = wc_ed448_init_ex(key, heap, devId);
752
    if (ret == 0) {
753
        /* Decode as an Ed448 private key. */
754
        idx = 0;
755
        ret = wc_Ed448PrivateKeyDecode(der->buffer, &idx, key, der->length);
756
    #ifdef WOLF_PRIVATE_KEY_ID
757
        /* If that didn't work then maybe a public key if device ID or callback.
758
         */
759
        if ((ret != 0) && ((devId != INVALID_DEVID) ||
760
                WOLFSSL_IS_PRIV_PK_SET(ctx, ssl))) {
761
            /* Decode as an Ed448 public key. */
762
            idx = 0;
763
            ret = wc_Ed448PublicKeyDecode(der->buffer, &idx, key, der->length);
764
        }
765
    #endif
766
        if (ret == 0) {
767
            /* Get the minimum ECC key size from SSL or SSL context object. */
768
            int minKeySz = ssl ? ssl->options.minEccKeySz : ctx->minEccKeySz;
769
770
            /* Format is known. */
771
            *keyFormat = ED448k;
772
            *keyType = ed448_sa_algo;
773
            *keySize = ED448_KEY_SIZE;
774
775
            /* Check that the size of the ECC key is enough. */
776
            if (ED448_KEY_SIZE < minKeySz) {
777
                WOLFSSL_MSG("ED448 private key too small");
778
                ret = ECC_KEY_SIZE_E;
779
            }
780
        #if !defined(WOLFSSL_NO_CLIENT_AUTH) && !defined(NO_ED448_CLIENT_AUTH)
781
            if (ssl != NULL) {
782
                /* Ed448 requires caching enabled for tracking message
783
                 * hash used in EdDSA_Update for signing */
784
                ssl->options.cacheMessages = 1;
785
            }
786
        #endif
787
        }
788
        /* Not an Ed448 key but check whether we know what it is. */
789
        else if (*keyFormat == 0) {
790
            WOLFSSL_MSG("Not an Ed448 key");
791
            /* Format unknown so keep trying. */
792
            ret = 0;
793
        }
794
795
        /* Free dynamically allocated data in key. */
796
        wc_ed448_free(key);
797
    }
798
799
    WC_FREE_VAR_EX(key, heap, DYNAMIC_TYPE_ED448);
800
    return ret;
801
}
802
#endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT */
803
804
#if defined(HAVE_FALCON)
805
/* See if DER data is an Falcon private key.
806
 *
807
 * Checks size meets minimum Falcon key size.
808
 *
809
 * @param [in, out] ctx        SSL context object.
810
 * @param [in, out] ssl        SSL object.
811
 * @param [in]      der        DER encoding.
812
 * @param [in, out] keyFormat  On in, expected format. 0 means unknown.
813
 * @param [in]      heap       Dynamic memory allocation hint.
814
 * @param [in]      devId      Device identifier.
815
 * @param [out]     keyType    Type of key.
816
 * @param [out]     keySize    Size of key.
817
 * @return  0 on success or not an Falcon key and format unknown.
818
 * @return  FALCON_KEY_SIZE_E when key size doesn't meet minimum required.
819
 */
820
static int ProcessBufferTryDecodeFalcon(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
821
    DerBuffer* der, int* keyFormat, void* heap, byte* keyType, int* keySize)
822
{
823
    int ret;
824
    int inited = 0;
825
    falcon_key* key;
826
827
    /* Allocate a Falcon key to parse into. */
828
    key = (falcon_key*)XMALLOC(sizeof(falcon_key), heap, DYNAMIC_TYPE_FALCON);
829
    if (key == NULL) {
830
        return MEMORY_E;
831
    }
832
833
    /* Initialize Falcon key. The struct came from 'heap' and, with
834
     * WOLFSSL_FALCON_DYNAMIC_KEYS, so must its encoded-key buffers. */
835
    ret = wc_falcon_init_ex(key, heap, INVALID_DEVID);
836
    if (ret == 0) {
837
        byte level = 0;
838
        word32 idx;
839
840
        inited = 1;
841
        if (*keyFormat == FALCON_LEVEL1k) {
842
            level = 1;
843
        }
844
        else if (*keyFormat == FALCON_LEVEL5k) {
845
            level = 5;
846
        }
847
848
        if (level != 0) {
849
            /* Caller told us the level via the OID sum. */
850
            ret = wc_falcon_set_level(key, level);
851
            if (ret == 0) {
852
                idx = 0;
853
                ret = wc_Falcon_PrivateKeyDecode(der->buffer, &idx, key,
854
                                                  der->length);
855
            }
856
        }
857
        else if (*keyFormat == 0) {
858
            int lvlRet;
859
860
            /* Key format unknown. Try both levels; the expected OID inside
861
             * wc_Falcon_PrivateKeyDecode rejects non-matching DER. Re-init
862
             * between attempts so a partial first decode can't leave stale
863
             * bytes in key->k / key->p. */
864
            idx = 0;
865
            lvlRet = wc_falcon_set_level(key, 1);
866
            if (lvlRet == WC_NO_ERR_TRACE(MEMORY_E)) {
867
                wc_falcon_free(key);
868
                XFREE(key, heap, DYNAMIC_TYPE_FALCON);
869
                return MEMORY_E;
870
            }
871
            if ((lvlRet == 0) &&
872
                (wc_Falcon_PrivateKeyDecode(der->buffer, &idx, key,
873
                                            der->length) == 0)) {
874
                level = 1;
875
            }
876
            else {
877
                /* Only an attempt that ran can have dirtied the key: a level
878
                 * that was not built returns before touching it. */
879
                if (lvlRet == 0) {
880
                    wc_falcon_free(key);
881
                    if (wc_falcon_init_ex(key, heap, INVALID_DEVID) != 0) {
882
                        XFREE(key, heap, DYNAMIC_TYPE_FALCON);
883
                        return MEMORY_E;
884
                    }
885
                }
886
                idx = 0;
887
                lvlRet = wc_falcon_set_level(key, 5);
888
                if (lvlRet == WC_NO_ERR_TRACE(MEMORY_E)) {
889
                    wc_falcon_free(key);
890
                    XFREE(key, heap, DYNAMIC_TYPE_FALCON);
891
                    return MEMORY_E;
892
                }
893
                if ((lvlRet == 0) &&
894
                    (wc_Falcon_PrivateKeyDecode(der->buffer, &idx, key,
895
                                                der->length) == 0)) {
896
                    level = 5;
897
                }
898
            }
899
            if (level == 0) {
900
                /* Not a Falcon key; let caller try another algorithm. */
901
                WOLFSSL_MSG("Not a Falcon key");
902
                wc_falcon_free(key);
903
                XFREE(key, heap, DYNAMIC_TYPE_FALCON);
904
                return 0;
905
            }
906
            ret = 0;
907
        }
908
        else {
909
            ret = ALGO_ID_E;
910
        }
911
    }
912
913
    if (ret == 0) {
914
        /* Get the minimum Falcon key size from SSL or SSL context object. */
915
        int minKeySz = ssl ? ssl->options.minFalconKeySz :
916
                             ctx->minFalconKeySz;
917
918
        if (key->level == 1) {
919
            *keyFormat = FALCON_LEVEL1k;
920
            *keyType = falcon_level1_sa_algo;
921
            *keySize = FALCON_LEVEL1_KEY_SIZE;
922
        }
923
        else {
924
            *keyFormat = FALCON_LEVEL5k;
925
            *keyType = falcon_level5_sa_algo;
926
            *keySize = FALCON_LEVEL5_KEY_SIZE;
927
        }
928
929
        /* Check that the size of the Falcon key is enough. */
930
        if (*keySize < minKeySz) {
931
            WOLFSSL_MSG("Falcon private key too small");
932
            ret = FALCON_KEY_SIZE_E;
933
        }
934
    }
935
    else if ((ret == WC_NO_ERR_TRACE(ALGO_ID_E)) && (*keyFormat == 0)) {
936
        WOLFSSL_MSG("Not a Falcon key");
937
        /* Format unknown so keep trying. */
938
        ret = 0;
939
    }
940
941
    /* Dispose of allocated key. With WOLFSSL_FALCON_DYNAMIC_KEYS the structure
942
     * owns heap buffers, so XFREE alone would leak. */
943
    if (inited) {
944
        wc_falcon_free(key);
945
    }
946
    XFREE(key, heap, DYNAMIC_TYPE_FALCON);
947
    return ret;
948
}
949
#endif
950
951
#if defined(WOLFSSL_HAVE_MLDSA) && !defined(WOLFSSL_MLDSA_NO_SIGN) && \
952
    !defined(WOLFSSL_MLDSA_NO_ASN1)
953
/* See if DER data is an Dilithium private key.
954
 *
955
 * Checks size meets minimum Falcon key size.
956
 *
957
 * @param [in, out] ctx        SSL context object.
958
 * @param [in, out] ssl        SSL object.
959
 * @param [in]      der        DER encoding.
960
 * @param [in, out] keyFormat  On in, expected format. 0 means unknown.
961
 * @param [in]      heap       Dynamic memory allocation hint.
962
 * @param [in]      devId      Device identifier.
963
 * @param [out]     keyType    Type of key.
964
 * @param [out]     keySize    Size of key.
965
 * @return  0 on success or not a Dilithium key and format unknown.
966
 * @return  MLDSA_KEY_SIZE_E when key size doesn't meet minimum required.
967
 */
968
static int ProcessBufferTryDecodeMlDsa(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
969
    DerBuffer* der, int* keyFormat, void* heap, byte* keyType, int* keySize)
970
{
971
    int ret;
972
    word32 idx;
973
    wc_MlDsaKey* key;
974
    int keyFormatTemp = 0;
975
    int keyTypeTemp = 0;
976
    int keySizeTemp = 0;
977
978
    /* Allocate a Dilithium key to parse into. */
979
    key = (wc_MlDsaKey*)XMALLOC(sizeof(wc_MlDsaKey), heap,
980
        DYNAMIC_TYPE_MLDSA);
981
    if (key == NULL) {
982
        return MEMORY_E;
983
    }
984
985
    /* Initialize ML-DSA key. */
986
    ret = wc_MlDsaKey_Init(key, NULL, INVALID_DEVID);
987
    if (ret == 0) {
988
        /* Decode as an ML-DSA private key. The FIPS wrapper for
989
         * wc_MlDsaKey_ImportPrivRaw gates on the per-thread
990
         * privateKeyReadEnable flag, which is unset by default in any
991
         * thread that hasn't called PRIVATE_KEY_UNLOCK(). Without the
992
         * bracket, loading an ML-DSA private key from a worker thread
993
         * fails with FIPS_PRIVATE_KEY_LOCKED_E. */
994
        idx = 0;
995
        PRIVATE_KEY_UNLOCK();
996
        ret = wc_MlDsaKey_PrivateKeyDecode(key, der->buffer,
997
            der->length, &idx);
998
        PRIVATE_KEY_LOCK();
999
        if (ret == 0) {
1000
            ret = mldsa_get_oid_sum(key, &keyFormatTemp);
1001
            if (ret == 0) {
1002
                /* Format is known. */
1003
                #if defined(WOLFSSL_MLDSA_FIPS204_DRAFT)
1004
                if (keyFormatTemp == DILITHIUM_LEVEL2k) {
1005
                    keyTypeTemp = mldsa_44_sa_algo;
1006
                    keySizeTemp = WC_MLDSA_44_KEY_SIZE;
1007
                }
1008
                else if (keyFormatTemp == DILITHIUM_LEVEL3k) {
1009
                    keyTypeTemp = mldsa_65_sa_algo;
1010
                    keySizeTemp = WC_MLDSA_65_KEY_SIZE;
1011
                }
1012
                else if (keyFormatTemp == DILITHIUM_LEVEL5k) {
1013
                    keyTypeTemp = mldsa_87_sa_algo;
1014
                    keySizeTemp = WC_MLDSA_87_KEY_SIZE;
1015
                }
1016
                else
1017
                #endif /* WOLFSSL_MLDSA_FIPS204_DRAFT */
1018
                if (keyFormatTemp == ML_DSA_44k) {
1019
                    keyTypeTemp = mldsa_44_sa_algo;
1020
                    keySizeTemp = WC_MLDSA_44_KEY_SIZE;
1021
                }
1022
                else if (keyFormatTemp == ML_DSA_65k) {
1023
                    keyTypeTemp = mldsa_65_sa_algo;
1024
                    keySizeTemp = WC_MLDSA_65_KEY_SIZE;
1025
                }
1026
                else if (keyFormatTemp == ML_DSA_87k) {
1027
                    keyTypeTemp = mldsa_87_sa_algo;
1028
                    keySizeTemp = WC_MLDSA_87_KEY_SIZE;
1029
                }
1030
                else {
1031
                    ret = ALGO_ID_E;
1032
                }
1033
            }
1034
1035
            if (ret == 0) {
1036
                /* Get the minimum Dilithium key size from SSL or SSL context
1037
                 * object. */
1038
                int minKeySz = ssl ? ssl->options.minMlDsaKeySz :
1039
                                     ctx->minMlDsaKeySz;
1040
1041
                /* Check that the size of the Dilithium key is enough. */
1042
                if (keySizeTemp < minKeySz) {
1043
                    WOLFSSL_MSG("ML-DSA private key too small");
1044
                    ret = MLDSA_KEY_SIZE_E;
1045
                }
1046
            }
1047
1048
            if (ret == 0) {
1049
                *keyFormat = keyFormatTemp;
1050
                *keyType = keyTypeTemp;
1051
                *keySize = keySizeTemp;
1052
            }
1053
        }
1054
        else if (*keyFormat == 0) {
1055
            WOLFSSL_MSG("Not an ML-DSA key");
1056
            /* Unknown format wasn't dilithium, so keep trying other formats. */
1057
            ret = 0;
1058
        }
1059
1060
        /* Free dynamically allocated data in key. */
1061
        wc_MlDsaKey_Free(key);
1062
    }
1063
1064
    /* Dispose of allocated key. */
1065
    XFREE(key, heap, DYNAMIC_TYPE_MLDSA);
1066
    return ret;
1067
}
1068
#endif /* WOLFSSL_HAVE_MLDSA */
1069
1070
#if defined(WOLFSSL_HAVE_SLHDSA) && !defined(WOLFSSL_SLHDSA_VERIFY_ONLY)
1071
/* Try to decode the DER encoding as an SLH-DSA private key.
1072
 *
1073
 * @param [in]      ctx        SSL context object.
1074
 * @param [in]      ssl        SSL object.
1075
 * @param [in]      der        DER encoding.
1076
 * @param [in, out] keyFormat  On in, expected format. 0 means unknown.
1077
 * @param [in]      heap       Dynamic memory allocation hint.
1078
 * @param [out]     keyType    Type of key (an slhdsa_*_sa_algo).
1079
 * @param [out]     keySize    Size of the private key.
1080
 * @return  0 on success or when not an SLH-DSA key (with keyFormat 0).
1081
 */
1082
static int ProcessBufferTryDecodeSlhDsa(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
1083
    DerBuffer* der, int* keyFormat, void* heap, byte* keyType, int* keySize)
1084
{
1085
    int ret;
1086
    word32 idx;
1087
    SlhDsaKey* key;
1088
    int keyTypeTemp = 0;
1089
    int keySizeTemp = 0;
1090
1091
    (void)ctx;
1092
    (void)ssl;
1093
1094
    /* Allocate an SLH-DSA key to parse into. */
1095
    key = (SlhDsaKey*)XMALLOC(sizeof(SlhDsaKey), heap, DYNAMIC_TYPE_SLHDSA);
1096
    if (key == NULL) {
1097
        return MEMORY_E;
1098
    }
1099
1100
    /* Clear the key so the unconditional Free below is well defined whatever
1101
     * wc_SlhDsaKey_Init returns. */
1102
    XMEMSET(key, 0, sizeof(SlhDsaKey));
1103
1104
    /* Initialise with an always-present placeholder parameter set;
1105
     * wc_SlhDsaKey_PrivateKeyDecode selects the real one from the key's
1106
     * algorithm OID. */
1107
    ret = wc_SlhDsaKey_Init(key, WC_SLHDSA_DEFAULT_PARAM, heap, INVALID_DEVID);
1108
    if (ret == 0) {
1109
        idx = 0;
1110
        PRIVATE_KEY_UNLOCK();
1111
        ret = wc_SlhDsaKey_PrivateKeyDecode(der->buffer, &idx, key,
1112
            der->length);
1113
        PRIVATE_KEY_LOCK();
1114
        if (ret == 0) {
1115
            int param = (int)key->params->param;
1116
1117
            keyTypeTemp = SlhDsaParamToType(param);
1118
            if (keyTypeTemp == (byte)invalid_sa_algo) {
1119
                ret = ALGO_ID_E;
1120
            }
1121
            else {
1122
                keySizeTemp = wc_SlhDsaKey_PrivateSize(key);
1123
                if (keySizeTemp <= 0) {
1124
                    ret = ALGO_ID_E;
1125
                }
1126
            }
1127
1128
            if (ret == 0) {
1129
                int oidSum = wc_SlhDsaParamToOid((enum SlhDsaParam)param);
1130
1131
                /* Negative for an unknown or disabled parameter set; storing it
1132
                 * would leave a nonsense key format behind a zero return. */
1133
                if (oidSum <= 0) {
1134
                    ret = ALGO_ID_E;
1135
                }
1136
                else {
1137
                    *keyFormat = oidSum;
1138
                    *keyType = (byte)keyTypeTemp;
1139
                    *keySize = keySizeTemp;
1140
                }
1141
            }
1142
        }
1143
        else if (*keyFormat == 0) {
1144
            WOLFSSL_MSG("Not an SLH-DSA key");
1145
            /* Unknown format wasn't SLH-DSA, so keep trying other formats. */
1146
            ret = 0;
1147
        }
1148
    }
1149
1150
    /* Free any data allocated by wc_SlhDsaKey_Init(). This also runs when Init
1151
     * failed part way through, releasing any hash objects allocated before the
1152
     * failure; it is a no-op once the key's parameter set has been cleared. */
1153
    wc_SlhDsaKey_Free(key);
1154
1155
    /* Dispose of allocated key. */
1156
    XFREE(key, heap, DYNAMIC_TYPE_SLHDSA);
1157
    return ret;
1158
}
1159
#endif /* WOLFSSL_HAVE_SLHDSA */
1160
1161
/* Try to decode DER data is a known private key.
1162
 *
1163
 * Checks size meets minimum for key type.
1164
 *
1165
 * @param [in, out] ctx        SSL context object.
1166
 * @param [in, out] ssl        SSL object.
1167
 * @param [in]      der        DER encoding.
1168
 * @param [in, out] keyFormat  On in, expected format. 0 means unknown.
1169
 * @param [in]      heap       Dynamic memory allocation hint.
1170
 * @param [out]     type       Type of key:
1171
 *                               PRIVATEKEY_TYPE or ALT_PRIVATEKEY_TYPE.
1172
 * @return  0 on success.
1173
 * @return  BAD_FUNC_ARG when der or keyFormat is NULL.
1174
 * @return  BAD_FUNC_ARG when ctx and ssl are NULL.
1175
 * @return  WOLFSSL_BAD_FILE when unable to identify the key format.
1176
 */
1177
static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
1178
    DerBuffer* der, int* keyFormat, void* heap, int type)
1179
0
{
1180
0
    int ret = 0;
1181
0
    int devId = wolfSSL_CTX_GetDevId(ctx, ssl);
1182
0
    byte* keyType = NULL;
1183
0
    int* keySz = NULL;
1184
0
    int matchAnyKey = 0;
1185
1186
0
    (void)heap;
1187
0
    (void)devId;
1188
0
    (void)type;
1189
    /* Only the per-algorithm decoders below read these back. */
1190
0
    (void)keyType;
1191
0
    (void)keySz;
1192
1193
    /* Validate parameters. */
1194
0
    if ((der == NULL) || (keyFormat == NULL)) {
1195
0
        ret = BAD_FUNC_ARG;
1196
0
    }
1197
    /* Must have an SSL context or SSL object to use. */
1198
0
    if ((ret == 0) && (ctx == NULL) && (ssl == NULL)) {
1199
0
        ret = BAD_FUNC_ARG;
1200
0
    }
1201
1202
0
    if (ret == 0) {
1203
        /* Determine where to put key type and size in SSL or context object. */
1204
    #ifdef WOLFSSL_DUAL_ALG_CERTS
1205
        if (type == ALT_PRIVATEKEY_TYPE) {
1206
            if (ssl != NULL) {
1207
                keyType = &ssl->buffers.altKeyType;
1208
                keySz = &ssl->buffers.altKeySz;
1209
            }
1210
            else {
1211
                keyType = &ctx->altPrivateKeyType;
1212
                keySz = &ctx->altPrivateKeySz;
1213
            }
1214
        }
1215
        else
1216
    #endif
1217
        /* Type is PRIVATEKEY_TYPE. */
1218
0
        if (ssl != NULL) {
1219
0
            keyType = &ssl->buffers.keyType;
1220
0
            keySz = &ssl->buffers.keySz;
1221
0
        }
1222
0
        else {
1223
0
            keyType = &ctx->privateKeyType;
1224
0
            keySz = &ctx->privateKeySz;
1225
0
        }
1226
0
    }
1227
1228
0
#ifndef NO_RSA
1229
    /* Try RSA if key format is RSA or yet unknown. */
1230
0
    if ((ret == 0) && ((*keyFormat == 0) || (*keyFormat == RSAk))) {
1231
0
#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \
1232
0
    (HAVE_FIPS_VERSION > 2))
1233
0
        ret = ProcessBufferTryDecodeRsa(ctx, ssl, der, keyFormat, devId,
1234
0
            keyType, keySz);
1235
#else
1236
        ret = ProcessBufferTryDecodeRsa(ctx, ssl, der, keyFormat, heap, devId,
1237
            keyType, keySz);
1238
#endif
1239
0
        matchAnyKey = 1;
1240
0
    }
1241
0
#ifdef WC_RSA_PSS
1242
0
    if((ret == 0) && (*keyFormat == RSAPSSk)) {
1243
        /* Require logic to verify that the der is RSAPSSk
1244
         * (when *keyFormat == RSAPSSK), and to detect that the der is RSAPSSk
1245
         * (when *keyFormat == 0). */
1246
0
        matchAnyKey = 1;
1247
0
    }
1248
0
#endif /* WC_RSA_PSS */
1249
0
#endif /* NO_RSA */
1250
0
#ifdef HAVE_ECC
1251
    /* Try ECC if key format is ECDSA or SM2, or yet unknown. */
1252
0
    if ((ret == 0) && ((*keyFormat == 0) || (*keyFormat == ECDSAk)
1253
    #ifdef WOLFSSL_SM2
1254
        || (*keyFormat == SM2k)
1255
    #endif
1256
0
        )) {
1257
0
        ret = ProcessBufferTryDecodeEcc(ctx, ssl, der, keyFormat, heap, devId,
1258
0
            keyType, keySz);
1259
0
        matchAnyKey = 1;
1260
0
    }
1261
0
#endif /* HAVE_ECC */
1262
#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT)
1263
    /* Try Ed25519 if key format is Ed25519 or yet unknown. */
1264
    if ((ret == 0) && ((*keyFormat == 0 || *keyFormat == ED25519k))) {
1265
        ret = ProcessBufferTryDecodeEd25519(ctx, ssl, der, keyFormat, heap,
1266
            devId, keyType, keySz);
1267
        matchAnyKey = 1;
1268
    }
1269
#endif /* HAVE_ED25519 && HAVE_ED25519_KEY_IMPORT */
1270
#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT)
1271
    /* Try Ed448 if key format is Ed448 or yet unknown. */
1272
    if ((ret == 0) && ((*keyFormat == 0 || *keyFormat == ED448k))) {
1273
        ret = ProcessBufferTryDecodeEd448(ctx, ssl, der, keyFormat, heap, devId,
1274
            keyType, keySz);
1275
        matchAnyKey = 1;
1276
    }
1277
#endif /* HAVE_ED448 && HAVE_ED448_KEY_IMPORT */
1278
#if defined(HAVE_FALCON)
1279
    /* Try Falcon if key format is Falcon level 1k or 5k or yet unknown. */
1280
    if ((ret == 0) && ((*keyFormat == 0) || (*keyFormat == FALCON_LEVEL1k) ||
1281
            (*keyFormat == FALCON_LEVEL5k))) {
1282
        ret = ProcessBufferTryDecodeFalcon(ctx, ssl, der, keyFormat, heap,
1283
            keyType, keySz);
1284
        matchAnyKey = 1;
1285
    }
1286
#endif /* HAVE_FALCON */
1287
#if defined(WOLFSSL_HAVE_MLDSA) && !defined(WOLFSSL_MLDSA_NO_SIGN) && \
1288
    !defined(WOLFSSL_MLDSA_NO_ASN1)
1289
    /* Try Falcon if key format is Dilithium level 2k, 3k or 5k or yet unknown.
1290
     */
1291
    if ((ret == 0) &&
1292
        ((*keyFormat == 0) ||
1293
        (*keyFormat == ML_DSA_44k) ||
1294
        (*keyFormat == ML_DSA_65k) ||
1295
        (*keyFormat == ML_DSA_87k)
1296
    #ifdef WOLFSSL_MLDSA_FIPS204_DRAFT
1297
     || (*keyFormat == DILITHIUM_LEVEL2k)
1298
     || (*keyFormat == DILITHIUM_LEVEL3k)
1299
     || (*keyFormat == DILITHIUM_LEVEL5k)
1300
    #endif
1301
        )) {
1302
        ret = ProcessBufferTryDecodeMlDsa(ctx, ssl, der, keyFormat, heap,
1303
            keyType, keySz);
1304
        matchAnyKey = 1;
1305
    }
1306
#endif /* WOLFSSL_HAVE_MLDSA */
1307
#if defined(WOLFSSL_HAVE_SLHDSA) && !defined(WOLFSSL_SLHDSA_VERIFY_ONLY)
1308
    /* Try SLH-DSA if key format is an SLH-DSA key OID or yet unknown. */
1309
    if ((ret == 0) &&
1310
        ((*keyFormat == 0) ||
1311
         (*keyFormat == SLH_DSA_SHA2_128Sk) ||
1312
         (*keyFormat == SLH_DSA_SHA2_128Fk) ||
1313
         (*keyFormat == SLH_DSA_SHA2_192Sk) ||
1314
         (*keyFormat == SLH_DSA_SHA2_192Fk) ||
1315
         (*keyFormat == SLH_DSA_SHA2_256Sk) ||
1316
         (*keyFormat == SLH_DSA_SHA2_256Fk) ||
1317
         (*keyFormat == SLH_DSA_SHAKE_128Sk) ||
1318
         (*keyFormat == SLH_DSA_SHAKE_128Fk) ||
1319
         (*keyFormat == SLH_DSA_SHAKE_192Sk) ||
1320
         (*keyFormat == SLH_DSA_SHAKE_192Fk) ||
1321
         (*keyFormat == SLH_DSA_SHAKE_256Sk) ||
1322
         (*keyFormat == SLH_DSA_SHAKE_256Fk))) {
1323
        ret = ProcessBufferTryDecodeSlhDsa(ctx, ssl, der, keyFormat, heap,
1324
            keyType, keySz);
1325
        matchAnyKey = 1;
1326
    }
1327
#endif /* WOLFSSL_HAVE_SLHDSA */
1328
1329
    /* Check we know the format. */
1330
0
    if ((ret == 0) &&
1331
0
        ((*keyFormat == 0) || ((*keyFormat != 0) && (matchAnyKey == 0)))) {
1332
0
        WOLFSSL_MSG("Not a supported key type");
1333
        /* Not supported key format. */
1334
0
        ret = WOLFSSL_BAD_FILE;
1335
0
    }
1336
1337
0
    return ret;
1338
0
}
1339
1340
#if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED)
1341
/* Decrypt PKCS#8 private key.
1342
 *
1343
 * @param [in] info   Encryption information.
1344
 * @param [in] der    DER encoded data.
1345
 * @param [in] heap   Dynamic memory allocation hint.
1346
 * @return  0 on success.
1347
 * @return  MEMORY_E when dynamic memory allocation fails.
1348
 */
1349
static int ProcessBufferPrivPkcs8Dec(EncryptedInfo* info, DerBuffer* der,
1350
    void* heap)
1351
{
1352
    int ret = 0;
1353
    word32 algId;
1354
    int   passwordSz = NAME_SZ;
1355
    WC_DECLARE_VAR(password, char, NAME_SZ, 0);
1356
1357
    (void)heap;
1358
#ifdef WOLFSSL_SMALL_STACK
1359
    /* Allocate memory for password. */
1360
    password = (char*)XMALLOC(passwordSz, heap, DYNAMIC_TYPE_STRING);
1361
    if (password == NULL) {
1362
        ret = MEMORY_E;
1363
    }
1364
#endif
1365
1366
    if (ret == 0) {
1367
        /* Get password. */
1368
        ret = info->passwd_cb(password, passwordSz, PEM_PASS_READ,
1369
            info->passwd_userdata);
1370
    }
1371
    if (ret >= 0) {
1372
        /* Returned value is password size. */
1373
        passwordSz = ret;
1374
    #ifdef WOLFSSL_CHECK_MEM_ZERO
1375
        wc_MemZero_Add("ProcessBuffer password", password, passwordSz);
1376
    #endif
1377
1378
        /* Decrypt PKCS#8 private key inline and get algorithm id. */
1379
        ret = ToTraditionalEnc(der->buffer, der->length, password, passwordSz,
1380
            &algId);
1381
    }
1382
    if (ret >= 0) {
1383
        /* Zero out encrypted data not overwritten. */
1384
        ForceZero(der->buffer + ret, der->length - (word32)ret);
1385
        /* Set decrypted data length. */
1386
        der->length = (word32)ret;
1387
    }
1388
1389
#ifdef WOLFSSL_SMALL_STACK
1390
    if (password != NULL)
1391
#endif
1392
    {
1393
        /* Ensure password is zeroized. */
1394
        ForceZero(password, (word32)passwordSz);
1395
    }
1396
#ifdef WOLFSSL_SMALL_STACK
1397
    /* Dispose of password memory. */
1398
    XFREE(password, heap, DYNAMIC_TYPE_STRING);
1399
#elif defined(WOLFSSL_CHECK_MEM_ZERO)
1400
    wc_MemZero_Check(password, NAME_SZ);
1401
#endif
1402
    return ret;
1403
}
1404
#endif /* WOLFSSL_ENCRYPTED_KEYS && !NO_PWDBASED */
1405
1406
/* Put the DER into the SSL or SSL context object.
1407
 *
1408
 * Precondition: ctx or ssl is not NULL.
1409
 * Precondition: Must be a private key type.
1410
 *
1411
 * @param [in, out] ctx  SSL context object.
1412
 * @param [in, out] ssl  SSL object.
1413
 * @param [in]      der  DER encoding.
1414
 * @return  0 on success.
1415
 */
1416
static int ProcessBufferPrivKeyHandleDer(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
1417
    DerBuffer** der, int type)
1418
0
{
1419
0
    int ret = 0;
1420
1421
0
    (void)type;
1422
1423
#ifdef WOLFSSL_DUAL_ALG_CERTS
1424
    if (type == ALT_PRIVATEKEY_TYPE) {
1425
        /* Put in alternate private key fields of objects. */
1426
        if (ssl != NULL) {
1427
            /* Dispose of previous key if not context's. */
1428
            if (ssl->buffers.weOwnAltKey) {
1429
                FreeKeyDer(&ssl->buffers.altKey);
1430
            #ifdef WOLFSSL_BLIND_PRIVATE_KEY
1431
                FreeDer(&ssl->buffers.altKeyMask);
1432
            #endif
1433
            }
1434
            ssl->buffers.altKeyId = 0;
1435
            ssl->buffers.altKeyLabel = 0;
1436
            ssl->buffers.altKeyDevId = INVALID_DEVID;
1437
            /* Store key by reference and own it. */
1438
            ssl->buffers.altKey = *der;
1439
        #ifdef WOLFSSL_CHECK_MEM_ZERO
1440
            wc_MemZero_Add("SSL Buffers key", (*der)->buffer, (*der)->length);
1441
        #endif
1442
            ssl->buffers.weOwnAltKey = 1;
1443
        }
1444
        else if (ctx != NULL) {
1445
            /* Dispose of previous key. */
1446
            FreeKeyDer(&ctx->altPrivateKey);
1447
            ctx->altPrivateKeyId = 0;
1448
            ctx->altPrivateKeyLabel = 0;
1449
            ctx->altPrivateKeyDevId = INVALID_DEVID;
1450
            /* Store key by reference. */
1451
            ctx->altPrivateKey = *der;
1452
        #ifdef WOLFSSL_CHECK_MEM_ZERO
1453
            wc_MemZero_Add("CTX private key", (*der)->buffer, (*der)->length);
1454
        #endif
1455
        }
1456
    }
1457
    else
1458
#endif /* WOLFSSL_DUAL_ALG_CERTS */
1459
0
    if (ssl != NULL) {
1460
        /* Dispose of previous key if not context's. */
1461
0
        if (ssl->buffers.weOwnKey) {
1462
0
            FreeKeyDer(&ssl->buffers.key);
1463
        #ifdef WOLFSSL_BLIND_PRIVATE_KEY
1464
            FreeDer(&ssl->buffers.keyMask);
1465
        #endif
1466
0
        }
1467
0
        ssl->buffers.keyId = 0;
1468
0
        ssl->buffers.keyLabel = 0;
1469
0
        ssl->buffers.keyDevId = INVALID_DEVID;
1470
        /* Store key by reference and own it. */
1471
0
        ssl->buffers.key = *der;
1472
    #ifdef WOLFSSL_CHECK_MEM_ZERO
1473
        wc_MemZero_Add("SSL Buffers key", (*der)->buffer, (*der)->length);
1474
    #endif
1475
0
        ssl->buffers.weOwnKey = 1;
1476
0
    }
1477
0
    else if (ctx != NULL) {
1478
        /* Dispose of previous key. */
1479
0
        FreeKeyDer(&ctx->privateKey);
1480
0
        ctx->privateKeyId = 0;
1481
0
        ctx->privateKeyLabel = 0;
1482
0
        ctx->privateKeyDevId = INVALID_DEVID;
1483
        /* Store key by reference. */
1484
0
        ctx->privateKey = *der;
1485
    #ifdef WOLFSSL_CHECK_MEM_ZERO
1486
        wc_MemZero_Add("CTX private key", (*der)->buffer, (*der)->length);
1487
    #endif
1488
0
    }
1489
1490
0
    return ret;
1491
0
}
1492
1493
/* Decode private key.
1494
 *
1495
 * Precondition: ctx or ssl is not NULL.
1496
 * Precondition: Must be a private key type.
1497
 *
1498
 * @param [in, out] ctx     SSL context object.
1499
 * @param [in, out] ssl     SSL object.
1500
 * @param [in]      der     DER encoding.
1501
 * @param [in]      format  Original format of data.
1502
 * @param [in]      info    Encryption information.
1503
 * @param [in]      heap    Dynamic memory allocation hint.
1504
 * @param [in]      type    Type of data:
1505
 *                            PRIVATEKEY_TYPE or ALT_PRIVATEKEY_TYPE.
1506
 * @param [in]      algId   Algorithm id of key.
1507
 * @return  0 on success.
1508
 * @return  WOLFSSL_BAD_FILE when not able to decode.
1509
 */
1510
static int ProcessBufferPrivateKey(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
1511
    DerBuffer* der, int format, EncryptedInfo* info, void* heap, int type,
1512
    int algId)
1513
0
{
1514
0
    int ret;
1515
1516
0
    (void)info;
1517
0
    (void)format;
1518
1519
    /* Put the data into the SSL or SSL context object. */
1520
0
    ret = ProcessBufferPrivKeyHandleDer(ctx, ssl, &der, type);
1521
0
    if (ret == 0) {
1522
        /* Try to decode the DER data. */
1523
0
        ret = ProcessBufferTryDecode(ctx, ssl, der, &algId, heap, type);
1524
0
    }
1525
1526
#if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED)
1527
    /* If private key type PKCS8 header wasn't already removed (algId == 0). */
1528
    if (((ret != 0) || (algId == 0)) && (format != WOLFSSL_FILETYPE_PEM) &&
1529
            (info->passwd_cb != NULL) && (algId == 0)) {
1530
        /* Try to decrypt DER data as a PKCS#8 private key. */
1531
        ret = ProcessBufferPrivPkcs8Dec(info, der, heap);
1532
        if (ret >= 0) {
1533
            /* Try to decode decrypted data.  */
1534
            ret = ProcessBufferTryDecode(ctx, ssl, der, &algId, heap, type);
1535
        }
1536
    }
1537
#endif /* WOLFSSL_ENCRYPTED_KEYS && !NO_PWDBASED */
1538
1539
#ifdef WOLFSSL_BLIND_PRIVATE_KEY
1540
    {
1541
        int blindRet = 0;
1542
#ifdef WOLFSSL_DUAL_ALG_CERTS
1543
        if (type == ALT_PRIVATEKEY_TYPE) {
1544
            if (ssl != NULL) {
1545
                blindRet = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.altKey,
1546
                    &ssl->buffers.altKeyMask);
1547
            }
1548
            else {
1549
                blindRet = wolfssl_priv_der_blind(NULL, ctx->altPrivateKey,
1550
                    &ctx->altPrivateKeyMask);
1551
            }
1552
        }
1553
        else
1554
#endif
1555
        if (ssl != NULL) {
1556
            blindRet = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key,
1557
                &ssl->buffers.keyMask);
1558
        }
1559
        else {
1560
            blindRet = wolfssl_priv_der_blind(NULL, ctx->privateKey,
1561
                &ctx->privateKeyMask);
1562
        }
1563
        if (ret == 0 && blindRet != 0)
1564
            ret = blindRet;
1565
    }
1566
#endif
1567
1568
    /* Check if we were able to determine algorithm id. */
1569
0
    if ((ret == 0) && (algId == 0)) {
1570
    #ifdef OPENSSL_EXTRA
1571
        /* Decryption password is probably wrong. */
1572
        if (info->passwd_cb) {
1573
            WOLFSSL_EVPerr(0, -WOLFSSL_EVP_R_BAD_DECRYPT_E);
1574
        }
1575
    #endif
1576
0
        WOLFSSL_ERROR(WOLFSSL_BAD_FILE);
1577
        /* Unable to decode DER data. */
1578
0
        ret = WOLFSSL_BAD_FILE;
1579
0
    }
1580
1581
0
    return ret;
1582
0
}
1583
1584
/* Use the key OID to determine have options.
1585
 *
1586
 * @param [in, out] ctx     SSL context object.
1587
 * @param [in, out] ssl     SSL object.
1588
 * @param [in]      keyOID  OID for public/private key.
1589
 */
1590
static void wolfssl_set_have_from_key_oid(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
1591
    int keyOID)
1592
0
{
1593
    /* Set which private key algorithm available based on key OID. */
1594
0
    switch (keyOID) {
1595
0
        case ECDSAk:
1596
    #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
1597
        case SM2k:
1598
    #endif
1599
    #ifdef HAVE_ED25519
1600
        case ED25519k:
1601
    #endif
1602
    #ifdef HAVE_ED448
1603
        case ED448k:
1604
    #endif
1605
0
            if (ssl != NULL) {
1606
0
                ssl->options.haveECC = 1;
1607
0
            }
1608
0
            else {
1609
0
                ctx->haveECC = 1;
1610
0
            }
1611
0
            break;
1612
0
    #ifndef NO_RSA
1613
0
        case RSAk:
1614
0
        #ifdef WC_RSA_PSS
1615
0
        case RSAPSSk:
1616
0
        #endif
1617
0
            if (ssl != NULL) {
1618
0
                ssl->options.haveRSA = 1;
1619
0
            }
1620
0
            else {
1621
0
                ctx->haveRSA = 1;
1622
0
            }
1623
0
            break;
1624
0
    #endif
1625
    #ifdef HAVE_FALCON
1626
        case FALCON_LEVEL1k:
1627
        case FALCON_LEVEL5k:
1628
            if (ssl != NULL) {
1629
                ssl->options.haveFalconSig = 1;
1630
            }
1631
            else {
1632
                ctx->haveFalconSig = 1;
1633
            }
1634
            break;
1635
    #endif /* HAVE_FALCON */
1636
    #ifdef WOLFSSL_HAVE_MLDSA
1637
        case ML_DSA_44k:
1638
        case ML_DSA_65k:
1639
        case ML_DSA_87k:
1640
        #ifdef WOLFSSL_MLDSA_FIPS204_DRAFT
1641
        case DILITHIUM_LEVEL2k:
1642
        case DILITHIUM_LEVEL3k:
1643
        case DILITHIUM_LEVEL5k:
1644
        #endif
1645
            if (ssl != NULL) {
1646
                ssl->options.haveMlDsaSig = 1;
1647
            }
1648
            else {
1649
                ctx->haveMlDsaSig = 1;
1650
            }
1651
            break;
1652
    #endif /* WOLFSSL_HAVE_MLDSA */
1653
    #ifdef WOLFSSL_HAVE_SLHDSA
1654
        case SLH_DSA_SHA2_128Sk:
1655
        case SLH_DSA_SHA2_128Fk:
1656
        case SLH_DSA_SHA2_192Sk:
1657
        case SLH_DSA_SHA2_192Fk:
1658
        case SLH_DSA_SHA2_256Sk:
1659
        case SLH_DSA_SHA2_256Fk:
1660
        case SLH_DSA_SHAKE_128Sk:
1661
        case SLH_DSA_SHAKE_128Fk:
1662
        case SLH_DSA_SHAKE_192Sk:
1663
        case SLH_DSA_SHAKE_192Fk:
1664
        case SLH_DSA_SHAKE_256Sk:
1665
        case SLH_DSA_SHAKE_256Fk:
1666
            if (ssl != NULL) {
1667
                ssl->options.haveSlhDsaSig = 1;
1668
            }
1669
            else {
1670
                ctx->haveSlhDsaSig = 1;
1671
            }
1672
            break;
1673
    #endif /* WOLFSSL_HAVE_SLHDSA */
1674
0
        default:
1675
0
            WOLFSSL_MSG("Cert key not supported");
1676
0
            break;
1677
0
        }
1678
0
}
1679
1680
/* Set which private key algorithm we have against SSL or SSL context object.
1681
 *
1682
 * Precondition: ctx or ssl is not NULL.
1683
 *
1684
 * @param [in, out] ctx     SSL context object.
1685
 * @param [in, out] ssl     SSL object.
1686
 * @param [in]      cert    Decode certificate.
1687
 */
1688
static void ProcessBufferCertSetHave(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
1689
    DecodedCert* cert)
1690
0
{
1691
0
    if (ssl != NULL) {
1692
        /* Reset signatures we have in SSL. */
1693
0
        ssl->options.haveECDSAsig = 0;
1694
0
        ssl->options.haveFalconSig = 0;
1695
0
        ssl->options.haveMlDsaSig = 0;
1696
0
        ssl->options.haveSlhDsaSig = 0;
1697
0
    }
1698
1699
    /* Set which signature we have based on the type in the cert. */
1700
0
    switch (cert->signatureOID) {
1701
0
        case CTC_SHAwECDSA:
1702
0
        case CTC_SHA256wECDSA:
1703
0
        case CTC_SHA384wECDSA:
1704
0
        case CTC_SHA512wECDSA:
1705
    #ifdef HAVE_ED25519
1706
        case CTC_ED25519:
1707
    #endif
1708
    #ifdef HAVE_ED448
1709
        case CTC_ED448:
1710
    #endif
1711
    #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
1712
        case CTC_SM3wSM2:
1713
    #endif
1714
0
            WOLFSSL_MSG("ECDSA/ED25519/ED448 cert signature");
1715
0
            if (ssl) {
1716
0
                ssl->options.haveECDSAsig = 1;
1717
0
            }
1718
0
            else if (ctx) {
1719
0
                ctx->haveECDSAsig = 1;
1720
0
            }
1721
0
            break;
1722
    #ifdef HAVE_FALCON
1723
        case CTC_FALCON_LEVEL1:
1724
        case CTC_FALCON_LEVEL5:
1725
            WOLFSSL_MSG("Falcon cert signature");
1726
            if (ssl) {
1727
                ssl->options.haveFalconSig = 1;
1728
            }
1729
            else if (ctx) {
1730
                ctx->haveFalconSig = 1;
1731
            }
1732
            break;
1733
    #endif
1734
    #ifdef WOLFSSL_HAVE_MLDSA
1735
        case CTC_ML_DSA_44:
1736
        case CTC_ML_DSA_65:
1737
        case CTC_ML_DSA_87:
1738
        #ifdef WOLFSSL_MLDSA_FIPS204_DRAFT
1739
        case CTC_DILITHIUM_LEVEL2:
1740
        case CTC_DILITHIUM_LEVEL3:
1741
        case CTC_DILITHIUM_LEVEL5:
1742
        #endif /* WOLFSSL_MLDSA_FIPS204_DRAFT */
1743
            WOLFSSL_MSG("ML-DSA cert signature");
1744
            if (ssl) {
1745
                ssl->options.haveMlDsaSig = 1;
1746
            }
1747
            else if (ctx) {
1748
                ctx->haveMlDsaSig = 1;
1749
            }
1750
            break;
1751
    #endif
1752
    #ifdef WOLFSSL_HAVE_SLHDSA
1753
        case CTC_SLH_DSA_SHA2_128S:
1754
        case CTC_SLH_DSA_SHA2_128F:
1755
        case CTC_SLH_DSA_SHA2_192S:
1756
        case CTC_SLH_DSA_SHA2_192F:
1757
        case CTC_SLH_DSA_SHA2_256S:
1758
        case CTC_SLH_DSA_SHA2_256F:
1759
        case CTC_SLH_DSA_SHAKE_128S:
1760
        case CTC_SLH_DSA_SHAKE_128F:
1761
        case CTC_SLH_DSA_SHAKE_192S:
1762
        case CTC_SLH_DSA_SHAKE_192F:
1763
        case CTC_SLH_DSA_SHAKE_256S:
1764
        case CTC_SLH_DSA_SHAKE_256F:
1765
            WOLFSSL_MSG("SLH-DSA cert signature");
1766
            if (ssl) {
1767
                ssl->options.haveSlhDsaSig = 1;
1768
            }
1769
            else if (ctx) {
1770
                ctx->haveSlhDsaSig = 1;
1771
            }
1772
            break;
1773
    #endif
1774
0
        default:
1775
0
            WOLFSSL_MSG("Cert signature not supported");
1776
0
            break;
1777
0
    }
1778
1779
0
#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \
1780
0
    defined(HAVE_FALCON) || defined(WOLFSSL_HAVE_MLDSA) || \
1781
0
    defined(WOLFSSL_HAVE_SLHDSA) || !defined(NO_RSA)
1782
0
    #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \
1783
0
        defined(HAVE_FALCON) || defined(WOLFSSL_HAVE_MLDSA) || \
1784
0
        defined(WOLFSSL_HAVE_SLHDSA)
1785
    /* Set the private key curve OID. */
1786
0
    if (ssl != NULL) {
1787
0
        ssl->pkCurveOID = cert->pkCurveOID;
1788
0
    }
1789
0
    else if (ctx) {
1790
0
        ctx->pkCurveOID = cert->pkCurveOID;
1791
0
    }
1792
0
    #endif
1793
0
#ifndef WC_STRICT_SIG
1794
0
    if ((ctx != NULL) || (ssl != NULL)) {
1795
0
        wolfssl_set_have_from_key_oid(ctx, ssl, (int)cert->keyOID);
1796
0
    }
1797
#else
1798
    /* Set whether ECC is available based on signature available. */
1799
    if (ssl != NULL) {
1800
        ssl->options.haveECC = ssl->options.haveECDSAsig;
1801
    }
1802
    else if (ctx) {
1803
        ctx->haveECC = ctx->haveECDSAsig;
1804
    }
1805
#endif /* !WC_STRICT_SIG */
1806
0
#endif
1807
0
}
1808
1809
/* Check key size is valid.
1810
 *
1811
 * Precondition: ctx or ssl is not NULL.
1812
 *
1813
 * @param [in] min    Minimum key size.
1814
 * @param [in] max    Maximum key size.
1815
 * @param [in] keySz  Key size.
1816
 * @param [in] err    Error value to return when key size is invalid.
1817
 * @return  0 on success.
1818
 * @return  err when verifying and min is less than 0 or key size is invalid.
1819
 */
1820
#define CHECK_KEY_SZ(min, max, keySz, err)                                     \
1821
0
    (((min) < 0) || ((keySz) < (min)) || ((keySz) > (max))) ? (err) : 0
1822
1823
/* Check public key in certificate.
1824
 *
1825
 * @param [in, out] ctx   SSL context object.
1826
 * @param [in, out] ssl   SSL object.
1827
 * @param [in]      cert  Certificate object.
1828
 * @return  0 on success.
1829
 * @return  Non-zero when an error occurred.
1830
 */
1831
static int ProcessBufferCertPublicKey(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
1832
    DecodedCert* cert, int checkKeySz)
1833
0
{
1834
0
    int ret = 0;
1835
0
    byte keyType = 0;
1836
0
    int keySz = 0;
1837
0
#ifndef NO_RSA
1838
0
    word32 idx;
1839
0
#endif
1840
0
    if (ctx == NULL && ssl == NULL) {
1841
0
        return BAD_FUNC_ARG;
1842
0
    }
1843
1844
    /* Get key size and check unless not verifying. */
1845
0
    switch (cert->keyOID) {
1846
0
#ifndef NO_RSA
1847
0
    #ifdef WC_RSA_PSS
1848
0
        case RSAPSSk:
1849
0
    #endif
1850
0
        case RSAk:
1851
0
            keyType = rsa_sa_algo;
1852
            /* Determine RSA key size by parsing public key */
1853
0
            idx = 0;
1854
0
            ret = wc_RsaPublicKeyDecode_ex(cert->publicKey, &idx,
1855
0
                cert->pubKeySize, NULL, (word32*)&keySz, NULL, NULL);
1856
0
            if ((ret == 0) && checkKeySz) {
1857
0
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minRsaKeySz :
1858
0
                    ctx->minRsaKeySz, RSA_MAX_SIZE / 8, keySz, RSA_KEY_SIZE_E);
1859
0
            }
1860
0
    #ifdef WC_RSA_PSS
1861
0
            if (ssl) {
1862
0
                ssl->useRsaPss = cert->keyOID == RSAPSSk;
1863
0
            }
1864
0
            if (ctx) {
1865
0
                ctx->useRsaPss = cert->keyOID == RSAPSSk;
1866
0
            }
1867
0
    #endif
1868
0
            break;
1869
0
#endif /* !NO_RSA */
1870
0
    #ifdef HAVE_ECC
1871
0
        case ECDSAk:
1872
0
            keyType = ecc_dsa_sa_algo;
1873
            /* Determine ECC key size based on curve */
1874
        #ifdef WOLFSSL_CUSTOM_CURVES
1875
            if ((cert->pkCurveOID == 0) && (cert->pkCurveSize != 0)) {
1876
                keySz = cert->pkCurveSize;
1877
            }
1878
            else
1879
        #endif
1880
0
            {
1881
0
                keySz = wc_ecc_get_curve_size_from_id(wc_ecc_get_oid(
1882
0
                    cert->pkCurveOID, NULL, NULL));
1883
0
            }
1884
1885
0
            if (checkKeySz) {
1886
0
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minEccKeySz :
1887
0
                     ctx->minEccKeySz, (MAX_ECC_BITS + 7) / 8, keySz,
1888
0
                     ECC_KEY_SIZE_E);
1889
0
            }
1890
0
            break;
1891
0
    #endif /* HAVE_ECC */
1892
    #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
1893
        case SM2k:
1894
            keyType = sm2_sa_algo;
1895
            /* Determine ECC key size based on curve */
1896
            keySz = WOLFSSL_SM2_KEY_BITS / 8;
1897
            if (checkKeySz) {
1898
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minEccKeySz :
1899
                    ctx->minEccKeySz, (MAX_ECC_BITS + 7) / 8, keySz,
1900
                    ECC_KEY_SIZE_E);
1901
            }
1902
            break;
1903
    #endif /* WOLFSSL_SM2 && WOLFSSL_SM3 */
1904
    #ifdef HAVE_ED25519
1905
        case ED25519k:
1906
            keyType = ed25519_sa_algo;
1907
            /* ED25519 is fixed key size */
1908
            keySz = ED25519_KEY_SIZE;
1909
            if (checkKeySz) {
1910
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minEccKeySz :
1911
                    ctx->minEccKeySz, ED25519_KEY_SIZE, keySz, ECC_KEY_SIZE_E);
1912
            }
1913
            break;
1914
    #endif /* HAVE_ED25519 */
1915
    #ifdef HAVE_ED448
1916
        case ED448k:
1917
            keyType = ed448_sa_algo;
1918
            /* ED448 is fixed key size */
1919
            keySz = ED448_KEY_SIZE;
1920
            if (checkKeySz) {
1921
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minEccKeySz :
1922
                    ctx->minEccKeySz, ED448_KEY_SIZE, keySz, ECC_KEY_SIZE_E);
1923
            }
1924
            break;
1925
    #endif /* HAVE_ED448 */
1926
    #if defined(HAVE_FALCON)
1927
        case FALCON_LEVEL1k:
1928
            keyType = falcon_level1_sa_algo;
1929
            /* Falcon is fixed key size */
1930
            keySz = FALCON_LEVEL1_KEY_SIZE;
1931
            if (checkKeySz) {
1932
            #ifdef WOLFSSL_NO_FALCON_LEVEL1
1933
                ret = NOT_COMPILED_IN;
1934
            #else
1935
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minFalconKeySz :
1936
                    ctx->minFalconKeySz, FALCON_MAX_KEY_SIZE, keySz,
1937
                    FALCON_KEY_SIZE_E);
1938
            #endif
1939
            }
1940
            break;
1941
        case FALCON_LEVEL5k:
1942
            keyType = falcon_level5_sa_algo;
1943
            /* Falcon is fixed key size */
1944
            keySz = FALCON_LEVEL5_KEY_SIZE;
1945
            if (checkKeySz) {
1946
            #ifdef WOLFSSL_NO_FALCON_LEVEL5
1947
                ret = NOT_COMPILED_IN;
1948
            #else
1949
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minFalconKeySz :
1950
                    ctx->minFalconKeySz, FALCON_MAX_KEY_SIZE, keySz,
1951
                    FALCON_KEY_SIZE_E);
1952
            #endif
1953
            }
1954
            break;
1955
    #endif /* HAVE_FALCON */
1956
    #if defined(WOLFSSL_HAVE_MLDSA)
1957
        #ifdef WOLFSSL_MLDSA_FIPS204_DRAFT
1958
        case DILITHIUM_LEVEL2k:
1959
            keyType = mldsa_44_sa_algo;
1960
            /* Dilithium is fixed key size */
1961
            keySz = WC_MLDSA_44_KEY_SIZE;
1962
            if (checkKeySz) {
1963
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minMlDsaKeySz :
1964
                    ctx->minMlDsaKeySz, MLDSA_MAX_KEY_SIZE, keySz,
1965
                    MLDSA_KEY_SIZE_E);
1966
            }
1967
            break;
1968
        case DILITHIUM_LEVEL3k:
1969
            keyType = mldsa_65_sa_algo;
1970
            /* Dilithium is fixed key size */
1971
            keySz = WC_MLDSA_65_KEY_SIZE;
1972
            if (checkKeySz) {
1973
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minMlDsaKeySz :
1974
                    ctx->minMlDsaKeySz, MLDSA_MAX_KEY_SIZE, keySz,
1975
                    MLDSA_KEY_SIZE_E);
1976
            }
1977
            break;
1978
        case DILITHIUM_LEVEL5k:
1979
            keyType = mldsa_87_sa_algo;
1980
            /* Dilithium is fixed key size */
1981
            keySz = WC_MLDSA_87_KEY_SIZE;
1982
            if (checkKeySz) {
1983
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minMlDsaKeySz :
1984
                    ctx->minMlDsaKeySz, MLDSA_MAX_KEY_SIZE, keySz,
1985
                    MLDSA_KEY_SIZE_E);
1986
            }
1987
            break;
1988
        #endif /* WOLFSSL_MLDSA_FIPS204_DRAFT */
1989
        case ML_DSA_44k:
1990
            keyType = mldsa_44_sa_algo;
1991
            /* Dilithium is fixed key size */
1992
            keySz = WC_MLDSA_44_KEY_SIZE;
1993
            if (checkKeySz) {
1994
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minMlDsaKeySz :
1995
                    ctx->minMlDsaKeySz, MLDSA_MAX_KEY_SIZE, keySz,
1996
                    MLDSA_KEY_SIZE_E);
1997
            }
1998
            break;
1999
        case ML_DSA_65k:
2000
            keyType = mldsa_65_sa_algo;
2001
            /* Dilithium is fixed key size */
2002
            keySz = WC_MLDSA_65_KEY_SIZE;
2003
            if (checkKeySz) {
2004
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minMlDsaKeySz :
2005
                    ctx->minMlDsaKeySz, MLDSA_MAX_KEY_SIZE, keySz,
2006
                    MLDSA_KEY_SIZE_E);
2007
            }
2008
            break;
2009
        case ML_DSA_87k:
2010
            keyType = mldsa_87_sa_algo;
2011
            /* Dilithium is fixed key size */
2012
            keySz = WC_MLDSA_87_KEY_SIZE;
2013
            if (checkKeySz) {
2014
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minMlDsaKeySz :
2015
                    ctx->minMlDsaKeySz, MLDSA_MAX_KEY_SIZE, keySz,
2016
                    MLDSA_KEY_SIZE_E);
2017
            }
2018
            break;
2019
    #endif /* WOLFSSL_HAVE_MLDSA */
2020
    #if defined(WOLFSSL_HAVE_SLHDSA)
2021
        case SLH_DSA_SHA2_128Sk:
2022
        case SLH_DSA_SHA2_128Fk:
2023
        case SLH_DSA_SHA2_192Sk:
2024
        case SLH_DSA_SHA2_192Fk:
2025
        case SLH_DSA_SHA2_256Sk:
2026
        case SLH_DSA_SHA2_256Fk:
2027
        case SLH_DSA_SHAKE_128Sk:
2028
        case SLH_DSA_SHAKE_128Fk:
2029
        case SLH_DSA_SHAKE_192Sk:
2030
        case SLH_DSA_SHAKE_192Fk:
2031
        case SLH_DSA_SHAKE_256Sk:
2032
        case SLH_DSA_SHAKE_256Fk:
2033
        {
2034
            int slhParam = wc_SlhDsaOidToParam((int)cert->keyOID);
2035
            int keySzTemp;
2036
2037
            if (slhParam < 0) {
2038
                ret = ALGO_ID_E;
2039
                break;
2040
            }
2041
            keyType = SlhDsaParamToType(slhParam);
2042
            if (keyType == (byte)invalid_sa_algo) {
2043
                ret = ALGO_ID_E;
2044
                break;
2045
            }
2046
            /* SLH-DSA has fixed, small public keys and no minimum-size
2047
             * option; store the public key size for reference. checkKeySz is
2048
             * unused for SLH-DSA (this is the only key type without a size
2049
             * check, so mark it used to avoid -Wunused-parameter in a build
2050
             * where SLH-DSA is the only certificate signature algorithm). */
2051
            keySzTemp = wc_SlhDsaKey_PublicSizeFromParam(
2052
                            (enum SlhDsaParam)slhParam);
2053
            if (keySzTemp <= 0) {
2054
                ret = ALGO_ID_E;
2055
                break;
2056
            }
2057
            keySz = keySzTemp;
2058
            (void)checkKeySz;
2059
            break;
2060
        }
2061
    #endif /* WOLFSSL_HAVE_SLHDSA */
2062
2063
0
        default:
2064
0
            WOLFSSL_MSG("No key size check done on public key in certificate");
2065
0
            break;
2066
0
    }
2067
2068
    /* Store the type and key size as there may not be a private key set. */
2069
0
    if (ssl != NULL) {
2070
0
        ssl->buffers.keyType = keyType;
2071
0
        ssl->buffers.keySz = keySz;
2072
0
    }
2073
0
    else {
2074
0
        ctx->privateKeyType = keyType;
2075
0
        ctx->privateKeySz = keySz;
2076
0
    }
2077
2078
0
    return ret;
2079
0
}
2080
2081
#ifdef WOLFSSL_DUAL_ALG_CERTS
2082
static int ProcessBufferCertAltPublicKey(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
2083
    DecodedCert* cert, int checkKeySz)
2084
{
2085
    int ret = 0;
2086
    void* heap = WOLFSSL_HEAP(ctx, ssl);
2087
    byte keyType = 0;
2088
    int keySz = 0;
2089
#ifndef NO_RSA
2090
    word32 idx;
2091
#endif
2092
2093
    /* Check alternative key size of cert. */
2094
    switch (cert->sapkiOID) {
2095
        /* No OID set. */
2096
        case 0:
2097
            if (cert->sapkiLen != 0) {
2098
                /* Have the alternative key data but no OID. */
2099
                ret = NOT_COMPILED_IN;
2100
            }
2101
            break;
2102
2103
#ifndef NO_RSA
2104
    #ifdef WC_RSA_PSS
2105
        case RSAPSSk:
2106
    #endif
2107
        case RSAk:
2108
            keyType = rsa_sa_algo;
2109
            /* Determine RSA key size by parsing public key */
2110
            idx = 0;
2111
            ret = wc_RsaPublicKeyDecode_ex(cert->sapkiDer, &idx,
2112
                cert->sapkiLen, NULL, (word32*)&keySz, NULL, NULL);
2113
            if ((ret == 0) && checkKeySz) {
2114
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minRsaKeySz :
2115
                    ctx->minRsaKeySz, RSA_MAX_SIZE / 8, keySz, RSA_KEY_SIZE_E);
2116
            }
2117
            break;
2118
#endif /* !NO_RSA */
2119
    #ifdef HAVE_ECC
2120
        case ECDSAk:
2121
        {
2122
            WC_DECLARE_VAR(temp_key, ecc_key, 1, 0);
2123
            keyType = ecc_dsa_sa_algo;
2124
2125
            WC_ALLOC_VAR_EX(temp_key, ecc_key, 1, heap, DYNAMIC_TYPE_ECC,
2126
                ret=MEMORY_E);
2127
2128
            /* Determine ECC key size. We have to decode the sapki for
2129
             * that. */
2130
            if (ret == 0) {
2131
                ret = wc_ecc_init_ex(temp_key, heap, INVALID_DEVID);
2132
                if (ret == 0) {
2133
                    idx = 0;
2134
                    ret = wc_EccPublicKeyDecode(cert->sapkiDer, &idx, temp_key,
2135
                        cert->sapkiLen);
2136
                    if (ret == 0) {
2137
                        keySz = wc_ecc_size(temp_key);
2138
                    }
2139
                    wc_ecc_free(temp_key);
2140
                }
2141
            }
2142
            WC_FREE_VAR_EX(temp_key, heap, DYNAMIC_TYPE_ECC);
2143
2144
            if ((ret == 0) && checkKeySz) {
2145
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minEccKeySz :
2146
                     ctx->minEccKeySz, (MAX_ECC_BITS + 7) / 8, keySz,
2147
                     ECC_KEY_SIZE_E);
2148
            }
2149
            break;
2150
        }
2151
    #endif /* HAVE_ECC */
2152
    #if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
2153
        case SM2k:
2154
            keyType = sm2_sa_algo;
2155
            /* Determine ECC key size based on curve */
2156
            keySz = WOLFSSL_SM2_KEY_BITS / 8;
2157
            if (checkKeySz) {
2158
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minEccKeySz :
2159
                    ctx->minEccKeySz, (MAX_ECC_BITS + 7) / 8, keySz,
2160
                    ECC_KEY_SIZE_E);
2161
            }
2162
            break;
2163
    #endif /* WOLFSSL_SM2 && WOLFSSL_SM3 */
2164
    #ifdef HAVE_ED25519
2165
        case ED25519k:
2166
            keyType = ed25519_sa_algo;
2167
            /* ED25519 is fixed key size */
2168
            keySz = ED25519_KEY_SIZE;
2169
            if (checkKeySz) {
2170
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minEccKeySz :
2171
                    ctx->minEccKeySz, ED25519_KEY_SIZE, keySz, ECC_KEY_SIZE_E);
2172
            }
2173
            break;
2174
    #endif /* HAVE_ED25519 */
2175
    #ifdef HAVE_ED448
2176
        case ED448k:
2177
            keyType = ed448_sa_algo;
2178
            /* ED448 is fixed key size */
2179
            keySz = ED448_KEY_SIZE;
2180
            if (checkKeySz) {
2181
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minEccKeySz :
2182
                    ctx->minEccKeySz, ED448_KEY_SIZE, keySz, ECC_KEY_SIZE_E);
2183
            }
2184
            break;
2185
    #endif /* HAVE_ED448 */
2186
    #if defined(HAVE_FALCON)
2187
        case FALCON_LEVEL1k:
2188
            keyType = falcon_level1_sa_algo;
2189
            /* Falcon is fixed key size */
2190
            keySz = FALCON_LEVEL1_KEY_SIZE;
2191
            if (checkKeySz) {
2192
            #ifdef WOLFSSL_NO_FALCON_LEVEL1
2193
                ret = NOT_COMPILED_IN;
2194
            #else
2195
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minFalconKeySz :
2196
                    ctx->minFalconKeySz, FALCON_MAX_KEY_SIZE, keySz,
2197
                    FALCON_KEY_SIZE_E);
2198
            #endif
2199
            }
2200
            break;
2201
        case FALCON_LEVEL5k:
2202
            keyType = falcon_level5_sa_algo;
2203
            /* Falcon is fixed key size */
2204
            keySz = FALCON_LEVEL5_KEY_SIZE;
2205
            if (checkKeySz) {
2206
            #ifdef WOLFSSL_NO_FALCON_LEVEL5
2207
                ret = NOT_COMPILED_IN;
2208
            #else
2209
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minFalconKeySz :
2210
                    ctx->minFalconKeySz, FALCON_MAX_KEY_SIZE, keySz,
2211
                    FALCON_KEY_SIZE_E);
2212
            #endif
2213
            }
2214
            break;
2215
    #endif /* HAVE_FALCON */
2216
    #if defined(WOLFSSL_HAVE_MLDSA)
2217
        #ifdef WOLFSSL_MLDSA_FIPS204_DRAFT
2218
        case DILITHIUM_LEVEL2k:
2219
            keyType = mldsa_44_sa_algo;
2220
            /* Dilithium is fixed key size */
2221
            keySz = WC_MLDSA_44_KEY_SIZE;
2222
            if (checkKeySz) {
2223
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minMlDsaKeySz :
2224
                    ctx->minMlDsaKeySz, MLDSA_MAX_KEY_SIZE, keySz,
2225
                    MLDSA_KEY_SIZE_E);
2226
            }
2227
            break;
2228
        case DILITHIUM_LEVEL3k:
2229
            keyType = mldsa_65_sa_algo;
2230
            /* Dilithium is fixed key size */
2231
            keySz = WC_MLDSA_65_KEY_SIZE;
2232
            if (checkKeySz) {
2233
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minMlDsaKeySz :
2234
                    ctx->minMlDsaKeySz, MLDSA_MAX_KEY_SIZE, keySz,
2235
                    MLDSA_KEY_SIZE_E);
2236
            }
2237
            break;
2238
        case DILITHIUM_LEVEL5k:
2239
            keyType = mldsa_87_sa_algo;
2240
            /* Dilithium is fixed key size */
2241
            keySz = WC_MLDSA_87_KEY_SIZE;
2242
            if (checkKeySz) {
2243
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minMlDsaKeySz :
2244
                    ctx->minMlDsaKeySz, MLDSA_MAX_KEY_SIZE, keySz,
2245
                    MLDSA_KEY_SIZE_E);
2246
            }
2247
            break;
2248
        #endif /* WOLFSSL_MLDSA_FIPS204_DRAFT */
2249
        case ML_DSA_44k:
2250
            keyType = mldsa_44_sa_algo;
2251
            /* Dilithium is fixed key size */
2252
            keySz = WC_MLDSA_44_KEY_SIZE;
2253
            if (checkKeySz) {
2254
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minMlDsaKeySz :
2255
                    ctx->minMlDsaKeySz, MLDSA_MAX_KEY_SIZE, keySz,
2256
                    MLDSA_KEY_SIZE_E);
2257
            }
2258
            break;
2259
        case ML_DSA_65k:
2260
            keyType = mldsa_65_sa_algo;
2261
            /* Dilithium is fixed key size */
2262
            keySz = WC_MLDSA_65_KEY_SIZE;
2263
            if (checkKeySz) {
2264
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minMlDsaKeySz :
2265
                    ctx->minMlDsaKeySz, MLDSA_MAX_KEY_SIZE, keySz,
2266
                    MLDSA_KEY_SIZE_E);
2267
            }
2268
            break;
2269
        case ML_DSA_87k:
2270
            keyType = mldsa_87_sa_algo;
2271
            /* Dilithium is fixed key size */
2272
            keySz = WC_MLDSA_87_KEY_SIZE;
2273
            if (checkKeySz) {
2274
                ret = CHECK_KEY_SZ(ssl ? ssl->options.minMlDsaKeySz :
2275
                    ctx->minMlDsaKeySz, MLDSA_MAX_KEY_SIZE, keySz,
2276
                    MLDSA_KEY_SIZE_E);
2277
            }
2278
            break;
2279
    #endif /* WOLFSSL_HAVE_MLDSA */
2280
    #if defined(WOLFSSL_HAVE_SLHDSA)
2281
        case SLH_DSA_SHA2_128Sk:
2282
        case SLH_DSA_SHA2_128Fk:
2283
        case SLH_DSA_SHA2_192Sk:
2284
        case SLH_DSA_SHA2_192Fk:
2285
        case SLH_DSA_SHA2_256Sk:
2286
        case SLH_DSA_SHA2_256Fk:
2287
        case SLH_DSA_SHAKE_128Sk:
2288
        case SLH_DSA_SHAKE_128Fk:
2289
        case SLH_DSA_SHAKE_192Sk:
2290
        case SLH_DSA_SHAKE_192Fk:
2291
        case SLH_DSA_SHAKE_256Sk:
2292
        case SLH_DSA_SHAKE_256Fk:
2293
        {
2294
            /* This switch is over the alternative key's OID, so the
2295
             * parameter set comes from sapkiOID; keyOID describes the native
2296
             * key and would name a different algorithm entirely. */
2297
            int slhParam = wc_SlhDsaOidToParam((int)cert->sapkiOID);
2298
            int keySzTemp;
2299
2300
            if (slhParam < 0) {
2301
                ret = ALGO_ID_E;
2302
                break;
2303
            }
2304
            keyType = SlhDsaParamToType(slhParam);
2305
            if (keyType == (byte)invalid_sa_algo) {
2306
                ret = ALGO_ID_E;
2307
                break;
2308
            }
2309
            keySzTemp = wc_SlhDsaKey_PublicSizeFromParam(
2310
                            (enum SlhDsaParam)slhParam);
2311
            if (keySzTemp <= 0) {
2312
                ret = ALGO_ID_E;
2313
                break;
2314
            }
2315
            keySz = keySzTemp;
2316
            break;
2317
        }
2318
    #endif /* WOLFSSL_HAVE_SLHDSA */
2319
2320
        default:
2321
            /* In this case, there was an OID that we didn't recognize.
2322
             * This is an error. Use not compiled in because likely the
2323
             * given algorithm was not enabled. */
2324
            ret = NOT_COMPILED_IN;
2325
            WOLFSSL_MSG("No alt key size check done on certificate");
2326
            break;
2327
    }
2328
2329
    if (ssl != NULL) {
2330
        ssl->buffers.altKeyType = (byte)keyType;
2331
        ssl->buffers.altKeySz = keySz;
2332
    }
2333
    else if (ctx != NULL) {
2334
        ctx->altPrivateKeyType = (byte)keyType;
2335
        ctx->altPrivateKeySz = keySz;
2336
    }
2337
2338
    return ret;
2339
}
2340
#endif /* WOLFSSL_DUAL_ALG_CERTS */
2341
2342
/* Parse the certificate and pull out information for TLS handshake.
2343
 *
2344
 * @param [in, out] ctx   SSL context object.
2345
 * @param [in, out] ssl   SSL object.
2346
 * @param [in]      der   DER encoded X509 certificate.
2347
 * @return  0 on success.
2348
 * @return  MEMORY_E when dynamic memory allocation fails.
2349
 * @return  WOLFSSL_BAD_FILE when decoding certificate fails.
2350
 */
2351
static int ProcessBufferCert(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der)
2352
0
{
2353
0
    int ret = 0;
2354
0
    void* heap = WOLFSSL_HEAP(ctx, ssl);
2355
#if defined(HAVE_RPK)
2356
    RpkState* rpkState = ssl ? &ssl->options.rpkState : &ctx->rpkState;
2357
#endif
2358
0
    WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
2359
2360
    /* Allocate memory for certificate to be decoded into. */
2361
0
    WC_ALLOC_VAR_EX(cert, DecodedCert, 1, heap, DYNAMIC_TYPE_DCERT,
2362
0
        ret=MEMORY_E);
2363
0
    if (WC_VAR_OK(cert))
2364
0
    {
2365
        /* Get device id from SSL context or SSL object. */
2366
0
        int devId = wolfSSL_CTX_GetDevId(ctx, ssl);
2367
2368
0
        WOLFSSL_MSG("Checking cert signature type");
2369
        /* Initialize certificate object. */
2370
0
        InitDecodedCert_ex(cert, der->buffer, der->length, heap, devId);
2371
2372
        /* Decode up to and including public key. */
2373
0
        if (DecodeToKey(cert, 0) < 0) {
2374
0
            WOLFSSL_MSG("Decode to key failed");
2375
0
            ret = WOLFSSL_BAD_FILE;
2376
0
        }
2377
0
        if (ret == 0) {
2378
0
            int checkKeySz = 1;
2379
2380
        #if defined(HAVE_RPK)
2381
            /* Store whether the crtificate is a raw public key. */
2382
            rpkState->isRPKLoaded = cert->isRPK;
2383
        #endif /* HAVE_RPK */
2384
2385
            /* Set which private key algorithm we have. */
2386
0
            ProcessBufferCertSetHave(ctx, ssl, cert);
2387
2388
            /* Don't check if verification is disabled for SSL. */
2389
0
            if ((ssl != NULL) && ssl->options.verifyNone) {
2390
0
                checkKeySz = 0;
2391
0
            }
2392
            /* Don't check if no SSL object verification is disabled for SSL
2393
             * context. */
2394
0
            else if ((ssl == NULL) && (ctx != NULL) && ctx->verifyNone) {
2395
0
                checkKeySz = 0;
2396
0
            }
2397
2398
            /* Check public key size. */
2399
0
            ret = ProcessBufferCertPublicKey(ctx, ssl, cert, checkKeySz);
2400
        #ifdef WOLFSSL_DUAL_ALG_CERTS
2401
            if (ret == 0) {
2402
                ret = ProcessBufferCertAltPublicKey(ctx, ssl, cert, checkKeySz);
2403
            }
2404
        #endif
2405
0
        }
2406
0
    }
2407
2408
    /* Dispose of dynamic memory in certificate object. */
2409
0
    FreeDecodedCert(cert);
2410
0
    WC_FREE_VAR_EX(cert, heap, DYNAMIC_TYPE_DCERT);
2411
0
    return ret;
2412
0
}
2413
2414
/* Handle storing the DER encoding of the certificate.
2415
 *
2416
 * Do not free der outside of this function.
2417
 *
2418
 * @param [in, out] ctx     SSL context object.
2419
 * @param [in, out] ssl     SSL object.
2420
 * @param [in]      der     DER encoded certificate.
2421
 * @param [in]      type    Type of data:
2422
 *                            CERT_TYPE, CA_TYPE or TRUSTED_PEER_TYPE.
2423
 * @param [in]      verify  What verification to do.
2424
 * @return  0 on success.
2425
 * @return  BAD_FUNC_ARG when type is CA_TYPE and ctx is NULL.
2426
 * @return  WOLFSSL_BAD_CERTTYPE when data type is not supported.
2427
 */
2428
static int ProcessBufferCertHandleDer(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
2429
    DerBuffer* der, int type, int verify)
2430
0
{
2431
0
    int ret = 0;
2432
2433
    /* CA certificate to verify with. */
2434
0
    if (type == CA_TYPE) {
2435
#ifdef WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION
2436
        /* TEST ONLY CODE:
2437
         * Store the DER encoding of the CA certificate so we can append it to
2438
         * the list of trusted CA certificates if the subsequent call to AddCA
2439
         * is successful */
2440
        word32 derLen;
2441
        byte* derBuf;
2442
        if (ctx->doAppleNativeCertValidationFlag == 1) {
2443
            WOLFSSL_MSG("ANCV Test: copy DER CA cert");
2444
            derLen = der->length;
2445
            derBuf = (byte*)XMALLOC(derLen, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2446
            if (derBuf == NULL) {
2447
                return MEMORY_E;
2448
            }
2449
            XMEMCPY(derBuf, der->buffer, derLen);
2450
        }
2451
        else {
2452
            (void)derLen;
2453
            (void)derBuf;
2454
        }
2455
#endif
2456
        /* verify CA unless user set to no verify */
2457
0
        ret = AddCA(ctx->cm, &der, WOLFSSL_USER_CA, verify);
2458
2459
#ifdef WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION
2460
        /* TEST ONLY CODE:
2461
         * Append the DER encoded CA certificate to the list of trusted CA
2462
         * certificates so we can inject them at verification time */
2463
        if (ret == 1 && ctx->doAppleNativeCertValidationFlag == 1) {
2464
            WOLFSSL_MSG("ANCV Test: Appending CA to cert list");
2465
            ret = wolfSSL_TestAppleNativeCertValidation_AppendCA(ctx, derBuf,
2466
                (int)derLen);
2467
            if (ret == WOLFSSL_SUCCESS) {
2468
                WOLFSSL_MSG("ANCV Test: Clearing CA table");
2469
                /* Clear the CA table so we can ensure they won't be used for
2470
                 * verification */
2471
                ret = wolfSSL_CertManagerUnloadCAs(ctx->cm);
2472
                if (ret == WOLFSSL_SUCCESS) {
2473
                    ret = 0;
2474
                }
2475
            }
2476
            XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2477
        }
2478
#endif /* !WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION */
2479
2480
0
        if (ret == 1) {
2481
0
            ret = 0;
2482
0
        }
2483
0
    }
2484
#ifdef WOLFSSL_TRUST_PEER_CERT
2485
    /* Trusted certificate to verify peer with. */
2486
    else if (type == TRUSTED_PEER_TYPE) {
2487
        WOLFSSL_CERT_MANAGER* cm;
2488
2489
        /* Get certificate manager to add certificate to. */
2490
        if (ctx != NULL) {
2491
            cm = ctx->cm;
2492
        }
2493
        else {
2494
            SSL_CM_WARNING(ssl);
2495
            cm = SSL_CM(ssl);
2496
        }
2497
        /* Add certificate as a trusted peer. */
2498
        ret = AddTrustedPeer(cm, &der, verify);
2499
        if (ret != 1) {
2500
            WOLFSSL_MSG("Error adding trusted peer");
2501
        }
2502
    }
2503
#endif /* WOLFSSL_TRUST_PEER_CERT */
2504
    /* Leaf certificate - our certificate. */
2505
0
    else if (type == CERT_TYPE) {
2506
0
        if (ssl != NULL) {
2507
            /* Free previous certificate if we own it. */
2508
0
            if (ssl->buffers.weOwnCert) {
2509
0
                FreeDer(&ssl->buffers.certificate);
2510
            #ifdef KEEP_OUR_CERT
2511
                /* Dispose of X509 version of certificate. */
2512
                wolfSSL_X509_free(ssl->ourCert);
2513
                ssl->ourCert = NULL;
2514
            #endif
2515
0
            }
2516
            /* Store certificate as ours. */
2517
0
            ssl->buffers.certificate = der;
2518
        #ifdef KEEP_OUR_CERT
2519
            ssl->keepCert = 1; /* hold cert for ssl lifetime */
2520
        #endif
2521
            /* We have to free the certificate buffer. */
2522
0
            ssl->buffers.weOwnCert = 1;
2523
            /* ourCert is created on demand. */
2524
0
        }
2525
0
        else if (ctx != NULL) {
2526
            /* Free previous certificate. */
2527
0
            FreeDer(&ctx->certificate); /* Make sure previous is free'd */
2528
        #ifdef KEEP_OUR_CERT
2529
            /* Dispose of X509 version of certificate if we own it. */
2530
            if (ctx->ownOurCert) {
2531
                wolfSSL_X509_free(ctx->ourCert);
2532
            }
2533
            ctx->ourCert = NULL;
2534
        #endif
2535
            /* Store certificate as ours. */
2536
0
            ctx->certificate = der;
2537
            /* ourCert is created on demand. */
2538
            /* The cached OCSP request was built from the old certificate. */
2539
0
            FreeCtxOcspRequestCache(ctx);
2540
0
        }
2541
0
    }
2542
0
    else {
2543
        /* Dispose of DER buffer. */
2544
0
        FreeDer(&der);
2545
        /* Not a certificate type supported. */
2546
0
        ret = WOLFSSL_BAD_CERTTYPE;
2547
0
    }
2548
2549
0
    return ret;
2550
0
}
2551
2552
/* Process certificate based on type.
2553
 *
2554
 * @param [in, out] ctx     SSL context object.
2555
 * @param [in, out] ssl     SSL object.
2556
 * @param [in]      buff    Buffer holding original data.
2557
 * @param [in]      sz      Size of data in buffer.
2558
 * @param [in]      der     DER encoding of certificate.
2559
 * @param [in]      format  Format of data.
2560
 * @param [in]      type    Type of data:
2561
 *                            CERT_TYPE, CA_TYPE or TRUSTED_PEER_TYPE.
2562
 * @param [in]      verify  What verification to do.
2563
 * @return  0 on success.
2564
 * @return  WOLFSSL_FATAL_ERROR on failure.
2565
 */
2566
static int ProcessBufferCertTypes(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
2567
    const unsigned char* buff, long sz, DerBuffer* der, int format, int type,
2568
    int verify)
2569
0
{
2570
0
    int ret;
2571
2572
0
    (void)buff;
2573
0
    (void)sz;
2574
0
    (void)format;
2575
2576
0
    ret = ProcessBufferCertHandleDer(ctx, ssl, der, type, verify);
2577
0
    if ((ret == 0) && (type == CERT_TYPE)) {
2578
        /* Process leaf certificate. */
2579
0
        ret = ProcessBufferCert(ctx, ssl, der);
2580
0
    }
2581
0
#if !defined(NO_WOLFSSL_CM_VERIFY) && (!defined(NO_WOLFSSL_CLIENT) || \
2582
0
    !defined(WOLFSSL_NO_CLIENT_AUTH))
2583
    /* Hand bad CA or user certificate to callback. */
2584
0
    if ((ret < 0) && ((type == CA_TYPE) || (type == CERT_TYPE))) {
2585
        /* Check for verification callback that may override error. */
2586
0
        if ((ctx != NULL) && (ctx->cm != NULL) &&
2587
0
                (ctx->cm->verifyCallback != NULL)) {
2588
            /* Verify and use callback. */
2589
0
            ret = CM_VerifyBuffer_ex(ctx->cm, buff, sz, format, ret, NULL);
2590
            /* Convert error. */
2591
0
            if (ret == 0) {
2592
0
                ret = WOLFSSL_FATAL_ERROR;
2593
0
            }
2594
0
            if (ret == 1) {
2595
0
                ret = 0;
2596
0
            }
2597
0
        }
2598
0
    }
2599
0
#endif /* NO_WOLFSSL_CM_VERIFY */
2600
2601
0
    return ret;
2602
0
}
2603
2604
/* Reset the cipher suites based on updated private key or certificate.
2605
 *
2606
 * @param [in, out] ctx     SSL context object.
2607
 * @param [in, out] ssl     SSL object.
2608
 * @param [in]      type    Type of certificate.
2609
 * @return  0 on success.
2610
 * @return  WOLFSSL_FATAL_ERROR when allocation fails.
2611
 */
2612
static int ProcessBufferResetSuites(WOLFSSL_CTX* ctx, WOLFSSL* ssl, int type)
2613
0
{
2614
0
    int ret = 0;
2615
2616
    /* Reset suites of SSL object. */
2617
0
    if (ssl != NULL) {
2618
0
        if (ssl->options.side == WOLFSSL_SERVER_END) {
2619
            /* Allocate memory for suites. */
2620
0
            if (AllocateSuites(ssl) != 0) {
2621
0
                ret = WOLFSSL_FATAL_ERROR;
2622
0
            }
2623
0
            else {
2624
                /* Determine cipher suites based on what we have. */
2625
0
                InitSuites(ssl->suites, ssl->version, ssl->buffers.keySz,
2626
0
                    WOLFSSL_HAVE_RSA, SSL_HAVE_PSK(ssl), ssl->options.haveDH,
2627
0
                    ssl->options.haveECDSAsig, ssl->options.haveECC, TRUE,
2628
0
                    ssl->options.haveStaticECC,
2629
0
                    ssl->options.useAnon, TRUE,
2630
0
                    TRUE, TRUE, TRUE, ssl->options.side);
2631
0
            }
2632
0
        }
2633
0
    }
2634
    /* Reset suites of SSL context object. */
2635
0
    else if ((type == CERT_TYPE) && (ctx->method->side == WOLFSSL_SERVER_END)) {
2636
        /* Allocate memory for suites. */
2637
0
        if (AllocateCtxSuites(ctx) != 0) {
2638
0
            ret = WOLFSSL_FATAL_ERROR;
2639
0
        }
2640
0
        else {
2641
            /* Determine cipher suites based on what we have. */
2642
0
            InitSuites(ctx->suites, ctx->method->version, ctx->privateKeySz,
2643
0
                WOLFSSL_HAVE_RSA, CTX_HAVE_PSK(ctx), ctx->haveDH,
2644
0
                ctx->haveECDSAsig, ctx->haveECC, TRUE, ctx->haveStaticECC,
2645
0
                CTX_USE_ANON(ctx),
2646
0
                TRUE, TRUE, TRUE, TRUE, ctx->method->side);
2647
0
        }
2648
0
    }
2649
2650
0
    return ret;
2651
0
}
2652
2653
#ifndef WOLFSSL_DUAL_ALG_CERTS
2654
    /* Determine whether the type is for a private key. */
2655
0
    #define IS_PRIVKEY_TYPE(type) ((type) == PRIVATEKEY_TYPE)
2656
#else
2657
    /* Determine whether the type is for a private key. */
2658
    #define IS_PRIVKEY_TYPE(type) (((type) == PRIVATEKEY_TYPE) ||   \
2659
                                   ((type) == ALT_PRIVATEKEY_TYPE))
2660
#endif
2661
2662
/* Process a buffer of data.
2663
 *
2664
 * Data type is a private key or a certificate.
2665
 * The format can be ASN.1 (DER) or PEM.
2666
 *
2667
 * @param [in, out] ctx        SSL context object.
2668
 * @param [in]      buff       Buffer holding data.
2669
 * @param [in]      sz         Size of data in buffer.
2670
 * @param [in]      format     Format of data:
2671
 *                               WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
2672
 * @param [in]      type       Type of data:
2673
 *                               CERT_TYPE, CA_TYPE, TRUSTED_PEER_TYPE,
2674
 *                               PRIVATEKEY_TYPE or ALT_PRIVATEKEY_TYPE.
2675
 * @param [in, out] ssl        SSL object.
2676
 * @param [out]     used       Number of bytes consumed.
2677
 * @param [in[      userChain  Whether this certificate is for user's chain.
2678
 * @param [in]      verify     How to verify certificate.
2679
 * @param [in]      source_name Associated filename or other source ID.
2680
 * @return  1 on success.
2681
 * @return  Less than 1 on failure.
2682
 */
2683
int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, long sz,
2684
    int format, int type, WOLFSSL* ssl, long* used, int userChain, int verify,
2685
    const char *source_name)
2686
0
{
2687
0
    DerBuffer*    der = NULL;
2688
0
    int           ret = 0;
2689
0
    void*         heap = WOLFSSL_HEAP(ctx, ssl);
2690
0
    WC_DECLARE_VAR(info, EncryptedInfo, 1, 0);
2691
0
    int           algId = 0;
2692
#ifdef WOLFSSL_DEBUG_CERTIFICATE_LOADS
2693
    long usedAtStart = used ? *used : 0L;
2694
#else
2695
0
    (void)source_name;
2696
0
#endif
2697
2698
0
    WOLFSSL_ENTER("ProcessBuffer");
2699
2700
    /* Check data format is supported. */
2701
0
    if ((format != WOLFSSL_FILETYPE_ASN1) && (format != WOLFSSL_FILETYPE_PEM)) {
2702
0
        ret = WOLFSSL_BAD_FILETYPE;
2703
0
    }
2704
    /* Need an object to store certificate into. */
2705
0
    if ((ret == 0) && (ctx == NULL) && (ssl == NULL)) {
2706
0
        ret = BAD_FUNC_ARG;
2707
0
    }
2708
    /* CA certificates go into the SSL context object. */
2709
0
    if ((ret == 0) && (ctx == NULL) && (type == CA_TYPE)) {
2710
0
        ret = BAD_FUNC_ARG;
2711
0
    }
2712
    /* This API does not handle CHAIN_CERT_TYPE */
2713
0
    if ((ret == 0) && (type == CHAIN_CERT_TYPE)) {
2714
0
        ret = BAD_FUNC_ARG;
2715
0
    }
2716
    /* Reject negative size - would wrap to huge word32. */
2717
0
    if ((ret == 0) && (sz < 0)) {
2718
0
        ret = BAD_FUNC_ARG;
2719
0
    }
2720
2721
#ifdef WOLFSSL_SMALL_STACK
2722
    if (ret == 0) {
2723
        /* Allocate memory for encryption information. */
2724
        info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), heap,
2725
            DYNAMIC_TYPE_ENCRYPTEDINFO);
2726
        if (info == NULL) {
2727
            ret = MEMORY_E;
2728
        }
2729
    }
2730
#endif
2731
0
    if (ret == 0) {
2732
        /* Initialize encryption information. */
2733
0
        XMEMSET(info, 0, sizeof(EncryptedInfo));
2734
    #if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED)
2735
        if (ctx != NULL) {
2736
            info->passwd_cb       = ctx->passwd_cb;
2737
            info->passwd_userdata = ctx->passwd_userdata;
2738
        }
2739
    #endif
2740
2741
        /* Get the DER data for a private key or certificate. */
2742
0
        ret = DataToDerBuffer(buff, (word32)sz, format, type, info, heap, &der,
2743
0
            &algId);
2744
0
        if (used != NULL) {
2745
            /* Update to amount used/consumed. */
2746
0
            *used = info->consumed;
2747
0
        }
2748
    #ifdef WOLFSSL_SMALL_STACK
2749
        if (ret != 0) {
2750
             /* Info no longer needed as loading failed. */
2751
             XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO);
2752
        }
2753
    #endif
2754
0
    }
2755
2756
0
    if ((ret == 0) && IS_PRIVKEY_TYPE(type)) {
2757
        /* Process the private key. */
2758
0
        ret = ProcessBufferPrivateKey(ctx, ssl, der, format, info, heap, type,
2759
0
            algId);
2760
0
        WC_FREE_VAR_EX(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO);
2761
0
    }
2762
0
    else if (ret == 0) {
2763
        /* Processing a certificate. */
2764
0
        if (userChain) {
2765
            /* Take original buffer and add to user chain to send in TLS
2766
             * handshake. */
2767
0
            ret = ProcessUserChain(ctx, ssl, buff, sz, format, type, used, info,
2768
0
                verify);
2769
            /* Additional chain is optional */
2770
0
            if (ret == WC_NO_ERR_TRACE(ASN_NO_PEM_HEADER)) {
2771
0
                unsigned long pemErr = 0;
2772
0
                CLEAR_ASN_NO_PEM_HEADER_ERROR(pemErr);
2773
0
                ret = 0;
2774
0
            }
2775
#ifdef WOLFSSL_DEBUG_CERTIFICATE_LOADS
2776
            if (ret < 0) {
2777
#ifdef NO_ERROR_STRINGS
2778
                WOLFSSL_DEBUG_PRINTF(
2779
                    "ERROR: ProcessUserChain: certificate from %s at offset %ld"
2780
                    " rejected with code %d\n",
2781
                    source_name, usedAtStart, ret);
2782
#else
2783
                WOLFSSL_DEBUG_PRINTF(
2784
                    "ERROR: ProcessUserChain: certificate from %s at offset %ld"
2785
                    " rejected with code %d: %s\n",
2786
                    source_name, usedAtStart, ret,
2787
                    wolfSSL_ERR_reason_error_string(ret));
2788
#endif
2789
            }
2790
#endif /* WOLFSSL_DEBUG_CERTIFICATE_LOADS */
2791
0
        }
2792
2793
0
        WC_FREE_VAR_EX(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO);
2794
2795
0
        if (ret == 0) {
2796
            /* Process the different types of certificates. */
2797
0
            ret = ProcessBufferCertTypes(ctx, ssl, buff, sz, der, format, type,
2798
0
                verify);
2799
#ifdef WOLFSSL_DEBUG_CERTIFICATE_LOADS
2800
            if (ret < 0) {
2801
#ifdef NO_ERROR_STRINGS
2802
                WOLFSSL_DEBUG_PRINTF(
2803
                    "ERROR: ProcessBufferCertTypes: certificate from %s at"
2804
                    " offset %ld rejected with code %d\n",
2805
                    source_name, usedAtStart, ret);
2806
#else
2807
                WOLFSSL_DEBUG_PRINTF(
2808
                    "ERROR: ProcessBufferCertTypes: certificate from %s at"
2809
                    " offset %ld rejected with code %d: %s\n",
2810
                    source_name, usedAtStart, ret,
2811
                    wolfSSL_ERR_reason_error_string(ret));
2812
#endif
2813
            }
2814
#endif /* WOLFSSL_DEBUG_CERTIFICATE_LOADS */
2815
0
        }
2816
0
        else {
2817
0
            FreeDer(&der);
2818
0
        }
2819
0
    }
2820
2821
    /* Reset suites if this is a private key or user certificate. */
2822
0
    if ((ret == 0) && ((type == PRIVATEKEY_TYPE) || (type == CERT_TYPE))) {
2823
0
        ret = ProcessBufferResetSuites(ctx, ssl, type);
2824
0
    }
2825
2826
    /* Convert return code. */
2827
0
    if (ret == 0) {
2828
0
        ret = 1;
2829
0
    }
2830
0
    else if (ret == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) {
2831
0
        ret = 0;
2832
0
    }
2833
0
    WOLFSSL_LEAVE("ProcessBuffer", ret);
2834
0
    return ret;
2835
0
}
2836
2837
#if defined(WOLFSSL_WPAS) && defined(HAVE_CRL)
2838
/* Try to parse data as a PEM CRL.
2839
 *
2840
 * @param [in]  ctx       SSL context object.
2841
 * @param [in]  buff      Buffer containing potential CRL in PEM format.
2842
 * @param [in]  sz        Amount of data in buffer remaining.
2843
 * @param [out] consumed  Number of bytes in buffer was the CRL.
2844
 * @return  0 on success.
2845
 */
2846
static int ProcessChainBufferCRL(WOLFSSL_CTX* ctx, const unsigned char* buff,
2847
    long sz, long* consumed)
2848
{
2849
    int        ret = 0;
2850
    DerBuffer* der = NULL;
2851
    WC_DECLARE_VAR(info, EncryptedInfo, 1, 0);
2852
2853
    WOLFSSL_MSG("Trying a CRL");
2854
2855
    /* A PEM CRL has no Proc-Type header, so the encryption information must
2856
     * start zeroed or PemToDer() acts on a stale encrypted-key flag. */
2857
    WC_CALLOC_VAR_EX(info, EncryptedInfo, 1, ctx->heap,
2858
        DYNAMIC_TYPE_ENCRYPTEDINFO, ret = MEMORY_E);
2859
2860
    if (ret == 0) {
2861
        ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, info, NULL);
2862
    }
2863
    if (ret == 0) {
2864
        WOLFSSL_MSG("   Processed a CRL");
2865
        wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, der->buffer, der->length,
2866
            WOLFSSL_FILETYPE_ASN1);
2867
        FreeDer(&der);
2868
        *consumed = info->consumed;
2869
    }
2870
2871
    WC_FREE_VAR_EX(info, ctx->heap, DYNAMIC_TYPE_ENCRYPTEDINFO);
2872
2873
    return ret;
2874
}
2875
#endif
2876
2877
/* Process all chain certificates (and CRLs) in the PEM data.
2878
 *
2879
 * @param [in, out] ctx     SSL context object.
2880
 * @param [in, out] ssl     SSL object.
2881
 * @param [in]      buff    Buffer containing PEM data.
2882
 * @param [in]      sz      Size of data in buffer.
2883
 * @param [in]      type    Type of data.
2884
 * @param [in]      verify  How to verify certificate.
2885
 * @param [in]      source_name   Associated filename or other source ID.
2886
 * @return  1 on success.
2887
 * @return  0 on failure.
2888
 * @return  MEMORY_E when dynamic memory allocation fails.
2889
 */
2890
static int ProcessChainBuffer(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
2891
    const unsigned char* buff, long sz, int type, int verify,
2892
    const char *source_name)
2893
0
{
2894
0
    int  ret    = 0;
2895
0
    long used   = 0;
2896
0
    int  gotOne = 0;
2897
2898
0
    WOLFSSL_MSG("Processing CA PEM file");
2899
    /* Keep processing file while no errors and data to parse. */
2900
0
    while ((ret >= 0) && (used < sz)) {
2901
0
        long consumed = used;
2902
2903
        /* Process the buffer. */
2904
0
        ret = ProcessBuffer(ctx, buff + used, sz - used, WOLFSSL_FILETYPE_PEM,
2905
0
            type, ssl, &consumed, 0, verify, source_name);
2906
        /* Memory allocation failure is fatal. */
2907
0
        if (ret == WC_NO_ERR_TRACE(MEMORY_E)) {
2908
0
            gotOne = 0;
2909
0
        }
2910
        /* Other error parsing. */
2911
0
        else if (ret < 0) {
2912
#if defined(WOLFSSL_WPAS) && defined(HAVE_CRL)
2913
            /* Try parsing a CRL. */
2914
            if (ProcessChainBufferCRL(ctx, buff + used, sz - used,
2915
                    &consumed) == 0) {
2916
                ret = 0;
2917
            }
2918
            else
2919
#endif
2920
            /* Check whether we made progress. */
2921
0
            if (consumed > 0) {
2922
0
                WOLFSSL_ERROR(ret);
2923
0
                WOLFSSL_MSG("CA Parse failed, with progress in file.");
2924
0
                WOLFSSL_MSG("Search for other certs in file");
2925
                /* Check if we have more data to parse to recover. */
2926
0
                if (used + consumed < sz) {
2927
0
                    ret = 0;
2928
0
                }
2929
0
            }
2930
0
            else {
2931
                /* No progress in parsing being made - stop here. */
2932
0
                WOLFSSL_MSG("CA Parse failed, no progress in file.");
2933
0
                WOLFSSL_MSG("Do not continue search for other certs in file");
2934
0
            }
2935
0
        }
2936
0
        else {
2937
            /* Got a certificate out. */
2938
0
            WOLFSSL_MSG("   Processed a CA");
2939
0
            gotOne = 1;
2940
0
        }
2941
        /* Update used count. */
2942
0
        used += consumed;
2943
0
    }
2944
2945
    /* May have other unparsable data but did we get a certificate? */
2946
0
    if (gotOne) {
2947
0
        WOLFSSL_MSG("Processed at least one valid CA. Other stuff OK");
2948
0
        ret = 1;
2949
0
    }
2950
0
    return ret;
2951
0
}
2952
2953
2954
/* Get verify settings for AddCA from SSL context. */
2955
#define GET_VERIFY_SETTING_CTX(ctx) \
2956
0
    ((ctx) && (ctx)->verifyNone ? NO_VERIFY : VERIFY)
2957
/* Get verify settings for AddCA from SSL. */
2958
#define GET_VERIFY_SETTING_SSL(ssl) \
2959
0
    ((ssl)->options.verifyNone ? NO_VERIFY : VERIFY)
2960
2961
#ifndef NO_FILESYSTEM
2962
2963
/* Process data from a file as private keys, CRL or certificates.
2964
 *
2965
 * @param [in, out] ctx        SSL context object.
2966
 * @param [in]      fname      Name of file to read.
2967
 * @param [in]      format     Format of data:
2968
 *                               WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
2969
 * @param [in]      type       Type of data:
2970
 *                               CERT_TYPE, CA_TYPE, TRUSTED_PEER_TYPE,
2971
 *                               PRIVATEKEY_TYPE or ALT_PRIVATEKEY_TYPE.
2972
 * @param [in, out] ssl        SSL object.
2973
 * @param [in]      userChain  Whether file contains chain of certificates.
2974
 * @param [in, out] crl        CRL object to load data into.
2975
 * @param [in]      verify     How to verify certificates.
2976
 * @return  1 on success.
2977
 * @return  WOLFSSL_BAD_FILE when reading the file fails.
2978
 * @return  WOLFSSL_BAD_CERTTYPE when unable to detect certificate type.
2979
 */
2980
int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type,
2981
    WOLFSSL* ssl, int userChain, WOLFSSL_CRL* crl, int verify)
2982
0
{
2983
0
    int    ret = 0;
2984
0
#ifndef WOLFSSL_SMALL_STACK
2985
0
    byte   stackBuffer[FILE_BUFFER_SIZE];
2986
0
#endif
2987
0
    StaticBuffer content;
2988
0
    long   sz = 0;
2989
0
    void*  heap = WOLFSSL_HEAP(ctx, ssl);
2990
2991
0
    (void)crl;
2992
0
    (void)heap;
2993
2994
#ifdef WOLFSSL_SMALL_STACK
2995
    static_buffer_init(&content);
2996
#else
2997
0
    static_buffer_init(&content, stackBuffer, FILE_BUFFER_SIZE);
2998
0
#endif
2999
3000
    /* Read file into static buffer. */
3001
0
    ret = wolfssl_read_file_static(fname, &content, heap, DYNAMIC_TYPE_FILE,
3002
0
        &sz);
3003
0
    if ((ret == 0) && (type == DETECT_CERT_TYPE) &&
3004
0
            (format != WOLFSSL_FILETYPE_PEM)) {
3005
0
        WOLFSSL_MSG_CERT_LOG("Cannot detect certificate type when not PEM");
3006
0
        ret = WOLFSSL_BAD_CERTTYPE;
3007
0
    }
3008
    /* Try to detect type by parsing cert header and footer. */
3009
0
    if ((ret == 0) && (type == DETECT_CERT_TYPE)) {
3010
0
#if !defined(NO_CODING) && !defined(WOLFSSL_NO_PEM)
3011
0
        const char* header = NULL;
3012
0
        const char* footer = NULL;
3013
#ifdef HAVE_CRL
3014
        WOLFSSL_MSG_CERT("Detecting cert type... (including CRL_TYPE)");
3015
#else
3016
0
        WOLFSSL_MSG_CERT("Detecting cert type... (HAVE_CRL not defined)");
3017
0
#endif
3018
3019
        /* Look for CA header and footer - same as CERT_TYPE. */
3020
0
        if (wc_PemGetHeaderFooter(CA_TYPE, &header, &footer) == 0 &&
3021
0
                (XSTRNSTR((char*)content.buffer, header, sz) != NULL)) {
3022
0
            type = CA_TYPE;
3023
0
            WOLFSSL_MSG_CERT_LOG_EX("Detected cert type CA_TYPE = %d:", type);
3024
0
        }
3025
#ifdef HAVE_CRL
3026
        /* Look for CRL header and footer. */
3027
        else if (wc_PemGetHeaderFooter(CRL_TYPE, &header, &footer) == 0 &&
3028
                (XSTRNSTR((char*)content.buffer, header, sz) != NULL)) {
3029
            type = CRL_TYPE;
3030
            WOLFSSL_MSG_CERT_LOG_EX("Detected cert type CRL_TYPE = %d:", type);
3031
        }
3032
#endif
3033
        /* Look for cert header and footer - same as CA_TYPE. */
3034
0
        else if (wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer) == 0 &&
3035
0
                (XSTRNSTR((char*)content.buffer, header, sz) !=
3036
0
                    NULL)) {
3037
0
            type = CERT_TYPE;
3038
0
            WOLFSSL_MSG_CERT_LOG_EX("Detected cert type CERT_TYPE = %d:", type);
3039
0
        }
3040
0
        else
3041
0
#endif /* !NO_CODING && !WOLFSSL_NO_PEM */
3042
0
        {
3043
            /* Not a header that we support. */
3044
0
            WOLFSSL_MSG_CERT_LOG("Failed to detect certificate type");
3045
#ifdef WOLFSSL_DEBUG_CERTIFICATE_LOADS
3046
            WOLFSSL_DEBUG_PRINTF(
3047
                "ERROR: ProcessFile: Failed to detect certificate type"
3048
                " of \"%s\"\n",
3049
                fname);
3050
#endif
3051
0
            ret = WOLFSSL_BAD_CERTTYPE;
3052
0
        }
3053
0
    } /* (ret == 0) && (type == DETECT_CERT_TYPE) */
3054
3055
0
    if (ret == 0) {
3056
        /* When CA or trusted peer and PEM - process as a chain buffer. */
3057
0
        if (((type == CA_TYPE) || (type == TRUSTED_PEER_TYPE)) &&
3058
0
                (format == WOLFSSL_FILETYPE_PEM)) {
3059
0
            WOLFSSL_MSG_CERT("Processing cert chain buffer...");
3060
0
            ret = ProcessChainBuffer(ctx, ssl, content.buffer, sz, type,
3061
0
                verify, fname);
3062
0
        }
3063
#ifdef HAVE_CRL
3064
        else if (type == CRL_TYPE) {
3065
            WOLFSSL_MSG_CERT("Loading CRL...");
3066
            ret = BufferLoadCRL(crl, content.buffer, sz, format, verify);
3067
        }
3068
#endif
3069
#ifdef WOLFSSL_DUAL_ALG_CERTS
3070
        else if (type == PRIVATEKEY_TYPE) {
3071
            /* When support for dual algorithm certificates is enabled, the
3072
             * private key file may contain both the primary and the
3073
             * alternative private key. Hence, we have to parse both of them.
3074
             */
3075
            long consumed = 0;
3076
3077
            ret = ProcessBuffer(ctx, content.buffer, sz, format, type, ssl,
3078
                &consumed, userChain, verify, fname);
3079
            if ((ret == 1) && (consumed < sz)) {
3080
                ret = ProcessBuffer(ctx, content.buffer + consumed,
3081
                    sz - consumed, format, ALT_PRIVATEKEY_TYPE, ssl, NULL, 0,
3082
                    verify, fname);
3083
            }
3084
        }
3085
#endif
3086
0
        else {
3087
            /* Load all other certificate types. */
3088
0
            ret = ProcessBuffer(ctx, content.buffer, sz, format, type, ssl,
3089
0
                NULL, userChain, verify, fname);
3090
0
        }
3091
0
    }
3092
3093
    /* Dispose of dynamically allocated data. */
3094
0
    static_buffer_free(&content, heap, DYNAMIC_TYPE_FILE);
3095
0
    return ret;
3096
0
}
3097
3098
#if defined(WOLFSSL_TRUST_PEER_CERT)
3099
/* Load a trusted peer certificate from a file with the caller's verification
3100
 * setting.
3101
 *
3102
 * @param [in, out] ctx     SSL context object.
3103
 * @param [in]      file    Name of peer certificate file.
3104
 * @param [in]      format  Format of data: WOLFSSL_FILETYPE_PEM or
3105
 *                             WOLFSSL_FILETYPE_ASN1.
3106
 * @param [in]      verify  How to verify the certificate.
3107
 * @return  1 on success.
3108
 * @return  0 when ctx or file is NULL.
3109
 * @return  Negative on error.
3110
 */
3111
static int TrustPeerCertFile(WOLFSSL_CTX* ctx, const char* file, int format,
3112
    int verify)
3113
{
3114
    int ret;
3115
3116
    /* Validate parameters. */
3117
    if ((ctx == NULL) || (file == NULL)) {
3118
        ret = 0;
3119
    }
3120
    else {
3121
        ret = ProcessFile(ctx, file, format, TRUSTED_PEER_TYPE, NULL, 0, NULL,
3122
            verify);
3123
    }
3124
3125
    return ret;
3126
}
3127
#endif /* WOLFSSL_TRUST_PEER_CERT */
3128
3129
#ifndef NO_WOLFSSL_DIR
3130
/* Load file when filename is in the path.
3131
 *
3132
 * @param [in, out] ctx           SSL context object.
3133
 * @param [in]      name          Name of file.
3134
 * @param [in]      verify        How to verify a certificate.
3135
 * @param [in]      flags         Flags representing options for loading.
3136
 * @param [in, out] failCount     Number of files that failed to load.
3137
 * @param [in, out] successCount  Number of files successfully loaded.
3138
 * @return  1 on success.
3139
 * @return  Not 1 when loading PEM certificate failed.
3140
 */
3141
static int wolfssl_ctx_load_path_file(WOLFSSL_CTX* ctx, const char* name,
3142
    int verify, int flags, int* failCount, int* successCount)
3143
0
{
3144
0
    int ret;
3145
3146
    /* Attempt to load file as a CA. */
3147
0
    ret = ProcessFile(ctx, name, WOLFSSL_FILETYPE_PEM, CA_TYPE, NULL, 0, NULL,
3148
0
        verify);
3149
0
    if (ret != 1) {
3150
        /* When ignoring errors or loading PEM only and no PEM. don't fail. */
3151
0
        if ((flags & WOLFSSL_LOAD_FLAG_IGNORE_ERR) ||
3152
0
                ((flags & WOLFSSL_LOAD_FLAG_PEM_CA_ONLY) &&
3153
0
                 (ret == WC_NO_ERR_TRACE(ASN_NO_PEM_HEADER)))) {
3154
0
            unsigned long err = 0;
3155
0
            CLEAR_ASN_NO_PEM_HEADER_ERROR(err);
3156
        #if defined(WOLFSSL_QT)
3157
            ret = 1;
3158
        #endif
3159
0
        }
3160
0
        else {
3161
0
            WOLFSSL_ERROR(ret);
3162
0
            WOLFSSL_MSG("Load CA file failed, continuing");
3163
            /* Add to fail count. */
3164
0
            (*failCount)++;
3165
0
        }
3166
0
    }
3167
0
    else {
3168
    #if defined(WOLFSSL_TRUST_PEER_CERT) && defined(OPENSSL_COMPATIBLE_DEFAULTS)
3169
        /* Try loading as a trusted peer certificate with the same
3170
         * verification setting as the CA load. */
3171
        ret = TrustPeerCertFile(ctx, name, WOLFSSL_FILETYPE_PEM, verify);
3172
        if (ret != 1) {
3173
            WOLFSSL_MSG("wolfSSL_CTX_trust_peer_cert error. "
3174
                        "Ignoring this error.");
3175
        }
3176
    #endif
3177
        /* Add to success count. */
3178
0
        (*successCount)++;
3179
0
    }
3180
3181
0
    return ret;
3182
0
}
3183
3184
/* Load PEM formatted CA files from a path.
3185
 *
3186
 * @param [in, out] ctx           SSL context object.
3187
 * @param [in]      path          Path to directory to read.
3188
 * @param [in]      flags         Flags representing options for loading.
3189
 * @param [in]      verify        How to verify a certificate.
3190
 * @param [in]      successCount  Number of files successfully loaded.
3191
 * @return  1 on success.
3192
 * @return  0 on failure.
3193
 * @return  MEMORY_E when dynamic memory allocation fails.
3194
 */
3195
static int wolfssl_ctx_load_path(WOLFSSL_CTX* ctx, const char* path,
3196
    word32 flags, int verify, int successCount)
3197
0
{
3198
0
    int ret = 1;
3199
0
    char* name = NULL;
3200
0
    int fileRet;
3201
0
    int failCount = 0;
3202
0
    WC_DECLARE_VAR(readCtx, ReadDirCtx, 1, 0);
3203
3204
    /* Allocate memory for directory reading context. */
3205
0
    WC_ALLOC_VAR_EX(readCtx, ReadDirCtx, 1, ctx->heap, DYNAMIC_TYPE_DIRCTX,
3206
0
        ret=MEMORY_E);
3207
3208
0
    if (ret == 1) {
3209
        /* Get name of first file in path. */
3210
0
        fileRet = wc_ReadDirFirst(readCtx, path, &name);
3211
        /* While getting filename doesn't fail and name returned, process file.
3212
         */
3213
0
        while ((fileRet == 0) && (name != NULL)) {
3214
0
            WOLFSSL_MSG(name);
3215
            /* Load file. */
3216
0
            ret = wolfssl_ctx_load_path_file(ctx, name, verify, (int)flags,
3217
0
                &failCount, &successCount);
3218
            /* Get next filename. */
3219
0
            fileRet = wc_ReadDirNext(readCtx, path, &name);
3220
0
        }
3221
        /* Cleanup directory reading context. */
3222
0
        wc_ReadDirClose(readCtx);
3223
3224
        /* When not WOLFSSL_QT, ret is always overwritten. */
3225
0
        (void)ret;
3226
3227
        /* Return real directory read failure error codes. */
3228
0
        if (fileRet != WC_READDIR_NOFILE) {
3229
0
            ret = fileRet;
3230
        #if defined(WOLFSSL_QT) || defined(WOLFSSL_IGNORE_BAD_CERT_PATH)
3231
            /* Ignore bad path error when flag set. */
3232
            if ((ret == WC_NO_ERR_TRACE(BAD_PATH_ERROR)) &&
3233
                    (flags & WOLFSSL_LOAD_FLAG_IGNORE_BAD_PATH_ERR)) {
3234
               /* QSslSocket always loads certs in system folder
3235
                * when it is initialized.
3236
                * Compliant with OpenSSL when flag set.
3237
                */
3238
                ret = 1;
3239
            }
3240
            else {
3241
                /* qssl socket wants to know errors. */
3242
                WOLFSSL_ERROR(ret);
3243
            }
3244
        #endif
3245
0
        }
3246
        /* Report failure if no files successfully loaded or there were
3247
         * failures. */
3248
0
        else if ((successCount == 0) || (failCount > 0)) {
3249
            /* Use existing error code if exists. */
3250
        #if defined(WOLFSSL_QT)
3251
            /* Compliant with OpenSSL when flag set. */
3252
            if (!(flags & WOLFSSL_LOAD_FLAG_IGNORE_ZEROFILE))
3253
        #endif
3254
0
            {
3255
                /* Return 0 when no files loaded. */
3256
0
                ret = 0;
3257
0
            }
3258
0
        }
3259
0
        else {
3260
            /* We loaded something so it is a success. */
3261
0
            ret = 1;
3262
0
        }
3263
3264
0
        WC_FREE_VAR_EX(readCtx, ctx->heap, DYNAMIC_TYPE_DIRCTX);
3265
0
    }
3266
3267
0
    return ret;
3268
0
}
3269
#endif
3270
3271
/* Load a file and/or files in path
3272
 *
3273
 * No c_rehash.
3274
 *
3275
 * @param [in, out] ctx    SSL context object.
3276
 * @param [in]      file   Name of file to load. May be NULL.
3277
 * @param [in]      path   Path to directory containing PEM CA files.
3278
 *                         May be NULL.
3279
 * @param [in]      flags  Flags representing options for loading.
3280
 * @return  1 on success.
3281
 * @return  0 on failure.
3282
 * @return  NOT_COMPILED_IN when directory reading not supported and path is
3283
 *          not NULL.
3284
 * @return  Other negative on error.
3285
 */
3286
int wolfSSL_CTX_load_verify_locations_ex(WOLFSSL_CTX* ctx, const char* file,
3287
    const char* path, word32 flags)
3288
0
{
3289
0
    int ret = 1;
3290
0
#ifndef NO_WOLFSSL_DIR
3291
0
    int successCount = 0;
3292
0
#endif
3293
0
    int verify = WOLFSSL_VERIFY_DEFAULT;
3294
3295
0
    WOLFSSL_MSG("wolfSSL_CTX_load_verify_locations_ex");
3296
3297
    /* Validate parameters. */
3298
0
    if ((ctx == NULL) || ((file == NULL) && (path == NULL))) {
3299
0
        ret = 0;
3300
0
    }
3301
3302
#ifdef WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION
3303
    if (ret == 1) {
3304
    /* TEST ONLY CODE: force native cert validation on */
3305
        WOLFSSL_MSG("ANCV Test: Loading system CA certs");
3306
        wolfSSL_CTX_load_system_CA_certs(ctx);
3307
    }
3308
#endif
3309
3310
0
    if (ret == 1) {
3311
        /* Get setting on how to verify certificates. */
3312
0
        verify = GET_VERIFY_SETTING_CTX(ctx);
3313
        /* Overwrite setting when flag set. */
3314
0
        if (flags & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY) {
3315
0
            verify = VERIFY_SKIP_DATE;
3316
0
        }
3317
3318
0
        if (file != NULL) {
3319
0
#ifdef WOLFSSL_PEM_TO_DER
3320
            /* Load the PEM formatted CA file */
3321
0
            ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CA_TYPE, NULL, 0,
3322
0
                NULL, verify);
3323
#else
3324
            /* Load the DER formatted CA file */
3325
            ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_ASN1, CA_TYPE, NULL,
3326
                0, NULL, verify);
3327
#endif
3328
0
#ifndef NO_WOLFSSL_DIR
3329
0
            if (ret == 1) {
3330
                /* Include success in overall count. */
3331
0
                successCount++;
3332
0
            }
3333
0
#endif
3334
#if defined(WOLFSSL_TRUST_PEER_CERT) && defined(OPENSSL_COMPATIBLE_DEFAULTS)
3335
            if (ret == 1) {
3336
                /* Load CA as a trusted peer certificate. The verification
3337
                 * setting computed above, including
3338
                 * WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY, applies to the trusted
3339
                 * peer copy too. */
3340
#ifdef WOLFSSL_PEM_TO_DER
3341
                ret = TrustPeerCertFile(ctx, file, WOLFSSL_FILETYPE_PEM,
3342
                    verify);
3343
#else
3344
                ret = TrustPeerCertFile(ctx, file, WOLFSSL_FILETYPE_ASN1,
3345
                    verify);
3346
#endif
3347
                if (ret != 1) {
3348
                    WOLFSSL_MSG("wolfSSL_CTX_trust_peer_cert error");
3349
                }
3350
            }
3351
#endif
3352
0
        }
3353
0
    }
3354
3355
0
    if ((ret == 1) && (path != NULL)) {
3356
0
#ifndef NO_WOLFSSL_DIR
3357
        /* Load CA files form path. */
3358
0
        ret = wolfssl_ctx_load_path(ctx, path, flags, verify, successCount);
3359
#else
3360
        /* Loading a path not supported. */
3361
        ret = NOT_COMPILED_IN;
3362
        (void)flags;
3363
#endif
3364
0
    }
3365
3366
0
    return ret;
3367
0
}
3368
3369
/* Load a file and/or files in path
3370
 *
3371
 * No c_rehash.
3372
 *
3373
 * @param [in, out] ctx    SSL context object.
3374
 * @param [in]      file   Name of file to load. May be NULL.
3375
 * @param [in]      path   Path to directory containing PEM CA files.
3376
 *                         May be NULL.
3377
 * @return  1 on success.
3378
 * @return  0 on failure.
3379
 */
3380
WOLFSSL_ABI
3381
int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file,
3382
                                     const char* path)
3383
0
{
3384
    /* Load using default flags/options. */
3385
0
    int ret = wolfSSL_CTX_load_verify_locations_ex(ctx, file, path,
3386
0
        WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS);
3387
3388
    /* Return 1 on success or 0 on failure. */
3389
0
    return WS_RETURN_CODE(ret, 0);
3390
0
}
3391
3392
/* Load a file and/or files in path, with OpenSSL-compatible semantics.
3393
 *
3394
 * No c_rehash.
3395
 *
3396
 * @param [in, out] ctx    SSL context object.
3397
 * @param [in]      file   Name of file to load. May be NULL.
3398
 * @param [in]      path   Path to directory containing PEM CA files.
3399
 *                         May be NULL.
3400
 * @return  1 on success.
3401
 * @return  0 on failure.
3402
 */
3403
int wolfSSL_CTX_load_verify_locations_compat(WOLFSSL_CTX* ctx, const char* file,
3404
                                     const char* path)
3405
0
{
3406
    /* We want to keep trying to load more CA certs even if one cert in the
3407
     * directory is bad and can't be used (e.g. if one is expired), and we
3408
     * want to return success if any were successfully loaded (mimicking
3409
     * OpenSSL SSL_CTX_load_verify_locations() semantics), so we use
3410
     * WOLFSSL_LOAD_FLAG_IGNORE_ERR.  OpenSSL (as of v3.3.2) actually
3411
     * returns success even if no certs are loaded (e.g. because the
3412
     * supplied "path" doesn't exist or access is prohibited), and only
3413
     * returns failure if the "file" is non-null and fails to load.
3414
     *
3415
     * Note that if a file is supplied and can't be successfully loaded, the
3416
     * overall call fails and the path is never even evaluated.  This is
3417
     * consistent with OpenSSL behavior.
3418
     */
3419
3420
0
    int ret = wolfSSL_CTX_load_verify_locations_ex(ctx, file, path,
3421
0
        WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS | WOLFSSL_LOAD_FLAG_IGNORE_ERR);
3422
3423
    /* Return 1 on success or 0 on failure. */
3424
0
    return WS_RETURN_CODE(ret, 0);
3425
0
}
3426
3427
#ifdef WOLFSSL_TRUST_PEER_CERT
3428
/* Load a trusted peer certificate into SSL context.
3429
 *
3430
 * @param [in, out] ctx     SSL context object.
3431
 * @param [in]      file    Name of peer certificate file.
3432
 * @param [in]      format  Format of data:
3433
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
3434
 * @return  1 on success.
3435
 * @return  0 when ctx or file is NULL.
3436
 */
3437
int wolfSSL_CTX_trust_peer_cert(WOLFSSL_CTX* ctx, const char* file, int format)
3438
{
3439
    int ret;
3440
3441
    WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_cert");
3442
3443
    /* Validate parameters. */
3444
    if ((ctx == NULL) || (file == NULL)) {
3445
        ret = 0;
3446
    }
3447
    else {
3448
        ret = TrustPeerCertFile(ctx, file, format, GET_VERIFY_SETTING_CTX(ctx));
3449
    }
3450
3451
    return ret;
3452
}
3453
3454
/* Load a trusted peer certificate into SSL.
3455
 *
3456
 * @param [in, out] ssl     SSL object.
3457
 * @param [in]      file    Name of peer certificate file.
3458
 * @param [in]      format  Format of data:
3459
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
3460
 * @return  1 on success.
3461
 * @return  0 when ssl or file is NULL.
3462
 */
3463
int wolfSSL_trust_peer_cert(WOLFSSL* ssl, const char* file, int format)
3464
{
3465
    int ret;
3466
3467
    WOLFSSL_ENTER("wolfSSL_trust_peer_cert");
3468
3469
    /* Validate parameters. */
3470
    if ((ssl == NULL) || (file == NULL)) {
3471
        ret = 0;
3472
    }
3473
    else {
3474
        ret = ProcessFile(NULL, file, format, TRUSTED_PEER_TYPE, ssl, 0, NULL,
3475
            GET_VERIFY_SETTING_SSL(ssl));
3476
    }
3477
3478
    return ret;
3479
}
3480
#endif /* WOLFSSL_TRUST_PEER_CERT */
3481
3482
3483
#ifdef WOLFSSL_DER_LOAD
3484
3485
/* Load a CA certificate into SSL context.
3486
 *
3487
 * @param [in, out] ctx     SSL context object.
3488
 * @param [in]      file    Name of peer certificate file.
3489
 * @param [in]      format  Format of data:
3490
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
3491
 * @return  1 on success.
3492
 * @return  0 on failure.
3493
 */
3494
int wolfSSL_CTX_der_load_verify_locations(WOLFSSL_CTX* ctx, const char* file,
3495
    int format)
3496
{
3497
    int ret;
3498
3499
    WOLFSSL_ENTER("wolfSSL_CTX_der_load_verify_locations");
3500
3501
    /* Validate parameters. */
3502
    if ((ctx == NULL) || (file == NULL)) {
3503
        ret = 0;
3504
    }
3505
    else {
3506
#ifdef WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION
3507
        /* TEST ONLY CODE: force native cert validation on */
3508
        WOLFSSL_MSG("ANCV Test: loading system CA certs");
3509
        wolfSSL_CTX_load_system_CA_certs(ctx);
3510
#endif
3511
        ret = ProcessFile(ctx, file, format, CA_TYPE, NULL, 0, NULL,
3512
            GET_VERIFY_SETTING_CTX(ctx));
3513
    }
3514
3515
    /* Return 1 on success or 0 on failure. */
3516
    return WS_RC(ret);
3517
}
3518
3519
#endif /* WOLFSSL_DER_LOAD */
3520
3521
3522
/* Load a user certificate into SSL context.
3523
 *
3524
 * @param [in, out] ctx     SSL context object.
3525
 * @param [in]      file    Name of user certificate file.
3526
 * @param [in]      format  Format of data:
3527
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
3528
 * @return  1 on success.
3529
 * @return  0 on failure.
3530
 */
3531
WOLFSSL_ABI
3532
int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX* ctx, const char* file,
3533
    int format)
3534
0
{
3535
0
    int ret;
3536
3537
0
    WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_file");
3538
3539
0
    ret = ProcessFile(ctx, file, format, CERT_TYPE, NULL, 0, NULL,
3540
0
        GET_VERIFY_SETTING_CTX(ctx));
3541
3542
    /* Return 1 on success or 0 on failure. */
3543
0
    return WS_RC(ret);
3544
0
}
3545
3546
3547
/* Load a private key into SSL context.
3548
 *
3549
 * @param [in, out] ctx     SSL context object.
3550
 * @param [in]      file    Name of private key file.
3551
 * @param [in]      format  Format of data:
3552
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
3553
 * @return  1 on success.
3554
 * @return  0 on failure.
3555
 */
3556
WOLFSSL_ABI
3557
int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX* ctx, const char* file,
3558
    int format)
3559
0
{
3560
0
    int ret;
3561
3562
0
    WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_file");
3563
3564
0
    ret = ProcessFile(ctx, file, format, PRIVATEKEY_TYPE, NULL, 0, NULL,
3565
0
        GET_VERIFY_SETTING_CTX(ctx));
3566
3567
    /* Return 1 on success or 0 on failure. */
3568
0
    return WS_RC(ret);
3569
0
}
3570
3571
#ifdef WOLFSSL_DUAL_ALG_CERTS
3572
/* Load an alternative private key into SSL context.
3573
 *
3574
 * @param [in, out] ctx     SSL context object.
3575
 * @param [in]      file    Name of private key file.
3576
 * @param [in]      format  Format of data:
3577
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
3578
 * @return  1 on success.
3579
 * @return  0 on failure.
3580
 */
3581
int wolfSSL_CTX_use_AltPrivateKey_file(WOLFSSL_CTX* ctx, const char* file,
3582
    int format)
3583
{
3584
    int ret;
3585
3586
    WOLFSSL_ENTER("wolfSSL_CTX_use_AltPrivateKey_file");
3587
3588
    ret = ProcessFile(ctx, file, format, ALT_PRIVATEKEY_TYPE, NULL, 0, NULL,
3589
        GET_VERIFY_SETTING_CTX(ctx));
3590
3591
    /* Return 1 on success or 0 on failure. */
3592
    return WS_RC(ret);
3593
}
3594
#endif /* WOLFSSL_DUAL_ALG_CERTS */
3595
3596
3597
/* Load a PEM certificate chain into SSL context.
3598
 *
3599
 * @param [in, out] ctx     SSL context object.
3600
 * @param [in]      file    Name of PEM certificate chain file.
3601
 * @return  1 on success.
3602
 * @return  0 on failure.
3603
 */
3604
WOLFSSL_ABI
3605
int wolfSSL_CTX_use_certificate_chain_file(WOLFSSL_CTX* ctx, const char* file)
3606
0
{
3607
0
    int ret;
3608
3609
    /* process up to MAX_CHAIN_DEPTH plus subject cert */
3610
0
    WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file");
3611
3612
0
#ifdef WOLFSSL_PEM_TO_DER
3613
0
    ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE, NULL, 1, NULL,
3614
0
        GET_VERIFY_SETTING_CTX(ctx));
3615
#else
3616
    ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_ASN1, CERT_TYPE, NULL, 1,
3617
        NULL, GET_VERIFY_SETTING_CTX(ctx));
3618
#endif
3619
3620
    /* Return 1 on success or 0 on failure. */
3621
0
    return WS_RC(ret);
3622
0
}
3623
3624
/* Load certificate chain into SSL context.
3625
 *
3626
 * Processes up to MAX_CHAIN_DEPTH plus subject cert.
3627
 *
3628
 * @param [in, out] ctx     SSL context object.
3629
 * @param [in]      file    Name of private key file.
3630
 * @param [in]      format  Format of data:
3631
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
3632
 * @return  1 on success.
3633
 * @return  0 on failure.
3634
 */
3635
int wolfSSL_CTX_use_certificate_chain_file_format(WOLFSSL_CTX* ctx,
3636
     const char* file, int format)
3637
0
{
3638
0
    int ret;
3639
3640
0
    WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file_format");
3641
3642
0
    ret = ProcessFile(ctx, file, format, CERT_TYPE, NULL, 1, NULL,
3643
0
        GET_VERIFY_SETTING_CTX(ctx));
3644
3645
    /* Return 1 on success or 0 on failure. */
3646
0
    return WS_RC(ret);
3647
0
}
3648
3649
#endif /* NO_FILESYSTEM */
3650
3651
#ifdef WOLFSSL_SYS_CA_CERTS
3652
3653
#ifdef USE_WINDOWS_API
3654
3655
/* Load CA certificate from Windows store.
3656
 *
3657
 * Assumes loaded is 0.
3658
 *
3659
 * @param [in, out] ctx     SSL context object.
3660
 * @param [out]     loaded  Whether CA certificates were loaded.
3661
 * @return  1 on success.
3662
 * @return  0 on failure.
3663
 */
3664
static int LoadSystemCaCertsWindows(WOLFSSL_CTX* ctx, byte* loaded)
3665
{
3666
    int ret = 1;
3667
    word32 i;
3668
    HANDLE handle = NULL;
3669
    PCCERT_CONTEXT certCtx = NULL;
3670
    LPCSTR storeNames[2] = {"ROOT", "CA"};
3671
    HCRYPTPROV_LEGACY hProv = (HCRYPTPROV_LEGACY)NULL;
3672
3673
    if ((ctx == NULL) || (loaded == NULL)) {
3674
        ret = 0;
3675
    }
3676
3677
    for (i = 0; (ret == 1) && (i < sizeof(storeNames)/sizeof(*storeNames));
3678
         ++i) {
3679
        handle = CertOpenSystemStoreA(hProv, storeNames[i]);
3680
        if (handle != NULL) {
3681
            while ((certCtx = CertEnumCertificatesInStore(handle, certCtx))
3682
                   != NULL) {
3683
                if (certCtx->dwCertEncodingType == X509_ASN_ENCODING) {
3684
                    if (ProcessBuffer(ctx, certCtx->pbCertEncoded,
3685
                          certCtx->cbCertEncoded, WOLFSSL_FILETYPE_ASN1,
3686
                          CA_TYPE, NULL, NULL, 0,
3687
                          GET_VERIFY_SETTING_CTX(ctx),
3688
                          storeNames[i]) == 1) {
3689
                        /*
3690
                         * Set "loaded" as long as we've loaded one CA
3691
                         * cert.
3692
                         */
3693
                        *loaded = 1;
3694
                    }
3695
                }
3696
            }
3697
        }
3698
        else {
3699
            WOLFSSL_MSG_EX("Failed to open cert store %s.", storeNames[i]);
3700
        }
3701
3702
        if (handle != NULL && !CertCloseStore(handle, 0)) {
3703
            WOLFSSL_MSG_EX("Failed to close cert store %s.", storeNames[i]);
3704
            ret = 0;
3705
        }
3706
    }
3707
3708
    return ret;
3709
}
3710
3711
#elif defined(__APPLE__)
3712
3713
#if defined(HAVE_SECURITY_SECTRUSTSETTINGS_H) \
3714
  && !defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION)
3715
/* Manually obtains certificates from the system trust store and loads them
3716
 * directly into wolfSSL "the old way".
3717
 *
3718
 * As of MacOS 14.0 we are still able to use this method to access system
3719
 * certificates. Accessibility of this API is indicated by the presence of the
3720
 * Security/SecTrustSettings.h header. In the likely event that Apple removes
3721
 * access to this API on Macs, this function should be removed and the
3722
 * DoAppleNativeCertValidation() routine should be used for all devices.
3723
 *
3724
 * Assumes loaded is 0.
3725
 *
3726
 * @param [in, out] ctx     SSL context object.
3727
 * @param [out]     loaded  Whether CA certificates were loaded.
3728
 * @return  1 on success.
3729
 * @return  0 on failure.
3730
 */
3731
static int LoadSystemCaCertsMac(WOLFSSL_CTX* ctx, byte* loaded)
3732
{
3733
    int ret = 1;
3734
    word32 i;
3735
    const unsigned int trustDomains[] = {
3736
        kSecTrustSettingsDomainUser,
3737
        kSecTrustSettingsDomainAdmin,
3738
        kSecTrustSettingsDomainSystem
3739
    };
3740
    CFArrayRef certs;
3741
    OSStatus stat;
3742
    CFIndex numCerts;
3743
    CFDataRef der;
3744
    CFIndex j;
3745
3746
    if ((ctx == NULL) || (loaded == NULL)) {
3747
        ret = 0;
3748
    }
3749
3750
    for (i = 0; (ret == 1) && (i < sizeof(trustDomains)/sizeof(*trustDomains));
3751
         ++i) {
3752
        stat = SecTrustSettingsCopyCertificates(
3753
            (SecTrustSettingsDomain)trustDomains[i], &certs);
3754
        if (stat == errSecSuccess) {
3755
            numCerts = CFArrayGetCount(certs);
3756
            for (j = 0; j < numCerts; ++j) {
3757
                der = SecCertificateCopyData((SecCertificateRef)
3758
                          CFArrayGetValueAtIndex(certs, j));
3759
                if (der != NULL) {
3760
                    if (ProcessBuffer(ctx, CFDataGetBytePtr(der),
3761
                          CFDataGetLength(der), WOLFSSL_FILETYPE_ASN1,
3762
                          CA_TYPE, NULL, NULL, 0,
3763
                          GET_VERIFY_SETTING_CTX(ctx),
3764
                          "MacOSX trustDomains") == 1) {
3765
                        /*
3766
                         * Set "loaded" as long as we've loaded one CA
3767
                         * cert.
3768
                         */
3769
                        *loaded = 1;
3770
                    }
3771
3772
                    CFRelease(der);
3773
                }
3774
            }
3775
3776
            CFRelease(certs);
3777
        }
3778
        else if (stat == errSecNoTrustSettings) {
3779
            WOLFSSL_MSG_EX("No trust settings for domain %d, moving to next "
3780
                "domain.", trustDomains[i]);
3781
        }
3782
        else {
3783
            WOLFSSL_MSG_EX("SecTrustSettingsCopyCertificates failed with"
3784
                " status %d.", stat);
3785
            ret = 0;
3786
            break;
3787
        }
3788
    }
3789
3790
    return ret;
3791
}
3792
#endif /* defined(HAVE_SECURITY_SECTRUSTSETTINGS_H) */
3793
3794
#elif !defined(NO_FILESYSTEM)
3795
3796
/* Potential system CA certs directories on Linux/Unix distros. */
3797
static const char* systemCaDirs[] = {
3798
#if defined(__ANDROID__) || defined(ANDROID)
3799
    "/system/etc/security/cacerts"      /* Android */
3800
#else
3801
    "/etc/ssl/certs",                   /* Debian, Ubuntu, Gentoo, others */
3802
    "/etc/pki/ca-trust/source/anchors", /* Fedora, RHEL */
3803
    "/etc/pki/tls/certs"                /* Older RHEL */
3804
#endif
3805
};
3806
3807
/* Get CA directory list.
3808
 *
3809
 * @param [out] num  Number of CA directories.
3810
 * @return  CA directory list.
3811
 * @return  NULL when num is NULL.
3812
 */
3813
const char** wolfSSL_get_system_CA_dirs(word32* num)
3814
0
{
3815
0
    const char** ret;
3816
3817
    /* Validate parameters. */
3818
0
    if (num == NULL) {
3819
0
        ret = NULL;
3820
0
    }
3821
0
    else {
3822
0
        ret = systemCaDirs;
3823
0
        *num = sizeof(systemCaDirs)/sizeof(*systemCaDirs);
3824
0
    }
3825
3826
0
    return ret;
3827
0
}
3828
3829
/* Load CA certificate from default system directories.
3830
 *
3831
 * Assumes loaded is 0.
3832
 *
3833
 * @param [in, out] ctx     SSL context object.
3834
 * @param [out]     loaded  Whether CA certificates were loaded.
3835
 * @return  1 on success.
3836
 * @return  0 on failure.
3837
 */
3838
0
static int LoadSystemCaCertsNix(WOLFSSL_CTX* ctx, byte* loaded) {
3839
0
    int ret = 1;
3840
0
    word32 i;
3841
3842
0
    if ((ctx == NULL) || (loaded == NULL)) {
3843
0
        ret = 0;
3844
0
    }
3845
3846
0
    for (i = 0; (ret == 1) && (i < sizeof(systemCaDirs)/sizeof(*systemCaDirs));
3847
0
         ++i) {
3848
0
        WOLFSSL_MSG_EX("Attempting to load system CA certs from %s.",
3849
0
            systemCaDirs[i]);
3850
        /*
3851
         * We want to keep trying to load more CA certs even if one cert in
3852
         * the directory is bad and can't be used (e.g. if one is expired),
3853
         * so we use WOLFSSL_LOAD_FLAG_IGNORE_ERR.
3854
         */
3855
0
        if (wolfSSL_CTX_load_verify_locations_ex(ctx, NULL, systemCaDirs[i],
3856
0
                WOLFSSL_LOAD_FLAG_IGNORE_ERR) != 1) {
3857
0
            WOLFSSL_MSG_EX("Failed to load CA certs from %s, trying "
3858
0
                "next possible location.", systemCaDirs[i]);
3859
0
        }
3860
0
        else {
3861
0
            WOLFSSL_MSG_EX("Loaded CA certs from %s.",
3862
0
                systemCaDirs[i]);
3863
0
            *loaded = 1;
3864
            /* Stop searching after we've loaded one directory. */
3865
0
            break;
3866
0
        }
3867
0
    }
3868
3869
0
    return ret;
3870
0
}
3871
3872
#endif
3873
3874
/* Load CA certificates from system defined locations.
3875
 *
3876
 * @param [in, out] ctx  SSL context object.
3877
 * @return  1 on success.
3878
 * @return  0 on failure.
3879
 * @return  WOLFSSL_BAD_PATH when no error but no certificates loaded.
3880
 */
3881
int wolfSSL_CTX_load_system_CA_certs(WOLFSSL_CTX* ctx)
3882
0
{
3883
0
    int ret;
3884
0
    byte loaded = 0;
3885
3886
0
    WOLFSSL_ENTER("wolfSSL_CTX_load_system_CA_certs");
3887
3888
#ifdef USE_WINDOWS_API
3889
3890
    ret = LoadSystemCaCertsWindows(ctx, &loaded);
3891
3892
#elif defined(__APPLE__)
3893
3894
#if defined(HAVE_SECURITY_SECTRUSTSETTINGS_H) \
3895
  && !defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION)
3896
    /* As of MacOS 14.0 we are still able to access system certificates and
3897
     * load them manually into wolfSSL "the old way". Accessibility of this API
3898
     * is indicated by the presence of the Security/SecTrustSettings.h header */
3899
    ret = LoadSystemCaCertsMac(ctx, &loaded);
3900
#elif defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION)
3901
    /* For other Apple devices, Apple has removed the ability to obtain
3902
     * certificates from the trust store, so we can't use wolfSSL's built-in
3903
     * certificate validation mechanisms anymore. We instead must call into the
3904
     * Security Framework APIs to authenticate peer certificates when received.
3905
     * (see src/internal.c:DoAppleNativeCertValidation()).
3906
     * Thus, there is no CA "loading" required, but to keep behavior consistent
3907
     * with the current API (not using system CA certs unless this function has
3908
     * been called), we simply set a flag indicating that the new apple trust
3909
     * verification routine should be used later */
3910
    ctx->doAppleNativeCertValidationFlag = 1;
3911
    ret = 1;
3912
    loaded = 1;
3913
3914
#if FIPS_VERSION_GE(2,0) /* Gate back to cert 3389 FIPS modules */
3915
#warning "Cryptographic operations may occur outside the FIPS module boundary" \
3916
         "Please review FIPS claims for cryptography on this Apple device"
3917
#endif /* FIPS_VERSION_GE(2,0) */
3918
3919
#else
3920
/* HAVE_SECURITY_SECXXX_H macros are set by autotools or CMake when searching
3921
 * system for the required SDK headers. If building with user_settings.h, you
3922
 * will need to manually define WOLFSSL_APPLE_NATIVE_CERT_VALIDATION
3923
 * and ensure the appropriate Security.framework headers and libraries are
3924
 * visible to your compiler */
3925
#error "WOLFSSL_SYS_CA_CERTS on Apple devices requires Security.framework" \
3926
       " header files to be detected, or a manual override with" \
3927
       " WOLFSSL_APPLE_NATIVE_CERT_VALIDATION"
3928
#endif
3929
3930
#else
3931
3932
0
    ret = LoadSystemCaCertsNix(ctx, &loaded);
3933
3934
0
#endif
3935
3936
    /* If we didn't fail but didn't load then we error out. */
3937
0
    if ((ret == 1) && (!loaded)) {
3938
0
        ret = WOLFSSL_BAD_PATH;
3939
0
    }
3940
3941
0
    WOLFSSL_LEAVE("wolfSSL_CTX_load_system_CA_certs", ret);
3942
3943
0
    return ret;
3944
0
}
3945
3946
#endif /* WOLFSSL_SYS_CA_CERTS */
3947
3948
#ifdef OPENSSL_EXTRA
3949
3950
/* Load a private key into SSL.
3951
 *
3952
 * @param [in, out] ssl   SSL object.
3953
 * @param [in]      pkey  EVP private key.
3954
 * @return  1 on success.
3955
 * @return  0 on failure.
3956
 */
3957
int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey)
3958
{
3959
    int ret;
3960
3961
    WOLFSSL_ENTER("wolfSSL_use_PrivateKey");
3962
3963
    /* Validate parameters. */
3964
    if ((ssl == NULL) || (pkey == NULL)) {
3965
        ret = 0;
3966
    }
3967
    else {
3968
        /* Get DER encoded key data from EVP private key. */
3969
        ret = wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char*)pkey->pkey.ptr,
3970
            pkey->pkey_sz, WOLFSSL_FILETYPE_ASN1);
3971
    }
3972
3973
    return ret;
3974
}
3975
3976
/* Load a DER encoded private key in a buffer into SSL.
3977
 *
3978
 * @param [in]      pri    Indicates type of private key. Ignored.
3979
 * @param [in, out] ssl    SSL object.
3980
 * @param [in]      der    Buffer holding DER encoded private key.
3981
 * @param [in]      derSz  Size of data in bytes.
3982
 * @return  1 on success.
3983
 * @return  0 on failure.
3984
 */
3985
int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl, const unsigned char* der,
3986
    long derSz)
3987
{
3988
    int ret;
3989
3990
    WOLFSSL_ENTER("wolfSSL_use_PrivateKey_ASN1");
3991
3992
    (void)pri;
3993
3994
    /* Validate parameters. */
3995
    if ((ssl == NULL) || (der == NULL)) {
3996
        ret = 0;
3997
    }
3998
    else {
3999
        ret = wolfSSL_use_PrivateKey_buffer(ssl, der, derSz,
4000
            WOLFSSL_FILETYPE_ASN1);
4001
    }
4002
4003
    return ret;
4004
}
4005
4006
/* Load a DER encoded private key in a buffer into SSL context.
4007
 *
4008
 * @param [in]      pri    Indicates type of private key. Ignored.
4009
 * @param [in, out] ctx    SSL context object.
4010
 * @param [in]      der    Buffer holding DER encoded private key.
4011
 * @param [in]      derSz  Size of data in bytes.
4012
 * @return  1 on success.
4013
 * @return  0 on failure.
4014
 */
4015
int wolfSSL_CTX_use_PrivateKey_ASN1(int pri, WOLFSSL_CTX* ctx,
4016
    unsigned char* der, long derSz)
4017
{
4018
    int ret;
4019
4020
    WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_ASN1");
4021
4022
    (void)pri;
4023
4024
    /* Validate parameters. */
4025
    if ((ctx == NULL) || (der == NULL)) {
4026
        ret = 0;
4027
    }
4028
    else {
4029
        ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, derSz,
4030
            WOLFSSL_FILETYPE_ASN1);
4031
    }
4032
4033
    return ret;
4034
}
4035
4036
4037
#ifndef NO_RSA
4038
/* Load a DER encoded RSA private key in a buffer into SSL.
4039
 *
4040
 * @param [in, out] ssl    SSL object.
4041
 * @param [in]      der    Buffer holding DER encoded RSA private key.
4042
 * @param [in]      derSz  Size of data in bytes.
4043
 * @return  1 on success.
4044
 * @return  0 on failure.
4045
 */
4046
int wolfSSL_use_RSAPrivateKey_ASN1(WOLFSSL* ssl, unsigned char* der, long derSz)
4047
{
4048
    int ret;
4049
4050
    WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_ASN1");
4051
4052
    /* Validate parameters. */
4053
    if ((ssl == NULL) || (der == NULL)) {
4054
        ret = 0;
4055
    }
4056
    else {
4057
        ret = wolfSSL_use_PrivateKey_buffer(ssl, der, derSz,
4058
            WOLFSSL_FILETYPE_ASN1);
4059
    }
4060
4061
    return ret;
4062
}
4063
#endif
4064
4065
/* Load a certificate into SSL.
4066
 *
4067
 * @param [in, out] ssl   SSL object.
4068
 * @param [in]      x509  X509 certificate object.
4069
 * @return  1 on success.
4070
 * @return  0 on failure.
4071
 */
4072
int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509)
4073
{
4074
    int ret;
4075
4076
    WOLFSSL_ENTER("wolfSSL_use_certificate");
4077
4078
    /* Validate parameters. */
4079
    if ((ssl == NULL) || (x509 == NULL) || (x509->derCert == NULL)) {
4080
        ret = 0;
4081
    }
4082
    else {
4083
        long idx = 0;
4084
4085
        /* Get DER encoded certificate data from X509 object. */
4086
        ret = ProcessBuffer(NULL, x509->derCert->buffer, x509->derCert->length,
4087
            WOLFSSL_FILETYPE_ASN1, CERT_TYPE, ssl, &idx, 0,
4088
            GET_VERIFY_SETTING_SSL(ssl),
4089
            "x509 buffer");
4090
    }
4091
4092
    /* Return 1 on success or 0 on failure. */
4093
    return WS_RC(ret);
4094
}
4095
4096
#endif /* OPENSSL_EXTRA */
4097
4098
/* Load a DER encoded certificate in a buffer into SSL.
4099
 *
4100
 * @param [in, out] ssl    SSL object.
4101
 * @param [in]      der    Buffer holding DER encoded certificate.
4102
 * @param [in]      derSz  Size of data in bytes.
4103
 * @return  1 on success.
4104
 * @return  0 on failure.
4105
 */
4106
int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl, const unsigned char* der,
4107
    int derSz)
4108
0
{
4109
0
    int ret;
4110
4111
0
    WOLFSSL_ENTER("wolfSSL_use_certificate_ASN1");
4112
4113
    /* Validate parameters. */
4114
0
    if ((ssl == NULL) || (der == NULL)) {
4115
0
        ret = 0;
4116
0
    }
4117
0
    else {
4118
0
        long idx = 0;
4119
4120
0
        ret = ProcessBuffer(NULL, der, derSz, WOLFSSL_FILETYPE_ASN1, CERT_TYPE,
4121
0
            ssl, &idx, 0, GET_VERIFY_SETTING_SSL(ssl),
4122
0
            "asn1 buffer");
4123
0
    }
4124
4125
    /* Return 1 on success or 0 on failure. */
4126
0
    return WS_RC(ret);
4127
0
}
4128
4129
#ifndef NO_FILESYSTEM
4130
4131
/* Load a certificate from a file into SSL.
4132
 *
4133
 * @param [in, out] ssl     SSL object.
4134
 * @param [in]      file    Name of file.
4135
 * @param [in]      format  Format of data:
4136
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
4137
 * @return  1 on success.
4138
 * @return  0 on failure.
4139
 * @return  BAD_FUNC_ARG when ssl is NULL.
4140
 */
4141
WOLFSSL_ABI
4142
int wolfSSL_use_certificate_file(WOLFSSL* ssl, const char* file, int format)
4143
0
{
4144
0
    int ret;
4145
4146
0
    WOLFSSL_ENTER("wolfSSL_use_certificate_file");
4147
4148
    /* Validate parameters. */
4149
0
    if (ssl == NULL) {
4150
0
        ret = BAD_FUNC_ARG;
4151
0
    }
4152
0
    else {
4153
0
        ret = ProcessFile(ssl->ctx, file, format, CERT_TYPE, ssl, 0, NULL,
4154
0
            GET_VERIFY_SETTING_SSL(ssl));
4155
        /* Return 1 on success or 0 on failure. */
4156
0
        ret = WS_RC(ret);
4157
0
    }
4158
4159
0
    return ret;
4160
0
}
4161
4162
4163
/* Load a private key from a file into SSL.
4164
 *
4165
 * @param [in, out] ssl     SSL object.
4166
 * @param [in]      file    Name of file.
4167
 * @param [in]      format  Format of data:
4168
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
4169
 * @return  1 on success.
4170
 * @return  0 on failure.
4171
 * @return  BAD_FUNC_ARG when ssl is NULL.
4172
 */
4173
WOLFSSL_ABI
4174
int wolfSSL_use_PrivateKey_file(WOLFSSL* ssl, const char* file, int format)
4175
0
{
4176
0
    int ret;
4177
4178
0
    WOLFSSL_ENTER("wolfSSL_use_PrivateKey_file");
4179
4180
    /* Validate parameters. */
4181
0
    if (ssl == NULL) {
4182
0
        ret = BAD_FUNC_ARG;
4183
0
    }
4184
0
    else {
4185
0
        ret = ProcessFile(ssl->ctx, file, format, PRIVATEKEY_TYPE, ssl, 0, NULL,
4186
0
            GET_VERIFY_SETTING_SSL(ssl));
4187
        /* Return 1 on success or 0 on failure. */
4188
0
        ret = WS_RC(ret);
4189
0
    }
4190
4191
0
    return ret;
4192
0
}
4193
4194
4195
/* Load a PEM encoded certificate chain from a file into SSL.
4196
 *
4197
 * Process up to MAX_CHAIN_DEPTH plus subject cert.
4198
 *
4199
 * @param [in, out] ssl     SSL object.
4200
 * @param [in]      file    Name of file.
4201
 * @return  1 on success.
4202
 * @return  0 on failure.
4203
 * @return  BAD_FUNC_ARG when ssl is NULL.
4204
 */
4205
WOLFSSL_ABI
4206
int wolfSSL_use_certificate_chain_file(WOLFSSL* ssl, const char* file)
4207
0
{
4208
0
    int ret;
4209
4210
0
    WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file");
4211
4212
    /* Validate parameters. */
4213
0
    if (ssl == NULL) {
4214
0
        ret = BAD_FUNC_ARG;
4215
0
    }
4216
0
    else {
4217
0
#ifdef WOLFSSL_PEM_TO_DER
4218
0
        ret = ProcessFile(ssl->ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE, ssl,
4219
0
            1, NULL, GET_VERIFY_SETTING_SSL(ssl));
4220
#else
4221
        ret = ProcessFile(ssl->ctx, file, WOLFSSL_FILETYPE_ASN1, CERT_TYPE, ssl,
4222
            1, NULL, GET_VERIFY_SETTING_SSL(ssl));
4223
#endif
4224
        /* Return 1 on success or 0 on failure. */
4225
0
        ret = WS_RC(ret);
4226
0
    }
4227
4228
0
   return ret;
4229
0
}
4230
4231
/* Load a certificate chain from a file into SSL.
4232
 *
4233
 * @param [in, out] ssl     SSL object.
4234
 * @param [in]      file    Name of file.
4235
 * @param [in]      format  Format of data:
4236
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
4237
 * @return  1 on success.
4238
 * @return  0 on failure.
4239
 * @return  BAD_FUNC_ARG when ssl is NULL.
4240
 */
4241
int wolfSSL_use_certificate_chain_file_format(WOLFSSL* ssl, const char* file,
4242
    int format)
4243
0
{
4244
0
    int ret;
4245
4246
    /* process up to MAX_CHAIN_DEPTH plus subject cert */
4247
0
    WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file_format");
4248
4249
    /* Validate parameters. */
4250
0
    if (ssl == NULL) {
4251
0
        ret = BAD_FUNC_ARG;
4252
0
    }
4253
0
    else {
4254
0
        ret = ProcessFile(ssl->ctx, file, format, CERT_TYPE, ssl, 1, NULL,
4255
0
            GET_VERIFY_SETTING_SSL(ssl));
4256
        /* Return 1 on success or 0 on failure. */
4257
0
        ret = WS_RC(ret);
4258
0
    }
4259
4260
0
    return ret;
4261
0
}
4262
4263
#endif /* !NO_FILESYSTEM */
4264
4265
#ifdef OPENSSL_EXTRA
4266
4267
#ifndef NO_FILESYSTEM
4268
/* Load an RSA private key from a file into SSL context.
4269
 *
4270
 * @param [in, out] ctx     SSL context object.
4271
 * @param [in]      file    Name of file.
4272
 * @param [in]      format  Format of data:
4273
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
4274
 * @return  1 on success.
4275
 * @return  0 on failure.
4276
 */
4277
int wolfSSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX* ctx,const char* file,
4278
    int format)
4279
{
4280
    WOLFSSL_ENTER("wolfSSL_CTX_use_RSAPrivateKey_file");
4281
4282
    return wolfSSL_CTX_use_PrivateKey_file(ctx, file, format);
4283
}
4284
4285
/* Load an RSA private key from a file into SSL.
4286
 *
4287
 * @param [in, out] ssl     SSL object.
4288
 * @param [in]      file    Name of file.
4289
 * @param [in]      format  Format of data:
4290
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
4291
 * @return  1 on success.
4292
 * @return  0 on failure.
4293
 * @return  BAD_FUNC_ARG when ssl is NULL.
4294
 */
4295
int wolfSSL_use_RSAPrivateKey_file(WOLFSSL* ssl, const char* file, int format)
4296
{
4297
    WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_file");
4298
4299
    return wolfSSL_use_PrivateKey_file(ssl, file, format);
4300
}
4301
#endif /* NO_FILESYSTEM */
4302
4303
#endif /* OPENSSL_EXTRA */
4304
4305
#if defined(WOLFSSL_TRUST_PEER_CERT)
4306
/* Load a buffer of certificate/s as trusted peer certificates with the
4307
 * caller's verification setting.
4308
 *
4309
 * @param [in, out] ctx     SSL context object.
4310
 * @param [in]      in      Buffer holding certificate/s.
4311
 * @param [in]      sz      Length of data in buffer in bytes.
4312
 * @param [in]      format  Format of data: WOLFSSL_FILETYPE_PEM or
4313
 *                             WOLFSSL_FILETYPE_ASN1.
4314
 * @param [in]      verify  How to verify the certificate/s.
4315
 * @return  1 on success.
4316
 * @return  0 on failure.
4317
 * @return  BAD_FUNC_ARG when ctx or in is NULL, or sz is less than zero.
4318
 * @return  Negative on error.
4319
 */
4320
static int TrustPeerCertBuffer(WOLFSSL_CTX* ctx, const unsigned char* in,
4321
    long sz, int format, int verify)
4322
{
4323
    int ret;
4324
4325
    /* Validate parameters. */
4326
    if ((ctx == NULL) || (in == NULL) || (sz < 0)) {
4327
        ret = BAD_FUNC_ARG;
4328
    }
4329
    else {
4330
        /* When PEM, treat as certificate chain of trusted peer
4331
         * certificates. */
4332
        if (format == WOLFSSL_FILETYPE_PEM) {
4333
            ret = ProcessChainBuffer(ctx, NULL, in, sz, TRUSTED_PEER_TYPE,
4334
                verify, "peer");
4335
        }
4336
        /* When DER, load the trusted peer certificate. */
4337
        else {
4338
            ret = ProcessBuffer(ctx, in, sz, format, TRUSTED_PEER_TYPE, NULL,
4339
                NULL, 0, verify, "peer");
4340
        }
4341
    }
4342
4343
    return ret;
4344
}
4345
#endif /* WOLFSSL_TRUST_PEER_CERT */
4346
4347
/* Load a buffer of certificate/s into SSL context.
4348
 *
4349
 * @param [in, out] ctx        SSL context object.
4350
 * @param [in]      in         Buffer holding certificate or private key.
4351
 * @param [in]      sz         Length of data in buffer in bytes.
4352
 * @param [in]      format     Format of data:
4353
 *                               WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
4354
 * @param [in]      userChain  Whether file contains chain of certificates.
4355
 * @param [in]      flags      Flags representing options for loading.
4356
 * @return  1 on success.
4357
 * @return  0 on failure.
4358
 * @return  Negative on error.
4359
 */
4360
int wolfSSL_CTX_load_verify_buffer_ex(WOLFSSL_CTX* ctx, const unsigned char* in,
4361
    long sz, int format, int userChain, word32 flags)
4362
0
{
4363
0
    int ret;
4364
0
    int verify;
4365
4366
0
    WOLFSSL_ENTER("wolfSSL_CTX_load_verify_buffer_ex");
4367
4368
#ifdef WOLFSSL_TEST_APPLE_NATIVE_CERT_VALIDATION
4369
    /* TEST ONLY CODE: force native cert validation on */
4370
    if (ctx != NULL) {
4371
        WOLFSSL_MSG("ANCV Test: loading system CA certs");
4372
        wolfSSL_CTX_load_system_CA_certs(ctx);
4373
    }
4374
#endif
4375
4376
    /* Get setting on how to verify certificates. */
4377
0
    verify = GET_VERIFY_SETTING_CTX(ctx);
4378
    /* Overwrite setting when flag set. */
4379
0
    if (flags & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY) {
4380
0
        verify = VERIFY_SKIP_DATE;
4381
0
    }
4382
4383
    /* When PEM, treat as certificate chain of CA certificates. */
4384
0
    if (format == WOLFSSL_FILETYPE_PEM) {
4385
0
        ret = ProcessChainBuffer(ctx, NULL, in, sz, CA_TYPE, verify,
4386
0
                                 "PEM buffer");
4387
0
    }
4388
    /* When DER, load the CA certificate. */
4389
0
    else {
4390
0
        ret = ProcessBuffer(ctx, in, sz, format, CA_TYPE, NULL, NULL,
4391
0
            userChain, verify, "buffer");
4392
0
    }
4393
#if defined(WOLFSSL_TRUST_PEER_CERT) && defined(OPENSSL_COMPATIBLE_DEFAULTS)
4394
    if (ret == 1) {
4395
        /* Load certificate/s as trusted peer certificate. The verification
4396
         * setting computed above, including WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY,
4397
         * applies to the trusted peer copy too. */
4398
        ret = TrustPeerCertBuffer(ctx, in, sz, format, verify);
4399
    }
4400
#endif
4401
4402
0
    WOLFSSL_LEAVE("wolfSSL_CTX_load_verify_buffer_ex", ret);
4403
0
    return ret;
4404
0
}
4405
4406
/* Load a buffer of certificate/s into SSL context.
4407
 *
4408
 * @param [in, out] ctx     SSL context object.
4409
 * @param [in]      in      Buffer holding certificate or private key.
4410
 * @param [in]      sz      Length of data in buffer in bytes.
4411
 * @param [in]      format  Format of data:
4412
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
4413
 * @return  1 on success.
4414
 * @return  0 on failure.
4415
 * @return  Negative on error.
4416
 */
4417
int wolfSSL_CTX_load_verify_buffer(WOLFSSL_CTX* ctx, const unsigned char* in,
4418
    long sz, int format)
4419
0
{
4420
0
    return wolfSSL_CTX_load_verify_buffer_ex(ctx, in, sz, format, 0,
4421
0
        WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS);
4422
0
}
4423
4424
/* Load a buffer of certificate chain into SSL context.
4425
 *
4426
 * @param [in, out] ctx     SSL context object.
4427
 * @param [in]      in      Buffer holding certificate chain.
4428
 * @param [in]      sz      Length of data in buffer in bytes.
4429
 * @param [in]      format  Format of data:
4430
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
4431
 * @return  1 on success.
4432
 * @return  0 on failure.
4433
 * @return  Negative on error.
4434
 */
4435
int wolfSSL_CTX_load_verify_chain_buffer_format(WOLFSSL_CTX* ctx,
4436
    const unsigned char* in, long sz, int format)
4437
0
{
4438
0
    return wolfSSL_CTX_load_verify_buffer_ex(ctx, in, sz, format, 1,
4439
0
        WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS);
4440
0
}
4441
4442
4443
#ifdef WOLFSSL_TRUST_PEER_CERT
4444
/* Load a buffer of certificate/s into SSL context.
4445
 *
4446
 * @param [in, out] ctx     SSL context object.
4447
 * @param [in]      in      Buffer holding certificate/s.
4448
 * @param [in]      sz      Length of data in buffer in bytes.
4449
 * @param [in]      format  Format of data:
4450
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
4451
 * @return  1 on success.
4452
 * @return  0 on failure.
4453
 * @return  BAD_FUNC_ARG when ctx or in is NULL, or sz is less than zero.
4454
 */
4455
int wolfSSL_CTX_trust_peer_buffer(WOLFSSL_CTX* ctx, const unsigned char* in,
4456
    long sz, int format)
4457
{
4458
    int ret;
4459
    int verify;
4460
4461
    WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_buffer");
4462
4463
    /* Validate parameters. */
4464
    if ((ctx == NULL) || (in == NULL) || (sz < 0)) {
4465
        ret = BAD_FUNC_ARG;
4466
    }
4467
    else {
4468
    #if WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY
4469
        verify = VERIFY_SKIP_DATE;
4470
    #else
4471
        verify = GET_VERIFY_SETTING_CTX(ctx);
4472
    #endif
4473
4474
        ret = TrustPeerCertBuffer(ctx, in, sz, format, verify);
4475
    }
4476
4477
    return ret;
4478
}
4479
#endif /* WOLFSSL_TRUST_PEER_CERT */
4480
4481
/* Load a certificate in a buffer into SSL context.
4482
 *
4483
 * @param [in, out] ctx     SSL context object.
4484
 * @param [in]      in      Buffer holding certificate.
4485
 * @param [in]      sz      Size of data in bytes.
4486
 * @param [in]      format  Format of data:
4487
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
4488
 * @return  1 on success.
4489
 * @return  0 on failure.
4490
 * @return  Negative on error.
4491
 */
4492
int wolfSSL_CTX_use_certificate_buffer(WOLFSSL_CTX* ctx,
4493
    const unsigned char* in, long sz, int format)
4494
0
{
4495
0
    int ret;
4496
4497
0
    WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_buffer");
4498
0
    ret = ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 0,
4499
0
        GET_VERIFY_SETTING_CTX(ctx), "buffer");
4500
0
    WOLFSSL_LEAVE("wolfSSL_CTX_use_certificate_buffer", ret);
4501
4502
0
    return ret;
4503
0
}
4504
4505
/* Load a private key in a buffer into SSL context.
4506
 *
4507
 * @param [in, out] ctx     SSL context object.
4508
 * @param [in]      in      Buffer holding private key.
4509
 * @param [in]      sz      Size of data in bytes.
4510
 * @param [in]      format  Format of data:
4511
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
4512
 * @return  1 on success.
4513
 * @return  0 on failure.
4514
 * @return  Negative on error.
4515
 */
4516
int wolfSSL_CTX_use_PrivateKey_buffer(WOLFSSL_CTX* ctx, const unsigned char* in,
4517
    long sz, int format)
4518
0
{
4519
0
    int ret;
4520
0
    long consumed = 0;
4521
4522
0
    WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_buffer");
4523
4524
0
    ret = ProcessBuffer(ctx, in, sz, format, PRIVATEKEY_TYPE, NULL, &consumed,
4525
0
        0, GET_VERIFY_SETTING_CTX(ctx), "key buffer");
4526
#ifdef WOLFSSL_DUAL_ALG_CERTS
4527
    if ((ret == 1) && (consumed < sz)) {
4528
        /* When support for dual algorithm certificates is enabled, the
4529
         * buffer may contain both the primary and the alternative
4530
         * private key. Hence, we have to parse both of them.
4531
         */
4532
        ret = ProcessBuffer(ctx, in + consumed, sz - consumed, format,
4533
            ALT_PRIVATEKEY_TYPE, NULL, NULL, 0, GET_VERIFY_SETTING_CTX(ctx),
4534
            "key buffer");
4535
    }
4536
#endif
4537
4538
0
    (void)consumed;
4539
4540
0
    WOLFSSL_LEAVE("wolfSSL_CTX_use_PrivateKey_buffer", ret);
4541
0
    return ret;
4542
0
}
4543
4544
#ifdef WOLFSSL_DUAL_ALG_CERTS
4545
int wolfSSL_CTX_use_AltPrivateKey_buffer(WOLFSSL_CTX* ctx,
4546
    const unsigned char* in, long sz, int format)
4547
{
4548
    int ret;
4549
4550
    WOLFSSL_ENTER("wolfSSL_CTX_use_AltPrivateKey_buffer");
4551
    ret = ProcessBuffer(ctx, in, sz, format, ALT_PRIVATEKEY_TYPE, NULL,
4552
        NULL, 0, GET_VERIFY_SETTING_CTX(ctx), "alt key buffer");
4553
    WOLFSSL_LEAVE("wolfSSL_CTX_use_AltPrivateKey_buffer", ret);
4554
4555
    return ret;
4556
}
4557
#endif /* WOLFSSL_DUAL_ALG_CERTS */
4558
4559
#ifdef WOLF_PRIVATE_KEY_ID
4560
/* Load the id of a private key into SSL context.
4561
 *
4562
 * @param [in, out] ctx    SSL context object.
4563
 * @param [in]      id     Buffer holding id.
4564
 * @param [in]      sz     Size of data in bytes.
4565
 * @param [in]      devId  Device identifier.
4566
 * @return  1 on success.
4567
 * @return  0 on failure.
4568
 */
4569
int wolfSSL_CTX_use_PrivateKey_Id(WOLFSSL_CTX* ctx, const unsigned char* id,
4570
    long sz, int devId)
4571
{
4572
    int ret = 1;
4573
4574
    WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_Id");
4575
4576
    if (ctx == NULL || id == NULL || sz < 0) {
4577
        return 0;
4578
    }
4579
4580
    /* Dispose of old private key and allocate and copy in id. */
4581
    FreeKeyDer(&ctx->privateKey);
4582
    if (AllocCopyDer(&ctx->privateKey, id, (word32)sz, PRIVATEKEY_TYPE,
4583
            ctx->heap) != 0) {
4584
        ret = 0;
4585
    }
4586
    if (ret == 1) {
4587
        /* Private key is an id. */
4588
        ctx->privateKeyId = 1;
4589
        ctx->privateKeyLabel = 0;
4590
        /* Set private key device id to be one passed in or for SSL context. */
4591
        if (devId != INVALID_DEVID) {
4592
            ctx->privateKeyDevId = devId;
4593
        }
4594
        else {
4595
            ctx->privateKeyDevId = ctx->devId;
4596
        }
4597
4598
    #ifdef WOLFSSL_DUAL_ALG_CERTS
4599
        /* Set the ID for the alternative key, too. User can still override that
4600
         * afterwards. */
4601
        ret = wolfSSL_CTX_use_AltPrivateKey_Id(ctx, id, sz, devId);
4602
    #endif
4603
    }
4604
4605
    WOLFSSL_LEAVE("wolfSSL_CTX_use_PrivateKey_Id", ret);
4606
    return ret;
4607
}
4608
4609
/* Load the id of a private key into SSL context and set key size.
4610
 *
4611
 * @param [in, out] ctx    SSL context object.
4612
 * @param [in]      id     Buffer holding id.
4613
 * @param [in]      sz     Size of data in bytes.
4614
 * @param [in]      devId  Device identifier.
4615
 * @param [in]      keySz  Size of key.
4616
 * @return  1 on success.
4617
 * @return  0 on failure.
4618
 */
4619
int wolfSSL_CTX_use_PrivateKey_Id_ex(WOLFSSL_CTX* ctx, const unsigned char* id,
4620
    long sz, int devId, long keySz)
4621
{
4622
    int ret;
4623
4624
    WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_Id_ex");
4625
4626
    ret = wolfSSL_CTX_use_PrivateKey_Id(ctx, id, sz, devId);
4627
    if (ret == 1) {
4628
        /* Set the key size which normally is calculated during decoding. */
4629
        ctx->privateKeySz = (int)keySz;
4630
    }
4631
4632
    WOLFSSL_LEAVE("wolfSSL_CTX_use_PrivateKey_Id_ex", ret);
4633
    return ret;
4634
}
4635
4636
/* Load the label name of a private key into SSL context.
4637
 *
4638
 * @param [in, out] ctx    SSL context object.
4639
 * @param [in]      label  Buffer holding label.
4640
 * @param [in]      devId  Device identifier.
4641
 * @return  1 on success.
4642
 * @return  0 on failure.
4643
 */
4644
int wolfSSL_CTX_use_PrivateKey_Label(WOLFSSL_CTX* ctx, const char* label,
4645
    int devId)
4646
{
4647
    int ret = 1;
4648
    word32 sz;
4649
4650
    WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_Label");
4651
4652
    if (ctx == NULL || label == NULL) {
4653
        return 0;
4654
    }
4655
4656
    sz = (word32)XSTRLEN(label) + 1;
4657
4658
    /* Dispose of old private key and allocate and copy in label. */
4659
    FreeKeyDer(&ctx->privateKey);
4660
    if (AllocCopyDer(&ctx->privateKey, (const byte*)label, (word32)sz,
4661
            PRIVATEKEY_TYPE, ctx->heap) != 0) {
4662
        ret = 0;
4663
    }
4664
    if (ret == 1) {
4665
        /* Private key is a label. */
4666
        ctx->privateKeyId = 0;
4667
        ctx->privateKeyLabel = 1;
4668
        /* Set private key device id to be one passed in or for SSL context. */
4669
        if (devId != INVALID_DEVID) {
4670
            ctx->privateKeyDevId = devId;
4671
        }
4672
        else {
4673
            ctx->privateKeyDevId = ctx->devId;
4674
        }
4675
4676
    #ifdef WOLFSSL_DUAL_ALG_CERTS
4677
        /* Set the ID for the alternative key, too. User can still override that
4678
         * afterwards. */
4679
        ret = wolfSSL_CTX_use_AltPrivateKey_Label(ctx, label, devId);
4680
    #endif
4681
    }
4682
4683
    WOLFSSL_LEAVE("wolfSSL_CTX_use_PrivateKey_Label", ret);
4684
    return ret;
4685
}
4686
4687
#ifdef WOLFSSL_DUAL_ALG_CERTS
4688
int wolfSSL_CTX_use_AltPrivateKey_Id(WOLFSSL_CTX* ctx, const unsigned char* id,
4689
    long sz, int devId)
4690
{
4691
    int ret = 1;
4692
4693
    WOLFSSL_ENTER("wolfSSL_CTX_use_AltPrivateKey_Id");
4694
4695
    if ((ctx == NULL) || (id == NULL) || (sz < 0)) {
4696
        ret = 0;
4697
    }
4698
4699
    if (ret == 1) {
4700
        FreeKeyDer(&ctx->altPrivateKey);
4701
        if (AllocDer(&ctx->altPrivateKey, (word32)sz, ALT_PRIVATEKEY_TYPE,
4702
                ctx->heap) != 0) {
4703
            ret = 0;
4704
        }
4705
    }
4706
    if (ret == 1) {
4707
        XMEMCPY(ctx->altPrivateKey->buffer, id, (word32)sz);
4708
        ctx->altPrivateKeyId = 1;
4709
        if (devId != INVALID_DEVID) {
4710
            ctx->altPrivateKeyDevId = devId;
4711
        }
4712
        else {
4713
            ctx->altPrivateKeyDevId = ctx->devId;
4714
        }
4715
    }
4716
4717
    WOLFSSL_LEAVE("wolfSSL_CTX_use_AltPrivateKey_Id", ret);
4718
    return ret;
4719
}
4720
4721
int wolfSSL_CTX_use_AltPrivateKey_Id_ex(WOLFSSL_CTX* ctx,
4722
    const unsigned char* id, long sz, int devId, long keySz)
4723
{
4724
    int ret;
4725
4726
    WOLFSSL_ENTER("wolfSSL_CTX_use_AltPrivateKey_Id_ex");
4727
4728
    ret = wolfSSL_CTX_use_AltPrivateKey_Id(ctx, id, sz, devId);
4729
    if (ret == 1) {
4730
        ctx->altPrivateKeySz = (word32)keySz;
4731
    }
4732
4733
    WOLFSSL_LEAVE("wolfSSL_CTX_use_AltPrivateKey_Id_ex", ret);
4734
    return ret;
4735
}
4736
4737
int wolfSSL_CTX_use_AltPrivateKey_Label(WOLFSSL_CTX* ctx, const char* label,
4738
    int devId)
4739
{
4740
    int ret = 1;
4741
    word32 sz;
4742
4743
    WOLFSSL_ENTER("wolfSSL_CTX_use_AltPrivateKey_Label");
4744
4745
    if ((ctx == NULL) || (label == NULL)) {
4746
        ret = 0;
4747
    }
4748
4749
    if (ret == 1) {
4750
        sz = (word32)XSTRLEN(label) + 1;
4751
        FreeKeyDer(&ctx->altPrivateKey);
4752
        if (AllocDer(&ctx->altPrivateKey, (word32)sz, ALT_PRIVATEKEY_TYPE,
4753
                ctx->heap) != 0) {
4754
            ret = 0;
4755
        }
4756
    }
4757
    if (ret == 1) {
4758
        XMEMCPY(ctx->altPrivateKey->buffer, label, sz);
4759
        ctx->altPrivateKeyLabel = 1;
4760
        if (devId != INVALID_DEVID) {
4761
            ctx->altPrivateKeyDevId = devId;
4762
        }
4763
        else {
4764
            ctx->altPrivateKeyDevId = ctx->devId;
4765
        }
4766
    }
4767
4768
    WOLFSSL_LEAVE("wolfSSL_CTX_use_AltPrivateKey_Label", ret);
4769
    return ret;
4770
}
4771
#endif /* WOLFSSL_DUAL_ALG_CERTS */
4772
#endif /* WOLF_PRIVATE_KEY_ID */
4773
4774
#if defined(WOLF_CRYPTO_CB) && !defined(NO_CERTS)
4775
4776
static int wolfSSL_CTX_use_certificate_ex(WOLFSSL_CTX* ctx,
4777
    const char *label, const unsigned char *id, int idLen, int devId)
4778
{
4779
    int ret;
4780
    byte *certData = NULL;
4781
    word32 certDataLen = 0;
4782
    word32 labelLen = 0;
4783
    int certFormat = 0;
4784
4785
    WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_ex");
4786
4787
    if (label != NULL) {
4788
        labelLen = (word32)XSTRLEN(label);
4789
    }
4790
4791
    ret = wc_CryptoCb_GetCert(devId, label, labelLen, id, idLen,
4792
        &certData, &certDataLen, &certFormat, ctx->heap);
4793
    if (ret != 0) {
4794
        ret = WOLFSSL_FAILURE;
4795
        goto exit;
4796
    }
4797
4798
    ret = ProcessBuffer(ctx, certData, certDataLen, certFormat,
4799
        CERT_TYPE, NULL, NULL, 0, GET_VERIFY_SETTING_CTX(ctx),
4800
        label ? label : "cert buffer");
4801
4802
exit:
4803
    XFREE(certData, ctx->heap, DYNAMIC_TYPE_CERT);
4804
    return ret;
4805
}
4806
4807
/* Load the label name of a certificate into the SSL context.
4808
 *
4809
 * @param [in, out] ctx    SSL context object.
4810
 * @param [in]      label  Buffer holding label.
4811
 * @param [in]      devId  Device identifier.
4812
 * @return  1 on success.
4813
 * @return  0 on failure.
4814
 */
4815
int wolfSSL_CTX_use_certificate_label(WOLFSSL_CTX* ctx,
4816
    const char *label, int devId)
4817
{
4818
    if ((ctx == NULL) || (label == NULL)) {
4819
        return WOLFSSL_FAILURE;
4820
    }
4821
4822
    return wolfSSL_CTX_use_certificate_ex(ctx, label, NULL, 0, devId);
4823
}
4824
4825
/* Load the id of a certificate into SSL context.
4826
 *
4827
 * @param [in, out] ctx    SSL context object.
4828
 * @param [in]      id     Buffer holding id.
4829
 * @param [in]      idLen  Size of data in bytes.
4830
 * @param [in]      devId  Device identifier.
4831
 * @return  1 on success.
4832
 * @return  0 on failure.
4833
 */
4834
int wolfSSL_CTX_use_certificate_id(WOLFSSL_CTX* ctx,
4835
    const unsigned char *id, int idLen, int devId)
4836
{
4837
    if ((ctx == NULL) || (id == NULL) || (idLen <= 0)) {
4838
        return WOLFSSL_FAILURE;
4839
    }
4840
4841
    return wolfSSL_CTX_use_certificate_ex(ctx, NULL, id, idLen, devId);
4842
}
4843
4844
#endif /* if defined(WOLF_CRYPTO_CB) && !defined(NO_CERTS) */
4845
4846
/* Load a certificate chain in a buffer into SSL context.
4847
 *
4848
 * @param [in, out] ctx     SSL context object.
4849
 * @param [in]      in      Buffer holding DER encoded certificate chain.
4850
 * @param [in]      sz      Size of data in bytes.
4851
 * @param [in]      format  Format of data:
4852
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
4853
 * @return  1 on success.
4854
 * @return  0 on failure.
4855
 * @return  Negative on error.
4856
 */
4857
int wolfSSL_CTX_use_certificate_chain_buffer_format(WOLFSSL_CTX* ctx,
4858
    const unsigned char* in, long sz, int format)
4859
0
{
4860
0
    WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_buffer_format");
4861
0
    return ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 1,
4862
0
        GET_VERIFY_SETTING_CTX(ctx), "cert chain buffer");
4863
0
}
4864
4865
/* Load a PEM encoded certificate chain in a buffer into SSL context.
4866
 *
4867
 * @param [in, out] ctx     SSL context object.
4868
 * @param [in]      in      Buffer holding DER encoded certificate chain.
4869
 * @param [in]      sz      Size of data in bytes.
4870
 * @return  1 on success.
4871
 * @return  0 on failure.
4872
 * @return  Negative on error.
4873
 */
4874
int wolfSSL_CTX_use_certificate_chain_buffer(WOLFSSL_CTX* ctx,
4875
    const unsigned char* in, long sz)
4876
0
{
4877
0
#ifdef WOLFSSL_PEM_TO_DER
4878
0
    return wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, in, sz,
4879
0
        WOLFSSL_FILETYPE_PEM);
4880
#else
4881
    return wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, in, sz,
4882
        WOLFSSL_FILETYPE_ASN1);
4883
#endif
4884
0
}
4885
4886
/* Load a user certificate in a buffer into SSL.
4887
 *
4888
 * @param [in, out] ssl     SSL object.
4889
 * @param [in]      in      Buffer holding user certificate.
4890
 * @param [in]      sz      Size of data in bytes.
4891
 * @param [in]      format  Format of data:
4892
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
4893
 * @return  1 on success.
4894
 * @return  0 on failure.
4895
 * @return  BAD_FUNC_ARG when ssl is NULL.
4896
 */
4897
int wolfSSL_use_certificate_buffer(WOLFSSL* ssl, const unsigned char* in,
4898
    long sz, int format)
4899
0
{
4900
0
    int ret;
4901
4902
0
    WOLFSSL_ENTER("wolfSSL_use_certificate_buffer");
4903
4904
    /* Validate parameters. */
4905
0
    if (ssl == NULL) {
4906
0
        ret = BAD_FUNC_ARG;
4907
0
    }
4908
0
    else {
4909
0
        ret = ProcessBuffer(ssl->ctx, in, sz, format, CERT_TYPE, ssl, NULL, 0,
4910
0
            GET_VERIFY_SETTING_SSL(ssl), "cert buffer");
4911
0
    }
4912
4913
0
    return ret;
4914
0
}
4915
4916
/* Load a private key in a buffer into SSL.
4917
 *
4918
 * @param [in, out] ssl     SSL object.
4919
 * @param [in]      in      Buffer holding private key.
4920
 * @param [in]      sz      Size of data in bytes.
4921
 * @param [in]      format  Format of data:
4922
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
4923
 * @return  1 on success.
4924
 * @return  0 on failure.
4925
 * @return  BAD_FUNC_ARG when ssl is NULL.
4926
 */
4927
int wolfSSL_use_PrivateKey_buffer(WOLFSSL* ssl, const unsigned char* in,
4928
    long sz, int format)
4929
0
{
4930
0
    int ret;
4931
0
    long consumed = 0;
4932
4933
0
    WOLFSSL_ENTER("wolfSSL_use_PrivateKey_buffer");
4934
4935
    /* Validate parameters. */
4936
0
    if (ssl == NULL) {
4937
0
        ret = BAD_FUNC_ARG;
4938
0
    }
4939
0
    else {
4940
0
        ret = ProcessBuffer(ssl->ctx, in, sz, format, PRIVATEKEY_TYPE, ssl,
4941
0
            &consumed, 0, GET_VERIFY_SETTING_SSL(ssl), "key buffer");
4942
    #ifdef WOLFSSL_DUAL_ALG_CERTS
4943
        if ((ret == 1) && (consumed < sz)) {
4944
            /* When support for dual algorithm certificates is enabled, the
4945
             * buffer may contain both the primary and the alternative
4946
             * private key. Hence, we have to parse both of them.
4947
             */
4948
            ret = ProcessBuffer(ssl->ctx, in + consumed, sz - consumed, format,
4949
                ALT_PRIVATEKEY_TYPE, ssl, NULL, 0, GET_VERIFY_SETTING_SSL(ssl),
4950
                "key buffer");
4951
        }
4952
    #endif
4953
0
    }
4954
4955
0
    return ret;
4956
0
}
4957
4958
#ifdef WOLFSSL_DUAL_ALG_CERTS
4959
int wolfSSL_use_AltPrivateKey_buffer(WOLFSSL* ssl, const unsigned char* in,
4960
    long sz, int format)
4961
{
4962
    int ret;
4963
4964
    WOLFSSL_ENTER("wolfSSL_use_AltPrivateKey_buffer");
4965
    ret = ProcessBuffer(ssl->ctx, in, sz, format, ALT_PRIVATEKEY_TYPE, ssl,
4966
        NULL, 0, GET_VERIFY_SETTING_SSL(ssl), "alt key buffer");
4967
    WOLFSSL_LEAVE("wolfSSL_use_AltPrivateKey_buffer", ret);
4968
4969
    return ret;
4970
}
4971
#endif /* WOLFSSL_DUAL_ALG_CERTS */
4972
4973
#ifdef WOLF_PRIVATE_KEY_ID
4974
/* Load the id of a private key into SSL.
4975
 *
4976
 * @param [in, out] ssl    SSL object.
4977
 * @param [in]      id     Buffer holding id.
4978
 * @param [in]      sz     Size of data in bytes.
4979
 * @param [in]      devId  Device identifier.
4980
 * @return  1 on success.
4981
 * @return  0 on failure.
4982
 */
4983
int wolfSSL_use_PrivateKey_Id(WOLFSSL* ssl, const unsigned char* id,
4984
                              long sz, int devId)
4985
{
4986
    int ret = 1;
4987
4988
    if (ssl == NULL || id == NULL || sz < 0) {
4989
        return 0;
4990
    }
4991
4992
    /* Dispose of old private key if owned and allocate and copy in id. */
4993
    if (ssl->buffers.weOwnKey) {
4994
        FreeKeyDer(&ssl->buffers.key);
4995
    #ifdef WOLFSSL_BLIND_PRIVATE_KEY
4996
        FreeDer(&ssl->buffers.keyMask);
4997
    #endif
4998
    }
4999
    if (AllocCopyDer(&ssl->buffers.key, id, (word32)sz, PRIVATEKEY_TYPE,
5000
            ssl->heap) != 0) {
5001
        ret = 0;
5002
    }
5003
    if (ret == 1) {
5004
        /* Buffer now ours. */
5005
        ssl->buffers.weOwnKey = 1;
5006
        /* Private key is an id. */
5007
        ssl->buffers.keyId = 1;
5008
        ssl->buffers.keyLabel = 0;
5009
        /* Set private key device id to be one passed in or for SSL. */
5010
        if (devId != INVALID_DEVID) {
5011
            ssl->buffers.keyDevId = devId;
5012
        }
5013
        else {
5014
            ssl->buffers.keyDevId = ssl->devId;
5015
        }
5016
5017
    #ifdef WOLFSSL_DUAL_ALG_CERTS
5018
        /* Set the ID for the alternative key, too. User can still override that
5019
         * afterwards. */
5020
        ret = wolfSSL_use_AltPrivateKey_Id(ssl, id, sz, devId);
5021
    #endif
5022
    }
5023
5024
    return ret;
5025
}
5026
5027
/* Load the id of a private key into SSL and set key size.
5028
 *
5029
 * @param [in, out] ssl    SSL object.
5030
 * @param [in]      id     Buffer holding id.
5031
 * @param [in]      sz     Size of data in bytes.
5032
 * @param [in]      devId  Device identifier.
5033
 * @param [in]      keySz  Size of key.
5034
 * @return  1 on success.
5035
 * @return  0 on failure.
5036
 */
5037
int wolfSSL_use_PrivateKey_Id_ex(WOLFSSL* ssl, const unsigned char* id,
5038
    long sz, int devId, long keySz)
5039
{
5040
    int ret = wolfSSL_use_PrivateKey_Id(ssl, id, sz, devId);
5041
    if (ret == 1) {
5042
        /* Set the key size which normally is calculated during decoding. */
5043
        ssl->buffers.keySz = (int)keySz;
5044
    }
5045
5046
    return ret;
5047
}
5048
5049
/* Load the label name of a private key into SSL.
5050
 *
5051
 * @param [in, out] ssl    SSL object.
5052
 * @param [in]      label  Buffer holding label.
5053
 * @param [in]      devId  Device identifier.
5054
 * @return  1 on success.
5055
 * @return  0 on failure.
5056
 */
5057
int wolfSSL_use_PrivateKey_Label(WOLFSSL* ssl, const char* label, int devId)
5058
{
5059
    int ret = 1;
5060
    word32 sz;
5061
5062
    if (ssl == NULL || label == NULL) {
5063
        return 0;
5064
    }
5065
5066
    sz = (word32)XSTRLEN(label) + 1;
5067
5068
    /* Dispose of old private key if owned and allocate and copy in label. */
5069
    if (ssl->buffers.weOwnKey) {
5070
        FreeKeyDer(&ssl->buffers.key);
5071
    #ifdef WOLFSSL_BLIND_PRIVATE_KEY
5072
        FreeDer(&ssl->buffers.keyMask);
5073
    #endif
5074
    }
5075
    if (AllocCopyDer(&ssl->buffers.key, (const byte*)label, (word32)sz,
5076
            PRIVATEKEY_TYPE, ssl->heap) != 0) {
5077
        ret = 0;
5078
    }
5079
    if (ret == 1) {
5080
        /* Buffer now ours. */
5081
        ssl->buffers.weOwnKey = 1;
5082
        /* Private key is a label. */
5083
        ssl->buffers.keyId = 0;
5084
        ssl->buffers.keyLabel = 1;
5085
        /* Set private key device id to be one passed in or for SSL. */
5086
        if (devId != INVALID_DEVID) {
5087
            ssl->buffers.keyDevId = devId;
5088
        }
5089
        else {
5090
            ssl->buffers.keyDevId = ssl->devId;
5091
        }
5092
5093
    #ifdef WOLFSSL_DUAL_ALG_CERTS
5094
        /* Set the label for the alternative key, too. User can still override
5095
         * that afterwards. */
5096
        ret = wolfSSL_use_AltPrivateKey_Label(ssl, label, devId);
5097
    #endif
5098
    }
5099
5100
    return ret;
5101
}
5102
5103
#ifdef WOLFSSL_DUAL_ALG_CERTS
5104
int wolfSSL_use_AltPrivateKey_Id(WOLFSSL* ssl, const unsigned char* id, long sz,
5105
    int devId)
5106
{
5107
    int ret = 1;
5108
5109
    if ((ssl == NULL) || (id == NULL) || (sz < 0)) {
5110
        ret = 0;
5111
    }
5112
5113
    if (ret == 1) {
5114
        if (ssl->buffers.weOwnAltKey) {
5115
            FreeKeyDer(&ssl->buffers.altKey);
5116
        #ifdef WOLFSSL_BLIND_PRIVATE_KEY
5117
            FreeDer(&ssl->buffers.altKeyMask);
5118
        #endif
5119
        }
5120
        if (AllocDer(&ssl->buffers.altKey, (word32)sz, ALT_PRIVATEKEY_TYPE,
5121
                ssl->heap) != 0) {
5122
            ret = 0;
5123
        }
5124
    }
5125
    if (ret == 1) {
5126
        XMEMCPY(ssl->buffers.altKey->buffer, id, (word32)sz);
5127
        ssl->buffers.weOwnAltKey = 1;
5128
        ssl->buffers.altKeyId = 1;
5129
        if (devId != INVALID_DEVID) {
5130
            ssl->buffers.altKeyDevId = devId;
5131
        }
5132
        else {
5133
            ssl->buffers.altKeyDevId = ssl->devId;
5134
        }
5135
    }
5136
5137
    return ret;
5138
}
5139
5140
int wolfSSL_use_AltPrivateKey_Id_ex(WOLFSSL* ssl, const unsigned char* id,
5141
    long sz, int devId, long keySz)
5142
{
5143
    int ret = wolfSSL_use_AltPrivateKey_Id(ssl, id, sz, devId);
5144
    if (ret == 1) {
5145
        ssl->buffers.altKeySz = (word32)keySz;
5146
    }
5147
5148
    return ret;
5149
}
5150
5151
int wolfSSL_use_AltPrivateKey_Label(WOLFSSL* ssl, const char* label, int devId)
5152
{
5153
    int ret = 1;
5154
    word32 sz;
5155
5156
    if ((ssl == NULL) || (label == NULL)) {
5157
        ret = 0;
5158
    }
5159
5160
    if (ret == 1) {
5161
        sz = (word32)XSTRLEN(label) + 1;
5162
        if (ssl->buffers.weOwnAltKey) {
5163
            FreeKeyDer(&ssl->buffers.altKey);
5164
        #ifdef WOLFSSL_BLIND_PRIVATE_KEY
5165
            FreeDer(&ssl->buffers.altKeyMask);
5166
        #endif
5167
        }
5168
        if (AllocDer(&ssl->buffers.altKey, (word32)sz, ALT_PRIVATEKEY_TYPE,
5169
                ssl->heap) != 0) {
5170
            ret = 0;
5171
        }
5172
    }
5173
    if (ret == 1) {
5174
        XMEMCPY(ssl->buffers.altKey->buffer, label, sz);
5175
        ssl->buffers.weOwnAltKey = 1;
5176
        ssl->buffers.altKeyLabel = 1;
5177
        if (devId != INVALID_DEVID) {
5178
            ssl->buffers.altKeyDevId = devId;
5179
        }
5180
        else {
5181
            ssl->buffers.altKeyDevId = ssl->devId;
5182
        }
5183
    }
5184
5185
    return ret;
5186
}
5187
#endif /* WOLFSSL_DUAL_ALG_CERTS */
5188
#endif /* WOLF_PRIVATE_KEY_ID */
5189
5190
/* Load a certificate chain in a buffer into SSL.
5191
 *
5192
 * @param [in, out] ssl     SSL object.
5193
 * @param [in]      in      Buffer holding DER encoded certificate chain.
5194
 * @param [in]      sz      Size of data in bytes.
5195
 * @param [in]      format  Format of data:
5196
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
5197
 * @return  1 on success.
5198
 * @return  0 on failure.
5199
 * @return  BAD_FUNC_ARG when ssl is NULL.
5200
 */
5201
int wolfSSL_use_certificate_chain_buffer_format(WOLFSSL* ssl,
5202
    const unsigned char* in, long sz, int format)
5203
0
{
5204
0
    int ret;
5205
5206
0
    WOLFSSL_ENTER("wolfSSL_use_certificate_chain_buffer_format");
5207
5208
    /* Validate parameters. */
5209
0
    if (ssl == NULL) {
5210
0
        ret = BAD_FUNC_ARG;
5211
0
    }
5212
0
    else {
5213
0
        ret = ProcessBuffer(ssl->ctx, in, sz, format, CERT_TYPE, ssl, NULL, 1,
5214
0
            GET_VERIFY_SETTING_SSL(ssl), "cert chain buffer");
5215
0
    }
5216
5217
0
    return ret;
5218
0
}
5219
5220
/* Load a PEM encoded certificate chain in a buffer into SSL.
5221
 *
5222
 * @param [in, out] ssl     SSL object.
5223
 * @param [in]      in      Buffer holding DER encoded certificate chain.
5224
 * @param [in]      sz      Size of data in bytes.
5225
 * @return  1 on success.
5226
 * @return  0 on failure.
5227
 * @return  Negative on error.
5228
 */
5229
int wolfSSL_use_certificate_chain_buffer(WOLFSSL* ssl, const unsigned char* in,
5230
    long sz)
5231
0
{
5232
0
#ifdef WOLFSSL_PEM_TO_DER
5233
0
    return wolfSSL_use_certificate_chain_buffer_format(ssl, in, sz,
5234
0
        WOLFSSL_FILETYPE_PEM);
5235
#else
5236
    return wolfSSL_use_certificate_chain_buffer_format(ssl, in, sz,
5237
        WOLFSSL_FILETYPE_ASN1);
5238
#endif
5239
0
}
5240
5241
#if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \
5242
    defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \
5243
    defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \
5244
    defined(WOLFSSL_HAPROXY)
5245
/* Add certificate to chain.
5246
 *
5247
 * @param [in, out] chain   Buffer holding encoded certificate for TLS.
5248
 * @param [in]      weOwn   Indicates we need to free chain if repleced.
5249
 * @param [in]      cert    Buffer holding DER encoded certificate.
5250
 * @param [in]      certSz  Size of DER encoded certificate in bytes.
5251
 * @param [in]      heap    Dynamic memory allocation hint.
5252
 * @return  1 on success.
5253
 * @return  0 on failure.
5254
 */
5255
static int wolfssl_add_to_chain(DerBuffer** chain, int weOwn, const byte* cert,
5256
    word32 certSz, void* heap)
5257
{
5258
    int res = 1;
5259
    int ret;
5260
    DerBuffer* oldChain = *chain;
5261
    DerBuffer* newChain = NULL;
5262
    word32 len = 0;
5263
5264
    if (oldChain != NULL) {
5265
        /* Get length of previous chain. */
5266
        len = oldChain->length;
5267
    }
5268
    /* Check for integer overflow in size calculation. */
5269
    if ((len > WOLFSSL_MAX_32BIT - CERT_HEADER_SZ) ||
5270
            (certSz > WOLFSSL_MAX_32BIT - CERT_HEADER_SZ - len)) {
5271
        WOLFSSL_MSG("wolfssl_add_to_chain overflow");
5272
        res = 0;
5273
    }
5274
    if (res == 1) {
5275
        /* Allocate DER buffer big enough to hold old and new certificates. */
5276
        ret = AllocDer(&newChain, len + CERT_HEADER_SZ + certSz, CERT_TYPE,
5277
            heap);
5278
        if (ret != 0) {
5279
            WOLFSSL_MSG("AllocDer error");
5280
            res = 0;
5281
        }
5282
    }
5283
5284
    if (res == 1) {
5285
        if (oldChain != NULL) {
5286
            /* Place old chain in new buffer. */
5287
            XMEMCPY(newChain->buffer, oldChain->buffer, len);
5288
        }
5289
        /* Append length and DER encoded certificate. */
5290
        c32to24(certSz, newChain->buffer + len);
5291
        XMEMCPY(newChain->buffer + len + CERT_HEADER_SZ, cert, certSz);
5292
5293
        /* Dispose of old chain if we own it. */
5294
        if (weOwn) {
5295
            FreeDer(chain);
5296
        }
5297
        /* Replace chain. */
5298
        *chain = newChain;
5299
    }
5300
5301
    return res;
5302
}
5303
#endif
5304
5305
#ifdef OPENSSL_EXTRA
5306
5307
/* Add a certificate to end of chain sent in TLS handshake.
5308
 *
5309
 * The certificate is only presented to the peer. It is deliberately kept out
5310
 * of the certificate manager so that it cannot be used to verify peers.
5311
 *
5312
 * @param [in, out] ctx    SSL context.
5313
 * @param [in]      der    Buffer holding DER encoded certificate.
5314
 * @param [in]      derSz  Size of data in buffer.
5315
 * @return  1 on success.
5316
 * @return  0 on failure.
5317
 */
5318
static int wolfssl_ctx_add_to_chain(WOLFSSL_CTX* ctx, const byte* der,
5319
    int derSz)
5320
{
5321
    int res;
5322
5323
    /* Add chain to DER buffer. */
5324
    res = wolfssl_add_to_chain(&ctx->certChain, 1, der, (word32)derSz,
5325
        ctx->heap);
5326
    if (res == 1) {
5327
        ctx->certChainCnt++;
5328
    }
5329
5330
    return res;
5331
}
5332
5333
/* Add a certificate to chain sent in TLS handshake.
5334
 *
5335
 * @param [in, out] ctx   SSL context.
5336
 * @param [in]      x509  X509 certificate object.
5337
 * @return  1 on success.
5338
 * @return  0 on failure.
5339
 */
5340
long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
5341
{
5342
    int   ret = 1;
5343
    int   derSz = 0;
5344
    const byte* der = NULL;
5345
5346
    WOLFSSL_ENTER("wolfSSL_CTX_add_extra_chain_cert");
5347
5348
    /* Validate parameters. */
5349
    if ((ctx == NULL) || (x509 == NULL)) {
5350
        WOLFSSL_MSG("Bad Argument");
5351
        ret = 0;
5352
    }
5353
5354
    if (ret == 1) {
5355
        /* Get the DER encoding of the certificate from the X509 object. */
5356
        der = wolfSSL_X509_get_der(x509, &derSz);
5357
        /* Validate buffer. */
5358
        if ((der == NULL) || (derSz <= 0)) {
5359
            WOLFSSL_MSG("Error getting X509 DER");
5360
            ret = 0;
5361
        }
5362
    }
5363
5364
    if ((ret == 1) && (ctx->certificate == NULL)) {
5365
        WOLFSSL_ENTER("wolfSSL_use_certificate_chain_buffer_format");
5366
5367
        /* Process buffer makes first certificate the leaf. */
5368
        ret = ProcessBuffer(ctx, der, derSz, WOLFSSL_FILETYPE_ASN1, CERT_TYPE,
5369
            NULL, NULL, 1, GET_VERIFY_SETTING_CTX(ctx), "extra chain buffer");
5370
        if (ret != 1) {
5371
            ret = 0;
5372
        }
5373
    }
5374
    else if (ret == 1) {
5375
        /* Add certificate to existing chain. */
5376
        ret = wolfssl_ctx_add_to_chain(ctx, der, derSz);
5377
    }
5378
5379
    if (ret == 1) {
5380
        /* On success WOLFSSL_X509 memory is responsibility of SSL context. */
5381
        wolfSSL_X509_free(x509);
5382
        x509 = NULL;
5383
    }
5384
5385
    WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret);
5386
    return ret;
5387
}
5388
5389
#endif /* OPENSSL_EXTRA */
5390
5391
#if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \
5392
    defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \
5393
    defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \
5394
    defined(WOLFSSL_HAPROXY)
5395
/* Load a certificate into SSL context.
5396
 *
5397
 * @param [in, out] ctx   SSL context object.
5398
 * @param [in]      x509  X509 certificate object.
5399
 * @return  1 on success.
5400
 * @return  0 on failure.
5401
 */
5402
int wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x)
5403
{
5404
    int res = 1;
5405
    int ret;
5406
5407
    WOLFSSL_ENTER("wolfSSL_CTX_use_certificate");
5408
5409
    /* Validate parameters. */
5410
    if ((ctx == NULL) || (x == NULL) || (x->derCert == NULL)) {
5411
        WOLFSSL_MSG("Bad parameter");
5412
        res = 0;
5413
    }
5414
5415
    if (res == 1) {
5416
        /* Replace certificate buffer with one holding the new certificate. */
5417
        FreeDer(&ctx->certificate);
5418
        /* The cached OCSP request was built from the old certificate. */
5419
        FreeCtxOcspRequestCache(ctx);
5420
        ret = AllocCopyDer(&ctx->certificate, x->derCert->buffer,
5421
            x->derCert->length, CERT_TYPE, ctx->heap);
5422
        if (ret != 0) {
5423
            res = 0;
5424
        }
5425
    }
5426
5427
#ifdef KEEP_OUR_CERT
5428
    if (res == 1) {
5429
        /* Dispose of our certificate if it is ours. */
5430
        if ((ctx->ourCert != NULL) && ctx->ownOurCert) {
5431
            wolfSSL_X509_free(ctx->ourCert);
5432
        }
5433
    #ifndef WOLFSSL_X509_STORE_CERTS
5434
        /* Keep a reference to the new certificate. */
5435
        ctx->ourCert = x;
5436
        if (wolfSSL_X509_up_ref(x) != 1) {
5437
            res = 0;
5438
        }
5439
    #else
5440
        /* Keep a copy of the new certificate. */
5441
        ctx->ourCert = wolfSSL_X509_d2i_ex(NULL, x->derCert->buffer,
5442
            x->derCert->length, ctx->heap);
5443
        if (ctx->ourCert == NULL) {
5444
            res = 0;
5445
        }
5446
    #endif
5447
        /* Now own our certificate. */
5448
        ctx->ownOurCert = 1;
5449
    }
5450
#endif
5451
5452
    if (res == 1) {
5453
        /* Set have options based on public key OID. */
5454
        wolfssl_set_have_from_key_oid(ctx, NULL, x->pubKeyOID);
5455
    }
5456
5457
    return res;
5458
}
5459
5460
/* Add the certificate to the chain in the SSL context and own the X509 object.
5461
 *
5462
 * @param [in, out] ctx   SSL context object.
5463
 * @param [in]      x509  X509 certificate object.
5464
 * @return  1 on success.
5465
 * @return  0 on failure.
5466
 */
5467
int wolfSSL_CTX_add0_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
5468
{
5469
    int ret;
5470
5471
    WOLFSSL_ENTER("wolfSSL_CTX_add0_chain_cert");
5472
5473
    /* Add certificate to chain and copy or up reference it. */
5474
    ret = wolfSSL_CTX_add1_chain_cert(ctx, x509);
5475
    if (ret == 1) {
5476
        /* Down reference or free original now as we own certificate. */
5477
        wolfSSL_X509_free(x509);
5478
        x509 = NULL;
5479
    }
5480
5481
    return ret;
5482
}
5483
5484
/* Add the certificate to the chain in the SSL context.
5485
 *
5486
 * X509 object copied or up referenced.
5487
 *
5488
 * @param [in, out] ctx   SSL context object.
5489
 * @param [in]      x509  X509 certificate object.
5490
 * @return  1 on success.
5491
 * @return  0 on failure.
5492
 */
5493
int wolfSSL_CTX_add1_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
5494
{
5495
    int ret = 1;
5496
5497
    WOLFSSL_ENTER("wolfSSL_CTX_add1_chain_cert");
5498
5499
    /* Validate parameters. */
5500
    if ((ctx == NULL) || (x509 == NULL) || (x509->derCert == NULL)) {
5501
        ret = 0;
5502
    }
5503
5504
    /* Check if we already have set a certificate. */
5505
    if ((ret == 1) && (ctx->certificate == NULL)) {
5506
        /* Use the certificate. */
5507
        ret = wolfSSL_CTX_use_certificate(ctx, x509);
5508
    }
5509
    /* Increase reference count as we will store it. */
5510
    else if ((ret == 1) && ((ret = wolfSSL_X509_up_ref(x509)) == 1)) {
5511
        /* Add DER encoding to chain. The certificate is presented to the
5512
         * peer only and must not become a CA to verify peers with. */
5513
        ret = wolfssl_add_to_chain(&ctx->certChain, 1,
5514
            x509->derCert->buffer, x509->derCert->length, ctx->heap);
5515
        if (ret == 1) {
5516
            ctx->certChainCnt++;
5517
        }
5518
        /* Store cert in stack to free it later. */
5519
        if ((ret == 1) && (ctx->x509Chain == NULL)) {
5520
            /* Create a stack for certificates. */
5521
            ctx->x509Chain = wolfSSL_sk_X509_new_null();
5522
            if (ctx->x509Chain == NULL) {
5523
                WOLFSSL_MSG("wolfSSL_sk_X509_new_null error");
5524
                ret = 0;
5525
            }
5526
        }
5527
        if (ret == 1) {
5528
            /* Push the X509 object onto stack. */
5529
            ret = wolfSSL_sk_X509_push(ctx->x509Chain, x509) > 0
5530
                    ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
5531
        }
5532
5533
        if (ret != 1) {
5534
            /* Decrease reference count on error as we didn't store it. */
5535
            wolfSSL_X509_free(x509);
5536
            x509 = NULL;
5537
        }
5538
    }
5539
5540
    return WS_RC(ret);
5541
}
5542
5543
#ifdef KEEP_OUR_CERT
5544
/* Add the certificate to the chain in the SSL and own the X509 object.
5545
 *
5546
 * @param [in, out] ssl   SSL object.
5547
 * @param [in]      x509  X509 certificate object.
5548
 * @return  1 on success.
5549
 * @return  0 on failure.
5550
 */
5551
int wolfSSL_add0_chain_cert(WOLFSSL* ssl, WOLFSSL_X509* x509)
5552
{
5553
    int ret = 1;
5554
5555
    WOLFSSL_ENTER("wolfSSL_add0_chain_cert");
5556
5557
    /* Validate parameters. */
5558
    if ((ssl == NULL) || (x509 == NULL) || (x509->derCert == NULL)) {
5559
        ret = 0;
5560
    }
5561
5562
    /* Check if we already have set a certificate. */
5563
    if ((ret == 1) && (ssl->buffers.certificate == NULL)) {
5564
        /* Use the certificate. */
5565
        ret = wolfSSL_use_certificate(ssl, x509);
5566
        if (ret == 1) {
5567
            /* Dispose of old certificate if we own it. */
5568
            if (ssl->buffers.weOwnCert) {
5569
                wolfSSL_X509_free(ssl->ourCert);
5570
            }
5571
            /* Store cert to free it later. */
5572
            ssl->ourCert = x509;
5573
            ssl->buffers.weOwnCert = 1;
5574
        }
5575
    }
5576
    else if (ret == 1) {
5577
        /* Add DER encoding to chain. */
5578
        ret = wolfssl_add_to_chain(&ssl->buffers.certChain,
5579
            ssl->buffers.weOwnCertChain, x509->derCert->buffer,
5580
            x509->derCert->length, ssl->heap);
5581
        if (ret == 1) {
5582
            /* We now own cert chain. */
5583
            ssl->buffers.weOwnCertChain = 1;
5584
            /* Account for the certificate just added to the chain. */
5585
            ssl->buffers.certChainCnt++;
5586
            /* Create a stack to put certificate into. */
5587
            if (ssl->ourCertChain == NULL) {
5588
                ssl->ourCertChain = wolfSSL_sk_X509_new_null();
5589
                if (ssl->ourCertChain == NULL) {
5590
                    WOLFSSL_MSG("wolfSSL_sk_X509_new_null error");
5591
                    ret = 0;
5592
                }
5593
            }
5594
        }
5595
        if (ret == 1) {
5596
            /* Push X509 object onto stack to be freed. */
5597
            ret = wolfSSL_sk_X509_push(ssl->ourCertChain, x509) > 0
5598
                    ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
5599
        }
5600
    }
5601
    return WS_RC(ret);
5602
}
5603
5604
/* Add the certificate to the chain in the SSL.
5605
 *
5606
 * X509 object is up referenced.
5607
 *
5608
 * @param [in, out] ssl   SSL object.
5609
 * @param [in]      x509  X509 certificate object.
5610
 * @return  1 on success.
5611
 * @return  0 on failure.
5612
 */
5613
int wolfSSL_add1_chain_cert(WOLFSSL* ssl, WOLFSSL_X509* x509)
5614
{
5615
    int ret = 1;
5616
5617
    WOLFSSL_ENTER("wolfSSL_add1_chain_cert");
5618
5619
    /* Validate parameters. */
5620
    if ((ssl == NULL) || (x509 == NULL) || (x509->derCert == NULL)) {
5621
        ret = 0;
5622
    }
5623
5624
    /* Increase reference count on X509 object before adding. */
5625
    if ((ret == 1) && ((ret = wolfSSL_X509_up_ref(x509)) == 1)) {
5626
        /* Add this to the chain. */
5627
        if ((ret = wolfSSL_add0_chain_cert(ssl, x509)) != 1) {
5628
            /* Decrease reference count on error as not stored. */
5629
            wolfSSL_X509_free(x509);
5630
            x509 = NULL;
5631
        }
5632
    }
5633
5634
    return ret;
5635
}
5636
5637
/* Clear all extra chain certificates set on the SSL object.
5638
 *
5639
 * Mirrors OpenSSL's SSL_clear_chain_certs(): drops the chain this SSL will
5640
 * send, whether it was added via SSL_add0_chain_cert / SSL_add1_chain_cert or
5641
 * inherited from the WOLFSSL_CTX. A chain still owned by the WOLFSSL_CTX is
5642
 * only detached, not freed, so the context is left usable. The leaf
5643
 * certificate and the private key are not affected.
5644
 *
5645
 * @param [in, out] ssl  SSL object.
5646
 * @return  1 on success.
5647
 * @return  0 when ssl is NULL.
5648
 */
5649
int wolfSSL_clear_chain_certs(WOLFSSL* ssl)
5650
{
5651
    WOLFSSL_ENTER("wolfSSL_clear_chain_certs");
5652
5653
    if (ssl == NULL)
5654
        return 0;
5655
5656
    /* Free the DER-encoded chain buffer if this SSL owns it. */
5657
    if (ssl->buffers.weOwnCertChain) {
5658
        FreeDer(&ssl->buffers.certChain);
5659
        ssl->buffers.weOwnCertChain = 0;
5660
    }
5661
    ssl->buffers.certChain = NULL;
5662
    ssl->buffers.certChainCnt = 0;
5663
5664
    /* Free the X509 stack used to track ownership of added chain certs. */
5665
    if (ssl->ourCertChain != NULL) {
5666
        wolfSSL_sk_X509_pop_free(ssl->ourCertChain, NULL);
5667
        ssl->ourCertChain = NULL;
5668
    }
5669
5670
    return 1;
5671
}
5672
#endif /* KEEP_OUR_CERT */
5673
#endif /* OPENSSL_EXTRA, HAVE_LIGHTY, WOLFSSL_MYSQL_COMPATIBLE, HAVE_STUNNEL,
5674
          WOLFSSL_NGINX, HAVE_POCO_LIB, WOLFSSL_HAPROXY */
5675
5676
#ifdef OPENSSL_EXTRA
5677
5678
/* Load a private key into SSL context.
5679
 *
5680
 * @param [in, out] ctx   SSL context object.
5681
 * @param [in]      pkey  EVP private key.
5682
 * @return  1 on success.
5683
 * @return  0 on failure.
5684
 */
5685
int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey)
5686
{
5687
    int ret = 1;
5688
5689
    WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey");
5690
5691
    /* Validate parameters. */
5692
    if ((ctx == NULL) || (pkey == NULL) || (pkey->pkey.ptr == NULL)) {
5693
        ret = 0;
5694
    }
5695
5696
    if (ret == 1) {
5697
        switch (pkey->type) {
5698
    #ifndef NO_RSA
5699
        case WC_EVP_PKEY_RSA:
5700
        #ifdef WOLFSSL_KEY_TO_DER
5701
            WOLFSSL_MSG("populating RSA key");
5702
            ret = PopulateRSAEvpPkeyDer(pkey);
5703
        #else
5704
            /* No RSA key encoder (FIPS or selftest without WOLFSSL_KEY_GEN):
5705
             * use the DER the key was decoded from, as
5706
             * wolfSSL_use_PrivateKey() does. */
5707
            WOLFSSL_MSG("using stored RSA key DER");
5708
        #endif
5709
            break;
5710
    #endif /* !NO_RSA */
5711
    #if !defined(HAVE_SELFTEST) && (defined(WOLFSSL_KEY_GEN) || \
5712
            defined(WOLFSSL_CERT_GEN)) && !defined(NO_DSA)
5713
        case WC_EVP_PKEY_DSA:
5714
            break;
5715
    #endif /* !HAVE_SELFTEST && (WOLFSSL_KEY_GEN || WOLFSSL_CERT_GEN) &&
5716
            * !NO_DSA */
5717
    #ifdef HAVE_ECC
5718
        case WC_EVP_PKEY_EC:
5719
            WOLFSSL_MSG("populating ECC key");
5720
            ret = ECC_populate_EVP_PKEY(pkey, pkey->ecc);
5721
            break;
5722
    #endif
5723
    #ifdef HAVE_ED25519
5724
        case WC_EVP_PKEY_ED25519:
5725
            /* DER is already stored in pkey->pkey.ptr by d2i_evp_pkey. */
5726
            WOLFSSL_MSG("populating Ed25519 key");
5727
            break;
5728
    #endif
5729
    #ifdef HAVE_ED448
5730
        case WC_EVP_PKEY_ED448:
5731
            /* DER is already stored in pkey->pkey.ptr by d2i_evp_pkey. */
5732
            WOLFSSL_MSG("populating Ed448 key");
5733
            break;
5734
    #endif
5735
        default:
5736
            ret = 0;
5737
        }
5738
    }
5739
5740
    if (ret == 1) {
5741
        /* ptr for WOLFSSL_EVP_PKEY struct is expected to be DER format */
5742
        ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx,
5743
            (const unsigned char*)pkey->pkey.ptr, pkey->pkey_sz,
5744
            WOLFSSL_FILETYPE_ASN1);
5745
    }
5746
5747
    return ret;
5748
}
5749
5750
#endif /* OPENSSL_EXTRA */
5751
5752
#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || \
5753
    defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT)
5754
/* Load a DER encoded certificate in a buffer into SSL context.
5755
 *
5756
 * @param [in, out] ctx    SSL context object.
5757
 * @param [in]      der    Buffer holding DER encoded certificate.
5758
 * @param [in]      derSz  Size of data in bytes.
5759
 * @return  1 on success.
5760
 * @return  0 on failure.
5761
 */
5762
int wolfSSL_CTX_use_certificate_ASN1(WOLFSSL_CTX *ctx, int derSz,
5763
    const unsigned char *der)
5764
{
5765
    int ret = 1;
5766
5767
    WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_ASN1");
5768
5769
    /* Validate parameters. */
5770
    if ((ctx == NULL) || (der == NULL)) {
5771
        ret = 0;
5772
    }
5773
    /* Load DER encoded certificate into SSL context. */
5774
    if ((ret == 1) && (wolfSSL_CTX_use_certificate_buffer(ctx, der, derSz,
5775
            WOLFSSL_FILETYPE_ASN1) != 1)) {
5776
        ret = 0;
5777
    }
5778
5779
    return ret;
5780
}
5781
5782
#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA)
5783
/* Load an RSA private key into SSL context.
5784
 *
5785
 * @param [in, out] ctx   SSL context object.
5786
 * @param [in]      rsa   RSA private key.
5787
 * @return  1 on success.
5788
 * @return  0 on failure.
5789
 * @return  BAD_FUNC_ARG when ctx or rsa is NULL.
5790
 * @return  MEMORY_E when dynamic memory allocation fails.
5791
 */
5792
int wolfSSL_CTX_use_RSAPrivateKey(WOLFSSL_CTX* ctx, WOLFSSL_RSA* rsa)
5793
{
5794
    int ret = 1;
5795
    int derSize = 0;
5796
    unsigned char* der = NULL;
5797
    unsigned char* p;
5798
5799
    WOLFSSL_ENTER("wolfSSL_CTX_use_RSAPrivateKey");
5800
5801
    /* Validate parameters. */
5802
    if ((ctx == NULL) || (rsa == NULL)) {
5803
        WOLFSSL_MSG("one or more inputs were NULL");
5804
        ret = BAD_FUNC_ARG;
5805
    }
5806
5807
    /* Get DER encoding size. */
5808
    if ((ret == 1) && ((derSize = wolfSSL_i2d_RSAPrivateKey(rsa, NULL)) <= 0)) {
5809
        ret = 0;
5810
    }
5811
5812
    if (ret == 1) {
5813
        /* Allocate memory to hold DER encoding.. */
5814
        der = (unsigned char*)XMALLOC((size_t)derSize, NULL,
5815
                                            DYNAMIC_TYPE_TMP_BUFFER);
5816
        if (der == NULL) {
5817
            WOLFSSL_MSG("Malloc failure");
5818
            ret = MEMORY_E;
5819
        }
5820
    }
5821
5822
    if (ret == 1) {
5823
        /* Pointer passed in is modified.. */
5824
        p = der;
5825
        /* Encode the RSA key as DER into buffer and get size. */
5826
        if ((derSize = wolfSSL_i2d_RSAPrivateKey(rsa, &p)) <= 0) {
5827
            WOLFSSL_MSG("wolfSSL_i2d_RSAPrivateKey() failure");
5828
            ret = 0;
5829
        }
5830
    }
5831
5832
    if (ret == 1) {
5833
        /* Load DER encoded certificate into SSL context. */
5834
        ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, derSize,
5835
            SSL_FILETYPE_ASN1);
5836
        if (ret != WOLFSSL_SUCCESS) {
5837
            WOLFSSL_MSG("wolfSSL_CTX_USE_PrivateKey_buffer() failure");
5838
            ret = 0;
5839
        }
5840
    }
5841
5842
    /* Dispos of dynamically allocated data. */
5843
    if (der != NULL) {
5844
        ForceZero(der, (word32)derSize);
5845
    }
5846
    XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
5847
    return ret;
5848
}
5849
#endif /* WOLFSSL_KEY_GEN && !NO_RSA */
5850
5851
#endif /* OPENSSL_ALL || WOLFSSL_ASIO || WOLFSSL_HAPROXY || WOLFSSL_QT */
5852
5853
#endif /* !NO_CERTS */
5854
5855
#ifdef OPENSSL_EXTRA
5856
5857
/* Use the default paths to look for CA certificate.
5858
 *
5859
 * This is an OpenSSL compatibility layer function, but it doesn't mirror
5860
 * the exact functionality of its OpenSSL counterpart. We don't support the
5861
 * notion of an "OpenSSL directory". This function will attempt to load the
5862
 * environment variables SSL_CERT_DIR and SSL_CERT_FILE, if either are
5863
 * found, they will be loaded. Otherwise, it will act as a wrapper around
5864
 * our native wolfSSL_CTX_load_system_CA_certs function. This function does
5865
 * conform to OpenSSL's return value conventions.
5866
 *
5867
 * @param [in] ctx  SSL context object.
5868
 * @return  1 on success.
5869
 * @return  0 on failure.
5870
 * @return  WOLFSSL_FATAL_ERROR when using a filesystem is not supported.
5871
 */
5872
int wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX* ctx)
5873
{
5874
    int ret;
5875
#if defined(XGETENV) && !defined(NO_GETENV)
5876
    char* certDir = NULL;
5877
    char* certFile = NULL;
5878
    word32 flags = 0;
5879
#elif !defined(WOLFSSL_SYS_CA_CERTS)
5880
    (void)ctx;
5881
#endif
5882
5883
    WOLFSSL_ENTER("wolfSSL_CTX_set_default_verify_paths");
5884
5885
#if defined(XGETENV) && !defined(NO_GETENV)
5886
    /* // NOLINTBEGIN(concurrency-mt-unsafe) */
5887
    certDir = wc_strdup_ex(XGETENV("SSL_CERT_DIR"), DYNAMIC_TYPE_TMP_BUFFER);
5888
    certFile = wc_strdup_ex(XGETENV("SSL_CERT_FILE"), DYNAMIC_TYPE_TMP_BUFFER);
5889
    flags = WOLFSSL_LOAD_FLAG_PEM_CA_ONLY;
5890
5891
    if ((certDir != NULL) || (certFile != NULL)) {
5892
        if (certDir != NULL) {
5893
           /* We want to keep trying to load more CA certs even if one cert in
5894
            * the directory is bad and can't be used (e.g. if one is
5895
            * expired), so we use WOLFSSL_LOAD_FLAG_IGNORE_ERR.
5896
            */
5897
            flags |= WOLFSSL_LOAD_FLAG_IGNORE_ERR;
5898
        }
5899
5900
        /* Load CA certificates from environment variable locations. */
5901
        ret = wolfSSL_CTX_load_verify_locations_ex(ctx, certFile, certDir,
5902
            flags);
5903
        if (ret != 1) {
5904
            WOLFSSL_MSG_EX("Failed to load CA certs from SSL_CERT_FILE: %s"
5905
                            " SSL_CERT_DIR: %s. Error: %d", certFile,
5906
                            certDir, ret);
5907
            ret = 0;
5908
        }
5909
    }
5910
    /* // NOLINTEND(concurrency-mt-unsafe) */
5911
    else
5912
#endif
5913
5914
    {
5915
    #ifdef NO_FILESYSTEM
5916
        WOLFSSL_MSG("wolfSSL_CTX_set_default_verify_paths not supported"
5917
                    " with NO_FILESYSTEM enabled");
5918
        ret = WOLFSSL_FATAL_ERROR;
5919
    #elif defined(WOLFSSL_SYS_CA_CERTS)
5920
        /* Load the system CA certificates. */
5921
        ret = wolfSSL_CTX_load_system_CA_certs(ctx);
5922
        if (ret == WC_NO_ERR_TRACE(WOLFSSL_BAD_PATH)) {
5923
            /* OpenSSL doesn't treat the lack of a system CA cert directory as a
5924
             * failure. We do the same here.
5925
             */
5926
            ret = 1;
5927
        }
5928
    #else
5929
        /* No source available: SSL_CERT_DIR/SSL_CERT_FILE not set and
5930
         * WOLFSSL_SYS_CA_CERTS not compiled in. Returning success would be
5931
         * fail-open since no trust anchors were loaded. */
5932
        WOLFSSL_MSG("wolfSSL_CTX_set_default_verify_paths: no CA source "
5933
                    "available (build without WOLFSSL_SYS_CA_CERTS and no "
5934
                    "SSL_CERT_DIR/SSL_CERT_FILE env)");
5935
        ret = WOLFSSL_FAILURE;
5936
    #endif
5937
    }
5938
5939
#if defined(XGETENV) && !defined(NO_GETENV)
5940
    XFREE(certFile, NULL, DYNAMIC_TYPE_TMP_BUFFER);
5941
    XFREE(certDir, NULL, DYNAMIC_TYPE_TMP_BUFFER);
5942
#endif
5943
    WOLFSSL_LEAVE("wolfSSL_CTX_set_default_verify_paths", ret);
5944
5945
    return ret;
5946
}
5947
5948
#endif /* OPENSSL_EXTRA */
5949
5950
#ifndef NO_DH
5951
5952
/* Set the temporary DH parameters against the SSL.
5953
 *
5954
 * @param [in, out] ssl   SSL object.
5955
 * @param [in]      p     Buffer holding prime.
5956
 * @param [in]      pSz   Length of prime in bytes.
5957
 * @param [in]      g     Buffer holding generator.
5958
 * @param [in]      gSz   Length of generator in bytes.
5959
 * @return  1 on success.
5960
 * @return  0 on failure.
5961
 * @return  DH_KEY_SIZE_E when the prime is too short or long.
5962
 * @return  SIDE_ERROR when the SSL is for a client.
5963
 */
5964
static int wolfssl_set_tmp_dh(WOLFSSL* ssl, unsigned char* p, int pSz,
5965
    unsigned char* g, int gSz)
5966
0
{
5967
0
    int ret = 1;
5968
5969
    /* Check the size of the prime meets the requirements of the SSL. */
5970
0
    if (((word16)pSz < ssl->options.minDhKeySz) ||
5971
0
            ((word16)pSz > ssl->options.maxDhKeySz)) {
5972
0
        ret = DH_KEY_SIZE_E;
5973
0
    }
5974
    /* Only able to set DH parameters on server. */
5975
0
    if ((ret == 1) && (ssl->options.side == WOLFSSL_CLIENT_END)) {
5976
0
        ret = SIDE_ERROR;
5977
0
    }
5978
5979
0
    if (ret == 1) {
5980
0
    #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \
5981
0
        !defined(HAVE_SELFTEST)
5982
        /* New DH parameters not tested for validity. */
5983
0
        ssl->options.dhKeyTested = 0;
5984
        /* New DH parameters must be tested for validity before use. */
5985
0
        ssl->options.dhDoKeyTest = 1;
5986
0
    #endif
5987
5988
        /* Dispose of old DH parameters if we own it. */
5989
0
        if (ssl->buffers.weOwnDH) {
5990
0
            XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap,
5991
0
                DYNAMIC_TYPE_PUBLIC_KEY);
5992
0
            XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap,
5993
0
                DYNAMIC_TYPE_PUBLIC_KEY);
5994
0
        }
5995
5996
        /* Assign the buffers and lengths to SSL. */
5997
0
        ssl->buffers.serverDH_P.buffer = p;
5998
0
        ssl->buffers.serverDH_G.buffer = g;
5999
0
        ssl->buffers.serverDH_P.length = (unsigned int)pSz;
6000
0
        ssl->buffers.serverDH_G.length = (unsigned int)gSz;
6001
        /* We own the buffers. */
6002
0
        ssl->buffers.weOwnDH = 1;
6003
        /* We have a DH parameters to use. */
6004
0
        ssl->options.haveDH = 1;
6005
0
    }
6006
6007
    /* Allocate space for cipher suites. */
6008
0
    if ((ret == 1) && (AllocateSuites(ssl) != 0)) {
6009
0
        ssl->buffers.serverDH_P.buffer = NULL;
6010
0
        ssl->buffers.serverDH_G.buffer = NULL;
6011
0
        ret = 0;
6012
0
    }
6013
0
    if (ret == 1) {
6014
        /* Reset the cipher suites based on having a DH parameters now. */
6015
0
        InitSuites(ssl->suites, ssl->version, SSL_KEY_SZ(ssl),
6016
0
            WOLFSSL_HAVE_RSA, SSL_HAVE_PSK(ssl), ssl->options.haveDH,
6017
0
            ssl->options.haveECDSAsig, ssl->options.haveECC, TRUE,
6018
0
            ssl->options.haveStaticECC,
6019
0
            ssl->options.useAnon, TRUE,
6020
0
            TRUE, TRUE, TRUE, ssl->options.side);
6021
0
    }
6022
6023
0
    return ret;
6024
0
}
6025
6026
/* Set the temporary DH parameters against the SSL.
6027
 *
6028
 * @param [in, out] ssl   SSL object.
6029
 * @param [in]      p     Buffer holding prime.
6030
 * @param [in]      pSz   Length of prime in bytes.
6031
 * @param [in]      g     Buffer holding generator.
6032
 * @param [in]      gSz   Length of generator in bytes.
6033
 * @return  1 on success.
6034
 * @return  0 on failure.
6035
 * @return  DH_KEY_SIZE_E when the prime is too short or long.
6036
 * @return  SIDE_ERROR when the SSL is for a client.
6037
 * @return  MEMORY_E when dynamic memory allocation fails.
6038
 */
6039
int wolfSSL_SetTmpDH(WOLFSSL* ssl, const unsigned char* p, int pSz,
6040
    const unsigned char* g, int gSz)
6041
0
{
6042
0
    int ret = 1;
6043
0
    byte* pAlloc = NULL;
6044
0
    byte* gAlloc = NULL;
6045
6046
0
    WOLFSSL_ENTER("wolfSSL_SetTmpDH");
6047
6048
    /* Validate parameters. */
6049
0
    if ((ssl == NULL) || (p == NULL) || (g == NULL)) {
6050
0
        ret = 0;
6051
0
    }
6052
6053
0
    if (ret == 1) {
6054
        /* Allocate buffers for p and g to be assigned into SSL. */
6055
0
        pAlloc = (byte*)XMALLOC((size_t)pSz, ssl->heap,
6056
0
            DYNAMIC_TYPE_PUBLIC_KEY);
6057
0
        gAlloc = (byte*)XMALLOC((size_t)gSz, ssl->heap,
6058
0
            DYNAMIC_TYPE_PUBLIC_KEY);
6059
0
        if ((pAlloc == NULL) || (gAlloc == NULL)) {
6060
            /* Memory will be freed below in the (ret != 1) block */
6061
0
            ret = MEMORY_E;
6062
0
        }
6063
0
    }
6064
0
    if (ret == 1) {
6065
        /* Copy p and g into allocated buffers. */
6066
0
        XMEMCPY(pAlloc, p, (size_t)pSz);
6067
0
        XMEMCPY(gAlloc, g, (size_t)gSz);
6068
        /* Set the buffers into SSL. */
6069
0
        ret = wolfssl_set_tmp_dh(ssl, pAlloc, pSz, gAlloc, gSz);
6070
0
    }
6071
6072
0
    if (ret != 1 && ssl != NULL) {
6073
        /* Free the allocated buffers if not assigned into SSL. */
6074
0
        XFREE(pAlloc, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
6075
0
        XFREE(gAlloc, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
6076
0
    }
6077
6078
0
    WOLFSSL_LEAVE("wolfSSL_SetTmpDH", ret);
6079
0
    return ret;
6080
0
}
6081
6082
#if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \
6083
    !defined(HAVE_SELFTEST)
6084
/* Check the DH parameters is valid.
6085
 *
6086
 * @param [in]      p     Buffer holding prime.
6087
 * @param [in]      pSz   Length of prime in bytes.
6088
 * @param [in]      g     Buffer holding generator.
6089
 * @param [in]      gSz   Length of generator in bytes.
6090
 * @return  1 on success.
6091
 * @return  DH_CHECK_PUB_E when p is not a prime.
6092
 * @return  BAD_FUNC_ARG when p or g is NULL, or pSz or gSz is 0.
6093
 * @return  MEMORY_E when dynamic memory allocation fails.
6094
 */
6095
static int wolfssl_check_dh_key(unsigned char* p, int pSz, unsigned char* g,
6096
    int gSz)
6097
0
{
6098
0
    WC_RNG rng;
6099
0
    int ret = 0;
6100
0
    WC_DECLARE_VAR(checkKey, DhKey, 1, 0);
6101
6102
0
    WC_ALLOC_VAR_EX(checkKey, DhKey, 1, NULL, DYNAMIC_TYPE_DH,
6103
0
        ret=MEMORY_E);
6104
    /* Initialize a new random number generator. */
6105
0
    if ((ret == 0) && ((ret = wc_InitRng(&rng)) == 0)) {
6106
        /* Initialize a DH object. */
6107
0
        if ((ret = wc_InitDhKey(checkKey)) == 0) {
6108
            /* Check DH parameters. */
6109
0
            ret = wc_DhSetCheckKey(checkKey, p, (word32)pSz, g, (word32)gSz,
6110
0
                NULL, 0, 0, &rng);
6111
            /* Dispose of DH object. */
6112
0
            wc_FreeDhKey(checkKey);
6113
0
        }
6114
        /* Dispose of random number generator. */
6115
0
        wc_FreeRng(&rng);
6116
0
    }
6117
6118
0
    WC_FREE_VAR_EX(checkKey, NULL, DYNAMIC_TYPE_DH);
6119
    /* Convert wolfCrypt return code to 1 on success and ret on failure. */
6120
0
    return WC_TO_WS_RC(ret);
6121
0
}
6122
#endif
6123
6124
/* Set the temporary DH parameters against the SSL context.
6125
 *
6126
 * @param [in, out] ctx   SSL context object.
6127
 * @param [in]      p     Buffer holding prime.
6128
 * @param [in]      pSz   Length of prime in bytes.
6129
 * @param [in]      g     Buffer holding generator.
6130
 * @param [in]      gSz   Length of generator in bytes.
6131
 * @return  1 on success.
6132
 * @return  0 on failure.
6133
 * @return  DH_KEY_SIZE_E when the prime is too short or long.
6134
 * @return  SIDE_ERROR when the SSL is for a client.
6135
 * @return  BAD_FUNC_ARG when ctx, p or g is NULL.
6136
 * @return  DH_CHECK_PUB_E when p is not a prime.
6137
 * @return  MEMORY_E when dynamic memory allocation fails.
6138
 */
6139
static int wolfssl_ctx_set_tmp_dh(WOLFSSL_CTX* ctx, unsigned char* p, int pSz,
6140
    unsigned char* g, int gSz)
6141
0
{
6142
0
    int ret = 1;
6143
6144
0
    WOLFSSL_ENTER("wolfSSL_CTX_SetTmpDH");
6145
6146
0
    if ((ctx == NULL) || (p == NULL) || (g == NULL))
6147
0
        ret = BAD_FUNC_ARG;
6148
6149
    /* Check the size of the prime meets the requirements of the SSL context. */
6150
0
    if (ret == 1) {
6151
0
        if (((word16)pSz < ctx->minDhKeySz) || ((word16)pSz > ctx->maxDhKeySz)) {
6152
0
            ret = DH_KEY_SIZE_E;
6153
0
        }
6154
0
    }
6155
6156
0
#if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \
6157
0
    !defined(HAVE_SELFTEST)
6158
0
    if (ret == 1) {
6159
        /* Test DH parameters for validity. */
6160
0
        ret = wolfssl_check_dh_key(p, pSz, g, gSz);
6161
        /* Record as whether tested based on result of validity test. */
6162
0
        ctx->dhKeyTested = (ret == 1);
6163
0
    }
6164
0
#endif
6165
6166
0
    if (ret == 1) {
6167
        /* Dispose of old DH parameters. */
6168
0
        XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
6169
0
        XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
6170
        /* Assign the buffers and lengths to SSL context. */
6171
0
        ctx->serverDH_P.buffer = p;
6172
0
        ctx->serverDH_G.buffer = g;
6173
0
        ctx->serverDH_P.length = (unsigned int)pSz;
6174
0
        ctx->serverDH_G.length = (unsigned int)gSz;
6175
        /* We have a DH parameters to use. */
6176
0
        ctx->haveDH = 1;
6177
0
    }
6178
6179
0
    WOLFSSL_LEAVE("wolfSSL_CTX_SetTmpDH", 0);
6180
0
    return ret;
6181
0
}
6182
6183
/* Set the temporary DH parameters against the SSL context.
6184
 *
6185
 * @param [in, out] ctx   SSL context object.
6186
 * @param [in]      p     Buffer holding prime.
6187
 * @param [in]      pSz   Length of prime in bytes.
6188
 * @param [in]      g     Buffer holding generator.
6189
 * @param [in]      gSz   Length of generator in bytes.
6190
 * @return  1 on success.
6191
 * @return  0 on failure.
6192
 * @return  DH_KEY_SIZE_E when the prime is too short or long.
6193
 * @return  SIDE_ERROR when the SSL is for a client.
6194
 * @return  BAD_FUNC_ARG when ctx, p or g is NULL.
6195
 * @return  DH_CHECK_PUB_E when p is not a prime.
6196
 */
6197
int wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX* ctx, const unsigned char* p, int pSz,
6198
                         const unsigned char* g, int gSz)
6199
0
{
6200
0
    int ret = 1;
6201
0
    byte* pAlloc = NULL;
6202
0
    byte* gAlloc = NULL;
6203
6204
    /* Validate parameters. */
6205
0
    if ((ctx == NULL) || (p == NULL) || (g == NULL)) {
6206
0
        ret = BAD_FUNC_ARG;
6207
0
    }
6208
6209
0
    if (ret == 1) {
6210
        /* Allocate buffers for p and g to be assigned into SSL context. */
6211
0
        pAlloc = (byte*)XMALLOC((size_t)pSz, ctx->heap,
6212
0
            DYNAMIC_TYPE_PUBLIC_KEY);
6213
0
        gAlloc = (byte*)XMALLOC((size_t)gSz, ctx->heap,
6214
0
            DYNAMIC_TYPE_PUBLIC_KEY);
6215
0
        if ((pAlloc == NULL) || (gAlloc == NULL)) {
6216
0
            ret = MEMORY_E;
6217
0
        }
6218
0
    }
6219
6220
0
    if (ret == 1) {
6221
        /* Copy p and g into allocated buffers. */
6222
0
        XMEMCPY(pAlloc, p, (size_t)pSz);
6223
0
        XMEMCPY(gAlloc, g, (size_t)gSz);
6224
        /* Set the buffers into SSL context. */
6225
0
        ret = wolfssl_ctx_set_tmp_dh(ctx, pAlloc, pSz, gAlloc, gSz);
6226
0
    }
6227
6228
0
    if ((ret != 1) && (ctx != NULL)) {
6229
        /* Free the allocated buffers if not assigned into SSL context. */
6230
0
        XFREE(pAlloc, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
6231
0
        XFREE(gAlloc, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
6232
0
    }
6233
0
    return ret;
6234
0
}
6235
6236
#ifdef OPENSSL_EXTRA
6237
/* Set the temporary DH parameters against the SSL.
6238
 *
6239
 * @param [in, out] ssl  SSL object.
6240
 * @param [in]      dh   DH object.
6241
 * @return  1 on success.
6242
 * @return  0 on failure.
6243
 * @return  WOLFSSL_FATAL_ERROR on failure.
6244
 * @return  BAD_FUNC_ARG when ssl or dh is NULL.
6245
 * @return  DH_KEY_SIZE_E when the prime is too short or long.
6246
 * @return  SIDE_ERROR when the SSL is for a client.
6247
 */
6248
long wolfSSL_set_tmp_dh(WOLFSSL *ssl, WOLFSSL_DH *dh)
6249
{
6250
    int ret = 1;
6251
    byte* p = NULL;
6252
    byte* g = NULL;
6253
    int pSz = 0;
6254
    int gSz = 0;
6255
6256
    WOLFSSL_ENTER("wolfSSL_set_tmp_dh");
6257
6258
    /* Validate parameters. */
6259
    if ((ssl == NULL) || (dh == NULL)) {
6260
        ret = BAD_FUNC_ARG;
6261
    }
6262
6263
    if (ret == 1) {
6264
        /* Get sizes of p and g. */
6265
        pSz = wolfSSL_BN_bn2bin(dh->p, NULL);
6266
        gSz = wolfSSL_BN_bn2bin(dh->g, NULL);
6267
        /* Validate p and g size. */
6268
        if ((pSz <= 0) || (gSz <= 0)) {
6269
            ret = WOLFSSL_FATAL_ERROR;
6270
        }
6271
    }
6272
6273
    if (ret == 1) {
6274
        /* Allocate buffers for p and g to be assigned into SSL. */
6275
        p = (byte*)XMALLOC((size_t)pSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
6276
        g = (byte*)XMALLOC((size_t)gSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
6277
        if ((p == NULL) || (g == NULL)) {
6278
            ret = MEMORY_E;
6279
        }
6280
    }
6281
    if (ret == 1) {
6282
        /* Encode p and g and get sizes. */
6283
        pSz = wolfSSL_BN_bn2bin(dh->p, p);
6284
        gSz = wolfSSL_BN_bn2bin(dh->g, g);
6285
        /* Check encoding worked. */
6286
        if ((pSz <= 0) || (gSz <= 0)) {
6287
            ret = WOLFSSL_FATAL_ERROR;
6288
        }
6289
    }
6290
    if (ret == 1) {
6291
        /* Set the buffers into SSL. */
6292
        ret = wolfssl_set_tmp_dh(ssl, p, pSz, g, gSz);
6293
    }
6294
6295
    if ((ret != 1) && (ssl != NULL)) {
6296
        /* Free the allocated buffers if not assigned into SSL. */
6297
        XFREE(p, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
6298
        XFREE(g, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
6299
    }
6300
    return ret;
6301
}
6302
6303
/* Set the temporary DH parameters object against the SSL context.
6304
 *
6305
 * @param [in, out] ctx     SSL context object.
6306
 * @param [in]      dh      DH object.
6307
 * @return  1 on success.
6308
 * @return  0 on failure.
6309
 * @return  DH_KEY_SIZE_E when the prime is too short or long.
6310
 * @return  SIDE_ERROR when the SSL is for a client.
6311
 * @return  BAD_FUNC_ARG when ctx, p or g is NULL.
6312
 * @return  DH_CHECK_PUB_E when p is not a prime.
6313
 */
6314
long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX* ctx, WOLFSSL_DH* dh)
6315
{
6316
    int ret = 1;
6317
    int pSz = 0;
6318
    int gSz = 0;
6319
    byte* p = NULL;
6320
    byte* g = NULL;
6321
6322
    WOLFSSL_ENTER("wolfSSL_CTX_set_tmp_dh");
6323
6324
    /* Validate parameters. */
6325
    if ((ctx == NULL) || (dh == NULL)) {
6326
        ret = BAD_FUNC_ARG;
6327
    }
6328
6329
    if (ret == 1) {
6330
        /* Get sizes of p and g. */
6331
        pSz = wolfSSL_BN_bn2bin(dh->p, NULL);
6332
        gSz = wolfSSL_BN_bn2bin(dh->g, NULL);
6333
        /* Validate p and g size. */
6334
        if ((pSz <= 0) || (gSz <= 0)) {
6335
            ret = WOLFSSL_FATAL_ERROR;
6336
        }
6337
    }
6338
6339
    if (ret == 1) {
6340
        /* Allocate buffers for p and g to be assigned into SSL. */
6341
        p = (byte*)XMALLOC((size_t)pSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
6342
        g = (byte*)XMALLOC((size_t)gSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
6343
        if ((p == NULL) || (g == NULL)) {
6344
            ret = MEMORY_E;
6345
        }
6346
    }
6347
6348
    if (ret == 1) {
6349
        /* Encode p and g and get sizes. */
6350
        pSz = wolfSSL_BN_bn2bin(dh->p, p);
6351
        gSz = wolfSSL_BN_bn2bin(dh->g, g);
6352
        /* Check encoding worked. */
6353
        if ((pSz <= 0) || (gSz <= 0)) {
6354
            ret = WOLFSSL_FATAL_ERROR;
6355
        }
6356
    }
6357
    if (ret == 1) {
6358
        /* Set the buffers into SSL context. */
6359
        ret = wolfssl_ctx_set_tmp_dh(ctx, p, pSz, g, gSz);
6360
    }
6361
6362
    if ((ret != 1) && (ctx != NULL)) {
6363
        /* Free the allocated buffers if not assigned into SSL. */
6364
        XFREE(p, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
6365
        XFREE(g, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
6366
    }
6367
    return ret;
6368
}
6369
6370
#endif /* OPENSSL_EXTRA */
6371
6372
#ifndef NO_CERTS
6373
6374
/* Set the temporary DH parameters against the SSL context or SSL.
6375
 *
6376
 * @param [in, out] ctx     SSL context object.
6377
 * @param [in, out] ssl     SSL object.
6378
 * @param [in]      buf     Buffer holding encoded DH parameters.
6379
 * @param [in]      sz      Size of encoded DH parameters.
6380
 * @param [in]      format  Format of data:
6381
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
6382
 * @return  1 on success.
6383
 * @return  0 on failure.
6384
 * @return  BAD_FUNC_ARG when ctx and ssl NULL or buf is NULL.
6385
 * @return  NOT_COMPLED_IN when format is PEM but PEM is not supported.
6386
 * @return  WOLFSSL_BAD_FILETYPE if format is not supported.
6387
 */
6388
static int ws_ctx_ssl_set_tmp_dh(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
6389
    const unsigned char* buf, long sz, int format)
6390
0
{
6391
0
    DerBuffer* der = NULL;
6392
0
    int res = 1;
6393
0
    int ret;
6394
    /* p and g size to allocate set to maximum valid size. */
6395
0
    word32 pSz = MAX_DH_SIZE;
6396
0
    word32 gSz = MAX_DH_SIZE;
6397
0
    byte* p = NULL;
6398
0
    byte* g = NULL;
6399
0
    void* heap = WOLFSSL_HEAP(ctx, ssl);
6400
6401
    /* Validate parameters. */
6402
0
    if (((ctx == NULL) && (ssl == NULL)) || (buf == NULL)) {
6403
0
        res = BAD_FUNC_ARG;
6404
0
    }
6405
    /* Check format is supported. */
6406
0
    if ((res == 1) && (format != WOLFSSL_FILETYPE_ASN1)) {
6407
0
        if (format != WOLFSSL_FILETYPE_PEM) {
6408
0
            res = WOLFSSL_BAD_FILETYPE;
6409
0
        }
6410
    #ifndef WOLFSSL_PEM_TO_DER
6411
        else {
6412
            res = NOT_COMPILED_IN;
6413
        }
6414
    #endif
6415
0
    }
6416
6417
    /* PemToDer allocates its own DER buffer. */
6418
0
    if ((res == 1) && (format != WOLFSSL_FILETYPE_PEM)) {
6419
        /* Create a DER buffer and copy in the encoded DH parameters. */
6420
0
        ret = AllocDer(&der, (word32)sz, DH_PARAM_TYPE, heap);
6421
0
        if (ret == 0) {
6422
0
            XMEMCPY(der->buffer, buf, (word32)sz);
6423
0
        }
6424
0
        else {
6425
0
            res = ret;
6426
0
        }
6427
0
    }
6428
6429
0
    if (res == 1) {
6430
        /* Allocate enough memory to p and g to support valid use cases. */
6431
0
        p = (byte*)XMALLOC(pSz, heap, DYNAMIC_TYPE_PUBLIC_KEY);
6432
0
        g = (byte*)XMALLOC(gSz, heap, DYNAMIC_TYPE_PUBLIC_KEY);
6433
0
        if ((p == NULL) || (g == NULL)) {
6434
0
            res = MEMORY_E;
6435
0
        }
6436
0
    }
6437
6438
0
#ifdef WOLFSSL_PEM_TO_DER
6439
0
    if ((res == 1) && (format == WOLFSSL_FILETYPE_PEM)) {
6440
        /* Convert from PEM to DER. */
6441
        /* Try converting DH parameters from PEM to DER. */
6442
0
        ret = PemToDer(buf, sz, DH_PARAM_TYPE, &der, heap, NULL, NULL);
6443
0
        if (ret < 0) {
6444
            /* Otherwise, try converting X9.43 format DH parameters. */
6445
0
            ret = PemToDer(buf, sz, X942_PARAM_TYPE, &der, heap, NULL, NULL);
6446
0
        }
6447
    #if defined(WOLFSSL_WPAS) && !defined(NO_DSA)
6448
        if (ret < 0) {
6449
            /* Otherwise, try converting DSA parameters. */
6450
            ret = PemToDer(buf, sz, DSA_PARAM_TYPE, &der, heap, NULL, NULL);
6451
        }
6452
    #endif /* WOLFSSL_WPAS && !NO_DSA */
6453
0
       if (ret < 0) {
6454
           /* Return error from conversion. */
6455
0
           res = ret;
6456
0
       }
6457
0
    }
6458
0
#endif /* WOLFSSL_PEM_TO_DER */
6459
6460
0
    if (res == 1) {
6461
        /* Get the p and g from the DER encoded parameters. */
6462
0
        if (wc_DhParamsLoad(der->buffer, der->length, p, &pSz, g, &gSz) < 0) {
6463
0
            res = WOLFSSL_BAD_FILETYPE;
6464
0
        }
6465
0
        else if (ssl != NULL) {
6466
            /* Set p and g into SSL. */
6467
0
            res = wolfssl_set_tmp_dh(ssl, p, (int)pSz, g, (int)gSz);
6468
0
        }
6469
0
        else {
6470
            /* Set p and g into SSL context. */
6471
0
            res = wolfssl_ctx_set_tmp_dh(ctx, p, (int)pSz, g, (int)gSz);
6472
0
        }
6473
0
    }
6474
6475
    /* Dispose of the DER buffer. */
6476
0
    FreeDer(&der);
6477
0
    if (res != 1) {
6478
        /* Free the allocated buffers if not assigned into SSL or context. */
6479
0
        XFREE(p, heap, DYNAMIC_TYPE_PUBLIC_KEY);
6480
0
        XFREE(g, heap, DYNAMIC_TYPE_PUBLIC_KEY);
6481
0
    }
6482
0
    return res;
6483
0
}
6484
6485
6486
/* Set the temporary DH parameters against the SSL.
6487
 *
6488
 * @param [in, out] ssl     SSL object.
6489
 * @param [in]      buf     Buffer holding encoded DH parameters.
6490
 * @param [in]      sz      Size of encoded DH parameters.
6491
 * @param [in]      format  Format of data:
6492
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
6493
 * @return  1 on success.
6494
 * @return  BAD_FUNC_ARG when ssl or buf is NULL.
6495
 * @return  NOT_COMPLED_IN when format is PEM but PEM is not supported.
6496
 * @return  WOLFSSL_BAD_FILETYPE if format is not supported.
6497
 */
6498
int wolfSSL_SetTmpDH_buffer(WOLFSSL* ssl, const unsigned char* buf, long sz,
6499
    int format)
6500
0
{
6501
0
    return ws_ctx_ssl_set_tmp_dh(NULL, ssl, buf, sz, format);
6502
0
}
6503
6504
6505
/* Set the temporary DH parameters against the SSL context.
6506
 *
6507
 * @param [in, out] ctx     SSL context object.
6508
 * @param [in]      buf     Buffer holding encoded DH parameters.
6509
 * @param [in]      sz      Size of encoded DH parameters.
6510
 * @param [in]      format  Format of data:
6511
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
6512
 * @return  1 on success.
6513
 * @return  BAD_FUNC_ARG when ctx or buf is NULL.
6514
 * @return  NOT_COMPLED_IN when format is PEM but PEM is not supported.
6515
 * @return  WOLFSSL_BAD_FILETYPE if format is not supported.
6516
 */
6517
int wolfSSL_CTX_SetTmpDH_buffer(WOLFSSL_CTX* ctx, const unsigned char* buf,
6518
    long sz, int format)
6519
0
{
6520
0
    return ws_ctx_ssl_set_tmp_dh(ctx, NULL, buf, sz, format);
6521
0
}
6522
6523
#ifndef NO_FILESYSTEM
6524
6525
/* Set the temporary DH parameters file against the SSL context or SSL.
6526
 *
6527
 * @param [in, out] ctx     SSL context object.
6528
 * @param [in, out] ssl     SSL object.
6529
 * @param [in]      fname   Name of file to load.
6530
 * @param [in]      format  Format of data:
6531
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
6532
 * @return  1 on success.
6533
 * @return  BAD_FUNC_ARG when ctx and ssl NULL or fname is NULL.
6534
 * @return  NOT_COMPLED_IN when format is PEM but PEM is not supported.
6535
 * @return  WOLFSSL_BAD_FILETYPE if format is not supported.
6536
 */
6537
static int ws_ctx_ssl_set_tmp_dh_file(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
6538
    const char* fname, int format)
6539
0
{
6540
0
    int    res = 1;
6541
0
    int    ret;
6542
0
#ifndef WOLFSSL_SMALL_STACK
6543
0
    byte   stackBuffer[FILE_BUFFER_SIZE];
6544
0
#endif
6545
0
    StaticBuffer dhFile;
6546
0
    long   sz = 0;
6547
0
    void*  heap = WOLFSSL_HEAP(ctx, ssl);
6548
6549
    /* Setup buffer to hold file contents. */
6550
#ifdef WOLFSSL_SMALL_STACK
6551
    static_buffer_init(&dhFile);
6552
#else
6553
0
    static_buffer_init(&dhFile, stackBuffer, FILE_BUFFER_SIZE);
6554
0
#endif
6555
6556
    /* Validate parameters. */
6557
0
    if (((ctx == NULL) && (ssl == NULL)) || (fname == NULL)) {
6558
0
        res = BAD_FUNC_ARG;
6559
0
    }
6560
6561
0
    if (res == 1) {
6562
        /* Read file into static buffer. */
6563
0
        ret = wolfssl_read_file_static(fname, &dhFile, heap, DYNAMIC_TYPE_FILE,
6564
0
            &sz);
6565
0
        if (ret != 0) {
6566
0
            res = ret;
6567
0
        }
6568
0
    }
6569
0
    if (res == 1) {
6570
0
        if (ssl != NULL) {
6571
            /* Set encoded DH parameters into SSL. */
6572
0
            res = wolfSSL_SetTmpDH_buffer(ssl, dhFile.buffer, sz, format);
6573
0
        }
6574
0
        else {
6575
            /* Set encoded DH parameters into SSL context. */
6576
0
            res = wolfSSL_CTX_SetTmpDH_buffer(ctx, dhFile.buffer, sz, format);
6577
0
        }
6578
0
    }
6579
6580
    /* Dispose of any dynamically allocated data. */
6581
0
    static_buffer_free(&dhFile, heap, DYNAMIC_TYPE_FILE);
6582
0
    return res;
6583
0
}
6584
6585
/* Set the temporary DH parameters file against the SSL.
6586
 *
6587
 * @param [in, out] ssl     SSL object.
6588
 * @param [in]      fname   Name of file to load.
6589
 * @param [in]      format  Format of data:
6590
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
6591
 * @return  1 on success.
6592
 * @return  BAD_FUNC_ARG when ssl or fname is NULL.
6593
 * @return  NOT_COMPLED_IN when format is PEM but PEM is not supported.
6594
 * @return  WOLFSSL_BAD_FILETYPE if format is not supported.
6595
 */
6596
int wolfSSL_SetTmpDH_file(WOLFSSL* ssl, const char* fname, int format)
6597
0
{
6598
0
    return ws_ctx_ssl_set_tmp_dh_file(NULL, ssl, fname, format);
6599
0
}
6600
6601
6602
/* Set the temporary DH parameters file against the SSL context.
6603
 *
6604
 * @param [in, out] ctx     SSL context object.
6605
 * @param [in]      fname   Name of file to load.
6606
 * @param [in]      format  Format of data:
6607
 *                            WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
6608
 * @return  1 on success.
6609
 * @return  BAD_FUNC_ARG when ctx or fname is NULL.
6610
 * @return  NOT_COMPLED_IN when format is PEM but PEM is not supported.
6611
 * @return  WOLFSSL_BAD_FILETYPE if format is not supported.
6612
 */
6613
int wolfSSL_CTX_SetTmpDH_file(WOLFSSL_CTX* ctx, const char* fname, int format)
6614
0
{
6615
    return ws_ctx_ssl_set_tmp_dh_file(ctx, NULL, fname, format);
6616
0
}
6617
6618
#endif /* NO_FILESYSTEM */
6619
6620
#endif /* NO_CERTS */
6621
6622
#endif /* !NO_DH */
6623
6624
#endif /* !WOLFSSL_SSL_LOAD_INCLUDED */
6625