Coverage Report

Created: 2026-04-01 07:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-openssl-api/src/ssl_certman.c
Line
Count
Source
1
/* ssl_certman.c
2
 *
3
 * Copyright (C) 2006-2026 wolfSSL Inc.
4
 *
5
 * This file is part of wolfSSL.
6
 *
7
 * wolfSSL is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * wolfSSL is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20
 */
21
22
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
23
24
#include <wolfssl/internal.h>
25
26
#if !defined(WOLFSSL_SSL_CERTMAN_INCLUDED)
27
    #ifndef WOLFSSL_IGNORE_FILE_WARN
28
        #warning ssl_certman.c not to be compiled separately from ssl.c
29
    #endif
30
#else
31
32
#ifndef NO_CERTS
33
34
/* Pick an available TLS method.
35
 *
36
 * Used when creating temporary WOLFSSL_CTX.
37
 *
38
 * @return  A TLS method on success.
39
 * @return  NULL when no TLS method built into wolfSSL.
40
 */
41
static WC_INLINE WOLFSSL_METHOD* cm_pick_method(void* heap)
42
0
{
43
0
    (void)heap;
44
0
    #ifndef NO_WOLFSSL_CLIENT
45
        #if !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_SSLV3)
46
            return wolfSSLv3_client_method_ex(heap);
47
        #elif !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLSV10)
48
            return wolfTLSv1_client_method_ex(heap);
49
        #elif !defined(NO_OLD_TLS)
50
            return wolfTLSv1_1_client_method_ex(heap);
51
        #elif !defined(WOLFSSL_NO_TLS12)
52
            return wolfTLSv1_2_client_method_ex(heap);
53
        #elif defined(WOLFSSL_TLS13)
54
            return wolfTLSv1_3_client_method_ex(heap);
55
        #else
56
            return NULL;
57
        #endif
58
    #elif !defined(NO_WOLFSSL_SERVER)
59
        #if !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_SSLV3)
60
            return wolfSSLv3_server_method_ex(heap);
61
        #elif !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLSV10)
62
            return wolfTLSv1_server_method_ex(heap);
63
        #elif !defined(NO_OLD_TLS)
64
            return wolfTLSv1_1_server_method_ex(heap);
65
        #elif !defined(WOLFSSL_NO_TLS12)
66
            return wolfTLSv1_2_server_method_ex(heap);
67
        #elif defined(WOLFSSL_TLS13)
68
            return wolfTLSv1_3_server_method_ex(heap);
69
        #else
70
            return NULL;
71
        #endif
72
    #else
73
        return NULL;
74
    #endif
75
0
}
76
77
/* Create a new certificate manager with a heap hint.
78
 *
79
 * @param [in] heap  Heap hint.
80
 * @return  Certificate manager object on success.
81
 * @return  NULL on failure.
82
 */
83
WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap)
84
5.34k
{
85
5.34k
    int err = 0;
86
5.34k
    WOLFSSL_CERT_MANAGER* cm;
87
88
5.34k
    WOLFSSL_ENTER("wolfSSL_CertManagerNew");
89
5.34k
    if (heap == NULL) {
90
5.34k
         WOLFSSL_MSG("heap param is null");
91
5.34k
    }
92
0
    else {
93
        /* Some systems may have heap in unexpected segments. (IRAM vs DRAM) */
94
0
        WOLFSSL_MSG_EX("heap param = %p", heap);
95
0
    }
96
5.34k
    WOLFSSL_MSG_EX("DYNAMIC_TYPE_CERT_MANAGER Allocating = %d bytes",
97
5.34k
                    (word32)sizeof(WOLFSSL_CERT_MANAGER));
98
99
    /* Allocate memory for certificate manager. */
100
5.34k
    cm = (WOLFSSL_CERT_MANAGER*)XMALLOC(sizeof(WOLFSSL_CERT_MANAGER), heap,
101
5.34k
        DYNAMIC_TYPE_CERT_MANAGER);
102
5.34k
    if (cm == NULL) {
103
0
        WOLFSSL_MSG_EX("XMALLOC failed to allocate WOLFSSL_CERT_MANAGER %d "
104
0
                    "bytes.", (int)sizeof(WOLFSSL_CERT_MANAGER));
105
0
        err = 1;
106
0
    }
107
5.34k
    if (!err) {
108
        /* Reset all fields. */
109
5.34k
        XMEMSET(cm, 0, sizeof(WOLFSSL_CERT_MANAGER));
110
111
        /* Create a mutex for use when modify table of stored CAs. */
112
5.34k
        if (wc_InitMutex(&cm->caLock) != 0) {
113
0
            WOLFSSL_MSG("Bad mutex init");
114
0
            err = 1;
115
0
        }
116
5.34k
    }
117
5.34k
    if (!err) {
118
        /* Initialize reference count. */
119
5.34k
        wolfSSL_RefInit(&cm->ref, &err);
120
    #ifdef WOLFSSL_REFCNT_ERROR_RETURN
121
        if (err != 0) {
122
            WOLFSSL_MSG("Bad reference count init");
123
        }
124
    #endif
125
5.34k
    }
126
#ifdef WOLFSSL_TRUST_PEER_CERT
127
    /* Create a mutex for use when modify table of trusted peers. */
128
    if ((!err) && (wc_InitMutex(&cm->tpLock) != 0)) {
129
        WOLFSSL_MSG("Bad mutex init");
130
        err = 1;
131
    }
132
#endif
133
5.34k
    if (!err) {
134
        /* Set default minimum key sizes allowed. */
135
5.34k
    #ifndef NO_RSA
136
5.34k
        cm->minRsaKeySz = MIN_RSAKEY_SZ;
137
5.34k
    #endif
138
5.34k
    #ifdef HAVE_ECC
139
5.34k
        cm->minEccKeySz = MIN_ECCKEY_SZ;
140
5.34k
    #endif
141
    #ifdef HAVE_FALCON
142
        cm->minFalconKeySz = MIN_FALCONKEY_SZ;
143
    #endif /* HAVE_FALCON */
144
    #ifdef HAVE_DILITHIUM
145
        cm->minDilithiumKeySz = MIN_DILITHIUMKEY_SZ;
146
    #endif /* HAVE_DILITHIUM */
147
148
        /* Set heap hint to use in certificate manager operations. */
149
5.34k
        cm->heap = heap;
150
5.34k
    }
151
152
    /* Dispose of certificate manager on error. */
153
5.34k
    if (err && (cm != NULL)) {
154
0
        wolfSSL_CertManagerFree(cm);
155
0
        cm = NULL;
156
0
    }
157
5.34k
    return cm;
158
5.34k
}
159
160
/* Create a new certificate manager.
161
 *
162
 * @return  Certificate manager object on success.
163
 * @return  NULL on failure.
164
 */
165
WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew(void)
166
0
{
167
    /* No heap hint. */
168
0
    return wolfSSL_CertManagerNew_ex(NULL);
169
0
}
170
171
/* Dispose of certificate manager.
172
 *
173
 * @param [in, out] cm  Certificate manager.
174
 */
175
void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm)
176
0
{
177
0
    WOLFSSL_ENTER("wolfSSL_CertManagerFree");
178
179
    /* Validate parameter. */
180
0
    if (cm != NULL) {
181
0
        int doFree = 0;
182
0
        int ret;
183
184
        /* Decrement reference count and check if value is 0. */
185
0
        wolfSSL_RefDec(&cm->ref, &doFree, &ret);
186
    #ifdef WOLFSSL_REFCNT_ERROR_RETURN
187
        if (ret != 0) {
188
            WOLFSSL_MSG("Couldn't lock cm mutex");
189
        }
190
    #else
191
0
        (void)ret;
192
0
    #endif
193
0
        if (doFree) {
194
        #ifdef HAVE_CRL
195
            /* Dispose of CRL handler. */
196
            if (cm->crl != NULL) {
197
                /* Dispose of CRL object - indicating dynamically allocated. */
198
                FreeCRL(cm->crl, 1);
199
            }
200
        #endif
201
202
0
    #ifdef HAVE_OCSP
203
            /* Dispose of OCSP handler. */
204
0
            if (cm->ocsp != NULL) {
205
0
                FreeOCSP(cm->ocsp, 1);
206
0
            }
207
            /* Dispose of URL. */
208
0
            XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL);
209
        #if !defined(NO_WOLFSSL_SERVER) && \
210
            (defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
211
             defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
212
            /* Dispose of OCSP stapling handler. */
213
            if (cm->ocsp_stapling) {
214
                FreeOCSP(cm->ocsp_stapling, 1);
215
            }
216
        #endif
217
0
    #endif /* HAVE_OCSP */
218
219
            /* Dispose of CA table and mutex. */
220
0
            FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
221
0
            wc_FreeMutex(&cm->caLock);
222
223
        #ifdef WOLFSSL_TRUST_PEER_CERT
224
            /* Dispose of trusted peer table and mutex. */
225
            FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, cm->heap);
226
            wc_FreeMutex(&cm->tpLock);
227
        #endif
228
229
            /* Dispose of reference count. */
230
0
            wolfSSL_RefFree(&cm->ref);
231
            /* Dispose of certificate manager memory. */
232
0
            XFREE(cm, cm->heap, DYNAMIC_TYPE_CERT_MANAGER);
233
0
        }
234
0
    }
235
0
}
236
237
/* Increase reference count on certificate manager.
238
 *
239
 * @param [in, out] cm  Certificate manager.
240
 * @return  WOLFSSL_SUCCESS on success.
241
 * @return  0 when cm is NULL or locking mutex fails.
242
 */
243
int wolfSSL_CertManager_up_ref(WOLFSSL_CERT_MANAGER* cm)
244
0
{
245
0
    int ret = WOLFSSL_SUCCESS;
246
247
    /* Validate parameter. */
248
0
    if (cm == NULL) {
249
0
        ret = 0;
250
0
    }
251
0
    if (ret == WOLFSSL_SUCCESS) {
252
0
        int err;
253
254
        /* Increment reference. */
255
0
        wolfSSL_RefInc(&cm->ref, &err);
256
    #ifdef WOLFSSL_REFCNT_ERROR_RETURN
257
        if (err) {
258
            WOLFSSL_MSG("Failed to lock cm mutex");
259
            ret = 0;
260
        }
261
    #else
262
0
        (void)err;
263
0
    #endif
264
0
    }
265
266
0
    return ret;
267
0
}
268
269
#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM)
270
#if defined(WOLFSSL_SIGNER_DER_CERT)
271
static WC_INLINE int wolfssl_cm_get_certs_der(WOLFSSL_CERT_MANAGER* cm,
272
    DerBuffer*** buffers, int* cnt)
273
{
274
    int err = 0;
275
    Signer* signers = NULL;
276
    DerBuffer** certBuffers = NULL;
277
    int i = 0;
278
    word32 row = 0;
279
    int numCerts = 0;
280
281
    /* Iterate once to get the number of certs, for memory allocation
282
     * purposes. */
283
    for (row = 0; row < CA_TABLE_SIZE; row++) {
284
        /* Get signer information of CAs in a row. */
285
        signers = cm->caTable[row];
286
        /* Count each signer in row that has a DER certificate buffer. */
287
        while ((signers != NULL) && (signers->derCert != NULL) &&
288
                (signers->derCert->buffer != NULL)) {
289
            ++numCerts;
290
            signers = signers->next;
291
        }
292
    }
293
    /* Check we found certificates. */
294
    if (numCerts == 0) {
295
        err = 1;
296
    }
297
298
    if (!err) {
299
        /* Allocate memory for pointers to each DER buffer. */
300
        certBuffers = (DerBuffer**)XMALLOC(
301
            sizeof(DerBuffer*) * (size_t)numCerts, cm->heap,
302
            DYNAMIC_TYPE_TMP_BUFFER);
303
        if (certBuffers == NULL) {
304
            err = 1;
305
        }
306
    }
307
    if (!err) {
308
        /* Reset pointers. */
309
        XMEMSET(certBuffers, 0, sizeof(DerBuffer*) * (size_t)numCerts);
310
    }
311
312
    /* Copy the certs locally so that we can release the caLock. If the lock
313
     * is held when wolfSSL_d2i_X509 is called, GetCA will also try to get
314
     * the lock, leading to deadlock. */
315
    for (row = 0; (!err) && (row < CA_TABLE_SIZE); row++) {
316
        /* Get signer information of CAs in a row. */
317
        signers = cm->caTable[row];
318
        /* Copy each DER certificate buffer of signers in a row. */
319
        while ((signers != NULL) && (signers->derCert != NULL) &&
320
                (signers->derCert->buffer != NULL)) {
321
            /* Allocate memory to hold DER certificate buffer. */
322
            int ret = AllocDer(&certBuffers[i], signers->derCert->length,
323
                CA_TYPE, cm->heap);
324
            if (ret < 0) {
325
                err = 1;
326
                break;
327
            }
328
329
            /* Copy buffer into array element. */
330
            XMEMCPY(certBuffers[i]->buffer, signers->derCert->buffer,
331
                signers->derCert->length);
332
            certBuffers[i]->length = signers->derCert->length;
333
334
            /* Store in next index. */
335
            ++i;
336
            /* Move on to next signer in row. */
337
            signers = signers->next;
338
        }
339
    }
340
341
    *buffers = certBuffers;
342
    *cnt = numCerts;
343
    return err;
344
}
345
346
/* Retrieve stack of X509 certificates in a certificate manager (CM).
347
 *
348
 * @param [in] cm  Certificate manager.
349
 *
350
 * @return  Stack of X509 certs on success
351
 * @return  NULL on failure.
352
 */
353
WOLFSSL_STACK* wolfSSL_CertManagerGetCerts(WOLFSSL_CERT_MANAGER* cm)
354
{
355
    WOLFSSL_STACK* sk = NULL;
356
    int numCerts = 0;
357
    DerBuffer** certBuffers = NULL;
358
    int i = 0;
359
    int err = 0;
360
361
    WOLFSSL_ENTER("wolfSSL_CertManagerGetCerts");
362
363
    /* Validate parameter. */
364
    if (cm == NULL) {
365
        err = 1;
366
    }
367
    if (!err) {
368
        /* Create an empty certificate stack to return. */
369
        sk = wolfSSL_sk_X509_new_null();
370
        if (sk == NULL) {
371
            err = 1;
372
        }
373
    }
374
    /* Lock CA table. */
375
    if ((!err) && (wc_LockMutex(&cm->caLock) != 0)) {
376
        err = 1;
377
    }
378
    if (!err) {
379
        err = wolfssl_cm_get_certs_der(cm, &certBuffers, &numCerts);
380
        /* Release CA lock. */
381
        wc_UnLockMutex(&cm->caLock);
382
    }
383
384
    /* Put each DER certificate buffer into a stack of WOLFSSL_X509 */
385
    for (i = 0; (!err) && (i < numCerts); ++i) {
386
        const byte* derBuffer = NULL;
387
        WOLFSSL_X509* x509 = NULL;
388
389
        /* Get pointer to DER encoding of certificate. */
390
        derBuffer = certBuffers[i]->buffer;
391
        /* Decode certificate. */
392
        wolfSSL_d2i_X509(&x509, &derBuffer, (int)certBuffers[i]->length);
393
        if (x509 == NULL) {
394
            err = 1;
395
        }
396
397
        /* Decode certificate. */
398
        if ((!err) && (wolfSSL_sk_X509_push(sk, x509) <= 0)) {
399
            wolfSSL_X509_free(x509);
400
            x509 = NULL;
401
            err = 1;
402
        }
403
    }
404
405
    if (certBuffers != NULL) {
406
        /* Dispose of temporary cert storage (for access outside of lock). */
407
        for (i = 0; i < numCerts && certBuffers[i] != NULL; ++i) {
408
            FreeDer(&certBuffers[i]);
409
        }
410
        XFREE(certBuffers, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
411
    }
412
413
    /* Dispose of stack of certificates on error. */
414
    if (err && (sk != NULL)) {
415
        wolfSSL_sk_X509_pop_free(sk, NULL);
416
        sk = NULL;
417
    }
418
    return sk;
419
}
420
421
#endif /* WOLFSSL_SIGNER_DER_CERT */
422
#endif /* OPENSSL_EXTRA && !NO_FILESYSTEM */
423
424
/* Unload the CA signer table.
425
 *
426
 * @param [in] cm  Certificate manager.
427
 * @return  WOLFSSL_SUCCESS on success.
428
 * @return  BAD_FUNC_ARG when cm is NULL.
429
 * @return  BAD_MUTEX_E when locking fails.
430
 */
431
int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm)
432
0
{
433
0
    int ret = WOLFSSL_SUCCESS;
434
435
0
    WOLFSSL_ENTER("wolfSSL_CertManagerUnloadCAs");
436
437
    /* Validate parameter. */
438
0
    if (cm == NULL) {
439
0
        ret = BAD_FUNC_ARG;
440
0
    }
441
    /* Lock CA table. */
442
0
    if ((ret == WOLFSSL_SUCCESS) && (wc_LockMutex(&cm->caLock) != 0)) {
443
0
        ret = BAD_MUTEX_E;
444
0
    }
445
0
    if (ret == WOLFSSL_SUCCESS) {
446
        /* Dispose of CA table. */
447
0
        FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
448
449
        /* Unlock CA table. */
450
0
        wc_UnLockMutex(&cm->caLock);
451
0
    }
452
453
0
    return ret;
454
0
}
455
456
int wolfSSL_CertManagerUnloadTypeCerts(
457
                                WOLFSSL_CERT_MANAGER* cm, byte type)
