Coverage Report

Created: 2026-08-15 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-openssl-api/src/ssl_certman.c
Line
Count
Source
1
/* ssl_certman.c
2
 *
3
 * Copyright (C) 2006-2026 wolfSSL Inc.
4
 *
5
 * This file is part of wolfSSL.
6
 *
7
 * wolfSSL is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * wolfSSL is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20
 */
21
22
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
23
24
#include <wolfssl/internal.h>
25
26
#if defined(WOLFSSL_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
4.86k
{
91
4.86k
    int err = 0;
92
4.86k
    WOLFSSL_CERT_MANAGER* cm;
93
94
4.86k
    WOLFSSL_ENTER("wolfSSL_CertManagerNew");
95
4.86k
    if (heap == NULL) {
96
4.86k
         WOLFSSL_MSG("heap param is null");
97
4.86k
    }
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
4.86k
    WOLFSSL_MSG_EX("DYNAMIC_TYPE_CERT_MANAGER Allocating = %d bytes",
103
4.86k
                    (word32)sizeof(WOLFSSL_CERT_MANAGER));
104
105
    /* Allocate memory for certificate manager. */
106
4.86k
    cm = (WOLFSSL_CERT_MANAGER*)XMALLOC(sizeof(WOLFSSL_CERT_MANAGER), heap,
107
4.86k
        DYNAMIC_TYPE_CERT_MANAGER);
108
4.86k
    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
4.86k
    if (!err) {
114
        /* Reset all fields. */
115
4.86k
        XMEMSET(cm, 0, sizeof(WOLFSSL_CERT_MANAGER));
116
        /* Set heap hint early so cleanup can use it. */
117
4.86k
        cm->heap = heap;
118
119
        /* Create a mutex for use when modify table of stored CAs. */
120
4.86k
        if (wc_InitMutex(&cm->caLock) != 0) {
121
0
            WOLFSSL_MSG("Bad mutex init");
122
0
            err = 1;
123
0
        }
124
4.86k
        else {
125
4.86k
            cm->caLockInit = 1;
126
4.86k
        }
127
4.86k
    }
128
4.86k
    if (!err) {
129
        /* Initialize reference count. */
130
4.86k
        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
4.86k
        cm->refInit = 1;
140
4.86k
    #endif
141
4.86k
    }
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
4.86k
    if (!err) {
155
        /* Set default minimum key sizes allowed. */
156
4.86k
    #ifndef NO_RSA
157
4.86k
        cm->minRsaKeySz = MIN_RSAKEY_SZ;
158
4.86k
    #endif
159
4.86k
    #ifdef HAVE_ECC
160
4.86k
        cm->minEccKeySz = MIN_ECCKEY_SZ;
161
4.86k
    #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
4.86k
    }
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
4.86k
    if (err && (cm != NULL)) {
173
0
        DoCertManagerFree(cm);
174
0
        cm = NULL;
175
0
    }
176
4.86k
    return cm;
177
4.86k
}
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
0
#ifdef HAVE_OCSP
209
    /* Dispose of OCSP handler. */
210
0
    if (cm->ocsp != NULL) {
211
0
        FreeOCSP(cm->ocsp, 1);
212
0
    }
213
    /* Dispose of URL. */
214
0
    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
0
#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
4.81k
{
253
4.81k
    WOLFSSL_ENTER("wolfSSL_CertManagerFree");
254
255
    /* Validate parameter. */
256
4.81k
    if (cm != NULL) {
257
4.81k
        int doFree = 0;
258
4.81k
        int ret;
259
260
        /* Decrement reference count and check if value is 0. */
261
4.81k
        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
4.81k
        (void)ret;
268
4.81k
    #endif
269
4.81k
        if (doFree) {
270
4.81k
            DoCertManagerFree(cm);
271
4.81k
        }
272
4.81k
    }
273
4.81k
}
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
0
{
525
0
    WOLFSSL_ENTER("wolfSSL_CertManagerUnloadTempIntermediateCerts");
526
0
    return wolfSSL_CertManagerUnloadTypeCerts(cm, WOLFSSL_TEMP_CA);
527
0
}
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
0
{
749
0
    WOLFSSL_ENTER("wolfSSL_CertManagerSetUnknownExtCallback");
750
0
    if (cm != NULL) {
751
0
        cm->unknownExtCallback = cb;
752
0
    }
753
754
0
}
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_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)) || \
783
    defined(OPENSSL_EXTRA)
784
/* Verify the certificate.
785
 *
786
 * Uses the verification callback if available.
787
 *
788
 * @param [in] cm        Certificate manager.
789
 * @param [in] buff      Buffer holding encoded certificate.
790
 * @param [in] sz        Size in bytes of data in buffer.
791
 * @param [in] format    Format of encoding. Valid values:
792
 *                         WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
793
 * @param [in] prev_err  Previous error. Passed to callback.
794
 * @return  WOLFSSL_SUCCESS on success.
795
 * @return  MEMORY_E when dynamic memory allocation fails.
796
 * @return  NOT_COMPILED_IN when converting from PEM to DER is not a feature of
797
 *          the wolfSSL build.
798
 */
799
int CM_VerifyBuffer_ex(WOLFSSL_CERT_MANAGER* cm, const unsigned char* buff,
800
    long sz, int format, int prev_err)
801
0
{
802
0
    int ret = 0;
803
0
    int fatal = 0;
804
0
    DerBuffer* der = NULL;
805
0
    WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
806
807
0
    WOLFSSL_ENTER("CM_VerifyBuffer_ex");
808
809
0
    (void)prev_err;
810
811
    /* Allocate memory for decoded certificate. */
812
0
    WC_ALLOC_VAR_EX(cert, DecodedCert, 1, cm->heap, DYNAMIC_TYPE_DCERT,
813
0
    {
814
0
        ret=MEMORY_E;
815
0
        fatal=1;
816
0
    });
817
0
    if (WC_VAR_OK(cert))
818
0
    {
819
        /* Reset fields of decoded certificate. */
820
0
        XMEMSET(cert, 0, sizeof(DecodedCert));
821
822
0
        if (format == WOLFSSL_FILETYPE_PEM) {
823
        #ifndef WOLFSSL_PEM_TO_DER
824
            ret = NOT_COMPILED_IN;
825
            fatal = 1;
826
        #else
827
            /* Convert to DER from PEM. */
828
0
            ret = PemToDer(buff, sz, CERT_TYPE, &der, cm->heap, NULL, NULL);
829
0
            if (ret != 0) {
830
0
                fatal = 1;
831
0
            }
832
0
            else {
833
                /* Replace buffer pointer and size with DER buffer. */
834
0
                buff = der->buffer;
835
0
                sz = (long)der->length;
836
0
            }
837
0
        #endif
838
0
        }
839
0
    }
840
0
    if (ret == 0) {
841
        /* Create a decoded certificate with DER buffer. */
842
0
        InitDecodedCert(cert, buff, (word32)sz, cm->heap);
843
844
0
#ifdef WC_ASN_UNKNOWN_EXT_CB
845
0
        if (cm->unknownExtCallback != NULL)
846
0
            wc_SetUnknownExtCallback(cert, cm->unknownExtCallback);
847
0
#endif
848
849
        /* Parse DER into decoded certificate fields and verify signature
850
         * against a known CA. */
851
0
        ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, cm, NULL);
852
0
     }
853
854
#ifdef HAVE_CRL
855
    if ((ret == 0) && cm->crlEnabled) {
856
        /* Check for a CRL for the CA and check validity of certificate. */
857
        ret = CheckCertCRL(cm->crl, cert);
858
    }
859
#endif
860
861
0
    (void)fatal;
862
863
0
#if !defined(NO_WOLFSSL_CM_VERIFY) && \
864
0
    (!defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH))
865
    /* Use callback to perform verification too if available. */
866
0
    if ((!fatal) && cm->verifyCallback) {
867
0
        WC_DECLARE_VAR(args, ProcPeerCertArgs, 1, 0);
868
0
        buffer certBuf;
869
870
0
    #ifdef WOLFSSL_SMALL_STACK
871
        /* Allocate memory for object to hold arguments for callback. */
872
0
        args = (ProcPeerCertArgs*)XMALLOC(sizeof(ProcPeerCertArgs), cm->heap,
873
0
            DYNAMIC_TYPE_TMP_BUFFER);
874
0
        if (args == NULL) {
875
0
            ret = MEMORY_E;
876
0
            fatal = 1;
877
0
        }
878
0
        if (!fatal)
879
0
    #endif
880
0
        {
881
0
            XMEMSET(args, 0, sizeof(ProcPeerCertArgs));
882
883
            /* DER encoding. */
884
0
            certBuf.buffer = (byte*)buff;
885
0
            certBuf.length = (unsigned int)sz;
886
887
            /* One certificate available. */
888
0
            args->totalCerts = 1;
889
0
            args->certs = &certBuf;
890
0
            args->dCert = cert;
891
0
            args->dCertInit = 1;
892
893
            /* Replace value in ret with an error value passed in. */
894
0
            if (prev_err != 0) {
895
0
                ret = prev_err;
896
0
            }
897
            /* Use callback to verify certificate. */
898
0
            ret = DoVerifyCallback(cm, NULL, ret, args);
899
0
        }
900
0
        WC_FREE_VAR_EX(args, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
901
0
    }
902
0
#endif
903
904
    /* Dispose of allocated memory. */
905
0
    FreeDecodedCert(cert);
906
0
    FreeDer(&der);
907
0
    WC_FREE_VAR_EX(cert, cm->heap, DYNAMIC_TYPE_DCERT);
908
909
    /* Convert the ret value to a return value. */
910
0
    return (ret == 0) ? WOLFSSL_SUCCESS : ret;
911
0
}
912
913
/* Verify the certificate.
914
 *
915
 * Uses the verification callback if available.
916
 *
917
 * @param [in] cm        Certificate manager.
918
 * @param [in] buff      Buffer holding encoded certificate.
919
 * @param [in] sz        Size in bytes of data in buffer.
920
 * @param [in] format    Format of encoding. Valid values:
921
 *                         WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
922
 * @param [in] prev_err  Previous error. Passed to callback.
923
 * @return  WOLFSSL_SUCCESS on success.
924
 * @return  BAD_FUNC_ARG when cm or buff is NULL or sz is negative or zero.
925
 * @return  WOLFSSL_BAD_FILETYPE when format is invalid.
926
 * @return  MEMORY_E when dynamic memory allocation fails.
927
 * @return  NOT_COMPILED_IN when converting from PEM to DER is not a feature of
928
 *          the wolfSSL build.
929
 */
930
int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm,
931
    const unsigned char* buff, long sz, int format)
932
0
{
933
0
    int ret;
934
935
0
    WOLFSSL_ENTER("wolfSSL_CertManagerVerifyBuffer");
936
937
    /* Validate parameters. */
938
0
    if ((cm == NULL) || (buff == NULL) || (sz <= 0)) {
939
0
        ret = BAD_FUNC_ARG;
940
0
    }
941
0
    else if ((format != WOLFSSL_FILETYPE_ASN1) &&
942
0
             (format != WOLFSSL_FILETYPE_PEM)) {
943
0
        ret = WOLFSSL_BAD_FILETYPE;
944
0
    }
945
0
    else {
946
        /* No previous error. */
947
0
        ret = CM_VerifyBuffer_ex(cm, buff, sz, format, 0);
948
0
    }
949
950
0
    return ret;
951
0
}
952
#endif /* (!NO_WOLFSSL_CLIENT || !WOLFSSL_NO_CLIENT_AUTH) || OPENSSL_EXTRA */
953
954
#ifndef NO_FILESYSTEM
955
956
#if (!defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)) || \
957
    defined(OPENSSL_EXTRA)
958
/* Verify the certificate loaded from a file.
959
 *
960
 * Uses the verification callback if available.
961
 *
962
 * @param [in] cm        Certificate manager.
963
 * @param [in] format    Format of encoding. Valid values:
964
 *                         WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
965
 * @param [in] prev_err  Previous error. Passed to callback.
966
 * @return  WOLFSSL_SUCCESS on success.
967
 * @return  BAD_FUNC_ARG when cm or buff is NULL or sz is negative.
968
 * @return  WOLFSSL_BAD_FILETYPE when format is invalid.
969
 * @return  WOLFSSL_BAD_FILE when reading the certificate file fails.
970
 * @return  MEMORY_E when dynamic memory allocation fails.
971
 * @return  NOT_COMPILED_IN when converting from PEM to DER is not a feature of
972
 *          the wolfSSL build.
973
 */
974
int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname,
975
    int format)
976
0
{
977
0
    int    ret = WOLFSSL_SUCCESS;
978
#ifndef WOLFSSL_SMALL_STACK
979
    byte   staticBuffer[FILE_BUFFER_SIZE];
980
#endif
981
0
    byte*  buff = NULL;
982
0
    long   sz = 0;
983
0
    XFILE  file = XBADFILE;
984
985
0
    WOLFSSL_ENTER("wolfSSL_CertManagerVerify");
986
987
#ifndef WOLFSSL_SMALL_STACK
988
    buff = staticBuffer;
989
#endif
990
991
    /* Validate parameters. cm and format validated in:
992
     *   wolfSSL_CertManagerVerifyBuffer */
993
0
    if ((cm == NULL) || (fname == NULL)) {
994
0
        ret = BAD_FUNC_ARG;
995
0
    }
996
997
    /* Open the file containing a certificate. */
998
0
    if ((ret == WOLFSSL_SUCCESS) &&
999
0
            ((file = XFOPEN(fname, "rb")) == XBADFILE)) {
1000
0
        ret = WOLFSSL_BAD_FILE;
1001
0
    }
1002
    /* Get the length of the file. */
1003
0
    if (ret == WOLFSSL_SUCCESS) {
1004
0
        ret = wolfssl_file_len(file, &sz);
1005
0
        if (ret == 0) {
1006
0
            ret = WOLFSSL_SUCCESS;
1007
0
        }
1008
0
    }
1009
    /* Allocate dynamic memory for file contents if no static buffer or too
1010
     * small. */
1011
#ifndef WOLFSSL_SMALL_STACK
1012
    if ((ret == WOLFSSL_SUCCESS) && (sz > (long)sizeof(staticBuffer)))
1013
#else
1014
1015
0
    if (ret == WOLFSSL_SUCCESS)
1016
0
#endif
1017
0
    {
1018
0
        WOLFSSL_MSG("Getting dynamic buffer");
1019
0
        buff = (byte*)XMALLOC((size_t)sz, cm->heap, DYNAMIC_TYPE_FILE);
1020
0
        if (buff == NULL) {
1021
0
            ret = WOLFSSL_BAD_FILE;
1022
0
        }
1023
0
    }
1024
    /* Read all the file into buffer. */
1025
0
    if ((ret == WOLFSSL_SUCCESS) && (XFREAD(buff, 1, (size_t)sz, file) !=
1026
0
            (size_t)sz)) {
1027
0
        ret = WOLFSSL_BAD_FILE;
1028
0
    }
1029
    /* Close file if opened. */
1030
0
    if (file != XBADFILE) {
1031
0
        XFCLOSE(file);
1032
0
    }
1033
0
    if (ret == WOLFSSL_SUCCESS) {
1034
        /* Verify the certificate read. */
1035
0
        ret = wolfSSL_CertManagerVerifyBuffer(cm, buff, sz, format);
1036
0
    }
1037
1038
    /* Dispose of buffer if it was allocated. */
1039
#ifndef WOLFSSL_SMALL_STACK
1040
    if (buff != staticBuffer)
1041
#endif
1042
0
    {
1043
0
        if (cm != NULL) {
1044
0
            XFREE(buff, cm->heap, DYNAMIC_TYPE_FILE);
1045
0
        }
1046
0
    }
1047
0
    return ret;
1048
0
}
1049
#endif
1050
1051
/* Load the CA file and/or certificate files in a path.
1052
 *
1053
 * @param [in] cm    Certificate manager.
1054
 * @param [in] file  Name of CA file.
1055
 * @param [in] path  Path to a directory containing certificates.
1056
 * @return  WOLFSSL_SUCCESS on success.
1057
 * @return  WOLFSSL_FATAL_ERROR when cm is NULL or unable to create WOLFSSL_CTX.
1058
 * @return  Otherwise failure.
1059
 */
