Coverage Report

Created: 2026-03-09 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/x509/x509_lu.c
Line
Count
Source
1
/*
2
 * Copyright 1995-2025 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
#include <stdio.h>
11
#include "internal/cryptlib.h"
12
#include "internal/hashtable.h"
13
#include "internal/hashfunc.h"
14
#include "internal/refcount.h"
15
#include <openssl/x509.h>
16
#include "crypto/x509.h"
17
#include <openssl/x509v3.h>
18
#include "x509_local.h"
19
20
0
#define X509_OBJS_HT_BUCKETS 8
21
22
X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method)
23
0
{
24
0
    X509_LOOKUP *ret = OPENSSL_zalloc(sizeof(*ret));
25
26
0
    if (ret == NULL)
27
0
        return NULL;
28
29
0
    ret->method = method;
30
0
    if (method->new_item != NULL && method->new_item(ret) == 0) {
31
0
        OPENSSL_free(ret);
32
0
        return NULL;
33
0
    }
34
0
    return ret;
35
0
}
36
37
void X509_LOOKUP_free(X509_LOOKUP *ctx)
38
0
{
39
0
    if (ctx == NULL)
40
0
        return;
41
0
    if ((ctx->method != NULL) && (ctx->method->free != NULL))
42
0
        (*ctx->method->free)(ctx);
43
0
    OPENSSL_free(ctx);
44
0
}
45
46
int X509_STORE_lock(X509_STORE *xs)
47
0
{
48
0
    return CRYPTO_THREAD_write_lock(xs->lock);
49
0
}
50
51
int ossl_x509_store_read_lock(X509_STORE *xs)
52
0
{
53
0
    return CRYPTO_THREAD_read_lock(xs->lock);
54
0
}
55
56
int X509_STORE_unlock(X509_STORE *xs)
57
0
{
58
0
    return CRYPTO_THREAD_unlock(xs->lock);
59
0
}
60
61
int X509_LOOKUP_init(X509_LOOKUP *ctx)
62
0
{
63
0
    if (ctx->method == NULL)
64
0
        return 0;
65
0
    if (ctx->method->init != NULL)
66
0
        return ctx->method->init(ctx);
67
0
    else
68
0
        return 1;
69
0
}
70
71
int X509_LOOKUP_shutdown(X509_LOOKUP *ctx)
72
0
{
73
0
    if (ctx->method == NULL)
74
0
        return 0;
75
0
    if (ctx->method->shutdown != NULL)
76
0
        return ctx->method->shutdown(ctx);
77
0
    else
78
0
        return 1;
79
0
}
80
81
int X509_LOOKUP_ctrl_ex(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
82
    char **ret, OSSL_LIB_CTX *libctx, const char *propq)
83
0
{
84
0
    if (ctx->method == NULL)
85
0
        return -1;
86
0
    if (ctx->method->ctrl_ex != NULL)
87
0
        return ctx->method->ctrl_ex(ctx, cmd, argc, argl, ret, libctx, propq);
88
0
    if (ctx->method->ctrl != NULL)
89
0
        return ctx->method->ctrl(ctx, cmd, argc, argl, ret);
90
0
    return 1;
91
0
}
92
93
int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
94
    char **ret)
95
0
{
96
0
    return X509_LOOKUP_ctrl_ex(ctx, cmd, argc, argl, ret, NULL, NULL);
97
0
}
98
99
int X509_LOOKUP_by_subject_ex(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
100
    const X509_NAME *name, X509_OBJECT *ret,
101
    OSSL_LIB_CTX *libctx, const char *propq)
102
0
{
103
0
    if (ctx->skip
104
0
        || ctx->method == NULL
105
0
        || (ctx->method->get_by_subject == NULL
106
0
            && ctx->method->get_by_subject_ex == NULL))
107
0
        return 0;
108
0
    if (ctx->method->get_by_subject_ex != NULL)
109
0
        return ctx->method->get_by_subject_ex(ctx, type, name, ret, libctx,
110
0
            propq);
111
0
    else
112
0
        return ctx->method->get_by_subject(ctx, type, name, ret);
113
0
}
114
115
int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
116
    const X509_NAME *name, X509_OBJECT *ret)
117
0
{
118
0
    return X509_LOOKUP_by_subject_ex(ctx, type, name, ret, NULL, NULL);
119
0
}
120
121
int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
122
    const X509_NAME *name,
123
    const ASN1_INTEGER *serial,
124
    X509_OBJECT *ret)
125
0
{
126
0
    if ((ctx->method == NULL) || (ctx->method->get_by_issuer_serial == NULL))
127
0
        return 0;
128
0
    return ctx->method->get_by_issuer_serial(ctx, type, name, serial, ret);
129
0
}
130
131
int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
132
    const unsigned char *bytes, int len,
133
    X509_OBJECT *ret)
134
0
{
135
0
    if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL))
136
0
        return 0;
137
0
    return ctx->method->get_by_fingerprint(ctx, type, bytes, len, ret);
138
0
}
139
140
int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
141
    const char *str, int len, X509_OBJECT *ret)
142
0
{
143
0
    if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL))
144
0
        return 0;
145
0
    return ctx->method->get_by_alias(ctx, type, str, len, ret);
146
0
}
147
148
int X509_LOOKUP_set_method_data(X509_LOOKUP *ctx, void *data)
149
0
{
150
0
    ctx->method_data = data;
151
0
    return 1;
152
0
}
153
154
void *X509_LOOKUP_get_method_data(const X509_LOOKUP *ctx)
155
0
{
156
0
    return ctx->method_data;
157
0
}
158
159
X509_STORE *X509_LOOKUP_get_store(const X509_LOOKUP *ctx)
160
0
{
161
0
    return ctx->store_ctx;
162
0
}
163
164
static int x509_object_cmp(const X509_OBJECT *const *a,
165
    const X509_OBJECT *const *b)
166
0
{
167
0
    int ret;
168
169
0
    ret = ((*a)->type - (*b)->type);
170
0
    if (ret)
171
0
        return ret;
172
0
    switch ((*a)->type) {
173
0
    case X509_LU_X509:
174
0
        ret = X509_subject_name_cmp((*a)->data.x509, (*b)->data.x509);
175
0
        break;
176
0
    case X509_LU_CRL:
177
0
        ret = X509_CRL_cmp((*a)->data.crl, (*b)->data.crl);
178
0
        break;
179
0
    case X509_LU_NONE:
180
        /* abort(); */
