Coverage Report

Created: 2025-10-28 06:56

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
498
static int x509_store_add(X509_STORE *store, void *x, int crl)
499
0
{
500
0
    X509_OBJECT *obj;
501
0
    int ret = 0, added = 0;
502
0
    X509_NAME *xn;
503
0
    STACK_OF(X509_OBJECT) *objs = NULL;
504
505
0
    if (x == NULL)
506
0
        return 0;
507
0
    obj = X509_OBJECT_new();
508
0
    if (obj == NULL)
509
0
        return 0;
510
511
0
    if (crl) {
512
0
        obj->type = X509_LU_CRL;
513
0
        obj->data.crl = (X509_CRL *)x;
514
0
        xn = obj->data.crl->crl.issuer;
515
0
    } else {
516
0
        obj->type = X509_LU_X509;
517
0
        obj->data.x509 = (X509 *)x;
518
0
        xn = obj->data.x509->cert_info.subject;
519
0
    }
520
521
0
    if (xn == NULL) {
522
0
        obj->type = X509_LU_NONE;
523
0
        X509_OBJECT_free(obj);
524
0
        return 0;
525
0
    }
526
527
0
    if (!X509_OBJECT_up_ref_count(obj)) {
528
0
        obj->type = X509_LU_NONE;
529
0
        X509_OBJECT_free(obj);
530
0
        return 0;
531
0
    }
532
533
0
    if (!X509_STORE_lock(store)) {
534
0
        X509_OBJECT_free(obj);
535
0
        return 0;
536
0
    }
537
538
0
    if (store->objs_ht != NULL) {
539
0
        objs = ossl_x509_store_ht_get_by_name(store, xn);
540
0
        if (objs != NULL && X509_OBJECT_retrieve_match(objs, obj)) {
541
0
            ret = 1;
542
0
        } else {
543
0
            added = x509_name_objs_ht_insert(store, xn, objs, obj);
544
0
            ret = added != 0;
545
0
        }
546
0
    } else {
547
0
        if (X509_OBJECT_retrieve_match(store->objs, obj)) {
548
0
            ret = 1;
549
0
        } else {
550
0
            added = sk_X509_OBJECT_push(store->objs, obj);
551
0
            ret = added != 0;
552
0
        }
553
0
    }
554
0
    X509_STORE_unlock(store);
555
556
0
    if (added == 0)             /* obj not pushed */
557
0
        X509_OBJECT_free(obj);
558
559
0
    return ret;
560
0
}
561
562
int X509_STORE_add_cert(X509_STORE *xs, X509 *x)
563
0
{
564
0
    if (!x509_store_add(xs, x, 0)) {
565
0
        ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB);
566
0
        return 0;
567
0
    }
568
0
    return 1;
