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