Coverage Report

Created: 2025-07-23 06:53

/src/wolfssl/src/ssl_certman.c
Line
Count
Source (jump to first uncovered line)
1
/* ssl_certman.c
2
 *
3
 * Copyright (C) 2006-2025 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 does not need to be compiled separately from ssl.c
29
    #endif
30
#else
31
32
#ifndef NO_CERTS
33
34
/* Pick an available TLS method.
35
 *
36
 * Used when creating temporary WOLFSSL_CTX.
37
 *
38
 * @return  A TLS method on success.
39
 * @return  NULL when no TLS method built into wolfSSL.
40
 */
41
static WC_INLINE WOLFSSL_METHOD* cm_pick_method(void* heap)
42
0
{
43
0
    (void)heap;
44
0
    #ifndef NO_WOLFSSL_CLIENT
45
        #if !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_SSLV3)
46
            return wolfSSLv3_client_method_ex(heap);
47
        #elif !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLSV10)
48
            return wolfTLSv1_client_method_ex(heap);
49
        #elif !defined(NO_OLD_TLS)
50
            return wolfTLSv1_1_client_method_ex(heap);
51
        #elif !defined(WOLFSSL_NO_TLS12)
52
            return wolfTLSv1_2_client_method_ex(heap);
53
        #elif defined(WOLFSSL_TLS13)
54
            return wolfTLSv1_3_client_method_ex(heap);
55
        #else
56
            return NULL;
57
        #endif
58
    #elif !defined(NO_WOLFSSL_SERVER)
59
        #if !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_SSLV3)
60
            return wolfSSLv3_server_method_ex(heap);
61
        #elif !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLSV10)
62
            return wolfTLSv1_server_method_ex(heap);
63
        #elif !defined(NO_OLD_TLS)
64
            return wolfTLSv1_1_server_method_ex(heap);
65
        #elif !defined(WOLFSSL_NO_TLS12)
66
            return wolfTLSv1_2_server_method_ex(heap);
67
        #elif defined(WOLFSSL_TLS13)
68
            return wolfTLSv1_3_server_method_ex(heap);
69
        #else
70
            return NULL;
71
        #endif
72
    #else
73
        return NULL;
74
    #endif
75
0
}
76
77
/* Create a new certificate manager with a heap hint.
78
 *
79
 * @param [in] heap  Heap hint.
80
 * @return  Certificate manager object on success.
81
 * @return  NULL on failure.
82
 */
83
WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap)
84
0
{
85
0
    int err = 0;
86
0
    WOLFSSL_CERT_MANAGER* cm;
87
88
0
    WOLFSSL_ENTER("wolfSSL_CertManagerNew");
89
0
    if (heap == NULL) {
90
0
         WOLFSSL_MSG("heap param is null");
91
0
    }
92
0
    else {
93
        /* Some systems may have heap in unexpected segments. (IRAM vs DRAM) */
94
0
        WOLFSSL_MSG_EX("heap param = %p", heap);
95
0
    }
96
0
    WOLFSSL_MSG_EX("DYNAMIC_TYPE_CERT_MANAGER Allocating = %d bytes",
97
0
                    (word32)sizeof(WOLFSSL_CERT_MANAGER));
98
99
    /* Allocate memory for certificate manager. */
100
0
    cm = (WOLFSSL_CERT_MANAGER*)XMALLOC(sizeof(WOLFSSL_CERT_MANAGER), heap,
101
0
        DYNAMIC_TYPE_CERT_MANAGER);
102
0
    if (cm == NULL) {
103
0
        WOLFSSL_MSG_EX("XMALLOC failed to allocate WOLFSSL_CERT_MANAGER %d "
104
0
                    "bytes.", (int)sizeof(WOLFSSL_CERT_MANAGER));
105
0
        err = 1;
106
0
    }
107
0
    if (!err) {
108
        /* Reset all fields. */
109
0
        XMEMSET(cm, 0, sizeof(WOLFSSL_CERT_MANAGER));
110
111
        /* Create a mutex for use when modify table of stored CAs. */
112
0
        if (wc_InitMutex(&cm->caLock) != 0) {
113
0
            WOLFSSL_MSG("Bad mutex init");
114
0
            err = 1;
115
0
        }
116
0
    }
117
0
    if (!err) {
118
        /* Initialize reference count. */
119
0
        wolfSSL_RefInit(&cm->ref, &err);
120
    #ifdef WOLFSSL_REFCNT_ERROR_RETURN
121
        if (err != 0) {
122
            WOLFSSL_MSG("Bad reference count init");
123
        }
124
    #endif
125
0
    }
126
#ifdef WOLFSSL_TRUST_PEER_CERT
127
    /* Create a mutex for use when modify table of trusted peers. */
128
    if ((!err) && (wc_InitMutex(&cm->tpLock) != 0)) {
129
        WOLFSSL_MSG("Bad mutex init");
130
        err = 1;
131
    }
132
#endif
133
0
    if (!err) {
134
        /* Set default minimum key sizes allowed. */
135
0
    #ifndef NO_RSA
136
0
        cm->minRsaKeySz = MIN_RSAKEY_SZ;
137
0
    #endif
138
0
    #ifdef HAVE_ECC
139
0
        cm->minEccKeySz = MIN_ECCKEY_SZ;
140
0
    #endif
141
    #ifdef HAVE_FALCON
142
        cm->minFalconKeySz = MIN_FALCONKEY_SZ;
143
    #endif /* HAVE_FALCON */
144
    #ifdef HAVE_DILITHIUM
145
        cm->minDilithiumKeySz = MIN_DILITHIUMKEY_SZ;
146
    #endif /* HAVE_DILITHIUM */
147
148
        /* Set heap hint to use in certificate manager operations. */
149
0
        cm->heap = heap;
150
0
    }
151
152
    /* Dispose of certificate manager on error. */
153
0
    if (err && (cm != NULL)) {
154
0
        wolfSSL_CertManagerFree(cm);
155
0
        cm = NULL;
156
0
    }
157
0
    return cm;
158
0
}
159
160
/* Create a new certificate manager.
161
 *
162
 * @return  Certificate manager object on success.
163
 * @return  NULL on failure.
164
 */
165
WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew(void)
166
0
{
167
    /* No heap hint. */
168
0
    return wolfSSL_CertManagerNew_ex(NULL);
169
0
}
170
171
/* Dispose of certificate manager.
172
 *
173
 * @param [in, out] cm  Certificate manager.
174
 */
175
void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm)
176
0
{
177
0
    WOLFSSL_ENTER("wolfSSL_CertManagerFree");
178
179
    /* Validate parameter. */
180
0
    if (cm != NULL) {
181
0
        int doFree = 0;
182
0
        int ret;
183
184
        /* Decrement reference count and check if value is 0. */
185
0
        wolfSSL_RefDec(&cm->ref, &doFree, &ret);
186
    #ifdef WOLFSSL_REFCNT_ERROR_RETURN
187
        if (ret != 0) {
188
            WOLFSSL_MSG("Couldn't lock cm mutex");
189
        }
190
    #else
191
0
        (void)ret;
192
0
    #endif
193
0
        if (doFree) {
194
        #ifdef HAVE_CRL
195
            /* Dispose of CRL handler. */
196
            if (cm->crl != NULL) {
197
                /* Dispose of CRL object - indicating dynamically allocated. */
198
                FreeCRL(cm->crl, 1);
199
            }
200
        #endif
201
202
    #ifdef HAVE_OCSP
203
            /* Dispose of OCSP handler. */
204
            if (cm->ocsp != NULL) {
205
                FreeOCSP(cm->ocsp, 1);
206
            }
207
            /* Dispose of URL. */
208
            XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL);
209
        #if !defined(NO_WOLFSSL_SERVER) && \
210
            (defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
211
             defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
212
            /* Dispose of OCSP stapling handler. */
213
            if (cm->ocsp_stapling) {
214
                FreeOCSP(cm->ocsp_stapling, 1);
215
            }
216
        #endif
217
    #endif /* HAVE_OCSP */
218
219
            /* Dispose of CA table and mutex. */
220
0
            FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
221
0
            wc_FreeMutex(&cm->caLock);
222
223
        #ifdef WOLFSSL_TRUST_PEER_CERT
224
            /* Dispose of trusted peer table and mutex. */
225
            FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, cm->heap);
226
            wc_FreeMutex(&cm->tpLock);
227
        #endif
228
229
            /* Dispose of reference count. */
230
0
            wolfSSL_RefFree(&cm->ref);
231
            /* Dispose of certificate manager memory. */
232
0
            XFREE(cm, cm->heap, DYNAMIC_TYPE_CERT_MANAGER);
233
0
        }
234
0
    }
235
0
}
236
237
/* Increase reference count on certificate manager.
238
 *
239
 * @param [in, out] cm  Certificate manager.
240
 * @return  WOLFSSL_SUCCESS on success.
241
 * @return  0 when cm is NULL or locking mutex fails.
242
 */
243
int wolfSSL_CertManager_up_ref(WOLFSSL_CERT_MANAGER* cm)
244
0
{
245
0
    int ret = WOLFSSL_SUCCESS;
246
247
    /* Validate parameter. */
248
0
    if (cm == NULL) {
249
0
        ret = 0;
250
0
    }
251
0
    if (ret == WOLFSSL_SUCCESS) {
252
0
        int err;
253
254
        /* Increment reference. */
255
0
        wolfSSL_RefInc(&cm->ref, &err);
256
    #ifdef WOLFSSL_REFCNT_ERROR_RETURN
257
        if (err) {
258
            WOLFSSL_MSG("Failed to lock cm mutex");
259
            ret = 0;
260
        }
261
    #else
262
0
        (void)err;
263
0
    #endif
264
0
    }
265
266
0
    return ret;
267
0
}
268
269
#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM)
270
#if defined(WOLFSSL_SIGNER_DER_CERT)
271
static WC_INLINE int wolfssl_cm_get_certs_der(WOLFSSL_CERT_MANAGER* cm,
272
    DerBuffer*** buffers, int* cnt)
273
{
274
    int err = 0;
275
    Signer* signers = NULL;
276
    DerBuffer** certBuffers = NULL;
277
    int i = 0;
278
    word32 row = 0;
279
    int numCerts = 0;
280
281
    /* Iterate once to get the number of certs, for memory allocation
282
     * purposes. */
283
    for (row = 0; row < CA_TABLE_SIZE; row++) {
284
        /* Get signer information of CAs in a row. */
285
        signers = cm->caTable[row];
286
        /* Count each signer in row that has a DER certificate buffer. */
287
        while ((signers != NULL) && (signers->derCert != NULL) &&
288
                (signers->derCert->buffer != NULL)) {
289
            ++numCerts;
290
            signers = signers->next;
291
        }
292
    }
293
    /* Check we found certificates. */
294
    if (numCerts == 0) {
295
        err = 1;
296
    }
297
298
    if (!err) {
299
        /* Allocate memory for pointers to each DER buffer. */
300
        certBuffers = (DerBuffer**)XMALLOC(
301
            sizeof(DerBuffer*) * (size_t)numCerts, cm->heap,
302
            DYNAMIC_TYPE_TMP_BUFFER);
303
        if (certBuffers == NULL) {
304
            err = 1;
305
        }
306
    }
307
    if (!err) {
308
        /* Reset pointers. */
309
        XMEMSET(certBuffers, 0, sizeof(DerBuffer*) * (size_t)numCerts);
310
    }
311
312
    /* Copy the certs locally so that we can release the caLock. If the lock
313
     * is held when wolfSSL_d2i_X509 is called, GetCA will also try to get
314
     * the lock, leading to deadlock. */
315
    for (row = 0; (!err) && (row < CA_TABLE_SIZE); row++) {
316
        /* Get signer information of CAs in a row. */
317
        signers = cm->caTable[row];
318
        /* Copy each DER certificate buffer of signers in a row. */
319
        while ((signers != NULL) && (signers->derCert != NULL) &&
320
                (signers->derCert->buffer != NULL)) {
321
            /* Allocate memory to hold DER certificate buffer. */
322
            int ret = AllocDer(&certBuffers[i], signers->derCert->length,
323
                CA_TYPE, cm->heap);
324
            if (ret < 0) {
325
                err = 1;
326
                break;
327
            }
328
329
            /* Copy buffer into array element. */
330
            XMEMCPY(certBuffers[i]->buffer, signers->derCert->buffer,
331
                signers->derCert->length);
332
            certBuffers[i]->length = signers->derCert->length;
333
334
            /* Store in next index. */
335
            ++i;
336
            /* Move on to next signer in row. */
337
            signers = signers->next;
338
        }
339
    }
340
341
    *buffers = certBuffers;
342
    *cnt = numCerts;
343
    return err;
344
}
345
346
/* Retrieve stack of X509 certificates in a certificate manager (CM).
347
 *
348
 * @param [in] cm  Certificate manager.
349
 *
350
 * @return  Stack of X509 certs on success
351
 * @return  NULL on failure.
352
 */