569
0
}
570
571
int X509_STORE_add_crl(X509_STORE *xs, X509_CRL *x)
572
0
{
573
0
    if (!x509_store_add(xs, x, 1)) {
574
0
        ERR_raise(ERR_LIB_X509, ERR_R_X509_LIB);
575
0
        return 0;
576
0
    }
577
0
    return 1;
578
0
}
579
580
int X509_OBJECT_up_ref_count(X509_OBJECT *a)
581
0
{
582
0
    switch (a->type) {
583
0
    case X509_LU_NONE:
584
0
        break;
585
0
    case X509_LU_X509:
586
0
        return X509_up_ref(a->data.x509);
587
0
    case X509_LU_CRL:
588
0
        return X509_CRL_up_ref(a->data.crl);
589
0
    }
590
0
    return 1;
591
0
}
592
593
X509 *X509_OBJECT_get0_X509(const X509_OBJECT *a)
594
0
{
595
0
    if (a == NULL || a->type != X509_LU_X509)
596
0
        return NULL;
597
0
    return a->data.x509;
598
0
}
599
600
X509_CRL *X509_OBJECT_get0_X509_CRL(const X509_OBJECT *a)
601
0
{
602
0
    if (a == NULL || a->type != X509_LU_CRL)
603
0
        return NULL;
604
0
    return a->data.crl;
605
0
}
606
607
X509_LOOKUP_TYPE X509_OBJECT_get_type(const X509_OBJECT *a)
608
0
{
609
0
    return a->type;
610
0
}
611
612
X509_OBJECT *X509_OBJECT_new(void)
613
0
{
614
0
    X509_OBJECT *ret = OPENSSL_zalloc(sizeof(*ret));
615
616
0
    if (ret == NULL)
617
0
        return NULL;
618
0
    ret->type = X509_LU_NONE;
619
0
    return ret;
620
0
}
621
622
static void x509_object_free_internal(X509_OBJECT *a)
623
0
{
624
0
    if (a == NULL)
625
0
        return;
626
0
    switch (a->type) {
627
0
    case X509_LU_NONE:
628
0
        break;
629
0
    case X509_LU_X509:
630
0
        X509_free(a->data.x509);
631
0
        break;
632
0
    case X509_LU_CRL:
633
0
        X509_CRL_free(a->data.crl);
634
0
        break;
635
0
    }
636
0
}
637
638
int X509_OBJECT_set1_X509(X509_OBJECT *a, X509 *obj)
639
0
{
640
0
    if (a == NULL || !X509_up_ref(obj))
641
0
        return 0;
642
643
0
    x509_object_free_internal(a);
644
0
    a->type = X509_LU_X509;
645
0
    a->data.x509 = obj;
646
0
    return 1;
647
0
}
648
649
int X509_OBJECT_set1_X509_CRL(X509_OBJECT *a, X509_CRL *obj)
650
0
{
651
0
    if (a == NULL || !X509_CRL_up_ref(obj))
652
0
        return 0;
653
654
0
    x509_object_free_internal(a);
655
0
    a->type = X509_LU_CRL;
656
0
    a->data.crl = obj;
657
0
    return 1;
658
0
}
659
660
void X509_OBJECT_free(X509_OBJECT *a)
661
0
{
662
0
    x509_object_free_internal(a);
663
0
    OPENSSL_free(a);
664
0
}
665
666
/* Returns -1 if not found, but also on error */
667
static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type,
668
                               const X509_NAME *name, int *pnmatch)
669
0
{
670
0
    X509_OBJECT stmp;
671
0
    X509 x509_s;
672
0
    X509_CRL crl_s;
673
674
0
    stmp.type = type;
675
0
    switch (type) {
676
0
    case X509_LU_X509:
677
0
        stmp.data.x509 = &x509_s;
678
0
        x509_s.cert_info.subject = (X509_NAME *)name; /* won't modify it */
679
0
        break;
680
0
    case X509_LU_CRL:
681
0
        stmp.data.crl = &crl_s;
682
0
        crl_s.crl.issuer = (X509_NAME *)name; /* won't modify it */
683
0
        break;
684
0
    case X509_LU_NONE:
685
0
    default:
686
        /* abort(); */
687
0
        return -1;
688
0
    }
689
690
    /* Assumes h is locked for read if applicable */
691
0
    return sk_X509_OBJECT_find_all(h, &stmp, pnmatch);
692
0
}
693
694
/* Assumes h is locked for read if applicable */
695
int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type,
696
                               const X509_NAME *name)
697
0
{
698
0
    return x509_object_idx_cnt(h, type, name, NULL);
699
0
}
700
701
/* Assumes h is locked for read if applicable */
702
X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,
703
                                             X509_LOOKUP_TYPE type,
704
                                             const X509_NAME *name)
