Coverage Report

Created: 2026-09-12 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl36/crypto/x509/v3_crld.c
Line
Count
Source
1
/*
2
 * Copyright 1999-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 <openssl/conf.h>
13
#include <openssl/asn1.h>
14
#include <openssl/asn1t.h>
15
#include <openssl/x509v3.h>
16
17
#include "crypto/x509.h"
18
#include "ext_dat.h"
19
#include "x509_local.h"
20
21
static void *v2i_crld(const X509V3_EXT_METHOD *method,
22
    X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
23
static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
24
    int indent);
25
26
const X509V3_EXT_METHOD ossl_v3_crld = {
27
    NID_crl_distribution_points, 0, ASN1_ITEM_ref(CRL_DIST_POINTS),
28
    0, 0, 0, 0,
29
    0, 0,
30
    0,
31
    v2i_crld,
32
    i2r_crldp, 0,
33
    NULL
34
};
35
36
const X509V3_EXT_METHOD ossl_v3_freshest_crl = {
37
    NID_freshest_crl, 0, ASN1_ITEM_ref(CRL_DIST_POINTS),
38
    0, 0, 0, 0,
39
    0, 0,
40
    0,
41
    v2i_crld,
42
    i2r_crldp, 0,
43
    NULL
44
};
45
46
static STACK_OF(GENERAL_NAME) *gnames_from_sectname(X509V3_CTX *ctx,
47
    char *sect)
48
69
{
49
69
    STACK_OF(CONF_VALUE) *gnsect;
50
69
    STACK_OF(GENERAL_NAME) *gens;
51
69
    if (*sect == '@')
52
9
        gnsect = X509V3_get_section(ctx, sect + 1);
53
60
    else
54
60
        gnsect = X509V3_parse_list(sect);
55
69
    if (!gnsect) {
56
9
        ERR_raise(ERR_LIB_X509V3, X509V3_R_SECTION_NOT_FOUND);
57
9
        return NULL;
58
9
    }
59
60
    gens = v2i_GENERAL_NAMES(NULL, ctx, gnsect);
60
60
    if (*sect == '@')
61
7
        X509V3_section_free(ctx, gnsect);
62
53
    else
63
53
        sk_CONF_VALUE_pop_free(gnsect, X509V3_conf_free);
64
60
    return gens;
65
69
}
66
67
static int set_dist_point_name(DIST_POINT_NAME **pdp, X509V3_CTX *ctx,
68
    CONF_VALUE *cnf)
69
4.96k
{
70
4.96k
    STACK_OF(GENERAL_NAME) *fnm = NULL;
71
4.96k
    STACK_OF(X509_NAME_ENTRY) *rnm = NULL;
72
73
4.96k
    if (cnf->value == NULL) {
74
3
        ERR_raise(ERR_LIB_X509V3, X509V3_R_MISSING_VALUE);
75
3
        goto err;
76
3
    }
77
78
4.95k
    if (HAS_PREFIX(cnf->name, "fullname")) {
79
66
        fnm = gnames_from_sectname(ctx, cnf->value);
80
66
        if (!fnm)
81
28
            goto err;
82
4.89k
    } else if (strcmp(cnf->name, "relativename") == 0) {
83
15
        int ret;
84
15
        STACK_OF(CONF_VALUE) *dnsect;
85
15
        X509_NAME *nm;
86
15
        nm = X509_NAME_new();
87
15
        if (nm == NULL)
88
0
            return -1;
89
15
        dnsect = X509V3_get_section(ctx, cnf->value);
90
15
        if (!dnsect) {
91
3
            X509_NAME_free(nm);
92
3
            ERR_raise(ERR_LIB_X509V3, X509V3_R_SECTION_NOT_FOUND);
93
3
            return -1;
94
3
        }
95
12
        ret = X509V3_NAME_from_section(nm, dnsect, MBSTRING_ASC);
96
12
        X509V3_section_free(ctx, dnsect);
97
12
        rnm = nm->entries;
98
12
        nm->entries = NULL;
99
12
        X509_NAME_free(nm);
100
12
        if (!ret || sk_X509_NAME_ENTRY_num(rnm) <= 0)
101
6
            goto err;
102
        /*
103
         * Since its a name fragment can't have more than one RDNSequence
104
         */
