Coverage Report

Created: 2026-08-23 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl/src/x509_str.c
Line
Count
Source
1
/* x509_str.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
#if !defined(WOLFSSL_X509_STORE_INCLUDED)
25
    #ifndef WOLFSSL_IGNORE_FILE_WARN
26
        #warning x509_str.c does not need to be compiled separately from ssl.c
27
    #endif
28
#else
29
30
#ifndef WOLFCRYPT_ONLY
31
32
#ifndef NO_CERTS
33
34
#ifdef OPENSSL_EXTRA
35
static int X509StoreGetIssuerEx(WOLFSSL_X509 **issuer,
36
                            WOLFSSL_STACK *certs, WOLFSSL_X509 *x);
37
static int X509StoreGetIssuerSkip(WOLFSSL_X509 **issuer,
38
                            WOLFSSL_STACK *certs, WOLFSSL_X509 *x,
39
                            WOLF_STACK_OF(WOLFSSL_X509)* skip);
40
static int X509StoreAddCa(WOLFSSL_X509_STORE* store,
41
                                          WOLFSSL_X509* x509, int type);
42
#endif
43
44
/* Based on OpenSSL default max depth */
45
#ifndef WOLFSSL_X509_STORE_DEFAULT_MAX_DEPTH
46
#define WOLFSSL_X509_STORE_DEFAULT_MAX_DEPTH 100
47
#endif
48
49
/******************************************************************************
50
 * START OF X509_STORE_CTX APIs
51
 *****************************************************************************/
52
53
/* This API is necessary outside of OPENSSL_EXTRA because it is used in
54
 * SetupStoreCtxCallback */
55
WOLFSSL_X509_STORE_CTX* wolfSSL_X509_STORE_CTX_new_ex(void* heap)
56
0
{
57
0
    WOLFSSL_X509_STORE_CTX* ctx;
58
0
    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_new_ex");
59
60
0
    ctx = (WOLFSSL_X509_STORE_CTX*)XMALLOC(sizeof(WOLFSSL_X509_STORE_CTX), heap,
61
0
                                    DYNAMIC_TYPE_X509_CTX);
62
0
    if (ctx != NULL) {
63
0
        XMEMSET(ctx, 0, sizeof(WOLFSSL_X509_STORE_CTX));
64
0
        ctx->heap = heap;
65
#ifdef OPENSSL_EXTRA
66
        if ((ctx->owned = wolfSSL_sk_X509_new_null()) == NULL) {
67
            XFREE(ctx, heap, DYNAMIC_TYPE_X509_CTX);
68
            ctx = NULL;
69
        }
70
        if (ctx != NULL &&
71
            wolfSSL_X509_STORE_CTX_init(ctx, NULL, NULL, NULL) !=
72
                WOLFSSL_SUCCESS) {
73
            wolfSSL_X509_STORE_CTX_free(ctx);
74
            ctx = NULL;
75
        }
76
#endif
77
0
    }
78
79
0
    return ctx;
80
0
}
81
82
/* This API is necessary outside of OPENSSL_EXTRA because it is used in
83
 * SetupStoreCtxCallback */
84
/* free's extra data */
85
void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX* ctx)
86
0
{
87
0
    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_free");
88
0
    if (ctx != NULL) {
89
#ifdef HAVE_EX_DATA_CLEANUP_HOOKS
90
        wolfSSL_CRYPTO_cleanup_ex_data(&ctx->ex_data);
91
#endif
92
93
#ifdef OPENSSL_EXTRA
94
        XFREE(ctx->param, ctx->heap, DYNAMIC_TYPE_OPENSSL);
95
        ctx->param = NULL;
96
97
        if (ctx->chain != NULL) {
98
            wolfSSL_sk_X509_pop_free(ctx->chain, NULL);
99
        }
100
        if (ctx->owned != NULL) {
101
            wolfSSL_sk_X509_pop_free(ctx->owned, NULL);
102
        }
103
104
        if (ctx->current_issuer != NULL) {
105
            wolfSSL_X509_free(ctx->current_issuer);
106
            ctx->current_issuer = NULL;
107
        }
108
#endif
109
110
0
        XFREE(ctx, ctx->heap, DYNAMIC_TYPE_X509_CTX);
111
0
    }
112
0
}
113
114
#ifdef OPENSSL_EXTRA
115
116
#if defined(SESSION_CERTS) || defined(WOLFSSL_SIGNER_DER_CERT)
117
118
/**
119
 * Find the issuing cert of the input cert. On a self-signed cert this
120
 * function will return an error.
121
 * @param issuer The issuer x509 struct is returned here
122
 * @param cm     The cert manager that is queried for the issuer
123
 * @param x      This cert's issuer will be queried in cm
124
 * @return       WOLFSSL_SUCCESS on success
125
 *               WOLFSSL_FAILURE on error
126
 */
127
static int x509GetIssuerFromCM(WOLFSSL_X509 **issuer, WOLFSSL_CERT_MANAGER* cm,
128
        WOLFSSL_X509 *x)
129
{
130
    Signer* ca = NULL;
131
    WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
132
133
    if (cm == NULL || x == NULL || x->derCert == NULL) {
134
        WOLFSSL_MSG("No cert DER buffer or NULL cm. Defining "
135
                    "WOLFSSL_SIGNER_DER_CERT could solve the issue");
136
        return WOLFSSL_FAILURE;
137
    }
138
139
    WC_ALLOC_VAR_EX(cert, DecodedCert, 1, NULL, DYNAMIC_TYPE_DCERT,
140
        return WOLFSSL_FAILURE);
141
142
    /* Use existing CA retrieval APIs that use DecodedCert. */
143
    InitDecodedCert(cert, x->derCert->buffer, x->derCert->length, cm->heap);
144
    if (ParseCertRelative(cert, CERT_TYPE, 0, NULL, NULL) == 0
145
            && !cert->selfSigned) {
146
    #ifndef NO_SKID
147
        if (cert->extAuthKeyIdSet)
148
            ca = GetCA(cm, cert->extAuthKeyId);
149
        if (ca == NULL)
150
            ca = GetCAByName(cm, cert->issuerHash);
151
    #else /* NO_SKID */
152
        ca = GetCA(cm, cert->issuerHash);
153
    #endif /* NO SKID */
154
    }
155
    FreeDecodedCert(cert);
156
    WC_FREE_VAR_EX(cert, NULL, DYNAMIC_TYPE_DCERT);
157
158
    if (ca == NULL)
159
        return WOLFSSL_FAILURE;
160
161
#ifdef WOLFSSL_SIGNER_DER_CERT
162
    /* populate issuer with Signer DER */
163
    if (wolfSSL_X509_d2i_ex(issuer, ca->derCert->buffer,
164
            ca->derCert->length, cm->heap) == NULL)
165
        return WOLFSSL_FAILURE;
166
#else
167
    /* Create an empty certificate as CA doesn't have a certificate. */
168
    *issuer = (WOLFSSL_X509 *)XMALLOC(sizeof(WOLFSSL_X509), 0,
169
        DYNAMIC_TYPE_OPENSSL);
170
    if (*issuer == NULL)
171
        return WOLFSSL_FAILURE;
172
173
    InitX509((*issuer), 1, NULL);
174
#endif
175
176
    return WOLFSSL_SUCCESS;
177
}
178
#endif /* SESSION_CERTS || WOLFSSL_SIGNER_DER_CERT */
179
180
WOLFSSL_X509_STORE_CTX* wolfSSL_X509_STORE_CTX_new(void)
181
{
182
    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_new");
183
    return wolfSSL_X509_STORE_CTX_new_ex(NULL);
184
}
185
186
int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx,
187
     WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509,
188
     WOLF_STACK_OF(WOLFSSL_X509)* sk)
189
{
190
    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_init");
191
192
    if (ctx != NULL) {
193
        ctx->store = store;
194
        #ifndef WOLFSSL_X509_STORE_CERTS
195
        ctx->current_cert = x509;
196
        #else
197
        if(x509 != NULL){
198
            ctx->current_cert = wolfSSL_X509_d2i_ex(NULL,
199
                    x509->derCert->buffer,
200
                    x509->derCert->length,
201
                    x509->heap);
202
            if(ctx->current_cert == NULL)
203
                return WOLFSSL_FAILURE;
204
        } else
205
            ctx->current_cert = NULL;
206
        #endif
207
208
        ctx->ctxIntermediates = sk;
209
#ifdef HAVE_CRL
210
        ctx->crls = NULL;
211
#endif
212
        if (ctx->chain != NULL) {
213
            wolfSSL_sk_X509_pop_free(ctx->chain, NULL);
214
            ctx->chain = NULL;
215
        }
216
#ifdef SESSION_CERTS
217
        ctx->sesChain = NULL;
218
#endif
219
        ctx->domain = NULL;
220
#ifdef HAVE_EX_DATA
221
        XMEMSET(&ctx->ex_data, 0, sizeof(ctx->ex_data));
222
#endif
223
        ctx->userCtx = NULL;
224
        ctx->verify_cb = NULL;
225
        ctx->error = 0;
226
        ctx->error_depth = 0;
227
        ctx->discardSessionCerts = 0;
228
229
        if (ctx->param == NULL) {
230
            ctx->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC(
231
                           sizeof(WOLFSSL_X509_VERIFY_PARAM),
232
                           ctx->heap, DYNAMIC_TYPE_OPENSSL);
233
            if (ctx->param == NULL){
234
                WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_init failed");
235
                return WOLFSSL_FAILURE;
236
            }
237
            XMEMSET(ctx->param, 0, sizeof(*ctx->param));
238
        }
239
240
        /* Copy check_time from store parameters if available */
241
        if (store != NULL && store->param != NULL) {
242
            if ((store->param->flags & WOLFSSL_USE_CHECK_TIME) != 0 &&
243
                store->param->check_time != 0) {
244
                ctx->param->check_time = store->param->check_time;
245
                ctx->param->flags |= WOLFSSL_USE_CHECK_TIME;
246
            }
247
            if ((store->param->flags & WOLFSSL_NO_CHECK_TIME) != 0) {
248
                ctx->param->flags |= WOLFSSL_NO_CHECK_TIME;
249
            }
250
        }
251
252
        return WOLFSSL_SUCCESS;
253
    }
254
    return WOLFSSL_FAILURE;
255
}
256
257
/* Its recommended to use a full free -> init cycle of all the objects
258
 * because wolfSSL_X509_STORE_CTX_init may modify the store too which doesn't
259
 * get reset here. */
260
void wolfSSL_X509_STORE_CTX_cleanup(WOLFSSL_X509_STORE_CTX* ctx)
261
{
262
    if (ctx != NULL) {
263
264
        XFREE(ctx->param, ctx->heap, DYNAMIC_TYPE_OPENSSL);
265
        ctx->param = NULL;
266
267
        wolfSSL_X509_STORE_CTX_init(ctx, NULL, NULL, NULL);
268
    }
269
}
270
271
272
#ifdef HAVE_CRL
273
/* Set the CRLs to use during certificate verification. The stack is not
274
 * copied. The caller keeps ownership and has to keep the stack valid as long
275
 * as it is set on the ctx. */
276
void wolfSSL_X509_STORE_CTX_set0_crls(WOLFSSL_X509_STORE_CTX *ctx,
277
                                      WOLF_STACK_OF(WOLFSSL_X509_CRL) *sk)
278
{
279
    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set0_crls");
280
    if (ctx != NULL) {
281
        ctx->crls = sk;
282
    }
283
}
284
#endif
285
286
void wolfSSL_X509_STORE_CTX_trusted_stack(WOLFSSL_X509_STORE_CTX *ctx,
287
                                          WOLF_STACK_OF(WOLFSSL_X509) *sk)
288
{
289
    if (ctx != NULL) {
290
        ctx->setTrustedSk = sk;
291
    }
292
}
293
294
295
/* Returns corresponding X509 error from internal ASN error <e> */
296
int GetX509Error(int e)
297
{
298
    switch (e) {
299
        case WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E):
300
            return WOLFSSL_X509_V_ERR_CERT_NOT_YET_VALID;
301
        case WC_NO_ERR_TRACE(ASN_AFTER_DATE_E):
302
            return WOLFSSL_X509_V_ERR_CERT_HAS_EXPIRED;
303
        case WC_NO_ERR_TRACE(ASN_NO_SIGNER_E):
304
            /* get issuer error if no CA found locally */
305
            return WOLFSSL_X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
306
        case WC_NO_ERR_TRACE(RPK_UNTRUSTED_E):
307
            /* RFC 7250 Raw Public Key not trusted out of band. Distinct from
308
             * the X.509 issuer-lookup error above so verify callbacks that
309
             * accept ASN_NO_SIGNER_E / UNABLE_TO_GET_ISSUER_CERT_LOCALLY do not
310
             * accidentally accept an unauthenticated RPK. */
311
            return WOLFSSL_X509_V_ERR_RPK_UNTRUSTED;
312
        case WC_NO_ERR_TRACE(ASN_SELF_SIGNED_E):
313
            return WOLFSSL_X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
314
        case WC_NO_ERR_TRACE(ASN_PATHLEN_INV_E):
315
        case WC_NO_ERR_TRACE(ASN_PATHLEN_SIZE_E):
316
            return WOLFSSL_X509_V_ERR_PATH_LENGTH_EXCEEDED;
317
        case WC_NO_ERR_TRACE(ASN_SIG_OID_E):
318
        case WC_NO_ERR_TRACE(ASN_SIG_CONFIRM_E):
319
        case WC_NO_ERR_TRACE(ASN_SIG_HASH_E):
320
        case WC_NO_ERR_TRACE(ASN_SIG_KEY_E):
321
            return WOLFSSL_X509_V_ERR_CERT_SIGNATURE_FAILURE;
322
        /* We can't disambiguate if its the before or after date that caused
323
         * the error. Assume expired. */
324
        case WC_NO_ERR_TRACE(CRL_CERT_DATE_ERR):
325
            return WOLFSSL_X509_V_ERR_CRL_HAS_EXPIRED;
326
        case WC_NO_ERR_TRACE(CRL_CERT_REVOKED):
327
            return WOLFSSL_X509_V_ERR_CERT_REVOKED;
328
        case WC_NO_ERR_TRACE(CRL_MISSING):
329
            return WOLFSSL_X509_V_ERR_UNABLE_TO_GET_CRL;
330
        /* <e> is an internal wolfSSL return code, not an X509_V_* code, so 1
331
         * here is WOLFSSL_SUCCESS - it does not collide with
332
         * WOLFSSL_X509_V_ERR_UNSPECIFIED, which shares the value but never
333
         * reaches this function. */
334
        case 0:
335
        case 1:
336
            return 0;
337
        default:
338
#ifdef HAVE_WOLFSSL_MSG_EX
339
            WOLFSSL_MSG_EX("Error not configured or implemented yet: %d", e);
340
#else
341
            WOLFSSL_MSG("Error not configured or implemented yet");
342
#endif
343
            return e;
344
    }
345
}
346
347
static void SetupStoreCtxError_ex(WOLFSSL_X509_STORE_CTX* ctx, int ret,
348
                                                                    int depth)