181
0
        return 0;
182
0
    }
183
0
    return ret;
184
0
}
185
186
static void objs_ht_free(HT_VALUE *v)
187
0
{
188
0
    STACK_OF(X509_OBJECT) *objs = v->value;
189
190
0
    sk_X509_OBJECT_pop_free(objs, X509_OBJECT_free);
191
0
}
192
193
static uint64_t obj_ht_hash(HT_KEY *key)
194
0
{
195
0
    OBJS_KEY *k = (OBJS_KEY *)key;
196
197
0
    return ossl_fnv1a_hash(k->keyfields.xn_canon, k->keyfields.xn_canon_enclen);
198
0
}
199
200
X509_STORE *X509_STORE_new(void)
201
0
{
202
0
    X509_STORE *ret = OPENSSL_zalloc(sizeof(*ret));
203
0
    HT_CONFIG htconf = {
204
0
        .ht_free_fn = objs_ht_free,
205
0
        .ht_hash_fn = obj_ht_hash,
206
0
        .init_neighborhoods = X509_OBJS_HT_BUCKETS,
207
0
        .no_rcu = 1,
208
0
    };
209
210
0
    if (ret == NULL)
211
0
        return NULL;
212
0
    if ((ret->objs_ht = ossl_ht_new(&htconf)) == NULL) {
213
0
        ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB);
214
0
        goto err;
215
0
    }
216
0
    if ((ret->objs = sk_X509_OBJECT_new(x509_object_cmp)) == NULL) {
217
0
        ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB);
218
0
        goto err;
219
0
    }
220
0
    ret->cache = 1;
221
0
    if ((ret->get_cert_methods = sk_X509_LOOKUP_new_null()) == NULL) {
222
0
        ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB);
223
0
        goto err;
224
0
    }
225
226
0
    if ((ret->param = X509_VERIFY_PARAM_new()) == NULL) {
227
0
        ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB);
228
0
        goto err;
229
0
    }
230
0
    if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data)) {
231
0
        ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB);
232
0
        goto err;
233
0
    }
234
235
0
    ret->lock = CRYPTO_THREAD_lock_new();
236
0
    if (ret->lock == NULL) {
237
0
        ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB);
238
0
        goto err;
239
0
    }
240
241
0
    if (!CRYPTO_NEW_REF(&ret->references, 1))
242
0
        goto err;
243
0
    return ret;
244
245
0
err:
246
0
    X509_VERIFY_PARAM_free(ret->param);
247
0
    sk_X509_OBJECT_free(ret->objs);
248
0
    sk_X509_LOOKUP_free(ret->get_cert_methods);
249
0
    ossl_ht_free(ret->objs_ht);
250
0
    CRYPTO_THREAD_lock_free(ret->lock);
251
0
    OPENSSL_free(ret);
252
0
    return NULL;
253
0
}
254
255
void X509_STORE_free(X509_STORE *xs)
256
0
{
257
0
    int i;
258
0
    STACK_OF(X509_LOOKUP) *sk;
259
0
    X509_LOOKUP *lu;
260
261
0
    if (xs == NULL)
262
0
        return;
263
0
    CRYPTO_DOWN_REF(&xs->references, &i);
264
0
    REF_PRINT_COUNT("X509_STORE", i, xs);
265
0
    if (i > 0)
266
0
        return;
267
0
    REF_ASSERT_ISNT(i < 0);
268
269
0
    sk = xs->get_cert_methods;
270
0
    for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) {
271
0
        lu = sk_X509_LOOKUP_value(sk, i);
272
0
        X509_LOOKUP_shutdown(lu);
273
0
        X509_LOOKUP_free(lu);
274
0
    }
275
0
    sk_X509_LOOKUP_free(sk);
276
0
    sk_X509_OBJECT_pop_free(xs->objs, X509_OBJECT_free);
277
278
0
    CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, xs, &xs->ex_data);
279
0
    X509_VERIFY_PARAM_free(xs->param);
280
0
    CRYPTO_THREAD_lock_free(xs->lock);
281
0
    CRYPTO_FREE_REF(&xs->references);
282
0
    ossl_ht_free(xs->objs_ht);
283
0
    OPENSSL_free(xs);
284
0
}
285
286
int X509_STORE_up_ref(X509_STORE *xs)
287
0
{
288
0
    int i;
289
290
0
    if (CRYPTO_UP_REF(&xs->references, &i) <= 0)
291
0
        return 0;
292
293
0
    REF_PRINT_COUNT("X509_STORE", i, xs);
294
0
    REF_ASSERT_ISNT(i < 2);
295
0
    return i > 1 ? 1 : 0;
296
0
}
297
298
X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *xs, X509_LOOKUP_METHOD *m)
299
0
{
300
0
    int i;
301
0
    STACK_OF(X509_LOOKUP) *sk;
302
0
    X509_LOOKUP *lu;
303
304
0
    sk = xs->get_cert_methods;
305
0
    for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) {
306
0
        lu = sk_X509_LOOKUP_value(sk, i);
307
0
        if (m == lu->method) {
308
0
            return lu;
309
0
        }
310
0
    }