105
6
        if (sk_X509_NAME_ENTRY_value(rnm,
106
6
                sk_X509_NAME_ENTRY_num(rnm) - 1)
107
6
                ->set) {
108
3
            ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_MULTIPLE_RDNS);
109
3
            goto err;
110
3
        }
111
6
    } else
112
4.87k
        return 0;
113
114
41
    if (*pdp) {
115
5
        ERR_raise(ERR_LIB_X509V3, X509V3_R_DISTPOINT_ALREADY_SET);
116
5
        goto err;
117
5
    }
118
119
36
    *pdp = DIST_POINT_NAME_new();
120
36
    if (*pdp == NULL)
121
0
        goto err;
122
36
    if (fnm) {
123
33
        (*pdp)->type = 0;
124
33
        (*pdp)->name.fullname = fnm;
125
33
    } else {
126
3
        (*pdp)->type = 1;
127
3
        (*pdp)->name.relativename = rnm;
128
3
    }
129
130
36
    return 1;
131
132
45
err:
133
45
    sk_GENERAL_NAME_pop_free(fnm, GENERAL_NAME_free);
134
45
    sk_X509_NAME_ENTRY_pop_free(rnm, X509_NAME_ENTRY_free);
135
45
    return -1;
136
36
}
137
138
static const BIT_STRING_BITNAME reason_flags[] = {
139
    { 0, "Unused", "unused" },
140
    { 1, "Key Compromise", "keyCompromise" },
141
    { 2, "CA Compromise", "CACompromise" },
142
    { 3, "Affiliation Changed", "affiliationChanged" },
143
    { 4, "Superseded", "superseded" },
144
    { 5, "Cessation Of Operation", "cessationOfOperation" },
145
    { 6, "Certificate Hold", "certificateHold" },
146
    { 7, "Privilege Withdrawn", "privilegeWithdrawn" },
147
    { 8, "AA Compromise", "AACompromise" },
148
    { -1, NULL, NULL }
149
};
150
151
static int set_reasons(ASN1_BIT_STRING **preas, char *value)
152
212
{
153
212
    STACK_OF(CONF_VALUE) *rsk = NULL;
154
212
    const BIT_STRING_BITNAME *pbn;
155
212
    const char *bnam;
156
212
    int i, ret = 0;
157
212
    rsk = X509V3_parse_list(value);
158
212
    if (rsk == NULL)
159
25
        return 0;
160
187
    if (*preas != NULL)
161
0
        goto err;
162
209
    for (i = 0; i < sk_CONF_VALUE_num(rsk); i++) {
163
196
        bnam = sk_CONF_VALUE_value(rsk, i)->name;
164
196
        if (*preas == NULL) {
165
187
            *preas = ASN1_BIT_STRING_new();
166
187
            if (*preas == NULL)
167
0
                goto err;
168
187
        }
169
1.84k
        for (pbn = reason_flags; pbn->lname; pbn++) {
170
1.67k
            if (strcmp(pbn->sname, bnam) == 0) {
171
22
                if (!ASN1_BIT_STRING_set_bit(*preas, pbn->bitnum, 1))
172
0
                    goto err;
173
22
                break;
174
22
            }
175
1.67k
        }
176
196
        if (pbn->lname == NULL)
177
174
            goto err;
178
196
    }
179
13
    ret = 1;
180
181
187
err:
182
187
    sk_CONF_VALUE_pop_free(rsk, X509V3_conf_free);
183
187
    return ret;
184
13
}
185
186
static int print_reasons(BIO *out, const char *rname,
187
    ASN1_BIT_STRING *rflags, int indent)
188
49.5k
{
189
49.5k
    int first = 1;
190
49.5k
    const BIT_STRING_BITNAME *pbn;
191
49.5k
    BIO_printf(out, "%*s%s:\n%*s", indent, "", rname, indent + 2, "");
192
495k
    for (pbn = reason_flags; pbn->lname; pbn++) {
193
446k
        if (ASN1_BIT_STRING_get_bit(rflags, pbn->bitnum)) {
194
132k
            if (first)
195
30.5k
                first = 0;
196
101k
            else
197
101k
                BIO_puts(out, ", ");
198
132k
            BIO_puts(out, pbn->lname);
199
132k
        }
200
446k
    }
201
49.5k
    if (first)
202
18.9k
        BIO_puts(out, "<EMPTY>\n");
203
30.5k
    else
204
30.5k
        BIO_puts(out, "\n");
205
49.5k
    return 1;
206
49.5k
}
207
208
static DIST_POINT *crldp_from_section(X509V3_CTX *ctx,
209
    STACK_OF(CONF_VALUE) *nval)