349
{
350
    int error = GetX509Error(ret);
351
352
    /* Do not overwrite a previously recorded error with success; preserve
353
     * the worst-seen error across the chain walk. */
354
    if (error == 0 && ctx->error != 0)
355
        return;
356
357
    wolfSSL_X509_STORE_CTX_set_error(ctx, error);
358
    wolfSSL_X509_STORE_CTX_set_error_depth(ctx, depth);
359
}
360
361
static void SetupStoreCtxError(WOLFSSL_X509_STORE_CTX* ctx, int ret)
362
{
363
    int depth = 0;
364
365
    /* Set error depth */
366
    if (ctx->chain)
367
        depth = (int)ctx->chain->num;
368
369
    SetupStoreCtxError_ex(ctx, ret, depth);
370
}
371
372
#ifndef NO_ASN_TIME
373
/* Post certificate validation date handling. This function is called after the
374
 * certificate has been verified by the certificate manager. It then checks if
375
 * X509 store parameters are set for date validation override.
376
 * @param ctx The certificate store context
377
 * @param ret The return value from the certificate manager verify
378
 * @return The return value for the certificate date validation after override
379
 */
380
static int X509StoreVerifyCertDate(WOLFSSL_X509_STORE_CTX* ctx, int ret)
381
{
382
    byte *afterDate  = ctx->current_cert->notAfter.data;
383
    byte *beforeDate = ctx->current_cert->notBefore.data;
384
385
    /* Only override existing date errors or WOLFSSL_SUCCESS. */
386
    if (ret == WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E) ||
387
            ret == WC_NO_ERR_TRACE(ASN_AFTER_DATE_E) ||
388
            ret == WC_NO_ERR_TRACE(WOLFSSL_SUCCESS)) {
389
#ifdef USE_WOLF_VALIDDATE
390
        WOLFSSL_X509_VERIFY_PARAM* param = NULL;
391
392
        /* If no external XVALIDATE_DATE was defined then use param for date
393
           validation overrides. */
394
        if (ctx->param != NULL) {
395
            param = ctx->param;
396
        }
397
        else if (ctx->store != NULL && ctx->store->param != NULL) {
398
            param = ctx->store->param;
399
        }
400
401
        if (param != NULL) {
402
            if ((param->flags & WOLFSSL_NO_CHECK_TIME) != 0) {
403
                WOLFSSL_MSG("Overriding date validation WOLFSSL_NO_CHECK_TIME");
404
                ret = WOLFSSL_SUCCESS;
405
            }
406
            else if ((param->flags & WOLFSSL_USE_CHECK_TIME) != 0 &&
407
                (param->check_time != 0)) {
408
                time_t checkTime = param->check_time;
409
                ret = WOLFSSL_SUCCESS; /* override date error and use custom set
410
                                        time for validating certificate dates */
411
                WOLFSSL_MSG("Override date validation, WOLFSSL_USE_CHECK_TIME");
412
                if (wc_ValidateDateWithTime(afterDate,
413
                    (byte)ctx->current_cert->notAfter.type, ASN_AFTER,
414
                    checkTime, ctx->current_cert->notAfter.length) < 1) {
415
                    ret = ASN_AFTER_DATE_E;
416
                }
417
                else if (wc_ValidateDateWithTime(beforeDate,
418
                    (byte)ctx->current_cert->notBefore.type, ASN_BEFORE,
419
                    checkTime, ctx->current_cert->notBefore.length) < 1) {
420
                    ret = ASN_BEFORE_DATE_E;
421
                }
422
            }
423
        #if defined(OPENSSL_ALL)
424
            else {
425
                WOLFSSL_MSG("Using system time for date validation");
426
                /* use system time for date validation */
427
                if (wc_ValidateDate(afterDate,
428
                        (byte)ctx->current_cert->notAfter.type, ASN_AFTER,
429
                        ctx->current_cert->notAfter.length) < 1) {
430
                    ret = ASN_AFTER_DATE_E;
431
                }
432
                else if (wc_ValidateDate(beforeDate,
433
                        (byte)ctx->current_cert->notBefore.type, ASN_BEFORE,
434
                        ctx->current_cert->notBefore.length) < 1) {
435
                    ret = ASN_BEFORE_DATE_E;
436
                }
437
            }
438
        #endif
439
        }
440
#else
441
        if (XVALIDATE_DATE(afterDate,
442
                (byte)ctx->current_cert->notAfter.type, ASN_AFTER,
443
                ctx->current_cert->notAfter.length) < 1) {
444
            ret = ASN_AFTER_DATE_E;
445
        }
446
        else if (XVALIDATE_DATE(beforeDate,
447
                (byte)ctx->current_cert->notBefore.type, ASN_BEFORE,
448
                ctx->current_cert->notBefore.length) < 1) {
449
            ret = ASN_BEFORE_DATE_E;
450
        }
451
#endif /* USE_WOLF_VALIDDATE */
452
    }
453
454
    return ret;
455
}
456
#endif /* NO_ASN_TIME */
457
458
#ifdef HAVE_CRL
459
/* Check ctx->current_cert against the CRLs set with
460
 * X509_STORE_CTX_set0_crls.
461
 * Returns WOLFSSL_SUCCESS if a CRL for the cert's issuer is in the stack and
462
 * the cert is not revoked. Returns CRL_MISSING if the stack has no CRL for
463
 * the issuer. Returns a negative error on revocation or CRL failure. */
464
static int X509StoreCheckCtxCrls(WOLFSSL_X509_STORE_CTX* ctx)
465
{
466
    int ret = WC_NO_ERR_TRACE(CRL_MISSING);
467
    int found = 0;
468
    int dateErr = 0;
469
    int i;
470
    int numCrls;
471
    WC_DECLARE_VAR(cert, DecodedCert, 1, 0);
472
473
    numCrls = wolfSSL_sk_X509_CRL_num(ctx->crls);
474
    if (numCrls <= 0)
475
        return ret;
476
477
    WC_ALLOC_VAR_EX(cert, DecodedCert, 1, ctx->heap, DYNAMIC_TYPE_DCERT,
478
        return MEMORY_E);
479
480
    InitDecodedCert(cert, ctx->current_cert->derCert->buffer,
481
        ctx->current_cert->derCert->length, ctx->heap);
482
    /* The cert signature is verified by the CertManager. Only the issuer and
483
     * serial info is needed here. */
484
    if (ParseCertRelative(cert, CERT_TYPE, NO_VERIFY, ctx->store->cm, NULL)
485
            == 0) {
486
        /* Check all CRLs in the stack. A revocation in any of them wins over
487
         * a CRL that does not list the cert, like in the CertManager. */
488
        for (i = 0; i < numCrls; i++) {
489
            WOLFSSL_X509_CRL* crl = wolfSSL_sk_X509_CRL_value(ctx->crls, i);
490
            if (crl == NULL)
491
                continue;
492
            /* Use the store's cm to verify the CRL. The caller-owned crl is
493
             * not modified. */
494
            ret = CheckCertCRLFromCm(ctx->store->cm, crl, cert);
495
            if (ret == 0)
496
                found = 1;
497
            else if (ret == WC_NO_ERR_TRACE(CRL_CERT_DATE_ERR))
498
                dateErr = 1; /* stale CRL, another CRL can still vouch */
499
            else if (ret != WC_NO_ERR_TRACE(CRL_MISSING))
500
                break;
501
        }
502
    }
503
    FreeDecodedCert(cert);
504
    WC_FREE_VAR_EX(cert, ctx->heap, DYNAMIC_TYPE_DCERT);
505
506
    if (ret == 0 || ret == WC_NO_ERR_TRACE(CRL_MISSING) ||
507
            ret == WC_NO_ERR_TRACE(CRL_CERT_DATE_ERR)) {
508
        if (found)
509
            ret = WOLFSSL_SUCCESS;
510
        else if (dateErr)
511
            ret = WC_NO_ERR_TRACE(CRL_CERT_DATE_ERR);
512
        else
513
            ret = WC_NO_ERR_TRACE(CRL_MISSING);
514
    }
515
    return ret;
516
}
517
#endif /* HAVE_CRL */
518
519
/* Get the verification callback that applies to this context, or NULL when
520
 * none is installed. A callback set with wolfSSL_X509_STORE_CTX_set_verify_cb
521
 * takes precedence over one set on the store, matching OpenSSL.
522
 *
523
 * The context callback is settable in every OPENSSL_EXTRA build, so the
524
 * pathLen and INVALID_CA overrides driven from here are now reachable there
525
 * too, not just under OPENSSL_ALL or WOLFSSL_QT. */
526
static WOLFSSL_X509_STORE_CTX_verify_cb X509StoreGetVerifyCb(
527
        WOLFSSL_X509_STORE_CTX* ctx)
528
{
529
    if (ctx == NULL)
530
        return NULL;
531
532
    if (ctx->verify_cb != NULL)
533
        return ctx->verify_cb;
534
535
#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
536
    if (ctx->store != NULL)
537
        return ctx->store->verify_cb;
538
#endif
539
540
    return NULL;
541
}
542
543
/* Verify ctx->current_cert against the store.
544
 *
545
 * <cbRejected> is an out-parameter, never NULL. It is set to 1 when the
546
 * application's per-context verify callback explicitly rejected a certificate
547
 * the verification itself accepted, and to 0 otherwise. The rejection is
548
 * reported out of band rather than as a return value so that it cannot be
549
 * confused with any of the internal error codes this function passes through.
550
 *
551
 * A caller must stop chain building when it is set: a veto must not be turned
552
 * into a retry with another issuer, and must not be cleared by the
553
 * partial-chain fallback in wolfSSL_X509_verify_cert(). */
554
static int X509StoreVerifyCert(WOLFSSL_X509_STORE_CTX* ctx, int* cbRejected)
555
{
556
    int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
557
    WOLFSSL_X509_STORE_CTX_verify_cb verifyCb;
558
    WOLFSSL_ENTER("X509StoreVerifyCert");
559
560
    *cbRejected = 0;
561
562
    verifyCb = X509StoreGetVerifyCb(ctx);
563
564
    if (ctx->current_cert != NULL && ctx->current_cert->derCert != NULL) {
565
        ret = wolfSSL_CertManagerVerifyBuffer(ctx->store->cm,
566
                    ctx->current_cert->derCert->buffer,
567
                    ctx->current_cert->derCert->length,
568
                    WOLFSSL_FILETYPE_ASN1);
569
    #ifndef NO_ASN_TIME
570
        /* update return value with any date validation overrides */
571
        ret = X509StoreVerifyCertDate(ctx, ret);
572
    #endif
573
#ifdef HAVE_CRL
574
        /* Consult the CRLs set with X509_STORE_CTX_set0_crls after the date
575
         * overrides. They can revoke a cert the CertManager accepted, also
576
         * one whose date error was overridden, and can satisfy a CRL
577
         * requirement the CertManager's own CRL store could not. */
578
        if (ctx->crls != NULL && ctx->store->cm->crlEnabled &&
579
                (ret == WOLFSSL_SUCCESS ||
580
                 ret == WC_NO_ERR_TRACE(CRL_MISSING))) {
581
            int crlRet = X509StoreCheckCtxCrls(ctx);
582
            if (crlRet == WOLFSSL_SUCCESS) {
583
                ret = WOLFSSL_SUCCESS;
584
            }
585
            else if (crlRet != WC_NO_ERR_TRACE(CRL_MISSING)) {
586
                ret = crlRet;
587
            }
588
        }
589
#endif
590
        SetupStoreCtxError(ctx, ret);
591
        if (verifyCb != NULL) {
592
            /* Snapshot the error so the rejection below can tell one the
593
             * callback recorded itself from one left over from an earlier
594
             * certificate in the chain - SetupStoreCtxError() preserves the
595
             * worst error seen so far, so ctx->error is not necessarily
596
             * WOLFSSL_X509_V_OK on entry even when this certificate
597
             * verified. */
598
            int preCbError = ctx->error;
599
600
            if (verifyCb(ret >= 0 ? 1 : 0, ctx) == 1) {
601
                ret = WOLFSSL_SUCCESS;
602
            }
603
            else if (ret >= 0 && ctx->verify_cb != NULL) {
604
                /* Returning 0 must reject a chain the cert manager accepted.
605
                 * Only for the per-context callback - a store callback has
606
                 * never been able to reject here, and widening it is a
607
                 * separate behavior change. */
608
                if (ctx->error == preCbError) {
609
                    /* Keep an error the callback recorded itself; otherwise
610
                     * the rejection has no error to report. */
611
                    wolfSSL_X509_STORE_CTX_set_error(ctx,
612
                        WOLFSSL_X509_V_ERR_UNSPECIFIED);
613
                }
614
                *cbRejected = 1;
615
                ret = WOLFSSL_FAILURE;
616
            }
617
        }
618
    }
619
#if !defined(NO_ASN_TIME) && defined(OPENSSL_ALL)
620
    /* Skipped once the callback has rejected: the decision is already made,
621
     * and re-running the date check would consult the callback a second time,
622
     * which could overturn the rejection. */
623
    if (*cbRejected == 0 &&
624
        ret != WC_NO_ERR_TRACE(ASN_BEFORE_DATE_E) &&
625
        ret != WC_NO_ERR_TRACE(ASN_AFTER_DATE_E)) {
626
        /* With OpenSSL, we need to check the certificate's date
627
        * after certificate manager verification,
628
        * as it skips date validation when other errors are present.
629
        */
630
        ret = X509StoreVerifyCertDate(ctx, ret);
631
        SetupStoreCtxError(ctx, ret);
632
        ret = ret == WOLFSSL_SUCCESS ? 1 : 0;
633
        if (verifyCb != NULL) {
634
            if (verifyCb(ret, ctx) == 1) {
635
                ret = WOLFSSL_SUCCESS;
636
            }
637
            else {
638
                ret = -1;
639
            }
640
        }
641
    }
642
#endif
643
    return ret;
644
}
645
646
static int addAllButSelfSigned(WOLF_STACK_OF(WOLFSSL_X509)*to,
647
                               WOLF_STACK_OF(WOLFSSL_X509)*from, int *numAdded)
648
{
649
    int ret = WOLFSSL_SUCCESS;
650
    int i = 0;
651
    int cnt = 0;
652
    WOLFSSL_X509 *x = NULL;
653
654
    for (i = 0; i < wolfSSL_sk_X509_num(from); i++) {
655
        x = wolfSSL_sk_X509_value(from, i);
656
        if (wolfSSL_X509_NAME_cmp(&x->issuer, &x->subject) != 0) {
657
            if (wolfSSL_sk_X509_push(to, x) <= 0) {
658
                ret = WOLFSSL_FAILURE;
659
                goto exit;
660
            }
661
            cnt++;
662
        }
663
    }
664
665
exit:
666
    if (numAdded != NULL) {
667
        *numAdded = cnt;
668
    }
669
    return ret;
670
}
671
672
static int X509StoreRemoveCa(WOLFSSL_X509_STORE* store,
673
                                            WOLFSSL_X509* x509, int type) {
674
    int result = WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR);
675
    byte          hash[KEYID_SIZE];