705
0
{
706
0
    int idx = X509_OBJECT_idx_by_subject(h, type, name);
707
708
0
    if (idx == -1)
709
0
        return NULL;
710
0
    return sk_X509_OBJECT_value(h, idx);
711
0
}
712
713
static X509_OBJECT *x509_object_dup(const X509_OBJECT *obj)
714
0
{
715
0
    X509_OBJECT *ret = X509_OBJECT_new();
716
0
    if (ret == NULL)
717
0
        return NULL;
718
719
0
    ret->type = obj->type;
720
0
    ret->data = obj->data;
721
0
    X509_OBJECT_up_ref_count(ret);
722
0
    return ret;
723
0
}
724
725
static int obj_ht_foreach_object(HT_VALUE *v, void *arg)
726
0
{
727
0
    STACK_OF(X509_OBJECT) **sk = arg;
728
0
    STACK_OF(X509_OBJECT) *objs = v->value;
729
0
    X509_OBJECT *dup, *obj;
730
0
    int i;
731
732
0
    for (i = 0; i < sk_X509_OBJECT_num(objs); i++) {
733
0
        obj = sk_X509_OBJECT_value(objs, i);
734
0
        dup = x509_object_dup(obj);
735
0
        if (dup == NULL)
736
0
            goto err;
737
0
        if (sk_X509_OBJECT_push(*sk, dup) == 0)
738
0
            goto err;
739
0
    }
740
741
0
    return 1;
742
743
0
 err:
744
0
    sk_X509_OBJECT_pop_free(*sk, X509_OBJECT_free);
745
0
    *sk = NULL;
746
747
0
    return 0;
748
0
}
749
750
#ifndef OPENSSL_NO_DEPRECATED_4_0
751
STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(const X509_STORE *xs)
752
0
{
753
0
    X509_STORE *store = (X509_STORE *)xs;
754
755
0
    if (xs->objs_ht != NULL) {
756
0
        ossl_ht_foreach_until(xs->objs_ht, obj_ht_foreach_object, &store->objs);
757
0
        ossl_ht_free(xs->objs_ht);
758
0
        store->objs_ht = NULL;
759
0
    }
760
761
0
    return xs->objs;
762
0
}
763
#endif
764
765
STACK_OF(X509_OBJECT) *X509_STORE_get1_objects(X509_STORE *store)
766
0
{
767
0
    STACK_OF(X509_OBJECT) *objs;
768
769
0
    if (store == NULL) {
770
0
        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
771
0
        return NULL;
772
0
    }
773
774
0
    if (!ossl_x509_store_read_lock(store))
775
0
        return NULL;
776
777
0
    if (store->objs_ht != NULL) {
778
0
        if ((objs = sk_X509_OBJECT_new(x509_object_cmp)) == NULL) {
779
0
            X509_STORE_unlock(store);
780
0
            return NULL;
781
0
        }
782
0
        ossl_ht_foreach_until(store->objs_ht, obj_ht_foreach_object, &objs);
783
0
    } else {
784
0
        objs = sk_X509_OBJECT_deep_copy(store->objs, x509_object_dup,
785
0
                                        X509_OBJECT_free);
786
0
    }
787
0
    X509_STORE_unlock(store);
788
789
0
    return objs;
790
0
}
791
792
STACK_OF(X509) *X509_STORE_get1_all_certs(X509_STORE *store)
793
0
{
794
0
    STACK_OF(X509) *sk = NULL;
795
796
0
    if (store == NULL) {
797
0
        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
798
0
        return NULL;
799
0
    }
800
0
    if ((sk = sk_X509_new_null()) == NULL)
801
0
        return NULL;
802
803
0
    if (!ossl_x509_store_read_lock(store))
804
0
        goto out_free;
805
806
0
    if (store->objs_ht != NULL) {
807
0
        ossl_ht_foreach_until(store->objs_ht, obj_ht_foreach_certs, &sk);
808
0
    } else {
809
0
        for (int i = 0; i < sk_X509_OBJECT_num(store->objs); i++) {
810
0
            X509 *cert = X509_OBJECT_get0_X509(sk_X509_OBJECT_value(store->objs, i));
811
812
0
            if (cert != NULL
813
0
                && !X509_add_cert(sk, cert, X509_ADD_FLAG_UP_REF))
814
0
                goto err;
815
0
        }
816
0
    }
817
0
    X509_STORE_unlock(store);
818
819
0
    return sk;
820
821
0
 err:
822
0
    X509_STORE_unlock(store);
823
0
 out_free:
824
0
    OSSL_STACK_OF_X509_free(sk);
825
0
    return NULL;
826
0
}
827
828
/*-
829
 * Collect from |ctx->store| all certs with subject matching |nm|.
830
 * Returns NULL on internal/fatal error, empty stack if not found.
831
 */
832
STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *ctx,
833
                                          const X509_NAME *nm)