1060
int wolfSSL_CertManagerLoadCA(WOLFSSL_CERT_MANAGER* cm, const char* file,
1061
                             const char* path)
1062
0
{
1063
0
    int ret = WOLFSSL_SUCCESS;
1064
0
    WOLFSSL_CTX* tmp = NULL;
1065
1066
0
    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCA");
1067
1068
    /* Validate parameters. file and path validated in:
1069
     *   wolfSSL_CTX_load_verify_locations*/
1070
0
    if (cm == NULL) {
1071
0
        WOLFSSL_MSG("No CertManager error");
1072
0
        ret = WOLFSSL_FATAL_ERROR;
1073
0
    }
1074
    /* Create temporary WOLFSSL_CTX. */
1075
0
    if ((ret == WOLFSSL_SUCCESS) && ((tmp =
1076
0
        wolfSSL_CTX_new_ex(cm_pick_method(cm->heap), cm->heap)) == NULL)) {
1077
0
        WOLFSSL_MSG("CTX new failed");
1078
0
        ret = WOLFSSL_FATAL_ERROR;
1079
0
    }
1080
0
    if (ret == WOLFSSL_SUCCESS) {
1081
        /* Some configurations like OPENSSL_COMPATIBLE_DEFAULTS may turn off
1082
         * verification by default. Let's restore our desired defaults. */
1083
0
        wolfSSL_CTX_set_verify(tmp, WOLFSSL_VERIFY_DEFAULT, NULL);
1084
1085
        /* Replace certificate manager with one to load certificate/s into. */
1086
0
        wolfSSL_CertManagerFree(tmp->cm);
1087
0
        tmp->cm = cm;
1088
1089
        /* Load certificate from file and path. */
1090
0
        ret = wolfSSL_CTX_load_verify_locations(tmp, file, path);
1091
1092
        /* Clear certificate manager in WOLFSSL_CTX so it won't be freed. */
1093
0
        tmp->cm = NULL;
1094
0
    }
1095
1096
    /* Dispose of temporary WOLFSSL_CTX. */
1097
0
    wolfSSL_CTX_free(tmp);
1098
0
    return ret;
1099
0
}
1100
1101
#endif /* NO_FILESYSTEM */
1102
1103
#if defined(PERSIST_CERT_CACHE)
1104
1105
/* Version of layout of cache of CA certificates. */
1106
#define WOLFSSL_CACHE_CERT_VERSION 1
1107
1108
/* CA certificates cache information. */
1109
typedef struct {
1110
    /* Cache certificate layout version id. */
1111
    int version;
1112
    /* Number of hash table rows. Maximum of CA_TABLE_SIZE. */
1113
    int rows;
1114
    /* Number of columns per row. */
1115
    int columns[CA_TABLE_SIZE];
1116
    /* Size of Signer object. */
1117
    int signerSz;
1118
} CertCacheHeader;
1119
1120
/* current cert persistence layout is:
1121
1122
   1) CertCacheHeader
1123
   2) caTable
1124
1125
   update WOLFSSL_CERT_CACHE_VERSION if change layout for the following
1126
   PERSIST_CERT_CACHE functions
1127
*/
1128
1129
1130
/* Return number of bytes of memory needed to persist this signer.
1131
 *
1132
 * Assumes we have locked CA table.
1133
 *
1134
 * @param [in] Signer  Signer entry in CA table.
1135
 * @return  Number of bytes.
1136
 */
1137
static WC_INLINE int cm_get_signer_memory(Signer* signer)
1138
{
1139
    int sz = sizeof(signer->pubKeySize) + sizeof(signer->keyOID)
1140
           + sizeof(signer->nameLen)    + sizeof(signer->subjectNameHash);
1141
1142
#if !defined(NO_SKID)
1143
        sz += (int)sizeof(signer->subjectKeyIdHash);
1144
#endif
1145
1146
    /* Add dynamic bytes needed. */
1147
    sz += (int)signer->pubKeySize;
1148
    sz += signer->nameLen;
1149
1150
    return sz;
1151
}
1152
1153
1154
/* Return number of bytes of memory needed to persist this row.
1155
 *
1156
 * Assumes we have locked CA table.
1157
 *
1158
 * @param [in] row  A row of signers from the CA table.
1159
 * @return  Number of bytes.
1160
 */
1161
static WC_INLINE int cm_get_cert_cache_row_memory(Signer* row)
1162
{
1163
    int sz = 0;
1164
1165
    /* Each signer in row. */
1166
    while (row != NULL) {
1167
        /* Add in size of this signer. */
1168
        sz += cm_get_signer_memory(row);
1169
        row = row->next;
1170
    }
1171
1172
    return sz;
1173
}
1174
1175
1176
/* Return the number of bytes of memory to persist cert cache.
1177
 *
1178
 * Assumes we have locked CA table.
1179
 *
1180
 * @param [in] cm  Certificate manager.
1181
 * @return  Number of bytes.
1182
 */
1183
static WC_INLINE int cm_get_cert_cache_mem_size(WOLFSSL_CERT_MANAGER* cm)
1184
{
1185
    int sz;
1186
    int i;
1187
1188
    sz = sizeof(CertCacheHeader);
1189
1190
    /* Each row in table. */
1191
    for (i = 0; i < CA_TABLE_SIZE; i++) {
1192
        /* Add in size of this row. */
1193
        sz += cm_get_cert_cache_row_memory(cm->caTable[i]);
1194
    }
1195
1196
    return sz;
1197
}
1198
1199
1200
/* Get count of columns for each row.
1201
 *
1202
 * Assumes we have locked CA table.
1203
 *
1204
 * @param [in] cm       Certificate manager.
1205
 * @param [in] columns  Array of row counts.
1206
 */
1207
static WC_INLINE void cm_set_cert_header_Columns(WOLFSSL_CERT_MANAGER* cm,
1208
    int* columns)
1209
{
1210
    int     i;
1211
    Signer* row;
1212
1213
    /* Each row in table. */
1214
    for (i = 0; i < CA_TABLE_SIZE; i++) {
1215
        int count = 0;
1216
1217
        /* Get row from table. */
1218
        row = cm->caTable[i];
1219
        /* Each entry in row. */
1220
        while (row != NULL) {
1221
            /* Update count. */
1222
            ++count;
1223
            row = row->next;
1224
        }
1225
        /* Store row count. */
1226
        columns[i] = count;
1227
    }
1228
}
1229
1230
1231
/* Restore whole cert row from memory,
1232
 *
1233
 * Assumes we have locked CA table.
1234
 *
1235
 * @param [in] cm       Certificate manager.
1236
 * @param [in] current  Buffer containing rows.
1237
 * @param [in] row      Row number being restored.
1238
 * @param [in] listSz   Number of entries in row.
1239
 * @param [in] end      End of data in buffer.
1240
 * @return  Number of bytes consumed on success.
1241
 * @return  PARSE_ERROR when listSz is less than zero.
1242
 * @return  BUFFER_E when buffer is too small.
1243
 * @return  MEMORY_E when dynamic memory allocation fails.
1244
 * @return  Negative value on error.
1245
 */
1246
static WC_INLINE int cm_restore_cert_row(WOLFSSL_CERT_MANAGER* cm,
1247
    byte* current, int row, int listSz, const byte* end)
1248
{
1249
    int ret = 0;
1250
    int idx = 0;
1251
1252
    /* Validate parameters. */
1253
    if (listSz < 0) {
1254
        WOLFSSL_MSG("Row header corrupted, negative value");
1255
        ret = PARSE_ERROR;
1256
    }
1257
1258
    /* Process all entries. */
1259
    while ((ret == 0) && (listSz > 0)) {
1260
        Signer* signer = NULL;
1261
        byte*   publicKey;
1262
        byte*   start = current + idx;  /* for end checks on this signer */
1263
        int     minSz = sizeof(signer->pubKeySize) + sizeof(signer->keyOID) +
1264
                      sizeof(signer->nameLen) + sizeof(signer->subjectNameHash);
1265
        #ifndef NO_SKID
1266
                minSz += (int)sizeof(signer->subjectKeyIdHash);
1267
        #endif
1268
1269
        /* Check minimal size of bytes available. */
1270
        if (start + minSz > end) {
1271
            WOLFSSL_MSG("Would overread restore buffer");
1272
            ret = BUFFER_E;
1273
        }
1274
        /* Make a new signer. */
1275
        if ((ret == 0) && ((signer = MakeSigner(cm->heap)) == NULL)) {
1276
            ret = MEMORY_E;
1277
        }
1278
1279
        if (ret == 0) {
1280
            /* Copy in public key size. */
1281
            XMEMCPY(&signer->pubKeySize, current + idx,
1282
                sizeof(signer->pubKeySize));
1283
            idx += (int)sizeof(signer->pubKeySize);
1284
1285
            /* Copy in public key OID. */
1286
            XMEMCPY(&signer->keyOID, current + idx, sizeof(signer->keyOID));
1287
            idx += (int)sizeof(signer->keyOID);
1288
1289
            /* Check bytes available for public key. */
1290
            if (start + minSz + signer->pubKeySize > end) {
1291
                WOLFSSL_MSG("Would overread restore buffer");
1292
                ret = BUFFER_E;
1293
            }
1294
        }
1295
        if (ret == 0) {
1296
            /* Allocate memory for public key to be stored in. */
1297
            publicKey = (byte*)XMALLOC(signer->pubKeySize, cm->heap,
1298
                DYNAMIC_TYPE_KEY);
1299
            if (publicKey == NULL) {
1300
                ret = MEMORY_E;
1301
            }
1302
        }
1303
1304
        if (ret == 0) {
1305
            /* Copy in public key. */
1306
            XMEMCPY(publicKey, current + idx, signer->pubKeySize);
1307
            signer->publicKey = publicKey;
1308
            idx += (int)signer->pubKeySize;
1309
1310
            /* Copy in certificate name length. */
1311
            XMEMCPY(&signer->nameLen, current + idx, sizeof(signer->nameLen));
1312
            idx += (int)sizeof(signer->nameLen);
1313
1314
            /* Check bytes available for certificate name. */
1315
            if (start + minSz + signer->pubKeySize + signer->nameLen > end) {
1316
                WOLFSSL_MSG("Would overread restore buffer");
1317
                ret = BUFFER_E;
1318
            }
1319
        }
1320
        if (ret == 0) {
1321
            /* Allocate memory for public key to be stored in. */
1322
            signer->name = (char*)XMALLOC((size_t)signer->nameLen, cm->heap,
1323
                DYNAMIC_TYPE_SUBJECT_CN);
1324
            if (signer->name == NULL) {
1325
                ret = MEMORY_E;
1326
            }
1327
        }
1328
1329
        if (ret == 0) {
1330
            /* Copy in certificate name. */
1331
            /* safe cast -- allocated by above XMALLOC(). */
1332
            XMEMCPY((void *)(wc_ptr_t)signer->name, current + idx,
1333
                    (size_t)signer->nameLen);
1334
            idx += signer->nameLen;
1335
1336
            /* Copy in hash of subject name. */
1337
            XMEMCPY(signer->subjectNameHash, current + idx, SIGNER_DIGEST_SIZE);
1338
            idx += SIGNER_DIGEST_SIZE;
1339
1340
        #ifndef NO_SKID
1341
            /* Copy in hash of subject key. */
1342
            XMEMCPY(signer->subjectKeyIdHash, current + idx,SIGNER_DIGEST_SIZE);
1343
            idx += SIGNER_DIGEST_SIZE;
1344
        #endif
1345
1346
            /* Make next Signer the head of the row. */
1347
            signer->next = cm->caTable[row];
1348
            /* Add Signer to start of row. */
1349
            cm->caTable[row] = signer;
1350
1351
            /* Done one more Signer. */
1352
            --listSz;
1353
        }
1354
1355
        if ((ret != 0) && (signer != NULL)) {
1356
            /* Dispose of allocated signer. */
1357
            FreeSigner(signer, cm->heap);
1358
        }
1359
    }
1360
1361
    if (ret == 0) {
1362
        /* Return the number of bytes used on success. */
1363
        ret = idx;
1364
    }
1365
    return ret;
1366
}
1367
1368
1369
/* Store whole CA certificate row into memory.
1370
 *
1371
 * Assumes we have locked CA table.
1372
 *
1373
 * @param [in] cm       Certificate manager.
1374
 * @param [in] current  Buffer to write to.
1375
 * @param [in] row      Row number being stored.
1376
 * @return  Number of bytes added.
1377
 */
1378
static WC_INLINE int cm_store_cert_row(WOLFSSL_CERT_MANAGER* cm, byte* current,
1379
    int row)