676
677
    if (store != NULL && x509 != NULL && x509->derCert != NULL) {
678
        result = GetHashId(x509->subjKeyId, (int)x509->subjKeyIdSz,
679
                    hash, HashIdAlg(x509->sigOID));
680
        if (result) {
681
            result = WOLFSSL_FATAL_ERROR;
682
        } else {
683
            result = RemoveCA(store->cm, hash, type);
684
        }
685
    }
686
687
    return result;
688
}
689
690
static int X509StoreMoveCert(WOLFSSL_STACK *certs_stack,
691
                             WOLFSSL_STACK *dest_stack,
692
                             WOLFSSL_X509 *cert) {
693
    int i;
694
695
    if (certs_stack == NULL || dest_stack == NULL || cert == NULL)
696
        return WOLFSSL_FATAL_ERROR;
697
698
    for (i = 0; i < wolfSSL_sk_X509_num(certs_stack); i++) {
699
        if (wolfSSL_sk_X509_value(certs_stack, i) == cert) {
700
            wolfSSL_sk_X509_push(dest_stack,
701
                                 (WOLFSSL_X509*)wolfSSL_sk_pop_node(certs_stack, i));
702
            return WOLFSSL_SUCCESS;
703
        }
704
    }
705
706
    return WOLFSSL_FAILURE;
707
}
708
709
/* Push x509 onto the ctx chain with its own reference, like OpenSSL.
710
 * The chain owns a reference to each of its certs. */
711
static int X509StoreChainPush(WOLF_STACK_OF(WOLFSSL_X509)* chain,
712
                              WOLFSSL_X509* x509)
713
{
714
    int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
715
716
    if (x509 == NULL || wolfSSL_X509_up_ref(x509) != WOLFSSL_SUCCESS)
717
        return ret;
718
    ret = wolfSSL_sk_X509_push(chain, x509) > 0 ? WOLFSSL_SUCCESS :
719
        WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
720
    if (ret != WOLFSSL_SUCCESS)
721
        wolfSSL_X509_free(x509);
722
    return ret;
723
}
724
725
/* Returns 1 if `cert` (by pointer identity) is present in `stack`, else 0.
726
 * Used to keep a candidate that already failed verification off the reported
727
 * chain. */
728
static int X509StoreCertInStack(WOLF_STACK_OF(WOLFSSL_X509)* stack,
729
        WOLFSSL_X509* cert)
730
{
731
    int i;
732
    int num;
733
734
    if (stack == NULL || cert == NULL)
735
        return 0;
736
737
    /* Index by logical position like the other helpers in this file rather
738
     * than walking raw nodes. */
739
    num = wolfSSL_sk_X509_num(stack);
740
    for (i = 0; i < num; i++) {
741
        if (wolfSSL_sk_X509_value(stack, i) == cert)
742
            return 1;
743
    }
744
745
    return 0;
746
}
747
748
/* Current certificate failed, but it is possible there is an
749
 * alternative cert with the same subject key which will work.
750
 * Retry until all possible candidate certs are exhausted. */
751
static int X509VerifyCertSetupRetry(WOLFSSL_X509_STORE_CTX* ctx,
752
    WOLF_STACK_OF(WOLFSSL_X509)* certs, WOLF_STACK_OF(WOLFSSL_X509)* failed,
753
    int* depth, int origDepth) {
754
    int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
755
756
    WOLFSSL_MSG("X509_verify_cert current cert failed, "
757
                "retrying with other certs.");
758
    ret = X509StoreRemoveCa(ctx->store, ctx->current_cert,
759
                            WOLFSSL_TEMP_CA);
760
    X509StoreMoveCert(certs, failed, ctx->current_cert);
761
    ctx->current_cert = wolfSSL_sk_X509_pop(ctx->chain);
762
    /* Release the chain's reference. The cert stays valid through its
763
     * original owner. */
764
    wolfSSL_X509_free(ctx->current_cert);
765
    if (*depth < origDepth)
766
        *depth += 1;
767
768
    return ret;
769
}
770
771
/* Returns 1 if cur and x509 have identical DER encodings, 0 otherwise. */
772
static int X509DerEquals(WOLFSSL_X509* cur, WOLFSSL_X509* x509)
773
{
774
    if (cur == NULL || cur->derCert == NULL ||
775
        x509 == NULL || x509->derCert == NULL) {
776
        return 0;
777
    }
778
    if (cur->derCert->length != x509->derCert->length)
779
        return 0;
780
    return XMEMCMP(cur->derCert->buffer, x509->derCert->buffer,
781
                   x509->derCert->length) == 0;
782
}
783
784
/* Returns 1 if x509's DER matches an entry in either origTrustedSk (an
785
 * immutable snapshot of the caller's trusted set - store->certs or the
786
 * set0_trusted_stack override - captured before any intermediates were
787
 * injected for this verification call) or in store->trusted.  Returns 0
788
 * otherwise.  Used by the X509_V_FLAG_PARTIAL_CHAIN fallback to confirm that
789
 * a chain actually terminates at a caller-trusted certificate.
790
 * NOTE: origTrustedSk is a private snapshot, but store->trusted is read live
791
 * and unlocked here (as it is at the terminal issuer lookup); this mitigation
792
 * is deliberately asymmetric, so a single X509_STORE must not be shared across
793
 * threads verifying concurrently. */
794
static int X509StoreCertIsTrusted(WOLFSSL_X509_STORE* store,
795
        WOLFSSL_X509* x509, WOLF_STACK_OF(WOLFSSL_X509)* origTrustedSk)
796
{
797
    int i;
798
    int n;
799
800
    if (x509 == NULL || x509->derCert == NULL)
801
        return 0;
802
803
    if (origTrustedSk != NULL) {
804
        n = wolfSSL_sk_X509_num(origTrustedSk);
805
        for (i = 0; i < n; i++) {
806
            if (X509DerEquals(wolfSSL_sk_X509_value(origTrustedSk, i), x509))
807
                return 1;
808
        }
809
    }
810
811
    if (store != NULL && store->trusted != NULL) {
812
        n = wolfSSL_sk_X509_num(store->trusted);
813
        for (i = 0; i < n; i++) {
814
            if (X509DerEquals(wolfSSL_sk_X509_value(store->trusted, i), x509))
815
                return 1;
816
        }
817
    }
818
819
    return 0;
820
}
821
822
/* Enforce the BasicConstraints pathLenConstraint (RFC 5280 sec. 4.2.1.9 and
823
 * the path validation rules in sec. 6.1.4 (l)/(m)) over the certification path
824
 * assembled in ctx->chain.
825
 *
826
 * wolfSSL_X509_verify_cert() authenticates each certificate individually via
827
 * the CertManager, which parses every certificate as CERT_TYPE.  The issuer
828
 * pathLen check in ParseCertRelative() is gated on a non-CERT_TYPE certificate
829
 * type (it is reached on the TLS handshake path via CHAIN_CERT_TYPE), so the
830
 * OpenSSL-compatibility path never enforced it.  Re-create that check here over
831
 * the completed path so that a CA asserting pathlen:N cannot issue more than N
832
 * subordinate intermediate CAs.
833
 *
834
 * ctx->chain is ordered leaf first (index 0) up to the trust anchor (highest
835
 * index).  Walk from the trust anchor down toward the leaf, tracking the
836
 * remaining number of non-self-issued intermediate certificates permitted.
837
 * The budget is only enforced once some CA in the path actually asserts a
838
 * pathLenConstraint; an explicit "haveConstraint" flag tracks that, so every
839
 * value 0..WOLFSSL_MAX_PATH_LEN (the parser's hard cap on pathLenConstraint)
840
 * is a usable budget rather than overloading the cap as a "no constraint"
841
 * sentinel.  The leaf (index 0) issues nothing and is therefore not subject to
842
 * the constraint.
843
 *
844
 * Returns WOLFSSL_SUCCESS if the path satisfies every pathLenConstraint, or
845
 * WOLFSSL_FAILURE (with ctx->error set) on the first violation. */
846
static int X509StoreCheckPathLen(WOLFSSL_X509_STORE_CTX* ctx)
847
{
848
    int num;
849
    int i;
850
    word32 maxPathLen = 0;
851
    byte haveConstraint = 0;
852
    WOLFSSL_X509* anchor;
853
    WOLFSSL_X509_STORE_CTX_verify_cb verifyCb;
854
855
    if (ctx == NULL || ctx->chain == NULL)
856
        return WOLFSSL_SUCCESS;
857
858
    verifyCb = X509StoreGetVerifyCb(ctx);
859
860
    num = wolfSSL_sk_X509_num(ctx->chain);
861
    /* A pathLen violation requires at least one intermediate between the leaf
862
     * (index 0) and the trust anchor, i.e. a chain of three or more. */
863
    if (num < 3)
864
        return WOLFSSL_SUCCESS;
865
866
    /* The trust anchor (top of chain) is not part of the prospective
867
     * certification path (RFC 5280 sec. 6.1): it does not consume path-length
868
     * budget, and the loop below runs from num-2 down to 1 so the anchor is
869
     * never processed as an intermediate. A self-signed anchor that asserts its
870
     * own pathLenConstraint does still bound the path, matching
871
     * ParseCertRelative()'s trust-anchor handling, so seed the budget from
872
     * it. */
873
    anchor = wolfSSL_sk_X509_value(ctx->chain, num - 1);
874
    if (anchor != NULL && anchor->isCa && anchor->basicConstPlSet) {
875
        maxPathLen = (word32)anchor->pathLength;
876
        haveConstraint = 1;
877
    }
878
879
    for (i = num - 2; i >= 1; i--) {
880
        WOLFSSL_X509* cert = wolfSSL_sk_X509_value(ctx->chain, i);
881
        int selfIssued;
882
883
        if (cert == NULL)
884
            continue;
885
886
        selfIssued =
887
            (wolfSSL_X509_NAME_cmp(&cert->issuer, &cert->subject) == 0);
888
889
        /* RFC 5280 sec. 6.1.4 (l): a non-self-issued *CA* certificate consumes
890
         * one unit of the issuer's remaining path length budget. Gate on isCa
891
         * to match ParseCertRelative() (wolfcrypt/src/asn.c) and the (m) step
892
         * below, so a non-CA intermediate tolerated via verify_cb does not
893
         * trigger a false PATH_LENGTH_EXCEEDED. Only meaningful once a CA above
894
         * has asserted a constraint (haveConstraint). */
895
        if (!selfIssued && cert->isCa && haveConstraint) {
896
            if (maxPathLen == 0) {
897
                SetupStoreCtxError_ex(ctx,
898
                    WOLFSSL_X509_V_ERR_PATH_LENGTH_EXCEEDED, i);
899
                /* Allow an application verify callback to override, matching
900
                 * the INVALID_CA handling in wolfSSL_X509_verify_cert(). */
901
                if (verifyCb != NULL && verifyCb(0, ctx) == 1) {
902
                    /* Overridden: keep walking without decrementing (budget is
903
                     * already exhausted). */
904
                    continue;
905
                }
906
                return WOLFSSL_FAILURE;
907
            }
908
            maxPathLen--;
909
        }
910
911
        /* RFC 5280 sec. 6.1.4 (m): tighten the budget with this CA's own
912
         * pathLenConstraint, if present. The first constraint encountered seeds
913
         * the budget; subsequent ones only ever lower it. */
914
        if (cert->isCa && cert->basicConstPlSet &&
915
                (!haveConstraint || (word32)cert->pathLength < maxPathLen)) {
916
            maxPathLen = (word32)cert->pathLength;
917
            haveConstraint = 1;
918
        }
919
    }
920
921
    return WOLFSSL_SUCCESS;
922
}
923
924
/* Verifies certificate chain using WOLFSSL_X509_STORE_CTX
925
 * returns 1 on success or <= 0 on failure.
926
 */