458
0
{
459
0
    int ret = WOLFSSL_SUCCESS;
460
461
0
    WOLFSSL_ENTER("wolfSSL_CertManagerUnloadTypeCerts");
462
463
    /* Validate parameter. */
464
0
    if (cm == NULL) {
465
0
        ret = BAD_FUNC_ARG;
466
0
    }
467
    /* Lock CA table. */
468
0
    if ((ret == WOLFSSL_SUCCESS) && (wc_LockMutex(&cm->caLock) != 0)) {
469
0
        ret = BAD_MUTEX_E;
470
0
    }
471
0
    if (ret == WOLFSSL_SUCCESS) {
472
        /* Dispose of CA table. */
473
0
        FreeSignerTableType(cm->caTable, CA_TABLE_SIZE, type,
474
0
                cm->heap);
475
476
        /* Unlock CA table. */
477
0
        wc_UnLockMutex(&cm->caLock);
478
0
    }
479
480
0
    return ret;
481
0
}
482
483
#if defined(OPENSSL_EXTRA)
484
static int wolfSSL_CertManagerUnloadTempIntermediateCerts(
485
    WOLFSSL_CERT_MANAGER* cm)
486
0
{
487
0
    WOLFSSL_ENTER("wolfSSL_CertManagerUnloadTempIntermediateCerts");
488
0
    return wolfSSL_CertManagerUnloadTypeCerts(cm, WOLFSSL_TEMP_CA);
489
0
}
490
#endif
491
492
int wolfSSL_CertManagerUnloadIntermediateCerts(
493
    WOLFSSL_CERT_MANAGER* cm)
494
0
{
495
0
    WOLFSSL_ENTER("wolfSSL_CertManagerUnloadIntermediateCerts");
496
0
    return wolfSSL_CertManagerUnloadTypeCerts(cm, WOLFSSL_CHAIN_CA);
497
0
}
498
499
#ifdef WOLFSSL_TRUST_PEER_CERT
500
/* Unload the trusted peers table.
501
 *
502
 * @param [in] cm  Certificate manager.
503
 * @return  WOLFSSL_SUCCESS on success.
504
 * @return  BAD_FUNC_ARG when cm is NULL.
505
 * @return  BAD_MUTEX_E when locking fails.
506
 */
507
int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm)
508
{
509
    int ret = WOLFSSL_SUCCESS;
510
511
    WOLFSSL_ENTER("wolfSSL_CertManagerUnload_trust_peers");
512
513
    /* Validate parameter. */
514
    if (cm == NULL) {
515
        ret = BAD_FUNC_ARG;
516
    }
517
    /* Lock trusted peers table. */
518
    if ((ret == WOLFSSL_SUCCESS) && (wc_LockMutex(&cm->tpLock) != 0)) {
519
        ret = BAD_MUTEX_E;
520
    }
521
    if (ret == WOLFSSL_SUCCESS) {
522
        /* Dispose of trusted peers table. */
523
        FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, cm->heap);
524
525
        /* Unlock trusted peers table. */
526
        wc_UnLockMutex(&cm->tpLock);
527
    }
528
529
    return ret;
530
}
531
#endif /* WOLFSSL_TRUST_PEER_CERT */
532
533
/* Load certificate/s from buffer with flags and type.
534
 *
535
 * @param [in] cm         Certificate manager.
536
 * @param [in] buff       Buffer holding encoding of certificate.
537
 * @param [in] sz         Length in bytes of data in buffer.
538
 * @param [in] format     Format of encoding. Valid values:
539
 *                          WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
540
 * @param [in] userChain  Indicates buffer holds chain of certificates.
541
 * @param [in] flags      Flags to modify behaviour of loading. Valid flags:
542
 *                          WOLFSSL_LOAD_FLAG_IGNORE_ERR,
543
 *                          WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY,
544
 *                          WOLFSSL_LOAD_FLAG_PEM_CA_ONLY,
545
 *                          WOLFSSL_LOAD_FLAG_IGNORE_BAD_PATH_ERR, and
546
 *                          WOLFSSL_LOAD_FLAG_IGNORE_ZEROFILE.
547
 * @param [in] type       The CA cert's type, used in the internal CA
548
                            table.  Defaults to WOLFSSL_USER_CA, passing
549
                            in WOLFSSL_USER_CA = noop.  Recommended to
550
                            set to WOLFSSL_USER_INTER when loading
551
                            intermediate certs to allow unloading via
552
                            wolfSSL_CertManagerUnloadTypeCerts.
553
 * @return  WOLFSSL_SUCCESS on success.
554
 * @return  WOLFSSL_FATAL_ERROR when cm is NULL or failed create WOLFSSL_CTX.
555
 * @return  Other values on loading failure.
556
 */
557
int wolfSSL_CertManagerLoadCABufferType(WOLFSSL_CERT_MANAGER* cm,
558
    const unsigned char* buff, long sz, int format, int userChain,
559
    word32 flags, int type)
560
0
{
561
0
    int ret = WOLFSSL_SUCCESS;
562
0
    WOLFSSL_CTX* tmp = NULL;
563
0
    DecodedCert* dCert = NULL;
564
0
    DerBuffer* der = NULL;
565
566
0
    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCABufferType");
567
568
    /* Validate parameters. */
569
0
    if (cm == NULL) {
570
0
        WOLFSSL_MSG("No CertManager error");
571
0
        ret = WOLFSSL_FATAL_ERROR;
572
0
    }
573
    /* Allocate a temporary WOLFSSL_CTX to load with. */
574
0
    if ((ret == WOLFSSL_SUCCESS) && ((tmp =
575
0
        wolfSSL_CTX_new_ex(cm_pick_method(cm->heap), cm->heap)) == NULL)) {
576
0
        WOLFSSL_MSG("CTX new failed");
577
0
        ret = WOLFSSL_FATAL_ERROR;
578
0
    }
579
0
    if (ret == WOLFSSL_SUCCESS) {
580
        /* Some configurations like OPENSSL_COMPATIBLE_DEFAULTS may turn off
581
         * verification by default. Let's restore our desired defaults. */
582
0
        wolfSSL_CTX_set_verify(tmp, WOLFSSL_VERIFY_DEFAULT, NULL);
583
584
        /* Replace certificate manager with one to load certificate/s into. */
585
0
        wolfSSL_CertManagerFree(tmp->cm);
586
0
        tmp->cm = cm;
587
588
        /* Load certificate buffer. */
589
0
        ret = wolfSSL_CTX_load_verify_buffer_ex(tmp, buff, sz, format,
590
0
            userChain, flags);
591
592
        /* Clear certificate manager in WOLFSSL_CTX so it won't be freed. */
593
0
        tmp->cm = NULL;
594
0
    }
595
0
    if (ret == WOLFSSL_SUCCESS && type != WOLFSSL_USER_CA) {
596
0
        dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap,
597
0
                                                DYNAMIC_TYPE_DCERT);
598
599
0
        if (dCert == NULL) {
600
0
            ret = WOLFSSL_FATAL_ERROR;
601
0
        } else {
602
0
            if (format == WOLFSSL_FILETYPE_PEM) {
603
            #ifndef WOLFSSL_PEM_TO_DER
604
                ret = NOT_COMPILED_IN;
605
            #else
606
0
                ret = PemToDer(buff, sz, CERT_TYPE, &der, cm->heap, NULL, NULL);
607
0
                if (!ret) {
608
                    /* Replace buffer pointer and size with DER buffer. */
609
0
                    buff = der->buffer;
610
0
                    sz = (long)der->length;
611
0
                    ret = WOLFSSL_SUCCESS;
612
0
                } else {
613
0
                    WOLFSSL_ERROR(ret);
614
0
                    ret = WOLFSSL_FATAL_ERROR;
615
0
                }
616
0
            #endif
617
0
            }
618
619
0
            if (ret == WOLFSSL_SUCCESS) {
620
0
                XMEMSET(dCert, 0, sizeof(DecodedCert));
621
0
                wc_InitDecodedCert(dCert, buff,
622
0
                                (word32)sz, cm->heap);
623
0
                ret = wc_ParseCert(dCert, CERT_TYPE, NO_VERIFY, NULL);
624
0
                if (ret) {
625
0
                    ret = WOLFSSL_FATAL_ERROR;
626
0
                } else {
627
0
                    ret = SetCAType(cm, dCert->extSubjKeyId, type);
628
0
                }
629
0
            }
630
631
0
            if (dCert) {
632
0
                wc_FreeDecodedCert(dCert);
633
0
                XFREE(dCert, cm->heap, DYNAMIC_TYPE_DCERT);
634
0
            }
635
0
            if (der) {
636
0
                FreeDer(&der);
637
0
            }
638
0
        }
639
0
    }
640
641
    /* Dispose of temporary WOLFSSL_CTX. */
642
0
    wolfSSL_CTX_free(tmp);
643
0
    return ret;
644
645
0
}
646
647
/* Load certificate/s from buffer with flags.
648
 *
649
 * @param [in] cm         Certificate manager.
650
 * @param [in] buff       Buffer holding encoding of certificate.
651
 * @param [in] sz         Length in bytes of data in buffer.
652
 * @param [in] format     Format of encoding. Valid values:
653
 *                          WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
654
 * @param [in] userChain  Indicates buffer holds chain of certificates.
655
 * @param [in] flags      Flags to modify behaviour of loading. Valid flags:
656
 *                          WOLFSSL_LOAD_FLAG_IGNORE_ERR,
657
 *                          WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY,
658
 *                          WOLFSSL_LOAD_FLAG_PEM_CA_ONLY,
659
 *                          WOLFSSL_LOAD_FLAG_IGNORE_BAD_PATH_ERR, and
660
 *                          WOLFSSL_LOAD_FLAG_IGNORE_ZEROFILE.
661
 * @return  WOLFSSL_SUCCESS on success.
662
 * @return  WOLFSSL_FATAL_ERROR when cm is NULL or failed create WOLFSSL_CTX.
663
 * @return  Other values on loading failure.
664
 */
665
int wolfSSL_CertManagerLoadCABuffer_ex(WOLFSSL_CERT_MANAGER* cm,
666
    const unsigned char* buff, long sz, int format, int userChain, word32 flags)
667
0
{
668
0
    return wolfSSL_CertManagerLoadCABufferType(cm, buff, sz, format, userChain,
669
0
        flags, WOLFSSL_USER_CA);
670
0
}
671
672
/* Load certificate/s from buffer into table.
673
 *
674
 * Uses default load verification flags and is not a user chain.
675
 *
676
 * @param [in] cm         Certificate manager.
677
 * @param [in] buff       Buffer holding encoding of certificate.
678
 * @param [in] sz         Length in bytes of data in buffer.
679
 * @param [in] format     Format of encoding. Valid values:
680
 *                          WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
681
 * @return  WOLFSSL_SUCCESS on success.
682
 * @return  WOLFSSL_FATAL_ERROR when cm is NULL or failed create WOLFSSL_CTX.
683
 * @return  Other values on loading failure.
684
 */
685
int wolfSSL_CertManagerLoadCABuffer(WOLFSSL_CERT_MANAGER* cm,
686
    const unsigned char* buff, long sz, int format)
687
0
{
688
0
    return wolfSSL_CertManagerLoadCABuffer_ex(cm, buff, sz, format, 0,
689
0
        WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS);
690
0
}
691
692
#ifndef NO_WOLFSSL_CM_VERIFY
693
/* Set the verification callback into certificate manager.
694
 *
695
 * @param [in] cm  Certificate manager.
696
 * @param [in] vc  Verification callback.
697
 */
698
void wolfSSL_CertManagerSetVerify(WOLFSSL_CERT_MANAGER* cm, VerifyCallback vc)
699
0
{
700
0
    WOLFSSL_ENTER("wolfSSL_CertManagerSetVerify");
701
0
    if (cm != NULL) {
702
0
        cm->verifyCallback = vc;
703
0
    }
704
0
}
705
#endif /* !NO_WOLFSSL_CM_VERIFY */
706
707
#ifdef WC_ASN_UNKNOWN_EXT_CB
708
void wolfSSL_CertManagerSetUnknownExtCallback(WOLFSSL_CERT_MANAGER* cm,
709
        wc_UnknownExtCallback cb)
710
0
{
711
0
    WOLFSSL_ENTER("wolfSSL_CertManagerSetUnknownExtCallback");
712
0
    if (cm != NULL) {
713
0
        cm->unknownExtCallback = cb;
714
0
    }
715
716
0
}
717
#endif /* WC_ASN_UNKNOWN_EXT_CB */
718
719
#if (!defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)) || \
720
    defined(OPENSSL_EXTRA)
721
/* Verify the certificate.
722
 *
723
 * Uses the verification callback if available.
724
 *
725
 * @param [in] cm        Certificate manager.
726
 * @param [in] buff      Buffer holding encoded certificate.
727
 * @param [in] sz        Size in bytes of data in buffer.
728
 * @param [in] format    Format of encoding. Valid values:
729
 *                         WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
730
 * @param [in] prev_err  Previous error. Passed to callback.
731
 * @return  WOLFSSL_SUCCESS on success.
732
 * @return  MEMORY_E when dynamic memory allocation fails.
733
 * @return  NOT_COMPILED_IN when converting from PEM to DER is not a feature of
734
 *          the wolfSSL build.
735
 */
736
int CM_VerifyBuffer_ex(WOLFSSL_CERT_MANAGER* cm, const unsigned char* buff,
737
    long sz, int format, int prev_err)
738
0
{
739
0
    int ret = 0;
740
0
    int fatal = 0;
741
0
    DerBuffer* der = NULL;
742
0
    WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
743
744
0
    WOLFSSL_ENTER("CM_VerifyBuffer_ex");
745
746
0
    (void)prev_err;
747
748
    /* Allocate memory for decoded certificate. */
749
0
    WC_ALLOC_VAR_EX(cert, DecodedCert, 1, cm->heap, DYNAMIC_TYPE_DCERT,
750
0
    {
751
0
        ret=MEMORY_E;
752
0
        fatal=1;
753
0
    });
754
0
    if (WC_VAR_OK(cert))
755
0
    {
756
        /* Reset fields of decoded certificate. */
757
0
        XMEMSET(cert, 0, sizeof(DecodedCert));
758
759
0
        if (format == WOLFSSL_FILETYPE_PEM) {
760
        #ifndef WOLFSSL_PEM_TO_DER
761
            ret = NOT_COMPILED_IN;
762
            fatal = 1;
763
        #else
764
            /* Convert to DER from PEM. */
765
0
            ret = PemToDer(buff, sz, CERT_TYPE, &der, cm->heap, NULL, NULL);
766
0
            if (ret != 0) {
767
0
                fatal = 1;
768
0
            }
769
0
            else {
770
                /* Replace buffer pointer and size with DER buffer. */
771
0
                buff = der->buffer;
772
0
                sz = (long)der->length;
773
0
            }
774
0
        #endif
775
0
        }
776
0
    }
777
0
    if (ret == 0) {
778
        /* Create a decoded certificate with DER buffer. */
779
0
        InitDecodedCert(cert, buff, (word32)sz, cm->heap);
780
781
0
#ifdef WC_ASN_UNKNOWN_EXT_CB
782
0
        if (cm->unknownExtCallback != NULL)
783
0
            wc_SetUnknownExtCallback(cert, cm->unknownExtCallback);
784
0
#endif
785
786
        /* Parse DER into decoded certificate fields and verify signature
787
         * against a known CA. */
788
0
        ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, cm, NULL);
789
0
     }
790
791
#ifdef HAVE_CRL
792
    if ((ret == 0) && cm->crlEnabled) {
793
        /* Check for a CRL for the CA and check validity of certificate. */
794
        ret = CheckCertCRL(cm->crl, cert);
795
    }
796
#endif
797
798
0
    (void)fatal;
799
800
0
#if !defined(NO_WOLFSSL_CM_VERIFY) && \
801
0
    (!defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH))
802
    /* Use callback to perform verification too if available. */
803
0
    if ((!fatal) && cm->verifyCallback) {
804
0
        WC_DECLARE_VAR(args, ProcPeerCertArgs, 1, 0);
805
0
        buffer certBuf;
806
807
0
    #ifdef WOLFSSL_SMALL_STACK
808
        /* Allocate memory for object to hold arguments for callback. */
809
0
        args = (ProcPeerCertArgs*)XMALLOC(sizeof(ProcPeerCertArgs), cm->heap,
810
0
            DYNAMIC_TYPE_TMP_BUFFER);
811
0
        if (args == NULL) {
812
0
            ret = MEMORY_E;
813
0
            fatal = 1;
814
0
        }
815
0
        if (!fatal)
816
0
    #endif
817
0
        {
818
0
            XMEMSET(args, 0, sizeof(ProcPeerCertArgs));
819
820
            /* DER encoding. */
821
0
            certBuf.buffer = (byte*)buff;
822
0
            certBuf.length = (unsigned int)sz;
823
824
            /* One certificate available. */
825
0
            args->totalCerts = 1;
826
0
            args->certs = &certBuf;
827
0
            args->dCert = cert;
828
0
            args->dCertInit = 1;
829
830
            /* Replace value in ret with an error value passed in. */
831
0
            if (prev_err != 0) {
832
0
                ret = prev_err;
833
0
            }
834
            /* Use callback to verify certificate. */
835
0
            ret = DoVerifyCallback(cm, NULL, ret, args);
836
0
        }
837
0
        WC_FREE_VAR_EX(args, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
838
0
    }
839
0
#endif
840
841
    /* Dispose of allocated memory. */
842
0
    FreeDecodedCert(cert);
843
0
    FreeDer(&der);
844
0
    WC_FREE_VAR_EX(cert, cm->heap, DYNAMIC_TYPE_DCERT);
845
846
    /* Convert the ret value to a return value. */
847
0
    return (ret == 0) ? WOLFSSL_SUCCESS : ret;
848
0
}
849
850
/* Verify the certificate.
851
 *
852
 * Uses the verification callback if available.
853
 *
854
 * @param [in] cm        Certificate manager.
855
 * @param [in] buff      Buffer holding encoded certificate.
856
 * @param [in] sz        Size in bytes of data in buffer.
857
 * @param [in] format    Format of encoding. Valid values:
858
 *                         WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
859
 * @param [in] prev_err  Previous error. Passed to callback.
860
 * @return  WOLFSSL_SUCCESS on success.
861
 * @return  BAD_FUNC_ARG when cm or buff is NULL or sz is negative or zero.
862
 * @return  WOLFSSL_BAD_FILETYPE when format is invalid.
863
 * @return  MEMORY_E when dynamic memory allocation fails.
864
 * @return  NOT_COMPILED_IN when converting from PEM to DER is not a feature of
865
 *          the wolfSSL build.
866
 */