353
WOLFSSL_STACK* wolfSSL_CertManagerGetCerts(WOLFSSL_CERT_MANAGER* cm)
354
{
355
    WOLFSSL_STACK* sk = NULL;
356
    int numCerts = 0;
357
    DerBuffer** certBuffers = NULL;
358
    int i = 0;
359
    int err = 0;
360
361
    WOLFSSL_ENTER("wolfSSL_CertManagerGetCerts");
362
363
    /* Validate parameter. */
364
    if (cm == NULL) {
365
        err = 1;
366
    }
367
    if (!err) {
368
        /* Create an empty certificate stack to return. */
369
        sk = wolfSSL_sk_X509_new_null();
370
        if (sk == NULL) {
371
            err = 1;
372
        }
373
    }
374
    /* Lock CA table. */
375
    if ((!err) && (wc_LockMutex(&cm->caLock) != 0)) {
376
        err = 1;
377
    }
378
    if (!err) {
379
        err = wolfssl_cm_get_certs_der(cm, &certBuffers, &numCerts);
380
        /* Release CA lock. */
381
        wc_UnLockMutex(&cm->caLock);
382
    }
383
384
    /* Put each DER certificate buffer into a stack of WOLFSSL_X509 */
385
    for (i = 0; (!err) && (i < numCerts); ++i) {
386
        const byte* derBuffer = NULL;
387
        WOLFSSL_X509* x509 = NULL;
388
389
        /* Get pointer to DER encoding of certificate. */
390
        derBuffer = certBuffers[i]->buffer;
391
        /* Decode certificate. */
392
        wolfSSL_d2i_X509(&x509, &derBuffer, (int)certBuffers[i]->length);
393
        if (x509 == NULL) {
394
            err = 1;
395
        }
396
397
        /* Decode certificate. */
398
        if ((!err) && (wolfSSL_sk_X509_push(sk, x509) <= 0)) {
399
            wolfSSL_X509_free(x509);
400
            x509 = NULL;
401
            err = 1;
402
        }
403
    }
404
405
    if (certBuffers != NULL) {
406
        /* Dispose of temporary cert storage (for access outside of lock). */
407
        for (i = 0; i < numCerts && certBuffers[i] != NULL; ++i) {
408
            FreeDer(&certBuffers[i]);
409
        }
410
        XFREE(certBuffers, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
411
    }
412
413
    /* Dispose of stack of certificates on error. */
414
    if (err && (sk != NULL)) {
415
        wolfSSL_sk_X509_pop_free(sk, NULL);
416
        sk = NULL;
417
    }
418
    return sk;
419
}
420
421
#endif /* WOLFSSL_SIGNER_DER_CERT */
422
#endif /* OPENSSL_EXTRA && !NO_FILESYSTEM */
423
424
/* Unload the CA signer table.
425
 *
426
 * @param [in] cm  Certificate manager.
427
 * @return  WOLFSSL_SUCCESS on success.
428
 * @return  BAD_FUNC_ARG when cm is NULL.
429
 * @return  BAD_MUTEX_E when locking fails.
430
 */
431
int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm)
432
0
{
433
0
    int ret = WOLFSSL_SUCCESS;
434
435
0
    WOLFSSL_ENTER("wolfSSL_CertManagerUnloadCAs");
436
437
    /* Validate parameter. */
438
0
    if (cm == NULL) {
439
0
        ret = BAD_FUNC_ARG;
440
0
    }
441
    /* Lock CA table. */
442
0
    if ((ret == WOLFSSL_SUCCESS) && (wc_LockMutex(&cm->caLock) != 0)) {
443
0
        ret = BAD_MUTEX_E;
444
0
    }
445
0
    if (ret == WOLFSSL_SUCCESS) {
446
        /* Dispose of CA table. */
447
0
        FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
448
449
        /* Unlock CA table. */
450
0
        wc_UnLockMutex(&cm->caLock);
451
0
    }
452
453
0
    return ret;
454
0
}
455
456
static int wolfSSL_CertManagerUnloadIntermediateCertsEx(
457
                                WOLFSSL_CERT_MANAGER* cm, byte type)
458
0
{
459
0
    int ret = WOLFSSL_SUCCESS;
460
461
0
    WOLFSSL_ENTER("wolfSSL_CertManagerUnloadIntermediateCertsEx");
462
463
    /* Validate parameter. */
464
0
    if (cm == NULL) {
465
0
        ret = BAD_FUNC_ARG;
466
0
    }
467
    /* Lock CA table. */
468
0
    if ((ret == WOLFSSL_SUCCESS) && (wc_LockMutex(&cm->caLock) != 0)) {
469
0
        ret = BAD_MUTEX_E;
470
0
    }
471
0
    if (ret == WOLFSSL_SUCCESS) {
472
        /* Dispose of CA table. */
473
0
        FreeSignerTableType(cm->caTable, CA_TABLE_SIZE, type,
474
0
                cm->heap);
475
476
        /* Unlock CA table. */
477
0
        wc_UnLockMutex(&cm->caLock);
478
0
    }
479
480
0
    return ret;
481
0
}
482
483
#if defined(OPENSSL_EXTRA)
484
static int wolfSSL_CertManagerUnloadTempIntermediateCerts(
485
    WOLFSSL_CERT_MANAGER* cm)
486
{
487
    WOLFSSL_ENTER("wolfSSL_CertManagerUnloadTempIntermediateCerts");
488
    return wolfSSL_CertManagerUnloadIntermediateCertsEx(cm, WOLFSSL_TEMP_CA);
489
}
490
#endif
491
492
int wolfSSL_CertManagerUnloadIntermediateCerts(
493
    WOLFSSL_CERT_MANAGER* cm)
494
0
{
495
0
    WOLFSSL_ENTER("wolfSSL_CertManagerUnloadIntermediateCerts");
496
0
    return wolfSSL_CertManagerUnloadIntermediateCertsEx(cm, WOLFSSL_CHAIN_CA);
497
0
}
498
499
#ifdef WOLFSSL_TRUST_PEER_CERT
500
/* Unload the trusted peers table.
501
 *
502
 * @param [in] cm  Certificate manager.
503
 * @return  WOLFSSL_SUCCESS on success.
504
 * @return  BAD_FUNC_ARG when cm is NULL.
505
 * @return  BAD_MUTEX_E when locking fails.
506
 */
507
int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm)
508
{
509
    int ret = WOLFSSL_SUCCESS;
510
511
    WOLFSSL_ENTER("wolfSSL_CertManagerUnload_trust_peers");
512
513
    /* Validate parameter. */
514
    if (cm == NULL) {
515
        ret = BAD_FUNC_ARG;
516
    }
517
    /* Lock trusted peers table. */
518
    if ((ret == WOLFSSL_SUCCESS) && (wc_LockMutex(&cm->tpLock) != 0)) {
519
        ret = BAD_MUTEX_E;
520
    }
521
    if (ret == WOLFSSL_SUCCESS) {
522
        /* Dispose of trusted peers table. */
523
        FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, cm->heap);
524
525
        /* Unlock trusted peers table. */
526
        wc_UnLockMutex(&cm->tpLock);
527
    }
528
529
    return ret;
530
}
531
#endif /* WOLFSSL_TRUST_PEER_CERT */
532
533
/* Load certificate/s from buffer with flags.
534
 *
535
 * @param [in] cm         Certificate manager.
536
 * @param [in] buff       Buffer holding encoding of certificate.
537
 * @param [in] sz         Length in bytes of data in buffer.
538
 * @param [in] format     Format of encoding. Valid values:
539
 *                          WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
540
 * @param [in] userChain  Indicates buffer holds chain of certificates.
541
 * @param [in] flags      Flags to modify behaviour of loading. Valid flags:
542
 *                          WOLFSSL_LOAD_FLAG_IGNORE_ERR,
543
 *                          WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY,
544
 *                          WOLFSSL_LOAD_FLAG_PEM_CA_ONLY,
545
 *                          WOLFSSL_LOAD_FLAG_IGNORE_BAD_PATH_ERR, and
546
 *                          WOLFSSL_LOAD_FLAG_IGNORE_ZEROFILE.
547
 * @return  WOLFSSL_SUCCESS on success.
548
 * @return  WOLFSSL_FATAL_ERROR when cm is NULL or failed create WOLFSSL_CTX.
549
 * @return  Other values on loading failure.
550
 */
551
int wolfSSL_CertManagerLoadCABuffer_ex(WOLFSSL_CERT_MANAGER* cm,
552
    const unsigned char* buff, long sz, int format, int userChain, word32 flags)
553
0
{
554
0
    int ret = WOLFSSL_SUCCESS;
555
0
    WOLFSSL_CTX* tmp = NULL;
556
557
0
    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCABuffer_ex");
558
559
    /* Validate parameters. */
560
0
    if (cm == NULL) {
561
0
        WOLFSSL_MSG("No CertManager error");
562
0
        ret = WOLFSSL_FATAL_ERROR;
563
0
    }
564
    /* Allocate a temporary WOLFSSL_CTX to load with. */
565
0
    if ((ret == WOLFSSL_SUCCESS) && ((tmp =
566
0
        wolfSSL_CTX_new_ex(cm_pick_method(cm->heap), cm->heap)) == NULL)) {
567
0
        WOLFSSL_MSG("CTX new failed");
568
0
        ret = WOLFSSL_FATAL_ERROR;
569
0
    }
570
0
    if (ret == WOLFSSL_SUCCESS) {
571
        /* Some configurations like OPENSSL_COMPATIBLE_DEFAULTS may turn off
572
         * verification by default. Let's restore our desired defaults. */
573
0
        wolfSSL_CTX_set_verify(tmp, WOLFSSL_VERIFY_DEFAULT, NULL);
574
575
        /* Replace certificate manager with one to load certificate/s into. */
576
0
        wolfSSL_CertManagerFree(tmp->cm);
577
0
        tmp->cm = cm;
578
579
        /* Load certificate buffer. */
580
0
        ret = wolfSSL_CTX_load_verify_buffer_ex(tmp, buff, sz, format,
581
0
            userChain, flags);
582
583
        /* Clear certificate manager in WOLFSSL_CTX so it won't be freed. */
584
0
        tmp->cm = NULL;
585
0
    }
586
587
    /* Dispose of temporary WOLFSSL_CTX. */
588
0
    wolfSSL_CTX_free(tmp);
589
0
    return ret;
590
0
}
591
592
/* Load certificate/s from buffer into table.
593
 *
594
 * Uses default load verification flags and is not a user chain.
595
 *
596
 * @param [in] cm         Certificate manager.
597
 * @param [in] buff       Buffer holding encoding of certificate.
598
 * @param [in] sz         Length in bytes of data in buffer.
599
 * @param [in] format     Format of encoding. Valid values:
600
 *                          WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
601
 * @return  WOLFSSL_SUCCESS on success.
602
 * @return  WOLFSSL_FATAL_ERROR when cm is NULL or failed create WOLFSSL_CTX.
603
 * @return  Other values on loading failure.
604
 */
605
int wolfSSL_CertManagerLoadCABuffer(WOLFSSL_CERT_MANAGER* cm,
606
    const unsigned char* buff, long sz, int format)
607
0
{
608
0
    return wolfSSL_CertManagerLoadCABuffer_ex(cm, buff, sz, format, 0,
609
0
        WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS);
610
0
}
611
612
#ifndef NO_WOLFSSL_CM_VERIFY
613
/* Set the verification callback into certificate manager.
614
 *
615
 * @param [in] cm  Certificate manager.
616
 * @param [in] vc  Verification callback.
617
 */
618
void wolfSSL_CertManagerSetVerify(WOLFSSL_CERT_MANAGER* cm, VerifyCallback vc)
619
0
{
620
0
    WOLFSSL_ENTER("wolfSSL_CertManagerSetVerify");
621
0
    if (cm != NULL) {
622
0
        cm->verifyCallback = vc;
623
0
    }
624
0
}
625
#endif /* !NO_WOLFSSL_CM_VERIFY */
626
627
#ifdef WC_ASN_UNKNOWN_EXT_CB
628
void wolfSSL_CertManagerSetUnknownExtCallback(WOLFSSL_CERT_MANAGER* cm,
629
        wc_UnknownExtCallback cb)