927
int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
928
{
929
    int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
930
    int done = 0;
931
    int depth = 0;
932
    int origDepth = 0;
933
    int cbRejected = 0;
934
    WOLFSSL_X509 *issuer = NULL;
935
    WOLFSSL_X509 *orig = NULL;
936
    WOLF_STACK_OF(WOLFSSL_X509)* callerTrusted = NULL;
937
    WOLF_STACK_OF(WOLFSSL_X509)* certsToUse = NULL;
938
    WOLF_STACK_OF(WOLFSSL_X509)* failedCerts = NULL;
939
    WOLF_STACK_OF(WOLFSSL_X509)* origTrustedSk = NULL;
940
#ifndef WOLFSSL_X509_STORE_ALLOW_NON_CA_INTERMEDIATE
941
    WOLFSSL_X509_STORE_CTX_verify_cb verifyCb;
942
#endif
943
    WOLFSSL_ENTER("wolfSSL_X509_verify_cert");
944
945
    if (ctx == NULL || ctx->store == NULL || ctx->store->cm == NULL
946
         || ctx->current_cert == NULL || ctx->current_cert->derCert == NULL) {
947
        return WOLFSSL_FATAL_ERROR;
948
    }
949
950
#ifndef WOLFSSL_X509_STORE_ALLOW_NON_CA_INTERMEDIATE
951
    verifyCb = X509StoreGetVerifyCb(ctx);
952
#endif
953
954
    /* Chain building mutates the working stack: caller-supplied intermediates
955
     * are appended and X509VerifyCertSetupRetry moves failed certs out of it.
956
     * store->certs is shared by every connection using this store and
957
     * setTrustedSk is owned by the caller, so build a per-verification shallow
958
     * copy (certsToUse) and leave both untouched. This removes the write-side
959
     * corruption a concurrent verification used to inflict on those stacks, but
960
     * it does NOT make concurrent use of one X509_STORE safe: the dup is itself
961
     * an unlocked read, and store->trusted is still walked live (see the NOTE
962
     * below). A single store must not be shared across threads that verify
963
     * concurrently.
964
     *
965
     * The X509_V_FLAG_PARTIAL_CHAIN fallback needs the set of certs that were
966
     * caller-trusted before any intermediates were injected. Snapshot it from
967
     * certsToUse - the private copy, taken before addAllButSelfSigned() injects
968
     * intermediates - rather than walking the shared stack a second time, so
969
     * the two snapshots are provably identical. Both dups hold borrowed
970
     * references and are shallow-freed at exit. */
971
    callerTrusted = ctx->store->certs;
972
    if (ctx->setTrustedSk != NULL) {
973
        callerTrusted = ctx->setTrustedSk;
974
    }
975
976
    if (callerTrusted != NULL) {
977
        certsToUse = wolfSSL_shallow_sk_dup(callerTrusted);
978
        if (certsToUse != NULL)
979
            origTrustedSk = wolfSSL_shallow_sk_dup(certsToUse);
980
        if (origTrustedSk == NULL) {
981
            ret = WOLFSSL_FAILURE;
982
            goto exit;
983
        }
984
    }
985
    else {
986
        certsToUse = wolfSSL_sk_X509_new_null();
987
    }
988
    if (certsToUse == NULL) {
989
        ret = WOLFSSL_FAILURE;
990
        goto exit;
991
    }
992
    /* Add the intermediates provided on init to the list of untrusted
993
     * intermediates to be used. */
994
    ret = addAllButSelfSigned(certsToUse, ctx->ctxIntermediates, NULL);
995
    if (ret != WOLFSSL_SUCCESS) {
996
        goto exit;
997
    }
998
999
    if (ctx->chain != NULL) {
1000
        wolfSSL_sk_X509_pop_free(ctx->chain, NULL);
1001
    }
1002
    ctx->chain = wolfSSL_sk_X509_new_null();
1003
    if (ctx->chain == NULL) {
1004
        ret = WOLFSSL_FAILURE;
1005
        goto exit;
1006
    }
1007
1008
    failedCerts = wolfSSL_sk_X509_new_null();
1009
    if (!failedCerts) {
1010
        /* Fail closed: ret is still WOLFSSL_SUCCESS from the checks above, so
1011
         * an unset error here would make the function report a verified chain
1012
         * after an allocation failure. */
1013
        ret = WOLFSSL_FAILURE;
1014
        goto exit;
1015
    }
1016
1017
    if (ctx->depth > 0) {
1018
        depth = ctx->depth + 1;
1019
    }
1020
    else {
1021
        depth = WOLFSSL_X509_STORE_DEFAULT_MAX_DEPTH + 1;
1022
    }
1023
1024
    orig = ctx->current_cert;
1025
    origDepth = depth;
1026
    while(done == 0 && depth > 0) {
1027
        issuer = NULL;
1028
1029
        /* Try to find an untrusted issuer first */
1030
        ret = X509StoreGetIssuerEx(&issuer, certsToUse,
1031
                                               ctx->current_cert);
1032
        if (ret == WOLFSSL_SUCCESS) {
1033
            if (ctx->current_cert == issuer) {
1034
                X509StoreChainPush(ctx->chain, ctx->current_cert);
1035
                break;
1036
            }
1037
1038
            /* We found our issuer in the non-trusted cert list, add it
1039
             * to the CM and verify the current cert against it */
1040
        #ifndef WOLFSSL_X509_STORE_ALLOW_NON_CA_INTERMEDIATE
1041
            /* RFC 5280 4.2.1.9: reject non-CA issuer. verify_cb may
1042
             * suppress the INVALID_CA error to keep building the chain,
1043
             * but the leaf signature must still be verified against the
1044
             * issuer below - never skip X509StoreVerifyCert. */
1045
            if (!issuer->isCa) {
1046
                /* error depth is current depth + 1 */
1047
                SetupStoreCtxError_ex(ctx, WOLFSSL_X509_V_ERR_INVALID_CA,
1048
                                (ctx->chain) ? (int)(ctx->chain->num + 1) : 1);
1049
                if (verifyCb != NULL) {
1050
                    ret = verifyCb(0, ctx);
1051
                    if (ret != WOLFSSL_SUCCESS) {
1052
                        ret = WOLFSSL_FAILURE;
1053
                        goto exit;
1054
                    }
1055
                }
1056
                else {
1057
                    ret = WOLFSSL_FAILURE;
1058
                    goto exit;
1059
                }
1060
            }
1061
        #endif
1062
            /* NOTE: this loads the caller-supplied intermediate into the
1063
             * shared ctx->store->cm as a WOLFSSL_TEMP_CA, and the unload paths
1064
             * drop *all* WOLFSSL_TEMP_CA signers in that CertManager, not only
1065
             * the ones added here.  This copy removes the working-stack race,
1066
             * but two threads running X509_verify_cert() against the same
1067
             * X509_STORE still contend on store->cm.  Concurrent verification
1068
             * on a single shared store therefore remains unsupported; callers
1069
             * needing it must use a store per thread. */
1070
            ret = X509StoreAddCa(ctx->store, issuer, WOLFSSL_TEMP_CA);
1071
            if (ret != WOLFSSL_SUCCESS) {
1072
                X509VerifyCertSetupRetry(ctx, certsToUse, failedCerts,
1073
                    &depth, origDepth);
1074
                continue;
1075
            }
1076
            ret = X509StoreVerifyCert(ctx, &cbRejected);
1077
            if (cbRejected) {
1078
                /* The application vetoed this certificate.  Stop instead of
1079
                 * looking for another issuer: the decision is the
1080
                 * application's and retrying would only ask it again. */
1081
                ret = WOLFSSL_FAILURE;
1082
                goto exit;
1083
            }
1084
            if (ret != WOLFSSL_SUCCESS) {
1085
                X509VerifyCertSetupRetry(ctx, certsToUse, failedCerts,
1086
                    &depth, origDepth);
1087
                continue;
1088
            }
1089
            /* Add it to the current chain and look at the issuer cert next */
1090
            X509StoreChainPush(ctx->chain, ctx->current_cert);
1091
            ctx->current_cert = issuer;
1092
        }
1093
        else if (ret == WC_NO_ERR_TRACE(WOLFSSL_FAILURE)) {
1094
            /* Could not find in untrusted list, only place left is
1095
             * a trusted CA in the CM. Drop any caller-supplied untrusted
1096
             * intermediates that were temporarily loaded into the CertManager
1097
             * to authenticate child certificates, so the current certificate
1098
             * must verify against a genuinely trusted CA. They must not be
1099
             * allowed to anchor the path: otherwise a chain that never reaches
1100
             * a configured trust anchor (or whose intermediate signature is
1101
             * invalid) would be accepted. */
1102
            if (wolfSSL_CertManagerUnloadTempIntermediateCerts(ctx->store->cm)
1103
                    != WOLFSSL_SUCCESS) {
1104
                /* Could not guarantee the temporary intermediates were
1105
                 * dropped; fail closed rather than risk verifying the current
1106
                 * certificate against one. */
1107
                ret = WOLFSSL_FATAL_ERROR;
1108
                goto exit;
1109
            }
1110
            ret = X509StoreVerifyCert(ctx, &cbRejected);
1111
            if (cbRejected) {
1112
                /* An application veto is final.  The partial-chain fallback
1113
                 * below must not accept the chain here and clear ctx->error:
1114
                 * the certificate verified, the application rejected it. */
1115
                ret = WOLFSSL_FAILURE;
1116
                goto exit;
1117
            }
1118
            if (ret != WOLFSSL_SUCCESS) {
1119
                /* WOLFSSL_PARTIAL_CHAIN may only terminate the chain at a
1120
                 * certificate the caller actually trusts, so verify that
1121
                 * ctx->current_cert is itself in the original trust set. */
1122
                if (((ctx->flags & WOLFSSL_PARTIAL_CHAIN) ||
1123
                     (ctx->store->param != NULL &&
1124
                      (ctx->store->param->flags & WOLFSSL_PARTIAL_CHAIN))) &&
1125
                    X509StoreCertIsTrusted(ctx->store, ctx->current_cert,
1126
                        origTrustedSk)) {
1127
                    X509StoreChainPush(ctx->chain, ctx->current_cert);
1128
                    /* Clear error set by the failed X509StoreVerifyCert
1129
                     * attempt; the partial-chain fallback accepted the
1130
                     * chain at a caller-trusted certificate. */
1131
                    ctx->error = 0;
1132
                    ret = WOLFSSL_SUCCESS;
1133
                    /* The caller-trusted certificate terminates the path:
1134
                     * it is the anchor, so stop here rather than falling
1135
                     * through to the "finish building the chain" push below,
1136
                     * which would add ctx->current_cert to ctx->chain a
1137
                     * second time.  Mirrors the self-issued terminus break
1138
                     * above; the depth>0/done==0 success path accepts it. */
1139
                    break;
1140
                } else {
1141
                    X509VerifyCertSetupRetry(ctx, certsToUse, failedCerts,
1142
                        &depth, origDepth);
1143
                    continue;
1144
                }
1145
            }
1146
1147
            /* Cert verified, finish building the chain */
1148
            X509StoreChainPush(ctx->chain, ctx->current_cert);
1149
            issuer = NULL;
1150
    #ifdef WOLFSSL_SIGNER_DER_CERT
1151
            x509GetIssuerFromCM(&issuer, ctx->store->cm, ctx->current_cert);
1152
            if (issuer != NULL && ctx->owned != NULL) {
1153
                wolfSSL_sk_X509_push(ctx->owned, issuer);
1154
            }
1155
    #else
1156
            /* A candidate that already failed verification (moved to
1157
             * failedCerts by the retry path) must not terminate the reported
1158
             * chain.  setTrustedSk / store->trusted are searched by name+AKID,
1159
             * not by signature, and setTrustedSk is no longer pruned during
1160
             * chain building, so a same-subject cert that was tried and
1161
             * rejected can match here.  Skip those entries and keep scanning so
1162
             * a genuine anchor further down the stack is still found. */
1163
            if (ctx->setTrustedSk == NULL) {
1164
                X509StoreGetIssuerSkip(&issuer,
1165
                    ctx->store->trusted, ctx->current_cert, failedCerts);
1166
            }
1167
            else {
1168
                X509StoreGetIssuerSkip(&issuer,
1169
                    ctx->setTrustedSk, ctx->current_cert, failedCerts);
1170
            }
1171
    #endif
1172
            if (issuer != NULL) {
1173
                X509StoreChainPush(ctx->chain, issuer);
1174
            }
1175
1176
            done = 1;
1177
        }
1178
        else {
1179
            goto exit;
1180
        }
1181
1182
        depth--;
1183
    }
1184
1185
    /* Success requires the path to have reached a configured trust anchor
1186
     * (done == 1) or to have terminated at a caller-trusted self-signed
1187
     * certificate via the break above (done == 0 with depth still > 0).  A
1188
     * loop that instead ran out of its depth budget (depth <= 0) without
1189
     * completing must fail closed: ret may still be WOLFSSL_SUCCESS from the
1190
     * last link, but no trust anchor was reached. */
1191
    if (ret == WOLFSSL_SUCCESS && done == 0 && depth <= 0) {
1192
        SetupStoreCtxError_ex(ctx, WOLFSSL_X509_V_ERR_CERT_CHAIN_TOO_LONG,
1193
            wolfSSL_sk_X509_num(ctx->chain));
1194
        ret = WOLFSSL_FAILURE;
1195
    }
1196
1197
    /* RFC 5280 sec. 6.1.4: the per-certificate CertManager verification above
1198
     * does not enforce the issuer's BasicConstraints pathLenConstraint on this
1199
     * API path, so check it over the assembled path before reporting success. */
1200
    if (ret == WOLFSSL_SUCCESS) {
1201
        ret = X509StoreCheckPathLen(ctx);
1202
    }
1203
1204
exit:
1205
    /* failedCerts, certsToUse and origTrustedSk hold only borrowed references;
1206
     * free the stack nodes, not the certs.  All three are per-verification
1207
     * stacks (certsToUse/origTrustedSk are shallow dups of the caller's set),
1208
     * so none of the caller's own stacks are touched here. */
1209
    wolfSSL_sk_X509_free(failedCerts);
1210
1211
    /* Remove intermediates added to CM. Unconditional: a "did we add one" flag
1212
     * is cleared by the same failure paths that leave one resident. Clears all
1213
     * TEMP_CAs, so concurrent verifies on one store are unsupported. */
1214
    if (ctx != NULL) {
1215
        if (ctx->store != NULL) {
1216
            if (wolfSSL_CertManagerUnloadTempIntermediateCerts(ctx->store->cm)
1217
                    != WOLFSSL_SUCCESS) {
1218
                WOLFSSL_MSG("Failed to unload temporary intermediates");
1219
                /* Residue would anchor later verifications. */
1220
                if (ret == WOLFSSL_SUCCESS)
1221
                    ret = WOLFSSL_FAILURE;
1222
            }
1223
        }
1224
        if (orig != NULL) {
1225
            ctx->current_cert = orig;
1226
        }
1227
    }
1228
    wolfSSL_sk_X509_free(certsToUse);
1229
    wolfSSL_sk_X509_free(origTrustedSk);
1230
1231
    /* Enforce hostname / IP verification from X509_VERIFY_PARAM if set.
1232
     * Always check against the leaf (end-entity) certificate, captured in
1233
     * orig before the chain-building loop modified ctx->current_cert. */
1234
    if (ctx->param != NULL) {
1235
        if (ret == WOLFSSL_SUCCESS && ctx->param->hostName[0] != '\0') {
1236
            if (wolfSSL_X509_check_host(orig,
1237
                    ctx->param->hostName,
1238
                    XSTRLEN(ctx->param->hostName),
1239
                    ctx->param->hostFlags, NULL) != WOLFSSL_SUCCESS) {
1240
                ctx->error = WOLFSSL_X509_V_ERR_HOSTNAME_MISMATCH;
1241
                ctx->error_depth = 0;
1242
                ctx->current_cert = orig;
1243
                ret = WOLFSSL_FAILURE;
1244
            }
1245
        }
1246
        if (ret == WOLFSSL_SUCCESS && ctx->param->ipasc[0] != '\0') {
1247
            if (wolfSSL_X509_check_ip_asc(orig,
1248
                    ctx->param->ipasc,
1249
                    ctx->param->hostFlags) != WOLFSSL_SUCCESS) {
1250
                ctx->error = WOLFSSL_X509_V_ERR_IP_ADDRESS_MISMATCH;
1251
                ctx->error_depth = 0;
1252
                ctx->current_cert = orig;
1253
                ret = WOLFSSL_FAILURE;
1254
            }
1255
        }
1256
    }
1257
1258
    /* Fail closed on the way out: every failure has to be reportable through
1259
     * X509_STORE_CTX_get_error(), or the application is told the chain was
1260
     * fine while this function reports failure. Not all of them record one -
1261
     * a verify callback that rejects a chain the verification accepted, an
1262
     * allocation failure, or a chain-building error that never reached
1263
     * SetupStoreCtxError() all leave ctx->error at X509_V_OK. This is a
1264
     * deliberate blanket fallback for that whole class; it is applied only
1265
     * when nothing more specific was recorded, so an error the callback or
1266
     * the verification did set survives untouched. */
1267
    if (ret != WOLFSSL_SUCCESS && ctx->error == WOLFSSL_X509_V_OK) {
1268
        ctx->error = WOLFSSL_X509_V_ERR_UNSPECIFIED;
1269
    }
1270
1271
    return ret == WOLFSSL_SUCCESS ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE;
1272
}
1273
1274
#endif /* OPENSSL_EXTRA */
1275
1276
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
1277
WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get_current_cert(
1278
                                            WOLFSSL_X509_STORE_CTX* ctx)
1279
{
1280
    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_current_cert");
1281
    if (ctx)
1282
        return ctx->current_cert;
1283
    return NULL;
1284
}
1285
1286
/* get X509_STORE_CTX ex_data, max idx is MAX_EX_DATA */
1287
void* wolfSSL_X509_STORE_CTX_get_ex_data(WOLFSSL_X509_STORE_CTX* ctx, int idx)
1288
{
1289
    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_ex_data");
1290
#ifdef HAVE_EX_DATA
1291
    if (ctx != NULL) {
1292
        return wolfSSL_CRYPTO_get_ex_data(&ctx->ex_data, idx);
1293
    }
1294
#else
1295
    (void)ctx;
1296
    (void)idx;
1297
#endif
1298
    return NULL;
1299
}
1300
#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
1301
1302
1303
    int wolfSSL_X509_STORE_CTX_get_error(WOLFSSL_X509_STORE_CTX* ctx)
1304
0
    {
1305
0
        WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_error");
1306
0
        if (ctx != NULL)
1307
0
            return ctx->error;
1308
0
        return 0;
1309
0
    }