867
int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm,
868
    const unsigned char* buff, long sz, int format)
869
0
{
870
0
    int ret;
871
872
0
    WOLFSSL_ENTER("wolfSSL_CertManagerVerifyBuffer");
873
874
    /* Validate parameters. */
875
0
    if ((cm == NULL) || (buff == NULL) || (sz <= 0)) {
876
0
        ret = BAD_FUNC_ARG;
877
0
    }
878
0
    else if ((format != WOLFSSL_FILETYPE_ASN1) &&
879
0
             (format != WOLFSSL_FILETYPE_PEM)) {
880
0
        ret = WOLFSSL_BAD_FILETYPE;
881
0
    }
882
0
    else {
883
        /* No previous error. */
884
0
        ret = CM_VerifyBuffer_ex(cm, buff, sz, format, 0);
885
0
    }
886
887
0
    return ret;
888
0
}
889
#endif /* (!NO_WOLFSSL_CLIENT || !WOLFSSL_NO_CLIENT_AUTH) || OPENSSL_EXTRA */
890
891
#ifndef NO_FILESYSTEM
892
893
#if (!defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)) || \
894
    defined(OPENSSL_EXTRA)
895
/* Verify the certificate loaded from a file.
896
 *
897
 * Uses the verification callback if available.
898
 *
899
 * @param [in] cm        Certificate manager.
900
 * @param [in] format    Format of encoding. Valid values:
901
 *                         WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
902
 * @param [in] prev_err  Previous error. Passed to callback.
903
 * @return  WOLFSSL_SUCCESS on success.
904
 * @return  BAD_FUNC_ARG when cm or buff is NULL or sz is negative.
905
 * @return  WOLFSSL_BAD_FILETYPE when format is invalid.
906
 * @return  WOLFSSL_BAD_FILE when reading the certificate file fails.
907
 * @return  MEMORY_E when dynamic memory allocation fails.
908
 * @return  NOT_COMPILED_IN when converting from PEM to DER is not a feature of
909
 *          the wolfSSL build.
910
 */
911
int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname,
912
    int format)
913
0
{
914
0
    int    ret = WOLFSSL_SUCCESS;
915
#ifndef WOLFSSL_SMALL_STACK
916
    byte   staticBuffer[FILE_BUFFER_SIZE];
917
#endif
918
0
    byte*  buff = NULL;
919
0
    long   sz = 0;
920
0
    XFILE  file = XBADFILE;
921
922
0
    WOLFSSL_ENTER("wolfSSL_CertManagerVerify");
923
924
#ifndef WOLFSSL_SMALL_STACK
925
    buff = staticBuffer;
926
#endif
927
928
    /* Validate parameters. cm and format validated in:
929
     *   wolfSSL_CertManagerVerifyBuffer */
930
0
    if ((cm == NULL) || (fname == NULL)) {
931
0
        ret = BAD_FUNC_ARG;
932
0
    }
933
934
    /* Open the file containing a certificate. */
935
0
    if ((ret == WOLFSSL_SUCCESS) &&
936
0
            ((file = XFOPEN(fname, "rb")) == XBADFILE)) {
937
0
        ret = WOLFSSL_BAD_FILE;
938
0
    }
939
    /* Get the length of the file. */
940
0
    if (ret == WOLFSSL_SUCCESS) {
941
0
        ret = wolfssl_file_len(file, &sz);
942
0
        if (ret == 0) {
943
0
            ret = WOLFSSL_SUCCESS;
944
0
        }
945
0
    }
946
    /* Allocate dynamic memory for file contents if no static buffer or too
947
     * small. */
948
#ifndef WOLFSSL_SMALL_STACK
949
    if ((ret == WOLFSSL_SUCCESS) && (sz > (long)sizeof(staticBuffer)))
950
#else
951
952
0
    if (ret == WOLFSSL_SUCCESS)
953
0
#endif
954
0
    {
955
0
        WOLFSSL_MSG("Getting dynamic buffer");
956
0
        buff = (byte*)XMALLOC((size_t)sz, cm->heap, DYNAMIC_TYPE_FILE);
957
0
        if (buff == NULL) {
958
0
            ret = WOLFSSL_BAD_FILE;
959
0
        }
960
0
    }
961
    /* Read all the file into buffer. */
962
0
    if ((ret == WOLFSSL_SUCCESS) && (XFREAD(buff, 1, (size_t)sz, file) !=
963
0
            (size_t)sz)) {
964
0
        ret = WOLFSSL_BAD_FILE;
965
0
    }
966
    /* Close file if opened. */
967
0
    if (file != XBADFILE) {
968
0
        XFCLOSE(file);
969
0
    }
970
0
    if (ret == WOLFSSL_SUCCESS) {
971
        /* Verify the certificate read. */
972
0
        ret = wolfSSL_CertManagerVerifyBuffer(cm, buff, sz, format);
973
0
    }
974
975
    /* Dispose of buffer if it was allocated. */
976
#ifndef WOLFSSL_SMALL_STACK
977
    if (buff != staticBuffer)
978
#endif
979
0
    {
980
0
        if (cm != NULL) {
981
0
            XFREE(buff, cm->heap, DYNAMIC_TYPE_FILE);
982
0
        }
983
0
    }
984
0
    return ret;
985
0
}
986
#endif
987
988
/* Load the CA file and/or certificate files in a path.
989
 *
990
 * @param [in] cm    Certificate manager.
991
 * @param [in] file  Name of CA file.
992
 * @param [in] path  Path to a directory containing certificates.
993
 * @return  WOLFSSL_SUCCESS on success.
994
 * @return  WOLFSSL_FATAL_ERROR when cm is NULL or unable to create WOLFSSL_CTX.
995
 * @return  Otherwise failure.
996
 */
997
int wolfSSL_CertManagerLoadCA(WOLFSSL_CERT_MANAGER* cm, const char* file,
998
                             const char* path)
999
0
{
1000
0
    int ret = WOLFSSL_SUCCESS;
1001
0
    WOLFSSL_CTX* tmp = NULL;
1002
1003
0
    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCA");
1004
1005
    /* Validate parameters. file and path validated in:
1006
     *   wolfSSL_CTX_load_verify_locations*/
1007
0
    if (cm == NULL) {
1008
0
        WOLFSSL_MSG("No CertManager error");
1009
0
        ret = WOLFSSL_FATAL_ERROR;
1010
0
    }
1011
    /* Create temporary WOLFSSL_CTX. */
1012
0
    if ((ret == WOLFSSL_SUCCESS) && ((tmp =
1013
0
        wolfSSL_CTX_new_ex(cm_pick_method(cm->heap), cm->heap)) == NULL)) {
1014
0
        WOLFSSL_MSG("CTX new failed");
1015
0
        ret = WOLFSSL_FATAL_ERROR;
1016
0
    }
1017
0
    if (ret == WOLFSSL_SUCCESS) {
1018
        /* Some configurations like OPENSSL_COMPATIBLE_DEFAULTS may turn off
1019
         * verification by default. Let's restore our desired defaults. */
1020
0
        wolfSSL_CTX_set_verify(tmp, WOLFSSL_VERIFY_DEFAULT, NULL);
1021
1022
        /* Replace certificate manager with one to load certificate/s into. */
1023
0
        wolfSSL_CertManagerFree(tmp->cm);
1024
0
        tmp->cm = cm;
1025
1026
        /* Load certificate from file and path. */
1027
0
        ret = wolfSSL_CTX_load_verify_locations(tmp, file, path);
1028
1029
        /* Clear certificate manager in WOLFSSL_CTX so it won't be freed. */
1030
0
        tmp->cm = NULL;
1031
0
    }
1032
1033
    /* Dispose of temporary WOLFSSL_CTX. */
1034
0
    wolfSSL_CTX_free(tmp);
1035
0
    return ret;
1036
0
}
1037
1038
#endif /* NO_FILESYSTEM */
1039
1040
#if defined(PERSIST_CERT_CACHE)
1041
1042
/* Version of layout of cache of CA certificates. */
1043
#define WOLFSSL_CACHE_CERT_VERSION 1
1044
1045
/* CA certificates cache information. */
1046
typedef struct {
1047
    /* Cache certificate layout version id. */
1048
    int version;
1049
    /* Number of hash table rows. Maximum of CA_TABLE_SIZE. */
1050
    int rows;
1051
    /* Number of columns per row. */
1052
    int columns[CA_TABLE_SIZE];
1053
    /* Size of Signer object. */
1054
    int signerSz;
1055
} CertCacheHeader;
1056
1057
/* current cert persistence layout is:
1058
1059
   1) CertCacheHeader
1060
   2) caTable
1061
1062
   update WOLFSSL_CERT_CACHE_VERSION if change layout for the following
1063
   PERSIST_CERT_CACHE functions
1064
*/
1065
1066
1067
/* Return number of bytes of memory needed to persist this signer.
1068
 *
1069
 * Assumes we have locked CA table.
1070
 *
1071
 * @param [in] Signer  Signer entry in CA table.
1072
 * @return  Number of bytes.
1073
 */
1074
static WC_INLINE int cm_get_signer_memory(Signer* signer)
1075
{
1076
    int sz = sizeof(signer->pubKeySize) + sizeof(signer->keyOID)
1077
           + sizeof(signer->nameLen)    + sizeof(signer->subjectNameHash);
1078
1079
#if !defined(NO_SKID)
1080
        sz += (int)sizeof(signer->subjectKeyIdHash);
1081
#endif
1082
1083
    /* Add dynamic bytes needed. */
1084
    sz += (int)signer->pubKeySize;
1085
    sz += signer->nameLen;
1086
1087
    return sz;
1088
}
1089
1090
1091
/* Return number of bytes of memory needed to persist this row.
1092
 *
1093
 * Assumes we have locked CA table.
1094
 *
1095
 * @param [in] row  A row of signers from the CA table.
1096
 * @return  Number of bytes.
1097
 */
1098
static WC_INLINE int cm_get_cert_cache_row_memory(Signer* row)
1099
{
1100
    int sz = 0;
1101
1102
    /* Each signer in row. */
1103
    while (row != NULL) {
1104
        /* Add in size of this signer. */
1105
        sz += cm_get_signer_memory(row);
1106
        row = row->next;
1107
    }
1108
1109
    return sz;
1110
}
1111
1112
1113
/* Return the number of bytes of memory to persist cert cache.
1114
 *
1115
 * Assumes we have locked CA table.
1116
 *
1117
 * @param [in] cm  Certificate manager.
1118
 * @return  Number of bytes.
1119
 */
1120
static WC_INLINE int cm_get_cert_cache_mem_size(WOLFSSL_CERT_MANAGER* cm)
1121
{
1122
    int sz;
1123
    int i;
1124
1125
    sz = sizeof(CertCacheHeader);
1126
1127
    /* Each row in table. */
1128
    for (i = 0; i < CA_TABLE_SIZE; i++) {
1129
        /* Add in size of this row. */
1130
        sz += cm_get_cert_cache_row_memory(cm->caTable[i]);
1131
    }
1132
1133
    return sz;
1134
}
1135
1136
1137
/* Get count of columns for each row.
1138
 *
1139
 * Assumes we have locked CA table.
1140
 *
1141
 * @param [in] cm       Certificate manager.
1142
 * @param [in] columns  Array of row counts.
1143
 */
1144
static WC_INLINE void cm_set_cert_header_Columns(WOLFSSL_CERT_MANAGER* cm,
1145
    int* columns)
1146
{
1147
    int     i;
1148
    Signer* row;
1149
1150
    /* Each row in table. */
1151
    for (i = 0; i < CA_TABLE_SIZE; i++) {
1152
        int count = 0;
1153
1154
        /* Get row from table. */
1155
        row = cm->caTable[i];
1156
        /* Each entry in row. */
1157
        while (row != NULL) {
1158
            /* Update count. */
1159
            ++count;
1160
            row = row->next;
1161
        }
1162
        /* Store row count. */
1163
        columns[i] = count;
1164
    }
1165
}
1166
1167
1168
/* Restore whole cert row from memory,
1169
 *
1170
 * Assumes we have locked CA table.
1171
 *
1172
 * @param [in] cm       Certificate manager.
1173
 * @param [in] current  Buffer containing rows.
1174
 * @param [in] row      Row number being restored.
1175
 * @param [in] listSz   Number of entries in row.
1176
 * @param [in] end      End of data in buffer.
1177
 * @return  Number of bytes consumed on success.
1178
 * @return  PARSE_ERROR when listSz is less than zero.
1179
 * @return  BUFFER_E when buffer is too small.
1180
 * @return  MEMORY_E when dynamic memory allocation fails.
1181
 * @return  Negative value on error.
1182
 */
1183
static WC_INLINE int cm_restore_cert_row(WOLFSSL_CERT_MANAGER* cm,
1184
    byte* current, int row, int listSz, const byte* end)
1185
{
1186
    int ret = 0;
1187
    int idx = 0;
1188
1189
    /* Validate parameters. */
1190
    if (listSz < 0) {
1191
        WOLFSSL_MSG("Row header corrupted, negative value");
1192
        ret = PARSE_ERROR;
1193
    }
1194
1195
    /* Process all entries. */
1196
    while ((ret == 0) && (listSz > 0)) {
1197
        Signer* signer = NULL;
1198
        byte*   publicKey;
1199
        byte*   start = current + idx;  /* for end checks on this signer */
1200
        int     minSz = sizeof(signer->pubKeySize) + sizeof(signer->keyOID) +
1201
                      sizeof(signer->nameLen) + sizeof(signer->subjectNameHash);
1202
        #ifndef NO_SKID
1203
                minSz += (int)sizeof(signer->subjectKeyIdHash);
1204
        #endif
1205
1206
        /* Check minimal size of bytes available. */
1207
        if (start + minSz > end) {
1208
            WOLFSSL_MSG("Would overread restore buffer");
1209
            ret = BUFFER_E;
1210
        }
1211
        /* Make a new signer. */
1212
        if ((ret == 0) && ((signer = MakeSigner(cm->heap)) == NULL)) {
1213
            ret = MEMORY_E;
1214
        }
1215
1216
        if (ret == 0) {
1217
            /* Copy in public key size. */
1218
            XMEMCPY(&signer->pubKeySize, current + idx,
1219
                sizeof(signer->pubKeySize));
1220
            idx += (int)sizeof(signer->pubKeySize);
1221
1222
            /* Copy in public key OID. */
1223
            XMEMCPY(&signer->keyOID, current + idx, sizeof(signer->keyOID));
1224
            idx += (int)sizeof(signer->keyOID);
1225
1226
            /* Check bytes available for public key. */
1227
            if (start + minSz + signer->pubKeySize > end) {
1228
                WOLFSSL_MSG("Would overread restore buffer");
1229
                ret = BUFFER_E;
1230
            }
1231
        }
1232
        if (ret == 0) {
1233
            /* Allocate memory for public key to be stored in. */
1234
            publicKey = (byte*)XMALLOC(signer->pubKeySize, cm->heap,
1235
                DYNAMIC_TYPE_KEY);
1236
            if (publicKey == NULL) {
1237
                ret = MEMORY_E;
1238
            }
1239
        }
1240
1241
        if (ret == 0) {
1242
            /* Copy in public key. */
1243
            XMEMCPY(publicKey, current + idx, signer->pubKeySize);
1244
            signer->publicKey = publicKey;
1245
            idx += (int)signer->pubKeySize;
1246
1247
            /* Copy in certificate name length. */
1248
            XMEMCPY(&signer->nameLen, current + idx, sizeof(signer->nameLen));
1249
            idx += (int)sizeof(signer->nameLen);
1250
1251
            /* Check bytes available for certificate name. */
1252
            if (start + minSz + signer->pubKeySize + signer->nameLen > end) {
1253
                WOLFSSL_MSG("Would overread restore buffer");
1254
                ret = BUFFER_E;
1255
            }
1256
        }
1257
        if (ret == 0) {
1258
            /* Allocate memory for public key to be stored in. */
1259
            signer->name = (char*)XMALLOC((size_t)signer->nameLen, cm->heap,
1260
                DYNAMIC_TYPE_SUBJECT_CN);
1261
            if (signer->name == NULL) {
1262
                ret = MEMORY_E;
1263
            }
1264
        }
1265
1266
        if (ret == 0) {
1267
            /* Copy in certificate name. */
1268
            XMEMCPY(signer->name, current + idx, (size_t)signer->nameLen);
1269
            idx += signer->nameLen;
1270
1271
            /* Copy in hash of subject name. */
1272
            XMEMCPY(signer->subjectNameHash, current + idx, SIGNER_DIGEST_SIZE);
1273
            idx += SIGNER_DIGEST_SIZE;
1274
1275
        #ifndef NO_SKID
1276
            /* Copy in hash of subject key. */
1277
            XMEMCPY(signer->subjectKeyIdHash, current + idx,SIGNER_DIGEST_SIZE);
1278
            idx += SIGNER_DIGEST_SIZE;
1279
        #endif
1280
1281
            /* Make next Signer the head of the row. */
1282
            signer->next = cm->caTable[row];
1283
            /* Add Signer to start of row. */
1284
            cm->caTable[row] = signer;
1285
1286
            /* Done one more Signer. */
1287
            --listSz;
1288
        }
1289
1290
        if ((ret != 0) && (signer != NULL)) {
1291
            /* Dispose of allocated signer. */
1292
            FreeSigner(signer, cm->heap);
1293
        }
1294
    }
1295
1296
    if (ret == 0) {
1297
        /* Return the number of bytes used on success. */
1298
        ret = idx;
1299
    }
1300
    return ret;
1301
}
1302
1303
1304
/* Store whole CA certificate row into memory.
1305
 *
1306
 * Assumes we have locked CA table.
1307
 *
1308
 * @param [in] cm       Certificate manager.
1309
 * @param [in] current  Buffer to write to.
1310
 * @param [in] row      Row number being stored.
1311
 * @return  Number of bytes added.
1312
 */
