Coverage Report

Created: 2026-01-06 06:52

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