1310
1311
    int wolfSSL_X509_STORE_CTX_get_error_depth(WOLFSSL_X509_STORE_CTX* ctx)
1312
0
    {
1313
0
        WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_error_depth");
1314
0
        if (ctx)
1315
0
            return ctx->error_depth;
1316
0
        return WOLFSSL_FATAL_ERROR;
1317
0
    }
1318
1319
#ifdef OPENSSL_EXTRA
1320
    void wolfSSL_X509_STORE_CTX_set_verify_cb(WOLFSSL_X509_STORE_CTX *ctx,
1321
                                  WOLFSSL_X509_STORE_CTX_verify_cb verify_cb)
1322
    {
1323
        WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_verify_cb");
1324
        if(ctx == NULL)
1325
            return;
1326
        ctx->verify_cb = verify_cb;
1327
    }
1328
1329
/* Gets pointer to X509_STORE that was used to create context.
1330
 *
1331
 * Return valid pointer on success, NULL if ctx was NULL or not initialized
1332
 */
1333
WOLFSSL_X509_STORE* wolfSSL_X509_STORE_CTX_get0_store(
1334
        WOLFSSL_X509_STORE_CTX* ctx)
1335
{
1336
    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get0_store");
1337
1338
    if (ctx == NULL)
1339
        return NULL;
1340
1341
    return ctx->store;
1342
}
1343
1344
WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get0_cert(WOLFSSL_X509_STORE_CTX* ctx)
1345
{
1346
    if (ctx == NULL)
1347
        return NULL;
1348
1349
    return ctx->current_cert;
1350
}
1351
1352
void wolfSSL_X509_STORE_CTX_set_time(WOLFSSL_X509_STORE_CTX* ctx,
1353
                                    unsigned long flags,
1354
                                    time_t t)
1355
{
1356
    (void)flags;
1357
1358
    if (ctx == NULL || ctx->param == NULL)
1359
        return;
1360
1361
    ctx->param->check_time = t;
1362
    ctx->param->flags |= WOLFSSL_USE_CHECK_TIME;
1363
}
1364
1365
#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
1366
#ifndef NO_WOLFSSL_STUB
1367
int wolfSSL_X509_STORE_CTX_set_purpose(WOLFSSL_X509_STORE_CTX *ctx,
1368
                                       int purpose)
1369
{
1370
    (void)ctx;
1371
    (void)purpose;
1372
    WOLFSSL_STUB("wolfSSL_X509_STORE_CTX_set_purpose (not implemented)");
1373
    return 0;
1374
}
1375
#endif /* !NO_WOLFSSL_STUB */
1376
1377
#endif /* WOLFSSL_QT || OPENSSL_ALL */
1378
#endif /* OPENSSL_EXTRA */
1379
1380
#ifdef OPENSSL_EXTRA
1381
1382
void wolfSSL_X509_STORE_CTX_set_flags(WOLFSSL_X509_STORE_CTX *ctx,
1383
        unsigned long flags)
1384
{
1385
    if ((ctx != NULL) && (flags & WOLFSSL_PARTIAL_CHAIN)){
1386
        ctx->flags |= WOLFSSL_PARTIAL_CHAIN;
1387
    }
1388
}
1389
1390
/* set X509_STORE_CTX ex_data, max idx is MAX_EX_DATA. Return WOLFSSL_SUCCESS
1391
 * on success, WOLFSSL_FAILURE on error. */
1392
int wolfSSL_X509_STORE_CTX_set_ex_data(WOLFSSL_X509_STORE_CTX* ctx, int idx,
1393
                                       void *data)
1394
{
1395
    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_ex_data");
1396
#ifdef HAVE_EX_DATA
1397
    if (ctx != NULL)
1398
    {
1399
        return wolfSSL_CRYPTO_set_ex_data(&ctx->ex_data, idx, data);
1400
    }
1401
#else
1402
    (void)ctx;
1403
    (void)idx;
1404
    (void)data;
1405
#endif
1406
    return WOLFSSL_FAILURE;
1407
}
1408
1409
#ifdef HAVE_EX_DATA_CLEANUP_HOOKS
1410
/* set X509_STORE_CTX ex_data, max idx is MAX_EX_DATA. Return WOLFSSL_SUCCESS
1411
 * on success, WOLFSSL_FAILURE on error. */
1412
int wolfSSL_X509_STORE_CTX_set_ex_data_with_cleanup(
1413
    WOLFSSL_X509_STORE_CTX* ctx,
1414
    int idx,
1415
    void *data,
1416
    wolfSSL_ex_data_cleanup_routine_t cleanup_routine)
1417
{
1418
    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_ex_data_with_cleanup");
1419
    if (ctx != NULL)
1420
    {
1421
        return wolfSSL_CRYPTO_set_ex_data_with_cleanup(&ctx->ex_data, idx,
1422
                                                        data, cleanup_routine);
1423
    }
1424
    return WOLFSSL_FAILURE;
1425
}
1426
#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */
1427
1428
#if defined(WOLFSSL_APACHE_HTTPD) || defined(OPENSSL_EXTRA)
1429
void wolfSSL_X509_STORE_CTX_set_depth(WOLFSSL_X509_STORE_CTX* ctx, int depth)
1430
{
1431
    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_depth");
1432
    if (ctx)
1433
        ctx->depth = depth;
1434
}
1435
#endif
1436
1437
WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get0_current_issuer(
1438
        WOLFSSL_X509_STORE_CTX* ctx)
1439
{
1440
    WOLFSSL_STACK* node;
1441
    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get0_current_issuer");
1442
1443
    if (ctx == NULL)
1444
        return NULL;
1445
1446
    /* get0 only checks currently built chain */
1447
    if (ctx->chain != NULL) {
1448
        for (node = ctx->chain; node != NULL; node = node->next) {
1449
            if (wolfSSL_X509_check_issued(node->data.x509,
1450
                                          ctx->current_cert) ==
1451
                                                WOLFSSL_X509_V_OK) {
1452
                return node->data.x509;
1453
            }
1454
        }
1455
    }
1456
1457
    return NULL;
1458
}
1459
1460
/* Set an error stat in the X509 STORE CTX
1461
 *
1462
 */
1463
void wolfSSL_X509_STORE_CTX_set_error(WOLFSSL_X509_STORE_CTX* ctx, int er)
1464
{
1465
    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_error");
1466
1467
    if (ctx != NULL) {
1468
        ctx->error = er;
1469
    }
1470
}
1471
1472
/* Set the error depth in the X509 STORE CTX */
1473
void wolfSSL_X509_STORE_CTX_set_error_depth(WOLFSSL_X509_STORE_CTX* ctx,
1474
                                                                    int depth)
1475
{
1476
    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_error_depth");
1477
1478
    if (ctx != NULL) {
1479
        ctx->error_depth = depth;
1480
    }
1481
}
1482
1483
WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get_chain(WOLFSSL_X509_STORE_CTX* ctx)
1484
{
1485
    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_chain");
1486
1487
    if (ctx == NULL) {
1488
        return NULL;
1489
    }
1490
1491
#ifdef SESSION_CERTS
1492
    /* if chain is null but sesChain is available then populate stack */
1493
    if (ctx->chain == NULL && ctx->sesChain != NULL) {
1494
        int i;
1495
        int error = 0;
1496
        WOLFSSL_X509_CHAIN* c = ctx->sesChain;
1497
        WOLFSSL_STACK*     sk = wolfSSL_sk_new_node(ctx->heap);
1498
1499
        if (sk == NULL)
1500
            return NULL;
1501
1502
        for (i = 0; i < c->count; i++) {
1503
            WOLFSSL_X509* x509 = wolfSSL_get_chain_X509(c, i);
1504
1505
            if (x509 == NULL) {
1506
                WOLFSSL_MSG("Unable to get x509 from chain");
1507
                error = 1;
1508
                break;
1509
            }
1510
1511
            if (wolfSSL_sk_X509_push(sk, x509) <= 0) {
1512
                WOLFSSL_MSG("Unable to load x509 into stack");
1513
                wolfSSL_X509_free(x509);
1514
                x509 = NULL;
1515
                error = 1;
1516
                break;
1517
            }
1518
        }
1519
1520
#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
1521
    defined(OPENSSL_EXTRA)
1522
        /* add CA used to verify top of chain to the list */
1523
        if (!error && c->count > 0) {
1524
            WOLFSSL_X509* x509 = wolfSSL_get_chain_X509(c, c->count - 1);
1525
            WOLFSSL_X509* issuer = NULL;
1526
            if (x509 != NULL) {
1527
                if (wolfSSL_X509_STORE_CTX_get1_issuer(&issuer, ctx, x509)
1528
                        == WOLFSSL_SUCCESS) {
1529
                    /* check that the certificate being looked up is not self
1530
                     * signed and that a issuer was found */
1531
                    if (issuer != NULL && wolfSSL_X509_NAME_cmp(&x509->issuer,
1532
                                &x509->subject) != 0) {
1533
                        if (wolfSSL_sk_X509_push(sk, issuer) <= 0) {
1534
                            WOLFSSL_MSG("Unable to load CA x509 into stack");
1535
                            error = 1;
1536
                            wolfSSL_X509_free(issuer);
1537
                            issuer = NULL;
1538
                        }
1539
                    }
1540
                    else {
1541
                        WOLFSSL_MSG("Certificate is self signed");
1542
                        wolfSSL_X509_free(issuer);
1543
                        issuer = NULL;
1544
                    }
1545
                }
1546
                else {
1547
                    WOLFSSL_MSG("Could not find CA for certificate");
1548
                }
1549
            }
1550
            wolfSSL_X509_free(x509);
1551
            x509 = NULL;
1552
        }
1553
#endif
1554
        if (error) {
1555
            wolfSSL_sk_X509_pop_free(sk, NULL);
1556
            return NULL;
1557
        }
1558
        ctx->chain = sk;
1559
    }
1560
#endif /* SESSION_CERTS */
1561
1562
    return ctx->chain;
1563
}
1564
1565
/* like X509_STORE_CTX_get_chain(), but return a copy with data reference
1566
   counts increased */
1567
WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get1_chain(WOLFSSL_X509_STORE_CTX* ctx)
1568
{
1569
    WOLFSSL_STACK* ref;
1570
1571
    if (ctx == NULL) {
1572
        return NULL;
1573
    }
1574
1575
    /* get chain in ctx */
1576
    ref = wolfSSL_X509_STORE_CTX_get_chain(ctx);
1577
    if (ref == NULL) {
1578
        return ref;
1579
    }
1580
1581
    /* create duplicate of ctx chain */
1582
    return wolfSSL_sk_dup(ref);
1583
}
1584
1585
#ifndef NO_WOLFSSL_STUB
1586
WOLFSSL_X509_STORE_CTX *wolfSSL_X509_STORE_CTX_get0_parent_ctx(
1587
                                                   WOLFSSL_X509_STORE_CTX *ctx)
1588
{
1589
    (void)ctx;
1590
    WOLFSSL_STUB("wolfSSL_X509_STORE_CTX_get0_parent_ctx");
1591
    return NULL;
1592
}
1593
1594
int wolfSSL_X509_STORE_get_by_subject(WOLFSSL_X509_STORE_CTX* ctx, int idx,
1595
                            WOLFSSL_X509_NAME* name, WOLFSSL_X509_OBJECT* obj)
1596
{
1597
    (void)ctx;
1598
    (void)idx;
1599
    (void)name;
1600
    (void)obj;
1601
    WOLFSSL_STUB("X509_STORE_get_by_subject");
1602
    return 0;
1603
}
1604
#endif
1605
1606
WOLFSSL_X509_VERIFY_PARAM *wolfSSL_X509_STORE_CTX_get0_param(
1607
        WOLFSSL_X509_STORE_CTX *ctx)
1608
{
1609
    if (ctx == NULL)
1610
        return NULL;
1611
1612
    return ctx->param;
1613
}
1614
1615
#endif /* OPENSSL_EXTRA */
1616
1617
#if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM)
1618
#if defined(WOLFSSL_SIGNER_DER_CERT)
1619
WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs(
1620
    WOLFSSL_X509_STORE_CTX* ctx, WOLFSSL_X509_NAME* name)
1621
{
1622
    WOLF_STACK_OF(WOLFSSL_X509)* ret = NULL;
1623
    int err = 0;
1624
    WOLFSSL_X509_STORE* store = NULL;
1625
    WOLFSSL_STACK* sk = NULL;
1626
    WOLFSSL_STACK* certToFilter = NULL;
1627
    WOLFSSL_X509_NAME* certToFilterName = NULL;
1628
    WOLF_STACK_OF(WOLFSSL_X509)* filteredCerts = NULL;
1629
    WOLFSSL_X509* filteredCert = NULL;
1630
1631
    WOLFSSL_ENTER("wolfSSL_X509_STORE_get1_certs");
1632
1633
    if (name == NULL) {
1634
        err = 1;
1635
    }
1636
1637
    if (err == 0) {
1638
        store = wolfSSL_X509_STORE_CTX_get0_store(ctx);
1639
        if (store == NULL) {
1640
            err = 1;
1641
        }
1642
    }
1643
1644
    if (err == 0) {
1645
        filteredCerts = wolfSSL_sk_X509_new_null();
1646
        if (filteredCerts == NULL) {
1647
            err = 1;
1648
        }
1649
    }
1650
1651
    if (err == 0) {
1652
        sk = wolfSSL_CertManagerGetCerts(store->cm);
1653
        if (sk == NULL) {
1654
            err = 1;
1655
        }
1656
    }
1657
1658
    if (err == 0) {
1659
        certToFilter = sk;
1660
        while (certToFilter != NULL) {
1661
            certToFilterName = wolfSSL_X509_get_subject_name(
1662
                                    certToFilter->data.x509);
1663
            if (certToFilterName != NULL) {
1664
                if (wolfSSL_X509_NAME_cmp(certToFilterName, name) == 0) {
1665
                    filteredCert = wolfSSL_X509_dup(certToFilter->data.x509);
1666
                    if (filteredCert == NULL ||
1667
                            wolfSSL_sk_X509_push(filteredCerts, filteredCert)
1668
                                <= 0) {
1669
                        err = 1;
1670
                        wolfSSL_X509_free(filteredCert);
1671
                        filteredCert = NULL;
1672
                        break;
1673
                    }
1674
                }
1675
            }
1676
            certToFilter = certToFilter->next;
1677
        }
1678
    }
1679
1680
    if (err == 1) {
1681
        if (filteredCerts != NULL) {
1682
            wolfSSL_sk_X509_pop_free(filteredCerts, NULL);
1683
        }
1684
        ret = NULL;
1685
    }
1686
    else {
1687
        ret = filteredCerts;
1688
    }
1689
1690
    if (sk != NULL) {
1691
        wolfSSL_sk_X509_pop_free(sk, NULL);
1692
    }
1693
1694
    return ret;
1695
}
1696
#endif /* WOLFSSL_SIGNER_DER_CERT */
1697
1698
#endif /* OPENSSL_EXTRA && !NO_FILESYSTEM */
1699
1700
#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
1701
    defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
1702
int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer,
1703
    WOLFSSL_X509_STORE_CTX *ctx, WOLFSSL_X509 *x)