210
265
{
211
265
    int i;
212
265
    CONF_VALUE *cnf;
213
265
    DIST_POINT *point = DIST_POINT_new();
214
215
265
    if (point == NULL)
216
0
        goto err;
217
1.46k
    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
218
1.32k
        int ret;
219
1.32k
        cnf = sk_CONF_VALUE_value(nval, i);
220
1.32k
        ret = set_dist_point_name(&point->distpoint, ctx, cnf);
221
1.32k
        if (ret > 0)
222
18
            continue;
223
1.30k
        if (ret < 0)
224
29
            goto err;
225
1.27k
        if (strcmp(cnf->name, "reasons") == 0) {
226
92
            if (!set_reasons(&point->reasons, cnf->value))
227
85
                goto err;
228
1.18k
        } else if (strcmp(cnf->name, "CRLissuer") == 0) {
229
3
            point->CRLissuer = gnames_from_sectname(ctx, cnf->value);
230
3
            if (point->CRLissuer == NULL)
231
3
                goto err;
232
3
        }
233
1.27k
    }
234
235
148
    return point;
236
237
117
err:
238
117
    DIST_POINT_free(point);
239
117
    return NULL;
240
265
}
241
242
static void *v2i_crld(const X509V3_EXT_METHOD *method,
243
    X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
244
1.43k
{
245
1.43k
    STACK_OF(DIST_POINT) *crld;
246
1.43k
    GENERAL_NAMES *gens = NULL;
247
1.43k
    GENERAL_NAME *gen = NULL;
248
1.43k
    CONF_VALUE *cnf;
249
1.43k
    const int num = sk_CONF_VALUE_num(nval);
250
1.43k
    int i;
251
252
1.43k
    crld = sk_DIST_POINT_new_reserve(NULL, num);
253
1.43k
    if (crld == NULL) {
254
0
        ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB);
255
0
        goto err;
256
0
    }
257
36.0k
    for (i = 0; i < num; i++) {
258
34.9k
        DIST_POINT *point;
259
260
34.9k
        cnf = sk_CONF_VALUE_value(nval, i);
261
34.9k
        if (cnf->value == NULL) {
262
314
            STACK_OF(CONF_VALUE) *dpsect;
263
314
            dpsect = X509V3_get_section(ctx, cnf->name);
264
314
            if (!dpsect)
265
49
                goto err;
266
265
            point = crldp_from_section(ctx, dpsect);
267
265
            X509V3_section_free(ctx, dpsect);
268
265
            if (point == NULL)
269
117
                goto err;
270
148
            sk_DIST_POINT_push(crld, point); /* no failure as it was reserved */
271
34.6k
        } else {
272
34.6k
            if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL)
273
179
                goto err;
274
34.4k
            if ((gens = GENERAL_NAMES_new()) == NULL) {
275
0
                ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB);
276
0
                goto err;
277
0
            }
278
34.4k
            if (!sk_GENERAL_NAME_push(gens, gen)) {
279
0
                ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB);
280
0
                goto err;
281
0
            }
282
34.4k
            gen = NULL;
283
34.4k
            if ((point = DIST_POINT_new()) == NULL) {
284
0
                ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB);
285
0
                goto err;
286
0
            }
287
34.4k
            sk_DIST_POINT_push(crld, point); /* no failure as it was reserved */
288
34.4k
            if ((point->distpoint = DIST_POINT_NAME_new()) == NULL) {
289
0
                ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB);
290
0
                goto err;
291
0
            }
292
34.4k
            point->distpoint->name.fullname = gens;
293
34.4k
            point->distpoint->type = 0;
294
34.4k
            gens = NULL;
295
34.4k
        }
296
34.9k
    }
297
1.09k
    return crld;
298
299
345
err:
300
345
    GENERAL_NAME_free(gen);
301
345
    GENERAL_NAMES_free(gens);
302
345
    sk_DIST_POINT_pop_free(crld, DIST_POINT_free);