311
    /* a new one */
312
0
    lu = X509_LOOKUP_new(m);
313
0
    if (lu == NULL) {
314
0
        ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB);
315
0
        return NULL;
316
0
    }
317
318
0
    lu->store_ctx = xs;
319
0
    if (sk_X509_LOOKUP_push(xs->get_cert_methods, lu))
320
0
        return lu;
321
    /* sk_X509_LOOKUP_push() failed */
322
0
    ERR_raise(ERR_LIB_X509, ERR_R_CRYPTO_LIB);
323
0
    X509_LOOKUP_free(lu);
324
0
    return NULL;
325
0
}
326
327
/* Also fill the cache (ctx->store->objs) with all matching certificates. */
328
X509_OBJECT *X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *ctx,
329
    X509_LOOKUP_TYPE type,
330
    const X509_NAME *name)
331
0
{
332
0
    X509_OBJECT *ret = X509_OBJECT_new();
333
334
0
    if (ret == NULL)
335
0
        return NULL;
336
0
    if (!X509_STORE_CTX_get_by_subject(ctx, type, name, ret)) {
337
0
        X509_OBJECT_free(ret);
338
0
        return NULL;
339
0
    }
340
0
    return ret;
341
0
}
342
343
STACK_OF(X509_OBJECT) *ossl_x509_store_ht_get_by_name(const X509_STORE *store,
344
    const X509_NAME *xn)
345
0
{
346
0
    HT_VALUE *v;
347
0
    OBJS_KEY key;
348
0
    int ret;
349
350
0
    if (xn->canon_enc == NULL || xn->modified) {
351
0
        ret = i2d_X509_NAME((X509_NAME *)xn, NULL);
352
0
        if (ret < 0)
353
0
            return NULL;
354
0
    }
355
356
0
    HT_INIT_KEY(&key);
357
0
    HT_SET_KEY_FIELD(&key, xn_canon, xn->canon_enc);
358
0
    HT_SET_KEY_FIELD(&key, xn_canon_enclen, xn->canon_enclen);
359
0
    v = ossl_ht_get(store->objs_ht, TO_HT_KEY(&key));
360
0
    if (v == NULL)
361
0
        return NULL;
362
0
    v = ossl_rcu_deref(&v);
363
364
0
    return v->value;
365
0
}
366
367
static int x509_name_objs_ht_insert(const X509_STORE *store, const X509_NAME *xn,
368
    STACK_OF(X509_OBJECT) *objs, X509_OBJECT *obj)
369
0
{
370
0
    int ret = 0, added = 0;
371
0
    OBJS_KEY key;
372
0
    HT_VALUE val = { 0 };
373
374
0
    if (objs != NULL) {
375
0
        added = sk_X509_OBJECT_push(objs, obj) != 0;
376
0
        return added;
377
0
    }
378
379
0
    if (xn->canon_enc == NULL || xn->modified) {
380
0
        ret = i2d_X509_NAME((X509_NAME *)xn, NULL);
381
0
        if (ret < 0)
382
0
            return 0;
383
0
    }
384
385
0
    objs = sk_X509_OBJECT_new(x509_object_cmp);
386
0
    if (objs == NULL)
387
0
        return 0;
388
389
0
    added = sk_X509_OBJECT_push(objs, obj) != 0;
390
0
    if (added == 0) {
391
0
        sk_X509_OBJECT_free(objs);
392
0
        return 0;
393
0
    }
394
395
0
    HT_INIT_KEY(&key);
396
0
    HT_SET_KEY_FIELD(&key, xn_canon, xn->canon_enc);
397
0
    HT_SET_KEY_FIELD(&key, xn_canon_enclen, xn->canon_enclen);
398
0
    val.value = (void *)objs;
399
0
    ret = ossl_ht_insert(store->objs_ht, TO_HT_KEY(&key), &val, NULL);
400
0
    if (ret != 1) {
401
0
        sk_X509_OBJECT_free(objs);
402
0
        return 0;
403
0
    }
404
405
0
    return 1;
406
0
}
407
408
static int obj_ht_foreach_certs(HT_VALUE *v, void *arg)
409
0
{
410
0
    STACK_OF(X509) **sk = arg;
411
0
    STACK_OF(X509_OBJECT) *objs = v->value;
412
0
    int i, r;
413
414
0
    for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
415
0
        X509 *cert = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(objs, i));
416
417
0
        if (cert == NULL)
418
0
            continue;
419
0
        r = X509_add_cert(*sk, cert, X509_ADD_FLAG_UP_REF);
420
0
        if (r == 0) {
421
0
            OSSL_STACK_OF_X509_free(*sk);
422
0
            *sk = NULL;
423
0
            return 0;
424
0
        }
425
0
    }
426
427
0
    return 1;
428
0
}
429
430
/*
431
 * May be called with |ret| == NULL just for the side effect of
432
 * caching all certs matching the given subject DN in |ctx->store->objs|.
433
 * Returns 1 if successful,
434
 * 0 if not found or X509_LOOKUP_by_subject_ex() returns an error,
435
 * -1 on failure
436
 */
437
int ossl_x509_store_ctx_get_by_subject(const X509_STORE_CTX *ctx, X509_LOOKUP_TYPE type,
438
    const X509_NAME *name, X509_OBJECT *ret)
