Coverage Report

Created: 2026-10-16 07:07

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