630
{
631
    WOLFSSL_ENTER("wolfSSL_CertManagerSetUnknownExtCallback");
632
    if (cm != NULL) {
633
        cm->unknownExtCallback = cb;
634
    }
635
636
}
637
#endif /* WC_ASN_UNKNOWN_EXT_CB */
638
639
#if !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)
640
/* Verify the certificate.
641
 *
642
 * Uses the verification callback if available.
643
 *
644
 * @param [in] cm        Certificate manager.
645
 * @param [in] buff      Buffer holding encoded certificate.
646
 * @param [in] sz        Size in bytes of data in buffer.
647
 * @param [in] format    Format of encoding. Valid values:
648
 *                         WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
649
 * @param [in] prev_err  Previous error. Passed to callback.
650
 * @return  WOLFSSL_SUCCESS on success.
651
 * @return  MEMORY_E when dynamic memory allocation fails.
652
 * @return  NOT_COMPILED_IN when converting from PEM to DER is not a feature of
653
 *          the wolfSSL build.
654
 */
655
int CM_VerifyBuffer_ex(WOLFSSL_CERT_MANAGER* cm, const unsigned char* buff,
656
    long sz, int format, int prev_err)
657
0
{
658
0
    int ret = 0;
659
0
    int fatal = 0;
660
0
    DerBuffer* der = NULL;
661
#ifdef WOLFSSL_SMALL_STACK
662
    DecodedCert* cert = NULL;
663
#else
664
0
    DecodedCert  cert[1];
665
0
#endif
666
667
0
    WOLFSSL_ENTER("CM_VerifyBuffer_ex");
668
669
0
    (void)prev_err;
670
671
#ifdef WOLFSSL_SMALL_STACK
672
    /* Allocate memory for decoded certificate. */
673
    cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap,
674
         DYNAMIC_TYPE_DCERT);
675
    if (cert == NULL) {
676
        ret = MEMORY_E;
677
        fatal = 1;
678
    }
679
    if (ret == 0)
680
#endif
681
0
    {
682
        /* Reset fields of decoded certificate. */
683
0
        XMEMSET(cert, 0, sizeof(DecodedCert));
684
685
0
        if (format == WOLFSSL_FILETYPE_PEM) {
686
        #ifndef WOLFSSL_PEM_TO_DER
687
            ret = NOT_COMPILED_IN;
688
            fatal = 1;
689
        #else
690
            /* Convert to DER from PEM. */
691
0
            ret = PemToDer(buff, sz, CERT_TYPE, &der, cm->heap, NULL, NULL);
692
0
            if (ret != 0) {
693
0
                fatal = 1;
694
0
            }
695
0
            else {
696
                /* Replace buffer pointer and size with DER buffer. */
697
0
                buff = der->buffer;
698
0
                sz = (long)der->length;
699
0
            }
700
0
        #endif
701
0
        }
702
0
    }
703
0
    if (ret == 0) {
704
        /* Create a decoded certificate with DER buffer. */
705
0
        InitDecodedCert(cert, buff, (word32)sz, cm->heap);
706
707
#ifdef WC_ASN_UNKNOWN_EXT_CB
708
        if (cm->unknownExtCallback != NULL)
709
            wc_SetUnknownExtCallback(cert, cm->unknownExtCallback);
710
#endif
711
712
        /* Parse DER into decoded certificate fields and verify signature
713
         * against a known CA. */
714
0
        ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, cm, NULL);
715
0
     }
716
717
#ifdef HAVE_CRL
718
    if ((ret == 0) && cm->crlEnabled) {
719
        /* Check for a CRL for the CA and check validity of certificate. */
720
        ret = CheckCertCRL(cm->crl, cert);
721
    }
722
#endif
723
724
0
    (void)fatal;
725
726
0
#ifndef NO_WOLFSSL_CM_VERIFY
727
    /* Use callback to perform verification too if available. */
728
0
    if ((!fatal) && cm->verifyCallback) {
729
    #ifdef WOLFSSL_SMALL_STACK
730
        ProcPeerCertArgs* args;
731
    #else
732
0
        ProcPeerCertArgs  args[1];
733
0
    #endif
734
0
        buffer certBuf;
735
736
    #ifdef WOLFSSL_SMALL_STACK
737
        /* Allocate memory for object to hold arguments for callback. */
738
        args = (ProcPeerCertArgs*)XMALLOC(sizeof(ProcPeerCertArgs), cm->heap,
739
            DYNAMIC_TYPE_TMP_BUFFER);
740
        if (args == NULL) {
741
            ret = MEMORY_E;
742
            fatal = 1;
743
        }
744
        if (!fatal)
745
    #endif
746
0
        {
747
0
            XMEMSET(args, 0, sizeof(ProcPeerCertArgs));
748
749
            /* DER encoding. */
750
0
            certBuf.buffer = (byte*)buff;
751
0
            certBuf.length = (unsigned int)sz;
752
753
            /* One certificate available. */
754
0
            args->totalCerts = 1;
755
0
            args->certs = &certBuf;
756
0
            args->dCert = cert;
757
0
            args->dCertInit = 1;
758
759
            /* Replace value in ret with an error value passed in. */
760
0
            if (prev_err != 0) {
761
0
                ret = prev_err;
762
0
            }
763
            /* Use callback to verify certificate. */
764
0
            ret = DoVerifyCallback(cm, NULL, ret, args);
765
0
        }
766
    #ifdef WOLFSSL_SMALL_STACK
767
        /* Dispose of allocated callback args. */
768
        XFREE(args, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
769
    #endif
770
0
    }
771
0
#endif
772
773
    /* Dispose of allocated memory. */
774
0
    FreeDecodedCert(cert);
775
0
    FreeDer(&der);
776
#ifdef WOLFSSL_SMALL_STACK
777
    XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
778
#endif
779
780
    /* Convert the ret value to a return value. */
781
0
    return (ret == 0) ? WOLFSSL_SUCCESS : ret;
782
0
}
783
784
/* Verify the certificate.
785
 *
786
 * Uses the verification callback if available.
787
 *
788
 * @param [in] cm        Certificate manager.
789
 * @param [in] buff      Buffer holding encoded certificate.
790
 * @param [in] sz        Size in bytes of data in buffer.
791
 * @param [in] format    Format of encoding. Valid values:
792
 *                         WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
793
 * @param [in] prev_err  Previous error. Passed to callback.
794
 * @return  WOLFSSL_SUCCESS on success.
795
 * @return  BAD_FUNC_ARG when cm or buff is NULL or sz is negative or zero.
796
 * @return  WOLFSSL_BAD_FILETYPE when format is invalid.
797
 * @return  MEMORY_E when dynamic memory allocation fails.
798
 * @return  NOT_COMPILED_IN when converting from PEM to DER is not a feature of
799
 *          the wolfSSL build.
800
 */
801
int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm,
802
    const unsigned char* buff, long sz, int format)
803
0
{
804
0
    int ret;
805
806
0
    WOLFSSL_ENTER("wolfSSL_CertManagerVerifyBuffer");
807
808
    /* Validate parameters. */
809
0
    if ((cm == NULL) || (buff == NULL) || (sz <= 0)) {
810
0
        ret = BAD_FUNC_ARG;
811
0
    }
812
0
    else if ((format != WOLFSSL_FILETYPE_ASN1) &&
813
0
             (format != WOLFSSL_FILETYPE_PEM)) {
814
0
        ret = WOLFSSL_BAD_FILETYPE;
815
0
    }
816
0
    else {
817
        /* No previous error. */
818
0
        ret = CM_VerifyBuffer_ex(cm, buff, sz, format, 0);
819
0
    }
820
821
0
    return ret;
822
0
}
823
#endif /* !NO_WOLFSSL_CLIENT || !WOLFSSL_NO_CLIENT_AUTH */
824
825
#ifndef NO_FILESYSTEM
826
827
#if !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)
828
/* Verify the certificate loaded from a file.
829
 *
830
 * Uses the verification callback if available.
831
 *
832
 * @param [in] cm        Certificate manager.
833
 * @param [in] format    Format of encoding. Valid values:
834
 *                         WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
835
 * @param [in] prev_err  Previous error. Passed to callback.
836
 * @return  WOLFSSL_SUCCESS on success.
837
 * @return  BAD_FUNC_ARG when cm or buff is NULL or sz is negative.
838
 * @return  WOLFSSL_BAD_FILETYPE when format is invalid.
839
 * @return  WOLFSSL_BAD_FILE when reading the certificate file fails.
840
 * @return  MEMORY_E when dynamic memory allocation fails.
841
 * @return  NOT_COMPILED_IN when converting from PEM to DER is not a feature of
842
 *          the wolfSSL build.
843
 */
844
int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname,
845
    int format)
846
0
{
847
0
    int    ret = WOLFSSL_SUCCESS;
848
0
#ifndef WOLFSSL_SMALL_STACK
849
0
    byte   staticBuffer[FILE_BUFFER_SIZE];
850
0
#endif
851
0
    byte*  buff = NULL;
852
0
    long   sz = 0;
853
0
    XFILE  file = XBADFILE;
854
855
0
    WOLFSSL_ENTER("wolfSSL_CertManagerVerify");
856
857
0
#ifndef WOLFSSL_SMALL_STACK
858
0
    buff = staticBuffer;
859
0
#endif
860
861
    /* Validate parameters. cm and format validated in:
862
     *   wolfSSL_CertManagerVerifyBuffer */
863
0
    if ((cm == NULL) || (fname == NULL)) {
864
0
        ret = BAD_FUNC_ARG;
865
0
    }
866
867
    /* Open the file containing a certificate. */
868
0
    if ((ret == WOLFSSL_SUCCESS) &&
869
0
            ((file = XFOPEN(fname, "rb")) == XBADFILE)) {
870
0
        ret = WOLFSSL_BAD_FILE;
871
0
    }
872
    /* Get the length of the file. */
873
0
    if (ret == WOLFSSL_SUCCESS) {
874
0
        ret = wolfssl_file_len(file, &sz);
875
0
        if (ret == 0) {
876
0
            ret = WOLFSSL_SUCCESS;
877
0
        }
878
0
    }
879
    /* Allocate dynamic memory for file contents if no static buffer or too
880
     * small. */
881
0
#ifndef WOLFSSL_SMALL_STACK
882
0
    if ((ret == WOLFSSL_SUCCESS) && (sz > (long)sizeof(staticBuffer)))
883
#else
884
885
    if (ret == WOLFSSL_SUCCESS)
886
#endif
887
0
    {
888
0
        WOLFSSL_MSG("Getting dynamic buffer");
889
0
        buff = (byte*)XMALLOC((size_t)sz, cm->heap, DYNAMIC_TYPE_FILE);
890
0
        if (buff == NULL) {
891
0
            ret = WOLFSSL_BAD_FILE;
892
0
        }
893
0
    }
894
    /* Read all the file into buffer. */
895
0
    if ((ret == WOLFSSL_SUCCESS) && (XFREAD(buff, 1, (size_t)sz, file) !=
896
0
            (size_t)sz)) {
897
0
        ret = WOLFSSL_BAD_FILE;
898
0
    }
899
    /* Close file if opened. */
900
0
    if (file != XBADFILE) {
901
0
        XFCLOSE(file);
902
0
    }
903
0
    if (ret == WOLFSSL_SUCCESS) {
904
        /* Verify the certificate read. */
905
0
        ret = wolfSSL_CertManagerVerifyBuffer(cm, buff, sz, format);
906
0
    }
907
908
    /* Dispose of buffer if it was allocated. */
909
0
#ifndef WOLFSSL_SMALL_STACK
910
0
    if (buff != staticBuffer)
911
0
#endif
912
0
    {
913
0
        if (cm != NULL) {
914
0
            XFREE(buff, cm->heap, DYNAMIC_TYPE_FILE);
915
0
        }
916
0
    }
917
0
    return ret;
918
0
}
919
#endif
920
921
/* Load the CA file and/or certificate files in a path.
922
 *
923
 * @param [in] cm    Certificate manager.
924
 * @param [in] file  Name of CA file.
925
 * @param [in] path  Path to a directory containing certificates.
926
 * @return  WOLFSSL_SUCCESS on success.
927
 * @return  WOLFSSL_FATAL_ERROR when cm is NULL or unable to create WOLFSSL_CTX.
928
 * @return  Otherwise failure.
929
 */
930
int wolfSSL_CertManagerLoadCA(WOLFSSL_CERT_MANAGER* cm, const char* file,
931
                             const char* path)