439
0
{
440
0
    X509_STORE *store = ctx->store;
441
0
    X509_LOOKUP *lu;
442
0
    X509_OBJECT stmp, *tmp = NULL;
443
0
    STACK_OF(X509_OBJECT) *objs;
444
0
    int i, j;
445
446
0
    if (store == NULL)
447
0
        return 0;
448
449
0
    stmp.type = X509_LU_NONE;
450
0
    stmp.data.x509 = NULL;
451
452
0
    if (!ossl_x509_store_read_lock(store))
453
0
        return 0;
454
0
    if (store->objs_ht != NULL) {
455
0
        objs = ossl_x509_store_ht_get_by_name(store, name);
456
0
        if (objs != NULL)
457
0
            tmp = X509_OBJECT_retrieve_by_subject(objs, type, name);
458
0
    } else {
459
0
        tmp = X509_OBJECT_retrieve_by_subject(store->objs, type, name);
460
0
    }
461
0
    X509_STORE_unlock(store);
462
463
0
    if (tmp == NULL || type == X509_LU_CRL) {
464
0
        for (i = 0; i < sk_X509_LOOKUP_num(store->get_cert_methods); i++) {
465
0
            lu = sk_X509_LOOKUP_value(store->get_cert_methods, i);
466
0
            if (lu->skip)
467
0
                continue;
468
0
            if (lu->method == NULL)
469
0
                return -1;
470
0
            j = X509_LOOKUP_by_subject_ex(lu, type, name, &stmp,
471
0
                ctx->libctx, ctx->propq);
472
0
            if (j != 0) { /* non-zero value is considered success here */
473
0
                tmp = &stmp;
474
0
                break;
475
0
            }
476
0
        }
477
0
        if (tmp == NULL)
478
0
            return 0;
479
0
    }
480
481
0
    if (ret != NULL) {
482
0
        if (!X509_OBJECT_up_ref_count(tmp))
483
0
            return -1;
484
0
        ret->type = tmp->type;
485
0
        ret->data = tmp->data;
486
0
    }
487
0
    return 1;
488
0
}
489
490
/* Also fill the cache |ctx->store->objs| with all matching certificates. */
491
int X509_STORE_CTX_get_by_subject(const X509_STORE_CTX *ctx,
492
    X509_LOOKUP_TYPE type,
493
    const X509_NAME *name, X509_OBJECT *ret)
494
0
{
495
0
    return ossl_x509_store_ctx_get_by_subject(ctx, type, name, ret) > 0;
496
0
}
497
static int x509_store_add_obj(X509_STORE *store, X509_OBJECT *obj)
498
0
{
499
0
    const X509_NAME *xn;
500
0
    STACK_OF(X509_OBJECT) *objs = NULL;
501
0
    int ret = 0, added = 0;
502
503
0
    if (obj->type == X509_LU_CRL)
504
0
        xn = obj->data.crl->crl.issuer;
505
0
    else
506
0
        xn = obj->data.x509->cert_info.subject;
507
508
0
    if (xn == NULL) {
509
0
        obj->type = X509_LU_NONE;
510
0
        X509_OBJECT_free(obj);
511
0
        return 0;
512
0
    }
513
514
0
    if (!X509_OBJECT_up_ref_count(obj)) {
515
0
        obj->type = X509_LU_NONE;
516
0
        X509_OBJECT_free(obj);
517
0
        return 0;
518
0
    }
519
520
0
    if (!X509_STORE_lock(store)) {
521
0
        X509_OBJECT_free(obj);
522
0
        return 0;
523
0
    }
524
525
0
    if (store->objs_ht != NULL) {
526
0
        objs = ossl_x509_store_ht_get_by_name(store, xn);
527
0
        if (objs != NULL && X509_OBJECT_retrieve_match(objs, obj)) {
528
0
            ret = 1;
529
0
        } else {
530
0
            added = x509_name_objs_ht_insert(store, xn, objs, obj);
531
0
            ret = added != 0;
532
0
        }
533
0
    } else {
534
0
        if (X509_OBJECT_retrieve_match(store->objs, obj)) {
535
0
            ret = 1;
536
0
        } else {
537
0
            added = sk_X509_OBJECT_push(store->objs, obj);
538
0
            ret = added != 0;
539
0
        }
540
0
    }
541
0
    X509_STORE_unlock(store);
542
543
0
    if (added == 0) /* obj not pushed */
544
0
        X509_OBJECT_free(obj);
545
546
0
    return ret;
547
0
}
548
549
static int x509_store_add_x509(X509_STORE *store, const X509 *x)
550
0
{
551
0
    X509_OBJECT *obj;
552
553
0
    if (x == NULL)
554
0
        return 0;
555
0
    obj = X509_OBJECT_new();
556
0
    if (obj == NULL)
557
0
        return 0;
558
559
0
    obj->type = X509_LU_X509;
560
    /*
561
     * XXX Casts away const, get rid of this once we can have the x509
562
     * member of OBJECT be const.
563
     */
564
0
    obj->data.x509 = (X509 *)x;
565
566
0
    return x509_store_add_obj(store, obj);
567
0
}
568
569
static int x509_store_add_crl(X509_STORE *store, X509_CRL *crl)
570
0
{
571
0
    X509_OBJECT *obj;
572
573
0
    if (crl == NULL)
574
0
        return 0;
575
0
    obj = X509_OBJECT_new();
576
0
    if (obj == NULL)
577
0
        return 0;
578
579
0
    obj->type = X509_LU_CRL;
580
0
    obj->data.crl = crl;
581
582
0
    return x509_store_add_obj(store, obj);
583
0
}
584
585
int X509_STORE_add_cert(X509_STORE *xs, const X509 *x)
586
0
{
587
0
    if (!x509_store_add_x509(xs, x)) {
588
0
        ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB);
589
0
        return 0;
590
0
    }