1380
{
1381
    int     added  = 0;
1382
    Signer* list;
1383
1384
    /* Get the row - a linked list. */
1385
    list  = cm->caTable[row];
1386
    /* Each certificate in row. */
1387
    while (list != NULL) {
1388
        /* Public key size. */
1389
        XMEMCPY(current + added, &list->pubKeySize, sizeof(list->pubKeySize));
1390
        added += (int)sizeof(list->pubKeySize);
1391
1392
        /* Public key OID. */
1393
        XMEMCPY(current + added, &list->keyOID,     sizeof(list->keyOID));
1394
        added += (int)sizeof(list->keyOID);
1395
1396
        /* Public key. */
1397
        XMEMCPY(current + added, list->publicKey, (size_t)list->pubKeySize);
1398
        added += (int)list->pubKeySize;
1399
1400
        /* Certificate name length. */
1401
        XMEMCPY(current + added, &list->nameLen, sizeof(list->nameLen));
1402
        added += (int)sizeof(list->nameLen);
1403
1404
        /* Certificate name. */
1405
        XMEMCPY(current + added, list->name, (size_t)list->nameLen);
1406
        added += list->nameLen;
1407
1408
        /* Hash of subject name. */
1409
        XMEMCPY(current + added, list->subjectNameHash, SIGNER_DIGEST_SIZE);
1410
        added += SIGNER_DIGEST_SIZE;
1411
1412
    #ifndef NO_SKID
1413
        /* Hash of public key. */
1414
        XMEMCPY(current + added, list->subjectKeyIdHash,SIGNER_DIGEST_SIZE);
1415
        added += SIGNER_DIGEST_SIZE;
1416
    #endif
1417
1418
        /* Next certificate in row. */
1419
        list = list->next;
1420
    }
1421
1422
    return added;
1423
}
1424
1425
1426
/* Persist CA certificate cache to memory.
1427
 *
1428
 * Assumes we have locked CA table.
1429
 *
1430
 * @param [in] cm   Certificate manager.
1431
 * @param [in] mem  Memory to persist into.
1432
 * @param [in] sz   Size in bytes of memory.
1433
 * @return  WOLFSSL_SUCCESS on success.
1434
 * @return  BUFFER_E when memory is too small.
1435
 */
1436
static WC_INLINE int cm_do_mem_save_cert_cache(WOLFSSL_CERT_MANAGER* cm,
1437
    void* mem, int sz)
1438
{
1439
    int ret = WOLFSSL_SUCCESS;
1440
    int realSz;
1441
    int i;
1442
1443
    WOLFSSL_ENTER("cm_do_mem_save_cert_cache");
1444
1445
    /* Calculate amount of memory required to store CA certificate table. */
1446
    realSz = cm_get_cert_cache_mem_size(cm);
1447
    if (realSz > sz) {
1448
        WOLFSSL_MSG("Mem output buffer too small");
1449
        ret = BUFFER_E;
1450
    }
1451
    if (ret == WOLFSSL_SUCCESS) {
1452
        byte*           current;
1453
        CertCacheHeader hdr;
1454
1455
        /* Create header for storage. */
1456
        hdr.version  = WOLFSSL_CACHE_CERT_VERSION;
1457
        hdr.rows     = CA_TABLE_SIZE;
1458
        cm_set_cert_header_Columns(cm, hdr.columns);
1459
        hdr.signerSz = (int)sizeof(Signer);
1460
1461
        /* Copy header into memory. */
1462
        XMEMCPY(mem, &hdr, sizeof(CertCacheHeader));
1463
        current = (byte*)mem + sizeof(CertCacheHeader);
1464
1465
        /* Each row of table. */
1466
        for (i = 0; i < CA_TABLE_SIZE; ++i) {
1467
            /* Append row to memory. */
1468
            current += cm_store_cert_row(cm, current, i);
1469
        }
1470
    }
1471
1472
    return ret;
1473
}
1474
1475
1476
#if !defined(NO_FILESYSTEM)
1477
1478
/* Persist CA certificate cache to file.
1479
 *
1480
 * Locks CA table.
1481
 *
1482
 * @param [in] cm     Certificate manager.
1483
 * @param [in] fname  File name to write to.
1484
 * @return  WOLFSSL_SUCCESS on success.
1485
 * @return  WOLFSSL_BAD_FILE when opening file fails.
1486
 * @return  BAD_MUTEX_E when locking fails.
1487
 * @return  MEMORY_E when dynamic memory allocation fails.
1488
 * @return  FWRITE_ERROR when writing to file fails.
1489
 */
1490
int CM_SaveCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
1491
{
1492
    XFILE file;
1493
    int   ret = WOLFSSL_SUCCESS;
1494
1495
    WOLFSSL_ENTER("CM_SaveCertCache");
1496
1497
    /* Open file for writing. */
1498
    file = XFOPEN(fname, "w+b");
1499
    if (file == XBADFILE) {
1500
       WOLFSSL_MSG("Couldn't open cert cache save file");
1501
       ret = WOLFSSL_BAD_FILE;
1502
    }
1503
1504
    /* Lock CA table. */
1505
    if ((ret == WOLFSSL_SUCCESS) && (wc_LockMutex(&cm->caLock) != 0)) {
1506
        WOLFSSL_MSG("wc_LockMutex on caLock failed");
1507
        ret = BAD_MUTEX_E;
1508
    }
1509
1510
    if (ret == WOLFSSL_SUCCESS) {
1511
        byte* mem;
1512
        /* Calculate size of memory required to store CA table. */
1513
        size_t memSz = (size_t)cm_get_cert_cache_mem_size(cm);
1514
        /* Allocate memory to hold CA table. */
1515
        mem = (byte*)XMALLOC(memSz, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
1516
        if (mem == NULL) {
1517
            WOLFSSL_MSG("Alloc for tmp buffer failed");
1518
            ret = MEMORY_E;
1519
        }
1520
        if (ret == WOLFSSL_SUCCESS) {
1521
            /* Store CA table in memory. */
1522
            ret = cm_do_mem_save_cert_cache(cm, mem, (int)memSz);
1523
        }
1524
        if (ret == WOLFSSL_SUCCESS) {
1525
            /* Write memory to file. */
1526
            int sz = (int)XFWRITE(mem, memSz, 1, file);
1527
            if (sz != 1) {
1528
                WOLFSSL_MSG("Cert cache file write failed");
1529
                ret = FWRITE_ERROR;
1530
            }
1531
        }
1532
        XFREE(mem, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
1533
1534
        /* Unlock CA table. */
1535
        wc_UnLockMutex(&cm->caLock);
1536
    }
1537
1538
    /* Close file. */
1539
    if (file != XBADFILE) {
1540
        XFCLOSE(file);
1541
    }
1542
    return ret;
1543
}
1544
1545
1546
/* Restore CA certificate cache from file.
1547
 *
1548
 * @param [in] cm     Certificate manager.
1549
 * @param [in] fname  File name to write to.
1550
 * @return  WOLFSSL_SUCCESS on success.
1551
 * @return  WOLFSSL_BAD_FILE when opening or using file fails.
1552
 * @return  MEMORY_E when dynamic memory allocation fails.
1553
 * @return  FREAD_ERROR when reading from file fails.
1554
 */
1555
int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
1556
{
1557
    XFILE file;
1558
    int   ret = WOLFSSL_SUCCESS;
1559
    int   memSz = 0;
1560
    byte* mem = NULL;
1561
1562
    WOLFSSL_ENTER("CM_RestoreCertCache");
1563
1564
    /* Open file for reading. */
1565
    file = XFOPEN(fname, "rb");
1566
    if (file == XBADFILE) {
1567
       WOLFSSL_MSG("Couldn't open cert cache save file");
1568
       ret = WOLFSSL_BAD_FILE;
1569
    }
1570
1571
    if (ret == WOLFSSL_SUCCESS) {
1572
        /* Read file into allocated memory. */
1573
        ret = wolfssl_read_file(file, (char**)&mem, &memSz);
1574
        if (ret == 0) {
1575
            ret = WOLFSSL_SUCCESS;
1576
        }
1577
    }
1578
    if (ret == WOLFSSL_SUCCESS) {
1579
        /* Create the CA certificate table from memory. */
1580
        ret = CM_MemRestoreCertCache(cm, mem, memSz);
1581
        if (ret != WOLFSSL_SUCCESS) {
1582
            WOLFSSL_MSG("Mem restore cert cache failed");
1583
        }
1584
    }
1585
1586
    /* Dispose of dynamic memory read into. */
1587
    XFREE(mem, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
1588
    /* Close file. */
1589
    if (file != XBADFILE) {
1590
        XFCLOSE(file);
1591
    }
1592
    return ret;
1593
}
1594
1595
#endif /* NO_FILESYSTEM */
1596
1597
1598
/* Persist CA certificate cache to memory.
1599
 *
1600
 * Locks CA table.
1601
 *
1602
 * @param [in]  cm    Certificate manager.
1603
 * @param [in]  mem   Memory to persist into.
1604
 * @param [in]  sz    Size in bytes of memory.
1605
 * @param [out] used  Number of bytes used when persisting cache.
1606
 * @return  WOLFSSL_SUCCESS on success.
1607
 * @return  BAD_MUTEX_E when locking fails.
1608
 * @return  BUFFER_E when memory is too small.
1609
 */
1610
int CM_MemSaveCertCache(WOLFSSL_CERT_MANAGER* cm, void* mem, int sz, int* used)
1611
{
1612
    int ret = WOLFSSL_SUCCESS;
1613
1614
    WOLFSSL_ENTER("CM_MemSaveCertCache");
1615
1616
    /* Lock CA table. */
1617
    if (wc_LockMutex(&cm->caLock) != 0) {
1618
        WOLFSSL_MSG("wc_LockMutex on caLock failed");
1619
        ret = BAD_MUTEX_E;
1620
    }
1621
    if (ret == WOLFSSL_SUCCESS) {
1622
        /* Save CA table into memory. */
1623
        ret = cm_do_mem_save_cert_cache(cm, mem, sz);
1624
        if (ret == WOLFSSL_SUCCESS) {
1625
            /* Get the number of bytes used. */
1626
            *used  = cm_get_cert_cache_mem_size(cm);
1627
        }
1628
1629
        /* Unlock CA table. */
1630
        wc_UnLockMutex(&cm->caLock);
1631
    }
1632
1633
    return ret;
1634
}
1635
1636
1637
/* Restore CA certificate table from memory,
1638
 *
1639
 * Locks CA table.
1640
 *
1641
 * @param [in] cm   Certificate manager.
1642
 * @param [in] mem  Buffer containing rows.
1643
 * @param [in] sz   Size in bytes of data in buffer.
1644
 * @return  WOLFSSL_SUCCESS on success.
1645
 * @return  BUFFER_E when buffer is too small.
1646
 * @return  BAD_MUTEX_E when locking fails.
1647
 * @return  MEMORY_E when dynamic memory allocation fails.
1648
 */
1649
int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const void* mem, int sz)
1650
{
1651
    int ret = WOLFSSL_SUCCESS;
1652
    int i;
1653
    CertCacheHeader* hdr = (CertCacheHeader*)mem;
1654
    byte*            current = (byte*)mem + sizeof(CertCacheHeader);
1655
    byte*            end     = (byte*)mem + sz;  /* don't go over */
1656
1657
    WOLFSSL_ENTER("CM_MemRestoreCertCache");
1658
1659
    /* Check memory available is bigger than cache header. */
1660
    if ((sz < (int)sizeof(CertCacheHeader)) || (current > end)) {
1661
        WOLFSSL_MSG("Cert Cache Memory buffer too small");
1662
        ret = BUFFER_E;
1663
    }
1664
1665
    /* Validate the cache header. */
1666
    if ((ret == WOLFSSL_SUCCESS) &&
1667
            ((hdr->version  != WOLFSSL_CACHE_CERT_VERSION) ||
1668
             (hdr->rows     != CA_TABLE_SIZE) ||
1669
             (hdr->signerSz != (int)sizeof(Signer)))) {
1670
        WOLFSSL_MSG("Cert Cache Memory header mismatch");
1671
        ret = CACHE_MATCH_ERROR;
1672
    }
1673
1674
    /* Lock CA table. */
1675
    if ((ret == WOLFSSL_SUCCESS) && (wc_LockMutex(&cm->caLock) != 0)) {
1676
        WOLFSSL_MSG("wc_LockMutex on caLock failed");
1677
        ret = BAD_MUTEX_E;
1678
    }
1679
1680
    if (ret == WOLFSSL_SUCCESS) {
1681
        /* Dispose of current CA certificate table. */
1682
        FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
1683
1684
        /* Each row. */
1685
        for (i = 0; i < CA_TABLE_SIZE; ++i) {
1686
            /* Restore a row from memory. */
1687
            int added = cm_restore_cert_row(cm, current, i, hdr->columns[i],
1688
                end);
1689
            /* Bail on error. */
1690
            if (added < 0) {
1691
                WOLFSSL_MSG("cm_restore_cert_row error");
1692
                ret = added;
1693
                break;
1694
            }
1695
            /* Update pointer to data of next row. */
1696
            current += added;
1697
        }
1698
1699
        /* Unlock CA table. */
1700
        wc_UnLockMutex(&cm->caLock);
1701
    }
1702
1703
    return ret;
1704
}
1705
1706
1707
/* Calculate size of CA certificate cache when persisted to memory.
1708
 *
1709
 * Locks CA table.
1710
 *
1711
 * @param [in] cm  Certificate manager.
1712
 * @return  Number of bytes on success.
1713
 * @return  BAD_MUTEX_E when locking fails.
1714
 */
1715
int CM_GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm)
1716
{
1717
    int ret;
1718
1719
    WOLFSSL_ENTER("CM_GetCertCacheMemSize");
1720
1721
    /* Lock CA table. */
1722
    if (wc_LockMutex(&cm->caLock) != 0) {
1723
        WOLFSSL_MSG("wc_LockMutex on caLock failed");
1724
        ret = BAD_MUTEX_E;
1725
    }
1726
    else {
1727
        /* Calculate memory size. */
1728
        ret = cm_get_cert_cache_mem_size(cm);
1729
1730
        /* Unlock CA table. */
1731
        wc_UnLockMutex(&cm->caLock);
1732
    }
1733
1734
    return ret;
1735
}
1736
1737
#endif /* PERSIST_CERT_CACHE */
1738
1739
/*******************************************************************************
1740
 * CRL handling
1741
 ******************************************************************************/
1742
1743
/* Enables/disables the use of CRLs when validating certificates.
1744
 *
1745
 * @param [in] cm       Certificate manager.
1746
 * @param [in] options  Options for using CRLs. Valid flags:
1747
 *                        WOLFSSL_CRL_CHECKALL, WOLFSSL_CRL_CHECK.
1748
 * @return  WOLFSSL_SUCCESS on success.
1749
 * @return  WOLFSSL_FAILURE when initializing the CRL object fails.
1750
 * @return  BAD_FUNC_ARG when cm is NULL.
1751
 * @return  BAD_MUTEX_E when locking the certificate manager fails.
1752
 * @return  MEMORY_E when dynamic memory allocation fails.
1753
 * @return  NOT_COMPILED_IN when the CRL feature is disabled.
1754
 */
1755
int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER* cm, int options)
1756
0
{
1757
0
    int ret = WOLFSSL_SUCCESS;
1758
1759
0
    WOLFSSL_ENTER("wolfSSL_CertManagerEnableCRL");
1760
1761
0
    (void)options;
1762
1763
    /* Validate parameters. */
1764
0
    if (cm == NULL) {
1765
0
        ret = BAD_FUNC_ARG;
1766
0
    }
1767
1768
#if defined(OPENSSL_COMPATIBLE_DEFAULTS)
1769
    /* If disabling then don't worry about whether CRL feature is enabled. */
1770
    if ((ret == WOLFSSL_SUCCESS) && (options == 0)) {
1771
        /* Disable leaf CRL check. */
1772
        cm->crlEnabled = 0;
1773
        /* Disable all CRL checks. */
1774
        cm->crlCheckAll = 0;
1775
    }
1776
    else
1777
#endif
1778
0
    if (ret == WOLFSSL_SUCCESS) {
1779
0
#ifndef HAVE_CRL
1780
        /* CRL feature not enabled. */
1781
0
        ret = NOT_COMPILED_IN;
1782
#else
1783
        /* Create CRL object if not present. */
1784
        if (cm->crl == NULL) {
1785
            WOLFSSL_CRL* crl;
1786
1787
            /* Serialize creation so that concurrent callers cannot both
1788
             * allocate a CRL object. */
1789
            if (wc_LockMutex(&cm->caLock) != 0) {
1790
                WOLFSSL_MSG("wc_LockMutex on caLock failed");
1791
                ret = BAD_MUTEX_E;
1792
            }
1793
            else {
1794
                /* Another thread may have created the object already. */
1795
                if (cm->crl == NULL) {
1796
                    /* Allocate memory for CRL object. */
1797
                    crl = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), cm->heap,
1798
                                                DYNAMIC_TYPE_CRL);
1799
                    if (crl == NULL) {
1800
                        ret = MEMORY_E;
1801
                    }
1802
                    else {
1803
                        /* Reset fields of CRL object. */
1804
                        XMEMSET(crl, 0, sizeof(WOLFSSL_CRL));
1805
                        /* Initialize CRL object. */
1806
                        if (InitCRL(crl, cm) != 0) {
1807
                            WOLFSSL_MSG("Init CRL failed");
1808
                            /* A failed InitCRL() has already released whatever
1809
                             * it managed to take, so only the memory is left
1810
                             * to dispose of. FreeCRL() would free the lock and
1811
                             * the condition variable a second time. */
1812
                            XFREE(crl, cm->heap, DYNAMIC_TYPE_CRL);
1813
                            ret = WOLFSSL_FAILURE;
1814
                        }
1815
                        else {
1816
                        #if defined(HAVE_CRL_IO) && defined(USE_WOLFSSL_IO)
1817
                            /* Set before publishing: a thread that picks the
1818
                             * object up must not find it without a lookup
1819
                             * callback and fall back to CRL_MISSING. */
1820
                            crl->crlIOCb = EmbedCrlLookup;
1821
                        #endif
1822
                            /* Publish only once fully initialized so that
1823
                             * other threads never see a half-built object. */
1824
                            cm->crl = crl;
1825
                        }
1826
                    }
1827
                }
1828
                wc_UnLockMutex(&cm->caLock);
1829
            }
1830
        }
