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