1167612Ssimon/* 2167612Ssimon * Contributed to the OpenSSL Project by the American Registry for 3167612Ssimon * Internet Numbers ("ARIN"). 4167612Ssimon */ 5167612Ssimon/* ==================================================================== 6167612Ssimon * Copyright (c) 2006 The OpenSSL Project. All rights reserved. 7167612Ssimon * 8167612Ssimon * Redistribution and use in source and binary forms, with or without 9167612Ssimon * modification, are permitted provided that the following conditions 10167612Ssimon * are met: 11167612Ssimon * 12167612Ssimon * 1. Redistributions of source code must retain the above copyright 13280297Sjkim * notice, this list of conditions and the following disclaimer. 14167612Ssimon * 15167612Ssimon * 2. Redistributions in binary form must reproduce the above copyright 16167612Ssimon * notice, this list of conditions and the following disclaimer in 17167612Ssimon * the documentation and/or other materials provided with the 18167612Ssimon * distribution. 19167612Ssimon * 20167612Ssimon * 3. All advertising materials mentioning features or use of this 21167612Ssimon * software must display the following acknowledgment: 22167612Ssimon * "This product includes software developed by the OpenSSL Project 23167612Ssimon * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24167612Ssimon * 25167612Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26167612Ssimon * endorse or promote products derived from this software without 27167612Ssimon * prior written permission. For written permission, please contact 28167612Ssimon * licensing@OpenSSL.org. 29167612Ssimon * 30167612Ssimon * 5. Products derived from this software may not be called "OpenSSL" 31167612Ssimon * nor may "OpenSSL" appear in their names without prior written 32167612Ssimon * permission of the OpenSSL Project. 33167612Ssimon * 34167612Ssimon * 6. Redistributions of any form whatsoever must retain the following 35167612Ssimon * acknowledgment: 36167612Ssimon * "This product includes software developed by the OpenSSL Project 37167612Ssimon * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38167612Ssimon * 39167612Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40167612Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41167612Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42167612Ssimon * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43167612Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44167612Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45167612Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46167612Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47167612Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48167612Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49167612Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50167612Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE. 51167612Ssimon * ==================================================================== 52167612Ssimon * 53167612Ssimon * This product includes cryptographic software written by Eric Young 54167612Ssimon * (eay@cryptsoft.com). This product includes software written by Tim 55167612Ssimon * Hudson (tjh@cryptsoft.com). 56167612Ssimon */ 57167612Ssimon 58167612Ssimon/* 59167612Ssimon * Implementation of RFC 3779 section 3.2. 60167612Ssimon */ 61167612Ssimon 62167612Ssimon#include <stdio.h> 63167612Ssimon#include <string.h> 64167612Ssimon#include "cryptlib.h" 65167612Ssimon#include <openssl/conf.h> 66167612Ssimon#include <openssl/asn1.h> 67167612Ssimon#include <openssl/asn1t.h> 68167612Ssimon#include <openssl/x509v3.h> 69167612Ssimon#include <openssl/x509.h> 70167612Ssimon#include <openssl/bn.h> 71167612Ssimon 72167612Ssimon#ifndef OPENSSL_NO_RFC3779 73167612Ssimon 74167612Ssimon/* 75167612Ssimon * OpenSSL ASN.1 template translation of RFC 3779 3.2.3. 76167612Ssimon */ 77167612Ssimon 78167612SsimonASN1_SEQUENCE(ASRange) = { 79167612Ssimon ASN1_SIMPLE(ASRange, min, ASN1_INTEGER), 80167612Ssimon ASN1_SIMPLE(ASRange, max, ASN1_INTEGER) 81167612Ssimon} ASN1_SEQUENCE_END(ASRange) 82167612Ssimon 83167612SsimonASN1_CHOICE(ASIdOrRange) = { 84167612Ssimon ASN1_SIMPLE(ASIdOrRange, u.id, ASN1_INTEGER), 85167612Ssimon ASN1_SIMPLE(ASIdOrRange, u.range, ASRange) 86167612Ssimon} ASN1_CHOICE_END(ASIdOrRange) 87167612Ssimon 88167612SsimonASN1_CHOICE(ASIdentifierChoice) = { 89167612Ssimon ASN1_SIMPLE(ASIdentifierChoice, u.inherit, ASN1_NULL), 90167612Ssimon ASN1_SEQUENCE_OF(ASIdentifierChoice, u.asIdsOrRanges, ASIdOrRange) 91167612Ssimon} ASN1_CHOICE_END(ASIdentifierChoice) 92167612Ssimon 93167612SsimonASN1_SEQUENCE(ASIdentifiers) = { 94167612Ssimon ASN1_EXP_OPT(ASIdentifiers, asnum, ASIdentifierChoice, 0), 95167612Ssimon ASN1_EXP_OPT(ASIdentifiers, rdi, ASIdentifierChoice, 1) 96167612Ssimon} ASN1_SEQUENCE_END(ASIdentifiers) 97167612Ssimon 98167612SsimonIMPLEMENT_ASN1_FUNCTIONS(ASRange) 99167612SsimonIMPLEMENT_ASN1_FUNCTIONS(ASIdOrRange) 100167612SsimonIMPLEMENT_ASN1_FUNCTIONS(ASIdentifierChoice) 101167612SsimonIMPLEMENT_ASN1_FUNCTIONS(ASIdentifiers) 102167612Ssimon 103167612Ssimon/* 104167612Ssimon * i2r method for an ASIdentifierChoice. 105167612Ssimon */ 106167612Ssimonstatic int i2r_ASIdentifierChoice(BIO *out, 107280297Sjkim ASIdentifierChoice *choice, 108280297Sjkim int indent, const char *msg) 109167612Ssimon{ 110280297Sjkim int i; 111280297Sjkim char *s; 112280297Sjkim if (choice == NULL) 113280297Sjkim return 1; 114280297Sjkim BIO_printf(out, "%*s%s:\n", indent, "", msg); 115280297Sjkim switch (choice->type) { 116280297Sjkim case ASIdentifierChoice_inherit: 117280297Sjkim BIO_printf(out, "%*sinherit\n", indent + 2, ""); 118280297Sjkim break; 119280297Sjkim case ASIdentifierChoice_asIdsOrRanges: 120280297Sjkim for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges); i++) { 121280297Sjkim ASIdOrRange *aor = 122280297Sjkim sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); 123280297Sjkim switch (aor->type) { 124280297Sjkim case ASIdOrRange_id: 125280297Sjkim if ((s = i2s_ASN1_INTEGER(NULL, aor->u.id)) == NULL) 126280297Sjkim return 0; 127280297Sjkim BIO_printf(out, "%*s%s\n", indent + 2, "", s); 128280297Sjkim OPENSSL_free(s); 129280297Sjkim break; 130280297Sjkim case ASIdOrRange_range: 131280297Sjkim if ((s = i2s_ASN1_INTEGER(NULL, aor->u.range->min)) == NULL) 132280297Sjkim return 0; 133280297Sjkim BIO_printf(out, "%*s%s-", indent + 2, "", s); 134280297Sjkim OPENSSL_free(s); 135280297Sjkim if ((s = i2s_ASN1_INTEGER(NULL, aor->u.range->max)) == NULL) 136280297Sjkim return 0; 137280297Sjkim BIO_printf(out, "%s\n", s); 138280297Sjkim OPENSSL_free(s); 139280297Sjkim break; 140280297Sjkim default: 141280297Sjkim return 0; 142280297Sjkim } 143280297Sjkim } 144280297Sjkim break; 145280297Sjkim default: 146280297Sjkim return 0; 147280297Sjkim } 148167612Ssimon return 1; 149167612Ssimon} 150167612Ssimon 151167612Ssimon/* 152167612Ssimon * i2r method for an ASIdentifier extension. 153167612Ssimon */ 154238405Sjkimstatic int i2r_ASIdentifiers(const X509V3_EXT_METHOD *method, 155280297Sjkim void *ext, BIO *out, int indent) 156167612Ssimon{ 157280297Sjkim ASIdentifiers *asid = ext; 158280297Sjkim return (i2r_ASIdentifierChoice(out, asid->asnum, indent, 159280297Sjkim "Autonomous System Numbers") && 160280297Sjkim i2r_ASIdentifierChoice(out, asid->rdi, indent, 161280297Sjkim "Routing Domain Identifiers")); 162167612Ssimon} 163167612Ssimon 164167612Ssimon/* 165167612Ssimon * Sort comparision function for a sequence of ASIdOrRange elements. 166167612Ssimon */ 167280297Sjkimstatic int ASIdOrRange_cmp(const ASIdOrRange *const *a_, 168280297Sjkim const ASIdOrRange *const *b_) 169167612Ssimon{ 170280297Sjkim const ASIdOrRange *a = *a_, *b = *b_; 171167612Ssimon 172280297Sjkim OPENSSL_assert((a->type == ASIdOrRange_id && a->u.id != NULL) || 173280297Sjkim (a->type == ASIdOrRange_range && a->u.range != NULL && 174280297Sjkim a->u.range->min != NULL && a->u.range->max != NULL)); 175167612Ssimon 176280297Sjkim OPENSSL_assert((b->type == ASIdOrRange_id && b->u.id != NULL) || 177280297Sjkim (b->type == ASIdOrRange_range && b->u.range != NULL && 178280297Sjkim b->u.range->min != NULL && b->u.range->max != NULL)); 179167612Ssimon 180280297Sjkim if (a->type == ASIdOrRange_id && b->type == ASIdOrRange_id) 181280297Sjkim return ASN1_INTEGER_cmp(a->u.id, b->u.id); 182167612Ssimon 183280297Sjkim if (a->type == ASIdOrRange_range && b->type == ASIdOrRange_range) { 184280297Sjkim int r = ASN1_INTEGER_cmp(a->u.range->min, b->u.range->min); 185280297Sjkim return r != 0 ? r : ASN1_INTEGER_cmp(a->u.range->max, 186280297Sjkim b->u.range->max); 187280297Sjkim } 188167612Ssimon 189280297Sjkim if (a->type == ASIdOrRange_id) 190280297Sjkim return ASN1_INTEGER_cmp(a->u.id, b->u.range->min); 191280297Sjkim else 192280297Sjkim return ASN1_INTEGER_cmp(a->u.range->min, b->u.id); 193167612Ssimon} 194167612Ssimon 195167612Ssimon/* 196167612Ssimon * Add an inherit element. 197167612Ssimon */ 198167612Ssimonint v3_asid_add_inherit(ASIdentifiers *asid, int which) 199167612Ssimon{ 200280297Sjkim ASIdentifierChoice **choice; 201280297Sjkim if (asid == NULL) 202280297Sjkim return 0; 203280297Sjkim switch (which) { 204280297Sjkim case V3_ASID_ASNUM: 205280297Sjkim choice = &asid->asnum; 206280297Sjkim break; 207280297Sjkim case V3_ASID_RDI: 208280297Sjkim choice = &asid->rdi; 209280297Sjkim break; 210280297Sjkim default: 211280297Sjkim return 0; 212280297Sjkim } 213280297Sjkim if (*choice == NULL) { 214280297Sjkim if ((*choice = ASIdentifierChoice_new()) == NULL) 215280297Sjkim return 0; 216280297Sjkim OPENSSL_assert((*choice)->u.inherit == NULL); 217280297Sjkim if (((*choice)->u.inherit = ASN1_NULL_new()) == NULL) 218280297Sjkim return 0; 219280297Sjkim (*choice)->type = ASIdentifierChoice_inherit; 220280297Sjkim } 221280297Sjkim return (*choice)->type == ASIdentifierChoice_inherit; 222167612Ssimon} 223167612Ssimon 224167612Ssimon/* 225167612Ssimon * Add an ID or range to an ASIdentifierChoice. 226167612Ssimon */ 227167612Ssimonint v3_asid_add_id_or_range(ASIdentifiers *asid, 228280297Sjkim int which, ASN1_INTEGER *min, ASN1_INTEGER *max) 229167612Ssimon{ 230280297Sjkim ASIdentifierChoice **choice; 231280297Sjkim ASIdOrRange *aor; 232280297Sjkim if (asid == NULL) 233280297Sjkim return 0; 234280297Sjkim switch (which) { 235280297Sjkim case V3_ASID_ASNUM: 236280297Sjkim choice = &asid->asnum; 237280297Sjkim break; 238280297Sjkim case V3_ASID_RDI: 239280297Sjkim choice = &asid->rdi; 240280297Sjkim break; 241280297Sjkim default: 242280297Sjkim return 0; 243280297Sjkim } 244280297Sjkim if (*choice != NULL && (*choice)->type == ASIdentifierChoice_inherit) 245280297Sjkim return 0; 246280297Sjkim if (*choice == NULL) { 247280297Sjkim if ((*choice = ASIdentifierChoice_new()) == NULL) 248280297Sjkim return 0; 249280297Sjkim OPENSSL_assert((*choice)->u.asIdsOrRanges == NULL); 250280297Sjkim (*choice)->u.asIdsOrRanges = sk_ASIdOrRange_new(ASIdOrRange_cmp); 251280297Sjkim if ((*choice)->u.asIdsOrRanges == NULL) 252280297Sjkim return 0; 253280297Sjkim (*choice)->type = ASIdentifierChoice_asIdsOrRanges; 254280297Sjkim } 255280297Sjkim if ((aor = ASIdOrRange_new()) == NULL) 256280297Sjkim return 0; 257280297Sjkim if (max == NULL) { 258280297Sjkim aor->type = ASIdOrRange_id; 259280297Sjkim aor->u.id = min; 260280297Sjkim } else { 261280297Sjkim aor->type = ASIdOrRange_range; 262280297Sjkim if ((aor->u.range = ASRange_new()) == NULL) 263280297Sjkim goto err; 264280297Sjkim ASN1_INTEGER_free(aor->u.range->min); 265280297Sjkim aor->u.range->min = min; 266280297Sjkim ASN1_INTEGER_free(aor->u.range->max); 267280297Sjkim aor->u.range->max = max; 268280297Sjkim } 269280297Sjkim if (!(sk_ASIdOrRange_push((*choice)->u.asIdsOrRanges, aor))) 270280297Sjkim goto err; 271280297Sjkim return 1; 272167612Ssimon 273167612Ssimon err: 274280297Sjkim ASIdOrRange_free(aor); 275280297Sjkim return 0; 276167612Ssimon} 277167612Ssimon 278167612Ssimon/* 279167612Ssimon * Extract min and max values from an ASIdOrRange. 280167612Ssimon */ 281167612Ssimonstatic void extract_min_max(ASIdOrRange *aor, 282280297Sjkim ASN1_INTEGER **min, ASN1_INTEGER **max) 283167612Ssimon{ 284280297Sjkim OPENSSL_assert(aor != NULL && min != NULL && max != NULL); 285280297Sjkim switch (aor->type) { 286280297Sjkim case ASIdOrRange_id: 287280297Sjkim *min = aor->u.id; 288280297Sjkim *max = aor->u.id; 289280297Sjkim return; 290280297Sjkim case ASIdOrRange_range: 291280297Sjkim *min = aor->u.range->min; 292280297Sjkim *max = aor->u.range->max; 293280297Sjkim return; 294280297Sjkim } 295167612Ssimon} 296167612Ssimon 297167612Ssimon/* 298167612Ssimon * Check whether an ASIdentifierChoice is in canonical form. 299167612Ssimon */ 300167612Ssimonstatic int ASIdentifierChoice_is_canonical(ASIdentifierChoice *choice) 301167612Ssimon{ 302280297Sjkim ASN1_INTEGER *a_max_plus_one = NULL; 303280297Sjkim BIGNUM *bn = NULL; 304280297Sjkim int i, ret = 0; 305167612Ssimon 306280297Sjkim /* 307280297Sjkim * Empty element or inheritance is canonical. 308280297Sjkim */ 309280297Sjkim if (choice == NULL || choice->type == ASIdentifierChoice_inherit) 310280297Sjkim return 1; 311167612Ssimon 312167612Ssimon /* 313280297Sjkim * If not a list, or if empty list, it's broken. 314167612Ssimon */ 315280297Sjkim if (choice->type != ASIdentifierChoice_asIdsOrRanges || 316280297Sjkim sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0) 317280297Sjkim return 0; 318167612Ssimon 319167612Ssimon /* 320280297Sjkim * It's a list, check it. 321167612Ssimon */ 322280297Sjkim for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) { 323280297Sjkim ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); 324280297Sjkim ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1); 325280297Sjkim ASN1_INTEGER *a_min, *a_max, *b_min, *b_max; 326280297Sjkim 327280297Sjkim extract_min_max(a, &a_min, &a_max); 328280297Sjkim extract_min_max(b, &b_min, &b_max); 329280297Sjkim 330280297Sjkim /* 331280297Sjkim * Punt misordered list, overlapping start, or inverted range. 332280297Sjkim */ 333280297Sjkim if (ASN1_INTEGER_cmp(a_min, b_min) >= 0 || 334280297Sjkim ASN1_INTEGER_cmp(a_min, a_max) > 0 || 335280297Sjkim ASN1_INTEGER_cmp(b_min, b_max) > 0) 336280297Sjkim goto done; 337280297Sjkim 338280297Sjkim /* 339280297Sjkim * Calculate a_max + 1 to check for adjacency. 340280297Sjkim */ 341280297Sjkim if ((bn == NULL && (bn = BN_new()) == NULL) || 342280297Sjkim ASN1_INTEGER_to_BN(a_max, bn) == NULL || 343280297Sjkim !BN_add_word(bn, 1) || 344280297Sjkim (a_max_plus_one = 345280297Sjkim BN_to_ASN1_INTEGER(bn, a_max_plus_one)) == NULL) { 346280297Sjkim X509V3err(X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL, 347280297Sjkim ERR_R_MALLOC_FAILURE); 348280297Sjkim goto done; 349280297Sjkim } 350280297Sjkim 351280297Sjkim /* 352280297Sjkim * Punt if adjacent or overlapping. 353280297Sjkim */ 354280297Sjkim if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) >= 0) 355280297Sjkim goto done; 356167612Ssimon } 357280297Sjkim 358167612Ssimon /* 359280297Sjkim * Check for inverted range. 360167612Ssimon */ 361280297Sjkim i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; 362280297Sjkim { 363280297Sjkim ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); 364280297Sjkim ASN1_INTEGER *a_min, *a_max; 365280297Sjkim if (a != NULL && a->type == ASIdOrRange_range) { 366280297Sjkim extract_min_max(a, &a_min, &a_max); 367280297Sjkim if (ASN1_INTEGER_cmp(a_min, a_max) > 0) 368280297Sjkim goto done; 369280297Sjkim } 370237657Sjkim } 371237657Sjkim 372280297Sjkim ret = 1; 373167612Ssimon 374167612Ssimon done: 375280297Sjkim ASN1_INTEGER_free(a_max_plus_one); 376280297Sjkim BN_free(bn); 377280297Sjkim return ret; 378167612Ssimon} 379167612Ssimon 380167612Ssimon/* 381167612Ssimon * Check whether an ASIdentifier extension is in canonical form. 382167612Ssimon */ 383167612Ssimonint v3_asid_is_canonical(ASIdentifiers *asid) 384167612Ssimon{ 385280297Sjkim return (asid == NULL || 386280297Sjkim (ASIdentifierChoice_is_canonical(asid->asnum) && 387280297Sjkim ASIdentifierChoice_is_canonical(asid->rdi))); 388167612Ssimon} 389167612Ssimon 390167612Ssimon/* 391167612Ssimon * Whack an ASIdentifierChoice into canonical form. 392167612Ssimon */ 393167612Ssimonstatic int ASIdentifierChoice_canonize(ASIdentifierChoice *choice) 394167612Ssimon{ 395280297Sjkim ASN1_INTEGER *a_max_plus_one = NULL; 396280297Sjkim BIGNUM *bn = NULL; 397280297Sjkim int i, ret = 0; 398167612Ssimon 399167612Ssimon /* 400280297Sjkim * Nothing to do for empty element or inheritance. 401167612Ssimon */ 402280297Sjkim if (choice == NULL || choice->type == ASIdentifierChoice_inherit) 403280297Sjkim return 1; 404167612Ssimon 405167612Ssimon /* 406280297Sjkim * If not a list, or if empty list, it's broken. 407237657Sjkim */ 408280297Sjkim if (choice->type != ASIdentifierChoice_asIdsOrRanges || 409280297Sjkim sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0) { 410280297Sjkim X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, 411280297Sjkim X509V3_R_EXTENSION_VALUE_ERROR); 412280297Sjkim return 0; 413280297Sjkim } 414237657Sjkim 415237657Sjkim /* 416280297Sjkim * We have a non-empty list. Sort it. 417167612Ssimon */ 418280297Sjkim sk_ASIdOrRange_sort(choice->u.asIdsOrRanges); 419167612Ssimon 420167612Ssimon /* 421280297Sjkim * Now check for errors and suboptimal encoding, rejecting the 422280297Sjkim * former and fixing the latter. 423167612Ssimon */ 424280297Sjkim for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) { 425280297Sjkim ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); 426280297Sjkim ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1); 427280297Sjkim ASN1_INTEGER *a_min, *a_max, *b_min, *b_max; 428280297Sjkim 429280297Sjkim extract_min_max(a, &a_min, &a_max); 430280297Sjkim extract_min_max(b, &b_min, &b_max); 431280297Sjkim 432280297Sjkim /* 433280297Sjkim * Make sure we're properly sorted (paranoia). 434280297Sjkim */ 435280297Sjkim OPENSSL_assert(ASN1_INTEGER_cmp(a_min, b_min) <= 0); 436280297Sjkim 437280297Sjkim /* 438280297Sjkim * Punt inverted ranges. 439280297Sjkim */ 440280297Sjkim if (ASN1_INTEGER_cmp(a_min, a_max) > 0 || 441280297Sjkim ASN1_INTEGER_cmp(b_min, b_max) > 0) 442280297Sjkim goto done; 443280297Sjkim 444280297Sjkim /* 445280297Sjkim * Check for overlaps. 446280297Sjkim */ 447280297Sjkim if (ASN1_INTEGER_cmp(a_max, b_min) >= 0) { 448280297Sjkim X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, 449280297Sjkim X509V3_R_EXTENSION_VALUE_ERROR); 450280297Sjkim goto done; 451280297Sjkim } 452280297Sjkim 453280297Sjkim /* 454280297Sjkim * Calculate a_max + 1 to check for adjacency. 455280297Sjkim */ 456280297Sjkim if ((bn == NULL && (bn = BN_new()) == NULL) || 457280297Sjkim ASN1_INTEGER_to_BN(a_max, bn) == NULL || 458280297Sjkim !BN_add_word(bn, 1) || 459280297Sjkim (a_max_plus_one = 460280297Sjkim BN_to_ASN1_INTEGER(bn, a_max_plus_one)) == NULL) { 461280297Sjkim X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, 462280297Sjkim ERR_R_MALLOC_FAILURE); 463280297Sjkim goto done; 464280297Sjkim } 465280297Sjkim 466280297Sjkim /* 467280297Sjkim * If a and b are adjacent, merge them. 468280297Sjkim */ 469280297Sjkim if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) == 0) { 470280297Sjkim ASRange *r; 471280297Sjkim switch (a->type) { 472280297Sjkim case ASIdOrRange_id: 473280297Sjkim if ((r = OPENSSL_malloc(sizeof(ASRange))) == NULL) { 474280297Sjkim X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, 475280297Sjkim ERR_R_MALLOC_FAILURE); 476280297Sjkim goto done; 477280297Sjkim } 478280297Sjkim r->min = a_min; 479280297Sjkim r->max = b_max; 480280297Sjkim a->type = ASIdOrRange_range; 481280297Sjkim a->u.range = r; 482280297Sjkim break; 483280297Sjkim case ASIdOrRange_range: 484280297Sjkim ASN1_INTEGER_free(a->u.range->max); 485280297Sjkim a->u.range->max = b_max; 486280297Sjkim break; 487280297Sjkim } 488280297Sjkim switch (b->type) { 489280297Sjkim case ASIdOrRange_id: 490280297Sjkim b->u.id = NULL; 491280297Sjkim break; 492280297Sjkim case ASIdOrRange_range: 493280297Sjkim b->u.range->max = NULL; 494280297Sjkim break; 495280297Sjkim } 496280297Sjkim ASIdOrRange_free(b); 497280297Sjkim (void)sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i + 1); 498280297Sjkim i--; 499280297Sjkim continue; 500280297Sjkim } 501167612Ssimon } 502280297Sjkim 503167612Ssimon /* 504280297Sjkim * Check for final inverted range. 505167612Ssimon */ 506280297Sjkim i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; 507280297Sjkim { 508280297Sjkim ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); 509280297Sjkim ASN1_INTEGER *a_min, *a_max; 510280297Sjkim if (a != NULL && a->type == ASIdOrRange_range) { 511280297Sjkim extract_min_max(a, &a_min, &a_max); 512280297Sjkim if (ASN1_INTEGER_cmp(a_min, a_max) > 0) 513280297Sjkim goto done; 514280297Sjkim } 515167612Ssimon } 516167612Ssimon 517280297Sjkim OPENSSL_assert(ASIdentifierChoice_is_canonical(choice)); /* Paranoia */ 518167612Ssimon 519280297Sjkim ret = 1; 520237657Sjkim 521167612Ssimon done: 522280297Sjkim ASN1_INTEGER_free(a_max_plus_one); 523280297Sjkim BN_free(bn); 524280297Sjkim return ret; 525167612Ssimon} 526167612Ssimon 527167612Ssimon/* 528167612Ssimon * Whack an ASIdentifier extension into canonical form. 529167612Ssimon */ 530167612Ssimonint v3_asid_canonize(ASIdentifiers *asid) 531167612Ssimon{ 532280297Sjkim return (asid == NULL || 533280297Sjkim (ASIdentifierChoice_canonize(asid->asnum) && 534280297Sjkim ASIdentifierChoice_canonize(asid->rdi))); 535167612Ssimon} 536167612Ssimon 537167612Ssimon/* 538167612Ssimon * v2i method for an ASIdentifier extension. 539167612Ssimon */ 540238405Sjkimstatic void *v2i_ASIdentifiers(const struct v3_ext_method *method, 541280297Sjkim struct v3_ext_ctx *ctx, 542280297Sjkim STACK_OF(CONF_VALUE) *values) 543167612Ssimon{ 544280297Sjkim ASN1_INTEGER *min = NULL, *max = NULL; 545280297Sjkim ASIdentifiers *asid = NULL; 546280297Sjkim int i; 547167612Ssimon 548280297Sjkim if ((asid = ASIdentifiers_new()) == NULL) { 549280297Sjkim X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE); 550280297Sjkim return NULL; 551280297Sjkim } 552167612Ssimon 553280297Sjkim for (i = 0; i < sk_CONF_VALUE_num(values); i++) { 554280297Sjkim CONF_VALUE *val = sk_CONF_VALUE_value(values, i); 555280297Sjkim int i1, i2, i3, is_range, which; 556167612Ssimon 557280297Sjkim /* 558280297Sjkim * Figure out whether this is an AS or an RDI. 559280297Sjkim */ 560280297Sjkim if (!name_cmp(val->name, "AS")) { 561280297Sjkim which = V3_ASID_ASNUM; 562280297Sjkim } else if (!name_cmp(val->name, "RDI")) { 563280297Sjkim which = V3_ASID_RDI; 564280297Sjkim } else { 565280297Sjkim X509V3err(X509V3_F_V2I_ASIDENTIFIERS, 566280297Sjkim X509V3_R_EXTENSION_NAME_ERROR); 567280297Sjkim X509V3_conf_err(val); 568280297Sjkim goto err; 569280297Sjkim } 570167612Ssimon 571280297Sjkim /* 572280297Sjkim * Handle inheritance. 573280297Sjkim */ 574280297Sjkim if (!strcmp(val->value, "inherit")) { 575280297Sjkim if (v3_asid_add_inherit(asid, which)) 576280297Sjkim continue; 577280297Sjkim X509V3err(X509V3_F_V2I_ASIDENTIFIERS, 578280297Sjkim X509V3_R_INVALID_INHERITANCE); 579280297Sjkim X509V3_conf_err(val); 580280297Sjkim goto err; 581280297Sjkim } 582167612Ssimon 583280297Sjkim /* 584280297Sjkim * Number, range, or mistake, pick it apart and figure out which. 585280297Sjkim */ 586280297Sjkim i1 = strspn(val->value, "0123456789"); 587280297Sjkim if (val->value[i1] == '\0') { 588280297Sjkim is_range = 0; 589280297Sjkim } else { 590280297Sjkim is_range = 1; 591280297Sjkim i2 = i1 + strspn(val->value + i1, " \t"); 592280297Sjkim if (val->value[i2] != '-') { 593280297Sjkim X509V3err(X509V3_F_V2I_ASIDENTIFIERS, 594280297Sjkim X509V3_R_INVALID_ASNUMBER); 595280297Sjkim X509V3_conf_err(val); 596280297Sjkim goto err; 597280297Sjkim } 598280297Sjkim i2++; 599280297Sjkim i2 = i2 + strspn(val->value + i2, " \t"); 600280297Sjkim i3 = i2 + strspn(val->value + i2, "0123456789"); 601280297Sjkim if (val->value[i3] != '\0') { 602280297Sjkim X509V3err(X509V3_F_V2I_ASIDENTIFIERS, 603280297Sjkim X509V3_R_INVALID_ASRANGE); 604280297Sjkim X509V3_conf_err(val); 605280297Sjkim goto err; 606280297Sjkim } 607280297Sjkim } 608280297Sjkim 609280297Sjkim /* 610280297Sjkim * Syntax is ok, read and add it. 611280297Sjkim */ 612280297Sjkim if (!is_range) { 613280297Sjkim if (!X509V3_get_value_int(val, &min)) { 614280297Sjkim X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE); 615280297Sjkim goto err; 616280297Sjkim } 617280297Sjkim } else { 618280297Sjkim char *s = BUF_strdup(val->value); 619280297Sjkim if (s == NULL) { 620280297Sjkim X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE); 621280297Sjkim goto err; 622280297Sjkim } 623280297Sjkim s[i1] = '\0'; 624280297Sjkim min = s2i_ASN1_INTEGER(NULL, s); 625280297Sjkim max = s2i_ASN1_INTEGER(NULL, s + i2); 626280297Sjkim OPENSSL_free(s); 627280297Sjkim if (min == NULL || max == NULL) { 628280297Sjkim X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE); 629280297Sjkim goto err; 630280297Sjkim } 631280297Sjkim if (ASN1_INTEGER_cmp(min, max) > 0) { 632280297Sjkim X509V3err(X509V3_F_V2I_ASIDENTIFIERS, 633280297Sjkim X509V3_R_EXTENSION_VALUE_ERROR); 634280297Sjkim goto err; 635280297Sjkim } 636280297Sjkim } 637280297Sjkim if (!v3_asid_add_id_or_range(asid, which, min, max)) { 638280297Sjkim X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE); 639280297Sjkim goto err; 640280297Sjkim } 641280297Sjkim min = max = NULL; 642167612Ssimon } 643167612Ssimon 644167612Ssimon /* 645280297Sjkim * Canonize the result, then we're done. 646167612Ssimon */ 647280297Sjkim if (!v3_asid_canonize(asid)) 648280297Sjkim goto err; 649280297Sjkim return asid; 650167612Ssimon 651167612Ssimon err: 652280297Sjkim ASIdentifiers_free(asid); 653280297Sjkim ASN1_INTEGER_free(min); 654280297Sjkim ASN1_INTEGER_free(max); 655280297Sjkim return NULL; 656167612Ssimon} 657167612Ssimon 658167612Ssimon/* 659167612Ssimon * OpenSSL dispatch. 660167612Ssimon */ 661167612Ssimonconst X509V3_EXT_METHOD v3_asid = { 662280297Sjkim NID_sbgp_autonomousSysNum, /* nid */ 663280297Sjkim 0, /* flags */ 664280297Sjkim ASN1_ITEM_ref(ASIdentifiers), /* template */ 665280297Sjkim 0, 0, 0, 0, /* old functions, ignored */ 666280297Sjkim 0, /* i2s */ 667280297Sjkim 0, /* s2i */ 668280297Sjkim 0, /* i2v */ 669280297Sjkim v2i_ASIdentifiers, /* v2i */ 670280297Sjkim i2r_ASIdentifiers, /* i2r */ 671280297Sjkim 0, /* r2i */ 672280297Sjkim NULL /* extension-specific data */ 673167612Ssimon}; 674167612Ssimon 675167612Ssimon/* 676167612Ssimon * Figure out whether extension uses inheritance. 677167612Ssimon */ 678167612Ssimonint v3_asid_inherits(ASIdentifiers *asid) 679167612Ssimon{ 680280297Sjkim return (asid != NULL && 681280297Sjkim ((asid->asnum != NULL && 682280297Sjkim asid->asnum->type == ASIdentifierChoice_inherit) || 683280297Sjkim (asid->rdi != NULL && 684280297Sjkim asid->rdi->type == ASIdentifierChoice_inherit))); 685167612Ssimon} 686167612Ssimon 687167612Ssimon/* 688167612Ssimon * Figure out whether parent contains child. 689167612Ssimon */ 690167612Ssimonstatic int asid_contains(ASIdOrRanges *parent, ASIdOrRanges *child) 691167612Ssimon{ 692280297Sjkim ASN1_INTEGER *p_min, *p_max, *c_min, *c_max; 693280297Sjkim int p, c; 694167612Ssimon 695280297Sjkim if (child == NULL || parent == child) 696280297Sjkim return 1; 697280297Sjkim if (parent == NULL) 698280297Sjkim return 0; 699167612Ssimon 700280297Sjkim p = 0; 701280297Sjkim for (c = 0; c < sk_ASIdOrRange_num(child); c++) { 702280297Sjkim extract_min_max(sk_ASIdOrRange_value(child, c), &c_min, &c_max); 703280297Sjkim for (;; p++) { 704280297Sjkim if (p >= sk_ASIdOrRange_num(parent)) 705280297Sjkim return 0; 706280297Sjkim extract_min_max(sk_ASIdOrRange_value(parent, p), &p_min, &p_max); 707280297Sjkim if (ASN1_INTEGER_cmp(p_max, c_max) < 0) 708280297Sjkim continue; 709280297Sjkim if (ASN1_INTEGER_cmp(p_min, c_min) > 0) 710280297Sjkim return 0; 711280297Sjkim break; 712280297Sjkim } 713167612Ssimon } 714167612Ssimon 715280297Sjkim return 1; 716167612Ssimon} 717167612Ssimon 718167612Ssimon/* 719167612Ssimon * Test whether a is a subet of b. 720167612Ssimon */ 721167612Ssimonint v3_asid_subset(ASIdentifiers *a, ASIdentifiers *b) 722167612Ssimon{ 723280297Sjkim return (a == NULL || 724280297Sjkim a == b || 725280297Sjkim (b != NULL && 726280297Sjkim !v3_asid_inherits(a) && 727280297Sjkim !v3_asid_inherits(b) && 728280297Sjkim asid_contains(b->asnum->u.asIdsOrRanges, 729280297Sjkim a->asnum->u.asIdsOrRanges) && 730280297Sjkim asid_contains(b->rdi->u.asIdsOrRanges, 731280297Sjkim a->rdi->u.asIdsOrRanges))); 732167612Ssimon} 733167612Ssimon 734167612Ssimon/* 735167612Ssimon * Validation error handling via callback. 736167612Ssimon */ 737280297Sjkim# define validation_err(_err_) \ 738280297Sjkim do { \ 739280297Sjkim if (ctx != NULL) { \ 740280297Sjkim ctx->error = _err_; \ 741280297Sjkim ctx->error_depth = i; \ 742280297Sjkim ctx->current_cert = x; \ 743280297Sjkim ret = ctx->verify_cb(0, ctx); \ 744280297Sjkim } else { \ 745280297Sjkim ret = 0; \ 746280297Sjkim } \ 747280297Sjkim if (!ret) \ 748280297Sjkim goto done; \ 749167612Ssimon } while (0) 750167612Ssimon 751167612Ssimon/* 752167612Ssimon * Core code for RFC 3779 3.3 path validation. 753167612Ssimon */ 754167612Ssimonstatic int v3_asid_validate_path_internal(X509_STORE_CTX *ctx, 755280297Sjkim STACK_OF(X509) *chain, 756280297Sjkim ASIdentifiers *ext) 757167612Ssimon{ 758280297Sjkim ASIdOrRanges *child_as = NULL, *child_rdi = NULL; 759280297Sjkim int i, ret = 1, inherit_as = 0, inherit_rdi = 0; 760280297Sjkim X509 *x; 761167612Ssimon 762280297Sjkim OPENSSL_assert(chain != NULL && sk_X509_num(chain) > 0); 763280297Sjkim OPENSSL_assert(ctx != NULL || ext != NULL); 764280297Sjkim OPENSSL_assert(ctx == NULL || ctx->verify_cb != NULL); 765167612Ssimon 766280297Sjkim /* 767280297Sjkim * Figure out where to start. If we don't have an extension to 768280297Sjkim * check, we're done. Otherwise, check canonical form and 769280297Sjkim * set up for walking up the chain. 770280297Sjkim */ 771280297Sjkim if (ext != NULL) { 772280297Sjkim i = -1; 773280297Sjkim x = NULL; 774280297Sjkim } else { 775280297Sjkim i = 0; 776280297Sjkim x = sk_X509_value(chain, i); 777280297Sjkim OPENSSL_assert(x != NULL); 778280297Sjkim if ((ext = x->rfc3779_asid) == NULL) 779280297Sjkim goto done; 780167612Ssimon } 781280297Sjkim if (!v3_asid_is_canonical(ext)) 782280297Sjkim validation_err(X509_V_ERR_INVALID_EXTENSION); 783280297Sjkim if (ext->asnum != NULL) { 784280297Sjkim switch (ext->asnum->type) { 785280297Sjkim case ASIdentifierChoice_inherit: 786280297Sjkim inherit_as = 1; 787280297Sjkim break; 788280297Sjkim case ASIdentifierChoice_asIdsOrRanges: 789280297Sjkim child_as = ext->asnum->u.asIdsOrRanges; 790280297Sjkim break; 791280297Sjkim } 792167612Ssimon } 793280297Sjkim if (ext->rdi != NULL) { 794280297Sjkim switch (ext->rdi->type) { 795280297Sjkim case ASIdentifierChoice_inherit: 796280297Sjkim inherit_rdi = 1; 797280297Sjkim break; 798280297Sjkim case ASIdentifierChoice_asIdsOrRanges: 799280297Sjkim child_rdi = ext->rdi->u.asIdsOrRanges; 800280297Sjkim break; 801280297Sjkim } 802280297Sjkim } 803167612Ssimon 804280297Sjkim /* 805280297Sjkim * Now walk up the chain. Extensions must be in canonical form, no 806280297Sjkim * cert may list resources that its parent doesn't list. 807280297Sjkim */ 808280297Sjkim for (i++; i < sk_X509_num(chain); i++) { 809280297Sjkim x = sk_X509_value(chain, i); 810280297Sjkim OPENSSL_assert(x != NULL); 811280297Sjkim if (x->rfc3779_asid == NULL) { 812280297Sjkim if (child_as != NULL || child_rdi != NULL) 813280297Sjkim validation_err(X509_V_ERR_UNNESTED_RESOURCE); 814280297Sjkim continue; 815280297Sjkim } 816280297Sjkim if (!v3_asid_is_canonical(x->rfc3779_asid)) 817280297Sjkim validation_err(X509_V_ERR_INVALID_EXTENSION); 818280297Sjkim if (x->rfc3779_asid->asnum == NULL && child_as != NULL) { 819280297Sjkim validation_err(X509_V_ERR_UNNESTED_RESOURCE); 820280297Sjkim child_as = NULL; 821280297Sjkim inherit_as = 0; 822280297Sjkim } 823280297Sjkim if (x->rfc3779_asid->asnum != NULL && 824280297Sjkim x->rfc3779_asid->asnum->type == 825280297Sjkim ASIdentifierChoice_asIdsOrRanges) { 826280297Sjkim if (inherit_as 827280297Sjkim || asid_contains(x->rfc3779_asid->asnum->u.asIdsOrRanges, 828280297Sjkim child_as)) { 829280297Sjkim child_as = x->rfc3779_asid->asnum->u.asIdsOrRanges; 830280297Sjkim inherit_as = 0; 831280297Sjkim } else { 832280297Sjkim validation_err(X509_V_ERR_UNNESTED_RESOURCE); 833280297Sjkim } 834280297Sjkim } 835280297Sjkim if (x->rfc3779_asid->rdi == NULL && child_rdi != NULL) { 836280297Sjkim validation_err(X509_V_ERR_UNNESTED_RESOURCE); 837280297Sjkim child_rdi = NULL; 838280297Sjkim inherit_rdi = 0; 839280297Sjkim } 840280297Sjkim if (x->rfc3779_asid->rdi != NULL && 841280297Sjkim x->rfc3779_asid->rdi->type == ASIdentifierChoice_asIdsOrRanges) { 842280297Sjkim if (inherit_rdi || 843280297Sjkim asid_contains(x->rfc3779_asid->rdi->u.asIdsOrRanges, 844280297Sjkim child_rdi)) { 845280297Sjkim child_rdi = x->rfc3779_asid->rdi->u.asIdsOrRanges; 846280297Sjkim inherit_rdi = 0; 847280297Sjkim } else { 848280297Sjkim validation_err(X509_V_ERR_UNNESTED_RESOURCE); 849280297Sjkim } 850280297Sjkim } 851280297Sjkim } 852280297Sjkim 853280297Sjkim /* 854280297Sjkim * Trust anchor can't inherit. 855280297Sjkim */ 856237657Sjkim OPENSSL_assert(x != NULL); 857280297Sjkim if (x->rfc3779_asid != NULL) { 858280297Sjkim if (x->rfc3779_asid->asnum != NULL && 859280297Sjkim x->rfc3779_asid->asnum->type == ASIdentifierChoice_inherit) 860280297Sjkim validation_err(X509_V_ERR_UNNESTED_RESOURCE); 861280297Sjkim if (x->rfc3779_asid->rdi != NULL && 862280297Sjkim x->rfc3779_asid->rdi->type == ASIdentifierChoice_inherit) 863280297Sjkim validation_err(X509_V_ERR_UNNESTED_RESOURCE); 864167612Ssimon } 865167612Ssimon 866167612Ssimon done: 867280297Sjkim return ret; 868167612Ssimon} 869167612Ssimon 870280297Sjkim# undef validation_err 871167612Ssimon 872167612Ssimon/* 873167612Ssimon * RFC 3779 3.3 path validation -- called from X509_verify_cert(). 874167612Ssimon */ 875167612Ssimonint v3_asid_validate_path(X509_STORE_CTX *ctx) 876167612Ssimon{ 877280297Sjkim return v3_asid_validate_path_internal(ctx, ctx->chain, NULL); 878167612Ssimon} 879167612Ssimon 880167612Ssimon/* 881167612Ssimon * RFC 3779 3.3 path validation of an extension. 882167612Ssimon * Test whether chain covers extension. 883167612Ssimon */ 884167612Ssimonint v3_asid_validate_resource_set(STACK_OF(X509) *chain, 885280297Sjkim ASIdentifiers *ext, int allow_inheritance) 886167612Ssimon{ 887280297Sjkim if (ext == NULL) 888280297Sjkim return 1; 889280297Sjkim if (chain == NULL || sk_X509_num(chain) == 0) 890280297Sjkim return 0; 891280297Sjkim if (!allow_inheritance && v3_asid_inherits(ext)) 892280297Sjkim return 0; 893280297Sjkim return v3_asid_validate_path_internal(NULL, chain, ext); 894167612Ssimon} 895167612Ssimon 896280297Sjkim#endif /* OPENSSL_NO_RFC3779 */ 897