932
0
{
933
0
    int ret = WOLFSSL_SUCCESS;
934
0
    WOLFSSL_CTX* tmp = NULL;
935
936
0
    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCA");
937
938
    /* Validate parameters. file and path validated in:
939
     *   wolfSSL_CTX_load_verify_locations*/
940
0
    if (cm == NULL) {
941
0
        WOLFSSL_MSG("No CertManager error");
942
0
        ret = WOLFSSL_FATAL_ERROR;
943
0
    }
944
    /* Create temporary WOLFSSL_CTX. */
945
0
    if ((ret == WOLFSSL_SUCCESS) && ((tmp =
946
0
        wolfSSL_CTX_new_ex(cm_pick_method(cm->heap), cm->heap)) == NULL)) {
947
0
        WOLFSSL_MSG("CTX new failed");
948
0
        ret = WOLFSSL_FATAL_ERROR;
949
0
    }
950
0
    if (ret == WOLFSSL_SUCCESS) {
951
        /* Some configurations like OPENSSL_COMPATIBLE_DEFAULTS may turn off
952
         * verification by default. Let's restore our desired defaults. */
953
0
        wolfSSL_CTX_set_verify(tmp, WOLFSSL_VERIFY_DEFAULT, NULL);
954
955
        /* Replace certificate manager with one to load certificate/s into. */
956
0
        wolfSSL_CertManagerFree(tmp->cm);
957
0
        tmp->cm = cm;
958
959
        /* Load certificate from file and path. */
960
0
        ret = wolfSSL_CTX_load_verify_locations(tmp, file, path);
961
962
        /* Clear certificate manager in WOLFSSL_CTX so it won't be freed. */
963
0
        tmp->cm = NULL;
964
0
    }
965
966
    /* Dispose of temporary WOLFSSL_CTX. */
967
0
    wolfSSL_CTX_free(tmp);
968
0
    return ret;
969
0
}
970
971
#endif /* NO_FILESYSTEM */
972
973
#if defined(PERSIST_CERT_CACHE)
974
975
/* Version of layout of cache of CA certificates. */
976
#define WOLFSSL_CACHE_CERT_VERSION 1
977
978
/* CA certificates cache information. */
979
typedef struct {
980
    /* Cache certificate layout version id. */
981
    int version;
982
    /* Number of hash table rows. Maximum of CA_TABLE_SIZE. */
983
    int rows;
984
    /* Number of columns per row. */
985
    int columns[CA_TABLE_SIZE];
986
    /* Size of Signer object. */
987
    int signerSz;
988
} CertCacheHeader;
989
990
/* current cert persistence layout is:
991
992
   1) CertCacheHeader
993
   2) caTable
994
995
   update WOLFSSL_CERT_CACHE_VERSION if change layout for the following
996
   PERSIST_CERT_CACHE functions
997
*/
998
999
1000
/* Return number of bytes of memory needed to persist this signer.
1001
 *
1002
 * Assumes we have locked CA table.
1003
 *
1004
 * @param [in] Signer  Signer entry in CA table.
1005
 * @return  Number of bytes.
1006
 */
1007
static WC_INLINE int cm_get_signer_memory(Signer* signer)
1008
{
1009
    int sz = sizeof(signer->pubKeySize) + sizeof(signer->keyOID)
1010
           + sizeof(signer->nameLen)    + sizeof(signer->subjectNameHash);
1011
1012
#if !defined(NO_SKID)
1013
        sz += (int)sizeof(signer->subjectKeyIdHash);
1014
#endif
1015
1016
    /* Add dynamic bytes needed. */
1017
    sz += (int)signer->pubKeySize;
1018
    sz += signer->nameLen;
1019
1020
    return sz;
1021
}
1022
1023
1024
/* Return number of bytes of memory needed to persist this row.
1025
 *
1026
 * Assumes we have locked CA table.
1027
 *
1028
 * @param [in] row  A row of signers from the CA table.
1029
 * @return  Number of bytes.
1030
 */
1031
static WC_INLINE int cm_get_cert_cache_row_memory(Signer* row)
1032
{
1033
    int sz = 0;
1034
1035
    /* Each signer in row. */
1036
    while (row != NULL) {
1037
        /* Add in size of this signer. */
1038
        sz += cm_get_signer_memory(row);
1039
        row = row->next;
1040
    }
1041
1042
    return sz;
1043
}
1044
1045
1046
/* Return the number of bytes of memory to persist cert cache.
1047
 *
1048
 * Assumes we have locked CA table.
1049
 *
1050
 * @param [in] cm  Certificate manager.
1051
 * @return  Number of bytes.
1052
 */
1053
static WC_INLINE int cm_get_cert_cache_mem_size(WOLFSSL_CERT_MANAGER* cm)
1054
{
1055
    int sz;
1056
    int i;
1057
1058
    sz = sizeof(CertCacheHeader);
1059
1060
    /* Each row in table. */
1061
    for (i = 0; i < CA_TABLE_SIZE; i++) {
1062
        /* Add in size of this row. */
1063
        sz += cm_get_cert_cache_row_memory(cm->caTable[i]);
1064
    }
1065
1066
    return sz;
1067
}
1068
1069
1070
/* Get count of columns for each row.
1071
 *
1072
 * Assumes we have locked CA table.
1073
 *
1074
 * @param [in] cm       Certificate manager.
1075
 * @param [in] columns  Array of row counts.
1076
 */
1077
static WC_INLINE void cm_set_cert_header_Columns(WOLFSSL_CERT_MANAGER* cm,
1078
    int* columns)
1079
{
1080
    int     i;
1081
    Signer* row;
1082
1083
    /* Each row in table. */
1084
    for (i = 0; i < CA_TABLE_SIZE; i++) {
1085
        int count = 0;
1086
1087
        /* Get row from table. */
1088
        row = cm->caTable[i];
1089
        /* Each entry in row. */
1090
        while (row != NULL) {
1091
            /* Update count. */
1092
            ++count;
1093
            row = row->next;
1094
        }
1095
        /* Store row count. */
1096
        columns[i] = count;
1097
    }
1098
}
1099
1100
1101
/* Restore whole cert row from memory,
1102
 *
1103
 * Assumes we have locked CA table.
1104
 *
1105
 * @param [in] cm       Certificate manager.
1106
 * @param [in] current  Buffer containing rows.
1107
 * @param [in] row      Row number being restored.
1108
 * @param [in] listSz   Number of entries in row.
1109
 * @param [in] end      End of data in buffer.
1110
 * @return  Number of bytes consumed on success.
1111
 * @return  PARSE_ERROR when listSz is less than zero.
1112
 * @return  BUFFER_E when buffer is too small.
1113
 * @return  MEMORY_E when dynamic memory allocation fails.
1114
 * @return  Negative value on error.
1115
 */
1116
static WC_INLINE int cm_restore_cert_row(WOLFSSL_CERT_MANAGER* cm,
1117
    byte* current, int row, int listSz, const byte* end)
1118
{
1119
    int ret = 0;
1120
    int idx = 0;
1121
1122
    /* Validate parameters. */
1123
    if (listSz < 0) {
1124
        WOLFSSL_MSG("Row header corrupted, negative value");
1125
        ret = PARSE_ERROR;
1126
    }
1127
1128
    /* Process all entries. */
1129
    while ((ret == 0) && (listSz > 0)) {
1130
        Signer* signer = NULL;
1131
        byte*   publicKey;
1132
        byte*   start = current + idx;  /* for end checks on this signer */
1133
        int     minSz = sizeof(signer->pubKeySize) + sizeof(signer->keyOID) +
1134
                      sizeof(signer->nameLen) + sizeof(signer->subjectNameHash);
1135
        #ifndef NO_SKID
1136
                minSz += (int)sizeof(signer->subjectKeyIdHash);
1137
        #endif
1138
1139
        /* Check minimal size of bytes available. */
1140
        if (start + minSz > end) {
1141
            WOLFSSL_MSG("Would overread restore buffer");
1142
            ret = BUFFER_E;
1143
        }
1144
        /* Make a new signer. */
1145
        if ((ret == 0) && ((signer = MakeSigner(cm->heap)) == NULL)) {
1146
            ret = MEMORY_E;
1147
        }
1148
1149
        if (ret == 0) {
1150
            /* Copy in public key size. */
1151
            XMEMCPY(&signer->pubKeySize, current + idx,
1152
                sizeof(signer->pubKeySize));
1153
            idx += (int)sizeof(signer->pubKeySize);
1154
1155
            /* Copy in public key OID. */
1156
            XMEMCPY(&signer->keyOID, current + idx, sizeof(signer->keyOID));
1157
            idx += (int)sizeof(signer->keyOID);
1158
1159
            /* Check bytes available for public key. */
1160
            if (start + minSz + signer->pubKeySize > end) {
1161
                WOLFSSL_MSG("Would overread restore buffer");
1162
                ret = BUFFER_E;
1163
            }
1164
        }
1165
        if (ret == 0) {
1166
            /* Allocate memory for public key to be stored in. */
1167
            publicKey = (byte*)XMALLOC(signer->pubKeySize, cm->heap,
1168
                DYNAMIC_TYPE_KEY);
1169
            if (publicKey == NULL) {
1170
                ret = MEMORY_E;
1171
            }
1172
        }
1173
1174
        if (ret == 0) {
1175
            /* Copy in public key. */
1176
            XMEMCPY(publicKey, current + idx, signer->pubKeySize);
1177
            signer->publicKey = publicKey;
1178
            idx += (int)signer->pubKeySize;
1179
1180
            /* Copy in certificate name length. */
1181
            XMEMCPY(&signer->nameLen, current + idx, sizeof(signer->nameLen));
1182
            idx += (int)sizeof(signer->nameLen);
1183
1184
            /* Check bytes available for certificate name. */
1185
            if (start + minSz + signer->pubKeySize + signer->nameLen > end) {
1186
                WOLFSSL_MSG("Would overread restore buffer");
1187
                ret = BUFFER_E;
1188
            }
1189
        }
1190
        if (ret == 0) {
1191
            /* Allocate memory for public key to be stored in. */
1192
            signer->name = (char*)XMALLOC((size_t)signer->nameLen, cm->heap,
1193
                DYNAMIC_TYPE_SUBJECT_CN);
1194
            if (signer->name == NULL) {
1195
                ret = MEMORY_E;
1196
            }
1197
        }
1198
1199
        if (ret == 0) {
1200
            /* Copy in certificate name. */
1201
            XMEMCPY(signer->name, current + idx, (size_t)signer->nameLen);
1202
            idx += signer->nameLen;
1203
1204
            /* Copy in hash of subject name. */
1205
            XMEMCPY(signer->subjectNameHash, current + idx, SIGNER_DIGEST_SIZE);
1206
            idx += SIGNER_DIGEST_SIZE;
1207
1208
        #ifndef NO_SKID
1209
            /* Copy in hash of subject key. */
1210
            XMEMCPY(signer->subjectKeyIdHash, current + idx,SIGNER_DIGEST_SIZE);
1211
            idx += SIGNER_DIGEST_SIZE;
1212
        #endif
1213
1214
            /* Make next Signer the head of the row. */
1215
            signer->next = cm->caTable[row];
1216
            /* Add Signer to start of row. */
1217
            cm->caTable[row] = signer;
1218
1219
            /* Done one more Signer. */
1220
            --listSz;
1221
        }
1222
1223
        if ((ret != 0) && (signer != NULL)) {
1224
            /* Dispose of allocated signer. */
1225
            FreeSigner(signer, cm->heap);
1226
        }
1227
    }
1228
1229
    if (ret == 0) {
1230
        /* Return the number of bytes used on success. */
1231
        ret = idx;
1232
    }
1233
    return ret;
1234
}
1235
1236
1237
/* Store whole CA certificate row into memory.
1238
 *
1239
 * Assumes we have locked CA table.
1240
 *
1241
 * @param [in] cm       Certificate manager.
1242
 * @param [in] current  Buffer to write to.
1243
 * @param [in] row      Row number being stored.
1244
 * @return  Number of bytes added.
1245
 */
1246
static WC_INLINE int cm_store_cert_row(WOLFSSL_CERT_MANAGER* cm, byte* current,
1247
    int row)
1248
{
1249
    int     added  = 0;
1250
    Signer* list;
1251
1252
    /* Get the row - a linked list. */
1253
    list  = cm->caTable[row];
1254
    /* Each certificate in row. */
1255
    while (list != NULL) {
1256
        /* Public key size. */
1257
        XMEMCPY(current + added, &list->pubKeySize, sizeof(list->pubKeySize));
1258
        added += (int)sizeof(list->pubKeySize);
1259
1260
        /* Public key OID. */
1261
        XMEMCPY(current + added, &list->keyOID,     sizeof(list->keyOID));
1262
        added += (int)sizeof(list->keyOID);
1263
1264
        /* Public key. */
1265
        XMEMCPY(current + added, list->publicKey, (size_t)list->pubKeySize);
1266
        added += (int)list->pubKeySize;
1267
1268
        /* Certificate name length. */
1269
        XMEMCPY(current + added, &list->nameLen, sizeof(list->nameLen));
1270
        added += (int)sizeof(list->nameLen);
1271
1272
        /* Certificate name. */
1273
        XMEMCPY(current + added, list->name, (size_t)list->nameLen);
1274
        added += list->nameLen;
1275
1276
        /* Hash of subject name. */
1277
        XMEMCPY(current + added, list->subjectNameHash, SIGNER_DIGEST_SIZE);
1278
        added += SIGNER_DIGEST_SIZE;
1279
1280
    #ifndef NO_SKID
1281
        /* Hash of public key. */
1282
        XMEMCPY(current + added, list->subjectKeyIdHash,SIGNER_DIGEST_SIZE);
1283
        added += SIGNER_DIGEST_SIZE;
1284
    #endif
1285
1286
        /* Next certificate in row. */
1287
        list = list->next;
1288
    }
1289
1290
    return added;
1291
}
1292
1293
1294
/* Persist CA certificate cache to memory.
1295
 *
1296
 * Assumes we have locked CA table.
1297
 *
1298
 * @param [in] cm   Certificate manager.
1299
 * @param [in] mem  Memory to persist into.
1300
 * @param [in] sz   Size in bytes of memory.
1301
 * @return  WOLFSSL_SUCCESS on success.
1302
 * @return  BUFFER_E when memory is too small.
1303
 */