1313
static WC_INLINE int cm_store_cert_row(WOLFSSL_CERT_MANAGER* cm, byte* current,
1314
    int row)
1315
{
1316
    int     added  = 0;
1317
    Signer* list;
1318
1319
    /* Get the row - a linked list. */
1320
    list  = cm->caTable[row];
1321
    /* Each certificate in row. */
1322
    while (list != NULL) {
1323
        /* Public key size. */
1324
        XMEMCPY(current + added, &list->pubKeySize, sizeof(list->pubKeySize));
1325
        added += (int)sizeof(list->pubKeySize);
1326
1327
        /* Public key OID. */
1328
        XMEMCPY(current + added, &list->keyOID,     sizeof(list->keyOID));
1329
        added += (int)sizeof(list->keyOID);
1330
1331
        /* Public key. */
1332
        XMEMCPY(current + added, list->publicKey, (size_t)list->pubKeySize);
1333
        added += (int)list->pubKeySize;
1334
1335
        /* Certificate name length. */
1336
        XMEMCPY(current + added, &list->nameLen, sizeof(list->nameLen));
1337
        added += (int)sizeof(list->nameLen);
1338
1339
        /* Certificate name. */
1340
        XMEMCPY(current + added, list->name, (size_t)list->nameLen);
1341
        added += list->nameLen;
1342
1343
        /* Hash of subject name. */
1344
        XMEMCPY(current + added, list->subjectNameHash, SIGNER_DIGEST_SIZE);
1345
        added += SIGNER_DIGEST_SIZE;
1346
1347
    #ifndef NO_SKID
1348
        /* Hash of public key. */
1349
        XMEMCPY(current + added, list->subjectKeyIdHash,SIGNER_DIGEST_SIZE);
1350
        added += SIGNER_DIGEST_SIZE;
1351
    #endif
1352
1353
        /* Next certificate in row. */
1354
        list = list->next;
1355
    }
1356
1357
    return added;
1358
}
1359
1360
1361
/* Persist CA certificate cache to memory.
1362
 *
1363
 * Assumes we have locked CA table.
1364
 *
1365
 * @param [in] cm   Certificate manager.
1366
 * @param [in] mem  Memory to persist into.
1367
 * @param [in] sz   Size in bytes of memory.
1368
 * @return  WOLFSSL_SUCCESS on success.
1369
 * @return  BUFFER_E when memory is too small.
1370
 */
1371
static WC_INLINE int cm_do_mem_save_cert_cache(WOLFSSL_CERT_MANAGER* cm,
1372
    void* mem, int sz)
1373
{
1374
    int ret = WOLFSSL_SUCCESS;
1375
    int realSz;
1376
    int i;
1377
1378
    WOLFSSL_ENTER("cm_do_mem_save_cert_cache");
1379
1380
    /* Calculate amount of memory required to store CA certificate table. */
1381
    realSz = cm_get_cert_cache_mem_size(cm);
1382
    if (realSz > sz) {
1383
        WOLFSSL_MSG("Mem output buffer too small");
1384
        ret = BUFFER_E;
1385
    }
1386
    if (ret == WOLFSSL_SUCCESS) {
1387
        byte*           current;
1388
        CertCacheHeader hdr;
1389
1390
        /* Create header for storage. */
1391
        hdr.version  = WOLFSSL_CACHE_CERT_VERSION;
1392
        hdr.rows     = CA_TABLE_SIZE;
1393
        cm_set_cert_header_Columns(cm, hdr.columns);
1394
        hdr.signerSz = (int)sizeof(Signer);
1395
1396
        /* Copy header into memory. */
1397
        XMEMCPY(mem, &hdr, sizeof(CertCacheHeader));
1398
        current = (byte*)mem + sizeof(CertCacheHeader);
1399
1400
        /* Each row of table. */
1401
        for (i = 0; i < CA_TABLE_SIZE; ++i) {
1402
            /* Append row to memory. */
1403
            current += cm_store_cert_row(cm, current, i);
1404
        }
1405
    }
1406
1407
    return ret;
1408
}
1409
1410
1411
#if !defined(NO_FILESYSTEM)
1412
1413
/* Persist CA certificate cache to file.
1414
 *
1415
 * Locks CA table.
1416
 *
1417
 * @param [in] cm     Certificate manager.
1418
 * @param [in] fname  File name to write to.
1419
 * @return  WOLFSSL_SUCCESS on success.
1420
 * @return  WOLFSSL_BAD_FILE when opening file fails.
1421
 * @return  BAD_MUTEX_E when locking fails.
1422
 * @return  MEMORY_E when dynamic memory allocation fails.
1423
 * @return  FWRITE_ERROR when writing to file fails.
1424
 */
1425
int CM_SaveCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
1426
{
1427
    XFILE file;
1428
    int   ret = WOLFSSL_SUCCESS;
1429
1430
    WOLFSSL_ENTER("CM_SaveCertCache");
1431
1432
    /* Open file for writing. */
1433
    file = XFOPEN(fname, "w+b");
1434
    if (file == XBADFILE) {
1435
       WOLFSSL_MSG("Couldn't open cert cache save file");
1436
       ret = WOLFSSL_BAD_FILE;
1437
    }
1438
1439
    /* Lock CA table. */
1440
    if ((ret == WOLFSSL_SUCCESS) && (wc_LockMutex(&cm->caLock) != 0)) {
1441
        WOLFSSL_MSG("wc_LockMutex on caLock failed");
1442
        ret = BAD_MUTEX_E;
1443
    }
1444
1445
    if (ret == WOLFSSL_SUCCESS) {
1446
        byte* mem;
1447
        /* Calculate size of memory required to store CA table. */
1448
        size_t memSz = (size_t)cm_get_cert_cache_mem_size(cm);
1449
        /* Allocate memory to hold CA table. */
1450
        mem = (byte*)XMALLOC(memSz, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
1451
        if (mem == NULL) {
1452
            WOLFSSL_MSG("Alloc for tmp buffer failed");
1453
            ret = MEMORY_E;
1454
        }
1455
        if (ret == WOLFSSL_SUCCESS) {
1456
            /* Store CA table in memory. */
1457
            ret = cm_do_mem_save_cert_cache(cm, mem, (int)memSz);
1458
        }
1459
        if (ret == WOLFSSL_SUCCESS) {
1460
            /* Write memory to file. */
1461
            int sz = (int)XFWRITE(mem, memSz, 1, file);
1462
            if (sz != 1) {
1463
                WOLFSSL_MSG("Cert cache file write failed");
1464
                ret = FWRITE_ERROR;
1465
            }
1466
        }
1467
        XFREE(mem, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
1468
1469
        /* Unlock CA table. */
1470
        wc_UnLockMutex(&cm->caLock);
1471
    }
1472
1473
    /* Close file. */
1474
    if (file != XBADFILE) {
1475
        XFCLOSE(file);
1476
    }
1477
    return ret;
1478
}
1479
1480
1481
/* Restore CA certificate cache from file.
1482
 *
1483
 * @param [in] cm     Certificate manager.
1484
 * @param [in] fname  File name to write to.
1485
 * @return  WOLFSSL_SUCCESS on success.
1486
 * @return  WOLFSSL_BAD_FILE when opening or using file fails.
1487
 * @return  MEMORY_E when dynamic memory allocation fails.
1488
 * @return  FREAD_ERROR when reading from file fails.
1489
 */
1490
int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
1491
{
1492
    XFILE file;
1493
    int   ret = WOLFSSL_SUCCESS;
1494
    int   memSz = 0;
1495
    byte* mem = NULL;
1496
1497
    WOLFSSL_ENTER("CM_RestoreCertCache");
1498
1499
    /* Open file for reading. */
1500
    file = XFOPEN(fname, "rb");
1501
    if (file == XBADFILE) {
1502
       WOLFSSL_MSG("Couldn't open cert cache save file");
1503
       ret = WOLFSSL_BAD_FILE;
1504
    }
1505
1506
    if (ret == WOLFSSL_SUCCESS) {
1507
        /* Read file into allocated memory. */
1508
        ret = wolfssl_read_file(file, (char**)&mem, &memSz);
1509
        if (ret == 0) {
1510
            ret = WOLFSSL_SUCCESS;
1511
        }
1512
    }
1513
    if (ret == WOLFSSL_SUCCESS) {
1514
        /* Create the CA certificate table from memory. */
1515
        ret = CM_MemRestoreCertCache(cm, mem, memSz);
1516
        if (ret != WOLFSSL_SUCCESS) {
1517
            WOLFSSL_MSG("Mem restore cert cache failed");
1518
        }
1519
    }
1520
1521
    /* Dispose of dynamic memory read into. */
1522
    XFREE(mem, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
1523
    /* Close file. */
1524
    if (file != XBADFILE) {
1525
        XFCLOSE(file);
1526
    }
1527
    return ret;
1528
}
1529
1530
#endif /* NO_FILESYSTEM */
1531
1532
1533
/* Persist CA certificate cache to memory.
1534
 *
1535
 * Locks CA table.
1536
 *
1537
 * @param [in]  cm    Certificate manager.
1538
 * @param [in]  mem   Memory to persist into.
1539
 * @param [in]  sz    Size in bytes of memory.
1540
 * @param [out] used  Number of bytes used when persisting cache.
1541
 * @return  WOLFSSL_SUCCESS on success.
1542
 * @return  BAD_MUTEX_E when locking fails.
1543
 * @return  BUFFER_E when memory is too small.
1544
 */
1545
int CM_MemSaveCertCache(WOLFSSL_CERT_MANAGER* cm, void* mem, int sz, int* used)
1546
{
1547
    int ret = WOLFSSL_SUCCESS;
1548
1549
    WOLFSSL_ENTER("CM_MemSaveCertCache");
1550
1551
    /* Lock CA table. */
1552
    if (wc_LockMutex(&cm->caLock) != 0) {
1553
        WOLFSSL_MSG("wc_LockMutex on caLock failed");
1554
        ret = BAD_MUTEX_E;
1555
    }
1556
    if (ret == WOLFSSL_SUCCESS) {
1557
        /* Save CA table into memory. */
1558
        ret = cm_do_mem_save_cert_cache(cm, mem, sz);
1559
        if (ret == WOLFSSL_SUCCESS) {
1560
            /* Get the number of bytes used. */
1561
            *used  = cm_get_cert_cache_mem_size(cm);
1562
        }
1563
1564
        /* Unlock CA table. */
1565
        wc_UnLockMutex(&cm->caLock);
1566
    }
1567
1568
    return ret;
1569
}
1570
1571
1572
/* Restore CA certificate table from memory,
1573
 *
1574
 * Locks CA table.
1575
 *
1576
 * @param [in] cm   Certificate manager.
1577
 * @param [in] mem  Buffer containing rows.
1578
 * @param [in] sz   Size in bytes of data in buffer.
1579
 * @return  WOLFSSL_SUCCESS on success.
1580
 * @return  BUFFER_E when buffer is too small.
1581
 * @return  BAD_MUTEX_E when locking fails.
1582
 * @return  MEMORY_E when dynamic memory allocation fails.
1583
 */
1584
int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const void* mem, int sz)
1585
{
1586
    int ret = WOLFSSL_SUCCESS;
1587
    int i;
1588
    CertCacheHeader* hdr = (CertCacheHeader*)mem;
1589
    byte*            current = (byte*)mem + sizeof(CertCacheHeader);
1590
    byte*            end     = (byte*)mem + sz;  /* don't go over */
1591
1592
    WOLFSSL_ENTER("CM_MemRestoreCertCache");
1593
1594
    /* Check memory available is bigger than cache header. */
1595
    if ((sz < (int)sizeof(CertCacheHeader)) || (current > end)) {
1596
        WOLFSSL_MSG("Cert Cache Memory buffer too small");
1597
        ret = BUFFER_E;
1598
    }
1599
1600
    /* Validate the cache header. */
1601
    if ((ret == WOLFSSL_SUCCESS) &&
1602
            ((hdr->version  != WOLFSSL_CACHE_CERT_VERSION) ||
1603
             (hdr->rows     != CA_TABLE_SIZE) ||
1604
             (hdr->signerSz != (int)sizeof(Signer)))) {
1605
        WOLFSSL_MSG("Cert Cache Memory header mismatch");
1606
        ret = CACHE_MATCH_ERROR;
1607
    }
1608
1609
    /* Lock CA table. */
1610
    if ((ret == WOLFSSL_SUCCESS) && (wc_LockMutex(&cm->caLock) != 0)) {
1611
        WOLFSSL_MSG("wc_LockMutex on caLock failed");
1612
        ret = BAD_MUTEX_E;
1613
    }
1614
1615
    if (ret == WOLFSSL_SUCCESS) {
1616
        /* Dispose of current CA certificate table. */
1617
        FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
1618
1619
        /* Each row. */
1620
        for (i = 0; i < CA_TABLE_SIZE; ++i) {
1621
            /* Restore a row from memory. */
1622
            int added = cm_restore_cert_row(cm, current, i, hdr->columns[i],
1623
                end);
1624
            /* Bail on error. */
1625
            if (added < 0) {
1626
                WOLFSSL_MSG("cm_restore_cert_row error");
1627
                ret = added;
1628
                break;
1629
            }
1630
            /* Update pointer to data of next row. */
1631
            current += added;
1632
        }
1633
1634
        /* Unlock CA table. */
1635
        wc_UnLockMutex(&cm->caLock);
1636
    }
1637
1638
    return ret;
1639
}
1640
1641
1642
/* Calculate size of CA certificate cache when persisted to memory.
1643
 *
1644
 * Locks CA table.
1645
 *
1646
 * @param [in] cm  Certificate manager.
1647
 * @return  Number of bytes on success.
1648
 * @return  BAD_MUTEX_E when locking fails.
1649
 */
1650
int CM_GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm)
1651
{
1652
    int ret;
1653
1654
    WOLFSSL_ENTER("CM_GetCertCacheMemSize");
1655
1656
    /* Lock CA table. */
1657
    if (wc_LockMutex(&cm->caLock) != 0) {
1658
        WOLFSSL_MSG("wc_LockMutex on caLock failed");
1659
        ret = BAD_MUTEX_E;
1660
    }
1661
    else {
1662
        /* Calculate memory size. */
1663
        ret = cm_get_cert_cache_mem_size(cm);
1664
1665
        /* Unlock CA table. */
1666
        wc_UnLockMutex(&cm->caLock);
1667
    }
1668
1669
    return ret;
1670
}
1671
1672
#endif /* PERSIST_CERT_CACHE */
1673
1674
/*******************************************************************************
1675
 * CRL handling
1676
 ******************************************************************************/
1677
1678
/* Enables/disables the use of CRLs when validating certificates.
1679
 *
1680
 * @param [in] cm       Certificate manager.
1681
 * @param [in] options  Options for using CRLs. Valid flags:
1682
 *                        WOLFSSL_CRL_CHECKALL, WOLFSSL_CRL_CHECK.
1683
 * @return  WOLFSSL_SUCCESS on success.
1684
 * @return  WOLFSSL_FAILURE when initializing the CRL object fails.
1685
 * @return  BAD_FUNC_ARG when cm is NULL.
1686
 * @return  MEMORY_E when dynamic memory allocation fails.
1687
 * @return  NOT_COMPILED_IN when the CRL feature is disabled.
1688
 */
1689
int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER* cm, int options)
1690
0
{
1691
0
    int ret = WOLFSSL_SUCCESS;
1692
1693
0
    WOLFSSL_ENTER("wolfSSL_CertManagerEnableCRL");
1694
1695
0
    (void)options;
1696
1697
    /* Validate parameters. */
1698
0
    if (cm == NULL) {
1699
0
        ret = BAD_FUNC_ARG;
1700
0
    }
1701
1702
#if defined(OPENSSL_COMPATIBLE_DEFAULTS)
1703
    /* If disabling then don't worry about whether CRL feature is enabled. */
1704
    if ((ret == WOLFSSL_SUCCESS) && (options == 0)) {
1705
        /* Disable leaf CRL check. */
1706
        cm->crlEnabled = 0;
1707
        /* Disable all CRL checks. */
1708
        cm->crlCheckAll = 0;
1709
    }
1710
    else
1711
#endif
1712
0
    if (ret == WOLFSSL_SUCCESS) {
1713
0
#ifndef HAVE_CRL
1714
        /* CRL feature not enabled. */
1715
0
        ret = NOT_COMPILED_IN;
1716
#else
1717
        /* Create CRL object if not present. */
1718
        if (cm->crl == NULL) {
1719
            /* Allocate memory for CRL object. */
1720
            cm->crl = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), cm->heap,
1721
                                            DYNAMIC_TYPE_CRL);
1722
            if (cm->crl == NULL) {
1723
                ret = MEMORY_E;
1724
            }
1725
            if (ret == WOLFSSL_SUCCESS) {
1726
                /* Reset fields of CRL object. */
1727
                XMEMSET(cm->crl, 0, sizeof(WOLFSSL_CRL));
1728
                /* Initialize CRL object. */
1729
                if (InitCRL(cm->crl, cm) != 0) {
1730
                    WOLFSSL_MSG("Init CRL failed");
1731
                    /* Dispose of CRL object - indicating dynamically allocated.
1732
                     */
1733
                    FreeCRL(cm->crl, 1);
1734
                    cm->crl = NULL;
1735
                    ret = WOLFSSL_FAILURE;
1736
                }
1737
            }
1738
        }
