Coverage Report

Created: 2026-10-16 06:40

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