Coverage Report

Created: 2026-08-15 06:21

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