xref: /third_party/openssl/crypto/x509/v3_asid.c (revision e1051a39)
1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci/*
11e1051a39Sopenharmony_ci * Implementation of RFC 3779 section 3.2.
12e1051a39Sopenharmony_ci */
13e1051a39Sopenharmony_ci
14e1051a39Sopenharmony_ci#include <assert.h>
15e1051a39Sopenharmony_ci#include <stdio.h>
16e1051a39Sopenharmony_ci#include <string.h>
17e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
18e1051a39Sopenharmony_ci#include <openssl/conf.h>
19e1051a39Sopenharmony_ci#include <openssl/asn1.h>
20e1051a39Sopenharmony_ci#include <openssl/asn1t.h>
21e1051a39Sopenharmony_ci#include <openssl/x509v3.h>
22e1051a39Sopenharmony_ci#include <openssl/x509.h>
23e1051a39Sopenharmony_ci#include "crypto/x509.h"
24e1051a39Sopenharmony_ci#include <openssl/bn.h>
25e1051a39Sopenharmony_ci#include "ext_dat.h"
26e1051a39Sopenharmony_ci#include "x509_local.h"
27e1051a39Sopenharmony_ci
28e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_RFC3779
29e1051a39Sopenharmony_ci
30e1051a39Sopenharmony_ci/*
31e1051a39Sopenharmony_ci * OpenSSL ASN.1 template translation of RFC 3779 3.2.3.
32e1051a39Sopenharmony_ci */
33e1051a39Sopenharmony_ci
34e1051a39Sopenharmony_ciASN1_SEQUENCE(ASRange) = {
35e1051a39Sopenharmony_ci  ASN1_SIMPLE(ASRange, min, ASN1_INTEGER),
36e1051a39Sopenharmony_ci  ASN1_SIMPLE(ASRange, max, ASN1_INTEGER)
37e1051a39Sopenharmony_ci} ASN1_SEQUENCE_END(ASRange)
38e1051a39Sopenharmony_ci
39e1051a39Sopenharmony_ciASN1_CHOICE(ASIdOrRange) = {
40e1051a39Sopenharmony_ci  ASN1_SIMPLE(ASIdOrRange, u.id,    ASN1_INTEGER),
41e1051a39Sopenharmony_ci  ASN1_SIMPLE(ASIdOrRange, u.range, ASRange)
42e1051a39Sopenharmony_ci} ASN1_CHOICE_END(ASIdOrRange)
43e1051a39Sopenharmony_ci
44e1051a39Sopenharmony_ciASN1_CHOICE(ASIdentifierChoice) = {
45e1051a39Sopenharmony_ci  ASN1_SIMPLE(ASIdentifierChoice,      u.inherit,       ASN1_NULL),
46e1051a39Sopenharmony_ci  ASN1_SEQUENCE_OF(ASIdentifierChoice, u.asIdsOrRanges, ASIdOrRange)
47e1051a39Sopenharmony_ci} ASN1_CHOICE_END(ASIdentifierChoice)
48e1051a39Sopenharmony_ci
49e1051a39Sopenharmony_ciASN1_SEQUENCE(ASIdentifiers) = {
50e1051a39Sopenharmony_ci  ASN1_EXP_OPT(ASIdentifiers, asnum, ASIdentifierChoice, 0),
51e1051a39Sopenharmony_ci  ASN1_EXP_OPT(ASIdentifiers, rdi,   ASIdentifierChoice, 1)
52e1051a39Sopenharmony_ci} ASN1_SEQUENCE_END(ASIdentifiers)
53e1051a39Sopenharmony_ci
54e1051a39Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(ASRange)
55e1051a39Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(ASIdOrRange)
56e1051a39Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(ASIdentifierChoice)
57e1051a39Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(ASIdentifiers)
58e1051a39Sopenharmony_ci
59e1051a39Sopenharmony_ci/*
60e1051a39Sopenharmony_ci * i2r method for an ASIdentifierChoice.
61e1051a39Sopenharmony_ci */
62e1051a39Sopenharmony_cistatic int i2r_ASIdentifierChoice(BIO *out,
63e1051a39Sopenharmony_ci                                  ASIdentifierChoice *choice,
64e1051a39Sopenharmony_ci                                  int indent, const char *msg)
65e1051a39Sopenharmony_ci{
66e1051a39Sopenharmony_ci    int i;
67e1051a39Sopenharmony_ci    char *s;
68e1051a39Sopenharmony_ci    if (choice == NULL)
69e1051a39Sopenharmony_ci        return 1;
70e1051a39Sopenharmony_ci    BIO_printf(out, "%*s%s:\n", indent, "", msg);
71e1051a39Sopenharmony_ci    switch (choice->type) {
72e1051a39Sopenharmony_ci    case ASIdentifierChoice_inherit:
73e1051a39Sopenharmony_ci        BIO_printf(out, "%*sinherit\n", indent + 2, "");
74e1051a39Sopenharmony_ci        break;
75e1051a39Sopenharmony_ci    case ASIdentifierChoice_asIdsOrRanges:
76e1051a39Sopenharmony_ci        for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges); i++) {
77e1051a39Sopenharmony_ci            ASIdOrRange *aor =
78e1051a39Sopenharmony_ci                sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
79e1051a39Sopenharmony_ci            switch (aor->type) {
80e1051a39Sopenharmony_ci            case ASIdOrRange_id:
81e1051a39Sopenharmony_ci                if ((s = i2s_ASN1_INTEGER(NULL, aor->u.id)) == NULL)
82e1051a39Sopenharmony_ci                    return 0;
83e1051a39Sopenharmony_ci                BIO_printf(out, "%*s%s\n", indent + 2, "", s);
84e1051a39Sopenharmony_ci                OPENSSL_free(s);
85e1051a39Sopenharmony_ci                break;
86e1051a39Sopenharmony_ci            case ASIdOrRange_range:
87e1051a39Sopenharmony_ci                if ((s = i2s_ASN1_INTEGER(NULL, aor->u.range->min)) == NULL)
88e1051a39Sopenharmony_ci                    return 0;
89e1051a39Sopenharmony_ci                BIO_printf(out, "%*s%s-", indent + 2, "", s);
90e1051a39Sopenharmony_ci                OPENSSL_free(s);
91e1051a39Sopenharmony_ci                if ((s = i2s_ASN1_INTEGER(NULL, aor->u.range->max)) == NULL)
92e1051a39Sopenharmony_ci                    return 0;
93e1051a39Sopenharmony_ci                BIO_printf(out, "%s\n", s);
94e1051a39Sopenharmony_ci                OPENSSL_free(s);
95e1051a39Sopenharmony_ci                break;
96e1051a39Sopenharmony_ci            default:
97e1051a39Sopenharmony_ci                return 0;
98e1051a39Sopenharmony_ci            }
99e1051a39Sopenharmony_ci        }
100e1051a39Sopenharmony_ci        break;
101e1051a39Sopenharmony_ci    default:
102e1051a39Sopenharmony_ci        return 0;
103e1051a39Sopenharmony_ci    }
104e1051a39Sopenharmony_ci    return 1;
105e1051a39Sopenharmony_ci}
106e1051a39Sopenharmony_ci
107e1051a39Sopenharmony_ci/*
108e1051a39Sopenharmony_ci * i2r method for an ASIdentifier extension.
109e1051a39Sopenharmony_ci */
110e1051a39Sopenharmony_cistatic int i2r_ASIdentifiers(const X509V3_EXT_METHOD *method,
111e1051a39Sopenharmony_ci                             void *ext, BIO *out, int indent)
112e1051a39Sopenharmony_ci{
113e1051a39Sopenharmony_ci    ASIdentifiers *asid = ext;
114e1051a39Sopenharmony_ci    return (i2r_ASIdentifierChoice(out, asid->asnum, indent,
115e1051a39Sopenharmony_ci                                   "Autonomous System Numbers") &&
116e1051a39Sopenharmony_ci            i2r_ASIdentifierChoice(out, asid->rdi, indent,
117e1051a39Sopenharmony_ci                                   "Routing Domain Identifiers"));
118e1051a39Sopenharmony_ci}
119e1051a39Sopenharmony_ci
120e1051a39Sopenharmony_ci/*
121e1051a39Sopenharmony_ci * Sort comparison function for a sequence of ASIdOrRange elements.
122e1051a39Sopenharmony_ci */
123e1051a39Sopenharmony_cistatic int ASIdOrRange_cmp(const ASIdOrRange *const *a_,
124e1051a39Sopenharmony_ci                           const ASIdOrRange *const *b_)
125e1051a39Sopenharmony_ci{
126e1051a39Sopenharmony_ci    const ASIdOrRange *a = *a_, *b = *b_;
127e1051a39Sopenharmony_ci
128e1051a39Sopenharmony_ci    assert((a->type == ASIdOrRange_id && a->u.id != NULL) ||
129e1051a39Sopenharmony_ci           (a->type == ASIdOrRange_range && a->u.range != NULL &&
130e1051a39Sopenharmony_ci            a->u.range->min != NULL && a->u.range->max != NULL));
131e1051a39Sopenharmony_ci
132e1051a39Sopenharmony_ci    assert((b->type == ASIdOrRange_id && b->u.id != NULL) ||
133e1051a39Sopenharmony_ci           (b->type == ASIdOrRange_range && b->u.range != NULL &&
134e1051a39Sopenharmony_ci            b->u.range->min != NULL && b->u.range->max != NULL));
135e1051a39Sopenharmony_ci
136e1051a39Sopenharmony_ci    if (a->type == ASIdOrRange_id && b->type == ASIdOrRange_id)
137e1051a39Sopenharmony_ci        return ASN1_INTEGER_cmp(a->u.id, b->u.id);
138e1051a39Sopenharmony_ci
139e1051a39Sopenharmony_ci    if (a->type == ASIdOrRange_range && b->type == ASIdOrRange_range) {
140e1051a39Sopenharmony_ci        int r = ASN1_INTEGER_cmp(a->u.range->min, b->u.range->min);
141e1051a39Sopenharmony_ci        return r != 0 ? r : ASN1_INTEGER_cmp(a->u.range->max,
142e1051a39Sopenharmony_ci                                             b->u.range->max);
143e1051a39Sopenharmony_ci    }
144e1051a39Sopenharmony_ci
145e1051a39Sopenharmony_ci    if (a->type == ASIdOrRange_id)
146e1051a39Sopenharmony_ci        return ASN1_INTEGER_cmp(a->u.id, b->u.range->min);
147e1051a39Sopenharmony_ci    else
148e1051a39Sopenharmony_ci        return ASN1_INTEGER_cmp(a->u.range->min, b->u.id);
149e1051a39Sopenharmony_ci}
150e1051a39Sopenharmony_ci
151e1051a39Sopenharmony_ci/*
152e1051a39Sopenharmony_ci * Add an inherit element.
153e1051a39Sopenharmony_ci */
154e1051a39Sopenharmony_ciint X509v3_asid_add_inherit(ASIdentifiers *asid, int which)
155e1051a39Sopenharmony_ci{
156e1051a39Sopenharmony_ci    ASIdentifierChoice **choice;
157e1051a39Sopenharmony_ci    if (asid == NULL)
158e1051a39Sopenharmony_ci        return 0;
159e1051a39Sopenharmony_ci    switch (which) {
160e1051a39Sopenharmony_ci    case V3_ASID_ASNUM:
161e1051a39Sopenharmony_ci        choice = &asid->asnum;
162e1051a39Sopenharmony_ci        break;
163e1051a39Sopenharmony_ci    case V3_ASID_RDI:
164e1051a39Sopenharmony_ci        choice = &asid->rdi;
165e1051a39Sopenharmony_ci        break;
166e1051a39Sopenharmony_ci    default:
167e1051a39Sopenharmony_ci        return 0;
168e1051a39Sopenharmony_ci    }
169e1051a39Sopenharmony_ci    if (*choice == NULL) {
170e1051a39Sopenharmony_ci        if ((*choice = ASIdentifierChoice_new()) == NULL)
171e1051a39Sopenharmony_ci            return 0;
172e1051a39Sopenharmony_ci        if (((*choice)->u.inherit = ASN1_NULL_new()) == NULL)
173e1051a39Sopenharmony_ci            return 0;
174e1051a39Sopenharmony_ci        (*choice)->type = ASIdentifierChoice_inherit;
175e1051a39Sopenharmony_ci    }
176e1051a39Sopenharmony_ci    return (*choice)->type == ASIdentifierChoice_inherit;
177e1051a39Sopenharmony_ci}
178e1051a39Sopenharmony_ci
179e1051a39Sopenharmony_ci/*
180e1051a39Sopenharmony_ci * Add an ID or range to an ASIdentifierChoice.
181e1051a39Sopenharmony_ci */
182e1051a39Sopenharmony_ciint X509v3_asid_add_id_or_range(ASIdentifiers *asid,
183e1051a39Sopenharmony_ci                                int which, ASN1_INTEGER *min, ASN1_INTEGER *max)
184e1051a39Sopenharmony_ci{
185e1051a39Sopenharmony_ci    ASIdentifierChoice **choice;
186e1051a39Sopenharmony_ci    ASIdOrRange *aor;
187e1051a39Sopenharmony_ci    if (asid == NULL)
188e1051a39Sopenharmony_ci        return 0;
189e1051a39Sopenharmony_ci    switch (which) {
190e1051a39Sopenharmony_ci    case V3_ASID_ASNUM:
191e1051a39Sopenharmony_ci        choice = &asid->asnum;
192e1051a39Sopenharmony_ci        break;
193e1051a39Sopenharmony_ci    case V3_ASID_RDI:
194e1051a39Sopenharmony_ci        choice = &asid->rdi;
195e1051a39Sopenharmony_ci        break;
196e1051a39Sopenharmony_ci    default:
197e1051a39Sopenharmony_ci        return 0;
198e1051a39Sopenharmony_ci    }
199e1051a39Sopenharmony_ci    if (*choice != NULL && (*choice)->type == ASIdentifierChoice_inherit)
200e1051a39Sopenharmony_ci        return 0;
201e1051a39Sopenharmony_ci    if (*choice == NULL) {
202e1051a39Sopenharmony_ci        if ((*choice = ASIdentifierChoice_new()) == NULL)
203e1051a39Sopenharmony_ci            return 0;
204e1051a39Sopenharmony_ci        (*choice)->u.asIdsOrRanges = sk_ASIdOrRange_new(ASIdOrRange_cmp);
205e1051a39Sopenharmony_ci        if ((*choice)->u.asIdsOrRanges == NULL)
206e1051a39Sopenharmony_ci            return 0;
207e1051a39Sopenharmony_ci        (*choice)->type = ASIdentifierChoice_asIdsOrRanges;
208e1051a39Sopenharmony_ci    }
209e1051a39Sopenharmony_ci    if ((aor = ASIdOrRange_new()) == NULL)
210e1051a39Sopenharmony_ci        return 0;
211e1051a39Sopenharmony_ci    if (max == NULL) {
212e1051a39Sopenharmony_ci        aor->type = ASIdOrRange_id;
213e1051a39Sopenharmony_ci        aor->u.id = min;
214e1051a39Sopenharmony_ci    } else {
215e1051a39Sopenharmony_ci        aor->type = ASIdOrRange_range;
216e1051a39Sopenharmony_ci        if ((aor->u.range = ASRange_new()) == NULL)
217e1051a39Sopenharmony_ci            goto err;
218e1051a39Sopenharmony_ci        ASN1_INTEGER_free(aor->u.range->min);
219e1051a39Sopenharmony_ci        aor->u.range->min = min;
220e1051a39Sopenharmony_ci        ASN1_INTEGER_free(aor->u.range->max);
221e1051a39Sopenharmony_ci        aor->u.range->max = max;
222e1051a39Sopenharmony_ci    }
223e1051a39Sopenharmony_ci    if (!(sk_ASIdOrRange_push((*choice)->u.asIdsOrRanges, aor)))
224e1051a39Sopenharmony_ci        goto err;
225e1051a39Sopenharmony_ci    return 1;
226e1051a39Sopenharmony_ci
227e1051a39Sopenharmony_ci err:
228e1051a39Sopenharmony_ci    ASIdOrRange_free(aor);
229e1051a39Sopenharmony_ci    return 0;
230e1051a39Sopenharmony_ci}
231e1051a39Sopenharmony_ci
232e1051a39Sopenharmony_ci/*
233e1051a39Sopenharmony_ci * Extract min and max values from an ASIdOrRange.
234e1051a39Sopenharmony_ci */
235e1051a39Sopenharmony_cistatic int extract_min_max(ASIdOrRange *aor,
236e1051a39Sopenharmony_ci                           ASN1_INTEGER **min, ASN1_INTEGER **max)
237e1051a39Sopenharmony_ci{
238e1051a39Sopenharmony_ci    if (!ossl_assert(aor != NULL))
239e1051a39Sopenharmony_ci        return 0;
240e1051a39Sopenharmony_ci    switch (aor->type) {
241e1051a39Sopenharmony_ci    case ASIdOrRange_id:
242e1051a39Sopenharmony_ci        *min = aor->u.id;
243e1051a39Sopenharmony_ci        *max = aor->u.id;
244e1051a39Sopenharmony_ci        return 1;
245e1051a39Sopenharmony_ci    case ASIdOrRange_range:
246e1051a39Sopenharmony_ci        *min = aor->u.range->min;
247e1051a39Sopenharmony_ci        *max = aor->u.range->max;
248e1051a39Sopenharmony_ci        return 1;
249e1051a39Sopenharmony_ci    }
250e1051a39Sopenharmony_ci
251e1051a39Sopenharmony_ci    return 0;
252e1051a39Sopenharmony_ci}
253e1051a39Sopenharmony_ci
254e1051a39Sopenharmony_ci/*
255e1051a39Sopenharmony_ci * Check whether an ASIdentifierChoice is in canonical form.
256e1051a39Sopenharmony_ci */
257e1051a39Sopenharmony_cistatic int ASIdentifierChoice_is_canonical(ASIdentifierChoice *choice)
258e1051a39Sopenharmony_ci{
259e1051a39Sopenharmony_ci    ASN1_INTEGER *a_max_plus_one = NULL;
260e1051a39Sopenharmony_ci    ASN1_INTEGER *orig;
261e1051a39Sopenharmony_ci    BIGNUM *bn = NULL;
262e1051a39Sopenharmony_ci    int i, ret = 0;
263e1051a39Sopenharmony_ci
264e1051a39Sopenharmony_ci    /*
265e1051a39Sopenharmony_ci     * Empty element or inheritance is canonical.
266e1051a39Sopenharmony_ci     */
267e1051a39Sopenharmony_ci    if (choice == NULL || choice->type == ASIdentifierChoice_inherit)
268e1051a39Sopenharmony_ci        return 1;
269e1051a39Sopenharmony_ci
270e1051a39Sopenharmony_ci    /*
271e1051a39Sopenharmony_ci     * If not a list, or if empty list, it's broken.
272e1051a39Sopenharmony_ci     */
273e1051a39Sopenharmony_ci    if (choice->type != ASIdentifierChoice_asIdsOrRanges ||
274e1051a39Sopenharmony_ci        sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0)
275e1051a39Sopenharmony_ci        return 0;
276e1051a39Sopenharmony_ci
277e1051a39Sopenharmony_ci    /*
278e1051a39Sopenharmony_ci     * It's a list, check it.
279e1051a39Sopenharmony_ci     */
280e1051a39Sopenharmony_ci    for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) {
281e1051a39Sopenharmony_ci        ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
282e1051a39Sopenharmony_ci        ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1);
283e1051a39Sopenharmony_ci        ASN1_INTEGER *a_min = NULL, *a_max = NULL, *b_min = NULL, *b_max =
284e1051a39Sopenharmony_ci            NULL;
285e1051a39Sopenharmony_ci
286e1051a39Sopenharmony_ci        if (!extract_min_max(a, &a_min, &a_max)
287e1051a39Sopenharmony_ci                || !extract_min_max(b, &b_min, &b_max))
288e1051a39Sopenharmony_ci            goto done;
289e1051a39Sopenharmony_ci
290e1051a39Sopenharmony_ci        /*
291e1051a39Sopenharmony_ci         * Punt misordered list, overlapping start, or inverted range.
292e1051a39Sopenharmony_ci         */
293e1051a39Sopenharmony_ci        if (ASN1_INTEGER_cmp(a_min, b_min) >= 0 ||
294e1051a39Sopenharmony_ci            ASN1_INTEGER_cmp(a_min, a_max) > 0 ||
295e1051a39Sopenharmony_ci            ASN1_INTEGER_cmp(b_min, b_max) > 0)
296e1051a39Sopenharmony_ci            goto done;
297e1051a39Sopenharmony_ci
298e1051a39Sopenharmony_ci        /*
299e1051a39Sopenharmony_ci         * Calculate a_max + 1 to check for adjacency.
300e1051a39Sopenharmony_ci         */
301e1051a39Sopenharmony_ci        if ((bn == NULL && (bn = BN_new()) == NULL) ||
302e1051a39Sopenharmony_ci            ASN1_INTEGER_to_BN(a_max, bn) == NULL ||
303e1051a39Sopenharmony_ci            !BN_add_word(bn, 1)) {
304e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
305e1051a39Sopenharmony_ci            goto done;
306e1051a39Sopenharmony_ci        }
307e1051a39Sopenharmony_ci
308e1051a39Sopenharmony_ci        if ((a_max_plus_one =
309e1051a39Sopenharmony_ci                BN_to_ASN1_INTEGER(bn, orig = a_max_plus_one)) == NULL) {
310e1051a39Sopenharmony_ci            a_max_plus_one = orig;
311e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
312e1051a39Sopenharmony_ci            goto done;
313e1051a39Sopenharmony_ci        }
314e1051a39Sopenharmony_ci
315e1051a39Sopenharmony_ci        /*
316e1051a39Sopenharmony_ci         * Punt if adjacent or overlapping.
317e1051a39Sopenharmony_ci         */
318e1051a39Sopenharmony_ci        if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) >= 0)
319e1051a39Sopenharmony_ci            goto done;
320e1051a39Sopenharmony_ci    }
321e1051a39Sopenharmony_ci
322e1051a39Sopenharmony_ci    /*
323e1051a39Sopenharmony_ci     * Check for inverted range.
324e1051a39Sopenharmony_ci     */
325e1051a39Sopenharmony_ci    i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1;
326e1051a39Sopenharmony_ci    {
327e1051a39Sopenharmony_ci        ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
328e1051a39Sopenharmony_ci        ASN1_INTEGER *a_min, *a_max;
329e1051a39Sopenharmony_ci        if (a != NULL && a->type == ASIdOrRange_range) {
330e1051a39Sopenharmony_ci            if (!extract_min_max(a, &a_min, &a_max)
331e1051a39Sopenharmony_ci                    || ASN1_INTEGER_cmp(a_min, a_max) > 0)
332e1051a39Sopenharmony_ci                goto done;
333e1051a39Sopenharmony_ci        }
334e1051a39Sopenharmony_ci    }
335e1051a39Sopenharmony_ci
336e1051a39Sopenharmony_ci    ret = 1;
337e1051a39Sopenharmony_ci
338e1051a39Sopenharmony_ci done:
339e1051a39Sopenharmony_ci    ASN1_INTEGER_free(a_max_plus_one);
340e1051a39Sopenharmony_ci    BN_free(bn);
341e1051a39Sopenharmony_ci    return ret;
342e1051a39Sopenharmony_ci}
343e1051a39Sopenharmony_ci
344e1051a39Sopenharmony_ci/*
345e1051a39Sopenharmony_ci * Check whether an ASIdentifier extension is in canonical form.
346e1051a39Sopenharmony_ci */
347e1051a39Sopenharmony_ciint X509v3_asid_is_canonical(ASIdentifiers *asid)
348e1051a39Sopenharmony_ci{
349e1051a39Sopenharmony_ci    return (asid == NULL ||
350e1051a39Sopenharmony_ci            (ASIdentifierChoice_is_canonical(asid->asnum) &&
351e1051a39Sopenharmony_ci             ASIdentifierChoice_is_canonical(asid->rdi)));
352e1051a39Sopenharmony_ci}
353e1051a39Sopenharmony_ci
354e1051a39Sopenharmony_ci/*
355e1051a39Sopenharmony_ci * Whack an ASIdentifierChoice into canonical form.
356e1051a39Sopenharmony_ci */
357e1051a39Sopenharmony_cistatic int ASIdentifierChoice_canonize(ASIdentifierChoice *choice)
358e1051a39Sopenharmony_ci{
359e1051a39Sopenharmony_ci    ASN1_INTEGER *a_max_plus_one = NULL;
360e1051a39Sopenharmony_ci    ASN1_INTEGER *orig;
361e1051a39Sopenharmony_ci    BIGNUM *bn = NULL;
362e1051a39Sopenharmony_ci    int i, ret = 0;
363e1051a39Sopenharmony_ci
364e1051a39Sopenharmony_ci    /*
365e1051a39Sopenharmony_ci     * Nothing to do for empty element or inheritance.
366e1051a39Sopenharmony_ci     */
367e1051a39Sopenharmony_ci    if (choice == NULL || choice->type == ASIdentifierChoice_inherit)
368e1051a39Sopenharmony_ci        return 1;
369e1051a39Sopenharmony_ci
370e1051a39Sopenharmony_ci    /*
371e1051a39Sopenharmony_ci     * If not a list, or if empty list, it's broken.
372e1051a39Sopenharmony_ci     */
373e1051a39Sopenharmony_ci    if (choice->type != ASIdentifierChoice_asIdsOrRanges ||
374e1051a39Sopenharmony_ci        sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0) {
375e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
376e1051a39Sopenharmony_ci        return 0;
377e1051a39Sopenharmony_ci    }
378e1051a39Sopenharmony_ci
379e1051a39Sopenharmony_ci    /*
380e1051a39Sopenharmony_ci     * We have a non-empty list.  Sort it.
381e1051a39Sopenharmony_ci     */
382e1051a39Sopenharmony_ci    sk_ASIdOrRange_sort(choice->u.asIdsOrRanges);
383e1051a39Sopenharmony_ci
384e1051a39Sopenharmony_ci    /*
385e1051a39Sopenharmony_ci     * Now check for errors and suboptimal encoding, rejecting the
386e1051a39Sopenharmony_ci     * former and fixing the latter.
387e1051a39Sopenharmony_ci     */
388e1051a39Sopenharmony_ci    for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) {
389e1051a39Sopenharmony_ci        ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
390e1051a39Sopenharmony_ci        ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1);
391e1051a39Sopenharmony_ci        ASN1_INTEGER *a_min = NULL, *a_max = NULL, *b_min = NULL, *b_max =
392e1051a39Sopenharmony_ci            NULL;
393e1051a39Sopenharmony_ci
394e1051a39Sopenharmony_ci        if (!extract_min_max(a, &a_min, &a_max)
395e1051a39Sopenharmony_ci                || !extract_min_max(b, &b_min, &b_max))
396e1051a39Sopenharmony_ci            goto done;
397e1051a39Sopenharmony_ci
398e1051a39Sopenharmony_ci        /*
399e1051a39Sopenharmony_ci         * Make sure we're properly sorted (paranoia).
400e1051a39Sopenharmony_ci         */
401e1051a39Sopenharmony_ci        if (!ossl_assert(ASN1_INTEGER_cmp(a_min, b_min) <= 0))
402e1051a39Sopenharmony_ci            goto done;
403e1051a39Sopenharmony_ci
404e1051a39Sopenharmony_ci        /*
405e1051a39Sopenharmony_ci         * Punt inverted ranges.
406e1051a39Sopenharmony_ci         */
407e1051a39Sopenharmony_ci        if (ASN1_INTEGER_cmp(a_min, a_max) > 0 ||
408e1051a39Sopenharmony_ci            ASN1_INTEGER_cmp(b_min, b_max) > 0)
409e1051a39Sopenharmony_ci            goto done;
410e1051a39Sopenharmony_ci
411e1051a39Sopenharmony_ci        /*
412e1051a39Sopenharmony_ci         * Check for overlaps.
413e1051a39Sopenharmony_ci         */
414e1051a39Sopenharmony_ci        if (ASN1_INTEGER_cmp(a_max, b_min) >= 0) {
415e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
416e1051a39Sopenharmony_ci            goto done;
417e1051a39Sopenharmony_ci        }
418e1051a39Sopenharmony_ci
419e1051a39Sopenharmony_ci        /*
420e1051a39Sopenharmony_ci         * Calculate a_max + 1 to check for adjacency.
421e1051a39Sopenharmony_ci         */
422e1051a39Sopenharmony_ci        if ((bn == NULL && (bn = BN_new()) == NULL) ||
423e1051a39Sopenharmony_ci            ASN1_INTEGER_to_BN(a_max, bn) == NULL ||
424e1051a39Sopenharmony_ci            !BN_add_word(bn, 1)) {
425e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
426e1051a39Sopenharmony_ci            goto done;
427e1051a39Sopenharmony_ci        }
428e1051a39Sopenharmony_ci
429e1051a39Sopenharmony_ci        if ((a_max_plus_one =
430e1051a39Sopenharmony_ci                 BN_to_ASN1_INTEGER(bn, orig = a_max_plus_one)) == NULL) {
431e1051a39Sopenharmony_ci            a_max_plus_one = orig;
432e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
433e1051a39Sopenharmony_ci            goto done;
434e1051a39Sopenharmony_ci        }
435e1051a39Sopenharmony_ci
436e1051a39Sopenharmony_ci        /*
437e1051a39Sopenharmony_ci         * If a and b are adjacent, merge them.
438e1051a39Sopenharmony_ci         */
439e1051a39Sopenharmony_ci        if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) == 0) {
440e1051a39Sopenharmony_ci            ASRange *r;
441e1051a39Sopenharmony_ci            switch (a->type) {
442e1051a39Sopenharmony_ci            case ASIdOrRange_id:
443e1051a39Sopenharmony_ci                if ((r = OPENSSL_malloc(sizeof(*r))) == NULL) {
444e1051a39Sopenharmony_ci                    ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
445e1051a39Sopenharmony_ci                    goto done;
446e1051a39Sopenharmony_ci                }
447e1051a39Sopenharmony_ci                r->min = a_min;
448e1051a39Sopenharmony_ci                r->max = b_max;
449e1051a39Sopenharmony_ci                a->type = ASIdOrRange_range;
450e1051a39Sopenharmony_ci                a->u.range = r;
451e1051a39Sopenharmony_ci                break;
452e1051a39Sopenharmony_ci            case ASIdOrRange_range:
453e1051a39Sopenharmony_ci                ASN1_INTEGER_free(a->u.range->max);
454e1051a39Sopenharmony_ci                a->u.range->max = b_max;
455e1051a39Sopenharmony_ci                break;
456e1051a39Sopenharmony_ci            }
457e1051a39Sopenharmony_ci            switch (b->type) {
458e1051a39Sopenharmony_ci            case ASIdOrRange_id:
459e1051a39Sopenharmony_ci                b->u.id = NULL;
460e1051a39Sopenharmony_ci                break;
461e1051a39Sopenharmony_ci            case ASIdOrRange_range:
462e1051a39Sopenharmony_ci                b->u.range->max = NULL;
463e1051a39Sopenharmony_ci                break;
464e1051a39Sopenharmony_ci            }
465e1051a39Sopenharmony_ci            ASIdOrRange_free(b);
466e1051a39Sopenharmony_ci            (void)sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i + 1);
467e1051a39Sopenharmony_ci            i--;
468e1051a39Sopenharmony_ci            continue;
469e1051a39Sopenharmony_ci        }
470e1051a39Sopenharmony_ci    }
471e1051a39Sopenharmony_ci
472e1051a39Sopenharmony_ci    /*
473e1051a39Sopenharmony_ci     * Check for final inverted range.
474e1051a39Sopenharmony_ci     */
475e1051a39Sopenharmony_ci    i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1;
476e1051a39Sopenharmony_ci    {
477e1051a39Sopenharmony_ci        ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
478e1051a39Sopenharmony_ci        ASN1_INTEGER *a_min, *a_max;
479e1051a39Sopenharmony_ci        if (a != NULL && a->type == ASIdOrRange_range) {
480e1051a39Sopenharmony_ci            if (!extract_min_max(a, &a_min, &a_max)
481e1051a39Sopenharmony_ci                    || ASN1_INTEGER_cmp(a_min, a_max) > 0)
482e1051a39Sopenharmony_ci                goto done;
483e1051a39Sopenharmony_ci        }
484e1051a39Sopenharmony_ci    }
485e1051a39Sopenharmony_ci
486e1051a39Sopenharmony_ci    /* Paranoia */
487e1051a39Sopenharmony_ci    if (!ossl_assert(ASIdentifierChoice_is_canonical(choice)))
488e1051a39Sopenharmony_ci        goto done;
489e1051a39Sopenharmony_ci
490e1051a39Sopenharmony_ci    ret = 1;
491e1051a39Sopenharmony_ci
492e1051a39Sopenharmony_ci done:
493e1051a39Sopenharmony_ci    ASN1_INTEGER_free(a_max_plus_one);
494e1051a39Sopenharmony_ci    BN_free(bn);
495e1051a39Sopenharmony_ci    return ret;
496e1051a39Sopenharmony_ci}
497e1051a39Sopenharmony_ci
498e1051a39Sopenharmony_ci/*
499e1051a39Sopenharmony_ci * Whack an ASIdentifier extension into canonical form.
500e1051a39Sopenharmony_ci */
501e1051a39Sopenharmony_ciint X509v3_asid_canonize(ASIdentifiers *asid)
502e1051a39Sopenharmony_ci{
503e1051a39Sopenharmony_ci    return (asid == NULL ||
504e1051a39Sopenharmony_ci            (ASIdentifierChoice_canonize(asid->asnum) &&
505e1051a39Sopenharmony_ci             ASIdentifierChoice_canonize(asid->rdi)));
506e1051a39Sopenharmony_ci}
507e1051a39Sopenharmony_ci
508e1051a39Sopenharmony_ci/*
509e1051a39Sopenharmony_ci * v2i method for an ASIdentifier extension.
510e1051a39Sopenharmony_ci */
511e1051a39Sopenharmony_cistatic void *v2i_ASIdentifiers(const struct v3_ext_method *method,
512e1051a39Sopenharmony_ci                               struct v3_ext_ctx *ctx,
513e1051a39Sopenharmony_ci                               STACK_OF(CONF_VALUE) *values)
514e1051a39Sopenharmony_ci{
515e1051a39Sopenharmony_ci    ASN1_INTEGER *min = NULL, *max = NULL;
516e1051a39Sopenharmony_ci    ASIdentifiers *asid = NULL;
517e1051a39Sopenharmony_ci    int i;
518e1051a39Sopenharmony_ci
519e1051a39Sopenharmony_ci    if ((asid = ASIdentifiers_new()) == NULL) {
520e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
521e1051a39Sopenharmony_ci        return NULL;
522e1051a39Sopenharmony_ci    }
523e1051a39Sopenharmony_ci
524e1051a39Sopenharmony_ci    for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
525e1051a39Sopenharmony_ci        CONF_VALUE *val = sk_CONF_VALUE_value(values, i);
526e1051a39Sopenharmony_ci        int i1 = 0, i2 = 0, i3 = 0, is_range = 0, which = 0;
527e1051a39Sopenharmony_ci
528e1051a39Sopenharmony_ci        /*
529e1051a39Sopenharmony_ci         * Figure out whether this is an AS or an RDI.
530e1051a39Sopenharmony_ci         */
531e1051a39Sopenharmony_ci        if (!ossl_v3_name_cmp(val->name, "AS")) {
532e1051a39Sopenharmony_ci            which = V3_ASID_ASNUM;
533e1051a39Sopenharmony_ci        } else if (!ossl_v3_name_cmp(val->name, "RDI")) {
534e1051a39Sopenharmony_ci            which = V3_ASID_RDI;
535e1051a39Sopenharmony_ci        } else {
536e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_NAME_ERROR);
537e1051a39Sopenharmony_ci            X509V3_conf_add_error_name_value(val);
538e1051a39Sopenharmony_ci            goto err;
539e1051a39Sopenharmony_ci        }
540e1051a39Sopenharmony_ci
541e1051a39Sopenharmony_ci        /*
542e1051a39Sopenharmony_ci         * Handle inheritance.
543e1051a39Sopenharmony_ci         */
544e1051a39Sopenharmony_ci        if (strcmp(val->value, "inherit") == 0) {
545e1051a39Sopenharmony_ci            if (X509v3_asid_add_inherit(asid, which))
546e1051a39Sopenharmony_ci                continue;
547e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_INHERITANCE);
548e1051a39Sopenharmony_ci            X509V3_conf_add_error_name_value(val);
549e1051a39Sopenharmony_ci            goto err;
550e1051a39Sopenharmony_ci        }
551e1051a39Sopenharmony_ci
552e1051a39Sopenharmony_ci        /*
553e1051a39Sopenharmony_ci         * Number, range, or mistake, pick it apart and figure out which.
554e1051a39Sopenharmony_ci         */
555e1051a39Sopenharmony_ci        i1 = strspn(val->value, "0123456789");
556e1051a39Sopenharmony_ci        if (val->value[i1] == '\0') {
557e1051a39Sopenharmony_ci            is_range = 0;
558e1051a39Sopenharmony_ci        } else {
559e1051a39Sopenharmony_ci            is_range = 1;
560e1051a39Sopenharmony_ci            i2 = i1 + strspn(val->value + i1, " \t");
561e1051a39Sopenharmony_ci            if (val->value[i2] != '-') {
562e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_ASNUMBER);
563e1051a39Sopenharmony_ci                X509V3_conf_add_error_name_value(val);
564e1051a39Sopenharmony_ci                goto err;
565e1051a39Sopenharmony_ci            }
566e1051a39Sopenharmony_ci            i2++;
567e1051a39Sopenharmony_ci            i2 = i2 + strspn(val->value + i2, " \t");
568e1051a39Sopenharmony_ci            i3 = i2 + strspn(val->value + i2, "0123456789");
569e1051a39Sopenharmony_ci            if (val->value[i3] != '\0') {
570e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_ASRANGE);
571e1051a39Sopenharmony_ci                X509V3_conf_add_error_name_value(val);
572e1051a39Sopenharmony_ci                goto err;
573e1051a39Sopenharmony_ci            }
574e1051a39Sopenharmony_ci        }
575e1051a39Sopenharmony_ci
576e1051a39Sopenharmony_ci        /*
577e1051a39Sopenharmony_ci         * Syntax is ok, read and add it.
578e1051a39Sopenharmony_ci         */
579e1051a39Sopenharmony_ci        if (!is_range) {
580e1051a39Sopenharmony_ci            if (!X509V3_get_value_int(val, &min)) {
581e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
582e1051a39Sopenharmony_ci                goto err;
583e1051a39Sopenharmony_ci            }
584e1051a39Sopenharmony_ci        } else {
585e1051a39Sopenharmony_ci            char *s = OPENSSL_strdup(val->value);
586e1051a39Sopenharmony_ci            if (s == NULL) {
587e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
588e1051a39Sopenharmony_ci                goto err;
589e1051a39Sopenharmony_ci            }
590e1051a39Sopenharmony_ci            s[i1] = '\0';
591e1051a39Sopenharmony_ci            min = s2i_ASN1_INTEGER(NULL, s);
592e1051a39Sopenharmony_ci            max = s2i_ASN1_INTEGER(NULL, s + i2);
593e1051a39Sopenharmony_ci            OPENSSL_free(s);
594e1051a39Sopenharmony_ci            if (min == NULL || max == NULL) {
595e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
596e1051a39Sopenharmony_ci                goto err;
597e1051a39Sopenharmony_ci            }
598e1051a39Sopenharmony_ci            if (ASN1_INTEGER_cmp(min, max) > 0) {
599e1051a39Sopenharmony_ci                ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
600e1051a39Sopenharmony_ci                goto err;
601e1051a39Sopenharmony_ci            }
602e1051a39Sopenharmony_ci        }
603e1051a39Sopenharmony_ci        if (!X509v3_asid_add_id_or_range(asid, which, min, max)) {
604e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
605e1051a39Sopenharmony_ci            goto err;
606e1051a39Sopenharmony_ci        }
607e1051a39Sopenharmony_ci        min = max = NULL;
608e1051a39Sopenharmony_ci    }
609e1051a39Sopenharmony_ci
610e1051a39Sopenharmony_ci    /*
611e1051a39Sopenharmony_ci     * Canonize the result, then we're done.
612e1051a39Sopenharmony_ci     */
613e1051a39Sopenharmony_ci    if (!X509v3_asid_canonize(asid))
614e1051a39Sopenharmony_ci        goto err;
615e1051a39Sopenharmony_ci    return asid;
616e1051a39Sopenharmony_ci
617e1051a39Sopenharmony_ci err:
618e1051a39Sopenharmony_ci    ASIdentifiers_free(asid);
619e1051a39Sopenharmony_ci    ASN1_INTEGER_free(min);
620e1051a39Sopenharmony_ci    ASN1_INTEGER_free(max);
621e1051a39Sopenharmony_ci    return NULL;
622e1051a39Sopenharmony_ci}
623e1051a39Sopenharmony_ci
624e1051a39Sopenharmony_ci/*
625e1051a39Sopenharmony_ci * OpenSSL dispatch.
626e1051a39Sopenharmony_ci */
627e1051a39Sopenharmony_ciconst X509V3_EXT_METHOD ossl_v3_asid = {
628e1051a39Sopenharmony_ci    NID_sbgp_autonomousSysNum,  /* nid */
629e1051a39Sopenharmony_ci    0,                          /* flags */
630e1051a39Sopenharmony_ci    ASN1_ITEM_ref(ASIdentifiers), /* template */
631e1051a39Sopenharmony_ci    0, 0, 0, 0,                 /* old functions, ignored */
632e1051a39Sopenharmony_ci    0,                          /* i2s */
633e1051a39Sopenharmony_ci    0,                          /* s2i */
634e1051a39Sopenharmony_ci    0,                          /* i2v */
635e1051a39Sopenharmony_ci    v2i_ASIdentifiers,          /* v2i */
636e1051a39Sopenharmony_ci    i2r_ASIdentifiers,          /* i2r */
637e1051a39Sopenharmony_ci    0,                          /* r2i */
638e1051a39Sopenharmony_ci    NULL                        /* extension-specific data */
639e1051a39Sopenharmony_ci};
640e1051a39Sopenharmony_ci
641e1051a39Sopenharmony_ci/*
642e1051a39Sopenharmony_ci * Figure out whether extension uses inheritance.
643e1051a39Sopenharmony_ci */
644e1051a39Sopenharmony_ciint X509v3_asid_inherits(ASIdentifiers *asid)
645e1051a39Sopenharmony_ci{
646e1051a39Sopenharmony_ci    return (asid != NULL &&
647e1051a39Sopenharmony_ci            ((asid->asnum != NULL &&
648e1051a39Sopenharmony_ci              asid->asnum->type == ASIdentifierChoice_inherit) ||
649e1051a39Sopenharmony_ci             (asid->rdi != NULL &&
650e1051a39Sopenharmony_ci              asid->rdi->type == ASIdentifierChoice_inherit)));
651e1051a39Sopenharmony_ci}
652e1051a39Sopenharmony_ci
653e1051a39Sopenharmony_ci/*
654e1051a39Sopenharmony_ci * Figure out whether parent contains child.
655e1051a39Sopenharmony_ci */
656e1051a39Sopenharmony_cistatic int asid_contains(ASIdOrRanges *parent, ASIdOrRanges *child)
657e1051a39Sopenharmony_ci{
658e1051a39Sopenharmony_ci    ASN1_INTEGER *p_min = NULL, *p_max = NULL, *c_min = NULL, *c_max = NULL;
659e1051a39Sopenharmony_ci    int p, c;
660e1051a39Sopenharmony_ci
661e1051a39Sopenharmony_ci    if (child == NULL || parent == child)
662e1051a39Sopenharmony_ci        return 1;
663e1051a39Sopenharmony_ci    if (parent == NULL)
664e1051a39Sopenharmony_ci        return 0;
665e1051a39Sopenharmony_ci
666e1051a39Sopenharmony_ci    p = 0;
667e1051a39Sopenharmony_ci    for (c = 0; c < sk_ASIdOrRange_num(child); c++) {
668e1051a39Sopenharmony_ci        if (!extract_min_max(sk_ASIdOrRange_value(child, c), &c_min, &c_max))
669e1051a39Sopenharmony_ci            return 0;
670e1051a39Sopenharmony_ci        for (;; p++) {
671e1051a39Sopenharmony_ci            if (p >= sk_ASIdOrRange_num(parent))
672e1051a39Sopenharmony_ci                return 0;
673e1051a39Sopenharmony_ci            if (!extract_min_max(sk_ASIdOrRange_value(parent, p), &p_min,
674e1051a39Sopenharmony_ci                                 &p_max))
675e1051a39Sopenharmony_ci                return 0;
676e1051a39Sopenharmony_ci            if (ASN1_INTEGER_cmp(p_max, c_max) < 0)
677e1051a39Sopenharmony_ci                continue;
678e1051a39Sopenharmony_ci            if (ASN1_INTEGER_cmp(p_min, c_min) > 0)
679e1051a39Sopenharmony_ci                return 0;
680e1051a39Sopenharmony_ci            break;
681e1051a39Sopenharmony_ci        }
682e1051a39Sopenharmony_ci    }
683e1051a39Sopenharmony_ci
684e1051a39Sopenharmony_ci    return 1;
685e1051a39Sopenharmony_ci}
686e1051a39Sopenharmony_ci
687e1051a39Sopenharmony_ci/*
688e1051a39Sopenharmony_ci * Test whether a is a subset of b.
689e1051a39Sopenharmony_ci */
690e1051a39Sopenharmony_ciint X509v3_asid_subset(ASIdentifiers *a, ASIdentifiers *b)
691e1051a39Sopenharmony_ci{
692e1051a39Sopenharmony_ci    int subset;
693e1051a39Sopenharmony_ci
694e1051a39Sopenharmony_ci    if (a == NULL || a == b)
695e1051a39Sopenharmony_ci        return 1;
696e1051a39Sopenharmony_ci
697e1051a39Sopenharmony_ci    if (b == NULL)
698e1051a39Sopenharmony_ci        return 0;
699e1051a39Sopenharmony_ci
700e1051a39Sopenharmony_ci    if (X509v3_asid_inherits(a) || X509v3_asid_inherits(b))
701e1051a39Sopenharmony_ci        return 0;
702e1051a39Sopenharmony_ci
703e1051a39Sopenharmony_ci    subset = a->asnum == NULL
704e1051a39Sopenharmony_ci             || (b->asnum != NULL
705e1051a39Sopenharmony_ci                 && asid_contains(b->asnum->u.asIdsOrRanges,
706e1051a39Sopenharmony_ci                                  a->asnum->u.asIdsOrRanges));
707e1051a39Sopenharmony_ci    if (!subset)
708e1051a39Sopenharmony_ci        return 0;
709e1051a39Sopenharmony_ci
710e1051a39Sopenharmony_ci    return a->rdi == NULL
711e1051a39Sopenharmony_ci           || (b->rdi != NULL
712e1051a39Sopenharmony_ci               && asid_contains(b->rdi->u.asIdsOrRanges,
713e1051a39Sopenharmony_ci                                a->rdi->u.asIdsOrRanges));
714e1051a39Sopenharmony_ci}
715e1051a39Sopenharmony_ci
716e1051a39Sopenharmony_ci/*
717e1051a39Sopenharmony_ci * Validation error handling via callback.
718e1051a39Sopenharmony_ci */
719e1051a39Sopenharmony_ci#define validation_err(_err_)           \
720e1051a39Sopenharmony_ci  do {                                  \
721e1051a39Sopenharmony_ci    if (ctx != NULL) {                  \
722e1051a39Sopenharmony_ci      ctx->error = _err_;               \
723e1051a39Sopenharmony_ci      ctx->error_depth = i;             \
724e1051a39Sopenharmony_ci      ctx->current_cert = x;            \
725e1051a39Sopenharmony_ci      ret = ctx->verify_cb(0, ctx);     \
726e1051a39Sopenharmony_ci    } else {                            \
727e1051a39Sopenharmony_ci      ret = 0;                          \
728e1051a39Sopenharmony_ci    }                                   \
729e1051a39Sopenharmony_ci    if (!ret)                           \
730e1051a39Sopenharmony_ci      goto done;                        \
731e1051a39Sopenharmony_ci  } while (0)
732e1051a39Sopenharmony_ci
733e1051a39Sopenharmony_ci/*
734e1051a39Sopenharmony_ci * Core code for RFC 3779 3.3 path validation.
735e1051a39Sopenharmony_ci */
736e1051a39Sopenharmony_cistatic int asid_validate_path_internal(X509_STORE_CTX *ctx,
737e1051a39Sopenharmony_ci                                       STACK_OF(X509) *chain,
738e1051a39Sopenharmony_ci                                       ASIdentifiers *ext)
739e1051a39Sopenharmony_ci{
740e1051a39Sopenharmony_ci    ASIdOrRanges *child_as = NULL, *child_rdi = NULL;
741e1051a39Sopenharmony_ci    int i, ret = 1, inherit_as = 0, inherit_rdi = 0;
742e1051a39Sopenharmony_ci    X509 *x;
743e1051a39Sopenharmony_ci
744e1051a39Sopenharmony_ci    if (!ossl_assert(chain != NULL && sk_X509_num(chain) > 0)
745e1051a39Sopenharmony_ci            || !ossl_assert(ctx != NULL || ext != NULL)
746e1051a39Sopenharmony_ci            || !ossl_assert(ctx == NULL || ctx->verify_cb != NULL)) {
747e1051a39Sopenharmony_ci        if (ctx != NULL)
748e1051a39Sopenharmony_ci            ctx->error = X509_V_ERR_UNSPECIFIED;
749e1051a39Sopenharmony_ci        return 0;
750e1051a39Sopenharmony_ci    }
751e1051a39Sopenharmony_ci
752e1051a39Sopenharmony_ci
753e1051a39Sopenharmony_ci    /*
754e1051a39Sopenharmony_ci     * Figure out where to start.  If we don't have an extension to
755e1051a39Sopenharmony_ci     * check, we're done.  Otherwise, check canonical form and
756e1051a39Sopenharmony_ci     * set up for walking up the chain.
757e1051a39Sopenharmony_ci     */
758e1051a39Sopenharmony_ci    if (ext != NULL) {
759e1051a39Sopenharmony_ci        i = -1;
760e1051a39Sopenharmony_ci        x = NULL;
761e1051a39Sopenharmony_ci    } else {
762e1051a39Sopenharmony_ci        i = 0;
763e1051a39Sopenharmony_ci        x = sk_X509_value(chain, i);
764e1051a39Sopenharmony_ci        if ((ext = x->rfc3779_asid) == NULL)
765e1051a39Sopenharmony_ci            goto done;
766e1051a39Sopenharmony_ci    }
767e1051a39Sopenharmony_ci    if (!X509v3_asid_is_canonical(ext))
768e1051a39Sopenharmony_ci        validation_err(X509_V_ERR_INVALID_EXTENSION);
769e1051a39Sopenharmony_ci    if (ext->asnum != NULL) {
770e1051a39Sopenharmony_ci        switch (ext->asnum->type) {
771e1051a39Sopenharmony_ci        case ASIdentifierChoice_inherit:
772e1051a39Sopenharmony_ci            inherit_as = 1;
773e1051a39Sopenharmony_ci            break;
774e1051a39Sopenharmony_ci        case ASIdentifierChoice_asIdsOrRanges:
775e1051a39Sopenharmony_ci            child_as = ext->asnum->u.asIdsOrRanges;
776e1051a39Sopenharmony_ci            break;
777e1051a39Sopenharmony_ci        }
778e1051a39Sopenharmony_ci    }
779e1051a39Sopenharmony_ci    if (ext->rdi != NULL) {
780e1051a39Sopenharmony_ci        switch (ext->rdi->type) {
781e1051a39Sopenharmony_ci        case ASIdentifierChoice_inherit:
782e1051a39Sopenharmony_ci            inherit_rdi = 1;
783e1051a39Sopenharmony_ci            break;
784e1051a39Sopenharmony_ci        case ASIdentifierChoice_asIdsOrRanges:
785e1051a39Sopenharmony_ci            child_rdi = ext->rdi->u.asIdsOrRanges;
786e1051a39Sopenharmony_ci            break;
787e1051a39Sopenharmony_ci        }
788e1051a39Sopenharmony_ci    }
789e1051a39Sopenharmony_ci
790e1051a39Sopenharmony_ci    /*
791e1051a39Sopenharmony_ci     * Now walk up the chain.  Extensions must be in canonical form, no
792e1051a39Sopenharmony_ci     * cert may list resources that its parent doesn't list.
793e1051a39Sopenharmony_ci     */
794e1051a39Sopenharmony_ci    for (i++; i < sk_X509_num(chain); i++) {
795e1051a39Sopenharmony_ci        x = sk_X509_value(chain, i);
796e1051a39Sopenharmony_ci        if (!ossl_assert(x != NULL)) {
797e1051a39Sopenharmony_ci            if (ctx != NULL)
798e1051a39Sopenharmony_ci                ctx->error = X509_V_ERR_UNSPECIFIED;
799e1051a39Sopenharmony_ci            return 0;
800e1051a39Sopenharmony_ci        }
801e1051a39Sopenharmony_ci        if (x->rfc3779_asid == NULL) {
802e1051a39Sopenharmony_ci            if (child_as != NULL || child_rdi != NULL)
803e1051a39Sopenharmony_ci                validation_err(X509_V_ERR_UNNESTED_RESOURCE);
804e1051a39Sopenharmony_ci            continue;
805e1051a39Sopenharmony_ci        }
806e1051a39Sopenharmony_ci        if (!X509v3_asid_is_canonical(x->rfc3779_asid))
807e1051a39Sopenharmony_ci            validation_err(X509_V_ERR_INVALID_EXTENSION);
808e1051a39Sopenharmony_ci        if (x->rfc3779_asid->asnum == NULL && child_as != NULL) {
809e1051a39Sopenharmony_ci            validation_err(X509_V_ERR_UNNESTED_RESOURCE);
810e1051a39Sopenharmony_ci            child_as = NULL;
811e1051a39Sopenharmony_ci            inherit_as = 0;
812e1051a39Sopenharmony_ci        }
813e1051a39Sopenharmony_ci        if (x->rfc3779_asid->asnum != NULL &&
814e1051a39Sopenharmony_ci            x->rfc3779_asid->asnum->type ==
815e1051a39Sopenharmony_ci            ASIdentifierChoice_asIdsOrRanges) {
816e1051a39Sopenharmony_ci            if (inherit_as
817e1051a39Sopenharmony_ci                || asid_contains(x->rfc3779_asid->asnum->u.asIdsOrRanges,
818e1051a39Sopenharmony_ci                                 child_as)) {
819e1051a39Sopenharmony_ci                child_as = x->rfc3779_asid->asnum->u.asIdsOrRanges;
820e1051a39Sopenharmony_ci                inherit_as = 0;
821e1051a39Sopenharmony_ci            } else {
822e1051a39Sopenharmony_ci                validation_err(X509_V_ERR_UNNESTED_RESOURCE);
823e1051a39Sopenharmony_ci            }
824e1051a39Sopenharmony_ci        }
825e1051a39Sopenharmony_ci        if (x->rfc3779_asid->rdi == NULL && child_rdi != NULL) {
826e1051a39Sopenharmony_ci            validation_err(X509_V_ERR_UNNESTED_RESOURCE);
827e1051a39Sopenharmony_ci            child_rdi = NULL;
828e1051a39Sopenharmony_ci            inherit_rdi = 0;
829e1051a39Sopenharmony_ci        }
830e1051a39Sopenharmony_ci        if (x->rfc3779_asid->rdi != NULL &&
831e1051a39Sopenharmony_ci            x->rfc3779_asid->rdi->type == ASIdentifierChoice_asIdsOrRanges) {
832e1051a39Sopenharmony_ci            if (inherit_rdi ||
833e1051a39Sopenharmony_ci                asid_contains(x->rfc3779_asid->rdi->u.asIdsOrRanges,
834e1051a39Sopenharmony_ci                              child_rdi)) {
835e1051a39Sopenharmony_ci                child_rdi = x->rfc3779_asid->rdi->u.asIdsOrRanges;
836e1051a39Sopenharmony_ci                inherit_rdi = 0;
837e1051a39Sopenharmony_ci            } else {
838e1051a39Sopenharmony_ci                validation_err(X509_V_ERR_UNNESTED_RESOURCE);
839e1051a39Sopenharmony_ci            }
840e1051a39Sopenharmony_ci        }
841e1051a39Sopenharmony_ci    }
842e1051a39Sopenharmony_ci
843e1051a39Sopenharmony_ci    /*
844e1051a39Sopenharmony_ci     * Trust anchor can't inherit.
845e1051a39Sopenharmony_ci     */
846e1051a39Sopenharmony_ci    if (!ossl_assert(x != NULL)) {
847e1051a39Sopenharmony_ci        if (ctx != NULL)
848e1051a39Sopenharmony_ci            ctx->error = X509_V_ERR_UNSPECIFIED;
849e1051a39Sopenharmony_ci        return 0;
850e1051a39Sopenharmony_ci    }
851e1051a39Sopenharmony_ci    if (x->rfc3779_asid != NULL) {
852e1051a39Sopenharmony_ci        if (x->rfc3779_asid->asnum != NULL &&
853e1051a39Sopenharmony_ci            x->rfc3779_asid->asnum->type == ASIdentifierChoice_inherit)
854e1051a39Sopenharmony_ci            validation_err(X509_V_ERR_UNNESTED_RESOURCE);
855e1051a39Sopenharmony_ci        if (x->rfc3779_asid->rdi != NULL &&
856e1051a39Sopenharmony_ci            x->rfc3779_asid->rdi->type == ASIdentifierChoice_inherit)
857e1051a39Sopenharmony_ci            validation_err(X509_V_ERR_UNNESTED_RESOURCE);
858e1051a39Sopenharmony_ci    }
859e1051a39Sopenharmony_ci
860e1051a39Sopenharmony_ci done:
861e1051a39Sopenharmony_ci    return ret;
862e1051a39Sopenharmony_ci}
863e1051a39Sopenharmony_ci
864e1051a39Sopenharmony_ci#undef validation_err
865e1051a39Sopenharmony_ci
866e1051a39Sopenharmony_ci/*
867e1051a39Sopenharmony_ci * RFC 3779 3.3 path validation -- called from X509_verify_cert().
868e1051a39Sopenharmony_ci */
869e1051a39Sopenharmony_ciint X509v3_asid_validate_path(X509_STORE_CTX *ctx)
870e1051a39Sopenharmony_ci{
871e1051a39Sopenharmony_ci    if (ctx->chain == NULL
872e1051a39Sopenharmony_ci            || sk_X509_num(ctx->chain) == 0
873e1051a39Sopenharmony_ci            || ctx->verify_cb == NULL) {
874e1051a39Sopenharmony_ci        ctx->error = X509_V_ERR_UNSPECIFIED;
875e1051a39Sopenharmony_ci        return 0;
876e1051a39Sopenharmony_ci    }
877e1051a39Sopenharmony_ci    return asid_validate_path_internal(ctx, ctx->chain, NULL);
878e1051a39Sopenharmony_ci}
879e1051a39Sopenharmony_ci
880e1051a39Sopenharmony_ci/*
881e1051a39Sopenharmony_ci * RFC 3779 3.3 path validation of an extension.
882e1051a39Sopenharmony_ci * Test whether chain covers extension.
883e1051a39Sopenharmony_ci */
884e1051a39Sopenharmony_ciint X509v3_asid_validate_resource_set(STACK_OF(X509) *chain,
885e1051a39Sopenharmony_ci                                      ASIdentifiers *ext, int allow_inheritance)
886e1051a39Sopenharmony_ci{
887e1051a39Sopenharmony_ci    if (ext == NULL)
888e1051a39Sopenharmony_ci        return 1;
889e1051a39Sopenharmony_ci    if (chain == NULL || sk_X509_num(chain) == 0)
890e1051a39Sopenharmony_ci        return 0;
891e1051a39Sopenharmony_ci    if (!allow_inheritance && X509v3_asid_inherits(ext))
892e1051a39Sopenharmony_ci        return 0;
893e1051a39Sopenharmony_ci    return asid_validate_path_internal(NULL, chain, ext);
894e1051a39Sopenharmony_ci}
895e1051a39Sopenharmony_ci
896e1051a39Sopenharmony_ci#endif                          /* OPENSSL_NO_RFC3779 */
897