Coverage Report

Created: 2026-11-12 06:59

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