834
0
{
835
0
    int i, idx = -1, cnt = 0;
836
0
    STACK_OF(X509) *sk = NULL;
837
0
    X509 *x;
838
0
    X509_OBJECT *obj;
839
0
    X509_STORE *store = ctx->store;
840
0
    STACK_OF(X509_OBJECT) *objs;
841
842
0
    if (store == NULL)
843
0
        return sk_X509_new_null();
844
845
0
    if (!ossl_x509_store_read_lock(store))
846
0
        return NULL;
847
848
0
    if (store->objs_ht != NULL) {
849
0
        objs = ossl_x509_store_ht_get_by_name(store, nm);
850
0
        if (objs != NULL)
851
0
            idx = x509_object_idx_cnt(objs, X509_LU_X509, nm, &cnt);
852
0
    } else {
853
0
        objs = store->objs;
854
0
        idx = x509_object_idx_cnt(objs, X509_LU_X509, nm, &cnt);
855
0
    }
856
0
    if (idx < 0 || objs == NULL) {
857
        /*
858
         * Nothing found in cache: do lookup to possibly add new objects to
859
         * cache
860
         */
861
0
        X509_STORE_unlock(store);
862
0
        i = ossl_x509_store_ctx_get_by_subject(ctx, X509_LU_X509, nm, NULL);
863
0
        if (i <= 0)
864
0
            return i < 0 ? NULL : sk_X509_new_null();
865
0
        if (!ossl_x509_store_read_lock(store))
866
0
            return NULL;
867
0
        if (store->objs_ht != NULL) {
868
0
            objs = ossl_x509_store_ht_get_by_name(store, nm);
869
0
            if (objs == NULL)
870
0
                goto end;
871
0
        } else {
872
0
            objs = store->objs;
873
0
        }
874
0
        idx = x509_object_idx_cnt(objs, X509_LU_X509, nm, &cnt);
875
0
    }
876
877
0
    sk = sk_X509_new_null();
878
0
    if (idx < 0 || sk == NULL)
879
0
        goto end;
880
0
    for (i = idx; i < sk_X509_OBJECT_num(objs); i++) {
881
0
        obj = sk_X509_OBJECT_value(objs, i);
882
0
        x = obj->data.x509;
883
0
        if (obj->type != X509_LU_X509)
884
0
            continue;
885
0
        if (X509_add_cert(sk, x, X509_ADD_FLAG_UP_REF) == 0) {
886
0
            X509_STORE_unlock(store);
887
0
            OSSL_STACK_OF_X509_free(sk);
888
0
            return NULL;
889
0
        }
890
0
    }
891
892
0
 end:
893
0
    X509_STORE_unlock(store);
894
0
    return sk;
895
0
}
896
897
/* Returns NULL on internal/fatal error, empty stack if not found */
898
STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(const X509_STORE_CTX *ctx,
899
                                             const X509_NAME *nm)
900
0
{
901
0
    int i = 1, idx, cnt = 0;
902
0
    STACK_OF(X509_CRL) *sk;
903
0
    X509_CRL *x;
904
0
    X509_OBJECT *obj;
905
0
    X509_STORE *store = ctx->store;
906
0
    STACK_OF(X509_OBJECT) *objs;
907
908
    /* Always do lookup to possibly add new CRLs to cache */
909
0
    i = ossl_x509_store_ctx_get_by_subject(ctx, X509_LU_CRL, nm, NULL);
910
0
    if (i < 0)
911
0
        return NULL;
912
0
    sk = sk_X509_CRL_new_null();
913
0
    if (i == 0)
914
0
        return sk;
915
0
    if (!ossl_x509_store_read_lock(store)) {
916
0
        sk_X509_CRL_free(sk);
917
0
        return NULL;
918
0
    }
919
0
    if (store->objs_ht) {
920
0
        objs = ossl_x509_store_ht_get_by_name(store, nm);
921
0
        if (objs == NULL)
922
0
            goto end;
923
0
    } else {
924
0
        objs = store->objs;
925
0
    }
926
0
    idx = x509_object_idx_cnt(objs, X509_LU_CRL, nm, &cnt);
927
0
    if (idx < 0)
928
0
        goto end;
929
930
0
    for (i = idx; i < sk_X509_OBJECT_num(objs); i++) {
931
0
        obj = sk_X509_OBJECT_value(objs, i);
932
0
        x = obj->data.crl;
933
0
        if (obj->type != X509_LU_CRL)
934
0
            continue;
935
0
        if (!X509_CRL_up_ref(x)) {
936
0
            X509_STORE_unlock(store);
937
0
            sk_X509_CRL_pop_free(sk, X509_CRL_free);
938
0
            return NULL;
939
0
        }
940
0
        if (!sk_X509_CRL_push(sk, x)) {
941
0
            X509_STORE_unlock(store);
942
0
            X509_CRL_free(x);
943
0
            sk_X509_CRL_pop_free(sk, X509_CRL_free);
944
0
            return NULL;
945
0
        }
946
0
    }
947
0
 end:
948
0
    X509_STORE_unlock(store);
949
0
    return sk;
950
0
}
951
952
X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h,
953
                                        X509_OBJECT *x)