1304
static WC_INLINE int cm_do_mem_save_cert_cache(WOLFSSL_CERT_MANAGER* cm,
1305
    void* mem, int sz)
1306
{
1307
    int ret = WOLFSSL_SUCCESS;
1308
    int realSz;
1309
    int i;
1310
1311
    WOLFSSL_ENTER("cm_do_mem_save_cert_cache");
1312
1313
    /* Calculate amount of memory required to store CA certificate table. */
1314
    realSz = cm_get_cert_cache_mem_size(cm);
1315
    if (realSz > sz) {
1316
        WOLFSSL_MSG("Mem output buffer too small");
1317
        ret = BUFFER_E;
1318
    }
1319
    if (ret == WOLFSSL_SUCCESS) {
1320
        byte*           current;
1321
        CertCacheHeader hdr;
1322
1323
        /* Create header for storage. */
1324
        hdr.version  = WOLFSSL_CACHE_CERT_VERSION;
1325
        hdr.rows     = CA_TABLE_SIZE;
1326
        cm_set_cert_header_Columns(cm, hdr.columns);
1327
        hdr.signerSz = (int)sizeof(Signer);
1328
1329
        /* Copy header into memory. */
1330
        XMEMCPY(mem, &hdr, sizeof(CertCacheHeader));
1331
        current = (byte*)mem + sizeof(CertCacheHeader);
1332
1333
        /* Each row of table. */
1334
        for (i = 0; i < CA_TABLE_SIZE; ++i) {
1335
            /* Append row to memory. */
1336
            current += cm_store_cert_row(cm, current, i);
1337
        }
1338
    }
1339
1340
    return ret;
1341
}
1342
1343
1344
#if !defined(NO_FILESYSTEM)
1345
1346
/* Persist CA certificate cache to file.
1347
 *
1348
 * Locks CA table.
1349
 *
1350
 * @param [in] cm     Certificate manager.
1351
 * @param [in] fname  File name to write to.
1352
 * @return  WOLFSSL_SUCCESS on success.
1353
 * @return  WOLFSSL_BAD_FILE when opening file fails.
1354
 * @return  BAD_MUTEX_E when locking fails.
1355
 * @return  MEMORY_E when dynamic memory allocation fails.
1356
 * @return  FWRITE_ERROR when writing to file fails.
1357
 */
1358
int CM_SaveCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
1359
{
1360
    XFILE file;
1361
    int   ret = WOLFSSL_SUCCESS;
1362
1363
    WOLFSSL_ENTER("CM_SaveCertCache");
1364
1365
    /* Open file for writing. */
1366
    file = XFOPEN(fname, "w+b");
1367
    if (file == XBADFILE) {
1368
       WOLFSSL_MSG("Couldn't open cert cache save file");
1369
       ret = WOLFSSL_BAD_FILE;
1370
    }
1371
1372
    /* Lock CA table. */
1373
    if ((ret == WOLFSSL_SUCCESS) && (wc_LockMutex(&cm->caLock) != 0)) {
1374
        WOLFSSL_MSG("wc_LockMutex on caLock failed");
1375
        ret = BAD_MUTEX_E;
1376
    }
1377
1378
    if (ret == WOLFSSL_SUCCESS) {
1379
        byte* mem;
1380
        /* Calculate size of memory required to store CA table. */
1381
        size_t memSz = (size_t)cm_get_cert_cache_mem_size(cm);
1382
        /* Allocate memory to hold CA table. */
1383
        mem = (byte*)XMALLOC(memSz, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
1384
        if (mem == NULL) {
1385
            WOLFSSL_MSG("Alloc for tmp buffer failed");
1386
            ret = MEMORY_E;
1387
        }
1388
        if (ret == WOLFSSL_SUCCESS) {
1389
            /* Store CA table in memory. */
1390
            ret = cm_do_mem_save_cert_cache(cm, mem, (int)memSz);
1391
        }
1392
        if (ret == WOLFSSL_SUCCESS) {
1393
            /* Write memory to file. */
1394
            int sz = (int)XFWRITE(mem, memSz, 1, file);
1395
            if (sz != 1) {
1396
                WOLFSSL_MSG("Cert cache file write failed");
1397
                ret = FWRITE_ERROR;
1398
            }
1399
        }
1400
        XFREE(mem, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
1401
1402
        /* Unlock CA table. */
1403
        wc_UnLockMutex(&cm->caLock);
1404
    }
1405
1406
    /* Close file. */
1407
    if (file != XBADFILE) {
1408
        XFCLOSE(file);
1409
    }
1410
    return ret;
1411
}
1412
1413
1414
/* Restore CA certificate cache from file.
1415
 *
1416
 * @param [in] cm     Certificate manager.
1417
 * @param [in] fname  File name to write to.
1418
 * @return  WOLFSSL_SUCCESS on success.
1419
 * @return  WOLFSSL_BAD_FILE when opening or using file fails.
1420
 * @return  MEMORY_E when dynamic memory allocation fails.
1421
 * @return  FREAD_ERROR when reading from file fails.
1422
 */
1423
int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname)
1424
{
1425
    XFILE file;
1426
    int   ret = WOLFSSL_SUCCESS;
1427
    int   memSz = 0;
1428
    byte* mem = NULL;
1429
1430
    WOLFSSL_ENTER("CM_RestoreCertCache");
1431
1432
    /* Open file for reading. */
1433
    file = XFOPEN(fname, "rb");
1434
    if (file == XBADFILE) {
1435
       WOLFSSL_MSG("Couldn't open cert cache save file");
1436
       ret = WOLFSSL_BAD_FILE;
1437
    }
1438
1439
    if (ret == WOLFSSL_SUCCESS) {
1440
        /* Read file into allocated memory. */
1441
        ret = wolfssl_read_file(file, (char**)&mem, &memSz);
1442
        if (ret == 0) {
1443
            ret = WOLFSSL_SUCCESS;
1444
        }
1445
    }
1446
    if (ret == WOLFSSL_SUCCESS) {
1447
        /* Create the CA certificate table from memory. */
1448
        ret = CM_MemRestoreCertCache(cm, mem, memSz);
1449
        if (ret != WOLFSSL_SUCCESS) {
1450
            WOLFSSL_MSG("Mem restore cert cache failed");
1451
        }
1452
    }
1453
1454
    /* Dispose of dynamic memory read into. */
1455
    XFREE(mem, cm->heap, DYNAMIC_TYPE_TMP_BUFFER);
1456
    /* Close file. */
1457
    if (file != XBADFILE) {
1458
        XFCLOSE(file);
1459
    }
1460
    return ret;
1461
}
1462
1463
#endif /* NO_FILESYSTEM */
1464
1465
1466
/* Persist CA certificate cache to memory.
1467
 *
1468
 * Locks CA table.
1469
 *
1470
 * @param [in]  cm    Certificate manager.
1471
 * @param [in]  mem   Memory to persist into.
1472
 * @param [in]  sz    Size in bytes of memory.
1473
 * @param [out] used  Number of bytes used when persisting cache.
1474
 * @return  WOLFSSL_SUCCESS on success.
1475
 * @return  BAD_MUTEX_E when locking fails.
1476
 * @return  BUFFER_E when memory is too small.
1477
 */
1478
int CM_MemSaveCertCache(WOLFSSL_CERT_MANAGER* cm, void* mem, int sz, int* used)
1479
{
1480
    int ret = WOLFSSL_SUCCESS;
1481
1482
    WOLFSSL_ENTER("CM_MemSaveCertCache");
1483
1484
    /* Lock CA table. */
1485
    if (wc_LockMutex(&cm->caLock) != 0) {
1486
        WOLFSSL_MSG("wc_LockMutex on caLock failed");
1487
        ret = BAD_MUTEX_E;
1488
    }
1489
    if (ret == WOLFSSL_SUCCESS) {
1490
        /* Save CA table into memory. */
1491
        ret = cm_do_mem_save_cert_cache(cm, mem, sz);
1492
        if (ret == WOLFSSL_SUCCESS) {
1493
            /* Get the number of bytes used. */
1494
            *used  = cm_get_cert_cache_mem_size(cm);
1495
        }
1496
1497
        /* Unlock CA table. */
1498
        wc_UnLockMutex(&cm->caLock);
1499
    }
1500
1501
    return ret;
1502
}
1503
1504
1505
/* Restore CA certificate table from memory,
1506
 *
1507
 * Locks CA table.
1508
 *
1509
 * @param [in] cm   Certificate manager.
1510
 * @param [in] mem  Buffer containing rows.
1511
 * @param [in] sz   Size in bytes of data in buffer.
1512
 * @return  WOLFSSL_SUCCESS on success.
1513
 * @return  BUFFER_E when buffer is too small.
1514
 * @return  BAD_MUTEX_E when locking fails.
1515
 * @return  MEMORY_E when dynamic memory allocation fails.
1516
 */
1517
int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const void* mem, int sz)
1518
{
1519
    int ret = WOLFSSL_SUCCESS;
1520
    int i;
1521
    CertCacheHeader* hdr = (CertCacheHeader*)mem;
1522
    byte*            current = (byte*)mem + sizeof(CertCacheHeader);
1523
    byte*            end     = (byte*)mem + sz;  /* don't go over */
1524
1525
    WOLFSSL_ENTER("CM_MemRestoreCertCache");
1526
1527
    /* Check memory available is bigger than cache header. */
1528
    if ((sz < (int)sizeof(CertCacheHeader)) || (current > end)) {
1529
        WOLFSSL_MSG("Cert Cache Memory buffer too small");
1530
        ret = BUFFER_E;
1531
    }
1532
1533
    /* Validate the cache header. */
1534
    if ((ret == WOLFSSL_SUCCESS) &&
1535
            ((hdr->version  != WOLFSSL_CACHE_CERT_VERSION) ||
1536
             (hdr->rows     != CA_TABLE_SIZE) ||
1537
             (hdr->signerSz != (int)sizeof(Signer)))) {
1538
        WOLFSSL_MSG("Cert Cache Memory header mismatch");
1539
        ret = CACHE_MATCH_ERROR;
1540
    }
1541
1542
    /* Lock CA table. */
1543
    if ((ret == WOLFSSL_SUCCESS) && (wc_LockMutex(&cm->caLock) != 0)) {
1544
        WOLFSSL_MSG("wc_LockMutex on caLock failed");
1545
        ret = BAD_MUTEX_E;
1546
    }
1547
1548
    if (ret == WOLFSSL_SUCCESS) {
1549
        /* Dispose of current CA certificate table. */
1550
        FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
1551
1552
        /* Each row. */
1553
        for (i = 0; i < CA_TABLE_SIZE; ++i) {
1554
            /* Restore a row from memory. */
1555
            int added = cm_restore_cert_row(cm, current, i, hdr->columns[i],
1556
                end);
1557
            /* Bail on error. */
1558
            if (added < 0) {
1559
                WOLFSSL_MSG("cm_restore_cert_row error");
1560
                ret = added;
1561
                break;
1562
            }
1563
            /* Update pointer to data of next row. */
1564
            current += added;
1565
        }
1566
1567
        /* Unlock CA table. */
1568
        wc_UnLockMutex(&cm->caLock);
1569
    }
1570
1571
    return ret;
1572
}
1573
1574
1575
/* Calculate size of CA certificate cache when persisted to memory.
1576
 *
1577
 * Locks CA table.
1578
 *
1579
 * @param [in] cm  Certificate manager.
1580
 * @return  Number of bytes on success.
1581
 * @return  BAD_MUTEX_E when locking fails.
1582
 */
