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