1831
1832
        if (ret == WOLFSSL_SUCCESS) {
1833
        #if defined(HAVE_CRL_IO) && defined(USE_WOLFSSL_IO)
1834
            /* Redundant for an object created above, but the CRL object can
1835
             * also have been published by wolfSSL_X509_STORE_add_crl(), which
1836
             * does not set the lookup callback. */
1837
            cm->crl->crlIOCb = EmbedCrlLookup;
1838
        #endif
1839
        #if defined(OPENSSL_COMPATIBLE_DEFAULTS)
1840
            if ((options & WOLFSSL_CRL_CHECKALL) ||
1841
                (options & WOLFSSL_CRL_CHECK))
1842
        #endif
1843
            {
1844
                /* Enable leaf CRL check. */
1845
                cm->crlEnabled = 1;
1846
                if (options & WOLFSSL_CRL_CHECKALL) {
1847
                    /* Enable all CRL check. */
1848
                    cm->crlCheckAll = 1;
1849
                }
1850
            }
1851
        }
1852
#endif
1853
0
    }
1854
1855
0
    return ret;
1856
0
}
1857
1858
1859
/* Disables the CRL checks.
1860
 *
1861
 * @param [in] cm  Certificate manager.
1862
 * @return  WOLFSSL_SUCCESS on success.
1863
 * @return  BAD_FUNC_ARG when cm is NULL.
1864
 */
1865
int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER* cm)
1866
0
{
1867
0
    int ret = WOLFSSL_SUCCESS;
1868
1869
0
    WOLFSSL_ENTER("wolfSSL_CertManagerDisableCRL");
1870
1871
    /* Validate parameter. */
1872
0
    if (cm == NULL) {
1873
0
        ret = BAD_FUNC_ARG;
1874
0
    }
1875
0
    if (ret == WOLFSSL_SUCCESS) {
1876
        /* Disable CRL checking. */
1877
0
        cm->crlEnabled = 0;
1878
0
        cm->crlCheckAll = 0;
1879
0
    }
1880
1881
0
    return ret;
1882
0
}
1883
1884
#ifdef HAVE_CRL
1885
1886
/* Load CRL for use.
1887
 *
1888
 * @param [in] cm    Certificate manager.
1889
 * @param [in] buff  Buffer holding CRL.
1890
 * @param [in] sz    Size in bytes of CRL in buffer.
1891
 * @param [in] type  Format of encoding. Valid values:
1892
 *                     WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
1893
 * @return  WOLFSSL_SUCCESS on success.
1894
 * @return  BAD_FUNC_ARG when cm or buff is NULL or sz is negative or zero.
1895
 * @return  DUPE_ENTRY_E if the same or a newer CRL already exists in the cm.
1896
 * @return  WOLFSSL_FATAL_ERROR when creating CRL object fails.
1897
 */
1898
int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER* cm,
1899
    const unsigned char* buff, long sz, int type)
1900
{
1901
    int ret = WOLFSSL_SUCCESS;
1902
1903
    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRLBuffer");
1904
1905
    /* Validate parameters. */
1906
    if ((cm == NULL) || (buff == NULL) || (sz <= 0)) {
1907
        ret = BAD_FUNC_ARG;
1908
    }
1909
1910
    /* Create a CRL object if not available and enable CRL checking. */
1911
    if ((ret == WOLFSSL_SUCCESS) && (cm->crl == NULL) &&
1912
            (wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK) !=
1913
             WOLFSSL_SUCCESS)) {
1914
        WOLFSSL_MSG("Enable CRL failed");
1915
        ret = WOLFSSL_FATAL_ERROR;
1916
    }
1917
1918
    if (ret == WOLFSSL_SUCCESS) {
1919
        /* Load CRL into CRL object of the certificate manager. */
1920
        ret = BufferLoadCRL(cm->crl, buff, sz, type, VERIFY);
1921
    }
1922
1923
    return ret;
1924
}
1925
1926
/* Free the CRL object of the certificate manager.
1927
 *
1928
 * @param [in] cm  Certificate manager.
1929
 * @return  WOLFSSL_SUCCESS on success.
1930
 * @return  BAD_FUNC_ARG when cm is NULL.
1931
 */
1932
int wolfSSL_CertManagerFreeCRL(WOLFSSL_CERT_MANAGER* cm)
1933
{
1934
    int ret = WOLFSSL_SUCCESS;
1935
1936
    WOLFSSL_ENTER("wolfSSL_CertManagerFreeCRL");
1937
1938
    /* Validate parameter. */
1939
    if (cm == NULL) {
1940
        ret = BAD_FUNC_ARG;
1941
    }
1942
    /* Check whether CRL object exists. */
1943
    if ((ret == WOLFSSL_SUCCESS) && (cm->crl != NULL)) {
1944
        /* Dispose of CRL object - indicating dynamically allocated. */
1945
        FreeCRL(cm->crl, 1);
1946
        cm->crl = NULL;
1947
    }
1948
1949
    return ret;
1950
}
1951
1952
/* Check DER encoded certificate against CRLs if checking enabled.
1953
 *
1954
 * @param [in] cm   Certificate manager.
1955
 * @param [in] der  DER encode certificate.
1956
 * @param [in] sz   Size in bytes of DER encode certificate.
1957
 * @return  WOLFSSL_SUCCESS on success.
1958
 * @return  BAD_FUNC_ARG when cm or der is NULL or sz is negative or zero.
1959
 * @return  MEMORY_E when dynamic memory allocation fails.
1960
 */
1961
int wolfSSL_CertManagerCheckCRL(WOLFSSL_CERT_MANAGER* cm,
1962
    const unsigned char* der, int sz)
1963
{
1964
    int ret = 0;
1965
    WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
1966
1967
    WOLFSSL_ENTER("wolfSSL_CertManagerCheckCRL");
1968
1969
    /* Validate parameters. */
1970
    if ((cm == NULL) || (der == NULL) || (sz <= 0)) {
1971
        ret = BAD_FUNC_ARG;
1972
    }
1973
1974
    /* Check if CRL checking enabled. */
1975
    if ((ret == 0) && cm->crlEnabled) {
1976
        /* Allocate memory for decoded certificate. */
1977
        WC_ALLOC_VAR_EX(cert, DecodedCert, 1, NULL, DYNAMIC_TYPE_DCERT,
1978
            ret=MEMORY_E);
1979
        if (WC_VAR_OK(cert))
1980
        {
1981
            /* Initialize decoded certificate with buffer. */
1982
            InitDecodedCert(cert, der, (word32)sz, NULL);
1983
1984
            /* Parse certificate and perform CRL checks. */
1985
            ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_CRL, cm, NULL);
1986
            if (ret != 0) {
1987
                WOLFSSL_MSG("ParseCert failed");
1988
            }
1989
            /* Do CRL checks with decoded certificate. */
1990
            else if ((ret = CheckCertCRL(cm->crl, cert)) != 0) {
1991
                WOLFSSL_MSG("CheckCertCRL failed");
1992
            }
1993
1994
            /* Dispose of dynamically allocated memory. */
1995
            FreeDecodedCert(cert);
1996
            WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
1997
        }
1998
    }
1999
2000
    return (ret == 0) ? WOLFSSL_SUCCESS : ret;
2001
}
2002
2003
/* Set the missing CRL callback.
2004
 *
2005
 * @param [in] cm  Certificate manager.
2006
 * @param [in] cb  Missing CRL callback.
2007
 * @return  WOLFSSL_SUCCESS on success.
2008
 * @return  BAD_FUNC_ARG when cm is NULL.
2009
 */
2010
int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER* cm, CbMissingCRL cb)
2011
{
2012
    int ret = WOLFSSL_SUCCESS;
2013
2014
    WOLFSSL_ENTER("wolfSSL_CertManagerSetCRL_Cb");
2015
2016
    /* Validate parameters. */
2017
    if (cm == NULL) {
2018
        ret = BAD_FUNC_ARG;
2019
    }
2020
    if (ret == WOLFSSL_SUCCESS) {
2021
        /* Store callback. */
2022
        cm->cbMissingCRL = cb;
2023
    }
2024
2025
    return ret;
2026
}
2027
2028
int wolfSSL_CertManagerSetCRL_ErrorCb(WOLFSSL_CERT_MANAGER* cm, crlErrorCb cb,
2029
                                      void* ctx)
2030
{
2031
    int ret = WOLFSSL_SUCCESS;
2032
2033
    WOLFSSL_ENTER("wolfSSL_CertManagerSetCRL_Cb");
2034
2035
    /* Validate parameters. */
2036
    if (cm == NULL) {
2037
        ret = BAD_FUNC_ARG;
2038
    }
2039
    if (ret == WOLFSSL_SUCCESS) {
2040
        /* Store callback. */
2041
        cm->crlCb = cb;
2042
        cm->crlCbCtx = ctx;
2043
    }
2044
2045
    return ret;
2046
}
2047
2048
#ifdef HAVE_CRL_UPDATE_CB
2049
int wolfSSL_CertManagerGetCRLInfo(WOLFSSL_CERT_MANAGER* cm, CrlInfo* info,
2050
    const byte* buff, long sz, int type)
2051
{
2052
    return GetCRLInfo(cm->crl, info, buff, sz, type);
2053
}
2054
2055
/* Set the callback to be called when a CRL entry has
2056
 * been updated (new entry had the same issuer hash and
2057
 * a newer CRL number).
2058
 *
2059
 * @param [in] cm  Certificate manager.
2060
 * @param [in] cb  CRL update callback.
2061
 * @return  WOLFSSL_SUCCESS on success.
2062
 * @return  BAD_FUNC_ARG when cm is NULL.
2063
 */
2064
int wolfSSL_CertManagerSetCRLUpdate_Cb(WOLFSSL_CERT_MANAGER* cm, CbUpdateCRL cb)
2065
{
2066
    int ret = WOLFSSL_SUCCESS;
2067
2068
    WOLFSSL_ENTER("wolfSSL_CertManagerSetCRLUpdate_Cb");
2069
2070
    /* Validate parameters. */
2071
    if (cm == NULL) {
2072
        ret = BAD_FUNC_ARG;
2073
    }
2074
    if (ret == WOLFSSL_SUCCESS) {
2075
        /* Store callback. */
2076
        cm->cbUpdateCRL = cb;
2077
    }
2078
2079
    return ret;
2080
}
2081
#endif
2082
2083
#ifdef HAVE_CRL_IO
2084
/* Set the CRL I/O callback.
2085
 *
2086
 * @param [in] cm  Certificate manager.
2087
 * @param [in] cb  CRL I/O callback.
2088
 * @return  WOLFSSL_SUCCESS on success.
2089
 * @return  BAD_FUNC_ARG when cm is NULL.
2090
 */
2091
int wolfSSL_CertManagerSetCRL_IOCb(WOLFSSL_CERT_MANAGER* cm, CbCrlIO cb)
2092
{
2093
    int ret = WOLFSSL_SUCCESS;
2094
2095
    /* Validate parameters. */
2096
    if (cm == NULL) {
2097
        ret = BAD_FUNC_ARG;
2098
    }
2099
    if ((ret == WOLFSSL_SUCCESS) && (cm->crl != NULL)) {
2100
        /* Store callback. */
2101
        cm->crl->crlIOCb = cb;
2102
    }
2103
2104
    return ret;
2105
}
2106
#endif
2107
2108
#ifndef NO_FILESYSTEM
2109
/* Load CRL/s from path with the option of monitoring for changes.
2110
 *
2111
 * @param [in] cm       Certificate manager.
2112
 * @param [in] path     Path to a directory containing CRLs.
2113
 * @param [in] type     Format of encoding. Valid values:
2114
 *                        WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
2115
 * @param [in] monitor  Whether to monitor path for changes to files.
2116
 * @return  WOLFSSL_SUCCESS on success.
2117
 * @return  BAD_FUNC_ARG when cm or path is NULL.
2118
 * @return  WOLFSSL_FATAL_ERROR when enabling CRLs fails.
2119
 */
2120
int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER* cm, const char* path,
2121
    int type, int monitor)
2122
{
2123
    int ret = WOLFSSL_SUCCESS;
2124
2125
    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRL");
2126
2127
    /* Validate parameters. */
2128
    if ((cm == NULL) || (path == NULL)) {
2129
        ret = BAD_FUNC_ARG;
2130
    }
2131
2132
    /* Create a CRL object if not available. */
2133
    if ((ret == WOLFSSL_SUCCESS) && (cm->crl == NULL) &&
2134
            (wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK) !=
2135
             WOLFSSL_SUCCESS)) {
2136
        WOLFSSL_MSG("Enable CRL failed");
2137
        ret = WOLFSSL_FATAL_ERROR;
2138
    }