303
345
    return NULL;
304
1.43k
}
305
306
static int dpn_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
307
    void *exarg)
308
1.44M
{
309
1.44M
    DIST_POINT_NAME *dpn = (DIST_POINT_NAME *)*pval;
310
311
1.44M
    switch (operation) {
312
246k
    case ASN1_OP_NEW_POST:
313
246k
        dpn->dpname = NULL;
314
246k
        break;
315
316
246k
    case ASN1_OP_FREE_POST:
317
246k
        X509_NAME_free(dpn->dpname);
318
246k
        break;
319
1.44M
    }
320
1.44M
    return 1;
321
1.44M
}
322
323
ASN1_CHOICE_cb(DIST_POINT_NAME, dpn_cb) = {
324
    ASN1_IMP_SEQUENCE_OF(DIST_POINT_NAME, name.fullname, GENERAL_NAME, 0),
325
    ASN1_IMP_SET_OF(DIST_POINT_NAME, name.relativename, X509_NAME_ENTRY, 1)
326
3.03M
} ASN1_CHOICE_END_cb(DIST_POINT_NAME, DIST_POINT_NAME, type)
327
328
IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT_NAME)
329
IMPLEMENT_ASN1_DUP_FUNCTION(DIST_POINT_NAME)
330
331
ASN1_SEQUENCE(DIST_POINT) = {
332
    ASN1_EXP_OPT(DIST_POINT, distpoint, DIST_POINT_NAME, 0),
333
    ASN1_IMP_OPT(DIST_POINT, reasons, ASN1_BIT_STRING, 1),
334
    ASN1_IMP_SEQUENCE_OF_OPT(DIST_POINT, CRLissuer, GENERAL_NAME, 2)
335
983k
} ASN1_SEQUENCE_END(DIST_POINT)
336
983k
337
983k
IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT)
338
983k
339
983k
ASN1_ITEM_TEMPLATE(CRL_DIST_POINTS) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CRLDistributionPoints, DIST_POINT)
340
1.86M
ASN1_ITEM_TEMPLATE_END(CRL_DIST_POINTS)
341
342
IMPLEMENT_ASN1_FUNCTIONS(CRL_DIST_POINTS)
343
344
ASN1_SEQUENCE(ISSUING_DIST_POINT) = {
345
    ASN1_EXP_OPT(ISSUING_DIST_POINT, distpoint, DIST_POINT_NAME, 0),
346
    ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyuser, ASN1_FBOOLEAN, 1),
347
    ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyCA, ASN1_FBOOLEAN, 2),
348
    ASN1_IMP_OPT(ISSUING_DIST_POINT, onlysomereasons, ASN1_BIT_STRING, 3),
349
    ASN1_IMP_OPT(ISSUING_DIST_POINT, indirectCRL, ASN1_FBOOLEAN, 4),
350
    ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyattr, ASN1_FBOOLEAN, 5)
351
869k
} ASN1_SEQUENCE_END(ISSUING_DIST_POINT)
352
869k
353
869k
IMPLEMENT_ASN1_FUNCTIONS(ISSUING_DIST_POINT)
354
869k
355
869k
static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out,
356
869k
    int indent);
357
869k
static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
358
869k
    STACK_OF(CONF_VALUE) *nval);
359
869k
360
869k
const X509V3_EXT_METHOD ossl_v3_idp = {
361
869k
    NID_issuing_distribution_point, X509V3_EXT_MULTILINE,
362
869k
    ASN1_ITEM_ref(ISSUING_DIST_POINT),
363
869k
    0, 0, 0, 0,
364
869k
    0, 0,
365
869k
    0,
366
869k
    v2i_idp,
367
869k
    i2r_idp, 0,
368
869k
    NULL
369
869k
};
370
869k
371
869k
static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
372
869k
    STACK_OF(CONF_VALUE) *nval)
373
869k
{
374
139
    ISSUING_DIST_POINT *idp = NULL;
375
139
    CONF_VALUE *cnf;
376
139
    char *name, *val;
377
139
    int i, ret;
378
139
    idp = ISSUING_DIST_POINT_new();
379
139
    if (idp == NULL) {
380
0
        ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB);
381
0
        goto err;
382
0
    }
383
139
    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