1704
{
1705
    int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
1706
    WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get1_issuer");
1707
1708
    if (issuer == NULL || ctx == NULL || x == NULL)
1709
        return WOLFSSL_FATAL_ERROR;
1710
1711
    ret = X509StoreGetIssuerEx(issuer, ctx->store->certs, x);
1712
    if ((ret == WOLFSSL_SUCCESS) && (*issuer != NULL)) {
1713
        return wolfSSL_X509_up_ref(*issuer);
1714
    }
1715
1716
#ifdef WOLFSSL_SIGNER_DER_CERT
1717
    ret = x509GetIssuerFromCM(issuer, ctx->store->cm, x);
1718
#else
1719
    ret = X509StoreGetIssuerEx(issuer, ctx->store->trusted, x);
1720
    if ((ret == WOLFSSL_SUCCESS) && (*issuer != NULL)) {
1721
        return wolfSSL_X509_up_ref(*issuer);
1722
    }
1723
#endif
1724
1725
    return ret;
1726
}
1727
#endif /* WOLFSSL_NGINX || WOLFSSL_HAPROXY || OPENSSL_EXTRA || OPENSSL_ALL */
1728
1729
#ifdef OPENSSL_EXTRA
1730
1731
/* Like X509StoreGetIssuerEx, but candidates present in `skip` are passed over
1732
 * and the scan continues, so a rejected same-subject cert does not hide a
1733
 * genuine issuer further down the stack. */
1734
static int X509StoreGetIssuerSkip(WOLFSSL_X509 **issuer,
1735
                            WOLFSSL_STACK * certs, WOLFSSL_X509 *x,
1736
                            WOLF_STACK_OF(WOLFSSL_X509)* skip)
1737
{
1738
    int i;
1739
1740
    if (issuer == NULL || x == NULL)
1741
        return WOLFSSL_FATAL_ERROR;
1742
1743
    if (certs != NULL) {
1744
        for (i = 0; i < wolfSSL_sk_X509_num(certs); i++) {
1745
            WOLFSSL_X509* cand = wolfSSL_sk_X509_value(certs, i);
1746
1747
            if (X509StoreCertInStack(skip, cand))
1748
                continue;
1749
            if (wolfSSL_X509_check_issued(cand, x) == WOLFSSL_X509_V_OK) {
1750
                *issuer = cand;
1751
                return WOLFSSL_SUCCESS;
1752
            }
1753
        }
1754
    }
1755
1756
    return WOLFSSL_FAILURE;
1757
}
1758
1759
static int X509StoreGetIssuerEx(WOLFSSL_X509 **issuer,
1760
                            WOLFSSL_STACK * certs, WOLFSSL_X509 *x)
1761
{
1762
    return X509StoreGetIssuerSkip(issuer, certs, x, NULL);
1763
}
1764
1765
#endif
1766
1767
/******************************************************************************
1768
 * END OF X509_STORE_CTX APIs
1769
 *****************************************************************************/
1770
1771
/******************************************************************************
1772
 * START OF X509_STORE APIs
1773
 *****************************************************************************/
1774
1775
#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \
1776
    defined(WOLFSSL_WPAS_SMALL)
1777
WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void)
1778
{
1779
    int ret;
1780
    WOLFSSL_X509_STORE* store = NULL;
1781
    WOLFSSL_ENTER("wolfSSL_X509_STORE_new");
1782
1783
    if ((store = (WOLFSSL_X509_STORE*)XMALLOC(sizeof(WOLFSSL_X509_STORE), NULL,
1784
                                    DYNAMIC_TYPE_X509_STORE)) == NULL)
1785
        goto err_exit;
1786
1787
    XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE));
1788
    store->isDynamic = 1;
1789
1790
    wolfSSL_RefInit(&store->ref, &ret);
1791
#ifdef WOLFSSL_REFCNT_ERROR_RETURN
1792
    if (ret != 0)
1793
        goto err_exit;
1794
#else
1795
    (void)ret;
1796
#endif
1797
1798
    if ((store->cm = wolfSSL_CertManagerNew()) == NULL)
1799
        goto err_exit;
1800
1801
#ifdef OPENSSL_EXTRA
1802
    if ((store->certs = wolfSSL_sk_X509_new_null()) == NULL)
1803
        goto err_exit;
1804
1805
    if ((store->owned = wolfSSL_sk_X509_new_null()) == NULL)
1806
        goto err_exit;
1807
1808
    if ((store->trusted = wolfSSL_sk_X509_new_null()) == NULL)
1809
        goto err_exit;
1810
#endif
1811
1812
#ifdef HAVE_CRL
1813
    store->crl = store->cm->crl;
1814
#endif
1815
1816
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
1817
1818
    /* Link store's new Certificate Manager to self by default */
1819
    store->cm->x509_store_p = store;
1820
1821
    if ((store->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC(
1822
                           sizeof(WOLFSSL_X509_VERIFY_PARAM),
1823
                           NULL, DYNAMIC_TYPE_OPENSSL)) == NULL) {
1824
        goto err_exit;
1825
    }
1826
    XMEMSET(store->param, 0, sizeof(WOLFSSL_X509_VERIFY_PARAM));
1827
    if ((store->lookup.dirs = (WOLFSSL_BY_DIR*)XMALLOC(sizeof(WOLFSSL_BY_DIR),
1828
                           NULL, DYNAMIC_TYPE_OPENSSL)) == NULL) {
1829
        WOLFSSL_MSG("store->lookup.dir memory allocation error");
1830
        goto err_exit;
1831
    }
1832
    XMEMSET(store->lookup.dirs, 0, sizeof(WOLFSSL_BY_DIR));
1833
    if (wc_InitMutex(&store->lookup.dirs->lock) != 0) {
1834
            WOLFSSL_MSG("Bad mutex init");
1835
            goto err_exit;
1836
    }
1837
#endif
1838
1839
    return store;
1840
1841
err_exit:
1842
    if (store == NULL)
1843
        return NULL;
1844
1845
    wolfSSL_X509_STORE_free(store);
1846
1847
    return NULL;
1848
}
1849
1850
void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE* store)
1851
{
1852
    int doFree = 0;
1853
    if (store != NULL && store->isDynamic) {
1854
        int ret;
1855
        wolfSSL_RefDec(&store->ref, &doFree, &ret);
1856
    #ifdef WOLFSSL_REFCNT_ERROR_RETURN
1857
        if (ret != 0) {
1858
            WOLFSSL_MSG("Couldn't lock store mutex");
1859
        }
1860
    #else
1861
        (void)ret;
1862
    #endif
1863
1864
        if (doFree) {
1865
#ifdef HAVE_EX_DATA_CLEANUP_HOOKS
1866
            wolfSSL_CRYPTO_cleanup_ex_data(&store->ex_data);
1867
#endif
1868
            if (store->cm != NULL) {
1869
                /* The manager may point back at this store, and can outlive
1870
                 * it when something else holds a reference to it. Break the
1871
                 * link before the store goes away so nothing is left
1872
                 * pointing at freed memory. The back-pointer is only a field
1873
                 * of the manager in the builds that can set it. */
1874
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
1875
                if (store->cm->x509_store_p == store) {
1876
                    store->cm->x509_store_p = NULL;
1877
                }
1878
#endif
1879
                wolfSSL_CertManagerFree(store->cm);
1880
                store->cm = NULL;
1881
            }
1882
#if defined(OPENSSL_EXTRA)
1883
            if (store->certs != NULL) {
1884
                wolfSSL_sk_X509_pop_free(store->certs, NULL);
1885
                store->certs = NULL;
1886
            }
1887
            if (store->owned != NULL) {
1888
                wolfSSL_sk_X509_pop_free(store->owned, NULL);
1889
                store->owned = NULL;
1890
            }
1891
            if (store->trusted != NULL) {
1892
                wolfSSL_sk_X509_pop_free(store->trusted, NULL);
1893
                store->trusted = NULL;
1894
            }
1895
#endif
1896
#ifdef OPENSSL_ALL
1897
            if (store->objs != NULL) {
1898
                wolfSSL_sk_X509_OBJECT_pop_free(store->objs, NULL);
1899
            }
1900
#endif
1901
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
1902
            XFREE(store->param, NULL, DYNAMIC_TYPE_OPENSSL);
1903
            store->param = NULL;
1904
1905
            if (store->lookup.dirs != NULL) {
1906
#if defined(OPENSSL_ALL) && !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
1907
                if (store->lookup.dirs->dir_entry) {
1908
                    wolfSSL_sk_BY_DIR_entry_free(
1909
                        store->lookup.dirs->dir_entry);
1910
                }
1911
#endif
1912
                wc_FreeMutex(&store->lookup.dirs->lock);
1913
                XFREE(store->lookup.dirs, NULL, DYNAMIC_TYPE_OPENSSL);
1914
                store->lookup.dirs = NULL;
1915
            }
1916
#endif
1917
            wolfSSL_RefFree(&store->ref);
1918
            XFREE(store, NULL, DYNAMIC_TYPE_X509_STORE);
1919
        }
1920
    }
1921
}
1922
1923
/**
1924
 * Get ex_data in WOLFSSL_STORE at given index
1925
 * @param store a pointer to WOLFSSL_X509_STORE structure
1926
 * @param idx   Index of ex_data to get data from
1927
 * @return void pointer to ex_data on success or NULL on failure
1928
 */
1929
void* wolfSSL_X509_STORE_get_ex_data(WOLFSSL_X509_STORE* store, int idx)
1930
{
1931
    WOLFSSL_ENTER("wolfSSL_X509_STORE_get_ex_data");
1932
#ifdef HAVE_EX_DATA
1933
    if (store != NULL && idx < MAX_EX_DATA && idx >= 0) {
1934
        return wolfSSL_CRYPTO_get_ex_data(&store->ex_data, idx);
1935
    }
1936
#else
1937
    (void)store;
1938
    (void)idx;
1939
#endif
1940
    return NULL;
1941
}
1942
1943
/* Take a reference to a certificate store.
1944
 *
1945
 * Only a store allocated by wolfSSL_X509_STORE_new() is reference counted. A
1946
 * store that is part of another object - the one a context returns from
1947
 * wolfSSL_CTX_get_cert_store() when none has been set on it, for example -
1948
 * has no count to take, and its lifetime is that of the object holding it.
1949
 * Success is still reported for such a store, so unlike OpenSSL's
1950
 * X509_STORE_up_ref() a successful return does not by itself mean the caller
1951
 * now owns something that keeps the store alive. A caller that intends to
1952
 * outlive the object the store belongs to cannot rely on this call and must
1953
 * use a store of its own.
1954
 *
1955
 * @param [in, out] store  Certificate store.
1956
 * @return  1 on success, including for a store that has no reference count.
1957
 * @return  0 when store is NULL, or when the count could not be taken.
1958
 */
1959
int wolfSSL_X509_STORE_up_ref(WOLFSSL_X509_STORE* store)
1960
{
1961
    if (store == NULL) {
1962
        return WOLFSSL_FAILURE;
1963
    }
1964
1965
    /* A store that is part of another object, such as the one in a context,
1966
     * is not reference counted - its reference count was never initialized
1967
     * and its lifetime is that of the object holding it. Nothing to do, as
1968
     * in wolfSSL_X509_STORE_free(). */
1969
    if (store->isDynamic) {
1970
        int ret;
1971
        wolfSSL_RefInc(&store->ref, &ret);
1972
    #ifdef WOLFSSL_REFCNT_ERROR_RETURN
1973
        if (ret != 0) {
1974
            WOLFSSL_MSG("Failed to lock store mutex");
1975
            return WOLFSSL_FAILURE;
1976
        }
1977
    #else
1978
        (void)ret;
1979
    #endif
1980
    }
1981
1982
    return WOLFSSL_SUCCESS;
1983
}
1984
1985
/**
1986
 * Set ex_data for WOLFSSL_STORE
1987
 * @param store a pointer to WOLFSSL_X509_STORE structure
1988
 * @param idx   Index of ex data to set
1989
 * @param data  Data to set in ex data
1990
 * @return WOLFSSL_SUCCESS on success or WOLFSSL_FAILURE on failure
1991
 */
1992
int wolfSSL_X509_STORE_set_ex_data(WOLFSSL_X509_STORE* store, int idx,
1993
                                                                void *data)
1994
{
1995
    WOLFSSL_ENTER("wolfSSL_X509_STORE_set_ex_data");
1996
#ifdef HAVE_EX_DATA
1997
    if (store != NULL && idx < MAX_EX_DATA) {
1998
        return wolfSSL_CRYPTO_set_ex_data(&store->ex_data, idx, data);
1999
    }
2000
#else
2001
    (void)store;
2002
    (void)idx;
2003
    (void)data;
2004
#endif
2005
    return WOLFSSL_FAILURE;
2006
}
2007
2008
#ifdef HAVE_EX_DATA_CLEANUP_HOOKS
2009
/**
2010
 * Set ex_data for WOLFSSL_STORE
2011
 * @param store a pointer to WOLFSSL_X509_STORE structure
2012
 * @param idx   Index of ex data to set
2013
 * @param data  Data to set in ex data
2014
 * @return WOLFSSL_SUCCESS on success or WOLFSSL_FAILURE on failure
2015
 */
2016
int wolfSSL_X509_STORE_set_ex_data_with_cleanup(
2017
    WOLFSSL_X509_STORE* store,
2018
    int idx,
2019
    void *data,
2020
    wolfSSL_ex_data_cleanup_routine_t cleanup_routine)
2021
{
2022
    WOLFSSL_ENTER("wolfSSL_X509_STORE_set_ex_data_with_cleanup");
2023
    if (store != NULL && idx < MAX_EX_DATA) {
2024
        return wolfSSL_CRYPTO_set_ex_data_with_cleanup(&store->ex_data, idx,
2025
                                                       data, cleanup_routine);
2026
    }
2027
    return WOLFSSL_FAILURE;
2028
}
2029
2030
#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */
2031
2032
#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER || WOLFSSL_WPAS_SMALL */
2033
2034
#ifdef OPENSSL_EXTRA
2035
2036
#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
2037
void wolfSSL_X509_STORE_set_verify_cb(WOLFSSL_X509_STORE *st,
2038
        WOLFSSL_X509_STORE_CTX_verify_cb verify_cb)
2039
{
2040
    WOLFSSL_ENTER("wolfSSL_X509_STORE_set_verify_cb");
2041
    if (st != NULL) {
2042
        st->verify_cb = verify_cb;
2043
    }
2044
}
2045
2046
void wolfSSL_X509_STORE_set_get_crl(WOLFSSL_X509_STORE *st,
2047
        WOLFSSL_X509_STORE_CTX_get_crl_cb get_cb)
2048
{
2049
    WOLFSSL_ENTER("wolfSSL_X509_STORE_set_get_crl");
2050
    if (st != NULL) {
2051
        st->get_crl_cb = get_cb;
2052
    }
2053
}
2054
2055
#ifndef NO_WOLFSSL_STUB
2056
void wolfSSL_X509_STORE_set_check_crl(WOLFSSL_X509_STORE *st,
2057
        WOLFSSL_X509_STORE_CTX_check_crl_cb check_crl)
