Coverage Report

Created: 2026-07-22 06:50

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