384
139
        cnf = sk_CONF_VALUE_value(nval, i);
385
139
        name = cnf->name;
386
139
        val = cnf->value;
387
139
        ret = set_dist_point_name(&idp->distpoint, ctx, cnf);
388
139
        if (ret > 0)
389
0
            continue;
390
139
        if (ret < 0)
391
5
            goto err;
392
134
        if (strcmp(name, "onlyuser") == 0) {
393
2
            if (!X509V3_get_value_bool(cnf, &idp->onlyuser))
394
2
                goto err;
395
132
        } else if (strcmp(name, "onlyCA") == 0) {
396
0
            if (!X509V3_get_value_bool(cnf, &idp->onlyCA))
397
0
                goto err;
398
132
        } else if (strcmp(name, "onlyAA") == 0) {
399
0
            if (!X509V3_get_value_bool(cnf, &idp->onlyattr))
400
0
                goto err;
401
132
        } else if (strcmp(name, "indirectCRL") == 0) {
402
0
            if (!X509V3_get_value_bool(cnf, &idp->indirectCRL))
403
0
                goto err;
404
132
        } else if (strcmp(name, "onlysomereasons") == 0) {
405
0
            if (!set_reasons(&idp->onlysomereasons, val))
406
0
                goto err;
407
132
        } else {
408
132
            ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_NAME);
409
132
            X509V3_conf_add_error_name_value(cnf);
410
132
            goto err;
411
132
        }
412
134
    }
413
0
    return idp;
414
415
139
err:
416
139
    ISSUING_DIST_POINT_free(idp);
417
139
    return NULL;
418
139
}
419
420
static int print_distpoint(BIO *out, DIST_POINT_NAME *dpn, int indent)
421
55.7k
{
422
55.7k
    if (dpn->type == 0) {
423
13.2k
        BIO_printf(out, "%*sFull Name:\n", indent, "");
424
13.2k
        OSSL_GENERAL_NAMES_print(out, dpn->name.fullname, indent);
425
13.2k
        BIO_puts(out, "\n");
426
42.5k
    } else {
427
42.5k
        X509_NAME ntmp;
428
42.5k
        ntmp.entries = dpn->name.relativename;
429
42.5k
        BIO_printf(out, "%*sRelative Name:\n%*s", indent, "", indent + 2, "");
430
42.5k
        X509_NAME_print_ex(out, &ntmp, 0, XN_FLAG_ONELINE);
431
42.5k
        BIO_puts(out, "\n");
432
42.5k
    }
433
55.7k
    return 1;
434
55.7k
}
435
436
static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out,
437
    int indent)
438
119k
{
439
119k
    ISSUING_DIST_POINT *idp = pidp;
440
119k
    if (idp->distpoint)
441
46.8k
        print_distpoint(out, idp->distpoint, indent);
442
119k
    if (idp->onlyuser > 0)
443
18.3k
        BIO_printf(out, "%*sOnly User Certificates\n", indent, "");
444
119k
    if (idp->onlyCA > 0)
445
1.51k
        BIO_printf(out, "%*sOnly CA Certificates\n", indent, "");
446
119k
    if (idp->indirectCRL > 0)
447
12.1k
        BIO_printf(out, "%*sIndirect CRL\n", indent, "");
448
119k
    if (idp->onlysomereasons)
449
26.1k
        print_reasons(out, "Only Some Reasons", idp->onlysomereasons, indent);
450
119k
    if (idp->onlyattr > 0)
451
6.20k
        BIO_printf(out, "%*sOnly Attribute Certificates\n", indent, "");
452
119k
    if (!idp->distpoint && (idp->onlyuser <= 0) && (idp->onlyCA <= 0)
453
52.5k
        && (idp->indirectCRL <= 0) && !idp->onlysomereasons
454
14.3k
        && (idp->onlyattr <= 0))
455
8.12k
        BIO_printf(out, "%*s<EMPTY>\n", indent, "");
456
457
119k
    return 1;
458
119k
}
459
460
static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
461
    int indent)