591
0
    return 1;
592
0
}
593
594
int X509_STORE_add_crl(X509_STORE *xs, X509_CRL *x)
595
0
{
596
0
    if (!x509_store_add_crl(xs, x)) {
597
0
        ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB);
598
0
        return 0;
599
0
    }
600
0
    return 1;
601
0
}
602
603
int X509_OBJECT_up_ref_count(X509_OBJECT *a)
604
0
{
605
0
    switch (a->type) {
606
0
    case X509_LU_NONE:
607
0
        break;
608
0
    case X509_LU_X509:
609
0
        return X509_up_ref(a->data.x509);
610
0
    case X509_LU_CRL:
611
0
        return X509_CRL_up_ref(a->data.crl);
612
0
    }
613
0
    return 1;
614
0
}
615
616
X509 *X509_OBJECT_get0_X509(const X509_OBJECT *a)
617
0
{
618
0
    if (a == NULL || a->type != X509_LU_X509)
619
0
        return NULL;
620
0
    return a->data.x509;
621
0
}
622
623
X509_CRL *X509_OBJECT_get0_X509_CRL(const X509_OBJECT *a)
624
0
{
625
0
    if (a == NULL || a->type != X509_LU_CRL)
626
0
        return NULL;
627
0
    return a->data.crl;
628
0
}
629
630
X509_LOOKUP_TYPE X509_OBJECT_get_type(const X509_OBJECT *a)
631
0
{
632
0
    return a->type;
633
0
}
634
635
X509_OBJECT *X509_OBJECT_new(void)
636
0
{
637
0
    X509_OBJECT *ret = OPENSSL_zalloc(sizeof(*ret));
638
639
0
    if (ret == NULL)
640
0
        return NULL;
641
0
    ret->type = X509_LU_NONE;
642
0
    return ret;
643
0
}
644
645
static void x509_object_free_internal(X509_OBJECT *a)
646
0
{
647
0
    if (a == NULL)
648
0
        return;
649
0
    switch (a->type) {
650
0
    case X509_LU_NONE:
651
0
        break;
652
0
    case X509_LU_X509:
653
0
        X509_free(a->data.x509);
654
0
        break;
655
0
    case X509_LU_CRL:
656
0
        X509_CRL_free(a->data.crl);
657
0
        break;
658
0
    }
659
0
}
660
661
int X509_OBJECT_set1_X509(X509_OBJECT *a, X509 *obj)
662
0
{
663
0
    if (a == NULL || !X509_up_ref(obj))
664
0
        return 0;
665
666
0
    x509_object_free_internal(a);
667
0
    a->type = X509_LU_X509;
668
0
    a->data.x509 = obj;
669
0
    return 1;
670
0
}
671
672
int X509_OBJECT_set1_X509_CRL(X509_OBJECT *a, X509_CRL *obj)
673
0
{
674
0
    if (a == NULL || !X509_CRL_up_ref(obj))
675
0
        return 0;
676
677
0
    x509_object_free_internal(a);
678
0
    a->type = X509_LU_CRL;
679
0
    a->data.crl = obj;
680
0
    return 1;
681
0
}
682
683
void X509_OBJECT_free(X509_OBJECT *a)
684
0
{
685
0
    x509_object_free_internal(a);
686
0
    OPENSSL_free(a);
687
0
}
688
689
/* Returns -1 if not found, but also on error */
690
static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type,
691
    const X509_NAME *name, int *pnmatch)
692
0
{
693
0
    X509_OBJECT stmp;
694
0
    X509 x509_s;
695
0
    X509_CRL crl_s;
696
697
0
    stmp.type = type;
698
0
    switch (type) {
699
0
    case X509_LU_X509:
700
0
        stmp.data.x509 = &x509_s;
701
0
        x509_s.cert_info.subject = (X509_NAME *)name; /* won't modify it */
702
0
        break;
703
0
    case X509_LU_CRL:
704
0
        stmp.data.crl = &crl_s;
705
0
        crl_s.crl.issuer = (X509_NAME *)name; /* won't modify it */
706
0
        break;
707
0
    case X509_LU_NONE:
708
0
    default:
709
        /* abort(); */
710
0
        return -1;
711
0
    }
712
713
    /* Assumes h is locked for read if applicable */
714
0
    return sk_X509_OBJECT_find_all(h, &stmp, pnmatch);
715
0
}
716
717
/* Assumes h is locked for read if applicable */
718
int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type,
719
    const X509_NAME *name)
720
0
{
721
0
    return x509_object_idx_cnt(h, type, name, NULL);
722
0
}
723
724
/* Assumes h is locked for read if applicable */
725
X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,
726
    X509_LOOKUP_TYPE type,
727
    const X509_NAME *name)
728
0
{
729
0
    int idx = X509_OBJECT_idx_by_subject(h, type, name);
730
731
0
    if (idx == -1)
732
0
        return NULL;
733
0
    return sk_X509_OBJECT_value(h, idx);
734
0
}
735
736
static X509_OBJECT *x509_object_dup(const X509_OBJECT *obj)
737
0
{
738
0
    X509_OBJECT *ret = X509_OBJECT_new();
739
0
    if (ret == NULL)
740
0
        return NULL;
741
742
0
    ret->type = obj->type;
743
0
    ret->data = obj->data;
744
0
    X509_OBJECT_up_ref_count(ret);
745
0
    return ret;
746
0
}
747
748
static int obj_ht_foreach_object(HT_VALUE *v, void *arg)
749
0
{
750
0
    STACK_OF(X509_OBJECT) **sk = arg;
751
0
    STACK_OF(X509_OBJECT) *objs = v->value;
752
0
    X509_OBJECT *dup, *obj;
753
0
    int i;
754
755
0
    for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
756
0
        obj = sk_X509_OBJECT_value(objs, i);
757
0
        dup = x509_object_dup(obj);
758
0
        if (dup == NULL)
759
0
            goto err;
760
0
        if (sk_X509_OBJECT_push(*sk, dup) == 0)
761
0
            goto err;
762
0
    }
