v3_asid.c revision 237657
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 13167612Ssimon * 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, 107167612Ssimon ASIdentifierChoice *choice, 108167612Ssimon int indent, 109167612Ssimon const char *msg) 110167612Ssimon{ 111167612Ssimon int i; 112167612Ssimon char *s; 113167612Ssimon if (choice == NULL) 114167612Ssimon return 1; 115167612Ssimon BIO_printf(out, "%*s%s:\n", indent, "", msg); 116167612Ssimon switch (choice->type) { 117167612Ssimon case ASIdentifierChoice_inherit: 118167612Ssimon BIO_printf(out, "%*sinherit\n", indent + 2, ""); 119167612Ssimon break; 120167612Ssimon case ASIdentifierChoice_asIdsOrRanges: 121167612Ssimon for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges); i++) { 122167612Ssimon ASIdOrRange *aor = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); 123167612Ssimon switch (aor->type) { 124167612Ssimon case ASIdOrRange_id: 125167612Ssimon if ((s = i2s_ASN1_INTEGER(NULL, aor->u.id)) == NULL) 126167612Ssimon return 0; 127167612Ssimon BIO_printf(out, "%*s%s\n", indent + 2, "", s); 128167612Ssimon OPENSSL_free(s); 129167612Ssimon break; 130167612Ssimon case ASIdOrRange_range: 131167612Ssimon if ((s = i2s_ASN1_INTEGER(NULL, aor->u.range->min)) == NULL) 132167612Ssimon return 0; 133167612Ssimon BIO_printf(out, "%*s%s-", indent + 2, "", s); 134167612Ssimon OPENSSL_free(s); 135167612Ssimon if ((s = i2s_ASN1_INTEGER(NULL, aor->u.range->max)) == NULL) 136167612Ssimon return 0; 137167612Ssimon BIO_printf(out, "%s\n", s); 138167612Ssimon OPENSSL_free(s); 139167612Ssimon break; 140167612Ssimon default: 141167612Ssimon return 0; 142167612Ssimon } 143167612Ssimon } 144167612Ssimon break; 145167612Ssimon default: 146167612Ssimon return 0; 147167612Ssimon } 148167612Ssimon return 1; 149167612Ssimon} 150167612Ssimon 151167612Ssimon/* 152167612Ssimon * i2r method for an ASIdentifier extension. 153167612Ssimon */ 154167612Ssimonstatic int i2r_ASIdentifiers(X509V3_EXT_METHOD *method, 155167612Ssimon void *ext, 156167612Ssimon BIO *out, 157167612Ssimon int indent) 158167612Ssimon{ 159167612Ssimon ASIdentifiers *asid = ext; 160167612Ssimon return (i2r_ASIdentifierChoice(out, asid->asnum, indent, 161167612Ssimon "Autonomous System Numbers") && 162167612Ssimon i2r_ASIdentifierChoice(out, asid->rdi, indent, 163167612Ssimon "Routing Domain Identifiers")); 164167612Ssimon} 165167612Ssimon 166167612Ssimon/* 167167612Ssimon * Sort comparision function for a sequence of ASIdOrRange elements. 168167612Ssimon */ 169167612Ssimonstatic int ASIdOrRange_cmp(const ASIdOrRange * const *a_, 170167612Ssimon const ASIdOrRange * const *b_) 171167612Ssimon{ 172167612Ssimon const ASIdOrRange *a = *a_, *b = *b_; 173167612Ssimon 174237657Sjkim OPENSSL_assert((a->type == ASIdOrRange_id && a->u.id != NULL) || 175167612Ssimon (a->type == ASIdOrRange_range && a->u.range != NULL && 176167612Ssimon a->u.range->min != NULL && a->u.range->max != NULL)); 177167612Ssimon 178237657Sjkim OPENSSL_assert((b->type == ASIdOrRange_id && b->u.id != NULL) || 179167612Ssimon (b->type == ASIdOrRange_range && b->u.range != NULL && 180167612Ssimon b->u.range->min != NULL && b->u.range->max != NULL)); 181167612Ssimon 182167612Ssimon if (a->type == ASIdOrRange_id && b->type == ASIdOrRange_id) 183167612Ssimon return ASN1_INTEGER_cmp(a->u.id, b->u.id); 184167612Ssimon 185167612Ssimon if (a->type == ASIdOrRange_range && b->type == ASIdOrRange_range) { 186167612Ssimon int r = ASN1_INTEGER_cmp(a->u.range->min, b->u.range->min); 187167612Ssimon return r != 0 ? r : ASN1_INTEGER_cmp(a->u.range->max, b->u.range->max); 188167612Ssimon } 189167612Ssimon 190167612Ssimon if (a->type == ASIdOrRange_id) 191167612Ssimon return ASN1_INTEGER_cmp(a->u.id, b->u.range->min); 192167612Ssimon else 193167612Ssimon return ASN1_INTEGER_cmp(a->u.range->min, b->u.id); 194167612Ssimon} 195167612Ssimon 196167612Ssimon/* 197167612Ssimon * Add an inherit element. 198167612Ssimon */ 199167612Ssimonint v3_asid_add_inherit(ASIdentifiers *asid, int which) 200167612Ssimon{ 201167612Ssimon ASIdentifierChoice **choice; 202167612Ssimon if (asid == NULL) 203167612Ssimon return 0; 204167612Ssimon switch (which) { 205167612Ssimon case V3_ASID_ASNUM: 206167612Ssimon choice = &asid->asnum; 207167612Ssimon break; 208167612Ssimon case V3_ASID_RDI: 209167612Ssimon choice = &asid->rdi; 210167612Ssimon break; 211167612Ssimon default: 212167612Ssimon return 0; 213167612Ssimon } 214167612Ssimon if (*choice == NULL) { 215167612Ssimon if ((*choice = ASIdentifierChoice_new()) == NULL) 216167612Ssimon return 0; 217237657Sjkim OPENSSL_assert((*choice)->u.inherit == NULL); 218167612Ssimon if (((*choice)->u.inherit = ASN1_NULL_new()) == NULL) 219167612Ssimon return 0; 220167612Ssimon (*choice)->type = ASIdentifierChoice_inherit; 221167612Ssimon } 222167612Ssimon return (*choice)->type == ASIdentifierChoice_inherit; 223167612Ssimon} 224167612Ssimon 225167612Ssimon/* 226167612Ssimon * Add an ID or range to an ASIdentifierChoice. 227167612Ssimon */ 228167612Ssimonint v3_asid_add_id_or_range(ASIdentifiers *asid, 229167612Ssimon int which, 230167612Ssimon ASN1_INTEGER *min, 231167612Ssimon ASN1_INTEGER *max) 232167612Ssimon{ 233167612Ssimon ASIdentifierChoice **choice; 234167612Ssimon ASIdOrRange *aor; 235167612Ssimon if (asid == NULL) 236167612Ssimon return 0; 237167612Ssimon switch (which) { 238167612Ssimon case V3_ASID_ASNUM: 239167612Ssimon choice = &asid->asnum; 240167612Ssimon break; 241167612Ssimon case V3_ASID_RDI: 242167612Ssimon choice = &asid->rdi; 243167612Ssimon break; 244167612Ssimon default: 245167612Ssimon return 0; 246167612Ssimon } 247167612Ssimon if (*choice != NULL && (*choice)->type == ASIdentifierChoice_inherit) 248167612Ssimon return 0; 249167612Ssimon if (*choice == NULL) { 250167612Ssimon if ((*choice = ASIdentifierChoice_new()) == NULL) 251167612Ssimon return 0; 252237657Sjkim OPENSSL_assert((*choice)->u.asIdsOrRanges == NULL); 253167612Ssimon (*choice)->u.asIdsOrRanges = sk_ASIdOrRange_new(ASIdOrRange_cmp); 254167612Ssimon if ((*choice)->u.asIdsOrRanges == NULL) 255167612Ssimon return 0; 256167612Ssimon (*choice)->type = ASIdentifierChoice_asIdsOrRanges; 257167612Ssimon } 258167612Ssimon if ((aor = ASIdOrRange_new()) == NULL) 259167612Ssimon return 0; 260167612Ssimon if (max == NULL) { 261167612Ssimon aor->type = ASIdOrRange_id; 262167612Ssimon aor->u.id = min; 263167612Ssimon } else { 264167612Ssimon aor->type = ASIdOrRange_range; 265167612Ssimon if ((aor->u.range = ASRange_new()) == NULL) 266167612Ssimon goto err; 267167612Ssimon ASN1_INTEGER_free(aor->u.range->min); 268167612Ssimon aor->u.range->min = min; 269167612Ssimon ASN1_INTEGER_free(aor->u.range->max); 270167612Ssimon aor->u.range->max = max; 271167612Ssimon } 272167612Ssimon if (!(sk_ASIdOrRange_push((*choice)->u.asIdsOrRanges, aor))) 273167612Ssimon goto err; 274167612Ssimon return 1; 275167612Ssimon 276167612Ssimon err: 277167612Ssimon ASIdOrRange_free(aor); 278167612Ssimon return 0; 279167612Ssimon} 280167612Ssimon 281167612Ssimon/* 282167612Ssimon * Extract min and max values from an ASIdOrRange. 283167612Ssimon */ 284167612Ssimonstatic void extract_min_max(ASIdOrRange *aor, 285167612Ssimon ASN1_INTEGER **min, 286167612Ssimon ASN1_INTEGER **max) 287167612Ssimon{ 288237657Sjkim OPENSSL_assert(aor != NULL && min != NULL && max != NULL); 289167612Ssimon switch (aor->type) { 290167612Ssimon case ASIdOrRange_id: 291167612Ssimon *min = aor->u.id; 292167612Ssimon *max = aor->u.id; 293167612Ssimon return; 294167612Ssimon case ASIdOrRange_range: 295167612Ssimon *min = aor->u.range->min; 296167612Ssimon *max = aor->u.range->max; 297167612Ssimon return; 298167612Ssimon } 299167612Ssimon} 300167612Ssimon 301167612Ssimon/* 302167612Ssimon * Check whether an ASIdentifierChoice is in canonical form. 303167612Ssimon */ 304167612Ssimonstatic int ASIdentifierChoice_is_canonical(ASIdentifierChoice *choice) 305167612Ssimon{ 306167612Ssimon ASN1_INTEGER *a_max_plus_one = NULL; 307167612Ssimon BIGNUM *bn = NULL; 308167612Ssimon int i, ret = 0; 309167612Ssimon 310167612Ssimon /* 311167612Ssimon * Empty element or inheritance is canonical. 312167612Ssimon */ 313167612Ssimon if (choice == NULL || choice->type == ASIdentifierChoice_inherit) 314167612Ssimon return 1; 315167612Ssimon 316167612Ssimon /* 317167612Ssimon * If not a list, or if empty list, it's broken. 318167612Ssimon */ 319167612Ssimon if (choice->type != ASIdentifierChoice_asIdsOrRanges || 320167612Ssimon sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0) 321167612Ssimon return 0; 322167612Ssimon 323167612Ssimon /* 324167612Ssimon * It's a list, check it. 325167612Ssimon */ 326167612Ssimon for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) { 327167612Ssimon ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); 328167612Ssimon ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1); 329167612Ssimon ASN1_INTEGER *a_min, *a_max, *b_min, *b_max; 330167612Ssimon 331167612Ssimon extract_min_max(a, &a_min, &a_max); 332167612Ssimon extract_min_max(b, &b_min, &b_max); 333167612Ssimon 334167612Ssimon /* 335167612Ssimon * Punt misordered list, overlapping start, or inverted range. 336167612Ssimon */ 337167612Ssimon if (ASN1_INTEGER_cmp(a_min, b_min) >= 0 || 338167612Ssimon ASN1_INTEGER_cmp(a_min, a_max) > 0 || 339167612Ssimon ASN1_INTEGER_cmp(b_min, b_max) > 0) 340167612Ssimon goto done; 341167612Ssimon 342167612Ssimon /* 343167612Ssimon * Calculate a_max + 1 to check for adjacency. 344167612Ssimon */ 345167612Ssimon if ((bn == NULL && (bn = BN_new()) == NULL) || 346167612Ssimon ASN1_INTEGER_to_BN(a_max, bn) == NULL || 347167612Ssimon !BN_add_word(bn, 1) || 348167612Ssimon (a_max_plus_one = BN_to_ASN1_INTEGER(bn, a_max_plus_one)) == NULL) { 349167612Ssimon X509V3err(X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL, 350167612Ssimon ERR_R_MALLOC_FAILURE); 351167612Ssimon goto done; 352167612Ssimon } 353167612Ssimon 354167612Ssimon /* 355167612Ssimon * Punt if adjacent or overlapping. 356167612Ssimon */ 357167612Ssimon if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) >= 0) 358167612Ssimon goto done; 359167612Ssimon } 360167612Ssimon 361237657Sjkim /* 362237657Sjkim * Check for inverted range. 363237657Sjkim */ 364237657Sjkim i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; 365237657Sjkim { 366237657Sjkim ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); 367237657Sjkim ASN1_INTEGER *a_min, *a_max; 368237657Sjkim if (a != NULL && a->type == ASIdOrRange_range) { 369237657Sjkim extract_min_max(a, &a_min, &a_max); 370237657Sjkim if (ASN1_INTEGER_cmp(a_min, a_max) > 0) 371237657Sjkim goto done; 372237657Sjkim } 373237657Sjkim } 374237657Sjkim 375167612Ssimon ret = 1; 376167612Ssimon 377167612Ssimon done: 378167612Ssimon ASN1_INTEGER_free(a_max_plus_one); 379167612Ssimon BN_free(bn); 380167612Ssimon return ret; 381167612Ssimon} 382167612Ssimon 383167612Ssimon/* 384167612Ssimon * Check whether an ASIdentifier extension is in canonical form. 385167612Ssimon */ 386167612Ssimonint v3_asid_is_canonical(ASIdentifiers *asid) 387167612Ssimon{ 388167612Ssimon return (asid == NULL || 389237657Sjkim (ASIdentifierChoice_is_canonical(asid->asnum) && 390167612Ssimon ASIdentifierChoice_is_canonical(asid->rdi))); 391167612Ssimon} 392167612Ssimon 393167612Ssimon/* 394167612Ssimon * Whack an ASIdentifierChoice into canonical form. 395167612Ssimon */ 396167612Ssimonstatic int ASIdentifierChoice_canonize(ASIdentifierChoice *choice) 397167612Ssimon{ 398167612Ssimon ASN1_INTEGER *a_max_plus_one = NULL; 399167612Ssimon BIGNUM *bn = NULL; 400167612Ssimon int i, ret = 0; 401167612Ssimon 402167612Ssimon /* 403167612Ssimon * Nothing to do for empty element or inheritance. 404167612Ssimon */ 405167612Ssimon if (choice == NULL || choice->type == ASIdentifierChoice_inherit) 406167612Ssimon return 1; 407167612Ssimon 408167612Ssimon /* 409237657Sjkim * If not a list, or if empty list, it's broken. 410167612Ssimon */ 411237657Sjkim if (choice->type != ASIdentifierChoice_asIdsOrRanges || 412237657Sjkim sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0) { 413237657Sjkim X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, 414237657Sjkim X509V3_R_EXTENSION_VALUE_ERROR); 415237657Sjkim return 0; 416237657Sjkim } 417237657Sjkim 418237657Sjkim /* 419237657Sjkim * We have a non-empty list. Sort it. 420237657Sjkim */ 421167612Ssimon sk_ASIdOrRange_sort(choice->u.asIdsOrRanges); 422167612Ssimon 423167612Ssimon /* 424167612Ssimon * Now check for errors and suboptimal encoding, rejecting the 425167612Ssimon * former and fixing the latter. 426167612Ssimon */ 427167612Ssimon for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) { 428167612Ssimon ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); 429167612Ssimon ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1); 430167612Ssimon ASN1_INTEGER *a_min, *a_max, *b_min, *b_max; 431167612Ssimon 432167612Ssimon extract_min_max(a, &a_min, &a_max); 433167612Ssimon extract_min_max(b, &b_min, &b_max); 434167612Ssimon 435167612Ssimon /* 436167612Ssimon * Make sure we're properly sorted (paranoia). 437167612Ssimon */ 438237657Sjkim OPENSSL_assert(ASN1_INTEGER_cmp(a_min, b_min) <= 0); 439167612Ssimon 440167612Ssimon /* 441237657Sjkim * Punt inverted ranges. 442237657Sjkim */ 443237657Sjkim if (ASN1_INTEGER_cmp(a_min, a_max) > 0 || 444237657Sjkim ASN1_INTEGER_cmp(b_min, b_max) > 0) 445237657Sjkim goto done; 446237657Sjkim 447237657Sjkim /* 448167612Ssimon * Check for overlaps. 449167612Ssimon */ 450167612Ssimon if (ASN1_INTEGER_cmp(a_max, b_min) >= 0) { 451167612Ssimon X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, 452167612Ssimon X509V3_R_EXTENSION_VALUE_ERROR); 453167612Ssimon goto done; 454167612Ssimon } 455167612Ssimon 456167612Ssimon /* 457167612Ssimon * Calculate a_max + 1 to check for adjacency. 458167612Ssimon */ 459167612Ssimon if ((bn == NULL && (bn = BN_new()) == NULL) || 460167612Ssimon ASN1_INTEGER_to_BN(a_max, bn) == NULL || 461167612Ssimon !BN_add_word(bn, 1) || 462167612Ssimon (a_max_plus_one = BN_to_ASN1_INTEGER(bn, a_max_plus_one)) == NULL) { 463167612Ssimon X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, ERR_R_MALLOC_FAILURE); 464167612Ssimon goto done; 465167612Ssimon } 466167612Ssimon 467167612Ssimon /* 468167612Ssimon * If a and b are adjacent, merge them. 469167612Ssimon */ 470167612Ssimon if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) == 0) { 471167612Ssimon ASRange *r; 472167612Ssimon switch (a->type) { 473167612Ssimon case ASIdOrRange_id: 474167612Ssimon if ((r = OPENSSL_malloc(sizeof(ASRange))) == NULL) { 475167612Ssimon X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, 476167612Ssimon ERR_R_MALLOC_FAILURE); 477167612Ssimon goto done; 478167612Ssimon } 479167612Ssimon r->min = a_min; 480167612Ssimon r->max = b_max; 481167612Ssimon a->type = ASIdOrRange_range; 482167612Ssimon a->u.range = r; 483167612Ssimon break; 484167612Ssimon case ASIdOrRange_range: 485167612Ssimon ASN1_INTEGER_free(a->u.range->max); 486167612Ssimon a->u.range->max = b_max; 487167612Ssimon break; 488167612Ssimon } 489167612Ssimon switch (b->type) { 490167612Ssimon case ASIdOrRange_id: 491167612Ssimon b->u.id = NULL; 492167612Ssimon break; 493167612Ssimon case ASIdOrRange_range: 494167612Ssimon b->u.range->max = NULL; 495167612Ssimon break; 496167612Ssimon } 497167612Ssimon ASIdOrRange_free(b); 498237657Sjkim (void) sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i + 1); 499167612Ssimon i--; 500167612Ssimon continue; 501167612Ssimon } 502167612Ssimon } 503167612Ssimon 504237657Sjkim /* 505237657Sjkim * Check for final inverted range. 506237657Sjkim */ 507237657Sjkim i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; 508237657Sjkim { 509237657Sjkim ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); 510237657Sjkim ASN1_INTEGER *a_min, *a_max; 511237657Sjkim if (a != NULL && a->type == ASIdOrRange_range) { 512237657Sjkim extract_min_max(a, &a_min, &a_max); 513237657Sjkim if (ASN1_INTEGER_cmp(a_min, a_max) > 0) 514237657Sjkim goto done; 515237657Sjkim } 516237657Sjkim } 517167612Ssimon 518237657Sjkim OPENSSL_assert(ASIdentifierChoice_is_canonical(choice)); /* Paranoia */ 519237657Sjkim 520167612Ssimon ret = 1; 521167612Ssimon 522167612Ssimon done: 523167612Ssimon ASN1_INTEGER_free(a_max_plus_one); 524167612Ssimon BN_free(bn); 525167612Ssimon return ret; 526167612Ssimon} 527167612Ssimon 528167612Ssimon/* 529167612Ssimon * Whack an ASIdentifier extension into canonical form. 530167612Ssimon */ 531167612Ssimonint v3_asid_canonize(ASIdentifiers *asid) 532167612Ssimon{ 533167612Ssimon return (asid == NULL || 534167612Ssimon (ASIdentifierChoice_canonize(asid->asnum) && 535167612Ssimon ASIdentifierChoice_canonize(asid->rdi))); 536167612Ssimon} 537167612Ssimon 538167612Ssimon/* 539167612Ssimon * v2i method for an ASIdentifier extension. 540167612Ssimon */ 541167612Ssimonstatic void *v2i_ASIdentifiers(struct v3_ext_method *method, 542167612Ssimon struct v3_ext_ctx *ctx, 543167612Ssimon STACK_OF(CONF_VALUE) *values) 544167612Ssimon{ 545237657Sjkim ASN1_INTEGER *min = NULL, *max = NULL; 546167612Ssimon ASIdentifiers *asid = NULL; 547167612Ssimon int i; 548167612Ssimon 549167612Ssimon if ((asid = ASIdentifiers_new()) == NULL) { 550167612Ssimon X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE); 551167612Ssimon return NULL; 552167612Ssimon } 553167612Ssimon 554167612Ssimon for (i = 0; i < sk_CONF_VALUE_num(values); i++) { 555167612Ssimon CONF_VALUE *val = sk_CONF_VALUE_value(values, i); 556167612Ssimon int i1, i2, i3, is_range, which; 557167612Ssimon 558167612Ssimon /* 559167612Ssimon * Figure out whether this is an AS or an RDI. 560167612Ssimon */ 561167612Ssimon if ( !name_cmp(val->name, "AS")) { 562167612Ssimon which = V3_ASID_ASNUM; 563167612Ssimon } else if (!name_cmp(val->name, "RDI")) { 564167612Ssimon which = V3_ASID_RDI; 565167612Ssimon } else { 566167612Ssimon X509V3err(X509V3_F_V2I_ASIDENTIFIERS, X509V3_R_EXTENSION_NAME_ERROR); 567167612Ssimon X509V3_conf_err(val); 568167612Ssimon goto err; 569167612Ssimon } 570167612Ssimon 571167612Ssimon /* 572167612Ssimon * Handle inheritance. 573167612Ssimon */ 574167612Ssimon if (!strcmp(val->value, "inherit")) { 575167612Ssimon if (v3_asid_add_inherit(asid, which)) 576167612Ssimon continue; 577167612Ssimon X509V3err(X509V3_F_V2I_ASIDENTIFIERS, X509V3_R_INVALID_INHERITANCE); 578167612Ssimon X509V3_conf_err(val); 579167612Ssimon goto err; 580167612Ssimon } 581167612Ssimon 582167612Ssimon /* 583167612Ssimon * Number, range, or mistake, pick it apart and figure out which. 584167612Ssimon */ 585167612Ssimon i1 = strspn(val->value, "0123456789"); 586167612Ssimon if (val->value[i1] == '\0') { 587167612Ssimon is_range = 0; 588167612Ssimon } else { 589167612Ssimon is_range = 1; 590167612Ssimon i2 = i1 + strspn(val->value + i1, " \t"); 591167612Ssimon if (val->value[i2] != '-') { 592167612Ssimon X509V3err(X509V3_F_V2I_ASIDENTIFIERS, X509V3_R_INVALID_ASNUMBER); 593167612Ssimon X509V3_conf_err(val); 594167612Ssimon goto err; 595167612Ssimon } 596167612Ssimon i2++; 597167612Ssimon i2 = i2 + strspn(val->value + i2, " \t"); 598167612Ssimon i3 = i2 + strspn(val->value + i2, "0123456789"); 599167612Ssimon if (val->value[i3] != '\0') { 600167612Ssimon X509V3err(X509V3_F_V2I_ASIDENTIFIERS, X509V3_R_INVALID_ASRANGE); 601167612Ssimon X509V3_conf_err(val); 602167612Ssimon goto err; 603167612Ssimon } 604167612Ssimon } 605167612Ssimon 606167612Ssimon /* 607167612Ssimon * Syntax is ok, read and add it. 608167612Ssimon */ 609167612Ssimon if (!is_range) { 610167612Ssimon if (!X509V3_get_value_int(val, &min)) { 611167612Ssimon X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE); 612167612Ssimon goto err; 613167612Ssimon } 614167612Ssimon } else { 615167612Ssimon char *s = BUF_strdup(val->value); 616167612Ssimon if (s == NULL) { 617167612Ssimon X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE); 618167612Ssimon goto err; 619167612Ssimon } 620167612Ssimon s[i1] = '\0'; 621167612Ssimon min = s2i_ASN1_INTEGER(NULL, s); 622167612Ssimon max = s2i_ASN1_INTEGER(NULL, s + i2); 623167612Ssimon OPENSSL_free(s); 624167612Ssimon if (min == NULL || max == NULL) { 625167612Ssimon X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE); 626167612Ssimon goto err; 627167612Ssimon } 628237657Sjkim if (ASN1_INTEGER_cmp(min, max) > 0) { 629237657Sjkim X509V3err(X509V3_F_V2I_ASIDENTIFIERS, X509V3_R_EXTENSION_VALUE_ERROR); 630237657Sjkim goto err; 631237657Sjkim } 632167612Ssimon } 633167612Ssimon if (!v3_asid_add_id_or_range(asid, which, min, max)) { 634167612Ssimon X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE); 635167612Ssimon goto err; 636167612Ssimon } 637237657Sjkim min = max = NULL; 638167612Ssimon } 639167612Ssimon 640167612Ssimon /* 641167612Ssimon * Canonize the result, then we're done. 642167612Ssimon */ 643167612Ssimon if (!v3_asid_canonize(asid)) 644167612Ssimon goto err; 645167612Ssimon return asid; 646167612Ssimon 647167612Ssimon err: 648167612Ssimon ASIdentifiers_free(asid); 649237657Sjkim ASN1_INTEGER_free(min); 650237657Sjkim ASN1_INTEGER_free(max); 651167612Ssimon return NULL; 652167612Ssimon} 653167612Ssimon 654167612Ssimon/* 655167612Ssimon * OpenSSL dispatch. 656167612Ssimon */ 657167612Ssimonconst X509V3_EXT_METHOD v3_asid = { 658167612Ssimon NID_sbgp_autonomousSysNum, /* nid */ 659167612Ssimon 0, /* flags */ 660167612Ssimon ASN1_ITEM_ref(ASIdentifiers), /* template */ 661167612Ssimon 0, 0, 0, 0, /* old functions, ignored */ 662167612Ssimon 0, /* i2s */ 663167612Ssimon 0, /* s2i */ 664167612Ssimon 0, /* i2v */ 665167612Ssimon v2i_ASIdentifiers, /* v2i */ 666167612Ssimon i2r_ASIdentifiers, /* i2r */ 667167612Ssimon 0, /* r2i */ 668167612Ssimon NULL /* extension-specific data */ 669167612Ssimon}; 670167612Ssimon 671167612Ssimon/* 672167612Ssimon * Figure out whether extension uses inheritance. 673167612Ssimon */ 674167612Ssimonint v3_asid_inherits(ASIdentifiers *asid) 675167612Ssimon{ 676167612Ssimon return (asid != NULL && 677167612Ssimon ((asid->asnum != NULL && 678167612Ssimon asid->asnum->type == ASIdentifierChoice_inherit) || 679167612Ssimon (asid->rdi != NULL && 680167612Ssimon asid->rdi->type == ASIdentifierChoice_inherit))); 681167612Ssimon} 682167612Ssimon 683167612Ssimon/* 684167612Ssimon * Figure out whether parent contains child. 685167612Ssimon */ 686167612Ssimonstatic int asid_contains(ASIdOrRanges *parent, ASIdOrRanges *child) 687167612Ssimon{ 688167612Ssimon ASN1_INTEGER *p_min, *p_max, *c_min, *c_max; 689167612Ssimon int p, c; 690167612Ssimon 691167612Ssimon if (child == NULL || parent == child) 692167612Ssimon return 1; 693167612Ssimon if (parent == NULL) 694167612Ssimon return 0; 695167612Ssimon 696167612Ssimon p = 0; 697167612Ssimon for (c = 0; c < sk_ASIdOrRange_num(child); c++) { 698167612Ssimon extract_min_max(sk_ASIdOrRange_value(child, c), &c_min, &c_max); 699167612Ssimon for (;; p++) { 700167612Ssimon if (p >= sk_ASIdOrRange_num(parent)) 701167612Ssimon return 0; 702167612Ssimon extract_min_max(sk_ASIdOrRange_value(parent, p), &p_min, &p_max); 703167612Ssimon if (ASN1_INTEGER_cmp(p_max, c_max) < 0) 704167612Ssimon continue; 705167612Ssimon if (ASN1_INTEGER_cmp(p_min, c_min) > 0) 706167612Ssimon return 0; 707167612Ssimon break; 708167612Ssimon } 709167612Ssimon } 710167612Ssimon 711167612Ssimon return 1; 712167612Ssimon} 713167612Ssimon 714167612Ssimon/* 715167612Ssimon * Test whether a is a subet of b. 716167612Ssimon */ 717167612Ssimonint v3_asid_subset(ASIdentifiers *a, ASIdentifiers *b) 718167612Ssimon{ 719167612Ssimon return (a == NULL || 720167612Ssimon a == b || 721167612Ssimon (b != NULL && 722167612Ssimon !v3_asid_inherits(a) && 723167612Ssimon !v3_asid_inherits(b) && 724167612Ssimon asid_contains(b->asnum->u.asIdsOrRanges, 725167612Ssimon a->asnum->u.asIdsOrRanges) && 726167612Ssimon asid_contains(b->rdi->u.asIdsOrRanges, 727167612Ssimon a->rdi->u.asIdsOrRanges))); 728167612Ssimon} 729167612Ssimon 730167612Ssimon/* 731167612Ssimon * Validation error handling via callback. 732167612Ssimon */ 733167612Ssimon#define validation_err(_err_) \ 734167612Ssimon do { \ 735167612Ssimon if (ctx != NULL) { \ 736167612Ssimon ctx->error = _err_; \ 737167612Ssimon ctx->error_depth = i; \ 738167612Ssimon ctx->current_cert = x; \ 739167612Ssimon ret = ctx->verify_cb(0, ctx); \ 740167612Ssimon } else { \ 741167612Ssimon ret = 0; \ 742167612Ssimon } \ 743167612Ssimon if (!ret) \ 744167612Ssimon goto done; \ 745167612Ssimon } while (0) 746167612Ssimon 747167612Ssimon/* 748167612Ssimon * Core code for RFC 3779 3.3 path validation. 749167612Ssimon */ 750167612Ssimonstatic int v3_asid_validate_path_internal(X509_STORE_CTX *ctx, 751167612Ssimon STACK_OF(X509) *chain, 752167612Ssimon ASIdentifiers *ext) 753167612Ssimon{ 754167612Ssimon ASIdOrRanges *child_as = NULL, *child_rdi = NULL; 755167612Ssimon int i, ret = 1, inherit_as = 0, inherit_rdi = 0; 756167612Ssimon X509 *x = NULL; 757167612Ssimon 758237657Sjkim OPENSSL_assert(chain != NULL && sk_X509_num(chain) > 0); 759237657Sjkim OPENSSL_assert(ctx != NULL || ext != NULL); 760237657Sjkim OPENSSL_assert(ctx == NULL || ctx->verify_cb != NULL); 761167612Ssimon 762167612Ssimon /* 763167612Ssimon * Figure out where to start. If we don't have an extension to 764167612Ssimon * check, we're done. Otherwise, check canonical form and 765167612Ssimon * set up for walking up the chain. 766167612Ssimon */ 767167612Ssimon if (ext != NULL) { 768167612Ssimon i = -1; 769167612Ssimon } else { 770167612Ssimon i = 0; 771167612Ssimon x = sk_X509_value(chain, i); 772237657Sjkim OPENSSL_assert(x != NULL); 773167612Ssimon if ((ext = x->rfc3779_asid) == NULL) 774167612Ssimon goto done; 775167612Ssimon } 776167612Ssimon if (!v3_asid_is_canonical(ext)) 777167612Ssimon validation_err(X509_V_ERR_INVALID_EXTENSION); 778167612Ssimon if (ext->asnum != NULL) { 779167612Ssimon switch (ext->asnum->type) { 780167612Ssimon case ASIdentifierChoice_inherit: 781167612Ssimon inherit_as = 1; 782167612Ssimon break; 783167612Ssimon case ASIdentifierChoice_asIdsOrRanges: 784167612Ssimon child_as = ext->asnum->u.asIdsOrRanges; 785167612Ssimon break; 786167612Ssimon } 787167612Ssimon } 788167612Ssimon if (ext->rdi != NULL) { 789167612Ssimon switch (ext->rdi->type) { 790167612Ssimon case ASIdentifierChoice_inherit: 791167612Ssimon inherit_rdi = 1; 792167612Ssimon break; 793167612Ssimon case ASIdentifierChoice_asIdsOrRanges: 794167612Ssimon child_rdi = ext->rdi->u.asIdsOrRanges; 795167612Ssimon break; 796167612Ssimon } 797167612Ssimon } 798167612Ssimon 799167612Ssimon /* 800167612Ssimon * Now walk up the chain. Extensions must be in canonical form, no 801167612Ssimon * cert may list resources that its parent doesn't list. 802167612Ssimon */ 803167612Ssimon for (i++; i < sk_X509_num(chain); i++) { 804167612Ssimon x = sk_X509_value(chain, i); 805237657Sjkim OPENSSL_assert(x != NULL); 806167612Ssimon if (x->rfc3779_asid == NULL) { 807167612Ssimon if (child_as != NULL || child_rdi != NULL) 808167612Ssimon validation_err(X509_V_ERR_UNNESTED_RESOURCE); 809167612Ssimon continue; 810167612Ssimon } 811167612Ssimon if (!v3_asid_is_canonical(x->rfc3779_asid)) 812167612Ssimon validation_err(X509_V_ERR_INVALID_EXTENSION); 813167612Ssimon if (x->rfc3779_asid->asnum == NULL && child_as != NULL) { 814167612Ssimon validation_err(X509_V_ERR_UNNESTED_RESOURCE); 815167612Ssimon child_as = NULL; 816167612Ssimon inherit_as = 0; 817167612Ssimon } 818167612Ssimon if (x->rfc3779_asid->asnum != NULL && 819167612Ssimon x->rfc3779_asid->asnum->type == ASIdentifierChoice_asIdsOrRanges) { 820167612Ssimon if (inherit_as || 821167612Ssimon asid_contains(x->rfc3779_asid->asnum->u.asIdsOrRanges, child_as)) { 822167612Ssimon child_as = x->rfc3779_asid->asnum->u.asIdsOrRanges; 823167612Ssimon inherit_as = 0; 824167612Ssimon } else { 825167612Ssimon validation_err(X509_V_ERR_UNNESTED_RESOURCE); 826167612Ssimon } 827167612Ssimon } 828167612Ssimon if (x->rfc3779_asid->rdi == NULL && child_rdi != NULL) { 829167612Ssimon validation_err(X509_V_ERR_UNNESTED_RESOURCE); 830167612Ssimon child_rdi = NULL; 831167612Ssimon inherit_rdi = 0; 832167612Ssimon } 833167612Ssimon if (x->rfc3779_asid->rdi != NULL && 834167612Ssimon x->rfc3779_asid->rdi->type == ASIdentifierChoice_asIdsOrRanges) { 835167612Ssimon if (inherit_rdi || 836167612Ssimon asid_contains(x->rfc3779_asid->rdi->u.asIdsOrRanges, child_rdi)) { 837167612Ssimon child_rdi = x->rfc3779_asid->rdi->u.asIdsOrRanges; 838167612Ssimon inherit_rdi = 0; 839167612Ssimon } else { 840167612Ssimon validation_err(X509_V_ERR_UNNESTED_RESOURCE); 841167612Ssimon } 842167612Ssimon } 843167612Ssimon } 844167612Ssimon 845167612Ssimon /* 846167612Ssimon * Trust anchor can't inherit. 847167612Ssimon */ 848167612Ssimon if (x->rfc3779_asid != NULL) { 849167612Ssimon if (x->rfc3779_asid->asnum != NULL && 850167612Ssimon x->rfc3779_asid->asnum->type == ASIdentifierChoice_inherit) 851167612Ssimon validation_err(X509_V_ERR_UNNESTED_RESOURCE); 852167612Ssimon if (x->rfc3779_asid->rdi != NULL && 853167612Ssimon x->rfc3779_asid->rdi->type == ASIdentifierChoice_inherit) 854167612Ssimon validation_err(X509_V_ERR_UNNESTED_RESOURCE); 855167612Ssimon } 856167612Ssimon 857167612Ssimon done: 858167612Ssimon return ret; 859167612Ssimon} 860167612Ssimon 861167612Ssimon#undef validation_err 862167612Ssimon 863167612Ssimon/* 864167612Ssimon * RFC 3779 3.3 path validation -- called from X509_verify_cert(). 865167612Ssimon */ 866167612Ssimonint v3_asid_validate_path(X509_STORE_CTX *ctx) 867167612Ssimon{ 868167612Ssimon return v3_asid_validate_path_internal(ctx, ctx->chain, NULL); 869167612Ssimon} 870167612Ssimon 871167612Ssimon/* 872167612Ssimon * RFC 3779 3.3 path validation of an extension. 873167612Ssimon * Test whether chain covers extension. 874167612Ssimon */ 875167612Ssimonint v3_asid_validate_resource_set(STACK_OF(X509) *chain, 876167612Ssimon ASIdentifiers *ext, 877167612Ssimon int allow_inheritance) 878167612Ssimon{ 879167612Ssimon if (ext == NULL) 880167612Ssimon return 1; 881167612Ssimon if (chain == NULL || sk_X509_num(chain) == 0) 882167612Ssimon return 0; 883167612Ssimon if (!allow_inheritance && v3_asid_inherits(ext)) 884167612Ssimon return 0; 885167612Ssimon return v3_asid_validate_path_internal(NULL, chain, ext); 886167612Ssimon} 887167612Ssimon 888167612Ssimon#endif /* OPENSSL_NO_RFC3779 */ 889