462
60.6k
{
463
60.6k
    STACK_OF(DIST_POINT) *crld = pcrldp;
464
60.6k
    DIST_POINT *point;
465
60.6k
    int i;
466
174k
    for (i = 0; i < sk_DIST_POINT_num(crld); i++) {
467
113k
        if (i > 0)
468
61.6k
            BIO_puts(out, "\n");
469
113k
        point = sk_DIST_POINT_value(crld, i);
470
113k
        if (point->distpoint)
471
6.41k
            print_distpoint(out, point->distpoint, indent);
472
113k
        if (point->reasons)
473
22.1k
            print_reasons(out, "Reasons", point->reasons, indent);
474
113k
        if (point->CRLissuer) {
475
8.68k
            BIO_printf(out, "%*sCRL Issuer:\n", indent, "");
476
8.68k
            OSSL_GENERAL_NAMES_print(out, point->CRLissuer, indent);
477
8.68k
        }
478
113k
    }
479
60.6k
    return 1;
480
60.6k
}
481
482
static int i2r_crl_invdate(const X509V3_EXT_METHOD *method, void *date,
483
    BIO *out, int indent);
484
static int i2r_object(const X509V3_EXT_METHOD *method, void *obj, BIO *out,
485
    int indent);
486
487
const X509V3_EXT_METHOD ossl_v3_crl_invdate = {
488
    NID_invalidity_date, 0, ASN1_ITEM_ref(ASN1_GENERALIZEDTIME),
489
    0, 0, 0, 0,
490
    0, 0,
491
    0, 0,
492
    i2r_crl_invdate, 0,
493
    NULL
494
};
495
496
const X509V3_EXT_METHOD ossl_v3_crl_hold = {
497
    NID_hold_instruction_code, 0, ASN1_ITEM_ref(ASN1_OBJECT),
498
    0, 0, 0, 0,
499
    0, 0,
500
    0, 0,
501
    i2r_object, 0,
502
    NULL
503
};
504
505
static int i2r_crl_invdate(const X509V3_EXT_METHOD *method, void *date,
506
    BIO *bp, int ind)
507
32.5k
{
508
32.5k
    if (BIO_printf(bp, "%*s", ind, "") <= 0)
509
0
        return 0;
510
32.5k
    if (!ASN1_GENERALIZEDTIME_print(bp, date))
511
28.7k
        return 0;
512
3.82k
    return 1;
513
32.5k
}
514
515
static int i2r_object(const X509V3_EXT_METHOD *method, void *oid, BIO *bp,
516
    int ind)
517
2.37k
{
518
2.37k
    if (BIO_printf(bp, "%*s", ind, "") <= 0)
519
0
        return 0;
520
2.37k
    if (i2a_ASN1_OBJECT(bp, oid) <= 0)
521
0
        return 0;
522
2.37k
    return 1;
523
2.37k
}
524
525
/* Append any nameRelativeToCRLIssuer in dpn to iname, set in dpn->dpname */
526
int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, const X509_NAME *iname)
527
22.7k
{
528
22.7k
    int i;
529
22.7k
    STACK_OF(X509_NAME_ENTRY) *frag;
530
22.7k
    X509_NAME_ENTRY *ne;
531
532
22.7k
    if (dpn == NULL || dpn->type != 1)
533
11.8k
        return 1;
534
10.8k
    frag = dpn->name.relativename;
535
10.8k
    X509_NAME_free(dpn->dpname); /* just in case it was already set */
536
10.8k
    dpn->dpname = X509_NAME_dup(iname);
537
10.8k
    if (dpn->dpname == NULL)
538
0
        return 0;
539
24.0k
    for (i = 0; i < sk_X509_NAME_ENTRY_num(frag); i++) {
540
13.1k
        ne = sk_X509_NAME_ENTRY_value(frag, i);
541
13.1k
        if (!X509_NAME_add_entry(dpn->dpname, ne, -1, i ? 0 : 1))
542
0
            goto err;
543
13.1k
    }
544
    /* generate cached encoding of name */
545
10.8k
    if (i2d_X509_NAME(dpn->dpname, NULL) >= 0)
546
9.82k
        return 1;
547
548
1.06k
err:
549
1.06k
    X509_NAME_free(dpn->dpname);
550
1.06k
    dpn->dpname = NULL;
551
1.06k
    return 0;
552
10.8k
}
553
554
ASN1_SEQUENCE(OSSL_AA_DIST_POINT) = {
555
    ASN1_EXP_OPT(OSSL_AA_DIST_POINT, distpoint, DIST_POINT_NAME, 0),
556
    ASN1_IMP_OPT(OSSL_AA_DIST_POINT, reasons, ASN1_BIT_STRING, 1),
557
    ASN1_IMP_OPT(OSSL_AA_DIST_POINT, indirectCRL, ASN1_FBOOLEAN, 2),
558
    ASN1_IMP_OPT(OSSL_AA_DIST_POINT, containsUserAttributeCerts, ASN1_TBOOLEAN, 3),
559
    ASN1_IMP_OPT(OSSL_AA_DIST_POINT, containsAACerts, ASN1_TBOOLEAN, 4),
560
    ASN1_IMP_OPT(OSSL_AA_DIST_POINT, containsSOAPublicKeyCerts, ASN1_TBOOLEAN, 5)
561
43.7k
} ASN1_SEQUENCE_END(OSSL_AA_DIST_POINT)
562
43.7k
563
43.7k
IMPLEMENT_ASN1_FUNCTIONS(OSSL_AA_DIST_POINT)
564
43.7k
565
43.7k
static int print_boolean(BIO *out, ASN1_BOOLEAN b)
566
43.7k
{
567
37.9k
    return BIO_puts(out, b ? "TRUE" : "FALSE");
568
37.9k
}
569
570
static OSSL_AA_DIST_POINT *aaidp_from_section(X509V3_CTX *ctx,
571
    STACK_OF(CONF_VALUE) *nval)