1583
int CM_GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm)
1584
{
1585
    int ret;
1586
1587
    WOLFSSL_ENTER("CM_GetCertCacheMemSize");
1588
1589
    /* Lock CA table. */
1590
    if (wc_LockMutex(&cm->caLock) != 0) {
1591
        WOLFSSL_MSG("wc_LockMutex on caLock failed");
1592
        ret = BAD_MUTEX_E;
1593
    }
1594
    else {
1595
        /* Calculate memory size. */
1596
        ret = cm_get_cert_cache_mem_size(cm);
1597
1598
        /* Unlock CA table. */
1599
        wc_UnLockMutex(&cm->caLock);
1600
    }
1601
1602
    return ret;
1603
}
1604
1605
#endif /* PERSIST_CERT_CACHE */
1606
1607
/*******************************************************************************
1608
 * CRL handling
1609
 ******************************************************************************/
1610
1611
/* Enables/disables the use of CRLs when validating certificates.
1612
 *
1613
 * @param [in] cm       Certificate manager.
1614
 * @param [in] options  Options for using CRLs. Valid flags:
1615
 *                        WOLFSSL_CRL_CHECKALL, WOLFSSL_CRL_CHECK.
1616
 * @return  WOLFSSL_SUCCESS on success.
1617
 * @return  WOLFSSL_FAILURE when initializing the CRL object fails.
1618
 * @return  BAD_FUNC_ARG when cm is NULL.
1619
 * @return  MEMORY_E when dynamic memory allocation fails.
1620
 * @return  NOT_COMPILED_IN when the CRL feature is disabled.
1621
 */
1622
int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER* cm, int options)
1623
0
{
1624
0
    int ret = WOLFSSL_SUCCESS;
1625
1626
0
    WOLFSSL_ENTER("wolfSSL_CertManagerEnableCRL");
1627
1628
0
    (void)options;
1629
1630
    /* Validate parameters. */
1631
0
    if (cm == NULL) {
1632
0
        ret = BAD_FUNC_ARG;
1633
0
    }
1634
1635
#if defined(OPENSSL_COMPATIBLE_DEFAULTS)
1636
    /* If disabling then don't worry about whether CRL feature is enabled. */
1637
    if ((ret == WOLFSSL_SUCCESS) && (options == 0)) {
1638
        /* Disable leaf CRL check. */
1639
        cm->crlEnabled = 0;
1640
        /* Disable all CRL checks. */
1641
        cm->crlCheckAll = 0;
1642
    }
1643
    else
1644
#endif
1645
0
    if (ret == WOLFSSL_SUCCESS) {
1646
0
#ifndef HAVE_CRL
1647
        /* CRL feature not enabled. */
1648
0
        ret = NOT_COMPILED_IN;
1649
#else
1650
        /* Create CRL object if not present. */
1651
        if (cm->crl == NULL) {
1652
            /* Allocate memory for CRL object. */
1653
            cm->crl = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), cm->heap,
1654
                                            DYNAMIC_TYPE_CRL);
1655
            if (cm->crl == NULL) {
1656
                ret = MEMORY_E;
1657
            }
1658
            if (ret == WOLFSSL_SUCCESS) {
1659
                /* Reset fields of CRL object. */
1660
                XMEMSET(cm->crl, 0, sizeof(WOLFSSL_CRL));
1661
                /* Initialize CRL object. */
1662
                if (InitCRL(cm->crl, cm) != 0) {
1663
                    WOLFSSL_MSG("Init CRL failed");
1664
                    /* Dispose of CRL object - indicating dynamically allocated.
1665
                     */
1666
                    FreeCRL(cm->crl, 1);
1667
                    cm->crl = NULL;
1668
                    ret = WOLFSSL_FAILURE;
1669
                }
1670
            }
1671
        }
1672
1673
        if (ret == WOLFSSL_SUCCESS) {
1674
        #if defined(HAVE_CRL_IO) && defined(USE_WOLFSSL_IO)
1675
            /* Use built-in callback to lookup CRL from URL. */
1676
            cm->crl->crlIOCb = EmbedCrlLookup;
1677
        #endif
1678
        #if defined(OPENSSL_COMPATIBLE_DEFAULTS)
1679
            if ((options & WOLFSSL_CRL_CHECKALL) ||
1680
                (options & WOLFSSL_CRL_CHECK))
1681
        #endif
1682
            {
1683
                /* Enable leaf CRL check. */
1684
                cm->crlEnabled = 1;
1685
                if (options & WOLFSSL_CRL_CHECKALL) {
1686
                    /* Enable all CRL check. */
1687
                    cm->crlCheckAll = 1;
1688
                }
1689
            }
1690
        }
1691
#endif
1692
0
    }
1693
1694
0
    return ret;
1695
0
}
1696
1697
1698
/* Disables the CRL checks.
1699
 *
1700
 * @param [in] cm  Certificate manager.
1701
 * @return  WOLFSSL_SUCCESS on success.
1702
 * @return  BAD_FUNC_ARG when cm is NULL.
1703
 */
1704
int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER* cm)
1705
0
{
1706
0
    int ret = WOLFSSL_SUCCESS;
1707
1708
0
    WOLFSSL_ENTER("wolfSSL_CertManagerDisableCRL");
1709
1710
    /* Validate parameter. */
1711
0
    if (cm == NULL) {
1712
0
        ret = BAD_FUNC_ARG;
1713
0
    }
1714
0
    if (ret == WOLFSSL_SUCCESS) {
1715
        /* Disable CRL checking. */
1716
0
        cm->crlEnabled = 0;
1717
0
        cm->crlCheckAll = 0;
1718
0
    }
1719
1720
0
    return ret;
1721
0
}
1722
1723
#ifdef HAVE_CRL
1724
1725
/* Load CRL for use.
1726
 *
1727
 * @param [in] cm    Certificate manager.
1728
 * @param [in] buff  Buffer holding CRL.
1729
 * @param [in] sz    Size in bytes of CRL in buffer.
1730
 * @param [in] type  Format of encoding. Valid values:
1731
 *                     WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
1732
 * @return  WOLFSSL_SUCCESS on success.
1733
 * @return  BAD_FUNC_ARG when cm or buff is NULL or sz is negative or zero.
1734
 * @return  WOLFSSL_FATAL_ERROR when creating CRL object fails.
1735
 */
1736
int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER* cm,
1737
    const unsigned char* buff, long sz, int type)
1738
{
1739
    int ret = WOLFSSL_SUCCESS;
1740
1741
    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRLBuffer");
1742
1743
    /* Validate parameters. */
1744
    if ((cm == NULL) || (buff == NULL) || (sz <= 0)) {
1745
        ret = BAD_FUNC_ARG;
1746
    }
1747
1748
    /* Create a CRL object if not available and enable CRL checking. */
1749
    if ((ret == WOLFSSL_SUCCESS) && (cm->crl == NULL) &&
1750
            (wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK) !=
1751
             WOLFSSL_SUCCESS)) {
1752
        WOLFSSL_MSG("Enable CRL failed");
1753
        ret = WOLFSSL_FATAL_ERROR;
1754
    }
1755
1756
    if (ret == WOLFSSL_SUCCESS) {
1757
        /* Load CRL into CRL object of the certificate manager. */
1758
        ret = BufferLoadCRL(cm->crl, buff, sz, type, VERIFY);
1759
    }
1760
1761
    return ret;
1762
}
1763
1764
/* Free the CRL object of the certificate manager.
1765
 *
1766
 * @param [in] cm  Certificate manager.
1767
 * @return  WOLFSSL_SUCCESS on success.
1768
 * @return  BAD_FUNC_ARG when cm is NULL.
1769
 */
1770
int wolfSSL_CertManagerFreeCRL(WOLFSSL_CERT_MANAGER* cm)
1771
{
1772
    int ret = WOLFSSL_SUCCESS;
1773
1774
    WOLFSSL_ENTER("wolfSSL_CertManagerFreeCRL");
1775
1776
    /* Validate parameter. */
1777
    if (cm == NULL) {
1778
        ret = BAD_FUNC_ARG;
1779
    }
1780
    /* Check whether CRL object exists. */
1781
    if ((ret == WOLFSSL_SUCCESS) && (cm->crl != NULL)) {
1782
        /* Dispose of CRL object - indicating dynamically allocated. */
1783
        FreeCRL(cm->crl, 1);
1784
        cm->crl = NULL;
1785
    }
1786
1787
    return ret;
1788
}
1789
1790
/* Check DER encoded certificate against CRLs if checking enabled.
1791
 *
1792
 * @param [in] cm   Certificate manager.
1793
 * @param [in] der  DER encode certificate.
1794
 * @param [in] sz   Size in bytes of DER encode certificate.
1795
 * @return  WOLFSSL_SUCCESS on success.
1796
 * @return  BAD_FUNC_ARG when cm or der is NULL or sz is negative or zero.
1797
 * @return  MEMORY_E when dynamic memory allocation fails.
1798
 */
1799
int wolfSSL_CertManagerCheckCRL(WOLFSSL_CERT_MANAGER* cm,
1800
    const unsigned char* der, int sz)
1801
{
1802
    int ret = 0;
1803
#ifdef WOLFSSL_SMALL_STACK
1804
    DecodedCert* cert = NULL;
1805
#else
1806
    DecodedCert  cert[1];
1807
#endif
1808
1809
    WOLFSSL_ENTER("wolfSSL_CertManagerCheckCRL");
1810
1811
    /* Validate parameters. */
1812
    if ((cm == NULL) || (der == NULL) || (sz <= 0)) {
1813
        ret = BAD_FUNC_ARG;
1814
    }
1815
1816
    /* Check if CRL checking enabled. */
1817
    if ((ret == 0) && cm->crlEnabled) {
1818
    #ifdef WOLFSSL_SMALL_STACK
1819
        /* Allocate memory for decoded certificate. */
1820
        cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
1821
            DYNAMIC_TYPE_DCERT);
1822
        if (cert == NULL)
1823
            ret = MEMORY_E;
1824
        if (ret == 0)
1825
    #endif
1826
        {
1827
            /* Initialize decoded certificate with buffer. */
1828
            InitDecodedCert(cert, der, (word32)sz, NULL);
1829
1830
            /* Parse certificate and perform CRL checks. */
1831
            ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_CRL, cm, NULL);
1832
            if (ret != 0) {
1833
                WOLFSSL_MSG("ParseCert failed");
1834
            }
1835
            /* Do CRL checks with decoded certificate. */
1836
            else if ((ret = CheckCertCRL(cm->crl, cert)) != 0) {
1837
                WOLFSSL_MSG("CheckCertCRL failed");
1838
            }
1839
1840
            /* Dispose of dynamically allocated memory. */
1841
            FreeDecodedCert(cert);
1842
        #ifdef WOLFSSL_SMALL_STACK
1843
            XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
1844
        #endif
1845
        }
1846
    }
1847
1848
    return (ret == 0) ? WOLFSSL_SUCCESS : ret;
1849
}
1850
1851
/* Set the missing CRL callback.
1852
 *
1853
 * @param [in] cm  Certificate manager.
1854
 * @param [in] cb  Missing CRL callback.
1855
 * @return  WOLFSSL_SUCCESS on success.
1856
 * @return  BAD_FUNC_ARG when cm is NULL.
1857
 */
1858
int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER* cm, CbMissingCRL cb)
1859
{
1860
    int ret = WOLFSSL_SUCCESS;
1861
1862
    WOLFSSL_ENTER("wolfSSL_CertManagerSetCRL_Cb");
1863
1864
    /* Validate parameters. */
1865
    if (cm == NULL) {
1866
        ret = BAD_FUNC_ARG;
1867
    }
1868
    if (ret == WOLFSSL_SUCCESS) {
1869
        /* Store callback. */
1870
        cm->cbMissingCRL = cb;
1871
    }
1872
1873
    return ret;
1874
}
1875
1876
int wolfSSL_CertManagerSetCRL_ErrorCb(WOLFSSL_CERT_MANAGER* cm, crlErrorCb cb,
1877
                                      void* ctx)
1878
{
1879
    int ret = WOLFSSL_SUCCESS;
1880
1881
    WOLFSSL_ENTER("wolfSSL_CertManagerSetCRL_Cb");
1882
1883
    /* Validate parameters. */
1884
    if (cm == NULL) {
1885
        ret = BAD_FUNC_ARG;
1886
    }
1887
    if (ret == WOLFSSL_SUCCESS) {
1888
        /* Store callback. */
1889
        cm->crlCb = cb;
1890
        cm->crlCbCtx = ctx;
1891
    }
1892
1893
    return ret;
1894
}
1895
1896
#ifdef HAVE_CRL_UPDATE_CB
1897
int wolfSSL_CertManagerGetCRLInfo(WOLFSSL_CERT_MANAGER* cm, CrlInfo* info,
1898
    const byte* buff, long sz, int type)