2058
{
2059
    (void)st;
2060
    (void)check_crl;
2061
    WOLFSSL_STUB("wolfSSL_X509_STORE_set_check_crl (not implemented)");
2062
}
2063
#endif
2064
#endif /* WOLFSSL_QT || OPENSSL_ALL */
2065
2066
WOLFSSL_X509_LOOKUP* wolfSSL_X509_STORE_add_lookup(WOLFSSL_X509_STORE* store,
2067
                                               WOLFSSL_X509_LOOKUP_METHOD* m)
2068
{
2069
    WOLFSSL_ENTER("wolfSSL_X509_STORE_add_lookup");
2070
    if (store == NULL || m == NULL)
2071
        return NULL;
2072
2073
    /* Make sure the lookup has a back reference to the store. */
2074
    store->lookup.store = store;
2075
    /* store a type to know which method wants to be used for */
2076
    store->lookup.type = m->type;
2077
    return &store->lookup;
2078
}
2079
2080
static int X509StoreAddCa(WOLFSSL_X509_STORE* store,
2081
                                          WOLFSSL_X509* x509, int type)
2082
{
2083
    int result = WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR);
2084
    DerBuffer* derCert = NULL;
2085
    int verify = VERIFY;
2086
2087
    WOLFSSL_ENTER("X509StoreAddCa");
2088
    if (store != NULL && x509 != NULL && x509->derCert != NULL) {
2089
        /* Check if NO_CHECK_TIME flag is set - if so, skip date validation */
2090
        if (store->param != NULL &&
2091
            (store->param->flags & WOLFSSL_NO_CHECK_TIME) != 0) {
2092
            verify = VERIFY_SKIP_DATE;
2093
        }
2094
        result = AllocDer(&derCert, x509->derCert->length,
2095
            x509->derCert->type, NULL);
2096
        if (result == 0) {
2097
            /* AddCA() frees the buffer. */
2098
            XMEMCPY(derCert->buffer,
2099
                            x509->derCert->buffer, x509->derCert->length);
2100
            result = AddCA(store->cm, &derCert, type, verify);
2101
        }
2102
    }
2103
2104
    return result;
2105
}
2106
2107
/* Push certificates from the store's X509 stacks (certs and trusted) into the
2108
 * CertManager, then free and NULL the stacks to signal that this store is now
2109
 * owned by an SSL_CTX.
2110
 *
2111
 * This is needed when an X509_STORE is attached to an SSL_CTX via
2112
 * SSL_CTX_set_cert_store: self-signed CAs are already in the CM (added by
2113
 * X509StoreAddCa during X509_STORE_add_cert), but non-self-signed intermediates
2114
 * are only in store->certs and must be explicitly added to the CM so that all
2115
 * verification paths (including CertManagerVerify) can find them. */
2116
WOLFSSL_LOCAL int X509StorePushCertsToCM(WOLFSSL_X509_STORE* store)
2117
{
2118
    int i;
2119
    int num;
2120
    int ret;
2121
    int anyFail = 0;
2122
    WOLFSSL_X509* x509;
2123
2124
    WOLFSSL_ENTER("X509StorePushCertsToCM");
2125
2126
    if (store == NULL || store->cm == NULL)
2127
        return WOLFSSL_SUCCESS;
2128
2129
    /* Push non-self-signed intermediates from store->certs into the CM. */
2130
    if (store->certs != NULL) {
2131
        num = wolfSSL_sk_X509_num(store->certs);
2132
        for (i = 0; i < num; i++) {
2133
            x509 = wolfSSL_sk_X509_value(store->certs, i);
2134
            if (x509 != NULL) {
2135
                ret = X509StoreAddCa(store, x509, WOLFSSL_USER_CA);
2136
                if (ret != WOLFSSL_SUCCESS) {
2137
                    WOLFSSL_MSG("X509StorePushCertsToCM: failed to add cert");
2138
                    anyFail = 1;
2139
                }
2140
            }
2141
        }
2142
        /* Free and NULL to mark store as CTX-owned. Future add_cert calls
2143
         * will go directly to the CertManager. */
2144
        wolfSSL_sk_X509_pop_free(store->certs, NULL);
2145
        store->certs = NULL;
2146
    }
2147
2148
    /* Push trusted certs too. Self-signed CAs are typically already in the CM
2149
     * (added during X509_STORE_add_cert), but AddCA handles duplicates. */
2150
    if (store->trusted != NULL) {
2151
        num = wolfSSL_sk_X509_num(store->trusted);
2152
        for (i = 0; i < num; i++) {
2153
            x509 = wolfSSL_sk_X509_value(store->trusted, i);
2154
            if (x509 != NULL) {
2155
                ret = X509StoreAddCa(store, x509, WOLFSSL_USER_CA);
2156
                if (ret != WOLFSSL_SUCCESS) {
2157
                    WOLFSSL_MSG("X509StorePushCertsToCM: failed to add "
2158
                                "trusted cert");
2159
                    anyFail = 1;
2160
                }
2161
            }
2162
        }
2163
        wolfSSL_sk_X509_pop_free(store->trusted, NULL);
2164
        store->trusted = NULL;
2165
    }
2166
2167
    if (anyFail) {
2168
        return WOLFSSL_FATAL_ERROR;
2169
    }
2170
    return WOLFSSL_SUCCESS;
2171
}
2172
2173
int wolfSSL_X509_STORE_add_cert(WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509)
2174
{
2175
    int result = WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR);
2176
2177
    WOLFSSL_ENTER("wolfSSL_X509_STORE_add_cert");
2178
    if (store != NULL && store->cm != NULL && x509 != NULL
2179
                                                && x509->derCert != NULL) {
2180
        /* Mimic the openssl behavior, must be self signed to be considered
2181
         * trusted, addCA() internals will do additional checks for
2182
         * CA=TRUE */
2183
        if (wolfSSL_X509_NAME_cmp(&x509->issuer, &x509->subject) == 0) {
2184
            result = X509StoreAddCa(store, x509, WOLFSSL_USER_CA);
2185
            if (result == WOLFSSL_SUCCESS && store->trusted != NULL) {
2186
                result = wolfSSL_X509_up_ref(x509);
2187
                if (result == WOLFSSL_SUCCESS) {
2188
                    result = wolfSSL_sk_X509_push(store->trusted, x509);
2189
                    if (result > 0) {
2190
                        result = WOLFSSL_SUCCESS;
2191
                    }
2192
                    else {
2193
                        result = WOLFSSL_FATAL_ERROR;
2194
                        wolfSSL_X509_free(x509);
2195
                        x509 = NULL;
2196
                    }
2197
                }
2198
            }
2199
        }
2200
        else {
2201
            if (store->certs != NULL) {
2202
                result = wolfSSL_X509_up_ref(x509);
2203
                if (result == WOLFSSL_SUCCESS) {
2204
                    result = wolfSSL_sk_X509_push(store->certs, x509);
2205
                    if (result > 0) {
2206
                        result = WOLFSSL_SUCCESS;
2207
                    }
2208
                    else {
2209
                        result = WOLFSSL_FATAL_ERROR;
2210
                        wolfSSL_X509_free(x509);
2211
                        x509 = NULL;
2212
                    }
2213
                }
2214
            }
2215
            else {
2216
                /* If store->certs is NULL, this is an X509_STORE managed by an
2217
                 * SSL_CTX, preserve behavior and always add as USER_CA */
2218
                result = X509StoreAddCa(
2219
                            store, x509, WOLFSSL_USER_CA);
2220
            }
2221
        }
2222
    }
2223
2224
    WOLFSSL_LEAVE("wolfSSL_X509_STORE_add_cert", result);
2225
2226
    if (result != WOLFSSL_SUCCESS) {
2227
        result = WOLFSSL_FATAL_ERROR;
2228
    }
2229
2230
    return result;
2231
}
2232
2233
int wolfSSL_X509_STORE_set_flags(WOLFSSL_X509_STORE* store, unsigned long flag)
2234
{
2235
    int ret = WOLFSSL_SUCCESS;
2236
2237
    WOLFSSL_ENTER("wolfSSL_X509_STORE_set_flags");
2238
2239
    if (store == NULL)
2240
        return WOLFSSL_FAILURE;
2241
2242
    if ((flag & WOLFSSL_CRL_CHECKALL) || (flag & WOLFSSL_CRL_CHECK)) {
2243
        ret = wolfSSL_CertManagerEnableCRL(store->cm, (int)flag);
2244
    }
2245
#if defined(OPENSSL_COMPATIBLE_DEFAULTS)
2246
    else if (flag == 0) {
2247
        ret = wolfSSL_CertManagerDisableCRL(store->cm);
2248
    }
2249
#endif
2250
    if (flag & WOLFSSL_PARTIAL_CHAIN) {
2251
        store->param->flags |= WOLFSSL_PARTIAL_CHAIN;
2252
    }
2253
    return ret;
2254
}
2255
2256
int X509StoreLoadCertBuffer(WOLFSSL_X509_STORE *str,
2257
                                        byte *buf, word32 bufLen, int type)
2258
{
2259
    int ret = WOLFSSL_SUCCESS;
2260
    WOLFSSL_X509 *x509 = NULL;
2261
2262
    if (str == NULL || buf == NULL) {
2263
        return WOLFSSL_FAILURE;
2264
    }
2265
2266
    /* OpenSSL X509_STORE_load_file fails on DER file, we will as well */
2267
    x509 = wolfSSL_X509_load_certificate_buffer(buf, bufLen, type);
2268
    if (x509 != NULL) {
2269
        ret = wolfSSL_X509_STORE_add_cert(str, x509);
2270
        if (ret != WOLFSSL_SUCCESS) {
2271
            WOLFSSL_MSG("Failed to load file");
2272
            ret = WOLFSSL_FAILURE;
2273
        }
2274
        if (ret == WOLFSSL_SUCCESS && str->owned != NULL) {
2275
            if (wolfSSL_sk_X509_push(str->owned, x509) <= 0) {
2276
                ret = WOLFSSL_FAILURE;
2277
            }
2278
            else {
2279
                x509 = NULL;
2280
            }
2281
        }
2282
        wolfSSL_X509_free(x509);
2283
        x509 = NULL;
2284
    }
2285
    else {
2286
        ret = WOLFSSL_FAILURE;
2287
    }
2288
2289
    return ret;
2290
}
2291
2292
#if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR)
2293
2294
static int X509StoreReadFile(const char *fname,
2295
                StaticBuffer *content, word32 *bytesRead, int *type)
2296
{
2297
    int ret = -1;
2298
    long sz = 0;
2299
#ifdef HAVE_CRL
2300
    const char* header = NULL;
2301
    const char* footer = NULL;
2302
#endif
2303
2304
    ret = wolfssl_read_file_static(fname, content, NULL, DYNAMIC_TYPE_FILE,
2305
        &sz);
2306
    if (ret == 0) {
2307
        *type = CERT_TYPE;
2308
        *bytesRead = (word32)sz;
2309
#ifdef HAVE_CRL
2310
        /* Look for CRL header and footer. */
2311
        if (wc_PemGetHeaderFooter(CRL_TYPE, &header, &footer) == 0 &&
2312
                (XSTRNSTR((char*)content->buffer, header, sz) !=
2313
                    NULL)) {
2314
            *type = CRL_TYPE;
2315
        }
2316
#endif
2317
    }
2318
2319
    return (ret == 0 ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE);
2320
}
2321
2322
static int X509StoreLoadFile(WOLFSSL_X509_STORE *str,
2323
                                        const char *fname)
2324
{
2325
    int ret = WOLFSSL_SUCCESS;
2326
    int type = 0;
2327
#ifndef WOLFSSL_SMALL_STACK
2328
    byte   stackBuffer[FILE_BUFFER_SIZE];
2329
#endif
2330
    StaticBuffer content;
2331
    word32 contentLen = 0;
2332
2333
#ifdef WOLFSSL_SMALL_STACK
2334
    static_buffer_init(&content);
2335
#else
2336
    static_buffer_init(&content, stackBuffer, FILE_BUFFER_SIZE);
2337
#endif
2338
2339
    WOLFSSL_MSG_EX("X509StoreLoadFile: Loading file: %s", fname);
2340
2341
    ret = X509StoreReadFile(fname, &content, &contentLen, &type);
2342
    if (ret != WOLFSSL_SUCCESS) {
2343
        WOLFSSL_MSG("Failed to load file");
2344
        ret = WOLFSSL_FAILURE;
2345
    }
2346
2347
    if ((ret == WOLFSSL_SUCCESS) && (type == CERT_TYPE)) {
2348
        ret = X509StoreLoadCertBuffer(str, content.buffer,
2349
                                        contentLen, WOLFSSL_FILETYPE_PEM);
2350
    }
2351
#ifdef HAVE_CRL
2352
    else if ((ret == WOLFSSL_SUCCESS) && (type == CRL_TYPE)) {
2353
        ret = BufferLoadCRL(str->cm->crl, content.buffer, contentLen,
2354
                                        WOLFSSL_FILETYPE_PEM, 0);
2355
    }
2356
#endif
2357
2358
    static_buffer_free(&content, NULL, DYNAMIC_TYPE_FILE);
2359
    return ret;
2360
}
2361
2362
/* Loads certificate(s) files in pem format into X509_STORE struct from either
2363
 * a file or directory.
2364
 * Returns WOLFSSL_SUCCESS on success or WOLFSSL_FAILURE if an error occurs.
2365
 */
2366
int wolfSSL_X509_STORE_load_locations(WOLFSSL_X509_STORE *str,
2367
                                            const char *file, const char *dir)
2368
{
2369
    WOLFSSL_CTX* ctx;
2370
    char *name = NULL;
2371
    int ret = WOLFSSL_SUCCESS;
2372
    WC_DECLARE_VAR(readCtx, ReadDirCtx, 1, 0);
2373
2374
    WOLFSSL_ENTER("wolfSSL_X509_STORE_load_locations");
2375
2376
    if (str == NULL || str->cm == NULL || (file == NULL  && dir == NULL))
2377
        return WOLFSSL_FAILURE;
2378
2379
    /* tmp ctx for setting our cert manager */
2380
    ctx = wolfSSL_CTX_new_ex(cm_pick_method(str->cm->heap), str->cm->heap);
2381
    if (ctx == NULL)
2382
        return WOLFSSL_FAILURE;
2383
2384
    wolfSSL_CertManagerFree(ctx->cm);
2385
    ctx->cm = str->cm;
2386
2387
#ifdef HAVE_CRL
2388
    if (str->cm->crl == NULL) {
2389
        /* Workaround to allocate the internals to load CRL's but don't enable
2390
         * CRL checking by default */
2391
        if (wolfSSL_CertManagerEnableCRL(str->cm, WOLFSSL_CRL_CHECK)
2392
                != WOLFSSL_SUCCESS ||
2393
                wolfSSL_CertManagerDisableCRL(str->cm) != WOLFSSL_SUCCESS) {
2394
            WOLFSSL_MSG("Enable CRL failed");
2395
            wolfSSL_CTX_free(ctx);
2396
            return WOLFSSL_FAILURE;
2397
        }
2398
    }
2399
#endif
2400
2401
    /* Load individual file */
2402
    if (file) {
2403
        ret = X509StoreLoadFile(str, file);
2404
        if (ret != WOLFSSL_SUCCESS) {
2405
            WOLFSSL_MSG("Failed to load file");
2406
            ret = WOLFSSL_FAILURE;
2407
        }
2408
    }
2409
2410
    /* Load files in dir */
2411
    if (dir && ret == WOLFSSL_SUCCESS) {
2412
        int successes = 0;
2413
2414
        #ifdef WOLFSSL_SMALL_STACK
2415
            readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), ctx->heap,
2416
                                                    DYNAMIC_TYPE_TMP_BUFFER);