1739
1740
        if (ret == WOLFSSL_SUCCESS) {
1741
        #if defined(HAVE_CRL_IO) && defined(USE_WOLFSSL_IO)
1742
            /* Use built-in callback to lookup CRL from URL. */
1743
            cm->crl->crlIOCb = EmbedCrlLookup;
1744
        #endif
1745
        #if defined(OPENSSL_COMPATIBLE_DEFAULTS)
1746
            if ((options & WOLFSSL_CRL_CHECKALL) ||
1747
                (options & WOLFSSL_CRL_CHECK))
1748
        #endif
1749
            {
1750
                /* Enable leaf CRL check. */
1751
                cm->crlEnabled = 1;
1752
                if (options & WOLFSSL_CRL_CHECKALL) {
1753
                    /* Enable all CRL check. */
1754
                    cm->crlCheckAll = 1;
1755
                }
1756
            }
1757
        }
1758
#endif
1759
0
    }
1760
1761
0
    return ret;
1762
0
}
1763
1764
1765
/* Disables the CRL checks.
1766
 *
1767
 * @param [in] cm  Certificate manager.
1768
 * @return  WOLFSSL_SUCCESS on success.
1769
 * @return  BAD_FUNC_ARG when cm is NULL.
1770
 */
1771
int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER* cm)
1772
0
{
1773
0
    int ret = WOLFSSL_SUCCESS;
1774
1775
0
    WOLFSSL_ENTER("wolfSSL_CertManagerDisableCRL");
1776
1777
    /* Validate parameter. */
1778
0
    if (cm == NULL) {
1779
0
        ret = BAD_FUNC_ARG;
1780
0
    }
1781
0
    if (ret == WOLFSSL_SUCCESS) {
1782
        /* Disable CRL checking. */
1783
0
        cm->crlEnabled = 0;
1784
0
        cm->crlCheckAll = 0;
1785
0
    }
1786
1787
0
    return ret;
1788
0
}
1789
1790
#ifdef HAVE_CRL
1791
1792
/* Load CRL for use.
1793
 *
1794
 * @param [in] cm    Certificate manager.
1795
 * @param [in] buff  Buffer holding CRL.
1796
 * @param [in] sz    Size in bytes of CRL in buffer.
1797
 * @param [in] type  Format of encoding. Valid values:
1798
 *                     WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
1799
 * @return  WOLFSSL_SUCCESS on success.
1800
 * @return  BAD_FUNC_ARG when cm or buff is NULL or sz is negative or zero.
1801
 * @return  DUPE_ENTRY_E if the same or a newer CRL already exists in the cm.
1802
 * @return  WOLFSSL_FATAL_ERROR when creating CRL object fails.
1803
 */
1804
int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER* cm,
1805
    const unsigned char* buff, long sz, int type)
1806
{
1807
    int ret = WOLFSSL_SUCCESS;
1808
1809
    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRLBuffer");
1810
1811
    /* Validate parameters. */
1812
    if ((cm == NULL) || (buff == NULL) || (sz <= 0)) {
1813
        ret = BAD_FUNC_ARG;
1814
    }
1815
1816
    /* Create a CRL object if not available and enable CRL checking. */
1817
    if ((ret == WOLFSSL_SUCCESS) && (cm->crl == NULL) &&
1818
            (wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK) !=
1819
             WOLFSSL_SUCCESS)) {
1820
        WOLFSSL_MSG("Enable CRL failed");
1821
        ret = WOLFSSL_FATAL_ERROR;
1822
    }
1823
1824
    if (ret == WOLFSSL_SUCCESS) {
1825
        /* Load CRL into CRL object of the certificate manager. */
1826
        ret = BufferLoadCRL(cm->crl, buff, sz, type, VERIFY);
1827
    }
1828
1829
    return ret;
1830
}
1831
1832
/* Free the CRL object of the certificate manager.
1833
 *
1834
 * @param [in] cm  Certificate manager.
1835
 * @return  WOLFSSL_SUCCESS on success.
1836
 * @return  BAD_FUNC_ARG when cm is NULL.
1837
 */
1838
int wolfSSL_CertManagerFreeCRL(WOLFSSL_CERT_MANAGER* cm)
1839
{
1840
    int ret = WOLFSSL_SUCCESS;
1841
1842
    WOLFSSL_ENTER("wolfSSL_CertManagerFreeCRL");
1843
1844
    /* Validate parameter. */
1845
    if (cm == NULL) {
1846
        ret = BAD_FUNC_ARG;
1847
    }
1848
    /* Check whether CRL object exists. */
1849
    if ((ret == WOLFSSL_SUCCESS) && (cm->crl != NULL)) {
1850
        /* Dispose of CRL object - indicating dynamically allocated. */
1851
        FreeCRL(cm->crl, 1);
1852
        cm->crl = NULL;
1853
    }
1854
1855
    return ret;
1856
}
1857
1858
/* Check DER encoded certificate against CRLs if checking enabled.
1859
 *
1860
 * @param [in] cm   Certificate manager.
1861
 * @param [in] der  DER encode certificate.
1862
 * @param [in] sz   Size in bytes of DER encode certificate.
1863
 * @return  WOLFSSL_SUCCESS on success.
1864
 * @return  BAD_FUNC_ARG when cm or der is NULL or sz is negative or zero.
1865
 * @return  MEMORY_E when dynamic memory allocation fails.
1866
 */
1867
int wolfSSL_CertManagerCheckCRL(WOLFSSL_CERT_MANAGER* cm,
1868
    const unsigned char* der, int sz)
1869
{
1870
    int ret = 0;
1871
    WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
1872
1873
    WOLFSSL_ENTER("wolfSSL_CertManagerCheckCRL");
1874
1875
    /* Validate parameters. */
1876
    if ((cm == NULL) || (der == NULL) || (sz <= 0)) {
1877
        ret = BAD_FUNC_ARG;
1878
    }
1879
1880
    /* Check if CRL checking enabled. */
1881
    if ((ret == 0) && cm->crlEnabled) {
1882
        /* Allocate memory for decoded certificate. */
1883
        WC_ALLOC_VAR_EX(cert, DecodedCert, 1, NULL, DYNAMIC_TYPE_DCERT,
1884
            ret=MEMORY_E);
1885
        if (WC_VAR_OK(cert))
1886
        {
1887
            /* Initialize decoded certificate with buffer. */
1888
            InitDecodedCert(cert, der, (word32)sz, NULL);
1889
1890
            /* Parse certificate and perform CRL checks. */
1891
            ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_CRL, cm, NULL);
1892
            if (ret != 0) {
1893
                WOLFSSL_MSG("ParseCert failed");
1894
            }
1895
            /* Do CRL checks with decoded certificate. */
1896
            else if ((ret = CheckCertCRL(cm->crl, cert)) != 0) {
1897
                WOLFSSL_MSG("CheckCertCRL failed");
1898
            }
1899
1900
            /* Dispose of dynamically allocated memory. */
1901
            FreeDecodedCert(cert);
1902
            WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
1903
        }
1904
    }
1905
1906
    return (ret == 0) ? WOLFSSL_SUCCESS : ret;
1907
}
1908
1909
/* Set the missing CRL callback.
1910
 *
1911
 * @param [in] cm  Certificate manager.
1912
 * @param [in] cb  Missing CRL callback.
1913
 * @return  WOLFSSL_SUCCESS on success.
1914
 * @return  BAD_FUNC_ARG when cm is NULL.
1915
 */
1916
int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER* cm, CbMissingCRL cb)
1917
{
1918
    int ret = WOLFSSL_SUCCESS;
1919
1920
    WOLFSSL_ENTER("wolfSSL_CertManagerSetCRL_Cb");
1921
1922
    /* Validate parameters. */
1923
    if (cm == NULL) {
1924
        ret = BAD_FUNC_ARG;
1925
    }
1926
    if (ret == WOLFSSL_SUCCESS) {
1927
        /* Store callback. */
1928
        cm->cbMissingCRL = cb;
1929
    }
1930
1931
    return ret;
1932
}
1933
1934
int wolfSSL_CertManagerSetCRL_ErrorCb(WOLFSSL_CERT_MANAGER* cm, crlErrorCb cb,
1935
                                      void* ctx)
1936
{
1937
    int ret = WOLFSSL_SUCCESS;
1938
1939
    WOLFSSL_ENTER("wolfSSL_CertManagerSetCRL_Cb");
1940
1941
    /* Validate parameters. */
1942
    if (cm == NULL) {
1943
        ret = BAD_FUNC_ARG;
1944
    }
1945
    if (ret == WOLFSSL_SUCCESS) {
1946
        /* Store callback. */
1947
        cm->crlCb = cb;
1948
        cm->crlCbCtx = ctx;
1949
    }
1950
1951
    return ret;
1952
}
1953
1954
#ifdef HAVE_CRL_UPDATE_CB
1955
int wolfSSL_CertManagerGetCRLInfo(WOLFSSL_CERT_MANAGER* cm, CrlInfo* info,
1956
    const byte* buff, long sz, int type)
1957
{
1958
    return GetCRLInfo(cm->crl, info, buff, sz, type);
1959
}
1960
1961
/* Set the callback to be called when a CRL entry has
1962
 * been updated (new entry had the same issuer hash and
1963
 * a newer CRL number).
1964
 *
1965
 * @param [in] cm  Certificate manager.
1966
 * @param [in] cb  CRL update callback.
1967
 * @return  WOLFSSL_SUCCESS on success.
1968
 * @return  BAD_FUNC_ARG when cm is NULL.
1969
 */
1970
int wolfSSL_CertManagerSetCRLUpdate_Cb(WOLFSSL_CERT_MANAGER* cm, CbUpdateCRL cb)
1971
{
1972
    int ret = WOLFSSL_SUCCESS;
1973
1974
    WOLFSSL_ENTER("wolfSSL_CertManagerSetCRLUpdate_Cb");
1975
1976
    /* Validate parameters. */
1977
    if (cm == NULL) {
1978
        ret = BAD_FUNC_ARG;
1979
    }
1980
    if (ret == WOLFSSL_SUCCESS) {
1981
        /* Store callback. */
1982
        cm->cbUpdateCRL = cb;
1983
    }
1984
1985
    return ret;
1986
}
1987
#endif
1988
1989
#ifdef HAVE_CRL_IO
1990
/* Set the CRL I/O callback.
1991
 *
1992
 * @param [in] cm  Certificate manager.
1993
 * @param [in] cb  CRL I/O callback.
1994
 * @return  WOLFSSL_SUCCESS on success.
1995
 * @return  BAD_FUNC_ARG when cm is NULL.
1996
 */
1997
int wolfSSL_CertManagerSetCRL_IOCb(WOLFSSL_CERT_MANAGER* cm, CbCrlIO cb)
1998
{
1999
    int ret = WOLFSSL_SUCCESS;
2000
2001
    /* Validate parameters. */
2002
    if (cm == NULL) {
2003
        ret = BAD_FUNC_ARG;
2004
    }
2005
    if ((ret == WOLFSSL_SUCCESS) && (cm->crl != NULL)) {
2006
        /* Store callback. */
2007
        cm->crl->crlIOCb = cb;
2008
    }
2009
2010
    return ret;
2011
}
2012
#endif
2013
2014
#ifndef NO_FILESYSTEM
2015
/* Load CRL/s from path with the option of monitoring for changes.
2016
 *
2017
 * @param [in] cm       Certificate manager.
2018
 * @param [in] path     Path to a directory containing CRLs.
2019
 * @param [in] type     Format of encoding. Valid values:
2020
 *                        WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
2021
 * @param [in] monitor  Whether to monitor path for changes to files.
2022
 * @return  WOLFSSL_SUCCESS on success.
2023
 * @return  BAD_FUNC_ARG when cm or path is NULL.
2024
 * @return  WOLFSSL_FATAL_ERROR when enabling CRLs fails.
2025
 */
2026
int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER* cm, const char* path,
2027
    int type, int monitor)
2028
{
2029
    int ret = WOLFSSL_SUCCESS;
2030
2031
    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRL");
2032
2033
    /* Validate parameters. */
2034
    if ((cm == NULL) || (path == NULL)) {
2035
        ret = BAD_FUNC_ARG;
2036
    }
2037
2038
    /* Create a CRL object if not available. */
2039
    if ((ret == WOLFSSL_SUCCESS) && (cm->crl == NULL) &&
2040
            (wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK) !=
2041
             WOLFSSL_SUCCESS)) {
2042
        WOLFSSL_MSG("Enable CRL failed");
2043
        ret = WOLFSSL_FATAL_ERROR;
2044
    }
2045
2046
    if (ret == WOLFSSL_SUCCESS) {
2047
        /* Load CRLs from path into CRL object of certificate manager. */
2048
        ret = LoadCRL(cm->crl, path, type, monitor);
2049
    }
2050
2051
    return ret;
2052
}
2053
2054
/* Load CRL from file.
2055
 *
2056
 * @param [in] cm    Certificate manager.
2057
 * @param [in] file  Path to a directory containing CRLs.
2058
 * @param [in] type  Format of encoding. Valid values:
2059
 *                       WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
2060
 * @return  WOLFSSL_SUCCESS on success.
2061
 * @return  BAD_FUNC_ARG when cm or file is NULL.
2062
 * @return  WOLFSSL_FATAL_ERROR when enabling CRLs fails.
2063
 */
2064
int wolfSSL_CertManagerLoadCRLFile(WOLFSSL_CERT_MANAGER* cm, const char* file,
2065
    int type)
2066
{
2067
    int ret = WOLFSSL_SUCCESS;
2068
2069
    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRLFile");
2070
2071
    /* Validate parameters. */
2072
    if ((cm == NULL) || (file == NULL)) {
2073
        ret = BAD_FUNC_ARG;
2074
    }
2075
2076
    /* Create a CRL object if not available. */
2077
    if ((ret == WOLFSSL_SUCCESS) && (cm->crl == NULL) &&
2078
            (wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK) !=
2079
             WOLFSSL_SUCCESS)) {
2080
        WOLFSSL_MSG("Enable CRL failed");
2081
        ret = WOLFSSL_FATAL_ERROR;
2082
    }
2083
2084
    if (ret == WOLFSSL_SUCCESS) {
2085
        /* Load CRL file into CRL object of certificate manager. */
2086
        ret = ProcessFile(NULL, file, type, CRL_TYPE, NULL, 0, cm->crl, VERIFY);
2087
    }
2088
2089
    return ret;
2090
}
2091
#endif /* !NO_FILESYSTEM */
2092
2093
#endif /* HAVE_CRL */
2094
2095
/*******************************************************************************
2096
 * OCSP handling
2097
 ******************************************************************************/
2098
2099
/* Enables OCSP when validating certificates and sets options.
2100
 *
2101
 * @param [in] cm       Certificate manager.
2102
 * @param [in] options  Options for using OCSP. Valid flags:
2103
 *                        WOLFSSL_OCSP_URL_OVERRIDE, WOLFSSL_OCSP_NO_NONCE,
2104
 *                        WOLFSSL_OCSP_CHECKALL.
2105
 * @return  WOLFSSL_SUCCESS on success.
2106
 * @return  0 when initializing the OCSP object fails.
2107
 * @return  BAD_FUNC_ARG when cm is NULL.
2108
 * @return  MEMORY_E when dynamic memory allocation fails.
2109
 * @return  NOT_COMPILED_IN when the OCSP feature is disabled.
2110
 */