1899
{
1900
    return GetCRLInfo(cm->crl, info, buff, sz, type);
1901
}
1902
1903
/* Set the callback to be called when a CRL entry has
1904
 * been updated (new entry had the same issuer hash and
1905
 * a newer CRL number).
1906
 *
1907
 * @param [in] cm  Certificate manager.
1908
 * @param [in] cb  CRL update callback.
1909
 * @return  WOLFSSL_SUCCESS on success.
1910
 * @return  BAD_FUNC_ARG when cm is NULL.
1911
 */
1912
int wolfSSL_CertManagerSetCRLUpdate_Cb(WOLFSSL_CERT_MANAGER* cm, CbUpdateCRL cb)
1913
{
1914
    int ret = WOLFSSL_SUCCESS;
1915
1916
    WOLFSSL_ENTER("wolfSSL_CertManagerSetCRLUpdate_Cb");
1917
1918
    /* Validate parameters. */
1919
    if (cm == NULL) {
1920
        ret = BAD_FUNC_ARG;
1921
    }
1922
    if (ret == WOLFSSL_SUCCESS) {
1923
        /* Store callback. */
1924
        cm->cbUpdateCRL = cb;
1925
    }
1926
1927
    return ret;
1928
}
1929
#endif
1930
1931
#ifdef HAVE_CRL_IO
1932
/* Set the CRL I/O callback.
1933
 *
1934
 * @param [in] cm  Certificate manager.
1935
 * @param [in] cb  CRL I/O callback.
1936
 * @return  WOLFSSL_SUCCESS on success.
1937
 * @return  BAD_FUNC_ARG when cm is NULL.
1938
 */
1939
int wolfSSL_CertManagerSetCRL_IOCb(WOLFSSL_CERT_MANAGER* cm, CbCrlIO cb)
1940
{
1941
    int ret = WOLFSSL_SUCCESS;
1942
1943
    /* Validate parameters. */
1944
    if (cm == NULL) {
1945
        ret = BAD_FUNC_ARG;
1946
    }
1947
    if ((ret == WOLFSSL_SUCCESS) && (cm->crl != NULL)) {
1948
        /* Store callback. */
1949
        cm->crl->crlIOCb = cb;
1950
    }
1951
1952
    return ret;
1953
}
1954
#endif
1955
1956
#ifndef NO_FILESYSTEM
1957
/* Load CRL/s from path with the option of monitoring for changes.
1958
 *
1959
 * @param [in] cm       Certificate manager.
1960
 * @param [in] path     Path to a directory containing CRLs.
1961
 * @param [in] type     Format of encoding. Valid values:
1962
 *                        WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
1963
 * @param [in] monitor  Whether to monitor path for changes to files.
1964
 * @return  WOLFSSL_SUCCESS on success.
1965
 * @return  BAD_FUNC_ARG when cm or path is NULL.
1966
 * @return  WOLFSSL_FATAL_ERROR when enabling CRLs fails.
1967
 */
1968
int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER* cm, const char* path,
1969
    int type, int monitor)
1970
{
1971
    int ret = WOLFSSL_SUCCESS;
1972
1973
    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRL");
1974
1975
    /* Validate parameters. */
1976
    if ((cm == NULL) || (path == NULL)) {
1977
        ret = BAD_FUNC_ARG;
1978
    }
1979
1980
    /* Create a CRL object if not available. */
1981
    if ((ret == WOLFSSL_SUCCESS) && (cm->crl == NULL) &&
1982
            (wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK) !=
1983
             WOLFSSL_SUCCESS)) {
1984
        WOLFSSL_MSG("Enable CRL failed");
1985
        ret = WOLFSSL_FATAL_ERROR;
1986
    }
1987
1988
    if (ret == WOLFSSL_SUCCESS) {
1989
        /* Load CRLs from path into CRL object of certificate manager. */
1990
        ret = LoadCRL(cm->crl, path, type, monitor);
1991
    }
1992
1993
    return ret;
1994
}
1995
1996
/* Load CRL from file.
1997
 *
1998
 * @param [in] cm    Certificate manager.
1999
 * @param [in] file  Path to a directory containing CRLs.
2000
 * @param [in] type  Format of encoding. Valid values:
2001
 *                       WOLFSSL_FILETYPE_ASN1, WOLFSSL_FILETYPE_PEM.
2002
 * @return  WOLFSSL_SUCCESS on success.
2003
 * @return  BAD_FUNC_ARG when cm or file is NULL.
2004
 * @return  WOLFSSL_FATAL_ERROR when enabling CRLs fails.
2005
 */
2006
int wolfSSL_CertManagerLoadCRLFile(WOLFSSL_CERT_MANAGER* cm, const char* file,
2007
    int type)
2008
{
2009
    int ret = WOLFSSL_SUCCESS;
2010
2011
    WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRLFile");
2012
2013
    /* Validate parameters. */
2014
    if ((cm == NULL) || (file == NULL)) {
2015
        ret = BAD_FUNC_ARG;
2016
    }
2017
2018
    /* Create a CRL object if not available. */
2019
    if ((ret == WOLFSSL_SUCCESS) && (cm->crl == NULL) &&
2020
            (wolfSSL_CertManagerEnableCRL(cm, WOLFSSL_CRL_CHECK) !=
2021
             WOLFSSL_SUCCESS)) {
2022
        WOLFSSL_MSG("Enable CRL failed");
2023
        ret = WOLFSSL_FATAL_ERROR;
2024
    }
2025
2026
    if (ret == WOLFSSL_SUCCESS) {
2027
        /* Load CRL file into CRL object of certificate manager. */
2028
        ret = ProcessFile(NULL, file, type, CRL_TYPE, NULL, 0, cm->crl, VERIFY);
2029
    }
2030
2031
    return ret;
2032
}
2033
#endif /* !NO_FILESYSTEM */
2034
2035
#endif /* HAVE_CRL */
2036
2037
/*******************************************************************************
2038
 * OCSP handling
2039
 ******************************************************************************/
2040
2041
/* Enables OCSP when validating certificates and sets options.
2042
 *
2043
 * @param [in] cm       Certificate manager.
2044
 * @param [in] options  Options for using OCSP. Valid flags:
2045
 *                        WOLFSSL_OCSP_URL_OVERRIDE, WOLFSSL_OCSP_NO_NONCE,
2046
 *                        WOLFSSL_OCSP_CHECKALL.
2047
 * @return  WOLFSSL_SUCCESS on success.
2048
 * @return  0 when initializing the OCSP object fails.
2049
 * @return  BAD_FUNC_ARG when cm is NULL.
2050
 * @return  MEMORY_E when dynamic memory allocation fails.
2051
 * @return  NOT_COMPILED_IN when the OCSP feature is disabled.
2052
 */
2053
int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER* cm, int options)
2054
0
{
2055
0
    int ret = WOLFSSL_SUCCESS;
2056
2057
0
    (void)options;
2058
2059
0
    WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSP");
2060
2061
    /* Validate parameters. */
2062
0
    if (cm == NULL) {
2063
0
        ret = BAD_FUNC_ARG;
2064
0
    }
2065
2066
0
#ifndef HAVE_OCSP
2067
0
    if (ret == WOLFSSL_SUCCESS) {
2068
        /* OCSP feature not enabled. */
2069
0
        ret = NOT_COMPILED_IN;
2070
0
    }
2071
#else
2072
    if (ret == WOLFSSL_SUCCESS) {
2073
        /* Check whether OCSP object is available. */
2074
        if (cm->ocsp == NULL) {
2075
            /* Allocate memory for OCSP object. */
2076
            cm->ocsp = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP), cm->heap,
2077
                DYNAMIC_TYPE_OCSP);
2078
            if (cm->ocsp == NULL) {
2079
                ret = MEMORY_E;
2080
            }
2081
            if (ret == WOLFSSL_SUCCESS) {
2082
                /* Reset the fields of the OCSP object. */
2083
                XMEMSET(cm->ocsp, 0, sizeof(WOLFSSL_OCSP));
2084
                /* Initialize the OCSP object. */
2085
                if (InitOCSP(cm->ocsp, cm) != 0) {
2086
                    WOLFSSL_MSG("Init OCSP failed");
2087
                    /* Dispose of OCSP object - indicating dynamically allocated.
2088
                     */
2089
                    FreeOCSP(cm->ocsp, 1);
2090
                    cm->ocsp = NULL;
2091
                    ret = 0;
2092
                }
2093
            }
2094
        }
2095
    }
2096
    if (ret == WOLFSSL_SUCCESS) {
2097
        /* Enable OCSP checking. */
2098
        cm->ocspEnabled = 1;
2099
        /* Enable URL override if requested. */
2100
        if (options & WOLFSSL_OCSP_URL_OVERRIDE) {
2101
            cm->ocspUseOverrideURL = 1;
2102
        }
2103
        /* Set nonce option for creating OCSP requests. */
2104
        cm->ocspSendNonce = (options & WOLFSSL_OCSP_NO_NONCE) !=
2105
            WOLFSSL_OCSP_NO_NONCE;
2106
        /* Set all OCSP checks on if requested. */
2107
        if (options & WOLFSSL_OCSP_CHECKALL) {
2108
            cm->ocspCheckAll = 1;
2109
        }
2110
    #ifndef WOLFSSL_USER_IO
2111
        /* Set built-in OCSP lookup. */
2112
        cm->ocspIOCb = EmbedOcspLookup;
2113
        cm->ocspRespFreeCb = EmbedOcspRespFree;
2114
        cm->ocspIOCtx = cm->heap;
2115
    #endif /* WOLFSSL_USER_IO */
2116
    }
2117
#endif /* HAVE_OCSP */
2118
2119
0
    return ret;
2120
0
}
2121
2122
/* Disables the OCSP checks.
2123
 *
2124
 * @param [in] cm  Certificate manager.
2125
 * @return  WOLFSSL_SUCCESS on success.
2126
 * @return  BAD_FUNC_ARG when cm is NULL.
2127
 */
2128
int wolfSSL_CertManagerDisableOCSP(WOLFSSL_CERT_MANAGER* cm)
2129
0
{
2130
0
    int ret = WOLFSSL_SUCCESS;
2131
2132
0
    WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSP");
2133
2134
    /* Validate parameter. */
2135
0
    if (cm == NULL) {
2136
0
        ret = BAD_FUNC_ARG;
2137
0
    }
2138
0
    if (ret == WOLFSSL_SUCCESS) {
2139
        /* Disable use of OCSP with certificate validation. */
2140
0
        cm->ocspEnabled = 0;
2141
0
    }
2142
2143
0
    return ret;
2144
0
}
2145
2146
/* Enables OCSP stapling with certificates in manager.
2147
 *
2148
 * @param [in] cm       Certificate manager.
2149
 * @param [in] options  Options for using OCSP. Valid flags:
2150
 *                        WOLFSSL_OCSP_URL_OVERRIDE, WOLFSSL_OCSP_NO_NONCE,
2151
 *                        WOLFSSL_OCSP_CHECKALL.
2152
 * @return  WOLFSSL_SUCCESS on success.
2153
 * @return  0 when initializing the OCSP stapling object fails.
2154
 * @return  BAD_FUNC_ARG when cm is NULL.
2155
 * @return  MEMORY_E when dynamic memory allocation fails.
2156
 * @return  NOT_COMPILED_IN when the OCSP stapling feature is disabled.
2157
 */
2158
int wolfSSL_CertManagerEnableOCSPStapling(WOLFSSL_CERT_MANAGER* cm)
2159
0
{
2160
0
    int ret = WOLFSSL_SUCCESS;
2161
2162
0
    WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSPStapling");
2163
2164
    /* Validate parameters. */
2165
0
    if (cm == NULL) {
2166
0
        ret = BAD_FUNC_ARG;
2167
0
    }
2168
2169
0
#if !defined(HAVE_CERTIFICATE_STATUS_REQUEST) && \
2170
0
    !defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
2171
0
    if (ret == WOLFSSL_SUCCESS) {
2172
        /* OCSP stapling feature not enabled. */
2173
0
        ret = NOT_COMPILED_IN;
2174
0
    }
2175
#else
2176
#ifndef NO_WOLFSSL_SERVER
2177
    if (ret == WOLFSSL_SUCCESS) {
2178
        /* Check whether OCSP object is available. */
2179
        if (cm->ocsp_stapling == NULL) {
2180
            /* Allocate memory for OCSP stapling object. */
2181
            cm->ocsp_stapling = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP),
2182
                cm->heap, DYNAMIC_TYPE_OCSP);
2183
            if (cm->ocsp_stapling == NULL) {
2184
                ret = MEMORY_E;
2185
            }
2186
            if (ret == WOLFSSL_SUCCESS) {
2187
                /* Reset the fields of the OCSP object. */
2188
                XMEMSET(cm->ocsp_stapling, 0, sizeof(WOLFSSL_OCSP));
2189
                /* Initialize the OCSP stapling object. */
2190
                if (InitOCSP(cm->ocsp_stapling, cm) != 0) {
2191
                    WOLFSSL_MSG("Init OCSP failed");
2192
                    /* Dispose of OCSP stapling object - indicating dynamically
2193
                     * allocated. */
2194
                    FreeOCSP(cm->ocsp_stapling, 1);
2195
                    cm->ocsp_stapling = NULL;
2196
                    ret = 0;
2197
                }
2198
            }
2199
        }