954
0
{
955
0
    int idx, i, num;
956
0
    X509_OBJECT *obj;
957
958
0
    idx = sk_X509_OBJECT_find(h, x);
959
0
    if (idx < 0)
960
0
        return NULL;
961
0
    if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL))
962
0
        return sk_X509_OBJECT_value(h, idx);
963
0
    for (i = idx, num = sk_X509_OBJECT_num(h); i < num; i++) {
964
0
        obj = sk_X509_OBJECT_value(h, i);
965
0
        if (x509_object_cmp((const X509_OBJECT **)&obj,
966
0
                            (const X509_OBJECT **)&x))
967
0
            return NULL;
968
0
        if (x->type == X509_LU_X509) {
969
0
            if (!X509_cmp(obj->data.x509, x->data.x509))
970
0
                return obj;
971
0
        } else if (x->type == X509_LU_CRL) {
972
0
            if (X509_CRL_match(obj->data.crl, x->data.crl) == 0)
973
0
                return obj;
974
0
        } else {
975
0
            return obj;
976
0
        }
977
0
    }
978
0
    return NULL;
979
0
}
980
981
int X509_STORE_set_flags(X509_STORE *xs, unsigned long flags)
982
0
{
983
0
    return X509_VERIFY_PARAM_set_flags(xs->param, flags);
984
0
}
985
986
int X509_STORE_set_depth(X509_STORE *xs, int depth)
987
0
{
988
0
    X509_VERIFY_PARAM_set_depth(xs->param, depth);
989
0
    return 1;
990
0
}
991
992
int X509_STORE_set_purpose(X509_STORE *xs, int purpose)
993
0
{
994
0
    return X509_VERIFY_PARAM_set_purpose(xs->param, purpose);
995
0
}
996
997
int X509_STORE_set_trust(X509_STORE *xs, int trust)
998
0
{
999
0
    return X509_VERIFY_PARAM_set_trust(xs->param, trust);
1000
0
}
1001
1002
int X509_STORE_set1_param(X509_STORE *xs, const X509_VERIFY_PARAM *param)
1003
0
{
1004
0
    return X509_VERIFY_PARAM_set1(xs->param, param);
1005
0
}
1006
1007
X509_VERIFY_PARAM *X509_STORE_get0_param(const X509_STORE *xs)
1008
0
{
1009
0
    return xs->param;
1010
0
}
1011
1012
void X509_STORE_set_verify(X509_STORE *xs, X509_STORE_CTX_verify_fn verify)
1013
0
{
1014
0
    xs->verify = verify;
1015
0
}
1016
1017
X509_STORE_CTX_verify_fn X509_STORE_get_verify(const X509_STORE *xs)
1018
0
{
1019
0
    return xs->verify;
1020
0
}
1021
1022
void X509_STORE_set_verify_cb(X509_STORE *xs,
1023
                              X509_STORE_CTX_verify_cb verify_cb)
1024
0
{
1025
0
    xs->verify_cb = verify_cb;
1026
0
}
1027
1028
X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(const X509_STORE *xs)
1029
0
{
1030
0
    return xs->verify_cb;
1031
0
}
1032
1033
void X509_STORE_set_get_issuer(X509_STORE *xs,
1034
                               X509_STORE_CTX_get_issuer_fn get_issuer)
1035
0
{
1036
0
    xs->get_issuer = get_issuer;
1037
0
}
1038
1039
X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(const X509_STORE *xs)
1040
0
{
1041
0
    return xs->get_issuer;
1042
0
}
1043
1044
void X509_STORE_set_check_issued(X509_STORE *xs,
1045
                                 X509_STORE_CTX_check_issued_fn check_issued)