2139
2140
    if (ret == WOLFSSL_SUCCESS) {
2141
        /* Load CRLs from path into CRL object of certificate manager. */
2142
        ret = LoadCRL(cm->crl, path, type, monitor);
2143
    }
2144
2145
    return ret;
2146
}
2147
2148
/* Load CRL from file.
2149
 *
2150
 * @param [in] cm    Certificate manager.
2151
 * @param [in] file  Path to a directory containing CRLs.
2152
 * @param [in] type  Format of encoding. Valid values:
2153
 *                       WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
2154
 * @return  WOLFSSL_SUCCESS on success.
2155
 * @return  BAD_FUNC_ARG when cm or file is NULL.
2156
 * @return  WOLFSSL_FATAL_ERROR when enabling CRLs fails.
2157
 */
2158
int wolfSSL_CertManagerLoadCRLFile(WOLFSSL_CERT_MANAGER* cm, const char* file,
2159
    int type)
2160
{
2161
    int ret = WOLFSSL_SUCCESS;
2162
2163
    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRLFile");
2164
2165
    /* Validate parameters. */
2166
    if ((cm == NULL) || (file == NULL)) {
2167
        ret = BAD_FUNC_ARG;
2168
    }
2169
2170
    /* Create a CRL object if not available. */
2171
    if ((ret == WOLFSSL_SUCCESS) && (cm->crl == NULL) &&
2172
            (wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK) !=
2173
             WOLFSSL_SUCCESS)) {
2174
        WOLFSSL_MSG("Enable CRL failed");
2175
        ret = WOLFSSL_FATAL_ERROR;
2176
    }
2177
2178
    if (ret == WOLFSSL_SUCCESS) {
2179
        /* Load CRL file into CRL object of certificate manager. */
2180
        ret = ProcessFile(NULL, file, type, CRL_TYPE, NULL, 0, cm->crl, VERIFY);
2181
    }
2182
2183
    return ret;
2184
}
2185
#endif /* !NO_FILESYSTEM */
2186
2187
#endif /* HAVE_CRL */
2188
2189
/*******************************************************************************
2190
 * OCSP handling
2191
 ******************************************************************************/
2192
2193
/* Enables OCSP when validating certificates and sets options.
2194
 *
2195
 * @param [in] cm       Certificate manager.
2196
 * @param [in] options  Options for using OCSP. Valid flags:
2197
 *                        WOLFSSL_OCSP_URL_OVERRIDE, WOLFSSL_OCSP_NO_NONCE,
2198
 *                        WOLFSSL_OCSP_CHECKALL,
2199
 *                        WOLFSSL_OCSP_FAIL_IF_NOT_SUPPORTED.
2200
 * @return  WOLFSSL_SUCCESS on success.
2201
 * @return  WOLFSSL_FAILURE when initializing the OCSP object fails.
2202
 * @return  BAD_FUNC_ARG when cm is NULL.
2203
 * @return  BAD_MUTEX_E when locking the certificate manager fails.
2204
 * @return  MEMORY_E when dynamic memory allocation fails.
2205
 * @return  NOT_COMPILED_IN when the OCSP feature is disabled.
2206
 */
2207
int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER* cm, int options)
2208
0
{
2209
0
    int ret = WOLFSSL_SUCCESS;
2210
2211
0
    (void)options;
2212
2213
0
    WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSP");
2214
2215
    /* Validate parameters. */
2216
0
    if (cm == NULL) {
2217
0
        ret = BAD_FUNC_ARG;
2218
0
    }
2219
2220
#ifndef HAVE_OCSP
2221
    if (ret == WOLFSSL_SUCCESS) {
2222
        /* OCSP feature not enabled. */
2223
        ret = NOT_COMPILED_IN;
2224
    }
2225
#else
2226
0
    if (ret == WOLFSSL_SUCCESS) {
2227
        /* Check whether OCSP object is available. */
2228
0
        if (cm->ocsp == NULL) {
2229
0
            WOLFSSL_OCSP* ocsp;
2230
2231
            /* Serialize creation so that concurrent callers cannot both
2232
             * allocate an OCSP object. */
2233
0
            if (wc_LockMutex(&cm->caLock) != 0) {
2234
0
                WOLFSSL_MSG("wc_LockMutex on caLock failed");
2235
0
                ret = BAD_MUTEX_E;
2236
0
            }
2237
0
            else {
2238
                /* Another thread may have created the object already. */
2239
0
                if (cm->ocsp == NULL) {
2240
                    /* Allocate memory for OCSP object. */
2241
0
                    ocsp = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP),
2242
0
                        cm->heap, DYNAMIC_TYPE_OCSP);
2243
0
                    if (ocsp == NULL) {
2244
0
                        ret = MEMORY_E;
2245
0
                    }
2246
0
                    else {
2247
                        /* Reset the fields of the OCSP object. */
2248
0
                        XMEMSET(ocsp, 0, sizeof(WOLFSSL_OCSP));
2249
                        /* Initialize the OCSP object. */
2250
0
                        if (InitOCSP(ocsp, cm) != 0) {
2251
0
                            WOLFSSL_MSG("Init OCSP failed");
2252
                            /* InitOCSP() only fails when it could not create
2253
                             * the lock, so there is nothing to release but the
2254
                             * memory. FreeOCSP() would destroy a mutex that was
2255
                             * never initialized. */
2256
0
                            XFREE(ocsp, cm->heap, DYNAMIC_TYPE_OCSP);
2257
0
                            ret = WOLFSSL_FAILURE;
2258
0
                        }
2259
0
                        else {
2260
                            /* Publish only once fully initialized so that
2261
                             * other threads never see a half-built object. */
2262
0
                            cm->ocsp = ocsp;
2263
0
                        }
2264
0
                    }
2265
0
                }
2266
0
                wc_UnLockMutex(&cm->caLock);
2267
0
            }
2268
0
        }
2269
0
    }
2270
0
    if (ret == WOLFSSL_SUCCESS) {
2271
        /* Enable OCSP checking. */
2272
0
        cm->ocspEnabled = 1;
2273
        /* Enable URL override if requested. */
2274
0
        if (options & WOLFSSL_OCSP_URL_OVERRIDE) {
2275
0
            cm->ocspUseOverrideURL = 1;
2276
0
        }
2277
        /* Set nonce option for creating OCSP requests. */
2278
0
        cm->ocspSendNonce = (options & WOLFSSL_OCSP_NO_NONCE) !=
2279
0
            WOLFSSL_OCSP_NO_NONCE;
2280
        /* Set all OCSP checks on if requested. */
2281
0
        if (options & WOLFSSL_OCSP_CHECKALL) {
2282
0
            cm->ocspCheckAll = 1;
2283
0
        }
2284
        /* Fail closed on certs that advertise no OCSP responder if requested. */
2285
0
        if (options & WOLFSSL_OCSP_FAIL_IF_NOT_SUPPORTED) {
2286
0
            cm->ocspFailIfNotSupported = 1;
2287
0
        }
2288
0
    #ifndef WOLFSSL_USER_IO
2289
        /* Set built-in OCSP lookup. */
2290
0
        cm->ocspIOCb = EmbedOcspLookup;
2291
0
        cm->ocspRespFreeCb = EmbedOcspRespFree;
2292
0
        cm->ocspIOCtx = cm->heap;
2293
0
    #endif /* WOLFSSL_USER_IO */
2294
0
    }
2295
0
#endif /* HAVE_OCSP */
2296
2297
0
    return ret;
2298
0
}
2299
2300
/* Disables the OCSP checks.
2301
 *
2302
 * @param [in] cm  Certificate manager.
2303
 * @return  WOLFSSL_SUCCESS on success.
2304
 * @return  BAD_FUNC_ARG when cm is NULL.
2305
 */
2306
int wolfSSL_CertManagerDisableOCSP(WOLFSSL_CERT_MANAGER* cm)
2307
0
{
2308
0
    int ret = WOLFSSL_SUCCESS;
2309
2310
0
    WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSP");
2311
2312
    /* Validate parameter. */
2313
0
    if (cm == NULL) {
2314
0
        ret = BAD_FUNC_ARG;
2315
0
    }
2316
0
    if (ret == WOLFSSL_SUCCESS) {
2317
        /* Disable use of OCSP with certificate validation. */
2318
0
        cm->ocspEnabled = 0;
2319
0
    }
2320
2321
0
    return ret;
2322
0
}
2323
2324
/* Enables OCSP stapling with certificates in manager.
2325
 *
2326
 * @param [in] cm       Certificate manager.
2327
 * @param [in] options  Options for using OCSP. Valid flags:
2328
 *                        WOLFSSL_OCSP_URL_OVERRIDE, WOLFSSL_OCSP_NO_NONCE,
2329
 *                        WOLFSSL_OCSP_CHECKALL.
2330
 * @return  WOLFSSL_SUCCESS on success.
2331
 * @return  WOLFSSL_FAILURE when initializing the OCSP stapling object fails.
2332
 * @return  BAD_FUNC_ARG when cm is NULL.
2333
 * @return  BAD_MUTEX_E when locking the certificate manager fails.
2334
 * @return  MEMORY_E when dynamic memory allocation fails.
2335
 * @return  NOT_COMPILED_IN when the OCSP stapling feature is disabled.
2336
 */
2337
int wolfSSL_CertManagerEnableOCSPStapling(WOLFSSL_CERT_MANAGER* cm)
2338
0
{
2339
0
    int ret = WOLFSSL_SUCCESS;
2340
2341
0
    WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSPStapling");
2342
2343
    /* Validate parameters. */
2344
0
    if (cm == NULL) {
2345
0
        ret = BAD_FUNC_ARG;
2346
0
    }
2347
2348
0
#if !defined(HAVE_CERTIFICATE_STATUS_REQUEST) && \
2349
0
    !defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
2350
0
    if (ret == WOLFSSL_SUCCESS) {
2351
        /* OCSP stapling feature not enabled. */
2352
0
        ret = NOT_COMPILED_IN;
2353
0
    }
2354
#else
2355
#ifndef NO_WOLFSSL_SERVER
2356
    if (ret == WOLFSSL_SUCCESS) {
2357
        /* Check whether OCSP object is available. */
2358
        if (cm->ocsp_stapling == NULL) {
2359
            WOLFSSL_OCSP* ocsp;
2360
2361
            /* Serialize creation so that concurrent callers cannot both
2362
             * allocate an OCSP stapling object. */
2363
            if (wc_LockMutex(&cm->caLock) != 0) {
2364
                WOLFSSL_MSG("wc_LockMutex on caLock failed");
2365
                ret = BAD_MUTEX_E;
2366
            }
2367
            else {
2368
                /* Another thread may have created the object already. */
2369
                if (cm->ocsp_stapling == NULL) {
2370
                    /* Allocate memory for OCSP stapling object. */
2371
                    ocsp = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP),
2372
                        cm->heap, DYNAMIC_TYPE_OCSP);
2373
                    if (ocsp == NULL) {
2374
                        ret = MEMORY_E;
2375
                    }
2376
                    else {
2377
                        /* Reset the fields of the OCSP object. */
2378
                        XMEMSET(ocsp, 0, sizeof(WOLFSSL_OCSP));
2379
                        /* Initialize the OCSP stapling object. */
2380
                        if (InitOCSP(ocsp, cm) != 0) {
2381
                            WOLFSSL_MSG("Init OCSP failed");
2382
                            /* InitOCSP() only fails when it could not create
2383
                             * the lock, so there is nothing to release but the
2384
                             * memory. FreeOCSP() would destroy a mutex that was
2385
                             * never initialized. */
2386
                            XFREE(ocsp, cm->heap, DYNAMIC_TYPE_OCSP);
2387
                            ret = WOLFSSL_FAILURE;
2388
                        }
2389
                        else {
2390
                            /* Publish only once fully initialized so that
2391
                             * other threads never see a half-built object. */
2392
                            cm->ocsp_stapling = ocsp;
2393
                        }
2394
                    }
2395
                }
2396
                wc_UnLockMutex(&cm->caLock);
2397
            }
2398
        }
2399
    }
2400
#ifndef WOLFSSL_USER_IO
2401
    if (ret == WOLFSSL_SUCCESS) {
2402
        /* Set built-in OCSP lookup. */
2403
        cm->ocspIOCb = EmbedOcspLookup;
2404
        cm->ocspRespFreeCb = EmbedOcspRespFree;
2405
        cm->ocspIOCtx = cm->heap;
2406
    }
2407
#endif /* WOLFSSL_USER_IO */
2408
#endif /* NO_WOLFSSL_SERVER */
2409
    if (ret == WOLFSSL_SUCCESS) {
2410
        /* Enable OCSP stapling. */
2411
        cm->ocspStaplingEnabled = 1;
2412
    }
2413
#endif /* HAVE_CERTIFICATE_STATUS_REQUEST ||
2414
        * HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
2415
2416
0
    return ret;
2417
0
}
2418
2419
/* Disables OCSP Stapling.
2420
 *
2421
 * @param [in] cm  Certificate manager.
2422
 * @return  WOLFSSL_SUCCESS on success.
2423
 * @return  BAD_FUNC_ARG when cm is NULL.
2424
 */
2425
int wolfSSL_CertManagerDisableOCSPStapling(WOLFSSL_CERT_MANAGER* cm)
2426
0
{
2427
0
    int ret = WOLFSSL_SUCCESS;
2428
2429
0
    WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSPStapling");
2430
2431
    /* Validate parameter. */
2432
0
    if (cm == NULL) {
2433
0
        ret = BAD_FUNC_ARG;
2434
0
    }
2435
0
    if (ret == WOLFSSL_SUCCESS) {
2436
    #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
2437
        defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
2438
        /* Disable use of OCSP Stapling. */
2439
        cm->ocspStaplingEnabled = 0;
2440
    #else
2441
        /* OCSP stapling feature not enabled. */
2442
0
        ret = NOT_COMPILED_IN;
2443
0
    #endif
2444
0
    }
2445
2446
0
    return ret;
2447
0
}
2448
2449
/* Enable the must use OCSP Stapling option.
2450
 *
2451
 * @param [in] cm  Certificate manager.
2452
 * @return  WOLFSSL_SUCCESS on success.
2453
 * @return  BAD_FUNC_ARG when cm is NULL.
2454
 */
