Coverage Report

Created: 2026-04-05 07:22

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