2417
            if (readCtx == NULL) {
2418
                WOLFSSL_MSG("Memory error");
2419
                wolfSSL_CTX_free(ctx);
2420
                return WOLFSSL_FAILURE;
2421
            }
2422
        #endif
2423
2424
        /* try to load each regular file in dir */
2425
        ret = wc_ReadDirFirst(readCtx, dir, &name);
2426
        while (ret == 0 && name) {
2427
            WOLFSSL_MSG(name);
2428
2429
            ret = X509StoreLoadFile(str, name);
2430
            /* Not failing on load errors */
2431
            if (ret != WOLFSSL_SUCCESS)
2432
                WOLFSSL_MSG("Failed to load file in path, continuing");
2433
            else
2434
                successes++;
2435
2436
            ret = wc_ReadDirNext(readCtx, dir, &name);
2437
        }
2438
        wc_ReadDirClose(readCtx);
2439
2440
        /* Success if at least one file in dir was loaded */
2441
        if (successes > 0)
2442
            ret = WOLFSSL_SUCCESS;
2443
        else {
2444
            WOLFSSL_ERROR(ret);
2445
            ret = WOLFSSL_FAILURE;
2446
        }
2447
2448
            WC_FREE_VAR_EX(readCtx, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
2449
    }
2450
2451
    ctx->cm = NULL;
2452
    wolfSSL_CTX_free(ctx);
2453
2454
    return ret;
2455
}
2456
2457
#if defined(XGETENV) && !defined(NO_GETENV)
2458
int wolfSSL_X509_STORE_set_default_paths(WOLFSSL_X509_STORE *str)
2459
{
2460
    int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
2461
    char* certDir = NULL;
2462
    char* certFile = NULL;
2463
2464
    WOLFSSL_ENTER("wolfSSL_X509_STORE_set_default_paths");
2465
2466
    certFile = wc_strdup_ex(XGETENV("SSL_CERT_FILE"), DYNAMIC_TYPE_TMP_BUFFER);
2467
    certDir = wc_strdup_ex(XGETENV("SSL_CERT_DIR"), DYNAMIC_TYPE_TMP_BUFFER);
2468
2469
    ret = wolfSSL_X509_STORE_load_locations(str, certFile, certDir);
2470
2471
    XFREE(certFile, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2472
    XFREE(certDir, NULL, DYNAMIC_TYPE_TMP_BUFFER);
2473
    return ret;
2474
}
2475
#endif /* XGETENV && !NO_GETENV */
2476
2477
#endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */
2478
2479
int wolfSSL_X509_CA_num(WOLFSSL_X509_STORE* store)
2480
{
2481
    int cnt_ret = 0;
2482
    Signer **table;
2483
2484
    WOLFSSL_ENTER("wolfSSL_X509_CA_num");
2485
    if (store == NULL || store->cm == NULL){
2486
        WOLFSSL_MSG("invalid parameter");
2487
        return WOLFSSL_FAILURE;
2488
    }
2489
2490
    table = store->cm->caTable;
2491
    if (table || (store->certs != NULL)){
2492
        if (wc_LockMutex(&store->cm->caLock) == 0){
2493
            if (table) {
2494
                int i = 0;
2495
                for (i = 0; i < CA_TABLE_SIZE; i++) {
2496
                    Signer* signer = table[i];
2497
                    while (signer) {
2498
                        Signer* next = signer->next;
2499
                        cnt_ret++;
2500
                        signer = next;
2501
                    }
2502
                }
2503
            }
2504
2505
            if (store->certs != NULL) {
2506
                cnt_ret += wolfSSL_sk_X509_num(store->certs);
2507
            }
2508
            wc_UnLockMutex(&store->cm->caLock);
2509
        }
2510
    }
2511
2512
    return cnt_ret;
2513
}
2514
2515
/******************************************************************************
2516
* wolfSSL_X509_STORE_GetCerts - retrieve stack of X509 in a certificate
2517
*                               store ctx
2518
*
2519
* This API can be used in SSL verify callback function to view cert chain
2520
* See examples/client/client.c and myVerify() function in test.h
2521
*
2522
* RETURNS:
2523
* returns stack of X509 certs on success, otherwise returns a NULL.
2524
*/
2525
WOLFSSL_STACK* wolfSSL_X509_STORE_GetCerts(WOLFSSL_X509_STORE_CTX* s)
2526
{
2527
    int  certIdx = 0;
2528
    WOLFSSL_BUFFER_INFO* cert = NULL;
2529
    DecodedCert* dCert = NULL;
2530
    WOLFSSL_X509* x509 = NULL;
2531
    WOLFSSL_STACK* sk = NULL;
2532
    int found = 0;
2533
2534
    if (s == NULL) {
2535
        return NULL;
2536
    }
2537
2538
    sk = wolfSSL_sk_X509_new_null();
2539
2540
    if (sk == NULL) {
2541
        return NULL;
2542
    }
2543
2544
    for (certIdx = s->totalCerts - 1; certIdx >= 0; certIdx--) {
2545
        /* get certificate buffer */
2546
        cert = &s->certs[certIdx];
2547
2548
        dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL,
2549
                                                DYNAMIC_TYPE_DCERT);
2550
2551
        if (dCert == NULL) {
2552
            goto error;
2553
        }
2554
        XMEMSET(dCert, 0, sizeof(DecodedCert));
2555
2556
        InitDecodedCert(dCert, cert->buffer, cert->length, NULL);
2557
2558
        /* Parse Certificate */
2559
        if (ParseCert(dCert, CERT_TYPE, NO_VERIFY, NULL)){
2560
            goto error;
2561
        }
2562
        x509 = wolfSSL_X509_new();
2563
2564
        if (x509 == NULL) {
2565
            goto error;
2566
        }
2567
        InitX509(x509, 1, NULL);
2568
2569
        if (CopyDecodedToX509(x509, dCert) == 0) {
2570
2571
            if (wolfSSL_sk_X509_push(sk, x509) <= 0) {
2572
                WOLFSSL_MSG("Unable to load x509 into stack");
2573
                wolfSSL_X509_free(x509);
2574
                x509 = NULL;
2575
                goto error;
2576
            }
2577
        }
2578
        else {
2579
            wolfSSL_X509_free(x509);
2580
            x509 = NULL;
2581
            goto error;
2582
        }
2583
        found = 1;
2584
2585
        FreeDecodedCert(dCert);
2586
        XFREE(dCert, NULL, DYNAMIC_TYPE_DCERT);
2587
        dCert = NULL;
2588
    }
2589
2590
    if (!found) {
2591
        wolfSSL_sk_X509_pop_free(sk, NULL);
2592
        sk = NULL;
2593
    }
2594
    return sk;
2595
2596
error:
2597
    if (dCert) {
2598
        FreeDecodedCert(dCert);
2599
        XFREE(dCert, NULL, DYNAMIC_TYPE_DCERT);
2600
    }
2601
2602
    if (sk)
2603
        wolfSSL_sk_X509_pop_free(sk, NULL);
2604
2605
    return NULL;
2606
}
2607
#endif /* OPENSSL_EXTRA */
2608
2609
#ifdef OPENSSL_ALL
2610
WOLF_STACK_OF(WOLFSSL_X509_OBJECT)* wolfSSL_X509_STORE_get0_objects(
2611
    WOLFSSL_X509_STORE* store)
2612
{
2613
    WOLFSSL_STACK* ret = NULL;
2614
    WOLFSSL_STACK* cert_stack = NULL;
2615
#if ((defined(WOLFSSL_SIGNER_DER_CERT) && !defined(NO_FILESYSTEM)) || \
2616
     (defined(HAVE_CRL)))
2617
    WOLFSSL_X509_OBJECT* obj = NULL;
2618
#endif
2619
#if defined(WOLFSSL_SIGNER_DER_CERT) && !defined(NO_FILESYSTEM)
2620
    WOLFSSL_X509* x509 = NULL;
2621
    int i = 0;
2622
#endif
2623
    WOLFSSL_ENTER("wolfSSL_X509_STORE_get0_objects");
2624
2625
    if (store == NULL || store->cm == NULL) {
2626
        WOLFSSL_MSG("Missing or empty store");
2627
        return NULL;
2628
    }
2629
2630
    if (store->objs != NULL) {
2631
#if defined(WOLFSSL_SIGNER_DER_CERT) && !defined(NO_FILESYSTEM)
2632
        /* want to update objs stack by cm stack again before returning it*/
2633
        wolfSSL_sk_X509_OBJECT_pop_free(store->objs, NULL);
2634
        store->objs = NULL;
2635
#else
2636
        if (wolfSSL_sk_X509_OBJECT_num(store->objs) == 0) {
2637
            /* Let's try generating the stack again */
2638
            wolfSSL_sk_X509_OBJECT_pop_free(store->objs, NULL);
2639
            store->objs = NULL;
2640
        }
2641
        else
2642
            return store->objs;
2643
#endif
2644
    }
2645
2646
    if ((ret = wolfSSL_sk_X509_OBJECT_new()) == NULL) {
2647
        WOLFSSL_MSG("wolfSSL_sk_X509_OBJECT_new error");
2648
        goto err_cleanup;
2649
    }
2650
2651
#if defined(WOLFSSL_SIGNER_DER_CERT) && !defined(NO_FILESYSTEM)
2652
    cert_stack = wolfSSL_CertManagerGetCerts(store->cm);
2653
    if (cert_stack == NULL && wolfSSL_sk_X509_num(store->certs) > 0) {
2654
        cert_stack = wolfSSL_sk_X509_new_null();
2655
        if (cert_stack == NULL) {
2656
            WOLFSSL_MSG("wolfSSL_sk_X509_OBJECT_new error");
2657
            goto err_cleanup;
2658
        }
2659
    }
2660
    /* Reference borrowed certs so cert_stack owns every entry. */
2661
    for (i = 0; i < wolfSSL_sk_X509_num(store->certs); i++) {
2662
        x509 = wolfSSL_sk_X509_value(store->certs, i);
2663
        if (wolfSSL_X509_up_ref(x509) != WOLFSSL_SUCCESS) {
2664
            WOLFSSL_MSG("wolfSSL_X509_up_ref error");
2665
            goto err_cleanup;
2666
        }
2667
        if (wolfSSL_sk_X509_push(cert_stack, x509) <= 0) {
2668
            WOLFSSL_MSG("wolfSSL_sk_X509_push error");
2669
            wolfSSL_X509_free(x509);
2670
            goto err_cleanup;
2671
        }
2672
    }
2673
    for (i = 0; i < wolfSSL_sk_X509_num(cert_stack); i++) {
2674
        x509 = (WOLFSSL_X509 *)wolfSSL_sk_value(cert_stack, i);
2675
        obj  = wolfSSL_X509_OBJECT_new();
2676
        if (obj == NULL) {
2677
            WOLFSSL_MSG("wolfSSL_X509_OBJECT_new error");
2678
            goto err_cleanup;
2679
        }
2680
        /* Push first so cleanup frees the object if the up_ref fails. */
2681
        if (wolfSSL_sk_X509_OBJECT_push(ret, obj) <= 0) {
2682
            WOLFSSL_MSG("wolfSSL_sk_X509_OBJECT_push error");
2683
            wolfSSL_X509_OBJECT_free(obj);
2684
            goto err_cleanup;
2685
        }
2686
        /* Object owns a reference, so the list frees independently. */
2687
        if (wolfSSL_X509_up_ref(x509) != WOLFSSL_SUCCESS) {
2688
            WOLFSSL_MSG("wolfSSL_X509_up_ref error");
2689
            goto err_cleanup;
2690
        }
2691
        obj->type = WOLFSSL_X509_LU_X509;
2692
        obj->data.x509 = x509;
2693
    }
2694
#endif
2695
2696
#ifdef HAVE_CRL
2697
    if (store->cm->crl != NULL) {
2698
        int res;
2699
        obj = wolfSSL_X509_OBJECT_new();
2700
        if (obj == NULL) {
2701
            WOLFSSL_MSG("wolfSSL_X509_OBJECT_new error");
2702
            goto err_cleanup;
2703
        }
2704
        if (wolfSSL_sk_X509_OBJECT_push(ret, obj) <= 0) {
2705
            WOLFSSL_MSG("wolfSSL_sk_X509_OBJECT_push error");
2706
            wolfSSL_X509_OBJECT_free(obj);
2707
            goto err_cleanup;
2708
        }
2709
        /* Reference first, so the object only claims what it can free. */
2710
        wolfSSL_RefInc(&store->cm->crl->ref, &res);
2711
        if (res != 0) {
2712
            WOLFSSL_MSG("Failed to lock crl mutex");
2713
            goto err_cleanup;
2714
        }
2715
        obj->type = WOLFSSL_X509_LU_CRL;
2716
        obj->data.crl = store->cm->crl;
2717
    }
2718
#endif
2719
2720
    if (cert_stack != NULL)
2721
        wolfSSL_sk_X509_pop_free(cert_stack, NULL);
2722
    store->objs = ret;
2723
    return ret;
2724
err_cleanup:
2725
    /* Objects own their contents, so one pop_free releases everything. */
2726
    if (ret != NULL)
2727
        wolfSSL_sk_X509_OBJECT_pop_free(ret, NULL);
2728
    if (cert_stack != NULL)
2729
        wolfSSL_sk_X509_pop_free(cert_stack, NULL);
2730
    return NULL;
2731
}
2732
#endif /* OPENSSL_ALL */
2733
2734
#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \
2735
    defined(WOLFSSL_WPAS_SMALL)
2736
WOLFSSL_X509_VERIFY_PARAM *wolfSSL_X509_STORE_get0_param(
2737
        const WOLFSSL_X509_STORE *ctx)
2738
{
2739
    if (ctx == NULL)
2740
        return NULL;
2741
    return ctx->param;
2742
}
2743
2744
#ifdef OPENSSL_EXTRA
2745
int wolfSSL_X509_STORE_set1_param(WOLFSSL_X509_STORE *ctx,
2746
        WOLFSSL_X509_VERIFY_PARAM *param)
2747
{
2748
    if (ctx == NULL)
2749
        return WOLFSSL_FAILURE;
2750
    return wolfSSL_X509_VERIFY_PARAM_set1(ctx->param, param);
2751
}
2752
#endif
2753
#endif
2754
2755
/******************************************************************************
2756
 * END OF X509_STORE APIs
2757
 *****************************************************************************/
2758
2759
#endif /* NO_CERTS */
2760
2761
#endif /* !WOLFCRYPT_ONLY */
2762
2763
#endif /* !WOLFSSL_X509_STORE_INCLUDED */