2111
int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER* cm, int options)
2112
0
{
2113
0
    int ret = WOLFSSL_SUCCESS;
2114
2115
0
    (void)options;
2116
2117
0
    WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSP");
2118
2119
    /* Validate parameters. */
2120
0
    if (cm == NULL) {
2121
0
        ret = BAD_FUNC_ARG;
2122
0
    }
2123
2124
#ifndef HAVE_OCSP
2125
    if (ret == WOLFSSL_SUCCESS) {
2126
        /* OCSP feature not enabled. */
2127
        ret = NOT_COMPILED_IN;
2128
    }
2129
#else
2130
0
    if (ret == WOLFSSL_SUCCESS) {
2131
        /* Check whether OCSP object is available. */
2132
0
        if (cm->ocsp == NULL) {
2133
            /* Allocate memory for OCSP object. */
2134
0
            cm->ocsp = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP), cm->heap,
2135
0
                DYNAMIC_TYPE_OCSP);
2136
0
            if (cm->ocsp == NULL) {
2137
0
                ret = MEMORY_E;
2138
0
            }
2139
0
            if (ret == WOLFSSL_SUCCESS) {
2140
                /* Reset the fields of the OCSP object. */
2141
0
                XMEMSET(cm->ocsp, 0, sizeof(WOLFSSL_OCSP));
2142
                /* Initialize the OCSP object. */
2143
0
                if (InitOCSP(cm->ocsp, cm) != 0) {
2144
0
                    WOLFSSL_MSG("Init OCSP failed");
2145
                    /* Dispose of OCSP object - indicating dynamically
2146
                     * allocated. */
2147
0
                    FreeOCSP(cm->ocsp, 1);
2148
0
                    cm->ocsp = NULL;
2149
0
                    ret = 0;
2150
0
                }
2151
0
            }
2152
0
        }
2153
0
    }
2154
0
    if (ret == WOLFSSL_SUCCESS) {
2155
        /* Enable OCSP checking. */
2156
0
        cm->ocspEnabled = 1;
2157
        /* Enable URL override if requested. */
2158
0
        if (options & WOLFSSL_OCSP_URL_OVERRIDE) {
2159
0
            cm->ocspUseOverrideURL = 1;
2160
0
        }
2161
        /* Set nonce option for creating OCSP requests. */
2162
0
        cm->ocspSendNonce = (options & WOLFSSL_OCSP_NO_NONCE) !=
2163
0
            WOLFSSL_OCSP_NO_NONCE;
2164
        /* Set all OCSP checks on if requested. */
2165
0
        if (options & WOLFSSL_OCSP_CHECKALL) {
2166
0
            cm->ocspCheckAll = 1;
2167
0
        }
2168
0
    #ifndef WOLFSSL_USER_IO
2169
        /* Set built-in OCSP lookup. */
2170
0
        cm->ocspIOCb = EmbedOcspLookup;
2171
0
        cm->ocspRespFreeCb = EmbedOcspRespFree;
2172
0
        cm->ocspIOCtx = cm->heap;
2173
0
    #endif /* WOLFSSL_USER_IO */
2174
0
    }
2175
0
#endif /* HAVE_OCSP */
2176
2177
0
    return ret;
2178
0
}
2179
2180
/* Disables the OCSP checks.
2181
 *
2182
 * @param [in] cm  Certificate manager.
2183
 * @return  WOLFSSL_SUCCESS on success.
2184
 * @return  BAD_FUNC_ARG when cm is NULL.
2185
 */
2186
int wolfSSL_CertManagerDisableOCSP(WOLFSSL_CERT_MANAGER* cm)
2187
0
{
2188
0
    int ret = WOLFSSL_SUCCESS;
2189
2190
0
    WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSP");
2191
2192
    /* Validate parameter. */
2193
0
    if (cm == NULL) {
2194
0
        ret = BAD_FUNC_ARG;
2195
0
    }
2196
0
    if (ret == WOLFSSL_SUCCESS) {
2197
        /* Disable use of OCSP with certificate validation. */
2198
0
        cm->ocspEnabled = 0;
2199
0
    }
2200
2201
0
    return ret;
2202
0
}
2203
2204
/* Enables OCSP stapling with certificates in manager.
2205
 *
2206
 * @param [in] cm       Certificate manager.
2207
 * @param [in] options  Options for using OCSP. Valid flags:
2208
 *                        WOLFSSL_OCSP_URL_OVERRIDE, WOLFSSL_OCSP_NO_NONCE,
2209
 *                        WOLFSSL_OCSP_CHECKALL.
2210
 * @return  WOLFSSL_SUCCESS on success.
2211
 * @return  0 when initializing the OCSP stapling object fails.
2212
 * @return  BAD_FUNC_ARG when cm is NULL.
2213
 * @return  MEMORY_E when dynamic memory allocation fails.
2214
 * @return  NOT_COMPILED_IN when the OCSP stapling feature is disabled.
2215
 */
2216
int wolfSSL_CertManagerEnableOCSPStapling(WOLFSSL_CERT_MANAGER* cm)
2217
{
2218
    int ret = WOLFSSL_SUCCESS;
2219
2220
    WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSPStapling");
2221
2222
    /* Validate parameters. */
2223
    if (cm == NULL) {
2224
        ret = BAD_FUNC_ARG;
2225
    }
2226
2227
#if !defined(HAVE_CERTIFICATE_STATUS_REQUEST) && \
2228
    !defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
2229
    if (ret == WOLFSSL_SUCCESS) {
2230
        /* OCSP stapling feature not enabled. */
2231
        ret = NOT_COMPILED_IN;
2232
    }
2233
#else
2234
#ifndef NO_WOLFSSL_SERVER
2235
    if (ret == WOLFSSL_SUCCESS) {
2236
        /* Check whether OCSP object is available. */
2237
        if (cm->ocsp_stapling == NULL) {
2238
            /* Allocate memory for OCSP stapling object. */
2239
            cm->ocsp_stapling = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP),
2240
                cm->heap, DYNAMIC_TYPE_OCSP);
2241
            if (cm->ocsp_stapling == NULL) {
2242
                ret = MEMORY_E;
2243
            }
2244
            if (ret == WOLFSSL_SUCCESS) {
2245
                /* Reset the fields of the OCSP object. */
2246
                XMEMSET(cm->ocsp_stapling, 0, sizeof(WOLFSSL_OCSP));
2247
                /* Initialize the OCSP stapling object. */
2248
                if (InitOCSP(cm->ocsp_stapling, cm) != 0) {
2249
                    WOLFSSL_MSG("Init OCSP failed");
2250
                    /* Dispose of OCSP stapling object - indicating dynamically
2251
                     * allocated. */
2252
                    FreeOCSP(cm->ocsp_stapling, 1);
2253
                    cm->ocsp_stapling = NULL;
2254
                    ret = 0;
2255
                }
2256
            }
2257
        }
2258
    }
2259
#ifndef WOLFSSL_USER_IO
2260
    if (ret == WOLFSSL_SUCCESS) {
2261
        /* Set built-in OCSP lookup. */
2262
        cm->ocspIOCb = EmbedOcspLookup;
2263
        cm->ocspRespFreeCb = EmbedOcspRespFree;
2264
        cm->ocspIOCtx = cm->heap;
2265
    }
2266
#endif /* WOLFSSL_USER_IO */
2267
#endif /* NO_WOLFSSL_SERVER */
2268
    if (ret == WOLFSSL_SUCCESS) {
2269
        /* Enable OCSP stapling. */
2270
        cm->ocspStaplingEnabled = 1;
2271
    }
2272
#endif /* HAVE_CERTIFICATE_STATUS_REQUEST ||
2273
        * HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
2274
2275
    return ret;
2276
}
2277
2278
/* Disables OCSP Stapling.
2279
 *
2280
 * @param [in] cm  Certificate manager.
2281
 * @return  WOLFSSL_SUCCESS on success.
2282
 * @return  BAD_FUNC_ARG when cm is NULL.
2283
 */
2284
int wolfSSL_CertManagerDisableOCSPStapling(WOLFSSL_CERT_MANAGER* cm)
2285
0
{
2286
0
    int ret = WOLFSSL_SUCCESS;
2287
2288
0
    WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSPStapling");
2289
2290
    /* Validate parameter. */
2291
0
    if (cm == NULL) {
2292
0
        ret = BAD_FUNC_ARG;
2293
0
    }
2294
0
    if (ret == WOLFSSL_SUCCESS) {
2295
    #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
2296
        defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
2297
        /* Disable use of OCSP Stapling. */
2298
        cm->ocspStaplingEnabled = 0;
2299
    #else
2300
        /* OCSP stapling feature not enabled. */
2301
0
        ret = NOT_COMPILED_IN;
2302
0
    #endif
2303
0
    }
2304
2305
0
    return ret;
2306
0
}
2307
2308
/* Enable the must use OCSP Stapling option.
2309
 *
2310
 * @param [in] cm  Certificate manager.
2311
 * @return  WOLFSSL_SUCCESS on success.
2312
 * @return  BAD_FUNC_ARG when cm is NULL.
2313
 */
2314
int wolfSSL_CertManagerEnableOCSPMustStaple(WOLFSSL_CERT_MANAGER* cm)
2315
0
{
2316
0
    int ret = WOLFSSL_SUCCESS;
2317
2318
0
    WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSPMustStaple");
2319
2320
    /* Validate parameter. */
2321
0
    if (cm == NULL) {
2322
0
        ret = BAD_FUNC_ARG;
2323
0
    }
2324
0
    if (ret == WOLFSSL_SUCCESS) {
2325
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
2326
    defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
2327
    #ifndef NO_WOLFSSL_CLIENT
2328
        /* Enable must use OCSP Stapling option. */
2329
        cm->ocspMustStaple = 1;
2330
    #endif
2331
#else
2332
        /* OCSP stapling feature not enabled. */
2333
0
        ret = NOT_COMPILED_IN;
2334
0
#endif
2335
0
    }
2336
2337
0
    return ret;
2338
0
}
2339
2340
/* Disable the must use OCSP Stapling option.
2341
 *
2342
 * @param [in] cm  Certificate manager.
2343
 * @return  WOLFSSL_SUCCESS on success.
2344
 * @return  BAD_FUNC_ARG when cm is NULL.
2345
 */
2346
int wolfSSL_CertManagerDisableOCSPMustStaple(WOLFSSL_CERT_MANAGER* cm)
2347
0
{
2348
0
    int ret = WOLFSSL_SUCCESS;
2349
2350
0
    WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSPMustStaple");
2351
2352
    /* Validate parameter. */
2353
0
    if (cm == NULL) {
2354
0
        ret = BAD_FUNC_ARG;
2355
0
    }
2356
2357
0
    if (ret == WOLFSSL_SUCCESS) {
2358
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
2359
    defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
2360
    #ifndef NO_WOLFSSL_CLIENT
2361
        /* Disable must use OCSP Stapling option. */
2362
        cm->ocspMustStaple = 0;
2363
    #endif
2364
#else
2365
        /* OCSP stapling feature not enabled. */
2366
0
        ret = NOT_COMPILED_IN;
2367
0
#endif
2368
0
    }
2369
2370
0
    return ret;
2371
0
}
2372
2373
#ifdef HAVE_OCSP
2374
/* Check DER encoded certificate against with OCSP if checking enabled.
2375
 *
2376
 * @param [in] cm   Certificate manager.
2377
 * @param [in] der  DER encode certificate.
2378
 * @param [in] sz   Size in bytes of DER encode certificate.
2379
 * @return  WOLFSSL_SUCCESS on success.
2380
 * @return  BAD_FUNC_ARG when cm or der is NULL or sz is negative or 0.
2381
 * @return  MEMORY_E when dynamic memory allocation fails.
2382
 */
2383
int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER* cm,
2384
    const unsigned char* der, int sz)
2385
0
{
2386
0
    int ret = 0;
2387
0
    WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
2388
2389
0
    WOLFSSL_ENTER("wolfSSL_CertManagerCheckOCSP");
2390
2391
    /* Validate parameters. */
2392
0
    if ((cm == NULL) || (der == NULL) || (sz <= 0)) {
2393
0
        ret = BAD_FUNC_ARG;
2394
0
    }
2395
2396
    /* Check if OCSP checking enabled. */
2397
0
    if ((ret == 0) && cm->ocspEnabled) {
2398
        /* Allocate memory for decoded certificate. */
2399
0
        WC_ALLOC_VAR_EX(cert, DecodedCert, 1, cm->heap, DYNAMIC_TYPE_DCERT,
2400
0
            ret=MEMORY_E);
2401
0
        if (WC_VAR_OK(cert))
2402
0
        {
2403
            /* Initialize decoded certificate with buffer. */
2404
0
            InitDecodedCert(cert, der, (word32)sz, NULL);
2405
2406
            /* Parse certificate and perform CRL checks. */
2407
0
            ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_OCSP, cm, NULL);
2408
0
            if (ret != 0) {
2409
0
                WOLFSSL_MSG("ParseCert failed");
2410
0
            }
2411
            /* Do OCSP checks with decoded certificate. */
2412
0
            else if ((ret = CheckCertOCSP(cm->ocsp, cert)) != 0) {
2413
0
                WOLFSSL_MSG("CheckCertOCSP failed");
2414
0
            }
2415
2416
            /* Dispose of dynamically allocated memory. */
2417
0
            FreeDecodedCert(cert);
2418
0
            WC_FREE_VAR_EX(cert, cm->heap, DYNAMIC_TYPE_DCERT);
2419
0
        }
2420
0
    }
2421
2422
0
    return (ret == 0) ? WOLFSSL_SUCCESS : ret;
2423
0
}
2424
2425
/* Check OCSP response.
2426
 *
2427
 * @param [in] cm              Certificate manager.
2428
 * @param [in] response        Buffer holding OCSP response.
2429
 * @param [in] responseSz      Size in bytes of OCSP response.
2430
 * @param [in] responseBuffer  Buffer to copy response into.
2431
 * @param [in] status          Place to store certificate status.
2432
 * @param [in] entry           Place to store OCSP entry.
2433
 * @param [in] ocspRequest     OCSP request to match with response.
2434
 * @return  WOLFSSL_SUCCESS on success.
2435
 * @return  BAD_FUNC_ARG when cm or response is NULL.
2436
 */
2437
int wolfSSL_CertManagerCheckOCSPResponse(WOLFSSL_CERT_MANAGER *cm,
2438
    byte *response, int responseSz, buffer *responseBuffer,
2439
    CertStatus *status, OcspEntry *entry, OcspRequest *ocspRequest)
2440
0
{
2441
0
    int ret = 0;
2442
2443
0
    WOLFSSL_ENTER("wolfSSL_CertManagerCheckOCSPResponse");
2444
2445
    /* Validate parameters. */
2446
0
    if ((cm == NULL) || (response == NULL)) {
2447
0
        ret = BAD_FUNC_ARG;
2448
0
    }
2449
0
    if ((ret == 0) && cm->ocspEnabled) {
2450
        /* Check OCSP response with OCSP object from certificate manager. */
2451
0
        ret = CheckOcspResponse(cm->ocsp, response, responseSz, responseBuffer,
2452
0
            status, entry, ocspRequest, NULL);
2453
0
    }
2454
2455
0
    return (ret == 0) ? WOLFSSL_SUCCESS : ret;
2456
0
}
2457
2458
/* Set the OCSP override URL.
2459
 *
2460
 * @param [in] cm   Certificate manager.
2461
 * @param [in] url  URL to get an OCSP response from.
2462
 * @return  WOLFSSL_SUCCESS on success.
2463
 * @return  BAD_FUNC_ARG when cm is NULL.
2464
 * @return  MEMORY_E when dynamic memory allocation fails.
2465
 */
2466
int wolfSSL_CertManagerSetOCSPOverrideURL(WOLFSSL_CERT_MANAGER* cm,
2467
    const char* url)
2468
0
{
2469
0
    int ret = WOLFSSL_SUCCESS;
2470
2471
0
    WOLFSSL_ENTER("wolfSSL_CertManagerSetOCSPOverrideURL");
2472
2473
    /* Validate parameters. */
2474
0
    if (cm == NULL) {
2475
0
        ret = BAD_FUNC_ARG;
2476
0
    }
2477
2478
0
    if (ret == WOLFSSL_SUCCESS) {
2479
        /* Dispose of old URL. */
2480
0
        XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL);
2481
0
        if (url != NULL) {
2482
            /* Calculate size of URL string. Include terminator character. */
2483
0
            int urlSz = (int)XSTRLEN(url) + 1;
2484
            /* Allocate memory for URL to be copied into. */
2485
0
            cm->ocspOverrideURL = (char*)XMALLOC((size_t)urlSz, cm->heap,
2486
0
                DYNAMIC_TYPE_URL);
2487
0
            if (cm->ocspOverrideURL == NULL) {
2488
0
                ret = MEMORY_E;
2489
0
            }
2490
0
            if (ret == WOLFSSL_SUCCESS) {
2491
                /* Copy URL into certificate manager. */
2492
0
                XMEMCPY(cm->ocspOverrideURL, url, (size_t)urlSz);
2493
0
            }
2494
0
        }
2495
0
        else {
2496
            /* No URL to set so make it NULL. */
2497
0
            cm->ocspOverrideURL = NULL;
2498
0
        }
2499
0
    }
2500
2501
0
    return ret;
2502
0
}
2503
2504
/* Set the OCSP I/O callback, OCSP response free callback and related data.
2505
 *
2506
 * @param [in] cm          Certificate manager.
2507
 * @param [in] ioCb        OCSP callback.
2508
 * @param [in] respFreeCb  Callback to free OCSP response buffer.
2509
 * @param [in] ioCbCtx     Context data to pass to OCSP callbacks.
2510
 * @return  WOLFSSL_SUCCESS on success.
2511
 * @return  BAD_FUNC_ARG when cm is NULL.
2512
 */
2513
int wolfSSL_CertManagerSetOCSP_Cb(WOLFSSL_CERT_MANAGER* cm, CbOCSPIO ioCb,
2514
    CbOCSPRespFree respFreeCb, void* ioCbCtx)
