Coverage Report

Created: 2026-08-12 07:05

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