763
764
0
    return 1;
765
766
0
err:
767
0
    sk_X509_OBJECT_pop_free(*sk, X509_OBJECT_free);
768
0
    *sk = NULL;
769
770
0
    return 0;
771
0
}
772
773
#ifndef OPENSSL_NO_DEPRECATED_4_0
774
STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(const X509_STORE *xs)
775
0
{
776
0
    X509_STORE *store = (X509_STORE *)xs;
777
778
0
    if (xs->objs_ht != NULL) {
779
0
        ossl_ht_foreach_until(xs->objs_ht, obj_ht_foreach_object, &store->objs);
780
0
        ossl_ht_free(xs->objs_ht);
781
0
        store->objs_ht = NULL;
782
0
    }
783
784
0
    return xs->objs;
785
0
}
786
#endif
787
788
STACK_OF(X509_OBJECT) *X509_STORE_get1_objects(X509_STORE *store)
789
0
{
790
0
    STACK_OF(X509_OBJECT) *objs;
791
792
0
    if (store == NULL) {
793
0
        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
794
0
        return NULL;
795
0
    }
796
797
0
    if (!ossl_x509_store_read_lock(store))
798
0
        return NULL;
799
800
0
    if (store->objs_ht != NULL) {
801
0
        if ((objs = sk_X509_OBJECT_new(x509_object_cmp)) == NULL) {
802
0
            X509_STORE_unlock(store);
803
0
            return NULL;
804
0
        }
805
0
        ossl_ht_foreach_until(store->objs_ht, obj_ht_foreach_object, &objs);
806
0
    } else {
807
0
        objs = sk_X509_OBJECT_deep_copy(store->objs, x509_object_dup,
808
0
            X509_OBJECT_free);
809
0
    }
810
0
    X509_STORE_unlock(store);
811
812
0
    return objs;
813
0
}
814
815
STACK_OF(X509) *X509_STORE_get1_all_certs(X509_STORE *store)
816
0
{
817
0
    STACK_OF(X509) *sk = NULL;
818
819
0
    if (store == NULL) {
820
0
        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
821
0
        return NULL;
822
0
    }
823
0
    if ((sk = sk_X509_new_null()) == NULL)
824
0
        return NULL;
825
826
0
    if (!ossl_x509_store_read_lock(store))
827
0
        goto out_free;
828
829
0
    if (store->objs_ht != NULL) {
830
0
        ossl_ht_foreach_until(store->objs_ht, obj_ht_foreach_certs, &sk);
831
0
    } else {
832
0
        for (int i = 0; i < sk_X509_OBJECT_num(store->objs); i++) {
833
0
            X509 *cert = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(store->objs, i));
834
835
0
            if (cert != NULL
836
0
                && !X509_add_cert(sk, cert, X509_ADD_FLAG_UP_REF))
837
0
                goto err;
838
0
        }
839
0
    }
840
0
    X509_STORE_unlock(store);
841
842
0
    return sk;
843
844
0
err:
845
0
    X509_STORE_unlock(store);
846
0
out_free:
847
0
    OSSL_STACK_OF_X509_free(sk);
848
0
    return NULL;
849
0
}
850
851
/*-
852
 * Collect from |ctx->store| all certs with subject matching |nm|.
853
 * Returns NULL on internal/fatal error, empty stack if not found.
854
 */
855
STACK_OF(X509) *X509_STORE_CTX_get1_certs(const X509_STORE_CTX *ctx,
856
    const X509_NAME *nm)
857
0
{
858
0
    int i, idx = -1, cnt = 0;
859
0
    STACK_OF(X509) *sk = NULL;
860
0
    X509 *x;
861
0
    X509_OBJECT *obj;
862
0
    X509_STORE *store = ctx->store;
863
0
    STACK_OF(X509_OBJECT) *objs;
864
865
0
    if (store == NULL)
866
0
        return sk_X509_new_null();
867
868
0
    if (!ossl_x509_store_read_lock(store))
869
0
        return NULL;
870
871
0
    if (store->objs_ht != NULL) {
872
0
        objs = ossl_x509_store_ht_get_by_name(store, nm);
873
0
        if (objs != NULL)
874
0
            idx = x509_object_idx_cnt(objs, X509_LU_X509, nm, &cnt);
875
0
    } else {
876
0
        objs = store->objs;
877
0
        idx = x509_object_idx_cnt(objs, X509_LU_X509, nm, &cnt);
878
0
    }
879
0
    if (idx < 0 || objs == NULL) {
880
        /*
881
         * Nothing found in cache: do lookup to possibly add new objects to
882
         * cache
883
         */
884
0
        X509_STORE_unlock(store);
885
0
        i = ossl_x509_store_ctx_get_by_subject(ctx, X509_LU_X509, nm, NULL);
886
0
        if (i <= 0)
887
0
            return i < 0 ? NULL : sk_X509_new_null();
888
0
        if (!ossl_x509_store_read_lock(store))
889
0
            return NULL;
890
0
        if (store->objs_ht != NULL) {
891
0
            objs = ossl_x509_store_ht_get_by_name(store, nm);
892
0
            if (objs == NULL)
893
0
                goto end;
894
0
        } else {
895
0
            objs = store->objs;
896
0
        }
897
0
        idx = x509_object_idx_cnt(objs, X509_LU_X509, nm, &cnt);
898
0
    }
899
900
0
    sk = sk_X509_new_null();
901
0
    if (idx < 0 || sk == NULL)
902
0
        goto end;
903
0
    for (i = idx; i < sk_X509_OBJECT_num(objs); i++) {
904
0
        obj = sk_X509_OBJECT_value(objs, i);
905
0
        x = obj->data.x509;
906
0
        if (obj->type != X509_LU_X509)
907
0
            continue;
908
0
        if (X509_add_cert(sk, x, X509_ADD_FLAG_UP_REF) == 0) {
909
0
            X509_STORE_unlock(store);
910
0
            OSSL_STACK_OF_X509_free(sk);
911
0
            return NULL;
912
0
        }
913
0
    }
914
915
0
end:
916
0
    X509_STORE_unlock(store);
917
0
    return sk;
918
0
}
919
920
/* Returns NULL on internal/fatal error, empty stack if not found */
921
STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(const X509_STORE_CTX *ctx,
922
    const X509_NAME *nm)