2515
0
{
2516
0
    int ret = WOLFSSL_SUCCESS;
2517
2518
0
    WOLFSSL_ENTER("wolfSSL_CertManagerSetOCSP_Cb");
2519
2520
    /* Validate parameters. */
2521
0
    if (cm == NULL) {
2522
0
        ret = BAD_FUNC_ARG;
2523
0
    }
2524
0
    if (ret == WOLFSSL_SUCCESS) {
2525
        /* Set callbacks and data into certificate manager. */
2526
0
        cm->ocspIOCb = ioCb;
2527
0
        cm->ocspRespFreeCb = respFreeCb;
2528
0
        cm->ocspIOCtx = ioCbCtx;
2529
0
    }
2530
2531
0
    return ret;
2532
0
}
2533
2534
#endif /* HAVE_OCSP */
2535
2536
/******************************************************************************
2537
 * Internal APIs that use WOLFSSL_CERT_MANAGER
2538
 ******************************************************************************/
2539
2540
/* hash is the SHA digest of name, just use first 32 bits as hash */
2541
static WC_INLINE word32 HashSigner(const byte* hash)
2542
6.29k
{
2543
6.29k
    return MakeWordFromHash(hash) % CA_TABLE_SIZE;
2544
6.29k
}
2545
2546
2547
/* does CA already exist on signer list */
2548
int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash)
2549
4.07k
{
2550
4.07k
    Signer* signers;
2551
4.07k
    int     ret = 0;
2552
4.07k
    word32  row;
2553
2554
4.07k
    if (cm == NULL || hash == NULL) {
2555
0
        return ret;
2556
0
    }
2557
2558
4.07k
    row = HashSigner(hash);
2559
2560
4.07k
    if (wc_LockMutex(&cm->caLock) != 0) {
2561
0
        return ret;
2562
0
    }
2563
4.07k
    signers = cm->caTable[row];
2564
4.69k
    while (signers) {
2565
880
        byte* subjectHash;
2566
2567
880
    #ifndef NO_SKID
2568
880
        subjectHash = signers->subjectKeyIdHash;
2569
    #else
2570
        subjectHash = signers->subjectNameHash;
2571
    #endif
2572
2573
880
        if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
2574
256
            ret = 1; /* success */
2575
256
            break;
2576
256
        }
2577
624
        signers = signers->next;
2578
624
    }
2579
4.07k
    wc_UnLockMutex(&cm->caLock);
2580
2581
4.07k
    return ret;
2582
4.07k
}
2583
2584
#ifdef WOLFSSL_TRUST_PEER_CERT
2585
/* hash is the SHA digest of name, just use first 32 bits as hash */
2586
static WC_INLINE word32 TrustedPeerHashSigner(const byte* hash)
2587
{
2588
    return MakeWordFromHash(hash) % TP_TABLE_SIZE;
2589
}
2590
2591
/* does trusted peer already exist on signer list */
2592
int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DecodedCert* cert)
2593
{
2594
    TrustedPeerCert* tp;
2595
    int     ret = 0;
2596
    word32  row = TrustedPeerHashSigner(cert->subjectHash);
2597
2598
    if (wc_LockMutex(&cm->tpLock) != 0)
2599
        return  ret;
2600
    tp = cm->tpTable[row];
2601
    while (tp) {
2602
        if ((XMEMCMP(cert->subjectHash, tp->subjectNameHash,
2603
                SIGNER_DIGEST_SIZE) == 0)
2604
    #ifndef WOLFSSL_NO_ISSUERHASH_TDPEER
2605
         && (XMEMCMP(cert->issuerHash, tp->issuerHash,
2606
                SIGNER_DIGEST_SIZE) == 0)
2607
    #endif
2608
        )
2609
            ret = 1;
2610
    #ifndef NO_SKID
2611
        if (cert->extSubjKeyIdSet) {
2612
            /* Compare SKID as well if available */
2613
            if (ret == 1 && XMEMCMP(cert->extSubjKeyId, tp->subjectKeyIdHash,
2614
                    SIGNER_DIGEST_SIZE) != 0)
2615
                ret = 0;
2616
        }
2617
    #endif
2618
        if (ret == 1)
2619
            break;
2620
        tp = tp->next;
2621
    }
2622
    wc_UnLockMutex(&cm->tpLock);
2623
2624
    return ret;
2625
}
2626
2627
/* return Trusted Peer if found, otherwise NULL
2628
    type is what to match on
2629
 */
2630
TrustedPeerCert* GetTrustedPeer(void* vp, DecodedCert* cert)
2631
{
2632
    WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
2633
    TrustedPeerCert* ret = NULL;
2634
    TrustedPeerCert* tp  = NULL;
2635
    word32  row;
2636
2637
    if (cm == NULL || cert == NULL)
2638
        return NULL;
2639
2640
    row = TrustedPeerHashSigner(cert->subjectHash);
2641
2642
    if (wc_LockMutex(&cm->tpLock) != 0)
2643
        return ret;
2644
2645
    tp = cm->tpTable[row];
2646
    while (tp) {
2647
        if ((XMEMCMP(cert->subjectHash, tp->subjectNameHash,
2648
                SIGNER_DIGEST_SIZE) == 0)
2649
        #ifndef WOLFSSL_NO_ISSUERHASH_TDPEER
2650
             && (XMEMCMP(cert->issuerHash, tp->issuerHash,
2651
                SIGNER_DIGEST_SIZE) == 0)
2652
        #endif
2653
            )
2654
            ret = tp;
2655
    #ifndef NO_SKID
2656
        if (cert->extSubjKeyIdSet) {
2657
            /* Compare SKID as well if available */
2658
            if (ret != NULL && XMEMCMP(cert->extSubjKeyId, tp->subjectKeyIdHash,
2659
                    SIGNER_DIGEST_SIZE) != 0)
2660
                ret = NULL;
2661
        }
2662
    #endif
2663
        if (ret != NULL)
2664
            break;
2665
        tp = tp->next;
2666
    }
2667
    wc_UnLockMutex(&cm->tpLock);
2668
2669
    return ret;
2670
}
2671
2672
2673
int MatchTrustedPeer(TrustedPeerCert* tp, DecodedCert* cert)
2674
{
2675
    if (tp == NULL || cert == NULL)
2676
        return BAD_FUNC_ARG;
2677
2678
    /* subject key id or subject hash has been compared when searching
2679
       tpTable for the cert from function GetTrustedPeer */
2680
2681
    /* compare signatures */
2682
    if (tp->sigLen == cert->sigLength) {
2683
        if (XMEMCMP(tp->sig, cert->signature, cert->sigLength)) {
2684
            return WOLFSSL_FAILURE;
2685
        }
2686
    }
2687
    else {
2688
        return WOLFSSL_FAILURE;
2689
    }
2690
2691
    return WOLFSSL_SUCCESS;
2692
}
2693
#endif /* WOLFSSL_TRUST_PEER_CERT */
2694
2695
/* return CA if found, otherwise NULL */
2696
Signer* GetCA(void* vp, byte* hash)
2697
1.82k
{
2698
1.82k
    WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
2699
1.82k
    Signer* ret = NULL;
2700
1.82k
    Signer* signers;
2701
1.82k
    word32  row = 0;
2702
2703
1.82k
    if (cm == NULL || hash == NULL)
2704
56
        return NULL;
2705
2706
1.76k
    row = HashSigner(hash);
2707
2708
1.76k
    if (wc_LockMutex(&cm->caLock) != 0)
2709
0
        return ret;
2710
2711
1.76k
    signers = cm->caTable[row];
2712
2.68k
    while (signers) {
2713
1.12k
        byte* subjectHash;
2714
1.12k
        #ifndef NO_SKID
2715
1.12k
            subjectHash = signers->subjectKeyIdHash;
2716
        #else
2717
            subjectHash = signers->subjectNameHash;
2718
        #endif
2719
1.12k
        if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
2720
204
            ret = signers;
2721
204
            break;
2722
204
        }
2723
917
        signers = signers->next;
2724
917
    }
2725
1.76k
    wc_UnLockMutex(&cm->caLock);
2726
2727
1.76k
    return ret;
2728
1.76k
}
2729
2730
#if defined(HAVE_OCSP)
2731
Signer* GetCAByKeyHash(void* vp, const byte* keyHash)
2732
0
{
2733
0
    WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
2734
0
    Signer* ret = NULL;
2735
0
    Signer* signers;
2736
0
    int row;
2737
2738
0
    if (cm == NULL || keyHash == NULL)
2739
0
        return NULL;
2740
2741
    /* try lookup using keyHash as subjKeyID first */
2742
0
    ret = GetCA(vp, (byte*)keyHash);
2743
0
    if (ret != NULL && XMEMCMP(ret->subjectKeyHash, keyHash, KEYID_SIZE) == 0) {
2744
0
        return ret;
2745
0
    }
2746
2747
    /* if we can't find the cert, we have to scan the full table */
2748
0
    if (wc_LockMutex(&cm->caLock) != 0)
2749
0
        return NULL;
2750
2751
    /* Unfortunately we need to look through the entire table */
2752
0
    for (row = 0; row < CA_TABLE_SIZE && ret == NULL; row++) {
2753
0
        for (signers = cm->caTable[row]; signers != NULL;
2754
0
                signers = signers->next) {
2755
0
            if (XMEMCMP(signers->subjectKeyHash, keyHash, KEYID_SIZE) == 0) {
2756
0
                ret = signers;
2757
0
                break;
2758
0
            }
2759
0
        }
2760
0
    }
2761
2762
0
    wc_UnLockMutex(&cm->caLock);
2763
0
    return ret;
2764
0
}
2765
#endif
2766
#ifdef WOLFSSL_AKID_NAME
2767
Signer* GetCAByAKID(void* vp, const byte* issuer, word32 issuerSz,
2768
        const byte* serial, word32 serialSz)
2769
316
{
2770
316
    WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
2771
316
    Signer* ret = NULL;
2772
316
    Signer* signers;
2773
316
    byte nameHash[SIGNER_DIGEST_SIZE];
2774
316
    byte serialHash[SIGNER_DIGEST_SIZE];
2775
316
    word32 row;
2776
2777
316
    if (cm == NULL || issuer == NULL || issuerSz == 0 ||
2778
0
            serial == NULL || serialSz == 0)
2779
316
        return NULL;
2780
2781
0
    if (CalcHashId(issuer, issuerSz, nameHash) != 0 ||
2782
0
            CalcHashId(serial, serialSz, serialHash) != 0)
2783
0
        return NULL;
2784
2785
0
    if (wc_LockMutex(&cm->caLock) != 0)
2786
0
        return ret;
2787
2788
    /* Unfortunately we need to look through the entire table */
2789
0
    for (row = 0; row < CA_TABLE_SIZE && ret == NULL; row++) {
2790
0
        for (signers = cm->caTable[row]; signers != NULL;
2791
0
                signers = signers->next) {
2792
0
            if (XMEMCMP(signers->issuerNameHash, nameHash, SIGNER_DIGEST_SIZE)
2793
0
                    == 0 && XMEMCMP(signers->serialHash, serialHash,
2794
0
                                    SIGNER_DIGEST_SIZE) == 0) {
2795
0
                ret = signers;
2796
0
                break;
2797
0
            }
2798
0
        }
2799
0
    }
2800
2801
0
    wc_UnLockMutex(&cm->caLock);
2802
2803
0
    return ret;
2804
0
}
2805
#endif
2806
2807
#ifndef NO_SKID
2808
/* return CA if found, otherwise NULL. Walk through hash table. */
2809
Signer* GetCAByName(void* vp, byte* hash)
2810
6.20k
{
2811
6.20k
    WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
2812
6.20k
    Signer* ret = NULL;
2813
6.20k
    Signer* signers;
2814
6.20k
    word32  row;
2815
2816
6.20k
    if (cm == NULL)
2817
1.77k
        return NULL;
2818
2819
4.42k
    if (wc_LockMutex(&cm->caLock) != 0)
2820
0
        return ret;
2821
2822
52.5k
    for (row = 0; row < CA_TABLE_SIZE && ret == NULL; row++) {
2823
48.1k
        signers = cm->caTable[row];
2824
49.8k
        while (signers && ret == NULL) {
2825
1.70k
            if (XMEMCMP(hash, signers->subjectNameHash,
2826
1.70k
                        SIGNER_DIGEST_SIZE) == 0) {
2827
124
                ret = signers;
2828
124
            }
2829
1.70k
            signers = signers->next;
2830
1.70k
        }
2831
48.1k
    }
2832
4.42k
    wc_UnLockMutex(&cm->caLock);
2833
2834
4.42k
    return ret;
2835
4.42k
}
2836
#endif
2837
2838
#ifdef WOLFSSL_TRUST_PEER_CERT
2839
/* add a trusted peer cert to linked list */
2840
int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify)
2841
{
2842
    int ret = 0;
2843
    int row = 0;
2844
    TrustedPeerCert* peerCert;
2845
    DecodedCert* cert;
2846
    DerBuffer*   der = *pDer;
2847
2848
    WOLFSSL_MSG("Adding a Trusted Peer Cert");
2849
2850
    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap,
2851
                                 DYNAMIC_TYPE_DCERT);
2852
    if (cert == NULL) {
2853
        FreeDer(&der);
2854
        return MEMORY_E;
2855
    }
2856
2857
    InitDecodedCert(cert, der->buffer, der->length, cm->heap);
2858
    if ((ret = ParseCert(cert, TRUSTED_PEER_TYPE, verify, cm)) != 0) {
2859
        FreeDecodedCert(cert);
2860
        XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
2861
        FreeDer(&der);
2862
        return ret;
2863
    }
2864
    WOLFSSL_MSG("\tParsed new trusted peer cert");
2865
2866
    peerCert = (TrustedPeerCert*)XMALLOC(sizeof(TrustedPeerCert), cm->heap,
2867
                                                             DYNAMIC_TYPE_CERT);
2868
    if (peerCert == NULL) {
2869
        FreeDecodedCert(cert);
2870
        XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
2871
        FreeDer(&der);
2872
        return MEMORY_E;
2873
    }
2874
    XMEMSET(peerCert, 0, sizeof(TrustedPeerCert));
2875
2876
    #ifndef IGNORE_NAME_CONSTRAINTS
2877
        if (peerCert->permittedNames)
2878
            FreeNameSubtrees(peerCert->permittedNames, cm->heap);
2879
        if (peerCert->excludedNames)
2880
            FreeNameSubtrees(peerCert->excludedNames, cm->heap);
2881
    #endif
2882
2883
    if (AlreadyTrustedPeer(cm, cert)) {
2884
        WOLFSSL_MSG("\tAlready have this CA, not adding again");
2885
        FreeTrustedPeer(peerCert, cm->heap);
2886
        (void)ret;
2887
    }
2888
    else {
2889
        /* add trusted peer signature */
2890
        peerCert->sigLen = cert->sigLength;
2891
        peerCert->sig = (byte *)XMALLOC(cert->sigLength, cm->heap,
2892
                                                        DYNAMIC_TYPE_SIGNATURE);
2893
        if (peerCert->sig == NULL) {
2894
            FreeDecodedCert(cert);
2895
            XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
2896
            FreeTrustedPeer(peerCert, cm->heap);
2897
            FreeDer(&der);
2898
            return MEMORY_E;
2899
        }
2900
        XMEMCPY(peerCert->sig, cert->signature, cert->sigLength);
2901
2902
        /* add trusted peer name */
2903
        peerCert->nameLen = cert->subjectCNLen;
2904
        peerCert->name    = cert->subjectCN;
2905
        #ifndef IGNORE_NAME_CONSTRAINTS
2906
            peerCert->permittedNames = cert->permittedNames;
2907
            peerCert->excludedNames  = cert->excludedNames;
2908
        #endif
2909
2910
        /* add SKID when available and hash of name */
2911
        #ifndef NO_SKID
2912
            XMEMCPY(peerCert->subjectKeyIdHash, cert->extSubjKeyId,
2913
                   SIGNER_DIGEST_SIZE);
2914
        #endif
2915
            XMEMCPY(peerCert->subjectNameHash, cert->subjectHash,
2916
                    SIGNER_DIGEST_SIZE);
2917
        #ifndef WOLFSSL_NO_ISSUERHASH_TDPEER
2918
            XMEMCPY(peerCert->issuerHash, cert->issuerHash,
2919
                    SIGNER_DIGEST_SIZE);
2920
        #endif
2921
            /* If Key Usage not set, all uses valid. */
2922
            peerCert->next    = NULL;
2923
            cert->subjectCN = 0;
2924
        #ifndef IGNORE_NAME_CONSTRAINTS
2925
            cert->permittedNames = NULL;
2926
            cert->excludedNames = NULL;
2927
        #endif
2928
2929
            row = (int)TrustedPeerHashSigner(peerCert->subjectNameHash);
2930
2931
            if (wc_LockMutex(&cm->tpLock) == 0) {
2932
                peerCert->next = cm->tpTable[row];
2933
                cm->tpTable[row] = peerCert;   /* takes ownership */
2934
                wc_UnLockMutex(&cm->tpLock);
2935
            }
2936
            else {
2937
                WOLFSSL_MSG("\tTrusted Peer Cert Mutex Lock failed");
2938
                FreeDecodedCert(cert);
2939
                XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
2940
                FreeTrustedPeer(peerCert, cm->heap);
2941
                FreeDer(&der);
2942
                return BAD_MUTEX_E;
2943
            }
2944
        }
2945
2946
    WOLFSSL_MSG("\tFreeing parsed trusted peer cert");
2947
    FreeDecodedCert(cert);
2948
    XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
2949
    WOLFSSL_MSG("\tFreeing der trusted peer cert");
2950
    FreeDer(&der);