572
638
{
573
638
    int i, ret;
574
638
    CONF_VALUE *cnf;
575
638
    OSSL_AA_DIST_POINT *point = OSSL_AA_DIST_POINT_new();
576
577
638
    if (point == NULL)
578
0
        goto err;
579
3.99k
    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
580
3.50k
        cnf = sk_CONF_VALUE_value(nval, i);
581
3.50k
        ret = set_dist_point_name(&point->distpoint, ctx, cnf);
582
3.50k
        if (ret > 0)
583
18
            continue;
584
3.48k
        if (ret < 0)
585
14
            goto err;
586
3.47k
        if (strcmp(cnf->name, "reasons") == 0) {
587
120
            if (!set_reasons(&point->reasons, cnf->value))
588
114
                goto err;
589
3.35k
        } else if (strcmp(cnf->name, "indirectCRL") == 0) {
590
16
            if (!X509V3_get_value_bool(cnf, &point->indirectCRL))
591
13
                goto err;
592
3.33k
        } else if (strcmp(cnf->name, "containsUserAttributeCerts") == 0) {
593
3
            if (!X509V3_get_value_bool(cnf, &point->containsUserAttributeCerts))
594
3
                goto err;
595
3.33k
        } else if (strcmp(cnf->name, "containsAACerts") == 0) {
596
5
            if (!X509V3_get_value_bool(cnf, &point->containsAACerts))
597
3
                goto err;
598
3.32k
        } else if (strcmp(cnf->name, "containsSOAPublicKeyCerts") == 0) {
599
6
            if (!X509V3_get_value_bool(cnf, &point->containsSOAPublicKeyCerts))
600
3
                goto err;
601
6
        }
602
3.47k
    }
603
604
488
    return point;
605
606
150
err:
607
150
    OSSL_AA_DIST_POINT_free(point);
608
150
    return NULL;
609
638
}
610
611
static void *v2i_aaidp(const X509V3_EXT_METHOD *method,
612
    X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
613
650
{
614
650
    GENERAL_NAMES *gens = NULL;
615
650
    GENERAL_NAME *gen = NULL;
616
650
    CONF_VALUE *cnf;
617
650
    OSSL_AA_DIST_POINT *point = NULL;
618
650
    STACK_OF(CONF_VALUE) *dpsect;
619
620
650
    cnf = sk_CONF_VALUE_value(nval, 0);
621
650
    if (cnf == NULL)
622
0
        return NULL;
623
650
    if (cnf->value == NULL) {
624
642
        dpsect = X509V3_get_section(ctx, cnf->name);
625
642
        if (dpsect == NULL)
626
4
            goto err;
627
638
        point = aaidp_from_section(ctx, dpsect);
628
638
        X509V3_section_free(ctx, dpsect);
629
638
        if (point == NULL)
630
150
            goto err;
631
638
    } else {
632
8
        if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL)
633
5
            goto err;
634
3
        if ((gens = GENERAL_NAMES_new()) == NULL) {
635
0
            ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB);
636
0
            goto err;
637
0
        }
638
3
        if (!sk_GENERAL_NAME_push(gens, gen)) {
639
0
            ERR_raise(ERR_LIB_X509V3, ERR_R_CRYPTO_LIB);
640
0
            goto err;
641
0
        }
642
3
        gen = NULL;
643
3
        if ((point = OSSL_AA_DIST_POINT_new()) == NULL) {
644
0
            ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB);
645
0
            goto err;
646
0
        }
