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 13280304Sjkim * 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, 107280304Sjkim ASIdentifierChoice *choice, 108280304Sjkim int indent, const char *msg) 109167612Ssimon{ 110280304Sjkim int i; 111280304Sjkim char *s; 112280304Sjkim if (choice == NULL) 113280304Sjkim return 1; 114280304Sjkim BIO_printf(out, "%*s%s:\n", indent, "", msg); 115280304Sjkim switch (choice->type) { 116280304Sjkim case ASIdentifierChoice_inherit: 117280304Sjkim BIO_printf(out, "%*sinherit\n", indent + 2, ""); 118280304Sjkim break; 119280304Sjkim case ASIdentifierChoice_asIdsOrRanges: 120280304Sjkim for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges); i++) { 121280304Sjkim ASIdOrRange *aor = 122280304Sjkim sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); 123280304Sjkim switch (aor->type) { 124280304Sjkim case ASIdOrRange_id: 125280304Sjkim if ((s = i2s_ASN1_INTEGER(NULL, aor->u.id)) == NULL) 126280304Sjkim return 0; 127280304Sjkim BIO_printf(out, "%*s%s\n", indent + 2, "", s); 128280304Sjkim OPENSSL_free(s); 129280304Sjkim break; 130280304Sjkim case ASIdOrRange_range: 131280304Sjkim if ((s = i2s_ASN1_INTEGER(NULL, aor->u.range->min)) == NULL) 132280304Sjkim return 0; 133280304Sjkim BIO_printf(out, "%*s%s-", indent + 2, "", s); 134280304Sjkim OPENSSL_free(s); 135280304Sjkim if ((s = i2s_ASN1_INTEGER(NULL, aor->u.range->max)) == NULL) 136280304Sjkim return 0; 137280304Sjkim BIO_printf(out, "%s\n", s); 138280304Sjkim OPENSSL_free(s); 139280304Sjkim break; 140280304Sjkim default: 141280304Sjkim return 0; 142280304Sjkim } 143280304Sjkim } 144280304Sjkim break; 145280304Sjkim default: 146280304Sjkim return 0; 147280304Sjkim } 148167612Ssimon return 1; 149167612Ssimon} 150167612Ssimon 151167612Ssimon/* 152167612Ssimon * i2r method for an ASIdentifier extension. 153167612Ssimon */ 154238405Sjkimstatic int i2r_ASIdentifiers(const X509V3_EXT_METHOD *method, 155280304Sjkim void *ext, BIO *out, int indent) 156167612Ssimon{ 157280304Sjkim ASIdentifiers *asid = ext; 158280304Sjkim return (i2r_ASIdentifierChoice(out, asid->asnum, indent, 159280304Sjkim "Autonomous System Numbers") && 160280304Sjkim i2r_ASIdentifierChoice(out, asid->rdi, indent, 161280304Sjkim "Routing Domain Identifiers")); 162167612Ssimon} 163167612Ssimon 164167612Ssimon/* 165167612Ssimon * Sort comparision function for a sequence of ASIdOrRange elements. 166167612Ssimon */ 167280304Sjkimstatic int ASIdOrRange_cmp(const ASIdOrRange *const *a_, 168280304Sjkim const ASIdOrRange *const *b_) 169167612Ssimon{ 170280304Sjkim const ASIdOrRange *a = *a_, *b = *b_; 171167612Ssimon 172280304Sjkim OPENSSL_assert((a->type == ASIdOrRange_id && a->u.id != NULL) || 173280304Sjkim (a->type == ASIdOrRange_range && a->u.range != NULL && 174280304Sjkim a->u.range->min != NULL && a->u.range->max != NULL)); 175167612Ssimon 176280304Sjkim OPENSSL_assert((b->type == ASIdOrRange_id && b->u.id != NULL) || 177280304Sjkim (b->type == ASIdOrRange_range && b->u.range != NULL && 178280304Sjkim b->u.range->min != NULL && b->u.range->max != NULL)); 179167612Ssimon 180280304Sjkim if (a->type == ASIdOrRange_id && b->type == ASIdOrRange_id) 181280304Sjkim return ASN1_INTEGER_cmp(a->u.id, b->u.id); 182167612Ssimon 183280304Sjkim if (a->type == ASIdOrRange_range && b->type == ASIdOrRange_range) { 184280304Sjkim int r = ASN1_INTEGER_cmp(a->u.range->min, b->u.range->min); 185280304Sjkim return r != 0 ? r : ASN1_INTEGER_cmp(a->u.range->max, 186280304Sjkim b->u.range->max); 187280304Sjkim } 188167612Ssimon 189280304Sjkim if (a->type == ASIdOrRange_id) 190280304Sjkim return ASN1_INTEGER_cmp(a->u.id, b->u.range->min); 191280304Sjkim else 192280304Sjkim 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{ 200280304Sjkim ASIdentifierChoice **choice; 201280304Sjkim if (asid == NULL) 202280304Sjkim return 0; 203280304Sjkim switch (which) { 204280304Sjkim case V3_ASID_ASNUM: 205280304Sjkim choice = &asid->asnum; 206280304Sjkim break; 207280304Sjkim case V3_ASID_RDI: 208280304Sjkim choice = &asid->rdi; 209280304Sjkim break; 210280304Sjkim default: 211280304Sjkim return 0; 212280304Sjkim } 213280304Sjkim if (*choice == NULL) { 214280304Sjkim if ((*choice = ASIdentifierChoice_new()) == NULL) 215280304Sjkim return 0; 216280304Sjkim OPENSSL_assert((*choice)->u.inherit == NULL); 217280304Sjkim if (((*choice)->u.inherit = ASN1_NULL_new()) == NULL) 218280304Sjkim return 0; 219280304Sjkim (*choice)->type = ASIdentifierChoice_inherit; 220280304Sjkim } 221280304Sjkim 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, 228280304Sjkim int which, ASN1_INTEGER *min, ASN1_INTEGER *max) 229167612Ssimon{ 230280304Sjkim ASIdentifierChoice **choice; 231280304Sjkim ASIdOrRange *aor; 232280304Sjkim if (asid == NULL) 233280304Sjkim return 0; 234280304Sjkim switch (which) { 235280304Sjkim case V3_ASID_ASNUM: 236280304Sjkim choice = &asid->asnum; 237280304Sjkim break; 238280304Sjkim case V3_ASID_RDI: 239280304Sjkim choice = &asid->rdi; 240280304Sjkim break; 241280304Sjkim default: 242280304Sjkim return 0; 243280304Sjkim } 244280304Sjkim if (*choice != NULL && (*choice)->type == ASIdentifierChoice_inherit) 245280304Sjkim return 0; 246280304Sjkim if (*choice == NULL) { 247280304Sjkim if ((*choice = ASIdentifierChoice_new()) == NULL) 248280304Sjkim return 0; 249280304Sjkim OPENSSL_assert((*choice)->u.asIdsOrRanges == NULL); 250280304Sjkim (*choice)->u.asIdsOrRanges = sk_ASIdOrRange_new(ASIdOrRange_cmp); 251280304Sjkim if ((*choice)->u.asIdsOrRanges == NULL) 252280304Sjkim return 0; 253280304Sjkim (*choice)->type = ASIdentifierChoice_asIdsOrRanges; 254280304Sjkim } 255280304Sjkim if ((aor = ASIdOrRange_new()) == NULL) 256280304Sjkim return 0; 257280304Sjkim if (max == NULL) { 258280304Sjkim aor->type = ASIdOrRange_id; 259280304Sjkim aor->u.id = min; 260280304Sjkim } else { 261280304Sjkim aor->type = ASIdOrRange_range; 262280304Sjkim if ((aor->u.range = ASRange_new()) == NULL) 263280304Sjkim goto err; 264280304Sjkim ASN1_INTEGER_free(aor->u.range->min); 265280304Sjkim aor->u.range->min = min; 266280304Sjkim ASN1_INTEGER_free(aor->u.range->max); 267280304Sjkim aor->u.range->max = max; 268280304Sjkim } 269280304Sjkim if (!(sk_ASIdOrRange_push((*choice)->u.asIdsOrRanges, aor))) 270280304Sjkim goto err; 271280304Sjkim return 1; 272167612Ssimon 273167612Ssimon err: 274280304Sjkim ASIdOrRange_free(aor); 275280304Sjkim return 0; 276167612Ssimon} 277167612Ssimon 278167612Ssimon/* 279167612Ssimon * Extract min and max values from an ASIdOrRange. 280167612Ssimon */ 281167612Ssimonstatic void extract_min_max(ASIdOrRange *aor, 282280304Sjkim ASN1_INTEGER **min, ASN1_INTEGER **max) 283167612Ssimon{ 284280304Sjkim OPENSSL_assert(aor != NULL && min != NULL && max != NULL); 285280304Sjkim switch (aor->type) { 286280304Sjkim case ASIdOrRange_id: 287280304Sjkim *min = aor->u.id; 288280304Sjkim *max = aor->u.id; 289280304Sjkim return; 290280304Sjkim case ASIdOrRange_range: 291280304Sjkim *min = aor->u.range->min; 292280304Sjkim *max = aor->u.range->max; 293280304Sjkim return; 294280304Sjkim } 295167612Ssimon} 296167612Ssimon 297167612Ssimon/* 298167612Ssimon * Check whether an ASIdentifierChoice is in canonical form. 299167612Ssimon */ 300167612Ssimonstatic int ASIdentifierChoice_is_canonical(ASIdentifierChoice *choice) 301167612Ssimon{ 302280304Sjkim ASN1_INTEGER *a_max_plus_one = NULL; 303280304Sjkim BIGNUM *bn = NULL; 304280304Sjkim int i, ret = 0; 305167612Ssimon 306280304Sjkim /* 307280304Sjkim * Empty element or inheritance is canonical. 308280304Sjkim */ 309280304Sjkim if (choice == NULL || choice->type == ASIdentifierChoice_inherit) 310280304Sjkim return 1; 311167612Ssimon 312167612Ssimon /* 313280304Sjkim * If not a list, or if empty list, it's broken. 314167612Ssimon */ 315280304Sjkim if (choice->type != ASIdentifierChoice_asIdsOrRanges || 316280304Sjkim sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0) 317280304Sjkim return 0; 318167612Ssimon 319167612Ssimon /* 320280304Sjkim * It's a list, check it. 321167612Ssimon */ 322280304Sjkim for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) { 323280304Sjkim ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); 324280304Sjkim ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1); 325280304Sjkim ASN1_INTEGER *a_min, *a_max, *b_min, *b_max; 326280304Sjkim 327280304Sjkim extract_min_max(a, &a_min, &a_max); 328280304Sjkim extract_min_max(b, &b_min, &b_max); 329280304Sjkim 330280304Sjkim /* 331280304Sjkim * Punt misordered list, overlapping start, or inverted range. 332280304Sjkim */ 333280304Sjkim if (ASN1_INTEGER_cmp(a_min, b_min) >= 0 || 334280304Sjkim ASN1_INTEGER_cmp(a_min, a_max) > 0 || 335280304Sjkim ASN1_INTEGER_cmp(b_min, b_max) > 0) 336280304Sjkim goto done; 337280304Sjkim 338280304Sjkim /* 339280304Sjkim * Calculate a_max + 1 to check for adjacency. 340280304Sjkim */ 341280304Sjkim if ((bn == NULL && (bn = BN_new()) == NULL) || 342280304Sjkim ASN1_INTEGER_to_BN(a_max, bn) == NULL || 343280304Sjkim !BN_add_word(bn, 1) || 344280304Sjkim (a_max_plus_one = 345280304Sjkim BN_to_ASN1_INTEGER(bn, a_max_plus_one)) == NULL) { 346280304Sjkim X509V3err(X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL, 347280304Sjkim ERR_R_MALLOC_FAILURE); 348280304Sjkim goto done; 349280304Sjkim } 350280304Sjkim 351280304Sjkim /* 352280304Sjkim * Punt if adjacent or overlapping. 353280304Sjkim */ 354280304Sjkim if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) >= 0) 355280304Sjkim goto done; 356167612Ssimon } 357280304Sjkim 358167612Ssimon /* 359280304Sjkim * Check for inverted range. 360167612Ssimon */ 361280304Sjkim i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; 362280304Sjkim { 363280304Sjkim ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); 364280304Sjkim ASN1_INTEGER *a_min, *a_max; 365280304Sjkim if (a != NULL && a->type == ASIdOrRange_range) { 366280304Sjkim extract_min_max(a, &a_min, &a_max); 367280304Sjkim if (ASN1_INTEGER_cmp(a_min, a_max) > 0) 368280304Sjkim goto done; 369280304Sjkim } 370237657Sjkim } 371237657Sjkim 372280304Sjkim ret = 1; 373167612Ssimon 374167612Ssimon done: 375280304Sjkim ASN1_INTEGER_free(a_max_plus_one); 376280304Sjkim BN_free(bn); 377280304Sjkim return ret; 378167612Ssimon} 379167612Ssimon 380167612Ssimon/* 381167612Ssimon * Check whether an ASIdentifier extension is in canonical form. 382167612Ssimon */ 383167612Ssimonint v3_asid_is_canonical(ASIdentifiers *asid) 384167612Ssimon{ 385280304Sjkim return (asid == NULL || 386280304Sjkim (ASIdentifierChoice_is_canonical(asid->asnum) && 387280304Sjkim ASIdentifierChoice_is_canonical(asid->rdi))); 388167612Ssimon} 389167612Ssimon 390167612Ssimon/* 391167612Ssimon * Whack an ASIdentifierChoice into canonical form. 392167612Ssimon */ 393167612Ssimonstatic int ASIdentifierChoice_canonize(ASIdentifierChoice *choice) 394167612Ssimon{ 395280304Sjkim ASN1_INTEGER *a_max_plus_one = NULL; 396280304Sjkim BIGNUM *bn = NULL; 397280304Sjkim int i, ret = 0; 398167612Ssimon 399167612Ssimon /* 400280304Sjkim * Nothing to do for empty element or inheritance. 401167612Ssimon */ 402280304Sjkim if (choice == NULL || choice->type == ASIdentifierChoice_inherit) 403280304Sjkim return 1; 404167612Ssimon 405167612Ssimon /* 406280304Sjkim * If not a list, or if empty list, it's broken. 407237657Sjkim */ 408280304Sjkim if (choice->type != ASIdentifierChoice_asIdsOrRanges || 409280304Sjkim sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0) { 410280304Sjkim X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, 411280304Sjkim X509V3_R_EXTENSION_VALUE_ERROR); 412280304Sjkim return 0; 413280304Sjkim } 414237657Sjkim 415237657Sjkim /* 416280304Sjkim * We have a non-empty list. Sort it. 417167612Ssimon */ 418280304Sjkim sk_ASIdOrRange_sort(choice->u.asIdsOrRanges); 419167612Ssimon 420167612Ssimon /* 421280304Sjkim * Now check for errors and suboptimal encoding, rejecting the 422280304Sjkim * former and fixing the latter. 423167612Ssimon */ 424280304Sjkim for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) { 425280304Sjkim ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); 426280304Sjkim ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1); 427280304Sjkim ASN1_INTEGER *a_min, *a_max, *b_min, *b_max; 428280304Sjkim 429280304Sjkim extract_min_max(a, &a_min, &a_max); 430280304Sjkim extract_min_max(b, &b_min, &b_max); 431280304Sjkim 432280304Sjkim /* 433280304Sjkim * Make sure we're properly sorted (paranoia). 434280304Sjkim */ 435280304Sjkim OPENSSL_assert(ASN1_INTEGER_cmp(a_min, b_min) <= 0); 436280304Sjkim 437280304Sjkim /* 438280304Sjkim * Punt inverted ranges. 439280304Sjkim */ 440280304Sjkim if (ASN1_INTEGER_cmp(a_min, a_max) > 0 || 441280304Sjkim ASN1_INTEGER_cmp(b_min, b_max) > 0) 442280304Sjkim goto done; 443280304Sjkim 444280304Sjkim /* 445280304Sjkim * Check for overlaps. 446280304Sjkim */ 447280304Sjkim if (ASN1_INTEGER_cmp(a_max, b_min) >= 0) { 448280304Sjkim X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, 449280304Sjkim X509V3_R_EXTENSION_VALUE_ERROR); 450280304Sjkim goto done; 451280304Sjkim } 452280304Sjkim 453280304Sjkim /* 454280304Sjkim * Calculate a_max + 1 to check for adjacency. 455280304Sjkim */ 456280304Sjkim if ((bn == NULL && (bn = BN_new()) == NULL) || 457280304Sjkim ASN1_INTEGER_to_BN(a_max, bn) == NULL || 458280304Sjkim !BN_add_word(bn, 1) || 459280304Sjkim (a_max_plus_one = 460280304Sjkim BN_to_ASN1_INTEGER(bn, a_max_plus_one)) == NULL) { 461280304Sjkim X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, 462280304Sjkim ERR_R_MALLOC_FAILURE); 463280304Sjkim goto done; 464280304Sjkim } 465280304Sjkim 466280304Sjkim /* 467280304Sjkim * If a and b are adjacent, merge them. 468280304Sjkim */ 469280304Sjkim if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) == 0) { 470280304Sjkim ASRange *r; 471280304Sjkim switch (a->type) { 472280304Sjkim case ASIdOrRange_id: 473280304Sjkim if ((r = OPENSSL_malloc(sizeof(ASRange))) == NULL) { 474280304Sjkim X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, 475280304Sjkim ERR_R_MALLOC_FAILURE); 476280304Sjkim goto done; 477280304Sjkim } 478280304Sjkim r->min = a_min; 479280304Sjkim r->max = b_max; 480280304Sjkim a->type = ASIdOrRange_range; 481280304Sjkim a->u.range = r; 482280304Sjkim break; 483280304Sjkim case ASIdOrRange_range: 484280304Sjkim ASN1_INTEGER_free(a->u.range->max); 485280304Sjkim a->u.range->max = b_max; 486280304Sjkim break; 487280304Sjkim } 488280304Sjkim switch (b->type) { 489280304Sjkim case ASIdOrRange_id: 490280304Sjkim b->u.id = NULL; 491280304Sjkim break; 492280304Sjkim case ASIdOrRange_range: 493280304Sjkim b->u.range->max = NULL; 494280304Sjkim break; 495280304Sjkim } 496280304Sjkim ASIdOrRange_free(b); 497280304Sjkim (void)sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i + 1); 498280304Sjkim i--; 499280304Sjkim continue; 500280304Sjkim } 501167612Ssimon } 502280304Sjkim 503167612Ssimon /* 504280304Sjkim * Check for final inverted range. 505167612Ssimon */ 506280304Sjkim i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; 507280304Sjkim { 508280304Sjkim ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); 509280304Sjkim ASN1_INTEGER *a_min, *a_max; 510280304Sjkim if (a != NULL && a->type == ASIdOrRange_range) { 511280304Sjkim extract_min_max(a, &a_min, &a_max); 512280304Sjkim if (ASN1_INTEGER_cmp(a_min, a_max) > 0) 513280304Sjkim goto done; 514280304Sjkim } 515167612Ssimon } 516167612Ssimon 517280304Sjkim OPENSSL_assert(ASIdentifierChoice_is_canonical(choice)); /* Paranoia */ 518167612Ssimon 519280304Sjkim ret = 1; 520237657Sjkim 521167612Ssimon done: 522280304Sjkim ASN1_INTEGER_free(a_max_plus_one); 523280304Sjkim BN_free(bn); 524280304Sjkim return ret; 525167612Ssimon} 526167612Ssimon 527167612Ssimon/* 528167612Ssimon * Whack an ASIdentifier extension into canonical form. 529167612Ssimon */ 530167612Ssimonint v3_asid_canonize(ASIdentifiers *asid) 531167612Ssimon{ 532280304Sjkim return (asid == NULL || 533280304Sjkim (ASIdentifierChoice_canonize(asid->asnum) && 534280304Sjkim 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, 541280304Sjkim struct v3_ext_ctx *ctx, 542280304Sjkim STACK_OF(CONF_VALUE) *values) 543167612Ssimon{ 544280304Sjkim ASN1_INTEGER *min = NULL, *max = NULL; 545280304Sjkim ASIdentifiers *asid = NULL; 546280304Sjkim int i; 547167612Ssimon 548280304Sjkim if ((asid = ASIdentifiers_new()) == NULL) { 549280304Sjkim X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE); 550280304Sjkim return NULL; 551280304Sjkim } 552167612Ssimon 553280304Sjkim for (i = 0; i < sk_CONF_VALUE_num(values); i++) { 554280304Sjkim CONF_VALUE *val = sk_CONF_VALUE_value(values, i); 555280304Sjkim int i1, i2, i3, is_range, which; 556167612Ssimon 557280304Sjkim /* 558280304Sjkim * Figure out whether this is an AS or an RDI. 559280304Sjkim */ 560280304Sjkim if (!name_cmp(val->name, "AS")) { 561280304Sjkim which = V3_ASID_ASNUM; 562280304Sjkim } else if (!name_cmp(val->name, "RDI")) { 563280304Sjkim which = V3_ASID_RDI; 564280304Sjkim } else { 565280304Sjkim X509V3err(X509V3_F_V2I_ASIDENTIFIERS, 566280304Sjkim X509V3_R_EXTENSION_NAME_ERROR); 567280304Sjkim X509V3_conf_err(val); 568280304Sjkim goto err; 569280304Sjkim } 570167612Ssimon 571280304Sjkim /* 572280304Sjkim * Handle inheritance. 573280304Sjkim */ 574280304Sjkim if (!strcmp(val->value, "inherit")) { 575280304Sjkim if (v3_asid_add_inherit(asid, which)) 576280304Sjkim continue; 577280304Sjkim X509V3err(X509V3_F_V2I_ASIDENTIFIERS, 578280304Sjkim X509V3_R_INVALID_INHERITANCE); 579280304Sjkim X509V3_conf_err(val); 580280304Sjkim goto err; 581280304Sjkim } 582167612Ssimon 583280304Sjkim /* 584280304Sjkim * Number, range, or mistake, pick it apart and figure out which. 585280304Sjkim */ 586280304Sjkim i1 = strspn(val->value, "0123456789"); 587280304Sjkim if (val->value[i1] == '\0') { 588280304Sjkim is_range = 0; 589280304Sjkim } else { 590280304Sjkim is_range = 1; 591280304Sjkim i2 = i1 + strspn(val->value + i1, " \t"); 592280304Sjkim if (val->value[i2] != '-') { 593280304Sjkim X509V3err(X509V3_F_V2I_ASIDENTIFIERS, 594280304Sjkim X509V3_R_INVALID_ASNUMBER); 595280304Sjkim X509V3_conf_err(val); 596280304Sjkim goto err; 597280304Sjkim } 598280304Sjkim i2++; 599280304Sjkim i2 = i2 + strspn(val->value + i2, " \t"); 600280304Sjkim i3 = i2 + strspn(val->value + i2, "0123456789"); 601280304Sjkim if (val->value[i3] != '\0') { 602280304Sjkim X509V3err(X509V3_F_V2I_ASIDENTIFIERS, 603280304Sjkim X509V3_R_INVALID_ASRANGE); 604280304Sjkim X509V3_conf_err(val); 605280304Sjkim goto err; 606280304Sjkim } 607280304Sjkim } 608280304Sjkim 609280304Sjkim /* 610280304Sjkim * Syntax is ok, read and add it. 611280304Sjkim */ 612280304Sjkim if (!is_range) { 613280304Sjkim if (!X509V3_get_value_int(val, &min)) { 614280304Sjkim X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE); 615280304Sjkim goto err; 616280304Sjkim } 617280304Sjkim } else { 618280304Sjkim char *s = BUF_strdup(val->value); 619280304Sjkim if (s == NULL) { 620280304Sjkim X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE); 621280304Sjkim goto err; 622280304Sjkim } 623280304Sjkim s[i1] = '\0'; 624280304Sjkim min = s2i_ASN1_INTEGER(NULL, s); 625280304Sjkim max = s2i_ASN1_INTEGER(NULL, s + i2); 626280304Sjkim OPENSSL_free(s); 627280304Sjkim if (min == NULL || max == NULL) { 628280304Sjkim X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE); 629280304Sjkim goto err; 630280304Sjkim } 631280304Sjkim if (ASN1_INTEGER_cmp(min, max) > 0) { 632280304Sjkim X509V3err(X509V3_F_V2I_ASIDENTIFIERS, 633280304Sjkim X509V3_R_EXTENSION_VALUE_ERROR); 634280304Sjkim goto err; 635280304Sjkim } 636280304Sjkim } 637280304Sjkim if (!v3_asid_add_id_or_range(asid, which, min, max)) { 638280304Sjkim X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE); 639280304Sjkim goto err; 640280304Sjkim } 641280304Sjkim min = max = NULL; 642167612Ssimon } 643167612Ssimon 644167612Ssimon /* 645280304Sjkim * Canonize the result, then we're done. 646167612Ssimon */ 647280304Sjkim if (!v3_asid_canonize(asid)) 648280304Sjkim goto err; 649280304Sjkim return asid; 650167612Ssimon 651167612Ssimon err: 652280304Sjkim ASIdentifiers_free(asid); 653280304Sjkim ASN1_INTEGER_free(min); 654280304Sjkim ASN1_INTEGER_free(max); 655280304Sjkim return NULL; 656167612Ssimon} 657167612Ssimon 658167612Ssimon/* 659167612Ssimon * OpenSSL dispatch. 660167612Ssimon */ 661167612Ssimonconst X509V3_EXT_METHOD v3_asid = { 662280304Sjkim NID_sbgp_autonomousSysNum, /* nid */ 663280304Sjkim 0, /* flags */ 664280304Sjkim ASN1_ITEM_ref(ASIdentifiers), /* template */ 665280304Sjkim 0, 0, 0, 0, /* old functions, ignored */ 666280304Sjkim 0, /* i2s */ 667280304Sjkim 0, /* s2i */ 668280304Sjkim 0, /* i2v */ 669280304Sjkim v2i_ASIdentifiers, /* v2i */ 670280304Sjkim i2r_ASIdentifiers, /* i2r */ 671280304Sjkim 0, /* r2i */ 672280304Sjkim NULL /* extension-specific data */ 673167612Ssimon}; 674167612Ssimon 675167612Ssimon/* 676167612Ssimon * Figure out whether extension uses inheritance. 677167612Ssimon */ 678167612Ssimonint v3_asid_inherits(ASIdentifiers *asid) 679167612Ssimon{ 680280304Sjkim return (asid != NULL && 681280304Sjkim ((asid->asnum != NULL && 682280304Sjkim asid->asnum->type == ASIdentifierChoice_inherit) || 683280304Sjkim (asid->rdi != NULL && 684280304Sjkim 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{ 692280304Sjkim ASN1_INTEGER *p_min, *p_max, *c_min, *c_max; 693280304Sjkim int p, c; 694167612Ssimon 695280304Sjkim if (child == NULL || parent == child) 696280304Sjkim return 1; 697280304Sjkim if (parent == NULL) 698280304Sjkim return 0; 699167612Ssimon 700280304Sjkim p = 0; 701280304Sjkim for (c = 0; c < sk_ASIdOrRange_num(child); c++) { 702280304Sjkim extract_min_max(sk_ASIdOrRange_value(child, c), &c_min, &c_max); 703280304Sjkim for (;; p++) { 704280304Sjkim if (p >= sk_ASIdOrRange_num(parent)) 705280304Sjkim return 0; 706280304Sjkim extract_min_max(sk_ASIdOrRange_value(parent, p), &p_min, &p_max); 707280304Sjkim if (ASN1_INTEGER_cmp(p_max, c_max) < 0) 708280304Sjkim continue; 709280304Sjkim if (ASN1_INTEGER_cmp(p_min, c_min) > 0) 710280304Sjkim return 0; 711280304Sjkim break; 712280304Sjkim } 713167612Ssimon } 714167612Ssimon 715280304Sjkim return 1; 716167612Ssimon} 717167612Ssimon 718167612Ssimon/* 719167612Ssimon * Test whether a is a subet of b. 720167612Ssimon */ 721167612Ssimonint v3_asid_subset(ASIdentifiers *a, ASIdentifiers *b) 722167612Ssimon{ 723280304Sjkim return (a == NULL || 724280304Sjkim a == b || 725280304Sjkim (b != NULL && 726280304Sjkim !v3_asid_inherits(a) && 727280304Sjkim !v3_asid_inherits(b) && 728280304Sjkim asid_contains(b->asnum->u.asIdsOrRanges, 729280304Sjkim a->asnum->u.asIdsOrRanges) && 730280304Sjkim asid_contains(b->rdi->u.asIdsOrRanges, 731280304Sjkim a->rdi->u.asIdsOrRanges))); 732167612Ssimon} 733167612Ssimon 734167612Ssimon/* 735167612Ssimon * Validation error handling via callback. 736167612Ssimon */ 737280304Sjkim# define validation_err(_err_) \ 738280304Sjkim do { \ 739280304Sjkim if (ctx != NULL) { \ 740280304Sjkim ctx->error = _err_; \ 741280304Sjkim ctx->error_depth = i; \ 742280304Sjkim ctx->current_cert = x; \ 743280304Sjkim ret = ctx->verify_cb(0, ctx); \ 744280304Sjkim } else { \ 745280304Sjkim ret = 0; \ 746280304Sjkim } \ 747280304Sjkim if (!ret) \ 748280304Sjkim 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, 755280304Sjkim STACK_OF(X509) *chain, 756280304Sjkim ASIdentifiers *ext) 757167612Ssimon{ 758280304Sjkim ASIdOrRanges *child_as = NULL, *child_rdi = NULL; 759280304Sjkim int i, ret = 1, inherit_as = 0, inherit_rdi = 0; 760280304Sjkim X509 *x; 761167612Ssimon 762280304Sjkim OPENSSL_assert(chain != NULL && sk_X509_num(chain) > 0); 763280304Sjkim OPENSSL_assert(ctx != NULL || ext != NULL); 764280304Sjkim OPENSSL_assert(ctx == NULL || ctx->verify_cb != NULL); 765167612Ssimon 766280304Sjkim /* 767280304Sjkim * Figure out where to start. If we don't have an extension to 768280304Sjkim * check, we're done. Otherwise, check canonical form and 769280304Sjkim * set up for walking up the chain. 770280304Sjkim */ 771280304Sjkim if (ext != NULL) { 772280304Sjkim i = -1; 773280304Sjkim x = NULL; 774280304Sjkim } else { 775280304Sjkim i = 0; 776280304Sjkim x = sk_X509_value(chain, i); 777280304Sjkim OPENSSL_assert(x != NULL); 778280304Sjkim if ((ext = x->rfc3779_asid) == NULL) 779280304Sjkim goto done; 780167612Ssimon } 781280304Sjkim if (!v3_asid_is_canonical(ext)) 782280304Sjkim validation_err(X509_V_ERR_INVALID_EXTENSION); 783280304Sjkim if (ext->asnum != NULL) { 784280304Sjkim switch (ext->asnum->type) { 785280304Sjkim case ASIdentifierChoice_inherit: 786280304Sjkim inherit_as = 1; 787280304Sjkim break; 788280304Sjkim case ASIdentifierChoice_asIdsOrRanges: 789280304Sjkim child_as = ext->asnum->u.asIdsOrRanges; 790280304Sjkim break; 791280304Sjkim } 792167612Ssimon } 793280304Sjkim if (ext->rdi != NULL) { 794280304Sjkim switch (ext->rdi->type) { 795280304Sjkim case ASIdentifierChoice_inherit: 796280304Sjkim inherit_rdi = 1; 797280304Sjkim break; 798280304Sjkim case ASIdentifierChoice_asIdsOrRanges: 799280304Sjkim child_rdi = ext->rdi->u.asIdsOrRanges; 800280304Sjkim break; 801280304Sjkim } 802280304Sjkim } 803167612Ssimon 804280304Sjkim /* 805280304Sjkim * Now walk up the chain. Extensions must be in canonical form, no 806280304Sjkim * cert may list resources that its parent doesn't list. 807280304Sjkim */ 808280304Sjkim for (i++; i < sk_X509_num(chain); i++) { 809280304Sjkim x = sk_X509_value(chain, i); 810280304Sjkim OPENSSL_assert(x != NULL); 811280304Sjkim if (x->rfc3779_asid == NULL) { 812280304Sjkim if (child_as != NULL || child_rdi != NULL) 813280304Sjkim validation_err(X509_V_ERR_UNNESTED_RESOURCE); 814280304Sjkim continue; 815280304Sjkim } 816280304Sjkim if (!v3_asid_is_canonical(x->rfc3779_asid)) 817280304Sjkim validation_err(X509_V_ERR_INVALID_EXTENSION); 818280304Sjkim if (x->rfc3779_asid->asnum == NULL && child_as != NULL) { 819280304Sjkim validation_err(X509_V_ERR_UNNESTED_RESOURCE); 820280304Sjkim child_as = NULL; 821280304Sjkim inherit_as = 0; 822280304Sjkim } 823280304Sjkim if (x->rfc3779_asid->asnum != NULL && 824280304Sjkim x->rfc3779_asid->asnum->type == 825280304Sjkim ASIdentifierChoice_asIdsOrRanges) { 826280304Sjkim if (inherit_as 827280304Sjkim || asid_contains(x->rfc3779_asid->asnum->u.asIdsOrRanges, 828280304Sjkim child_as)) { 829280304Sjkim child_as = x->rfc3779_asid->asnum->u.asIdsOrRanges; 830280304Sjkim inherit_as = 0; 831280304Sjkim } else { 832280304Sjkim validation_err(X509_V_ERR_UNNESTED_RESOURCE); 833280304Sjkim } 834280304Sjkim } 835280304Sjkim if (x->rfc3779_asid->rdi == NULL && child_rdi != NULL) { 836280304Sjkim validation_err(X509_V_ERR_UNNESTED_RESOURCE); 837280304Sjkim child_rdi = NULL; 838280304Sjkim inherit_rdi = 0; 839280304Sjkim } 840280304Sjkim if (x->rfc3779_asid->rdi != NULL && 841280304Sjkim x->rfc3779_asid->rdi->type == ASIdentifierChoice_asIdsOrRanges) { 842280304Sjkim if (inherit_rdi || 843280304Sjkim asid_contains(x->rfc3779_asid->rdi->u.asIdsOrRanges, 844280304Sjkim child_rdi)) { 845280304Sjkim child_rdi = x->rfc3779_asid->rdi->u.asIdsOrRanges; 846280304Sjkim inherit_rdi = 0; 847280304Sjkim } else { 848280304Sjkim validation_err(X509_V_ERR_UNNESTED_RESOURCE); 849280304Sjkim } 850280304Sjkim } 851280304Sjkim } 852280304Sjkim 853280304Sjkim /* 854280304Sjkim * Trust anchor can't inherit. 855280304Sjkim */ 856237657Sjkim OPENSSL_assert(x != NULL); 857280304Sjkim if (x->rfc3779_asid != NULL) { 858280304Sjkim if (x->rfc3779_asid->asnum != NULL && 859280304Sjkim x->rfc3779_asid->asnum->type == ASIdentifierChoice_inherit) 860280304Sjkim validation_err(X509_V_ERR_UNNESTED_RESOURCE); 861280304Sjkim if (x->rfc3779_asid->rdi != NULL && 862280304Sjkim x->rfc3779_asid->rdi->type == ASIdentifierChoice_inherit) 863280304Sjkim validation_err(X509_V_ERR_UNNESTED_RESOURCE); 864167612Ssimon } 865167612Ssimon 866167612Ssimon done: 867280304Sjkim return ret; 868167612Ssimon} 869167612Ssimon 870280304Sjkim# 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{ 877280304Sjkim 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, 885280304Sjkim ASIdentifiers *ext, int allow_inheritance) 886167612Ssimon{ 887280304Sjkim if (ext == NULL) 888280304Sjkim return 1; 889280304Sjkim if (chain == NULL || sk_X509_num(chain) == 0) 890280304Sjkim return 0; 891280304Sjkim if (!allow_inheritance && v3_asid_inherits(ext)) 892280304Sjkim return 0; 893280304Sjkim return v3_asid_validate_path_internal(NULL, chain, ext); 894167612Ssimon} 895167612Ssimon 896280304Sjkim#endif /* OPENSSL_NO_RFC3779 */ 897