2951
    WOLFSSL_MSG("\t\tOK Freeing der trusted peer cert");
2952
    WOLFSSL_LEAVE("AddTrustedPeer", ret);
2953
2954
    return WOLFSSL_SUCCESS;
2955
}
2956
#endif /* WOLFSSL_TRUST_PEER_CERT */
2957
2958
int AddSigner(WOLFSSL_CERT_MANAGER* cm, Signer *s)
2959
0
{
2960
0
    byte*   subjectHash;
2961
0
    Signer* signers;
2962
0
    word32  row;
2963
2964
0
    if (cm == NULL || s == NULL)
2965
0
        return BAD_FUNC_ARG;
2966
2967
0
#ifndef NO_SKID
2968
0
    subjectHash = s->subjectKeyIdHash;
2969
#else
2970
    subjectHash = s->subjectNameHash;
2971
#endif
2972
2973
0
    if (AlreadySigner(cm, subjectHash)) {
2974
0
        FreeSigner(s, cm->heap);
2975
0
        return 0;
2976
0
    }
2977
2978
0
    row = HashSigner(subjectHash);
2979
2980
0
    if (wc_LockMutex(&cm->caLock) != 0)
2981
0
        return BAD_MUTEX_E;
2982
2983
0
    signers = cm->caTable[row];
2984
0
    s->next = signers;
2985
0
    cm->caTable[row] = s;
2986
2987
0
    wc_UnLockMutex(&cm->caLock);
2988
0
    return 0;
2989
0
}
2990
2991
/* owns der, internal now uses too */
2992
/* type flag ids from user or from chain received during verify
2993
   don't allow chain ones to be added w/o isCA extension */
2994
int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
2995
{
2996
    int         ret = 0;
2997
    Signer*     signer = NULL;
2998
    word32      row = 0;
2999
    byte*       subjectHash = NULL;
3000
    WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
3001
    DerBuffer*   der = *pDer;
3002
3003
    WOLFSSL_MSG_CERT_LOG("Adding a CA");
3004
3005
    if (cm == NULL) {
3006
        FreeDer(pDer);
3007
        return BAD_FUNC_ARG;
3008
    }
3009
3010
    #ifdef WOLFSSL_SMALL_STACK
3011
    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
3012
    if (cert == NULL) {
3013
        FreeDer(pDer);
3014
        return MEMORY_E;
3015
    }
3016
    #endif
3017
3018
    InitDecodedCert(cert, der->buffer, der->length, cm->heap);
3019
3020
#ifdef WC_ASN_UNKNOWN_EXT_CB
3021
    if (cm->unknownExtCallback != NULL) {
3022
        wc_SetUnknownExtCallback(cert, cm->unknownExtCallback);
3023
    }
3024
#endif
3025
3026
    WOLFSSL_MSG_CERT("\tParsing new CA");
3027
    ret = ParseCert(cert, CA_TYPE, verify, cm);
3028
3029
    WOLFSSL_MSG("\tParsed new CA");
3030
#ifdef WOLFSSL_DEBUG_CERTS
3031
    {
3032
        const char*  err_msg;
3033
        if (ret == 0) {
3034
            WOLFSSL_MSG_CERT_EX(WOLFSSL_MSG_CERT_INDENT "issuer:  '%s'",
3035
                cert->issuer);
3036
            WOLFSSL_MSG_CERT_EX(WOLFSSL_MSG_CERT_INDENT "subject: '%s'",
3037
                cert->subject);
3038
        }
3039
        else {
3040
            WOLFSSL_MSG_CERT(
3041
                WOLFSSL_MSG_CERT_INDENT "Failed during parse of new CA");
3042
            err_msg = wc_GetErrorString(ret);
3043
            WOLFSSL_MSG_CERT_EX(WOLFSSL_MSG_CERT_INDENT "error ret: %d; %s",
3044
                ret, err_msg);
3045
        }
3046
    }
3047
#endif /* WOLFSSL_DEBUG_CERTS */
3048
3049
#ifndef NO_SKID
3050
    subjectHash = cert->extSubjKeyId;
3051
#else
3052
    subjectHash = cert->subjectHash;
3053
#endif
3054
3055
    /* check CA key size */
3056
    if (verify && (ret == 0 )) {
3057
        switch (cert->keyOID) {
3058
        #ifndef NO_RSA
3059
            #ifdef WC_RSA_PSS
3060
            case RSAPSSk:
3061
            #endif
3062
            case RSAk:
3063
                if (cm->minRsaKeySz < 0 ||
3064
                                   cert->pubKeySize < (word16)cm->minRsaKeySz) {
3065
                    ret = RSA_KEY_SIZE_E;
3066
                    WOLFSSL_MSG_CERT_LOG("\tCA RSA key size error");
3067
                    WOLFSSL_MSG_CERT_EX("\tCA RSA pubKeySize = %d; "
3068
                                                "minRsaKeySz = %d",
3069
                                   cert->pubKeySize, cm->minRsaKeySz);
3070
                }
3071
                break;
3072
        #endif /* !NO_RSA */
3073
            #ifdef HAVE_ECC
3074
            case ECDSAk:
3075
                if (cm->minEccKeySz < 0 ||
3076
                                   cert->pubKeySize < (word16)cm->minEccKeySz) {
3077
                    ret = ECC_KEY_SIZE_E;
3078
                    WOLFSSL_MSG_CERT_LOG("\tCA ECC key size error");
3079
                    WOLFSSL_MSG_CERT_EX("\tCA ECC pubKeySize = %d; "
3080
                                                 "minEccKeySz = %d",
3081
                                   cert->pubKeySize, cm->minEccKeySz);
3082
                }
3083
                break;
3084
            #endif /* HAVE_ECC */
3085
            #ifdef HAVE_ED25519
3086
            case ED25519k:
3087
                if (cm->minEccKeySz < 0 ||
3088
                                   ED25519_KEY_SIZE < (word16)cm->minEccKeySz) {
3089
                    ret = ECC_KEY_SIZE_E;
3090
                    WOLFSSL_MSG("\tCA ECC key size error");
3091
                }
3092
                break;
3093
            #endif /* HAVE_ED25519 */
3094
            #ifdef HAVE_ED448
3095
            case ED448k:
3096
                if (cm->minEccKeySz < 0 ||
3097
                                     ED448_KEY_SIZE < (word16)cm->minEccKeySz) {
3098
                    ret = ECC_KEY_SIZE_E;
3099
                    WOLFSSL_MSG("\tCA ECC key size error");
3100
                }
3101
                break;
3102
            #endif /* HAVE_ED448 */
3103
            #if defined(HAVE_FALCON)
3104
            case FALCON_LEVEL1k:
3105
                if (cm->minFalconKeySz < 0 ||
3106
                          FALCON_LEVEL1_KEY_SIZE < (word16)cm->minFalconKeySz) {
3107
                    ret = FALCON_KEY_SIZE_E;
3108
                    WOLFSSL_MSG("\tCA Falcon level 1 key size error");
3109
                }
3110
                break;
3111
            case FALCON_LEVEL5k:
3112
                if (cm->minFalconKeySz < 0 ||
3113
                          FALCON_LEVEL5_KEY_SIZE < (word16)cm->minFalconKeySz) {
3114
                    ret = FALCON_KEY_SIZE_E;
3115
                    WOLFSSL_MSG("\tCA Falcon level 5 key size error");
3116
                }
3117
                break;
3118
            #endif /* HAVE_FALCON */
3119
            #if defined(HAVE_DILITHIUM)
3120
            #ifdef WOLFSSL_DILITHIUM_FIPS204_DRAFT
3121
            case DILITHIUM_LEVEL2k:
3122
                if (cm->minDilithiumKeySz < 0 ||
3123
                    DILITHIUM_LEVEL2_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
3124
                    ret = DILITHIUM_KEY_SIZE_E;
3125
                    WOLFSSL_MSG("\tCA Dilithium level 2 key size error");
3126
                }
3127
                break;
3128
            case DILITHIUM_LEVEL3k:
3129
                if (cm->minDilithiumKeySz < 0 ||
3130
                    DILITHIUM_LEVEL3_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
3131
                    ret = DILITHIUM_KEY_SIZE_E;
3132
                    WOLFSSL_MSG("\tCA Dilithium level 3 key size error");
3133
                }
3134
                break;
3135
            case DILITHIUM_LEVEL5k:
3136
                if (cm->minDilithiumKeySz < 0 ||
3137
                    DILITHIUM_LEVEL5_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
3138
                    ret = DILITHIUM_KEY_SIZE_E;
3139
                    WOLFSSL_MSG("\tCA Dilithium level 5 key size error");
3140
                }
3141
                break;
3142
            #endif /* WOLFSSL_DILITHIUM_FIPS204_DRAFT */
3143
            case ML_DSA_LEVEL2k:
3144
                if (cm->minDilithiumKeySz < 0 ||
3145
                    ML_DSA_LEVEL2_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
3146
                    ret = DILITHIUM_KEY_SIZE_E;
3147
                    WOLFSSL_MSG("\tCA Dilithium level 2 key size error");
3148
                }
3149
                break;
3150
            case ML_DSA_LEVEL3k:
3151
                if (cm->minDilithiumKeySz < 0 ||
3152
                    ML_DSA_LEVEL3_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
3153
                    ret = DILITHIUM_KEY_SIZE_E;
3154
                    WOLFSSL_MSG("\tCA Dilithium level 3 key size error");
3155
                }
3156
                break;
3157
            case ML_DSA_LEVEL5k:
3158
                if (cm->minDilithiumKeySz < 0 ||
3159
                    ML_DSA_LEVEL5_KEY_SIZE < (word16)cm->minDilithiumKeySz) {
3160
                    ret = DILITHIUM_KEY_SIZE_E;
3161
                    WOLFSSL_MSG("\tCA Dilithium level 5 key size error");
3162
                }
3163
                break;
3164
            #endif /* HAVE_DILITHIUM */
3165
3166
            default:
3167
                WOLFSSL_MSG("\tNo key size check done on CA");
3168
                break; /* no size check if key type is not in switch */
3169
        }
3170
    }
3171
3172
    if (ret == 0 && cert->isCA == 0 && type != WOLFSSL_USER_CA &&
3173
        type != WOLFSSL_TEMP_CA) {
3174
        WOLFSSL_MSG("\tCan't add as CA if not actually one");
3175
        ret = NOT_CA_ERROR;
3176
    }
3177
#ifndef ALLOW_INVALID_CERTSIGN
3178
    else if (ret == 0 && cert->isCA == 1 && type != WOLFSSL_USER_CA &&
3179
        type != WOLFSSL_TEMP_CA && !cert->selfSigned &&
3180
        (cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) == 0) {
3181
        /* Intermediate CA certs are required to have the keyCertSign
3182
        * extension set. User loaded root certs are not. */
3183
        WOLFSSL_MSG("\tDoesn't have key usage certificate signing");
3184
        ret = NOT_CA_ERROR;
3185
    }
3186
#endif
3187
    else if (ret == 0 && AlreadySigner(cm, subjectHash)) {
3188
        WOLFSSL_MSG("\tAlready have this CA, not adding again");
3189
        (void)ret;
3190
    }
3191
    else if (ret == 0) {
3192
        /* take over signer parts */
3193
        signer = MakeSigner(cm->heap);
3194
        if (!signer)
3195
            ret = MEMORY_ERROR;
3196
    }
3197
    if (ret == 0 && signer != NULL) {
3198
        ret = FillSigner(signer, cert, type, der);
3199
3200
        if (ret == 0){
3201
        #ifndef NO_SKID
3202
            row = HashSigner(signer->subjectKeyIdHash);
3203
        #else
3204
            row = HashSigner(signer->subjectNameHash);
3205
        #endif
3206
        }
3207
3208
    #if defined(WOLFSSL_RENESAS_TSIP_TLS) || defined(WOLFSSL_RENESAS_FSPSM_TLS)
3209
        /* Verify CA by TSIP so that generated tsip key is going to          */
3210
        /* be able to be used for peer's cert verification                   */
3211
        /* TSIP is only able to handle USER CA, and only one CA.             */
3212
        /* Therefore, it doesn't need to call TSIP again if there is already */
3213
        /* verified CA.                                                      */
3214
        if ( ret == 0 && signer != NULL ) {
3215
            signer->cm_idx = row;
3216
            if (type == WOLFSSL_USER_CA) {
3217
                if ((ret = wc_Renesas_cmn_RootCertVerify(cert->source,
3218
                        cert->maxIdx,
3219
                        cert->sigCtx.CertAtt.pubkey_n_start,
3220
                        cert->sigCtx.CertAtt.pubkey_n_len - 1,
3221
                        cert->sigCtx.CertAtt.pubkey_e_start,
3222
                        cert->sigCtx.CertAtt.pubkey_e_len - 1,
3223
                     row/* cm index */))
3224
                    < 0)
3225
                    WOLFSSL_MSG("Renesas_RootCertVerify() failed");
3226
                else
3227
                    WOLFSSL_MSG("Renesas_RootCertVerify() succeed or skipped");
3228
            }
3229
        }
3230
    #endif /* TSIP or SCE */
3231
3232
        if (ret == 0 && wc_LockMutex(&cm->caLock) == 0) {
3233
            signer->next = cm->caTable[row];
3234
            cm->caTable[row] = signer;   /* takes ownership */
3235
            wc_UnLockMutex(&cm->caLock);
3236
            if (cm->caCacheCallback)
3237
                cm->caCacheCallback(der->buffer, (int)der->length, type);
3238
        }
3239
        else {
3240
            WOLFSSL_MSG("\tCA Mutex Lock failed");
3241
            ret = BAD_MUTEX_E;
3242
        }
3243
    }
3244
3245
    WOLFSSL_MSG("\tFreeing Parsed CA");
3246
    FreeDecodedCert(cert);
3247
    if (ret != 0 && signer != NULL)
3248
        FreeSigner(signer, cm->heap);
3249
    WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
3250
    WOLFSSL_MSG("\tFreeing der CA");
3251
    FreeDer(pDer);
3252
    WOLFSSL_MSG("\t\tOK Freeing der CA");
3253
3254
    WOLFSSL_LEAVE("AddCA", ret);
3255
3256
    return ret == 0 ? WOLFSSL_SUCCESS : ret;
3257
}
3258
3259
/* Removes the CA with the passed in subject hash from the
3260
   cert manager's CA cert store. */
3261
int RemoveCA(WOLFSSL_CERT_MANAGER* cm, byte* hash, int type)
3262
0
{
3263
0
    Signer* current;
3264
0
    Signer** prev;
3265
0
    int     ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
3266
0
    word32  row;
3267
3268
0
    WOLFSSL_MSG("Removing a CA");
3269
3270
0
    if (cm == NULL || hash == NULL) {
3271
0
        return BAD_FUNC_ARG;
3272
0
    }
3273
3274
0
    row = HashSigner(hash);
3275
3276
0
    if (wc_LockMutex(&cm->caLock) != 0) {
3277
0
        return BAD_MUTEX_E;
3278
0
    }
3279
0
    current = cm->caTable[row];
3280
0
    prev = &cm->caTable[row];
3281
0
    while (current) {
3282
0
        byte* subjectHash;
3283
3284
0
    #ifndef NO_SKID
3285
0
        subjectHash = current->subjectKeyIdHash;
3286
    #else
3287
        subjectHash = current->subjectNameHash;
3288
    #endif
3289
3290
0
        if ((current->type == type) &&
3291
0
            (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0)) {
3292
0
            *prev = current->next;
3293
0
            FreeSigner(current, cm->heap);
3294
0
            ret = WOLFSSL_SUCCESS;
3295
0
            break;
3296
0
        }
3297
0
        prev = &current->next;
3298
0
        current = current->next;
3299
0
    }
3300
0
    wc_UnLockMutex(&cm->caLock);
3301
3302
0
    WOLFSSL_LEAVE("RemoveCA", ret);
3303
3304
0
    return ret;
3305
0
}
3306
3307
/* Sets the CA with the passed in subject hash
3308
   to the provided type. */
3309
int SetCAType(WOLFSSL_CERT_MANAGER* cm, byte* hash, int type)
3310
0
{
3311
0
    Signer* current;
3312
0
    int     ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
3313
0
    word32  row;
3314
3315
0
    WOLFSSL_MSG_EX("Setting CA to type %d", type);
3316
3317
0
    if (cm == NULL || hash == NULL ||
3318
0
        type < WOLFSSL_USER_CA || type > WOLFSSL_USER_INTER) {
3319
0
        return ret;
3320
0
    }
3321
3322
0
    row = HashSigner(hash);
3323
3324
0
    if (wc_LockMutex(&cm->caLock) != 0) {
3325
0
        return ret;
3326
0
    }
3327
0
    current = cm->caTable[row];
3328
0
    while (current) {
3329
0
        byte* subjectHash;
3330
3331
0
    #ifndef NO_SKID
3332
0
        subjectHash = current->subjectKeyIdHash;
3333
    #else
3334
        subjectHash = current->subjectNameHash;
3335
    #endif
3336
3337
0
        if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
3338
0
            current->type = (byte)type;
3339
0
            ret = WOLFSSL_SUCCESS;
3340
0
            break;
3341
0
        }
3342
0
        current = current->next;
3343
0
    }
3344
0
    wc_UnLockMutex(&cm->caLock);
3345
3346
0
    WOLFSSL_LEAVE("SetCAType", ret);
3347
3348
0
    return ret;
3349
0
}
3350
3351
#endif /* NO_CERTS */
3352
3353
#endif /* !WOLFSSL_SSL_CERTMAN_INCLUDED */