Coverage Report

Created: 2026-09-20 06:33

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