11cb0ef41Sopenharmony_ci/*
21cb0ef41Sopenharmony_ci * Copyright 2006-2024 The OpenSSL Project Authors. All Rights Reserved.
31cb0ef41Sopenharmony_ci *
41cb0ef41Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
51cb0ef41Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
61cb0ef41Sopenharmony_ci * in the file LICENSE in the source distribution or at
71cb0ef41Sopenharmony_ci * https://www.openssl.org/source/license.html
81cb0ef41Sopenharmony_ci */
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci/*
111cb0ef41Sopenharmony_ci * Implementation of RFC 3779 section 3.2.
121cb0ef41Sopenharmony_ci */
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ci#include <assert.h>
151cb0ef41Sopenharmony_ci#include <stdio.h>
161cb0ef41Sopenharmony_ci#include <string.h>
171cb0ef41Sopenharmony_ci#include "internal/cryptlib.h"
181cb0ef41Sopenharmony_ci#include <openssl/conf.h>
191cb0ef41Sopenharmony_ci#include <openssl/asn1.h>
201cb0ef41Sopenharmony_ci#include <openssl/asn1t.h>
211cb0ef41Sopenharmony_ci#include <openssl/x509v3.h>
221cb0ef41Sopenharmony_ci#include <openssl/x509.h>
231cb0ef41Sopenharmony_ci#include "crypto/x509.h"
241cb0ef41Sopenharmony_ci#include <openssl/bn.h>
251cb0ef41Sopenharmony_ci#include "ext_dat.h"
261cb0ef41Sopenharmony_ci#include "x509_local.h"
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci#ifndef OPENSSL_NO_RFC3779
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci/*
311cb0ef41Sopenharmony_ci * OpenSSL ASN.1 template translation of RFC 3779 3.2.3.
321cb0ef41Sopenharmony_ci */
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ciASN1_SEQUENCE(ASRange) = {
351cb0ef41Sopenharmony_ci  ASN1_SIMPLE(ASRange, min, ASN1_INTEGER),
361cb0ef41Sopenharmony_ci  ASN1_SIMPLE(ASRange, max, ASN1_INTEGER)
371cb0ef41Sopenharmony_ci} ASN1_SEQUENCE_END(ASRange)
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ciASN1_CHOICE(ASIdOrRange) = {
401cb0ef41Sopenharmony_ci  ASN1_SIMPLE(ASIdOrRange, u.id,    ASN1_INTEGER),
411cb0ef41Sopenharmony_ci  ASN1_SIMPLE(ASIdOrRange, u.range, ASRange)
421cb0ef41Sopenharmony_ci} ASN1_CHOICE_END(ASIdOrRange)
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ciASN1_CHOICE(ASIdentifierChoice) = {
451cb0ef41Sopenharmony_ci  ASN1_SIMPLE(ASIdentifierChoice,      u.inherit,       ASN1_NULL),
461cb0ef41Sopenharmony_ci  ASN1_SEQUENCE_OF(ASIdentifierChoice, u.asIdsOrRanges, ASIdOrRange)
471cb0ef41Sopenharmony_ci} ASN1_CHOICE_END(ASIdentifierChoice)
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ciASN1_SEQUENCE(ASIdentifiers) = {
501cb0ef41Sopenharmony_ci  ASN1_EXP_OPT(ASIdentifiers, asnum, ASIdentifierChoice, 0),
511cb0ef41Sopenharmony_ci  ASN1_EXP_OPT(ASIdentifiers, rdi,   ASIdentifierChoice, 1)
521cb0ef41Sopenharmony_ci} ASN1_SEQUENCE_END(ASIdentifiers)
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(ASRange)
551cb0ef41Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(ASIdOrRange)
561cb0ef41Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(ASIdentifierChoice)
571cb0ef41Sopenharmony_ciIMPLEMENT_ASN1_FUNCTIONS(ASIdentifiers)
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci/*
601cb0ef41Sopenharmony_ci * i2r method for an ASIdentifierChoice.
611cb0ef41Sopenharmony_ci */
621cb0ef41Sopenharmony_cistatic int i2r_ASIdentifierChoice(BIO *out,
631cb0ef41Sopenharmony_ci                                  ASIdentifierChoice *choice,
641cb0ef41Sopenharmony_ci                                  int indent, const char *msg)
651cb0ef41Sopenharmony_ci{
661cb0ef41Sopenharmony_ci    int i;
671cb0ef41Sopenharmony_ci    char *s;
681cb0ef41Sopenharmony_ci    if (choice == NULL)
691cb0ef41Sopenharmony_ci        return 1;
701cb0ef41Sopenharmony_ci    BIO_printf(out, "%*s%s:\n", indent, "", msg);
711cb0ef41Sopenharmony_ci    switch (choice->type) {
721cb0ef41Sopenharmony_ci    case ASIdentifierChoice_inherit:
731cb0ef41Sopenharmony_ci        BIO_printf(out, "%*sinherit\n", indent + 2, "");
741cb0ef41Sopenharmony_ci        break;
751cb0ef41Sopenharmony_ci    case ASIdentifierChoice_asIdsOrRanges:
761cb0ef41Sopenharmony_ci        for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges); i++) {
771cb0ef41Sopenharmony_ci            ASIdOrRange *aor =
781cb0ef41Sopenharmony_ci                sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
791cb0ef41Sopenharmony_ci            switch (aor->type) {
801cb0ef41Sopenharmony_ci            case ASIdOrRange_id:
811cb0ef41Sopenharmony_ci                if ((s = i2s_ASN1_INTEGER(NULL, aor->u.id)) == NULL)
821cb0ef41Sopenharmony_ci                    return 0;
831cb0ef41Sopenharmony_ci                BIO_printf(out, "%*s%s\n", indent + 2, "", s);
841cb0ef41Sopenharmony_ci                OPENSSL_free(s);
851cb0ef41Sopenharmony_ci                break;
861cb0ef41Sopenharmony_ci            case ASIdOrRange_range:
871cb0ef41Sopenharmony_ci                if ((s = i2s_ASN1_INTEGER(NULL, aor->u.range->min)) == NULL)
881cb0ef41Sopenharmony_ci                    return 0;
891cb0ef41Sopenharmony_ci                BIO_printf(out, "%*s%s-", indent + 2, "", s);
901cb0ef41Sopenharmony_ci                OPENSSL_free(s);
911cb0ef41Sopenharmony_ci                if ((s = i2s_ASN1_INTEGER(NULL, aor->u.range->max)) == NULL)
921cb0ef41Sopenharmony_ci                    return 0;
931cb0ef41Sopenharmony_ci                BIO_printf(out, "%s\n", s);
941cb0ef41Sopenharmony_ci                OPENSSL_free(s);
951cb0ef41Sopenharmony_ci                break;
961cb0ef41Sopenharmony_ci            default:
971cb0ef41Sopenharmony_ci                return 0;
981cb0ef41Sopenharmony_ci            }
991cb0ef41Sopenharmony_ci        }
1001cb0ef41Sopenharmony_ci        break;
1011cb0ef41Sopenharmony_ci    default:
1021cb0ef41Sopenharmony_ci        return 0;
1031cb0ef41Sopenharmony_ci    }
1041cb0ef41Sopenharmony_ci    return 1;
1051cb0ef41Sopenharmony_ci}
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci/*
1081cb0ef41Sopenharmony_ci * i2r method for an ASIdentifier extension.
1091cb0ef41Sopenharmony_ci */
1101cb0ef41Sopenharmony_cistatic int i2r_ASIdentifiers(const X509V3_EXT_METHOD *method,
1111cb0ef41Sopenharmony_ci                             void *ext, BIO *out, int indent)
1121cb0ef41Sopenharmony_ci{
1131cb0ef41Sopenharmony_ci    ASIdentifiers *asid = ext;
1141cb0ef41Sopenharmony_ci    return (i2r_ASIdentifierChoice(out, asid->asnum, indent,
1151cb0ef41Sopenharmony_ci                                   "Autonomous System Numbers") &&
1161cb0ef41Sopenharmony_ci            i2r_ASIdentifierChoice(out, asid->rdi, indent,
1171cb0ef41Sopenharmony_ci                                   "Routing Domain Identifiers"));
1181cb0ef41Sopenharmony_ci}
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci/*
1211cb0ef41Sopenharmony_ci * Sort comparison function for a sequence of ASIdOrRange elements.
1221cb0ef41Sopenharmony_ci */
1231cb0ef41Sopenharmony_cistatic int ASIdOrRange_cmp(const ASIdOrRange *const *a_,
1241cb0ef41Sopenharmony_ci                           const ASIdOrRange *const *b_)
1251cb0ef41Sopenharmony_ci{
1261cb0ef41Sopenharmony_ci    const ASIdOrRange *a = *a_, *b = *b_;
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_ci    assert((a->type == ASIdOrRange_id && a->u.id != NULL) ||
1291cb0ef41Sopenharmony_ci           (a->type == ASIdOrRange_range && a->u.range != NULL &&
1301cb0ef41Sopenharmony_ci            a->u.range->min != NULL && a->u.range->max != NULL));
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_ci    assert((b->type == ASIdOrRange_id && b->u.id != NULL) ||
1331cb0ef41Sopenharmony_ci           (b->type == ASIdOrRange_range && b->u.range != NULL &&
1341cb0ef41Sopenharmony_ci            b->u.range->min != NULL && b->u.range->max != NULL));
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci    if (a->type == ASIdOrRange_id && b->type == ASIdOrRange_id)
1371cb0ef41Sopenharmony_ci        return ASN1_INTEGER_cmp(a->u.id, b->u.id);
1381cb0ef41Sopenharmony_ci
1391cb0ef41Sopenharmony_ci    if (a->type == ASIdOrRange_range && b->type == ASIdOrRange_range) {
1401cb0ef41Sopenharmony_ci        int r = ASN1_INTEGER_cmp(a->u.range->min, b->u.range->min);
1411cb0ef41Sopenharmony_ci        return r != 0 ? r : ASN1_INTEGER_cmp(a->u.range->max,
1421cb0ef41Sopenharmony_ci                                             b->u.range->max);
1431cb0ef41Sopenharmony_ci    }
1441cb0ef41Sopenharmony_ci
1451cb0ef41Sopenharmony_ci    if (a->type == ASIdOrRange_id)
1461cb0ef41Sopenharmony_ci        return ASN1_INTEGER_cmp(a->u.id, b->u.range->min);
1471cb0ef41Sopenharmony_ci    else
1481cb0ef41Sopenharmony_ci        return ASN1_INTEGER_cmp(a->u.range->min, b->u.id);
1491cb0ef41Sopenharmony_ci}
1501cb0ef41Sopenharmony_ci
1511cb0ef41Sopenharmony_ci/*
1521cb0ef41Sopenharmony_ci * Add an inherit element.
1531cb0ef41Sopenharmony_ci */
1541cb0ef41Sopenharmony_ciint X509v3_asid_add_inherit(ASIdentifiers *asid, int which)
1551cb0ef41Sopenharmony_ci{
1561cb0ef41Sopenharmony_ci    ASIdentifierChoice **choice;
1571cb0ef41Sopenharmony_ci    if (asid == NULL)
1581cb0ef41Sopenharmony_ci        return 0;
1591cb0ef41Sopenharmony_ci    switch (which) {
1601cb0ef41Sopenharmony_ci    case V3_ASID_ASNUM:
1611cb0ef41Sopenharmony_ci        choice = &asid->asnum;
1621cb0ef41Sopenharmony_ci        break;
1631cb0ef41Sopenharmony_ci    case V3_ASID_RDI:
1641cb0ef41Sopenharmony_ci        choice = &asid->rdi;
1651cb0ef41Sopenharmony_ci        break;
1661cb0ef41Sopenharmony_ci    default:
1671cb0ef41Sopenharmony_ci        return 0;
1681cb0ef41Sopenharmony_ci    }
1691cb0ef41Sopenharmony_ci    if (*choice == NULL) {
1701cb0ef41Sopenharmony_ci        if ((*choice = ASIdentifierChoice_new()) == NULL)
1711cb0ef41Sopenharmony_ci            return 0;
1721cb0ef41Sopenharmony_ci        if (((*choice)->u.inherit = ASN1_NULL_new()) == NULL) {
1731cb0ef41Sopenharmony_ci            ASIdentifierChoice_free(*choice);
1741cb0ef41Sopenharmony_ci            *choice = NULL;
1751cb0ef41Sopenharmony_ci            return 0;
1761cb0ef41Sopenharmony_ci        }
1771cb0ef41Sopenharmony_ci        (*choice)->type = ASIdentifierChoice_inherit;
1781cb0ef41Sopenharmony_ci    }
1791cb0ef41Sopenharmony_ci    return (*choice)->type == ASIdentifierChoice_inherit;
1801cb0ef41Sopenharmony_ci}
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ci/*
1831cb0ef41Sopenharmony_ci * Add an ID or range to an ASIdentifierChoice.
1841cb0ef41Sopenharmony_ci */
1851cb0ef41Sopenharmony_ciint X509v3_asid_add_id_or_range(ASIdentifiers *asid,
1861cb0ef41Sopenharmony_ci                                int which, ASN1_INTEGER *min, ASN1_INTEGER *max)
1871cb0ef41Sopenharmony_ci{
1881cb0ef41Sopenharmony_ci    ASIdentifierChoice **choice;
1891cb0ef41Sopenharmony_ci    ASIdOrRange *aor;
1901cb0ef41Sopenharmony_ci    if (asid == NULL)
1911cb0ef41Sopenharmony_ci        return 0;
1921cb0ef41Sopenharmony_ci    switch (which) {
1931cb0ef41Sopenharmony_ci    case V3_ASID_ASNUM:
1941cb0ef41Sopenharmony_ci        choice = &asid->asnum;
1951cb0ef41Sopenharmony_ci        break;
1961cb0ef41Sopenharmony_ci    case V3_ASID_RDI:
1971cb0ef41Sopenharmony_ci        choice = &asid->rdi;
1981cb0ef41Sopenharmony_ci        break;
1991cb0ef41Sopenharmony_ci    default:
2001cb0ef41Sopenharmony_ci        return 0;
2011cb0ef41Sopenharmony_ci    }
2021cb0ef41Sopenharmony_ci    if (*choice != NULL && (*choice)->type != ASIdentifierChoice_asIdsOrRanges)
2031cb0ef41Sopenharmony_ci        return 0;
2041cb0ef41Sopenharmony_ci    if (*choice == NULL) {
2051cb0ef41Sopenharmony_ci        if ((*choice = ASIdentifierChoice_new()) == NULL)
2061cb0ef41Sopenharmony_ci            return 0;
2071cb0ef41Sopenharmony_ci        (*choice)->u.asIdsOrRanges = sk_ASIdOrRange_new(ASIdOrRange_cmp);
2081cb0ef41Sopenharmony_ci        if ((*choice)->u.asIdsOrRanges == NULL) {
2091cb0ef41Sopenharmony_ci            ASIdentifierChoice_free(*choice);
2101cb0ef41Sopenharmony_ci            *choice = NULL;
2111cb0ef41Sopenharmony_ci            return 0;
2121cb0ef41Sopenharmony_ci        }
2131cb0ef41Sopenharmony_ci        (*choice)->type = ASIdentifierChoice_asIdsOrRanges;
2141cb0ef41Sopenharmony_ci    }
2151cb0ef41Sopenharmony_ci    if ((aor = ASIdOrRange_new()) == NULL)
2161cb0ef41Sopenharmony_ci        return 0;
2171cb0ef41Sopenharmony_ci    if (!sk_ASIdOrRange_reserve((*choice)->u.asIdsOrRanges, 1))
2181cb0ef41Sopenharmony_ci        goto err;
2191cb0ef41Sopenharmony_ci    if (max == NULL) {
2201cb0ef41Sopenharmony_ci        aor->type = ASIdOrRange_id;
2211cb0ef41Sopenharmony_ci        aor->u.id = min;
2221cb0ef41Sopenharmony_ci    } else {
2231cb0ef41Sopenharmony_ci        aor->type = ASIdOrRange_range;
2241cb0ef41Sopenharmony_ci        if ((aor->u.range = ASRange_new()) == NULL)
2251cb0ef41Sopenharmony_ci            goto err;
2261cb0ef41Sopenharmony_ci        ASN1_INTEGER_free(aor->u.range->min);
2271cb0ef41Sopenharmony_ci        aor->u.range->min = min;
2281cb0ef41Sopenharmony_ci        ASN1_INTEGER_free(aor->u.range->max);
2291cb0ef41Sopenharmony_ci        aor->u.range->max = max;
2301cb0ef41Sopenharmony_ci    }
2311cb0ef41Sopenharmony_ci    /* Cannot fail due to the reservation above */
2321cb0ef41Sopenharmony_ci    if (!ossl_assert(sk_ASIdOrRange_push((*choice)->u.asIdsOrRanges, aor)))
2331cb0ef41Sopenharmony_ci        goto err;
2341cb0ef41Sopenharmony_ci    return 1;
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_ci err:
2371cb0ef41Sopenharmony_ci    ASIdOrRange_free(aor);
2381cb0ef41Sopenharmony_ci    return 0;
2391cb0ef41Sopenharmony_ci}
2401cb0ef41Sopenharmony_ci
2411cb0ef41Sopenharmony_ci/*
2421cb0ef41Sopenharmony_ci * Extract min and max values from an ASIdOrRange.
2431cb0ef41Sopenharmony_ci */
2441cb0ef41Sopenharmony_cistatic int extract_min_max(ASIdOrRange *aor,
2451cb0ef41Sopenharmony_ci                           ASN1_INTEGER **min, ASN1_INTEGER **max)
2461cb0ef41Sopenharmony_ci{
2471cb0ef41Sopenharmony_ci    if (!ossl_assert(aor != NULL))
2481cb0ef41Sopenharmony_ci        return 0;
2491cb0ef41Sopenharmony_ci    switch (aor->type) {
2501cb0ef41Sopenharmony_ci    case ASIdOrRange_id:
2511cb0ef41Sopenharmony_ci        *min = aor->u.id;
2521cb0ef41Sopenharmony_ci        *max = aor->u.id;
2531cb0ef41Sopenharmony_ci        return 1;
2541cb0ef41Sopenharmony_ci    case ASIdOrRange_range:
2551cb0ef41Sopenharmony_ci        *min = aor->u.range->min;
2561cb0ef41Sopenharmony_ci        *max = aor->u.range->max;
2571cb0ef41Sopenharmony_ci        return 1;
2581cb0ef41Sopenharmony_ci    }
2591cb0ef41Sopenharmony_ci
2601cb0ef41Sopenharmony_ci    return 0;
2611cb0ef41Sopenharmony_ci}
2621cb0ef41Sopenharmony_ci
2631cb0ef41Sopenharmony_ci/*
2641cb0ef41Sopenharmony_ci * Check whether an ASIdentifierChoice is in canonical form.
2651cb0ef41Sopenharmony_ci */
2661cb0ef41Sopenharmony_cistatic int ASIdentifierChoice_is_canonical(ASIdentifierChoice *choice)
2671cb0ef41Sopenharmony_ci{
2681cb0ef41Sopenharmony_ci    ASN1_INTEGER *a_max_plus_one = NULL;
2691cb0ef41Sopenharmony_ci    ASN1_INTEGER *orig;
2701cb0ef41Sopenharmony_ci    BIGNUM *bn = NULL;
2711cb0ef41Sopenharmony_ci    int i, ret = 0;
2721cb0ef41Sopenharmony_ci
2731cb0ef41Sopenharmony_ci    /*
2741cb0ef41Sopenharmony_ci     * Empty element or inheritance is canonical.
2751cb0ef41Sopenharmony_ci     */
2761cb0ef41Sopenharmony_ci    if (choice == NULL || choice->type == ASIdentifierChoice_inherit)
2771cb0ef41Sopenharmony_ci        return 1;
2781cb0ef41Sopenharmony_ci
2791cb0ef41Sopenharmony_ci    /*
2801cb0ef41Sopenharmony_ci     * If not a list, or if empty list, it's broken.
2811cb0ef41Sopenharmony_ci     */
2821cb0ef41Sopenharmony_ci    if (choice->type != ASIdentifierChoice_asIdsOrRanges ||
2831cb0ef41Sopenharmony_ci        sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0)
2841cb0ef41Sopenharmony_ci        return 0;
2851cb0ef41Sopenharmony_ci
2861cb0ef41Sopenharmony_ci    /*
2871cb0ef41Sopenharmony_ci     * It's a list, check it.
2881cb0ef41Sopenharmony_ci     */
2891cb0ef41Sopenharmony_ci    for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) {
2901cb0ef41Sopenharmony_ci        ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
2911cb0ef41Sopenharmony_ci        ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1);
2921cb0ef41Sopenharmony_ci        ASN1_INTEGER *a_min = NULL, *a_max = NULL, *b_min = NULL, *b_max =
2931cb0ef41Sopenharmony_ci            NULL;
2941cb0ef41Sopenharmony_ci
2951cb0ef41Sopenharmony_ci        if (!extract_min_max(a, &a_min, &a_max)
2961cb0ef41Sopenharmony_ci                || !extract_min_max(b, &b_min, &b_max))
2971cb0ef41Sopenharmony_ci            goto done;
2981cb0ef41Sopenharmony_ci
2991cb0ef41Sopenharmony_ci        /*
3001cb0ef41Sopenharmony_ci         * Punt misordered list, overlapping start, or inverted range.
3011cb0ef41Sopenharmony_ci         */
3021cb0ef41Sopenharmony_ci        if (ASN1_INTEGER_cmp(a_min, b_min) >= 0 ||
3031cb0ef41Sopenharmony_ci            ASN1_INTEGER_cmp(a_min, a_max) > 0 ||
3041cb0ef41Sopenharmony_ci            ASN1_INTEGER_cmp(b_min, b_max) > 0)
3051cb0ef41Sopenharmony_ci            goto done;
3061cb0ef41Sopenharmony_ci
3071cb0ef41Sopenharmony_ci        /*
3081cb0ef41Sopenharmony_ci         * Calculate a_max + 1 to check for adjacency.
3091cb0ef41Sopenharmony_ci         */
3101cb0ef41Sopenharmony_ci        if ((bn == NULL && (bn = BN_new()) == NULL) ||
3111cb0ef41Sopenharmony_ci            ASN1_INTEGER_to_BN(a_max, bn) == NULL ||
3121cb0ef41Sopenharmony_ci            !BN_add_word(bn, 1)) {
3131cb0ef41Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
3141cb0ef41Sopenharmony_ci            goto done;
3151cb0ef41Sopenharmony_ci        }
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci        if ((a_max_plus_one =
3181cb0ef41Sopenharmony_ci                BN_to_ASN1_INTEGER(bn, orig = a_max_plus_one)) == NULL) {
3191cb0ef41Sopenharmony_ci            a_max_plus_one = orig;
3201cb0ef41Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
3211cb0ef41Sopenharmony_ci            goto done;
3221cb0ef41Sopenharmony_ci        }
3231cb0ef41Sopenharmony_ci
3241cb0ef41Sopenharmony_ci        /*
3251cb0ef41Sopenharmony_ci         * Punt if adjacent or overlapping.
3261cb0ef41Sopenharmony_ci         */
3271cb0ef41Sopenharmony_ci        if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) >= 0)
3281cb0ef41Sopenharmony_ci            goto done;
3291cb0ef41Sopenharmony_ci    }
3301cb0ef41Sopenharmony_ci
3311cb0ef41Sopenharmony_ci    /*
3321cb0ef41Sopenharmony_ci     * Check for inverted range.
3331cb0ef41Sopenharmony_ci     */
3341cb0ef41Sopenharmony_ci    i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1;
3351cb0ef41Sopenharmony_ci    {
3361cb0ef41Sopenharmony_ci        ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
3371cb0ef41Sopenharmony_ci        ASN1_INTEGER *a_min, *a_max;
3381cb0ef41Sopenharmony_ci        if (a != NULL && a->type == ASIdOrRange_range) {
3391cb0ef41Sopenharmony_ci            if (!extract_min_max(a, &a_min, &a_max)
3401cb0ef41Sopenharmony_ci                    || ASN1_INTEGER_cmp(a_min, a_max) > 0)
3411cb0ef41Sopenharmony_ci                goto done;
3421cb0ef41Sopenharmony_ci        }
3431cb0ef41Sopenharmony_ci    }
3441cb0ef41Sopenharmony_ci
3451cb0ef41Sopenharmony_ci    ret = 1;
3461cb0ef41Sopenharmony_ci
3471cb0ef41Sopenharmony_ci done:
3481cb0ef41Sopenharmony_ci    ASN1_INTEGER_free(a_max_plus_one);
3491cb0ef41Sopenharmony_ci    BN_free(bn);
3501cb0ef41Sopenharmony_ci    return ret;
3511cb0ef41Sopenharmony_ci}
3521cb0ef41Sopenharmony_ci
3531cb0ef41Sopenharmony_ci/*
3541cb0ef41Sopenharmony_ci * Check whether an ASIdentifier extension is in canonical form.
3551cb0ef41Sopenharmony_ci */
3561cb0ef41Sopenharmony_ciint X509v3_asid_is_canonical(ASIdentifiers *asid)
3571cb0ef41Sopenharmony_ci{
3581cb0ef41Sopenharmony_ci    return (asid == NULL ||
3591cb0ef41Sopenharmony_ci            (ASIdentifierChoice_is_canonical(asid->asnum) &&
3601cb0ef41Sopenharmony_ci             ASIdentifierChoice_is_canonical(asid->rdi)));
3611cb0ef41Sopenharmony_ci}
3621cb0ef41Sopenharmony_ci
3631cb0ef41Sopenharmony_ci/*
3641cb0ef41Sopenharmony_ci * Whack an ASIdentifierChoice into canonical form.
3651cb0ef41Sopenharmony_ci */
3661cb0ef41Sopenharmony_cistatic int ASIdentifierChoice_canonize(ASIdentifierChoice *choice)
3671cb0ef41Sopenharmony_ci{
3681cb0ef41Sopenharmony_ci    ASN1_INTEGER *a_max_plus_one = NULL;
3691cb0ef41Sopenharmony_ci    ASN1_INTEGER *orig;
3701cb0ef41Sopenharmony_ci    BIGNUM *bn = NULL;
3711cb0ef41Sopenharmony_ci    int i, ret = 0;
3721cb0ef41Sopenharmony_ci
3731cb0ef41Sopenharmony_ci    /*
3741cb0ef41Sopenharmony_ci     * Nothing to do for empty element or inheritance.
3751cb0ef41Sopenharmony_ci     */
3761cb0ef41Sopenharmony_ci    if (choice == NULL || choice->type == ASIdentifierChoice_inherit)
3771cb0ef41Sopenharmony_ci        return 1;
3781cb0ef41Sopenharmony_ci
3791cb0ef41Sopenharmony_ci    /*
3801cb0ef41Sopenharmony_ci     * If not a list, or if empty list, it's broken.
3811cb0ef41Sopenharmony_ci     */
3821cb0ef41Sopenharmony_ci    if (choice->type != ASIdentifierChoice_asIdsOrRanges ||
3831cb0ef41Sopenharmony_ci        sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0) {
3841cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
3851cb0ef41Sopenharmony_ci        return 0;
3861cb0ef41Sopenharmony_ci    }
3871cb0ef41Sopenharmony_ci
3881cb0ef41Sopenharmony_ci    /*
3891cb0ef41Sopenharmony_ci     * We have a non-empty list.  Sort it.
3901cb0ef41Sopenharmony_ci     */
3911cb0ef41Sopenharmony_ci    sk_ASIdOrRange_sort(choice->u.asIdsOrRanges);
3921cb0ef41Sopenharmony_ci
3931cb0ef41Sopenharmony_ci    /*
3941cb0ef41Sopenharmony_ci     * Now check for errors and suboptimal encoding, rejecting the
3951cb0ef41Sopenharmony_ci     * former and fixing the latter.
3961cb0ef41Sopenharmony_ci     */
3971cb0ef41Sopenharmony_ci    for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) {
3981cb0ef41Sopenharmony_ci        ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
3991cb0ef41Sopenharmony_ci        ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1);
4001cb0ef41Sopenharmony_ci        ASN1_INTEGER *a_min = NULL, *a_max = NULL, *b_min = NULL, *b_max =
4011cb0ef41Sopenharmony_ci            NULL;
4021cb0ef41Sopenharmony_ci
4031cb0ef41Sopenharmony_ci        if (!extract_min_max(a, &a_min, &a_max)
4041cb0ef41Sopenharmony_ci                || !extract_min_max(b, &b_min, &b_max))
4051cb0ef41Sopenharmony_ci            goto done;
4061cb0ef41Sopenharmony_ci
4071cb0ef41Sopenharmony_ci        /*
4081cb0ef41Sopenharmony_ci         * Make sure we're properly sorted (paranoia).
4091cb0ef41Sopenharmony_ci         */
4101cb0ef41Sopenharmony_ci        if (!ossl_assert(ASN1_INTEGER_cmp(a_min, b_min) <= 0))
4111cb0ef41Sopenharmony_ci            goto done;
4121cb0ef41Sopenharmony_ci
4131cb0ef41Sopenharmony_ci        /*
4141cb0ef41Sopenharmony_ci         * Punt inverted ranges.
4151cb0ef41Sopenharmony_ci         */
4161cb0ef41Sopenharmony_ci        if (ASN1_INTEGER_cmp(a_min, a_max) > 0 ||
4171cb0ef41Sopenharmony_ci            ASN1_INTEGER_cmp(b_min, b_max) > 0)
4181cb0ef41Sopenharmony_ci            goto done;
4191cb0ef41Sopenharmony_ci
4201cb0ef41Sopenharmony_ci        /*
4211cb0ef41Sopenharmony_ci         * Check for overlaps.
4221cb0ef41Sopenharmony_ci         */
4231cb0ef41Sopenharmony_ci        if (ASN1_INTEGER_cmp(a_max, b_min) >= 0) {
4241cb0ef41Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
4251cb0ef41Sopenharmony_ci            goto done;
4261cb0ef41Sopenharmony_ci        }
4271cb0ef41Sopenharmony_ci
4281cb0ef41Sopenharmony_ci        /*
4291cb0ef41Sopenharmony_ci         * Calculate a_max + 1 to check for adjacency.
4301cb0ef41Sopenharmony_ci         */
4311cb0ef41Sopenharmony_ci        if ((bn == NULL && (bn = BN_new()) == NULL) ||
4321cb0ef41Sopenharmony_ci            ASN1_INTEGER_to_BN(a_max, bn) == NULL ||
4331cb0ef41Sopenharmony_ci            !BN_add_word(bn, 1)) {
4341cb0ef41Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
4351cb0ef41Sopenharmony_ci            goto done;
4361cb0ef41Sopenharmony_ci        }
4371cb0ef41Sopenharmony_ci
4381cb0ef41Sopenharmony_ci        if ((a_max_plus_one =
4391cb0ef41Sopenharmony_ci                 BN_to_ASN1_INTEGER(bn, orig = a_max_plus_one)) == NULL) {
4401cb0ef41Sopenharmony_ci            a_max_plus_one = orig;
4411cb0ef41Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
4421cb0ef41Sopenharmony_ci            goto done;
4431cb0ef41Sopenharmony_ci        }
4441cb0ef41Sopenharmony_ci
4451cb0ef41Sopenharmony_ci        /*
4461cb0ef41Sopenharmony_ci         * If a and b are adjacent, merge them.
4471cb0ef41Sopenharmony_ci         */
4481cb0ef41Sopenharmony_ci        if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) == 0) {
4491cb0ef41Sopenharmony_ci            ASRange *r;
4501cb0ef41Sopenharmony_ci            switch (a->type) {
4511cb0ef41Sopenharmony_ci            case ASIdOrRange_id:
4521cb0ef41Sopenharmony_ci                if ((r = OPENSSL_malloc(sizeof(*r))) == NULL) {
4531cb0ef41Sopenharmony_ci                    ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
4541cb0ef41Sopenharmony_ci                    goto done;
4551cb0ef41Sopenharmony_ci                }
4561cb0ef41Sopenharmony_ci                r->min = a_min;
4571cb0ef41Sopenharmony_ci                r->max = b_max;
4581cb0ef41Sopenharmony_ci                a->type = ASIdOrRange_range;
4591cb0ef41Sopenharmony_ci                a->u.range = r;
4601cb0ef41Sopenharmony_ci                break;
4611cb0ef41Sopenharmony_ci            case ASIdOrRange_range:
4621cb0ef41Sopenharmony_ci                ASN1_INTEGER_free(a->u.range->max);
4631cb0ef41Sopenharmony_ci                a->u.range->max = b_max;
4641cb0ef41Sopenharmony_ci                break;
4651cb0ef41Sopenharmony_ci            }
4661cb0ef41Sopenharmony_ci            switch (b->type) {
4671cb0ef41Sopenharmony_ci            case ASIdOrRange_id:
4681cb0ef41Sopenharmony_ci                b->u.id = NULL;
4691cb0ef41Sopenharmony_ci                break;
4701cb0ef41Sopenharmony_ci            case ASIdOrRange_range:
4711cb0ef41Sopenharmony_ci                b->u.range->max = NULL;
4721cb0ef41Sopenharmony_ci                break;
4731cb0ef41Sopenharmony_ci            }
4741cb0ef41Sopenharmony_ci            ASIdOrRange_free(b);
4751cb0ef41Sopenharmony_ci            (void)sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i + 1);
4761cb0ef41Sopenharmony_ci            i--;
4771cb0ef41Sopenharmony_ci            continue;
4781cb0ef41Sopenharmony_ci        }
4791cb0ef41Sopenharmony_ci    }
4801cb0ef41Sopenharmony_ci
4811cb0ef41Sopenharmony_ci    /*
4821cb0ef41Sopenharmony_ci     * Check for final inverted range.
4831cb0ef41Sopenharmony_ci     */
4841cb0ef41Sopenharmony_ci    i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1;
4851cb0ef41Sopenharmony_ci    {
4861cb0ef41Sopenharmony_ci        ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
4871cb0ef41Sopenharmony_ci        ASN1_INTEGER *a_min, *a_max;
4881cb0ef41Sopenharmony_ci        if (a != NULL && a->type == ASIdOrRange_range) {
4891cb0ef41Sopenharmony_ci            if (!extract_min_max(a, &a_min, &a_max)
4901cb0ef41Sopenharmony_ci                    || ASN1_INTEGER_cmp(a_min, a_max) > 0)
4911cb0ef41Sopenharmony_ci                goto done;
4921cb0ef41Sopenharmony_ci        }
4931cb0ef41Sopenharmony_ci    }
4941cb0ef41Sopenharmony_ci
4951cb0ef41Sopenharmony_ci    /* Paranoia */
4961cb0ef41Sopenharmony_ci    if (!ossl_assert(ASIdentifierChoice_is_canonical(choice)))
4971cb0ef41Sopenharmony_ci        goto done;
4981cb0ef41Sopenharmony_ci
4991cb0ef41Sopenharmony_ci    ret = 1;
5001cb0ef41Sopenharmony_ci
5011cb0ef41Sopenharmony_ci done:
5021cb0ef41Sopenharmony_ci    ASN1_INTEGER_free(a_max_plus_one);
5031cb0ef41Sopenharmony_ci    BN_free(bn);
5041cb0ef41Sopenharmony_ci    return ret;
5051cb0ef41Sopenharmony_ci}
5061cb0ef41Sopenharmony_ci
5071cb0ef41Sopenharmony_ci/*
5081cb0ef41Sopenharmony_ci * Whack an ASIdentifier extension into canonical form.
5091cb0ef41Sopenharmony_ci */
5101cb0ef41Sopenharmony_ciint X509v3_asid_canonize(ASIdentifiers *asid)
5111cb0ef41Sopenharmony_ci{
5121cb0ef41Sopenharmony_ci    return (asid == NULL ||
5131cb0ef41Sopenharmony_ci            (ASIdentifierChoice_canonize(asid->asnum) &&
5141cb0ef41Sopenharmony_ci             ASIdentifierChoice_canonize(asid->rdi)));
5151cb0ef41Sopenharmony_ci}
5161cb0ef41Sopenharmony_ci
5171cb0ef41Sopenharmony_ci/*
5181cb0ef41Sopenharmony_ci * v2i method for an ASIdentifier extension.
5191cb0ef41Sopenharmony_ci */
5201cb0ef41Sopenharmony_cistatic void *v2i_ASIdentifiers(const struct v3_ext_method *method,
5211cb0ef41Sopenharmony_ci                               struct v3_ext_ctx *ctx,
5221cb0ef41Sopenharmony_ci                               STACK_OF(CONF_VALUE) *values)
5231cb0ef41Sopenharmony_ci{
5241cb0ef41Sopenharmony_ci    ASN1_INTEGER *min = NULL, *max = NULL;
5251cb0ef41Sopenharmony_ci    ASIdentifiers *asid = NULL;
5261cb0ef41Sopenharmony_ci    int i;
5271cb0ef41Sopenharmony_ci
5281cb0ef41Sopenharmony_ci    if ((asid = ASIdentifiers_new()) == NULL) {
5291cb0ef41Sopenharmony_ci        ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
5301cb0ef41Sopenharmony_ci        return NULL;
5311cb0ef41Sopenharmony_ci    }
5321cb0ef41Sopenharmony_ci
5331cb0ef41Sopenharmony_ci    for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
5341cb0ef41Sopenharmony_ci        CONF_VALUE *val = sk_CONF_VALUE_value(values, i);
5351cb0ef41Sopenharmony_ci        int i1 = 0, i2 = 0, i3 = 0, is_range = 0, which = 0;
5361cb0ef41Sopenharmony_ci
5371cb0ef41Sopenharmony_ci        /*
5381cb0ef41Sopenharmony_ci         * Figure out whether this is an AS or an RDI.
5391cb0ef41Sopenharmony_ci         */
5401cb0ef41Sopenharmony_ci        if (!ossl_v3_name_cmp(val->name, "AS")) {
5411cb0ef41Sopenharmony_ci            which = V3_ASID_ASNUM;
5421cb0ef41Sopenharmony_ci        } else if (!ossl_v3_name_cmp(val->name, "RDI")) {
5431cb0ef41Sopenharmony_ci            which = V3_ASID_RDI;
5441cb0ef41Sopenharmony_ci        } else {
5451cb0ef41Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_NAME_ERROR);
5461cb0ef41Sopenharmony_ci            X509V3_conf_add_error_name_value(val);
5471cb0ef41Sopenharmony_ci            goto err;
5481cb0ef41Sopenharmony_ci        }
5491cb0ef41Sopenharmony_ci
5501cb0ef41Sopenharmony_ci        if (val->value == NULL) {
5511cb0ef41Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
5521cb0ef41Sopenharmony_ci            goto err;
5531cb0ef41Sopenharmony_ci        }
5541cb0ef41Sopenharmony_ci
5551cb0ef41Sopenharmony_ci        /*
5561cb0ef41Sopenharmony_ci         * Handle inheritance.
5571cb0ef41Sopenharmony_ci         */
5581cb0ef41Sopenharmony_ci        if (strcmp(val->value, "inherit") == 0) {
5591cb0ef41Sopenharmony_ci            if (X509v3_asid_add_inherit(asid, which))
5601cb0ef41Sopenharmony_ci                continue;
5611cb0ef41Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_INHERITANCE);
5621cb0ef41Sopenharmony_ci            X509V3_conf_add_error_name_value(val);
5631cb0ef41Sopenharmony_ci            goto err;
5641cb0ef41Sopenharmony_ci        }
5651cb0ef41Sopenharmony_ci
5661cb0ef41Sopenharmony_ci        /*
5671cb0ef41Sopenharmony_ci         * Number, range, or mistake, pick it apart and figure out which.
5681cb0ef41Sopenharmony_ci         */
5691cb0ef41Sopenharmony_ci        i1 = strspn(val->value, "0123456789");
5701cb0ef41Sopenharmony_ci        if (val->value[i1] == '\0') {
5711cb0ef41Sopenharmony_ci            is_range = 0;
5721cb0ef41Sopenharmony_ci        } else {
5731cb0ef41Sopenharmony_ci            is_range = 1;
5741cb0ef41Sopenharmony_ci            i2 = i1 + strspn(val->value + i1, " \t");
5751cb0ef41Sopenharmony_ci            if (val->value[i2] != '-') {
5761cb0ef41Sopenharmony_ci                ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_ASNUMBER);
5771cb0ef41Sopenharmony_ci                X509V3_conf_add_error_name_value(val);
5781cb0ef41Sopenharmony_ci                goto err;
5791cb0ef41Sopenharmony_ci            }
5801cb0ef41Sopenharmony_ci            i2++;
5811cb0ef41Sopenharmony_ci            i2 = i2 + strspn(val->value + i2, " \t");
5821cb0ef41Sopenharmony_ci            i3 = i2 + strspn(val->value + i2, "0123456789");
5831cb0ef41Sopenharmony_ci            if (val->value[i3] != '\0') {
5841cb0ef41Sopenharmony_ci                ERR_raise(ERR_LIB_X509V3, X509V3_R_INVALID_ASRANGE);
5851cb0ef41Sopenharmony_ci                X509V3_conf_add_error_name_value(val);
5861cb0ef41Sopenharmony_ci                goto err;
5871cb0ef41Sopenharmony_ci            }
5881cb0ef41Sopenharmony_ci        }
5891cb0ef41Sopenharmony_ci
5901cb0ef41Sopenharmony_ci        /*
5911cb0ef41Sopenharmony_ci         * Syntax is ok, read and add it.
5921cb0ef41Sopenharmony_ci         */
5931cb0ef41Sopenharmony_ci        if (!is_range) {
5941cb0ef41Sopenharmony_ci            if (!X509V3_get_value_int(val, &min)) {
5951cb0ef41Sopenharmony_ci                ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
5961cb0ef41Sopenharmony_ci                goto err;
5971cb0ef41Sopenharmony_ci            }
5981cb0ef41Sopenharmony_ci        } else {
5991cb0ef41Sopenharmony_ci            char *s = OPENSSL_strdup(val->value);
6001cb0ef41Sopenharmony_ci            if (s == NULL) {
6011cb0ef41Sopenharmony_ci                ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
6021cb0ef41Sopenharmony_ci                goto err;
6031cb0ef41Sopenharmony_ci            }
6041cb0ef41Sopenharmony_ci            s[i1] = '\0';
6051cb0ef41Sopenharmony_ci            min = s2i_ASN1_INTEGER(NULL, s);
6061cb0ef41Sopenharmony_ci            max = s2i_ASN1_INTEGER(NULL, s + i2);
6071cb0ef41Sopenharmony_ci            OPENSSL_free(s);
6081cb0ef41Sopenharmony_ci            if (min == NULL || max == NULL) {
6091cb0ef41Sopenharmony_ci                ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
6101cb0ef41Sopenharmony_ci                goto err;
6111cb0ef41Sopenharmony_ci            }
6121cb0ef41Sopenharmony_ci            if (ASN1_INTEGER_cmp(min, max) > 0) {
6131cb0ef41Sopenharmony_ci                ERR_raise(ERR_LIB_X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
6141cb0ef41Sopenharmony_ci                goto err;
6151cb0ef41Sopenharmony_ci            }
6161cb0ef41Sopenharmony_ci        }
6171cb0ef41Sopenharmony_ci        if (!X509v3_asid_add_id_or_range(asid, which, min, max)) {
6181cb0ef41Sopenharmony_ci            ERR_raise(ERR_LIB_X509V3, ERR_R_MALLOC_FAILURE);
6191cb0ef41Sopenharmony_ci            goto err;
6201cb0ef41Sopenharmony_ci        }
6211cb0ef41Sopenharmony_ci        min = max = NULL;
6221cb0ef41Sopenharmony_ci    }
6231cb0ef41Sopenharmony_ci
6241cb0ef41Sopenharmony_ci    /*
6251cb0ef41Sopenharmony_ci     * Canonize the result, then we're done.
6261cb0ef41Sopenharmony_ci     */
6271cb0ef41Sopenharmony_ci    if (!X509v3_asid_canonize(asid))
6281cb0ef41Sopenharmony_ci        goto err;
6291cb0ef41Sopenharmony_ci    return asid;
6301cb0ef41Sopenharmony_ci
6311cb0ef41Sopenharmony_ci err:
6321cb0ef41Sopenharmony_ci    ASIdentifiers_free(asid);
6331cb0ef41Sopenharmony_ci    ASN1_INTEGER_free(min);
6341cb0ef41Sopenharmony_ci    ASN1_INTEGER_free(max);
6351cb0ef41Sopenharmony_ci    return NULL;
6361cb0ef41Sopenharmony_ci}
6371cb0ef41Sopenharmony_ci
6381cb0ef41Sopenharmony_ci/*
6391cb0ef41Sopenharmony_ci * OpenSSL dispatch.
6401cb0ef41Sopenharmony_ci */
6411cb0ef41Sopenharmony_ciconst X509V3_EXT_METHOD ossl_v3_asid = {
6421cb0ef41Sopenharmony_ci    NID_sbgp_autonomousSysNum,  /* nid */
6431cb0ef41Sopenharmony_ci    0,                          /* flags */
6441cb0ef41Sopenharmony_ci    ASN1_ITEM_ref(ASIdentifiers), /* template */
6451cb0ef41Sopenharmony_ci    0, 0, 0, 0,                 /* old functions, ignored */
6461cb0ef41Sopenharmony_ci    0,                          /* i2s */
6471cb0ef41Sopenharmony_ci    0,                          /* s2i */
6481cb0ef41Sopenharmony_ci    0,                          /* i2v */
6491cb0ef41Sopenharmony_ci    v2i_ASIdentifiers,          /* v2i */
6501cb0ef41Sopenharmony_ci    i2r_ASIdentifiers,          /* i2r */
6511cb0ef41Sopenharmony_ci    0,                          /* r2i */
6521cb0ef41Sopenharmony_ci    NULL                        /* extension-specific data */
6531cb0ef41Sopenharmony_ci};
6541cb0ef41Sopenharmony_ci
6551cb0ef41Sopenharmony_ci/*
6561cb0ef41Sopenharmony_ci * Figure out whether extension uses inheritance.
6571cb0ef41Sopenharmony_ci */
6581cb0ef41Sopenharmony_ciint X509v3_asid_inherits(ASIdentifiers *asid)
6591cb0ef41Sopenharmony_ci{
6601cb0ef41Sopenharmony_ci    return (asid != NULL &&
6611cb0ef41Sopenharmony_ci            ((asid->asnum != NULL &&
6621cb0ef41Sopenharmony_ci              asid->asnum->type == ASIdentifierChoice_inherit) ||
6631cb0ef41Sopenharmony_ci             (asid->rdi != NULL &&
6641cb0ef41Sopenharmony_ci              asid->rdi->type == ASIdentifierChoice_inherit)));
6651cb0ef41Sopenharmony_ci}
6661cb0ef41Sopenharmony_ci
6671cb0ef41Sopenharmony_ci/*
6681cb0ef41Sopenharmony_ci * Figure out whether parent contains child.
6691cb0ef41Sopenharmony_ci */
6701cb0ef41Sopenharmony_cistatic int asid_contains(ASIdOrRanges *parent, ASIdOrRanges *child)
6711cb0ef41Sopenharmony_ci{
6721cb0ef41Sopenharmony_ci    ASN1_INTEGER *p_min = NULL, *p_max = NULL, *c_min = NULL, *c_max = NULL;
6731cb0ef41Sopenharmony_ci    int p, c;
6741cb0ef41Sopenharmony_ci
6751cb0ef41Sopenharmony_ci    if (child == NULL || parent == child)
6761cb0ef41Sopenharmony_ci        return 1;
6771cb0ef41Sopenharmony_ci    if (parent == NULL)
6781cb0ef41Sopenharmony_ci        return 0;
6791cb0ef41Sopenharmony_ci
6801cb0ef41Sopenharmony_ci    p = 0;
6811cb0ef41Sopenharmony_ci    for (c = 0; c < sk_ASIdOrRange_num(child); c++) {
6821cb0ef41Sopenharmony_ci        if (!extract_min_max(sk_ASIdOrRange_value(child, c), &c_min, &c_max))
6831cb0ef41Sopenharmony_ci            return 0;
6841cb0ef41Sopenharmony_ci        for (;; p++) {
6851cb0ef41Sopenharmony_ci            if (p >= sk_ASIdOrRange_num(parent))
6861cb0ef41Sopenharmony_ci                return 0;
6871cb0ef41Sopenharmony_ci            if (!extract_min_max(sk_ASIdOrRange_value(parent, p), &p_min,
6881cb0ef41Sopenharmony_ci                                 &p_max))
6891cb0ef41Sopenharmony_ci                return 0;
6901cb0ef41Sopenharmony_ci            if (ASN1_INTEGER_cmp(p_max, c_max) < 0)
6911cb0ef41Sopenharmony_ci                continue;
6921cb0ef41Sopenharmony_ci            if (ASN1_INTEGER_cmp(p_min, c_min) > 0)
6931cb0ef41Sopenharmony_ci                return 0;
6941cb0ef41Sopenharmony_ci            break;
6951cb0ef41Sopenharmony_ci        }
6961cb0ef41Sopenharmony_ci    }
6971cb0ef41Sopenharmony_ci
6981cb0ef41Sopenharmony_ci    return 1;
6991cb0ef41Sopenharmony_ci}
7001cb0ef41Sopenharmony_ci
7011cb0ef41Sopenharmony_ci/*
7021cb0ef41Sopenharmony_ci * Test whether a is a subset of b.
7031cb0ef41Sopenharmony_ci */
7041cb0ef41Sopenharmony_ciint X509v3_asid_subset(ASIdentifiers *a, ASIdentifiers *b)
7051cb0ef41Sopenharmony_ci{
7061cb0ef41Sopenharmony_ci    int subset;
7071cb0ef41Sopenharmony_ci
7081cb0ef41Sopenharmony_ci    if (a == NULL || a == b)
7091cb0ef41Sopenharmony_ci        return 1;
7101cb0ef41Sopenharmony_ci
7111cb0ef41Sopenharmony_ci    if (b == NULL)
7121cb0ef41Sopenharmony_ci        return 0;
7131cb0ef41Sopenharmony_ci
7141cb0ef41Sopenharmony_ci    if (X509v3_asid_inherits(a) || X509v3_asid_inherits(b))
7151cb0ef41Sopenharmony_ci        return 0;
7161cb0ef41Sopenharmony_ci
7171cb0ef41Sopenharmony_ci    subset = a->asnum == NULL
7181cb0ef41Sopenharmony_ci             || (b->asnum != NULL
7191cb0ef41Sopenharmony_ci                 && asid_contains(b->asnum->u.asIdsOrRanges,
7201cb0ef41Sopenharmony_ci                                  a->asnum->u.asIdsOrRanges));
7211cb0ef41Sopenharmony_ci    if (!subset)
7221cb0ef41Sopenharmony_ci        return 0;
7231cb0ef41Sopenharmony_ci
7241cb0ef41Sopenharmony_ci    return a->rdi == NULL
7251cb0ef41Sopenharmony_ci           || (b->rdi != NULL
7261cb0ef41Sopenharmony_ci               && asid_contains(b->rdi->u.asIdsOrRanges,
7271cb0ef41Sopenharmony_ci                                a->rdi->u.asIdsOrRanges));
7281cb0ef41Sopenharmony_ci}
7291cb0ef41Sopenharmony_ci
7301cb0ef41Sopenharmony_ci/*
7311cb0ef41Sopenharmony_ci * Validation error handling via callback.
7321cb0ef41Sopenharmony_ci */
7331cb0ef41Sopenharmony_ci#define validation_err(_err_)           \
7341cb0ef41Sopenharmony_ci  do {                                  \
7351cb0ef41Sopenharmony_ci    if (ctx != NULL) {                  \
7361cb0ef41Sopenharmony_ci      ctx->error = _err_;               \
7371cb0ef41Sopenharmony_ci      ctx->error_depth = i;             \
7381cb0ef41Sopenharmony_ci      ctx->current_cert = x;            \
7391cb0ef41Sopenharmony_ci      ret = ctx->verify_cb(0, ctx);     \
7401cb0ef41Sopenharmony_ci    } else {                            \
7411cb0ef41Sopenharmony_ci      ret = 0;                          \
7421cb0ef41Sopenharmony_ci    }                                   \
7431cb0ef41Sopenharmony_ci    if (!ret)                           \
7441cb0ef41Sopenharmony_ci      goto done;                        \
7451cb0ef41Sopenharmony_ci  } while (0)
7461cb0ef41Sopenharmony_ci
7471cb0ef41Sopenharmony_ci/*
7481cb0ef41Sopenharmony_ci * Core code for RFC 3779 3.3 path validation.
7491cb0ef41Sopenharmony_ci */
7501cb0ef41Sopenharmony_cistatic int asid_validate_path_internal(X509_STORE_CTX *ctx,
7511cb0ef41Sopenharmony_ci                                       STACK_OF(X509) *chain,
7521cb0ef41Sopenharmony_ci                                       ASIdentifiers *ext)
7531cb0ef41Sopenharmony_ci{
7541cb0ef41Sopenharmony_ci    ASIdOrRanges *child_as = NULL, *child_rdi = NULL;
7551cb0ef41Sopenharmony_ci    int i, ret = 1, inherit_as = 0, inherit_rdi = 0;
7561cb0ef41Sopenharmony_ci    X509 *x;
7571cb0ef41Sopenharmony_ci
7581cb0ef41Sopenharmony_ci    if (!ossl_assert(chain != NULL && sk_X509_num(chain) > 0)
7591cb0ef41Sopenharmony_ci            || !ossl_assert(ctx != NULL || ext != NULL)
7601cb0ef41Sopenharmony_ci            || !ossl_assert(ctx == NULL || ctx->verify_cb != NULL)) {
7611cb0ef41Sopenharmony_ci        if (ctx != NULL)
7621cb0ef41Sopenharmony_ci            ctx->error = X509_V_ERR_UNSPECIFIED;
7631cb0ef41Sopenharmony_ci        return 0;
7641cb0ef41Sopenharmony_ci    }
7651cb0ef41Sopenharmony_ci
7661cb0ef41Sopenharmony_ci
7671cb0ef41Sopenharmony_ci    /*
7681cb0ef41Sopenharmony_ci     * Figure out where to start.  If we don't have an extension to
7691cb0ef41Sopenharmony_ci     * check, we're done.  Otherwise, check canonical form and
7701cb0ef41Sopenharmony_ci     * set up for walking up the chain.
7711cb0ef41Sopenharmony_ci     */
7721cb0ef41Sopenharmony_ci    if (ext != NULL) {
7731cb0ef41Sopenharmony_ci        i = -1;
7741cb0ef41Sopenharmony_ci        x = NULL;
7751cb0ef41Sopenharmony_ci    } else {
7761cb0ef41Sopenharmony_ci        i = 0;
7771cb0ef41Sopenharmony_ci        x = sk_X509_value(chain, i);
7781cb0ef41Sopenharmony_ci        if ((ext = x->rfc3779_asid) == NULL)
7791cb0ef41Sopenharmony_ci            goto done;
7801cb0ef41Sopenharmony_ci    }
7811cb0ef41Sopenharmony_ci    if (!X509v3_asid_is_canonical(ext))
7821cb0ef41Sopenharmony_ci        validation_err(X509_V_ERR_INVALID_EXTENSION);
7831cb0ef41Sopenharmony_ci    if (ext->asnum != NULL) {
7841cb0ef41Sopenharmony_ci        switch (ext->asnum->type) {
7851cb0ef41Sopenharmony_ci        case ASIdentifierChoice_inherit:
7861cb0ef41Sopenharmony_ci            inherit_as = 1;
7871cb0ef41Sopenharmony_ci            break;
7881cb0ef41Sopenharmony_ci        case ASIdentifierChoice_asIdsOrRanges:
7891cb0ef41Sopenharmony_ci            child_as = ext->asnum->u.asIdsOrRanges;
7901cb0ef41Sopenharmony_ci            break;
7911cb0ef41Sopenharmony_ci        }
7921cb0ef41Sopenharmony_ci    }
7931cb0ef41Sopenharmony_ci    if (ext->rdi != NULL) {
7941cb0ef41Sopenharmony_ci        switch (ext->rdi->type) {
7951cb0ef41Sopenharmony_ci        case ASIdentifierChoice_inherit:
7961cb0ef41Sopenharmony_ci            inherit_rdi = 1;
7971cb0ef41Sopenharmony_ci            break;
7981cb0ef41Sopenharmony_ci        case ASIdentifierChoice_asIdsOrRanges:
7991cb0ef41Sopenharmony_ci            child_rdi = ext->rdi->u.asIdsOrRanges;
8001cb0ef41Sopenharmony_ci            break;
8011cb0ef41Sopenharmony_ci        }
8021cb0ef41Sopenharmony_ci    }
8031cb0ef41Sopenharmony_ci
8041cb0ef41Sopenharmony_ci    /*
8051cb0ef41Sopenharmony_ci     * Now walk up the chain.  Extensions must be in canonical form, no
8061cb0ef41Sopenharmony_ci     * cert may list resources that its parent doesn't list.
8071cb0ef41Sopenharmony_ci     */
8081cb0ef41Sopenharmony_ci    for (i++; i < sk_X509_num(chain); i++) {
8091cb0ef41Sopenharmony_ci        x = sk_X509_value(chain, i);
8101cb0ef41Sopenharmony_ci        if (!ossl_assert(x != NULL)) {
8111cb0ef41Sopenharmony_ci            if (ctx != NULL)
8121cb0ef41Sopenharmony_ci                ctx->error = X509_V_ERR_UNSPECIFIED;
8131cb0ef41Sopenharmony_ci            return 0;
8141cb0ef41Sopenharmony_ci        }
8151cb0ef41Sopenharmony_ci        if (x->rfc3779_asid == NULL) {
8161cb0ef41Sopenharmony_ci            if (child_as != NULL || child_rdi != NULL)
8171cb0ef41Sopenharmony_ci                validation_err(X509_V_ERR_UNNESTED_RESOURCE);
8181cb0ef41Sopenharmony_ci            continue;
8191cb0ef41Sopenharmony_ci        }
8201cb0ef41Sopenharmony_ci        if (!X509v3_asid_is_canonical(x->rfc3779_asid))
8211cb0ef41Sopenharmony_ci            validation_err(X509_V_ERR_INVALID_EXTENSION);
8221cb0ef41Sopenharmony_ci        if (x->rfc3779_asid->asnum == NULL && child_as != NULL) {
8231cb0ef41Sopenharmony_ci            validation_err(X509_V_ERR_UNNESTED_RESOURCE);
8241cb0ef41Sopenharmony_ci            child_as = NULL;
8251cb0ef41Sopenharmony_ci            inherit_as = 0;
8261cb0ef41Sopenharmony_ci        }
8271cb0ef41Sopenharmony_ci        if (x->rfc3779_asid->asnum != NULL &&
8281cb0ef41Sopenharmony_ci            x->rfc3779_asid->asnum->type ==
8291cb0ef41Sopenharmony_ci            ASIdentifierChoice_asIdsOrRanges) {
8301cb0ef41Sopenharmony_ci            if (inherit_as
8311cb0ef41Sopenharmony_ci                || asid_contains(x->rfc3779_asid->asnum->u.asIdsOrRanges,
8321cb0ef41Sopenharmony_ci                                 child_as)) {
8331cb0ef41Sopenharmony_ci                child_as = x->rfc3779_asid->asnum->u.asIdsOrRanges;
8341cb0ef41Sopenharmony_ci                inherit_as = 0;
8351cb0ef41Sopenharmony_ci            } else {
8361cb0ef41Sopenharmony_ci                validation_err(X509_V_ERR_UNNESTED_RESOURCE);
8371cb0ef41Sopenharmony_ci            }
8381cb0ef41Sopenharmony_ci        }
8391cb0ef41Sopenharmony_ci        if (x->rfc3779_asid->rdi == NULL && child_rdi != NULL) {
8401cb0ef41Sopenharmony_ci            validation_err(X509_V_ERR_UNNESTED_RESOURCE);
8411cb0ef41Sopenharmony_ci            child_rdi = NULL;
8421cb0ef41Sopenharmony_ci            inherit_rdi = 0;
8431cb0ef41Sopenharmony_ci        }
8441cb0ef41Sopenharmony_ci        if (x->rfc3779_asid->rdi != NULL &&
8451cb0ef41Sopenharmony_ci            x->rfc3779_asid->rdi->type == ASIdentifierChoice_asIdsOrRanges) {
8461cb0ef41Sopenharmony_ci            if (inherit_rdi ||
8471cb0ef41Sopenharmony_ci                asid_contains(x->rfc3779_asid->rdi->u.asIdsOrRanges,
8481cb0ef41Sopenharmony_ci                              child_rdi)) {
8491cb0ef41Sopenharmony_ci                child_rdi = x->rfc3779_asid->rdi->u.asIdsOrRanges;
8501cb0ef41Sopenharmony_ci                inherit_rdi = 0;
8511cb0ef41Sopenharmony_ci            } else {
8521cb0ef41Sopenharmony_ci                validation_err(X509_V_ERR_UNNESTED_RESOURCE);
8531cb0ef41Sopenharmony_ci            }
8541cb0ef41Sopenharmony_ci        }
8551cb0ef41Sopenharmony_ci    }
8561cb0ef41Sopenharmony_ci
8571cb0ef41Sopenharmony_ci    /*
8581cb0ef41Sopenharmony_ci     * Trust anchor can't inherit.
8591cb0ef41Sopenharmony_ci     */
8601cb0ef41Sopenharmony_ci    if (!ossl_assert(x != NULL)) {
8611cb0ef41Sopenharmony_ci        if (ctx != NULL)
8621cb0ef41Sopenharmony_ci            ctx->error = X509_V_ERR_UNSPECIFIED;
8631cb0ef41Sopenharmony_ci        return 0;
8641cb0ef41Sopenharmony_ci    }
8651cb0ef41Sopenharmony_ci    if (x->rfc3779_asid != NULL) {
8661cb0ef41Sopenharmony_ci        if (x->rfc3779_asid->asnum != NULL &&
8671cb0ef41Sopenharmony_ci            x->rfc3779_asid->asnum->type == ASIdentifierChoice_inherit)
8681cb0ef41Sopenharmony_ci            validation_err(X509_V_ERR_UNNESTED_RESOURCE);
8691cb0ef41Sopenharmony_ci        if (x->rfc3779_asid->rdi != NULL &&
8701cb0ef41Sopenharmony_ci            x->rfc3779_asid->rdi->type == ASIdentifierChoice_inherit)
8711cb0ef41Sopenharmony_ci            validation_err(X509_V_ERR_UNNESTED_RESOURCE);
8721cb0ef41Sopenharmony_ci    }
8731cb0ef41Sopenharmony_ci
8741cb0ef41Sopenharmony_ci done:
8751cb0ef41Sopenharmony_ci    return ret;
8761cb0ef41Sopenharmony_ci}
8771cb0ef41Sopenharmony_ci
8781cb0ef41Sopenharmony_ci#undef validation_err
8791cb0ef41Sopenharmony_ci
8801cb0ef41Sopenharmony_ci/*
8811cb0ef41Sopenharmony_ci * RFC 3779 3.3 path validation -- called from X509_verify_cert().
8821cb0ef41Sopenharmony_ci */
8831cb0ef41Sopenharmony_ciint X509v3_asid_validate_path(X509_STORE_CTX *ctx)
8841cb0ef41Sopenharmony_ci{
8851cb0ef41Sopenharmony_ci    if (ctx->chain == NULL
8861cb0ef41Sopenharmony_ci            || sk_X509_num(ctx->chain) == 0
8871cb0ef41Sopenharmony_ci            || ctx->verify_cb == NULL) {
8881cb0ef41Sopenharmony_ci        ctx->error = X509_V_ERR_UNSPECIFIED;
8891cb0ef41Sopenharmony_ci        return 0;
8901cb0ef41Sopenharmony_ci    }
8911cb0ef41Sopenharmony_ci    return asid_validate_path_internal(ctx, ctx->chain, NULL);
8921cb0ef41Sopenharmony_ci}
8931cb0ef41Sopenharmony_ci
8941cb0ef41Sopenharmony_ci/*
8951cb0ef41Sopenharmony_ci * RFC 3779 3.3 path validation of an extension.
8961cb0ef41Sopenharmony_ci * Test whether chain covers extension.
8971cb0ef41Sopenharmony_ci */
8981cb0ef41Sopenharmony_ciint X509v3_asid_validate_resource_set(STACK_OF(X509) *chain,
8991cb0ef41Sopenharmony_ci                                      ASIdentifiers *ext, int allow_inheritance)
9001cb0ef41Sopenharmony_ci{
9011cb0ef41Sopenharmony_ci    if (ext == NULL)
9021cb0ef41Sopenharmony_ci        return 1;
9031cb0ef41Sopenharmony_ci    if (chain == NULL || sk_X509_num(chain) == 0)
9041cb0ef41Sopenharmony_ci        return 0;
9051cb0ef41Sopenharmony_ci    if (!allow_inheritance && X509v3_asid_inherits(ext))
9061cb0ef41Sopenharmony_ci        return 0;
9071cb0ef41Sopenharmony_ci    return asid_validate_path_internal(NULL, chain, ext);
9081cb0ef41Sopenharmony_ci}
9091cb0ef41Sopenharmony_ci
9101cb0ef41Sopenharmony_ci#endif                          /* OPENSSL_NO_RFC3779 */
911