1046
0
{
1047
0
    xs->check_issued = check_issued;
1048
0
}
1049
1050
X509_STORE_CTX_check_issued_fn X509_STORE_get_check_issued(const X509_STORE *xs)
1051
0
{
1052
0
    return xs->check_issued;
1053
0
}
1054
1055
void X509_STORE_set_check_revocation(X509_STORE *xs,
1056
                                     X509_STORE_CTX_check_revocation_fn cb)
1057
0
{
1058
0
    xs->check_revocation = cb;
1059
0
}
1060
1061
X509_STORE_CTX_check_revocation_fn X509_STORE_get_check_revocation(const X509_STORE *xs)
1062
0
{
1063
0
    return xs->check_revocation;
1064
0
}
1065
1066
void X509_STORE_set_get_crl(X509_STORE *xs,
1067
                            X509_STORE_CTX_get_crl_fn get_crl)
1068
0
{
1069
0
    xs->get_crl = get_crl;
1070
0
}
1071
1072
X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(const X509_STORE *xs)
1073
0
{
1074
0
    return xs->get_crl;
1075
0
}
1076
1077
void X509_STORE_set_check_crl(X509_STORE *xs,
1078
                              X509_STORE_CTX_check_crl_fn check_crl)
1079
0
{
1080
0
    xs->check_crl = check_crl;
1081
0
}
1082
1083
X509_STORE_CTX_check_crl_fn X509_STORE_get_check_crl(const X509_STORE *xs)
1084
0
{
1085
0
    return xs->check_crl;
1086
0
}
1087
1088
void X509_STORE_set_cert_crl(X509_STORE *xs,
1089
                             X509_STORE_CTX_cert_crl_fn cert_crl)
1090
0
{
1091
0
    xs->cert_crl = cert_crl;
1092
0
}
1093
1094
X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(const X509_STORE *xs)
1095
0
{
1096
0
    return xs->cert_crl;
1097
0
}
1098
1099
void X509_STORE_set_check_policy(X509_STORE *xs,
1100
                                 X509_STORE_CTX_check_policy_fn check_policy)
1101
0
{
1102
0
    xs->check_policy = check_policy;
1103
0
}
1104
1105
X509_STORE_CTX_check_policy_fn X509_STORE_get_check_policy(const X509_STORE *xs)
1106
0
{
1107
0
    return xs->check_policy;
1108
0
}
1109
1110
void X509_STORE_set_lookup_certs(X509_STORE *xs,
1111
                                 X509_STORE_CTX_lookup_certs_fn lookup_certs)
1112
0
{
1113
0
    xs->lookup_certs = lookup_certs;
1114
0
}
1115
1116
X509_STORE_CTX_lookup_certs_fn X509_STORE_get_lookup_certs(const X509_STORE *xs)
1117
0
{
1118
0
    return xs->lookup_certs;
1119
0
}
1120
1121
void X509_STORE_set_lookup_crls(X509_STORE *xs,
1122
                                X509_STORE_CTX_lookup_crls_fn lookup_crls)
1123
0
{
1124
0
    xs->lookup_crls = lookup_crls;
1125
0
}
1126
1127
X509_STORE_CTX_lookup_crls_fn X509_STORE_get_lookup_crls(const X509_STORE *xs)
1128
0
{
1129
0
    return xs->lookup_crls;
1130
0
}
1131
1132
void X509_STORE_set_cleanup(X509_STORE *xs,
1133
                            X509_STORE_CTX_cleanup_fn cleanup)
1134
0
{
1135
0
    xs->cleanup = cleanup;
1136
0
}
1137
1138
X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(const X509_STORE *xs)
1139
0
{
1140
0
    return xs->cleanup;
1141
0
}
1142
1143
int X509_STORE_set_ex_data(X509_STORE *xs, int idx, void *data)
1144
0
{
1145
0
    return CRYPTO_set_ex_data(&xs->ex_data, idx, data);
1146
0
}
1147
1148
void *X509_STORE_get_ex_data(const X509_STORE *xs, int idx)
1149
0
{
1150
0
    return CRYPTO_get_ex_data(&xs->ex_data, idx);
1151
0
}
1152
1153
X509_STORE *X509_STORE_CTX_get0_store(const X509_STORE_CTX *ctx)
1154
0
{
1155
0
    return ctx->store;
1156
0
}