2455
int wolfSSL_CertManagerEnableOCSPMustStaple(WOLFSSL_CERT_MANAGER* cm)
2456
0
{
2457
0
    int ret = WOLFSSL_SUCCESS;
2458
2459
0
    WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSPMustStaple");
2460
2461
    /* Validate parameter. */
2462
0
    if (cm == NULL) {
2463
0
        ret = BAD_FUNC_ARG;
2464
0
    }
2465
0
    if (ret == WOLFSSL_SUCCESS) {
2466
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
2467
    defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
2468
    #ifndef NO_WOLFSSL_CLIENT
2469
        /* Enable must use OCSP Stapling option. */
2470
        cm->ocspMustStaple = 1;
2471
    #endif
2472
#else
2473
        /* OCSP stapling feature not enabled. */
2474
0
        ret = NOT_COMPILED_IN;
2475
0
#endif
2476
0
    }
2477
2478
0
    return ret;
2479
0
}
2480
2481
/* Disable the must use OCSP Stapling option.
2482
 *
2483
 * @param [in] cm  Certificate manager.
2484
 * @return  WOLFSSL_SUCCESS on success.
2485
 * @return  BAD_FUNC_ARG when cm is NULL.
2486
 */
2487
int wolfSSL_CertManagerDisableOCSPMustStaple(WOLFSSL_CERT_MANAGER* cm)
2488
0
{
2489
0
    int ret = WOLFSSL_SUCCESS;
2490
2491
0
    WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSPMustStaple");
2492
2493
    /* Validate parameter. */
2494
0
    if (cm == NULL) {
2495
0
        ret = BAD_FUNC_ARG;
2496
0
    }
2497
2498
0
    if (ret == WOLFSSL_SUCCESS) {
2499
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
2500
    defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
2501
    #ifndef NO_WOLFSSL_CLIENT
2502
        /* Disable must use OCSP Stapling option. */
2503
        cm->ocspMustStaple = 0;
2504
    #endif
2505
#else
2506
        /* OCSP stapling feature not enabled. */
2507
0
        ret = NOT_COMPILED_IN;
2508
0
#endif
2509
0
    }
2510
2511
0
    return ret;
2512
0
}
2513
2514
#ifdef HAVE_OCSP
2515
/* Check DER encoded certificate against with OCSP if checking enabled.
2516
 *
2517
 * @param [in] cm   Certificate manager.
2518
 * @param [in] der  DER encode certificate.
2519
 * @param [in] sz   Size in bytes of DER encode certificate.
2520
 * @return  WOLFSSL_SUCCESS on success.
2521
 * @return  BAD_FUNC_ARG when cm or der is NULL or sz is negative or 0.
2522
 * @return  MEMORY_E when dynamic memory allocation fails.
2523
 */
2524
int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER* cm,
2525
    const unsigned char* der, int sz)
2526
0
{
2527
0
    int ret = 0;
2528
0
    WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
2529
2530
0
    WOLFSSL_ENTER("wolfSSL_CertManagerCheckOCSP");
2531
2532
    /* Validate parameters. */
2533
0
    if ((cm == NULL) || (der == NULL) || (sz <= 0)) {
2534
0
        ret = BAD_FUNC_ARG;
2535
0
    }
2536
2537
    /* Check if OCSP checking enabled. */
2538
0
    if ((ret == 0) && cm->ocspEnabled) {
2539
        /* Allocate memory for decoded certificate. */
2540
0
        WC_ALLOC_VAR_EX(cert, DecodedCert, 1, cm->heap, DYNAMIC_TYPE_DCERT,
2541
0
            ret=MEMORY_E);
2542
0
        if (WC_VAR_OK(cert))
2543
0
        {
2544
            /* Initialize decoded certificate with buffer. */
2545
0
            InitDecodedCert(cert, der, (word32)sz, NULL);
2546
2547
            /* Parse certificate and perform CRL checks. */
2548
0
            ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_OCSP, cm, NULL);
2549
0
            if (ret != 0) {
2550
0
                WOLFSSL_MSG("ParseCert failed");
2551
0
            }
2552
            /* Do OCSP checks with decoded certificate. */
2553
0
            else if ((ret = CheckCertOCSP(cm->ocsp, cert)) != 0) {
2554
                /* Apply the caller's policy for a cert that advertises no
2555
                 * responder rather than reporting a lookup failure. */
2556
0
                if (ret == WC_NO_ERR_TRACE(OCSP_NO_URL))
2557
0
                    ret = OcspNoUrlPolicy(cm);
2558
0
                if (ret != 0)
2559
0
                    WOLFSSL_MSG("CheckCertOCSP failed");
2560
0
            }
2561
2562
            /* Dispose of dynamically allocated memory. */
2563
0
            FreeDecodedCert(cert);
2564
0
            WC_FREE_VAR_EX(cert, cm->heap, DYNAMIC_TYPE_DCERT);
2565
0
        }
2566
0
    }
2567
2568
0
    return (ret == 0) ? WOLFSSL_SUCCESS : ret;
2569
0
}
2570
2571
/* Check OCSP response.
2572
 *
2573
 * @param [in] cm              Certificate manager.
2574
 * @param [in] response        Buffer holding OCSP response.
2575
 * @param [in] responseSz      Size in bytes of OCSP response.
2576
 * @param [in] responseBuffer  Buffer to copy response into.
2577
 * @param [in] status          Place to store certificate status.
2578
 * @param [in] entry           Place to store OCSP entry.
2579
 * @param [in] ocspRequest     OCSP request to match with response.
2580
 * @return  WOLFSSL_SUCCESS on success.
2581
 * @return  BAD_FUNC_ARG when cm or response is NULL.
2582
 */
2583
int wolfSSL_CertManagerCheckOCSPResponse(WOLFSSL_CERT_MANAGER *cm,
2584
    byte *response, int responseSz, buffer *responseBuffer,
2585
    CertStatus *status, OcspEntry *entry, OcspRequest *ocspRequest)
2586
0
{
2587
0
    int ret = 0;
2588
2589
0
    WOLFSSL_ENTER("wolfSSL_CertManagerCheckOCSPResponse");
2590
2591
    /* Validate parameters. */
2592
0
    if ((cm == NULL) || (response == NULL)) {
2593
0
        ret = BAD_FUNC_ARG;
2594
0
    }
2595
0
    if ((ret == 0) && cm->ocspEnabled) {
2596
        /* Check OCSP response with OCSP object from certificate manager. */
2597
0
        ret = CheckOcspResponse(cm->ocsp, response, responseSz, responseBuffer,
2598
0
            status, entry, ocspRequest, NULL, NULL);
2599
0
    }
2600
2601
0
    return (ret == 0) ? WOLFSSL_SUCCESS : ret;
2602
0
}
2603
2604
/* Set the OCSP override URL.
2605
 *
2606
 * @param [in] cm   Certificate manager.
2607
 * @param [in] url  URL to get an OCSP response from.
2608
 * @return  WOLFSSL_SUCCESS on success.
2609
 * @return  BAD_FUNC_ARG when cm is NULL.
2610
 * @return  MEMORY_E when dynamic memory allocation fails.
2611
 */
2612
int wolfSSL_CertManagerSetOCSPOverrideURL(WOLFSSL_CERT_MANAGER* cm,
2613
    const char* url)
2614
0
{
2615
0
    int ret = WOLFSSL_SUCCESS;
2616
2617
0
    WOLFSSL_ENTER("wolfSSL_CertManagerSetOCSPOverrideURL");
2618
2619
    /* Validate parameters. */
2620
0
    if (cm == NULL) {
2621
0
        ret = BAD_FUNC_ARG;
2622
0
    }
2623
2624
0
    if (ret == WOLFSSL_SUCCESS) {
2625
        /* Dispose of old URL. */
2626
0
        XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL);
2627
0
        if (url != NULL) {
2628
            /* Calculate size of URL string. Include terminator character. */
2629
0
            int urlSz = (int)XSTRLEN(url) + 1;
2630
            /* Allocate memory for URL to be copied into. */
2631
0
            cm->ocspOverrideURL = (char*)XMALLOC((size_t)urlSz, cm->heap,
2632
0
                DYNAMIC_TYPE_URL);
2633
0
            if (cm->ocspOverrideURL == NULL) {
2634
0
                ret = MEMORY_E;
2635
0
            }
2636
0
            if (ret == WOLFSSL_SUCCESS) {
2637
                /* Copy URL into certificate manager. */
2638
0
                XMEMCPY(cm->ocspOverrideURL, url, (size_t)urlSz);
2639
0
            }
2640
0
        }
2641
0
        else {
2642
            /* No URL to set so make it NULL. */
2643
0
            cm->ocspOverrideURL = NULL;
2644
0
        }
2645
0
    }
2646
2647
0
    return ret;
2648
0
}
2649
2650
/* Set the OCSP I/O callback, OCSP response free callback and related data.
2651
 *
2652
 * @param [in] cm          Certificate manager.
2653
 * @param [in] ioCb        OCSP callback.
2654
 * @param [in] respFreeCb  Callback to free OCSP response buffer.
2655
 * @param [in] ioCbCtx     Context data to pass to OCSP callbacks.
2656
 * @return  WOLFSSL_SUCCESS on success.
2657
 * @return  BAD_FUNC_ARG when cm is NULL.
2658
 */
2659
int wolfSSL_CertManagerSetOCSP_Cb(WOLFSSL_CERT_MANAGER* cm, CbOCSPIO ioCb,
2660
    CbOCSPRespFree respFreeCb, void* ioCbCtx)
2661
0
{
2662
0
    int ret = WOLFSSL_SUCCESS;
2663
2664
0
    WOLFSSL_ENTER("wolfSSL_CertManagerSetOCSP_Cb");
2665
2666
    /* Validate parameters. */
2667
0
    if (cm == NULL) {
2668
0
        ret = BAD_FUNC_ARG;
2669
0
    }
2670
0
    if (ret == WOLFSSL_SUCCESS) {
2671
        /* Set callbacks and data into certificate manager. */
2672
0
        cm->ocspIOCb = ioCb;
2673
0
        cm->ocspRespFreeCb = respFreeCb;
2674
0
        cm->ocspIOCtx = ioCbCtx;
2675
0
    }
2676
2677
0
    return ret;
2678
0
}
2679
2680
#endif /* HAVE_OCSP */
2681
2682
/******************************************************************************
2683
 * Internal APIs that use WOLFSSL_CERT_MANAGER
2684
 ******************************************************************************/
2685
2686
/* hash is the SHA digest of name, just use first 32 bits as hash */
2687
static WC_INLINE word32 HashSigner(const byte* hash)
2688
4.23k
{
2689
4.23k
    return MakeWordFromHash(hash) % CA_TABLE_SIZE;
2690
4.23k
}
2691
2692
2693
/* does CA already exist on signer list */
2694
int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash)
2695
1.48k
{
2696
1.48k
    Signer* signers;
2697
1.48k
    int     ret = 0;
2698
1.48k
    word32  row;
2699
2700
1.48k
    if (cm == NULL || hash == NULL) {
2701
0
        return ret;
2702
0
    }
2703
2704
1.48k
    row = HashSigner(hash);
2705
2706
1.48k
    if (wc_LockMutex(&cm->caLock) != 0) {
2707
0
        return ret;
2708
0
    }
2709
1.48k
    signers = cm->caTable[row];
2710
1.70k
    while (signers) {
2711
471
        byte* subjectHash;
2712
2713
471
    #ifndef NO_SKID
2714
471
        subjectHash = signers->subjectKeyIdHash;
2715
    #else
2716
        subjectHash = signers->subjectNameHash;
2717
    #endif
2718
2719
471
        if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
2720
246
            ret = 1; /* success */
2721
246
            break;
2722
246
        }
2723
225
        signers = signers->next;
2724
225
    }
2725
1.48k
    wc_UnLockMutex(&cm->caLock);
2726
2727
1.48k
    return ret;
2728
1.48k
}
2729
2730
#ifdef WOLFSSL_TRUST_PEER_CERT
2731
/* hash is the SHA digest of name, just use first 32 bits as hash */
2732
static WC_INLINE word32 TrustedPeerHashSigner(const byte* hash)
2733
{
2734
    return MakeWordFromHash(hash) % TP_TABLE_SIZE;
2735
}
2736
2737
/* does trusted peer already exist on signer list */
2738
int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DecodedCert* cert)
2739
{
2740
    TrustedPeerCert* tp;
2741
    int     ret = 0;
2742
    word32  row = TrustedPeerHashSigner(cert->subjectHash);
2743
2744
    if (wc_LockMutex(&cm->tpLock) != 0)
2745
        return  ret;
2746
    tp = cm->tpTable[row];
2747
    while (tp) {
2748
        if ((XMEMCMP(cert->subjectHash, tp->subjectNameHash,
2749
                SIGNER_DIGEST_SIZE) == 0)
2750
    #ifndef WOLFSSL_NO_ISSUERHASH_TDPEER
2751
         && (XMEMCMP(cert->issuerHash, tp->issuerHash,
2752
                SIGNER_DIGEST_SIZE) == 0)
2753
    #endif
2754
        )
2755
            ret = 1;
2756
    #ifndef NO_SKID
2757
        if (cert->extSubjKeyIdSet) {
2758
            /* Compare SKID as well if available */
2759
            if (ret == 1 && XMEMCMP(cert->extSubjKeyId, tp->subjectKeyIdHash,
2760
                    SIGNER_DIGEST_SIZE) != 0)
2761
                ret = 0;
2762
        }
2763
    #endif
2764
        if (ret == 1)
2765
            break;
2766
        tp = tp->next;
2767
    }
2768
    wc_UnLockMutex(&cm->tpLock);
2769
2770
    return ret;
2771
}
2772
2773
/* return Trusted Peer if found, otherwise NULL
2774
    type is what to match on
2775
 */