647
3
        if ((point->distpoint = DIST_POINT_NAME_new()) == NULL) {
648
0
            ERR_raise(ERR_LIB_X509V3, ERR_R_ASN1_LIB);
649
0
            goto err;
650
0
        }
651
3
        point->distpoint->name.fullname = gens;
652
3
        point->distpoint->type = 0;
653
3
        gens = NULL;
654
3
    }
655
491
    return point;
656
657
159
err:
658
159
    OSSL_AA_DIST_POINT_free(point);
659
159
    GENERAL_NAME_free(gen);
660
159
    GENERAL_NAMES_free(gens);
661
159
    return NULL;
662
650
}
663
664
static int i2r_aaidp(const X509V3_EXT_METHOD *method, void *dp, BIO *out,
665
    int indent)
666
14.1k
{
667
14.1k
    OSSL_AA_DIST_POINT *pdp = dp;
668
669
14.1k
    if (pdp->distpoint)
670
2.50k
        if (print_distpoint(out, pdp->distpoint, indent) <= 0)
671
0
            return 0;
672
14.1k
    if (pdp->reasons)
673
1.33k
        if (print_reasons(out, "Reasons", pdp->reasons, indent) <= 0)
674
0
            return 0;
675
14.1k
    if (pdp->indirectCRL) {
676
705
        if (BIO_printf(out, "%*sIndirect CRL: ", indent, "") <= 0)
677
0
            return 0;
678
705
        if (print_boolean(out, pdp->indirectCRL) <= 0)
679
0
            return 0;
680
705
        if (BIO_puts(out, "\n") <= 0)
681
0
            return 0;
682
705
    }
683
14.1k
    if (pdp->containsUserAttributeCerts) {
684
13.4k
        if (BIO_printf(out, "%*sContains User Attribute Certificates: ", indent, "") <= 0)
685
0
            return 0;
686
13.4k
        if (print_boolean(out, pdp->containsUserAttributeCerts) <= 0)
687
0
            return 0;
688
13.4k
        if (BIO_puts(out, "\n") <= 0)
689
0
            return 0;
690
13.4k
    }
691
14.1k
    if (pdp->containsAACerts) {
692
12.6k
        if (BIO_printf(out, "%*sContains Attribute Authority (AA) Certificates: ",
693
12.6k
                indent, "")
694
12.6k
            <= 0)
695
0
            return 0;
696
12.6k
        if (print_boolean(out, pdp->containsAACerts) <= 0)
697
0
            return 0;
698
12.6k
        if (BIO_puts(out, "\n") <= 0)
699
0
            return 0;
700
12.6k
    }
701
14.1k
    if (pdp->containsSOAPublicKeyCerts) {
702
11.1k
        if (BIO_printf(out,
703
11.1k
                "%*sContains Source Of Authority (SOA) Public Key Certificates: ",
704
11.1k
                indent, "")
705
11.1k
            <= 0)
706
0
            return 0;
707
11.1k
        if (print_boolean(out, pdp->containsSOAPublicKeyCerts) <= 0)
708
0
            return 0;
709
11.1k
        if (BIO_puts(out, "\n") <= 0)
710
0
            return 0;
711
11.1k
    }
712
14.1k
    return 1;
713
14.1k
}
714
715
const X509V3_EXT_METHOD ossl_v3_aa_issuing_dist_point = {
716
    NID_id_aa_issuing_distribution_point, 0,
717
    ASN1_ITEM_ref(OSSL_AA_DIST_POINT),
718
    0, 0, 0, 0,
719
    0, 0,
720
    0,
721
    v2i_aaidp,
722
    i2r_aaidp, 0,
723
    NULL
724
};