2200
    }
2201
#ifndef WOLFSSL_USER_IO
2202
    if (ret == WOLFSSL_SUCCESS) {
2203
        /* Set built-in OCSP lookup. */
2204
        cm->ocspIOCb = EmbedOcspLookup;
2205
        cm->ocspRespFreeCb = EmbedOcspRespFree;
2206
        cm->ocspIOCtx = cm->heap;
2207
    }
2208
#endif /* WOLFSSL_USER_IO */
2209
#endif /* NO_WOLFSSL_SERVER */
2210
    if (ret == WOLFSSL_SUCCESS) {
2211
        /* Enable OCSP stapling. */
2212
        cm->ocspStaplingEnabled = 1;
2213
    }
2214
#endif /* HAVE_CERTIFICATE_STATUS_REQUEST ||
2215
        * HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
2216
2217
0
    return ret;
2218
0
}
2219
2220
/* Disables OCSP Stapling.
2221
 *
2222
 * @param [in] cm  Certificate manager.
2223
 * @return  WOLFSSL_SUCCESS on success.
2224
 * @return  BAD_FUNC_ARG when cm is NULL.
2225
 */
2226
int wolfSSL_CertManagerDisableOCSPStapling(WOLFSSL_CERT_MANAGER* cm)
2227
0
{
2228
0
    int ret = WOLFSSL_SUCCESS;
2229
2230
0
    WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSPStapling");
2231
2232
    /* Validate parameter. */
2233
0
    if (cm == NULL) {
2234
0
        ret = BAD_FUNC_ARG;
2235
0
    }
2236
0
    if (ret == WOLFSSL_SUCCESS) {
2237
    #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
2238
        defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
2239
        /* Disable use of OCSP Stapling. */
2240
        cm->ocspStaplingEnabled = 0;
2241
    #else
2242
        /* OCSP stapling feature not enabled. */
2243
0
        ret = NOT_COMPILED_IN;
2244
0
    #endif
2245
0
    }
2246
2247
0
    return ret;
2248
0
}
2249
2250
/* Enable the must use OCSP Stapling option.
2251
 *
2252
 * @param [in] cm  Certificate manager.
2253
 * @return  WOLFSSL_SUCCESS on success.
2254
 * @return  BAD_FUNC_ARG when cm is NULL.
2255
 */
2256
int wolfSSL_CertManagerEnableOCSPMustStaple(WOLFSSL_CERT_MANAGER* cm)
2257
0
{
2258
0
    int ret = WOLFSSL_SUCCESS;
2259
2260
0
    WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSPMustStaple");
2261
2262
    /* Validate parameter. */
2263
0
    if (cm == NULL) {
2264
0
        ret = BAD_FUNC_ARG;
2265
0
    }
2266
0
    if (ret == WOLFSSL_SUCCESS) {
2267
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
2268
    defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
2269
    #ifndef NO_WOLFSSL_CLIENT
2270
        /* Enable must use OCSP Stapling option. */
2271
        cm->ocspMustStaple = 1;
2272
    #endif
2273
#else
2274
        /* OCSP stapling feature not enabled. */
2275
0
        ret = NOT_COMPILED_IN;
2276
0
#endif
2277
0
    }
2278
2279
0
    return ret;
2280
0
}
2281
2282
/* Disable the must use OCSP Stapling option.
2283
 *
2284
 * @param [in] cm  Certificate manager.
2285
 * @return  WOLFSSL_SUCCESS on success.
2286
 * @return  BAD_FUNC_ARG when cm is NULL.
2287
 */
2288
int wolfSSL_CertManagerDisableOCSPMustStaple(WOLFSSL_CERT_MANAGER* cm)
2289
0
{
2290
0
    int ret = WOLFSSL_SUCCESS;
2291
2292
0
    WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSPMustStaple");
2293
2294
    /* Validate parameter. */
2295
0
    if (cm == NULL) {
2296
0
        ret = BAD_FUNC_ARG;
2297
0
    }
2298
2299
0
    if (ret == WOLFSSL_SUCCESS) {
2300
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
2301
    defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
2302
    #ifndef NO_WOLFSSL_CLIENT
2303
        /* Disable must use OCSP Stapling option. */
2304
        cm->ocspMustStaple = 0;
2305
    #endif
2306
#else
2307
        /* OCSP stapling feature not enabled. */
2308
0
        ret = NOT_COMPILED_IN;
2309
0
#endif
2310
0
    }
2311
2312
0
    return ret;
2313
0
}
2314
2315
#ifdef HAVE_OCSP
2316
/* Check DER encoded certificate against with OCSP if checking enabled.
2317
 *
2318
 * @param [in] cm   Certificate manager.
2319
 * @param [in] der  DER encode certificate.
2320
 * @param [in] sz   Size in bytes of DER encode certificate.
2321
 * @return  WOLFSSL_SUCCESS on success.
2322
 * @return  BAD_FUNC_ARG when cm or der is NULL or sz is negative or 0.
2323
 * @return  MEMORY_E when dynamic memory allocation fails.
2324
 */
2325
int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER* cm,
2326
    const unsigned char* der, int sz)
2327
{
2328
    int ret = 0;
2329
#ifdef WOLFSSL_SMALL_STACK
2330
    DecodedCert* cert = NULL;
2331
#else
2332
    DecodedCert  cert[1];
2333
#endif
2334
2335
    WOLFSSL_ENTER("wolfSSL_CertManagerCheckOCSP");
2336
2337
    /* Validate parameters. */
2338
    if ((cm == NULL) || (der == NULL) || (sz <= 0)) {
2339
        ret = BAD_FUNC_ARG;
2340
    }
2341
2342
    /* Check if OCSP checking enabled. */
2343
    if ((ret == 0) && cm->ocspEnabled) {
2344
    #ifdef WOLFSSL_SMALL_STACK
2345
        /* Allocate memory for decoded certificate. */
2346
        cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap,
2347
            DYNAMIC_TYPE_DCERT);
2348
        if (cert == NULL) {
2349
            ret = MEMORY_E;
2350
        }
2351
        if (ret == 0)
2352
    #endif
2353
        {
2354
            /* Initialize decoded certificate with buffer. */
2355
            InitDecodedCert(cert, der, (word32)sz, NULL);
2356
2357
            /* Parse certificate and perform CRL checks. */
2358
            ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_OCSP, cm, NULL);
2359
            if (ret != 0) {
2360
                WOLFSSL_MSG("ParseCert failed");
2361
            }
2362
            /* Do OCSP checks with decoded certificate. */
2363
            else if ((ret = CheckCertOCSP(cm->ocsp, cert)) != 0) {
2364
                WOLFSSL_MSG("CheckCertOCSP failed");
2365
            }
2366
2367
            /* Dispose of dynamically allocated memory. */
2368
            FreeDecodedCert(cert);
2369
        #ifdef WOLFSSL_SMALL_STACK
2370
            XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT);
2371
        #endif
2372
        }
2373
    }
2374
2375
    return (ret == 0) ? WOLFSSL_SUCCESS : ret;
2376
}
2377
2378
/* Check OCSP response.
2379
 *
2380
 * @param [in] cm              Certificate manager.
2381
 * @param [in] response        Buffer holding OCSP response.
2382
 * @param [in] responseSz      Size in bytes of OCSP response.
2383
 * @param [in] responseBuffer  Buffer to copy response into.
2384
 * @param [in] status          Place to store certificate status.
2385
 * @param [in] entry           Place to store OCSP entry.
2386
 * @param [in] ocspRequest     OCSP request to match with response.
2387
 * @return  WOLFSSL_SUCCESS on success.
2388
 * @return  BAD_FUNC_ARG when cm or response is NULL.
2389
 */
2390
int wolfSSL_CertManagerCheckOCSPResponse(WOLFSSL_CERT_MANAGER *cm,
2391
    byte *response, int responseSz, buffer *responseBuffer,
2392
    CertStatus *status, OcspEntry *entry, OcspRequest *ocspRequest)
2393
{
2394
    int ret = 0;
2395
2396
    WOLFSSL_ENTER("wolfSSL_CertManagerCheckOCSPResponse");
2397
2398
    /* Validate parameters. */
2399
    if ((cm == NULL) || (response == NULL)) {
2400
        ret = BAD_FUNC_ARG;
2401
    }
2402
    if ((ret == 0) && cm->ocspEnabled) {
2403
        /* Check OCSP response with OCSP object from certificate manager. */
2404
        ret = CheckOcspResponse(cm->ocsp, response, responseSz, responseBuffer,
2405
            status, entry, ocspRequest, NULL);
2406
    }
2407
2408
    return (ret == 0) ? WOLFSSL_SUCCESS : ret;
2409
}
2410
2411
/* Set the OCSP override URL.
2412
 *
2413
 * @param [in] cm   Certificate manager.
2414
 * @param [in] url  URL to get an OCSP response from.
2415
 * @return  WOLFSSL_SUCCESS on success.
2416
 * @return  BAD_FUNC_ARG when cm is NULL.
2417
 * @return  MEMORY_E when dynamic memory allocation fails.
2418
 */
2419
int wolfSSL_CertManagerSetOCSPOverrideURL(WOLFSSL_CERT_MANAGER* cm,
2420
    const char* url)
2421
{
2422
    int ret = WOLFSSL_SUCCESS;
2423
2424
    WOLFSSL_ENTER("wolfSSL_CertManagerSetOCSPOverrideURL");
2425
2426
    /* Validate parameters. */
2427
    if (cm == NULL) {
2428
        ret = BAD_FUNC_ARG;
2429
    }
2430
2431
    if (ret == WOLFSSL_SUCCESS) {
2432
        /* Dispose of old URL. */
2433
        XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL);
2434
        if (url != NULL) {
2435
            /* Calculate size of URL string. Include terminator character. */
2436
            int urlSz = (int)XSTRLEN(url) + 1;
2437
            /* Allocate memory for URL to be copied into. */
2438
            cm->ocspOverrideURL = (char*)XMALLOC((size_t)urlSz, cm->heap,
2439
                DYNAMIC_TYPE_URL);
2440
            if (cm->ocspOverrideURL == NULL) {
2441
                ret = MEMORY_E;
2442
            }
2443
            if (ret == WOLFSSL_SUCCESS) {
2444
                /* Copy URL into certificate manager. */
2445
                XMEMCPY(cm->ocspOverrideURL, url, (size_t)urlSz);
2446
            }
2447
        }
2448
        else {
2449
            /* No URL to set so make it NULL. */
2450
            cm->ocspOverrideURL = NULL;
2451
        }
2452
    }
2453
2454
    return ret;
2455
}
2456
2457
/* Set the OCSP I/O callback, OCSP response free callback and related data.
2458
 *
2459
 * @param [in] cm          Certificate manager.
2460
 * @param [in] ioCb        OCSP callback.
2461
 * @param [in] respFreeCb  Callback to free OCSP response buffer.
2462
 * @param [in] ioCbCtx     Context data to pass to OCSP callbacks.
2463
 * @return  WOLFSSL_SUCCESS on success.
2464
 * @return  BAD_FUNC_ARG when cm is NULL.
2465
 */
2466
int wolfSSL_CertManagerSetOCSP_Cb(WOLFSSL_CERT_MANAGER* cm, CbOCSPIO ioCb,
2467
    CbOCSPRespFree respFreeCb, void* ioCbCtx)
2468
{
2469
    int ret = WOLFSSL_SUCCESS;
2470
2471
    WOLFSSL_ENTER("wolfSSL_CertManagerSetOCSP_Cb");
2472
2473
    /* Validate parameters. */
2474
    if (cm == NULL) {
2475
        ret = BAD_FUNC_ARG;
2476
    }
2477
    if (ret == WOLFSSL_SUCCESS) {
2478
        /* Set callbacks and data into certificate manager. */
2479
        cm->ocspIOCb = ioCb;
2480
        cm->ocspRespFreeCb = respFreeCb;
2481
        cm->ocspIOCtx = ioCbCtx;
2482
    }
2483
2484
    return ret;
2485
}
2486
2487
#endif /* HAVE_OCSP */
2488
2489
#endif /* NO_CERTS */
2490
2491
#endif /* !WOLFSSL_SSL_CERTMAN_INCLUDED */