2776
TrustedPeerCert* GetTrustedPeer(void* vp, DecodedCert* cert)
2777
{
2778
    WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
2779
    TrustedPeerCert* ret = NULL;
2780
    TrustedPeerCert* tp  = NULL;
2781
    word32  row;
2782
2783
    if (cm == NULL || cert == NULL)
2784
        return NULL;
2785
2786
    row = TrustedPeerHashSigner(cert->subjectHash);
2787
2788
    if (wc_LockMutex(&cm->tpLock) != 0)
2789
        return ret;
2790
2791
    tp = cm->tpTable[row];
2792
    while (tp) {
2793
        if ((XMEMCMP(cert->subjectHash, tp->subjectNameHash,
2794
                SIGNER_DIGEST_SIZE) == 0)
2795
        #ifndef WOLFSSL_NO_ISSUERHASH_TDPEER
2796
             && (XMEMCMP(cert->issuerHash, tp->issuerHash,
2797
                SIGNER_DIGEST_SIZE) == 0)
2798
        #endif
2799
            )
2800
            ret = tp;
2801
    #ifndef NO_SKID
2802
        if (cert->extSubjKeyIdSet) {
2803
            /* Compare SKID as well if available */
2804
            if (ret != NULL && XMEMCMP(cert->extSubjKeyId, tp->subjectKeyIdHash,
2805
                    SIGNER_DIGEST_SIZE) != 0)
2806
                ret = NULL;
2807
        }
2808
    #endif
2809
        if (ret != NULL)
2810
            break;
2811
        tp = tp->next;
2812
    }
2813
    wc_UnLockMutex(&cm->tpLock);
2814
2815
    return ret;
2816
}
2817
2818
2819
int MatchTrustedPeer(TrustedPeerCert* tp, DecodedCert* cert)
2820
{
2821
    if (tp == NULL || cert == NULL)
2822
        return BAD_FUNC_ARG;
2823
2824
    /* subject key id or subject hash has been compared when searching
2825
       tpTable for the cert from function GetTrustedPeer */
2826
2827
    /* compare signatures */
2828
    if (tp->sigLen == cert->sigLength) {
2829
        if (XMEMCMP(tp->sig, cert->signature, cert->sigLength)) {
2830
            return WOLFSSL_FAILURE;
2831
        }
2832
    }
2833
    else {
2834
        return WOLFSSL_FAILURE;
2835
    }
2836
2837
    return WOLFSSL_SUCCESS;
2838
}
2839
#endif /* WOLFSSL_TRUST_PEER_CERT */
2840
2841
/* return CA if found, otherwise NULL */
2842
Signer* GetCA(void* vp, byte* hash)
2843
2.60k
{
2844
2.60k
    WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
2845
2.60k
    Signer* ret = NULL;
2846
2.60k
    Signer* signers;
2847
2.60k
    word32  row = 0;
2848
2849
2.60k
    if (cm == NULL || hash == NULL)
2850
59
        return NULL;
2851
2852
2.54k
    row = HashSigner(hash);
2853
2854
2.54k
    if (wc_LockMutex(&cm->caLock) != 0)
2855
0
        return ret;
2856
2857
2.54k
    signers = cm->caTable[row];
2858
3.21k
    while (signers) {
2859
878
        byte* subjectHash;
2860
878
        #ifndef NO_SKID
2861
878
            subjectHash = signers->subjectKeyIdHash;
2862
        #else
2863
            subjectHash = signers->subjectNameHash;
2864
        #endif
2865
878
        if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
2866
216
            ret = signers;
2867
216
            break;
2868
216
        }
2869
662
        signers = signers->next;
2870
662
    }
2871
2.54k
    wc_UnLockMutex(&cm->caLock);
2872
2873
2.54k
    return ret;
2874
2.54k
}
2875
2876
#if defined(HAVE_OCSP)
2877
Signer* GetCAByKeyHash(void* vp, const byte* keyHash)
2878
0
{
2879
0
    WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
2880
0
    Signer* ret = NULL;
2881
0
    Signer* signers;
2882
0
    int row;
2883
2884
0
    if (cm == NULL || keyHash == NULL)
2885
0
        return NULL;
2886
2887
    /* try lookup using keyHash as subjKeyID first */
2888
0
    ret = GetCA(vp, (byte*)keyHash);
2889
0
    if (ret != NULL && XMEMCMP(ret->subjectKeyHash, keyHash, KEYID_SIZE) == 0) {
2890
0
        return ret;
2891
0
    }
2892
2893
    /* if we can't find the cert, we have to scan the full table */
2894
0
    if (wc_LockMutex(&cm->caLock) != 0)
2895
0
        return NULL;
2896
2897
    /* Unfortunately we need to look through the entire table */
2898
0
    for (row = 0; row < CA_TABLE_SIZE && ret == NULL; row++) {
2899
0
        for (signers = cm->caTable[row]; signers != NULL;
2900
0
                signers = signers->next) {
2901
0
            if (XMEMCMP(signers->subjectKeyHash, keyHash, KEYID_SIZE) == 0) {
2902
0
                ret = signers;
2903
0
                break;
2904
0
            }
2905
0
        }
2906
0
    }
2907
2908
0
    wc_UnLockMutex(&cm->caLock);
2909
0
    return ret;
2910
0
}
2911
#endif
2912
#ifdef WOLFSSL_AKID_NAME
2913
Signer* GetCAByAKID(void* vp, const byte* issuer, word32 issuerSz,
2914
        const byte* serial, word32 serialSz)
2915
742
{
2916
742
    WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
2917
742
    Signer* ret = NULL;
2918
742
    Signer* signers;
2919
742
    byte nameHash[SIGNER_DIGEST_SIZE];
2920
742
    byte serialHash[SIGNER_DIGEST_SIZE];
2921
742
    word32 row;
2922
2923
742
    if (cm == NULL || issuer == NULL || issuerSz == 0 ||
2924
0
            serial == NULL || serialSz == 0)
2925
742
        return NULL;
2926
2927
0
    if (CalcHashId(issuer, issuerSz, nameHash) != 0 ||
2928
0
            CalcHashId(serial, serialSz, serialHash) != 0)
2929
0
        return NULL;
2930
2931
0
    if (wc_LockMutex(&cm->caLock) != 0)
2932
0
        return ret;
2933
2934
    /* Unfortunately we need to look through the entire table */
2935
0
    for (row = 0; row < CA_TABLE_SIZE && ret == NULL; row++) {
2936
0
        for (signers = cm->caTable[row]; signers != NULL;
2937
0
                signers = signers->next) {
2938
0
            if (XMEMCMP(signers->issuerNameHash, nameHash, SIGNER_DIGEST_SIZE)
2939
0
                    == 0 && XMEMCMP(signers->serialHash, serialHash,
2940
0
                                    SIGNER_DIGEST_SIZE) == 0) {
2941
0
                ret = signers;
2942
0
                break;
2943
0
            }
2944
0
        }
2945
0
    }
2946
2947
0
    wc_UnLockMutex(&cm->caLock);
2948
2949
0
    return ret;
2950
0
}
2951
#endif
2952
2953
#ifndef NO_SKID
2954
/* return CA if found, otherwise NULL. Walk through hash table. */
2955
Signer* GetCAByName(void* vp, byte* hash)
2956
3.85k
{
2957
3.85k
    WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp;
2958
3.85k
    Signer* ret = NULL;
2959
3.85k
    Signer* signers;
2960
3.85k
    word32  row;
2961
2962
3.85k
    if (cm == NULL)
2963
1.77k
        return NULL;
2964
2965
2.07k
    if (wc_LockMutex(&cm->caLock) != 0)
2966
0
        return ret;
2967
2968
24.6k
    for (row = 0; row < CA_TABLE_SIZE && ret == NULL; row++) {
2969
22.5k
        signers = cm->caTable[row];
2970
23.1k
        while (signers && ret == NULL) {
2971
620
            if (XMEMCMP(hash, signers->subjectNameHash,
2972
620
                        SIGNER_DIGEST_SIZE) == 0) {
2973
131
                ret = signers;
2974
131
            }
2975
620
            signers = signers->next;
2976
620
        }
2977
22.5k
    }
2978
2.07k
    wc_UnLockMutex(&cm->caLock);
2979
2980
2.07k
    return ret;
2981
2.07k
}
2982
#endif
2983
2984
#ifdef WOLFSSL_TRUST_PEER_CERT
2985
/* add a trusted peer cert to linked list */
2986
int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify)
2987
{
2988
    int ret = 0;
2989
    int row = 0;
2990
    TrustedPeerCert* peerCert;
2991
    DecodedCert* cert;
2992
    DerBuffer*   der = *pDer;
2993
2994
    WOLFSSL_MSG("Adding a Trusted Peer Cert");
2995
2996
    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap,
2997
                                 DYNAMIC_TYPE_DCERT);
2998
    if (cert == NULL) {
2999
        FreeDer(&der);
3000
        return MEMORY_E;
3001
    }
3002
3003
    InitDecodedCert(cert, der->buffer, der->length, cm->heap);
3004
    if ((ret = ParseCert(cert, TRUSTED_PEER_TYPE, verify, cm)) != 0) {
3005
        FreeDecodedCert(cert);
3006
        XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
3007
        FreeDer(&der);
3008
        return ret;
3009
    }
3010
    WOLFSSL_MSG("\tParsed new trusted peer cert");
3011
3012
    peerCert = (TrustedPeerCert*)XMALLOC(sizeof(TrustedPeerCert), cm->heap,
3013
                                                             DYNAMIC_TYPE_CERT);
3014
    if (peerCert == NULL) {
3015
        FreeDecodedCert(cert);
3016
        XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
3017
        FreeDer(&der);
3018
        return MEMORY_E;
3019
    }
3020
    XMEMSET(peerCert, 0, sizeof(TrustedPeerCert));
3021
3022
    if (AlreadyTrustedPeer(cm, cert)) {
3023
        WOLFSSL_MSG("\tAlready have this CA, not adding again");
3024
        FreeTrustedPeer(peerCert, cm->heap);
3025
        (void)ret;
3026
    }
3027
    else {
3028
        /* add trusted peer signature */
3029
        peerCert->sigLen = cert->sigLength;
3030
        peerCert->sig = (byte *)XMALLOC(cert->sigLength, cm->heap,
3031
                                                        DYNAMIC_TYPE_SIGNATURE);
3032
        if (peerCert->sig == NULL) {
3033
            FreeDecodedCert(cert);
3034
            XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
3035
            FreeTrustedPeer(peerCert, cm->heap);
3036
            FreeDer(&der);
3037
            return MEMORY_E;
3038
        }
3039
        XMEMCPY(peerCert->sig, cert->signature, cert->sigLength);
3040
3041
        /* add trusted peer name */
3042
        peerCert->nameLen = cert->subjectCNLen;
3043
        peerCert->name    = cert->subjectCN;
3044
        #ifndef IGNORE_NAME_CONSTRAINTS
3045
            peerCert->permittedNames = cert->permittedNames;
3046
            peerCert->excludedNames  = cert->excludedNames;
3047
        #endif
3048
3049
        /* add SKID when available and hash of name */
3050
        #ifndef NO_SKID
3051
            XMEMCPY(peerCert->subjectKeyIdHash, cert->extSubjKeyId,
3052
                   SIGNER_DIGEST_SIZE);
3053
        #endif
3054
            XMEMCPY(peerCert->subjectNameHash, cert->subjectHash,
3055
                    SIGNER_DIGEST_SIZE);
3056
        #ifndef WOLFSSL_NO_ISSUERHASH_TDPEER
3057
            XMEMCPY(peerCert->issuerHash, cert->issuerHash,
3058
                    SIGNER_DIGEST_SIZE);
3059
        #endif
3060
            /* If Key Usage not set, all uses valid. */
3061
            peerCert->next    = NULL;
3062
            cert->subjectCN = 0;
3063
        #ifndef IGNORE_NAME_CONSTRAINTS
3064
            cert->permittedNames = NULL;
3065
            cert->excludedNames = NULL;
3066
        #endif
3067
3068
            row = (int)TrustedPeerHashSigner(peerCert->subjectNameHash);
3069
3070
            if (wc_LockMutex(&cm->tpLock) == 0) {
3071
                peerCert->next = cm->tpTable[row];
3072
                cm->tpTable[row] = peerCert;   /* takes ownership */
3073
                wc_UnLockMutex(&cm->tpLock);
3074
            }
3075
            else {
3076
                WOLFSSL_MSG("\tTrusted Peer Cert Mutex Lock failed");
3077
                FreeDecodedCert(cert);
3078
                XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
3079
                FreeTrustedPeer(peerCert, cm->heap);
3080
                FreeDer(&der);
3081
                return BAD_MUTEX_E;
3082
            }
3083
        }
3084
3085
    WOLFSSL_MSG("\tFreeing parsed trusted peer cert");
3086
    FreeDecodedCert(cert);
3087
    XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
3088
    WOLFSSL_MSG("\tFreeing der trusted peer cert");
3089
    FreeDer(&der);
3090
    WOLFSSL_MSG("\t\tOK Freeing der trusted peer cert");
3091
    WOLFSSL_LEAVE("AddTrustedPeer", ret);
3092
3093
    return WOLFSSL_SUCCESS;
3094
}
3095
#endif /* WOLFSSL_TRUST_PEER_CERT */
3096
3097
int AddSigner(WOLFSSL_CERT_MANAGER* cm, Signer *s)
3098
0
{
3099
0
    byte*   subjectHash;
3100
0
    Signer* signers;
3101
0
    word32  row;
3102
3103
0
    if (cm == NULL || s == NULL)
3104
0
        return BAD_FUNC_ARG;
3105
3106
0
#ifndef NO_SKID
3107
0
    subjectHash = s->subjectKeyIdHash;
3108
#else
3109
    subjectHash = s->subjectNameHash;
3110
#endif
3111
3112
0
    if (AlreadySigner(cm, subjectHash)) {
3113
0
        FreeSigner(s, cm->heap);
3114
0
        return 0;
3115
0
    }
3116
3117
0
    row = HashSigner(subjectHash);
3118
3119
0
    if (wc_LockMutex(&cm->caLock) != 0)
3120
0
        return BAD_MUTEX_E;
3121
3122
0
    signers = cm->caTable[row];
3123
0
    s->next = signers;
3124
0
    cm->caTable[row] = s;
3125
3126
0
    wc_UnLockMutex(&cm->caLock);
3127
0
    return 0;
3128
0
}
3129
3130
/* owns der, internal now uses too */
3131
/* type flag ids from user or from chain received during verify
3132
   don't allow chain ones to be added w/o isCA extension */
3133
int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
3134
{
3135
    int         ret = 0;
3136
    Signer*     signer = NULL;
3137
    word32      row = 0;
3138
    byte*       subjectHash = NULL;
3139
    WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
3140
    DerBuffer*   der = *pDer;
3141
3142
    WOLFSSL_MSG_CERT_LOG("Adding a CA");
3143
3144
    if (cm == NULL) {
3145
        FreeDer(pDer);
3146
        return BAD_FUNC_ARG;
3147
    }
3148
3149
    #ifdef WOLFSSL_SMALL_STACK
3150
    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT);
3151
    if (cert == NULL) {
3152
        FreeDer(pDer);
3153
        return MEMORY_E;
3154
    }
3155
    #endif
3156
3157
    InitDecodedCert(cert, der->buffer, der->length, cm->heap);
3158
3159
#ifdef WC_ASN_UNKNOWN_EXT_CB
3160
    if (cm->unknownExtCallback != NULL) {
3161
        wc_SetUnknownExtCallback(cert, cm->unknownExtCallback);
3162
    }
3163
#endif
3164
3165
    WOLFSSL_MSG_CERT("\tParsing new CA");
3166
    ret = ParseCert(cert, CA_TYPE, verify, cm);
3167
3168
    WOLFSSL_MSG("\tParsed new CA");
3169
#ifdef WOLFSSL_DEBUG_CERTS
3170
    {
3171
        const char*  err_msg;
3172
        if (ret == 0) {
3173
            WOLFSSL_MSG_CERT_EX(WOLFSSL_MSG_CERT_INDENT "issuer:  '%s'",
3174
                cert->issuer);
3175
            WOLFSSL_MSG_CERT_EX(WOLFSSL_MSG_CERT_INDENT "subject: '%s'",
3176
                cert->subject);
3177
        }
3178
        else {
3179
            WOLFSSL_MSG_CERT(
3180
                WOLFSSL_MSG_CERT_INDENT "Failed during parse of new CA");
3181
            err_msg = wc_GetErrorString(ret);
3182
            WOLFSSL_MSG_CERT_EX(WOLFSSL_MSG_CERT_INDENT "error ret: %d; %s",
3183
                ret, err_msg);
3184
        }
3185
    }
