Coverage Report

Created: 2026-05-21 06:58

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