Coverage Report

Created: 2026-09-27 06:31

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