3186
#endif /* WOLFSSL_DEBUG_CERTS */
3187
3188
#ifndef NO_SKID
3189
    subjectHash = cert->extSubjKeyId;
3190
#else
3191
    subjectHash = cert->subjectHash;
3192
#endif
3193
3194
    /* check CA key size */
3195
    if (verify && (ret == 0 )) {
3196
        switch (cert->keyOID) {
3197
        #ifndef NO_RSA
3198
            #ifdef WC_RSA_PSS
3199
            case RSAPSSk:
3200
            #endif
3201
            case RSAk:
3202
                if (cm->minRsaKeySz < 0 ||
3203
                                   cert->pubKeySize < (word16)cm->minRsaKeySz) {
3204
                    ret = RSA_KEY_SIZE_E;
3205
                    WOLFSSL_MSG_CERT_LOG("\tCA RSA key size error");
3206
                    WOLFSSL_MSG_CERT_EX("\tCA RSA pubKeySize = %d; "
3207
                                                "minRsaKeySz = %d",
3208
                                   cert->pubKeySize, cm->minRsaKeySz);
3209
                }
3210
                break;
3211
        #endif /* !NO_RSA */
3212
            #ifdef HAVE_ECC
3213
            case ECDSAk:
3214
                if (cm->minEccKeySz < 0 ||
3215
                                   cert->pubKeySize < (word16)cm->minEccKeySz) {
3216
                    ret = ECC_KEY_SIZE_E;
3217
                    WOLFSSL_MSG_CERT_LOG("\tCA ECC key size error");
3218
                    WOLFSSL_MSG_CERT_EX("\tCA ECC pubKeySize = %d; "
3219
                                                 "minEccKeySz = %d",
3220
                                   cert->pubKeySize, cm->minEccKeySz);
3221
                }
3222
                break;
3223
            #endif /* HAVE_ECC */
3224
            #ifdef HAVE_ED25519
3225
            case ED25519k:
3226
                if (cm->minEccKeySz < 0 ||
3227
                                   ED25519_KEY_SIZE < (word16)cm->minEccKeySz) {
3228
                    ret = ECC_KEY_SIZE_E;
3229
                    WOLFSSL_MSG("\tCA ECC key size error");
3230
                }
3231
                break;
3232
            #endif /* HAVE_ED25519 */
3233
            #ifdef HAVE_ED448
3234
            case ED448k:
3235
                if (cm->minEccKeySz < 0 ||
3236
                                     ED448_KEY_SIZE < (word16)cm->minEccKeySz) {
3237
                    ret = ECC_KEY_SIZE_E;
3238
                    WOLFSSL_MSG("\tCA ECC key size error");
3239
                }
3240
                break;
3241
            #endif /* HAVE_ED448 */
3242
            #if defined(HAVE_FALCON)
3243
            case FALCON_LEVEL1k:
3244
                if (cm->minFalconKeySz < 0 ||
3245
                          FALCON_LEVEL1_KEY_SIZE < (word16)cm->minFalconKeySz) {
3246
                    ret = FALCON_KEY_SIZE_E;
3247
                    WOLFSSL_MSG("\tCA Falcon level 1 key size error");
3248
                }
3249
                break;
3250
            case FALCON_LEVEL5k:
3251
                if (cm->minFalconKeySz < 0 ||
3252
                          FALCON_LEVEL5_KEY_SIZE < (word16)cm->minFalconKeySz) {
3253
                    ret = FALCON_KEY_SIZE_E;
3254
                    WOLFSSL_MSG("\tCA Falcon level 5 key size error");
3255
                }
3256
                break;
3257
            #endif /* HAVE_FALCON */
3258
            #if defined(WOLFSSL_HAVE_MLDSA)
3259
            #ifdef WOLFSSL_MLDSA_FIPS204_DRAFT
3260
            case DILITHIUM_LEVEL2k:
3261
                if (cm->minMlDsaKeySz < 0 ||
3262
                    WC_MLDSA_44_KEY_SIZE < (word16)cm->minMlDsaKeySz) {
3263
                    ret = MLDSA_KEY_SIZE_E;
3264
                    WOLFSSL_MSG("\tCA ML-DSA level 2 key size error");
3265
                }
3266
                break;
3267
            case DILITHIUM_LEVEL3k:
3268
                if (cm->minMlDsaKeySz < 0 ||
3269
                    WC_MLDSA_65_KEY_SIZE < (word16)cm->minMlDsaKeySz) {
3270
                    ret = MLDSA_KEY_SIZE_E;
3271
                    WOLFSSL_MSG("\tCA ML-DSA level 3 key size error");
3272
                }
3273
                break;
3274
            case DILITHIUM_LEVEL5k:
3275
                if (cm->minMlDsaKeySz < 0 ||
3276
                    WC_MLDSA_87_KEY_SIZE < (word16)cm->minMlDsaKeySz) {
3277
                    ret = MLDSA_KEY_SIZE_E;
3278
                    WOLFSSL_MSG("\tCA ML-DSA level 5 key size error");
3279
                }
3280
                break;
3281
            #endif /* WOLFSSL_MLDSA_FIPS204_DRAFT */
3282
            case ML_DSA_44k:
3283
                if (cm->minMlDsaKeySz < 0 ||
3284
                    WC_MLDSA_44_KEY_SIZE < (word16)cm->minMlDsaKeySz) {
3285
                    ret = MLDSA_KEY_SIZE_E;
3286
                    WOLFSSL_MSG("\tCA ML-DSA level 2 key size error");
3287
                }
3288
                break;
3289
            case ML_DSA_65k:
3290
                if (cm->minMlDsaKeySz < 0 ||
3291
                    WC_MLDSA_65_KEY_SIZE < (word16)cm->minMlDsaKeySz) {
3292
                    ret = MLDSA_KEY_SIZE_E;
3293
                    WOLFSSL_MSG("\tCA ML-DSA level 3 key size error");
3294
                }
3295
                break;
3296
            case ML_DSA_87k:
3297
                if (cm->minMlDsaKeySz < 0 ||
3298
                    WC_MLDSA_87_KEY_SIZE < (word16)cm->minMlDsaKeySz) {
3299
                    ret = MLDSA_KEY_SIZE_E;
3300
                    WOLFSSL_MSG("\tCA ML-DSA level 5 key size error");
3301
                }
3302
                break;
3303
            #endif /* WOLFSSL_HAVE_MLDSA */
3304
3305
            default:
3306
                WOLFSSL_MSG("\tNo key size check done on CA");
3307
                break; /* no size check if key type is not in switch */
3308
        }
3309
    }
3310
3311
    if (ret == 0 && cert->isCA == 0 && type != WOLFSSL_USER_CA &&
3312
        type != WOLFSSL_TEMP_CA) {
3313
        WOLFSSL_MSG("\tCan't add as CA if not actually one");
3314
        ret = NOT_CA_ERROR;
3315
    }
3316
    /* Enforced by default. ALLOW_INVALID_CERTSIGN is a deliberate,
3317
     * RFC-non-conformant opt-out for interop with deployed certs that carry
3318
     * malformed keyUsage; see the macro list at the top of
3319
     * wolfcrypt/src/asn.c. */
3320
#ifndef ALLOW_INVALID_CERTSIGN
3321
    else if (ret == 0 && cert->isCA == 1 && type != WOLFSSL_USER_CA &&
3322
        !cert->selfSigned && cert->extKeyUsageSet &&
3323
        (cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) == 0) {
3324
        /* Intermediate CA certs - including chain-supplied temporary CAs
3325
        * (WOLFSSL_TEMP_CA) added while building a path - are required to have
3326
        * the keyCertSign key usage when a Key Usage extension is present.
3327
        * Only operator-loaded root certs (WOLFSSL_USER_CA) and self-signed
3328
        * roots are exempt. Per RFC 5280 an absent Key Usage extension implies
3329
        * all usages, so only enforce this when the extension is actually
3330
        * present (extKeyUsageSet). */
3331
        WOLFSSL_MSG("\tDoesn't have key usage certificate signing");
3332
        ret = NOT_CA_ERROR;
3333
    }
3334
#endif
3335
    else if (ret == 0 && AlreadySigner(cm, subjectHash)) {
3336
        WOLFSSL_MSG("\tAlready have this CA, not adding again");
3337
        (void)ret;
3338
    }
3339
    else if (ret == 0) {
3340
        /* take over signer parts */
3341
        signer = MakeSigner(cm->heap);
3342
        if (!signer)
3343
            ret = MEMORY_ERROR;
3344
    }
3345
    if (ret == 0 && signer != NULL) {
3346
        ret = FillSigner(signer, cert, type, der);
3347
3348
        if (ret == 0){
3349
        #ifndef NO_SKID
3350
            row = HashSigner(signer->subjectKeyIdHash);
3351
        #else
3352
            row = HashSigner(signer->subjectNameHash);
3353
        #endif
3354
        }
3355
3356
    #if defined(WOLFSSL_RENESAS_TSIP_TLS) || defined(WOLFSSL_RENESAS_FSPSM_TLS)
3357
        /* Verify CA by TSIP so that generated tsip key is going to          */
3358
        /* be able to be used for peer's cert verification                   */
3359
        /* TSIP is only able to handle USER CA, and only one CA.             */
3360
        /* Therefore, it doesn't need to call TSIP again if there is already */
3361
        /* verified CA.                                                      */
3362
        if ( ret == 0 && signer != NULL ) {
3363
            signer->cm_idx = row;
3364
            if (type == WOLFSSL_USER_CA) {
3365
                if ((ret = wc_Renesas_cmn_RootCertVerify(cert->source,
3366
                        cert->maxIdx,
3367
                        cert->sigCtx.CertAtt.pubkey_n_start,
3368
                        cert->sigCtx.CertAtt.pubkey_n_len - 1,
3369
                        cert->sigCtx.CertAtt.pubkey_e_start,
3370
                        cert->sigCtx.CertAtt.pubkey_e_len - 1,
3371
                     row/* cm index */))
3372
                    < 0)
3373
                    WOLFSSL_MSG("Renesas_RootCertVerify() failed");
3374
                else
3375
                    WOLFSSL_MSG("Renesas_RootCertVerify() succeed or skipped");
3376
            }
3377
        }
3378
    #endif /* TSIP or SCE */
3379
3380
        if (ret == 0 && wc_LockMutex(&cm->caLock) == 0) {
3381
            signer->next = cm->caTable[row];
3382
            cm->caTable[row] = signer;   /* takes ownership */
3383
            wc_UnLockMutex(&cm->caLock);
3384
            if (cm->caCacheCallback)
3385
                cm->caCacheCallback(der->buffer, (int)der->length, type);
3386
        }
3387
        else {
3388
            WOLFSSL_MSG("\tCA Mutex Lock failed");
3389
            ret = BAD_MUTEX_E;
3390
        }
3391
    }
3392
3393
    WOLFSSL_MSG("\tFreeing Parsed CA");
3394
    FreeDecodedCert(cert);
3395
    if (ret != 0 && signer != NULL)
3396
        FreeSigner(signer, cm->heap);
3397
    WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
3398
    WOLFSSL_MSG("\tFreeing der CA");
3399
    FreeDer(pDer);
3400
    WOLFSSL_MSG("\t\tOK Freeing der CA");
3401
3402
    WOLFSSL_LEAVE("AddCA", ret);
3403
3404
    return ret == 0 ? WOLFSSL_SUCCESS : ret;
3405
}
3406
3407
/* Removes the CA with the passed in subject hash from the
3408
   cert manager's CA cert store. */
3409
int RemoveCA(WOLFSSL_CERT_MANAGER* cm, byte* hash, int type)
3410
0
{
3411
0
    Signer* current;
3412
0
    Signer** prev;
3413
0
    int     ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
3414
0
    word32  row;
3415
3416
0
    WOLFSSL_MSG("Removing a CA");
3417
3418
0
    if (cm == NULL || hash == NULL) {
3419
0
        return BAD_FUNC_ARG;
3420
0
    }
3421
3422
0
    row = HashSigner(hash);
3423
3424
0
    if (wc_LockMutex(&cm->caLock) != 0) {
3425
0
        return BAD_MUTEX_E;
3426
0
    }
3427
0
    current = cm->caTable[row];
3428
0
    prev = &cm->caTable[row];
3429
0
    while (current) {
3430
0
        byte* subjectHash;
3431
3432
0
    #ifndef NO_SKID
3433
0
        subjectHash = current->subjectKeyIdHash;
3434
    #else
3435
        subjectHash = current->subjectNameHash;
3436
    #endif
3437
3438
0
        if ((current->type == type) &&
3439
0
            (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0)) {
3440
0
            *prev = current->next;
3441
0
            FreeSigner(current, cm->heap);
3442
0
            ret = WOLFSSL_SUCCESS;
3443
0
            break;
3444
0
        }
3445
0
        prev = &current->next;
3446
0
        current = current->next;
3447
0
    }
3448
0
    wc_UnLockMutex(&cm->caLock);
3449
3450
0
    WOLFSSL_LEAVE("RemoveCA", ret);
3451
3452
0
    return ret;
3453
0
}
3454
3455
/* Sets the CA with the passed in subject hash
3456
   to the provided type. */
3457
int SetCAType(WOLFSSL_CERT_MANAGER* cm, byte* hash, int type)
3458
0
{
3459
0
    Signer* current;
3460
0
    int     ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
3461
0
    word32  row;
3462
3463
0
    WOLFSSL_MSG_EX("Setting CA to type %d", type);
3464
3465
0
    if (cm == NULL || hash == NULL ||
3466
0
        type < WOLFSSL_USER_CA || type > WOLFSSL_USER_INTER) {
3467
0
        return ret;
3468
0
    }
3469
3470
0
    row = HashSigner(hash);
3471
3472
0
    if (wc_LockMutex(&cm->caLock) != 0) {
3473
0
        return ret;
3474
0
    }
3475
0
    current = cm->caTable[row];
3476
0
    while (current) {
3477
0
        byte* subjectHash;
3478
3479
0
    #ifndef NO_SKID
3480
0
        subjectHash = current->subjectKeyIdHash;
3481
    #else
3482
        subjectHash = current->subjectNameHash;
3483
    #endif
3484
3485
0
        if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) {
3486
0
            current->type = (byte)type;
3487
0
            ret = WOLFSSL_SUCCESS;
3488
0
            break;
3489
0
        }
3490
0
        current = current->next;
3491
0
    }
3492
0
    wc_UnLockMutex(&cm->caLock);
3493
3494
0
    WOLFSSL_LEAVE("SetCAType", ret);
3495
3496
0
    return ret;
3497
0
}
3498
3499
#endif /* NO_CERTS */
3500
3501
#endif /* !WOLFSSL_SSL_CERTMAN_INCLUDED */