923
0
{
924
0
    int i = 1, idx, cnt = 0;
925
0
    STACK_OF(X509_CRL) *sk;
926
0
    X509_CRL *x;
927
0
    X509_OBJECT *obj;
928
0
    X509_STORE *store = ctx->store;
929
0
    STACK_OF(X509_OBJECT) *objs;
930
931
    /* Always do lookup to possibly add new CRLs to cache */
932
0
    i = ossl_x509_store_ctx_get_by_subject(ctx, X509_LU_CRL, nm, NULL);
933
0
    if (i < 0)
934
0
        return NULL;
935
0
    sk = sk_X509_CRL_new_null();
936
0
    if (i == 0)
937
0
        return sk;
938
0
    if (!ossl_x509_store_read_lock(store)) {
939
0
        sk_X509_CRL_free(sk);
940
0
        return NULL;
941
0
    }
942
0
    if (store->objs_ht) {
943
0
        objs = ossl_x509_store_ht_get_by_name(store, nm);
944
0
        if (objs == NULL)
945
0
            goto end;
946
0
    } else {
947
0
        objs = store->objs;
948
0
    }
949
0
    idx = x509_object_idx_cnt(objs, X509_LU_CRL, nm, &cnt);
950
0
    if (idx < 0)
951
0
        goto end;
952
953
0
    for (i = idx; i < sk_X509_OBJECT_num(objs); i++) {
954
0
        obj = sk_X509_OBJECT_value(objs, i);
955
0
        x = obj->data.crl;
956
0
        if (obj->type != X509_LU_CRL)
957
0
            continue;
958
0
        if (!X509_CRL_up_ref(x)) {
959
0
            X509_STORE_unlock(store);
960
0
            sk_X509_CRL_pop_free(sk, X509_CRL_free);
961
0
            return NULL;
962
0
        }
963
0
        if (!sk_X509_CRL_push(sk, x)) {
964
0
            X509_STORE_unlock(store);
965
0
            X509_CRL_free(x);
966
0
            sk_X509_CRL_pop_free(sk, X509_CRL_free);
967
0
            return NULL;
968
0
        }
969
0
    }
970
0
end:
971
0
    X509_STORE_unlock(store);
972
0
    return sk;
973
0
}
974
975
X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h,
976
    X509_OBJECT *x)
977
0
{
978
0
    int idx, i, num;
979
0
    X509_OBJECT *obj;
980
981
0
    idx = sk_X509_OBJECT_find(h, x);
982
0
    if (idx < 0)
983
0
        return NULL;
984
0
    if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL))
985
0
        return sk_X509_OBJECT_value(h, idx);
986
0
    for (i = idx, num = sk_X509_OBJECT_num(h); i < num; i++) {
987
0
        obj = sk_X509_OBJECT_value(h, i);
988
0
        if (x509_object_cmp((const X509_OBJECT **)&obj,
989
0
                (const X509_OBJECT **)&x))
990
0
            return NULL;
991
0
        if (x->type == X509_LU_X509) {
992
0
            if (!X509_cmp(obj->data.x509, x->data.x509))
993
0
                return obj;
994
0
        } else if (x->type == X509_LU_CRL) {
995
0
            if (X509_CRL_match(obj->data.crl, x->data.crl) == 0)
996
0
                return obj;
997
0
        } else {
998
0
            return obj;
999
0
        }
1000
0
    }
1001
0
    return NULL;
1002
0
}
1003
1004
int X509_STORE_set_flags(X509_STORE *xs, unsigned long flags)
1005
0
{
1006
0
    return X509_VERIFY_PARAM_set_flags(xs->param, flags);
1007
0
}
1008
1009
int X509_STORE_set_depth(X509_STORE *xs, int depth)
1010
0
{
1011
0
    X509_VERIFY_PARAM_set_depth(xs->param, depth);
1012
0
    return 1;
1013
0
}
1014
1015
int X509_STORE_set_purpose(X509_STORE *xs, int purpose)
1016
0
{
1017
0
    return X509_VERIFY_PARAM_set_purpose(xs->param, purpose);
1018
0
}
1019
1020
int X509_STORE_set_trust(X509_STORE *xs, int trust)
1021
0
{
1022
0
    return X509_VERIFY_PARAM_set_trust(xs->param, trust);
1023
0
}
1024
1025
int X509_STORE_set1_param(X509_STORE *xs, const X509_VERIFY_PARAM *param)
1026
0
{
1027
0
    return X509_VERIFY_PARAM_set1(xs->param, param);
1028
0
}
1029
1030
X509_VERIFY_PARAM *X509_STORE_get0_param(const X509_STORE *xs)
1031
0
{
1032
0
    return xs->param;
1033
0
}
1034
1035
void X509_STORE_set_verify(X509_STORE *xs, X509_STORE_CTX_verify_fn verify)
1036
0
{
1037
0
    xs->verify = verify;
1038
0
}
1039
1040
X509_STORE_CTX_verify_fn X509_STORE_get_verify(const X509_STORE *xs)
1041
0
{
1042
0
    return xs->verify;
1043
0
}
1044
1045
void X509_STORE_set_verify_cb(X509_STORE *xs,
1046
    X509_STORE_CTX_verify_cb verify_cb)
1047
0
{
1048
0
    xs->verify_cb = verify_cb;
1049
0
}
1050
1051
X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(const X509_STORE *xs)
1052
0
{
1053
0
    return xs->verify_cb;
1054
0
}
1055
1056
void X509_STORE_set_get_issuer(X509_STORE *xs,
1057
    X509_STORE_CTX_get_issuer_fn get_issuer)
1058
0
{
1059
0
    xs->get_issuer = get_issuer;
1060
0
}
1061
1062
X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(const X509_STORE *xs)
1063
0
{
1064
0
    return xs->get_issuer;
1065
0
}
1066
1067
void X509_STORE_set_check_issued(X509_STORE *xs,
1068
    X509_STORE_CTX_check_issued_fn check_issued)
1069
0
{
1070
0
    xs->check_issued = check_issued;
1071
0
}
1072
1073
X509_STORE_CTX_check_issued_fn X509_STORE_get_check_issued(const X509_STORE *xs)
1074
0
{
1075
0
    return xs->check_issued;
1076
0
}
1077
1078
void X509_STORE_set_check_revocation(X509_STORE *xs,
1079
    X509_STORE_CTX_check_revocation_fn cb)
1080
0
{
1081
0
    xs->check_revocation = cb;
1082
0
}
1083
1084
X509_STORE_CTX_check_revocation_fn X509_STORE_get_check_revocation(const X509_STORE *xs)
1085
0
{
1086
0
    return xs->check_revocation;
1087
0
}
1088
1089
void X509_STORE_set_get_crl(X509_STORE *xs,
1090
    X509_STORE_CTX_get_crl_fn get_crl)
1091
0
{
1092
0
    xs->get_crl = get_crl;
1093
0
}
1094
1095
X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(const X509_STORE *xs)
1096
0
{
1097
0
    return xs->get_crl;
1098
0
}
1099
1100
void X509_STORE_set_check_crl(X509_STORE *xs,
1101
    X509_STORE_CTX_check_crl_fn check_crl)
1102
0
{
1103
0
    xs->check_crl = check_crl;
1104
0
}
1105
1106
X509_STORE_CTX_check_crl_fn X509_STORE_get_check_crl(const X509_STORE *xs)
1107
0
{
1108
0
    return xs->check_crl;
1109
0
}
1110
1111
void X509_STORE_set_cert_crl(X509_STORE *xs,
1112
    X509_STORE_CTX_cert_crl_fn cert_crl)
1113
0
{
1114
0
    xs->cert_crl = cert_crl;
1115
0
}
1116
1117
X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(const X509_STORE *xs)
1118
0
{
1119
0
    return xs->cert_crl;
1120
0
}
1121
1122
void X509_STORE_set_check_policy(X509_STORE *xs,
1123
    X509_STORE_CTX_check_policy_fn check_policy)
1124
0
{
1125
0
    xs->check_policy = check_policy;
1126
0
}
1127
1128
X509_STORE_CTX_check_policy_fn X509_STORE_get_check_policy(const X509_STORE *xs)
1129
0
{
1130
0
    return xs->check_policy;
1131
0
}
1132
1133
void X509_STORE_set_lookup_certs(X509_STORE *xs,
1134
    X509_STORE_CTX_lookup_certs_fn lookup_certs)
1135
0
{
1136
0
    xs->lookup_certs = lookup_certs;
1137
0
}
1138
1139
X509_STORE_CTX_lookup_certs_fn X509_STORE_get_lookup_certs(const X509_STORE *xs)
1140
0
{
1141
0
    return xs->lookup_certs;
1142
0
}
1143
1144
void X509_STORE_set_lookup_crls(X509_STORE *xs,
1145
    X509_STORE_CTX_lookup_crls_fn lookup_crls)
1146
0
{
1147
0
    xs->lookup_crls = lookup_crls;
1148
0
}
1149
1150
X509_STORE_CTX_lookup_crls_fn X509_STORE_get_lookup_crls(const X509_STORE *xs)
1151
0
{
1152
0
    return xs->lookup_crls;
1153
0
}
1154
1155
void X509_STORE_set_cleanup(X509_STORE *xs,
1156
    X509_STORE_CTX_cleanup_fn cleanup)
1157
0
{
1158
0
    xs->cleanup = cleanup;
1159
0
}
1160
1161
X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(const X509_STORE *xs)
1162
0
{
1163
0
    return xs->cleanup;
1164
0
}
1165
1166
int X509_STORE_set_ex_data(X509_STORE *xs, int idx, void *data)
1167
0
{
1168
0
    return CRYPTO_set_ex_data(&xs->ex_data, idx, data);
1169
0
}
1170
1171
void *X509_STORE_get_ex_data(const X509_STORE *xs, int idx)
1172
0
{
1173
0
    return CRYPTO_get_ex_data(&xs->ex_data, idx);
1174
0
}
1175
1176
X509_STORE *X509_STORE_CTX_get0_store(const X509_STORE_CTX *ctx)
1177
0
{
1178
0
    return ctx->store;
1179
0
}