1 /* $OpenBSD: x509_utl.c,v 1.5 2022/12/26 07:18:53 jmc Exp $ */ 2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3 * project. 4 */ 5 /* ==================================================================== 6 * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. All advertising materials mentioning features or use of this 21 * software must display the following acknowledgment: 22 * "This product includes software developed by the OpenSSL Project 23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24 * 25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26 * endorse or promote products derived from this software without 27 * prior written permission. For written permission, please contact 28 * licensing@OpenSSL.org. 29 * 30 * 5. Products derived from this software may not be called "OpenSSL" 31 * nor may "OpenSSL" appear in their names without prior written 32 * permission of the OpenSSL Project. 33 * 34 * 6. Redistributions of any form whatsoever must retain the following 35 * acknowledgment: 36 * "This product includes software developed by the OpenSSL Project 37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38 * 39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50 * OF THE POSSIBILITY OF SUCH DAMAGE. 51 * ==================================================================== 52 * 53 * This product includes cryptographic software written by Eric Young 54 * (eay@cryptsoft.com). This product includes software written by Tim 55 * Hudson (tjh@cryptsoft.com). 56 * 57 */ 58 /* X509 v3 extension utilities */ 59 60 #include <ctype.h> 61 #include <stdio.h> 62 #include <string.h> 63 64 #include <openssl/bn.h> 65 #include <openssl/conf.h> 66 #include <openssl/err.h> 67 #include <openssl/x509v3.h> 68 69 char *bn_to_string(const BIGNUM *bn); 70 static char *strip_spaces(char *name); 71 static int sk_strcmp(const char * const *a, const char * const *b); 72 static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, 73 GENERAL_NAMES *gens); 74 static void str_free(OPENSSL_STRING str); 75 static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email); 76 77 static int ipv4_from_asc(unsigned char *v4, const char *in); 78 static int ipv6_from_asc(unsigned char *v6, const char *in); 79 static int ipv6_cb(const char *elem, int len, void *usr); 80 static int ipv6_hex(unsigned char *out, const char *in, int inlen); 81 82 /* Add a CONF_VALUE name-value pair to stack. */ 83 int 84 X509V3_add_value(const char *name, const char *value, 85 STACK_OF(CONF_VALUE) **extlist) 86 { 87 CONF_VALUE *vtmp = NULL; 88 STACK_OF(CONF_VALUE) *free_exts = NULL; 89 90 if ((vtmp = calloc(1, sizeof(CONF_VALUE))) == NULL) 91 goto err; 92 if (name != NULL) { 93 if ((vtmp->name = strdup(name)) == NULL) 94 goto err; 95 } 96 if (value != NULL) { 97 if ((vtmp->value = strdup(value)) == NULL) 98 goto err; 99 } 100 101 if (*extlist == NULL) { 102 if ((free_exts = *extlist = sk_CONF_VALUE_new_null()) == NULL) 103 goto err; 104 } 105 106 if (!sk_CONF_VALUE_push(*extlist, vtmp)) 107 goto err; 108 109 return 1; 110 111 err: 112 X509V3error(ERR_R_MALLOC_FAILURE); 113 X509V3_conf_free(vtmp); 114 if (free_exts != NULL) { 115 sk_CONF_VALUE_free(*extlist); 116 *extlist = NULL; 117 } 118 return 0; 119 } 120 LCRYPTO_ALIAS(X509V3_add_value) 121 122 int 123 X509V3_add_value_uchar(const char *name, const unsigned char *value, 124 STACK_OF(CONF_VALUE) **extlist) 125 { 126 return X509V3_add_value(name, (const char *)value, extlist); 127 } 128 LCRYPTO_ALIAS(X509V3_add_value_uchar) 129 130 /* Free function for STACK_OF(CONF_VALUE) */ 131 132 void 133 X509V3_conf_free(CONF_VALUE *conf) 134 { 135 if (!conf) 136 return; 137 free(conf->name); 138 free(conf->value); 139 free(conf->section); 140 free(conf); 141 } 142 LCRYPTO_ALIAS(X509V3_conf_free) 143 144 int 145 X509V3_add_value_bool(const char *name, int asn1_bool, 146 STACK_OF(CONF_VALUE) **extlist) 147 { 148 if (asn1_bool) 149 return X509V3_add_value(name, "TRUE", extlist); 150 return X509V3_add_value(name, "FALSE", extlist); 151 } 152 LCRYPTO_ALIAS(X509V3_add_value_bool) 153 154 int 155 X509V3_add_value_bool_nf(const char *name, int asn1_bool, 156 STACK_OF(CONF_VALUE) **extlist) 157 { 158 if (asn1_bool) 159 return X509V3_add_value(name, "TRUE", extlist); 160 return 1; 161 } 162 LCRYPTO_ALIAS(X509V3_add_value_bool_nf) 163 164 char * 165 bn_to_string(const BIGNUM *bn) 166 { 167 const char *sign = ""; 168 char *bnstr, *hex; 169 char *ret = NULL; 170 171 /* Only display small numbers in decimal, as conversion is quadratic. */ 172 if (BN_num_bits(bn) < 128) 173 return BN_bn2dec(bn); 174 175 if ((hex = bnstr = BN_bn2hex(bn)) == NULL) 176 goto err; 177 178 if (BN_is_negative(bn)) { 179 sign = "-"; 180 hex++; 181 } 182 183 if (asprintf(&ret, "%s0x%s", sign, hex) == -1) 184 ret = NULL; 185 186 err: 187 free(bnstr); 188 return ret; 189 } 190 191 char * 192 i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, const ASN1_ENUMERATED *a) 193 { 194 BIGNUM *bntmp; 195 char *strtmp = NULL; 196 197 if (a == NULL) 198 return NULL; 199 if ((bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) == NULL || 200 (strtmp = bn_to_string(bntmp)) == NULL) 201 X509V3error(ERR_R_MALLOC_FAILURE); 202 BN_free(bntmp); 203 return strtmp; 204 } 205 LCRYPTO_ALIAS(i2s_ASN1_ENUMERATED) 206 207 char * 208 i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, const ASN1_INTEGER *a) 209 { 210 BIGNUM *bntmp; 211 char *strtmp = NULL; 212 213 if (a == NULL) 214 return NULL; 215 if ((bntmp = ASN1_INTEGER_to_BN(a, NULL)) == NULL || 216 (strtmp = bn_to_string(bntmp)) == NULL) 217 X509V3error(ERR_R_MALLOC_FAILURE); 218 BN_free(bntmp); 219 return strtmp; 220 } 221 LCRYPTO_ALIAS(i2s_ASN1_INTEGER) 222 223 ASN1_INTEGER * 224 s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, const char *value) 225 { 226 BIGNUM *bn = NULL; 227 ASN1_INTEGER *aint; 228 int isneg, ishex; 229 int ret; 230 231 if (!value) { 232 X509V3error(X509V3_R_INVALID_NULL_VALUE); 233 return 0; 234 } 235 bn = BN_new(); 236 if (value[0] == '-') { 237 value++; 238 isneg = 1; 239 } else 240 isneg = 0; 241 242 if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) { 243 value += 2; 244 ishex = 1; 245 } else 246 ishex = 0; 247 248 if (ishex) 249 ret = BN_hex2bn(&bn, value); 250 else 251 ret = BN_dec2bn(&bn, value); 252 253 if (!ret || value[ret]) { 254 BN_free(bn); 255 X509V3error(X509V3_R_BN_DEC2BN_ERROR); 256 return 0; 257 } 258 259 if (isneg && BN_is_zero(bn)) 260 isneg = 0; 261 262 aint = BN_to_ASN1_INTEGER(bn, NULL); 263 BN_free(bn); 264 if (!aint) { 265 X509V3error(X509V3_R_BN_TO_ASN1_INTEGER_ERROR); 266 return 0; 267 } 268 if (isneg) 269 aint->type |= V_ASN1_NEG; 270 return aint; 271 } 272 LCRYPTO_ALIAS(s2i_ASN1_INTEGER) 273 274 int 275 X509V3_add_value_int(const char *name, const ASN1_INTEGER *aint, 276 STACK_OF(CONF_VALUE) **extlist) 277 { 278 char *strtmp; 279 int ret; 280 281 if (!aint) 282 return 1; 283 if (!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) 284 return 0; 285 ret = X509V3_add_value(name, strtmp, extlist); 286 free(strtmp); 287 return ret; 288 } 289 LCRYPTO_ALIAS(X509V3_add_value_int) 290 291 int 292 X509V3_get_value_bool(const CONF_VALUE *value, int *asn1_bool) 293 { 294 char *btmp; 295 296 if (!(btmp = value->value)) 297 goto err; 298 if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true") || 299 !strcmp(btmp, "Y") || !strcmp(btmp, "y") || 300 !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) { 301 *asn1_bool = 0xff; 302 return 1; 303 } else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false") || 304 !strcmp(btmp, "N") || !strcmp(btmp, "n") || 305 !strcmp(btmp, "NO") || !strcmp(btmp, "no")) { 306 *asn1_bool = 0; 307 return 1; 308 } 309 310 err: 311 X509V3error(X509V3_R_INVALID_BOOLEAN_STRING); 312 X509V3_conf_err(value); 313 return 0; 314 } 315 LCRYPTO_ALIAS(X509V3_get_value_bool) 316 317 int 318 X509V3_get_value_int(const CONF_VALUE *value, ASN1_INTEGER **aint) 319 { 320 ASN1_INTEGER *itmp; 321 322 if (!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) { 323 X509V3_conf_err(value); 324 return 0; 325 } 326 *aint = itmp; 327 return 1; 328 } 329 LCRYPTO_ALIAS(X509V3_get_value_int) 330 331 #define HDR_NAME 1 332 #define HDR_VALUE 2 333 334 /*#define DEBUG*/ 335 336 STACK_OF(CONF_VALUE) * 337 X509V3_parse_list(const char *line) 338 { 339 char *p, *q, c; 340 char *ntmp, *vtmp; 341 STACK_OF(CONF_VALUE) *values = NULL; 342 char *linebuf; 343 int state; 344 345 /* We are going to modify the line so copy it first */ 346 if ((linebuf = strdup(line)) == NULL) { 347 X509V3error(ERR_R_MALLOC_FAILURE); 348 goto err; 349 } 350 state = HDR_NAME; 351 ntmp = NULL; 352 353 /* Go through all characters */ 354 for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && 355 (c != '\n'); p++) { 356 357 switch (state) { 358 case HDR_NAME: 359 if (c == ':') { 360 state = HDR_VALUE; 361 *p = 0; 362 ntmp = strip_spaces(q); 363 if (!ntmp) { 364 X509V3error(X509V3_R_INVALID_NULL_NAME); 365 goto err; 366 } 367 q = p + 1; 368 } else if (c == ',') { 369 *p = 0; 370 ntmp = strip_spaces(q); 371 q = p + 1; 372 if (!ntmp) { 373 X509V3error(X509V3_R_INVALID_NULL_NAME); 374 goto err; 375 } 376 X509V3_add_value(ntmp, NULL, &values); 377 } 378 break; 379 380 case HDR_VALUE: 381 if (c == ',') { 382 state = HDR_NAME; 383 *p = 0; 384 vtmp = strip_spaces(q); 385 if (!vtmp) { 386 X509V3error(X509V3_R_INVALID_NULL_VALUE); 387 goto err; 388 } 389 X509V3_add_value(ntmp, vtmp, &values); 390 ntmp = NULL; 391 q = p + 1; 392 } 393 394 } 395 } 396 397 if (state == HDR_VALUE) { 398 vtmp = strip_spaces(q); 399 if (!vtmp) { 400 X509V3error(X509V3_R_INVALID_NULL_VALUE); 401 goto err; 402 } 403 X509V3_add_value(ntmp, vtmp, &values); 404 } else { 405 ntmp = strip_spaces(q); 406 if (!ntmp) { 407 X509V3error(X509V3_R_INVALID_NULL_NAME); 408 goto err; 409 } 410 X509V3_add_value(ntmp, NULL, &values); 411 } 412 free(linebuf); 413 return values; 414 415 err: 416 free(linebuf); 417 sk_CONF_VALUE_pop_free(values, X509V3_conf_free); 418 return NULL; 419 420 } 421 LCRYPTO_ALIAS(X509V3_parse_list) 422 423 /* Delete leading and trailing spaces from a string */ 424 static char * 425 strip_spaces(char *name) 426 { 427 char *p, *q; 428 429 /* Skip over leading spaces */ 430 p = name; 431 while (*p && isspace((unsigned char)*p)) 432 p++; 433 if (!*p) 434 return NULL; 435 q = p + strlen(p) - 1; 436 while ((q != p) && isspace((unsigned char)*q)) 437 q--; 438 if (p != q) 439 q[1] = 0; 440 if (!*p) 441 return NULL; 442 return p; 443 } 444 445 /* hex string utilities */ 446 447 /* Given a buffer of length 'len' return a malloc'ed string with its 448 * hex representation 449 */ 450 char * 451 hex_to_string(const unsigned char *buffer, long len) 452 { 453 char *tmp, *q; 454 const unsigned char *p; 455 int i; 456 static const char hexdig[] = "0123456789ABCDEF"; 457 458 if (!buffer || !len) 459 return NULL; 460 if (!(tmp = malloc(len * 3 + 1))) { 461 X509V3error(ERR_R_MALLOC_FAILURE); 462 return NULL; 463 } 464 q = tmp; 465 for (i = 0, p = buffer; i < len; i++, p++) { 466 *q++ = hexdig[(*p >> 4) & 0xf]; 467 *q++ = hexdig[*p & 0xf]; 468 *q++ = ':'; 469 } 470 q[-1] = 0; 471 return tmp; 472 } 473 LCRYPTO_ALIAS(hex_to_string) 474 475 /* Give a string of hex digits convert to 476 * a buffer 477 */ 478 479 unsigned char * 480 string_to_hex(const char *str, long *len) 481 { 482 unsigned char *hexbuf, *q; 483 unsigned char ch, cl, *p; 484 if (!str) { 485 X509V3error(X509V3_R_INVALID_NULL_ARGUMENT); 486 return NULL; 487 } 488 if (!(hexbuf = malloc(strlen(str) >> 1))) 489 goto err; 490 for (p = (unsigned char *)str, q = hexbuf; *p; ) { 491 ch = *p++; 492 if (ch == ':') 493 continue; 494 cl = *p++; 495 if (!cl) { 496 X509V3error(X509V3_R_ODD_NUMBER_OF_DIGITS); 497 free(hexbuf); 498 return NULL; 499 } 500 ch = tolower(ch); 501 cl = tolower(cl); 502 503 if ((ch >= '0') && (ch <= '9')) 504 ch -= '0'; 505 else if ((ch >= 'a') && (ch <= 'f')) 506 ch -= 'a' - 10; 507 else 508 goto badhex; 509 510 if ((cl >= '0') && (cl <= '9')) 511 cl -= '0'; 512 else if ((cl >= 'a') && (cl <= 'f')) 513 cl -= 'a' - 10; 514 else 515 goto badhex; 516 517 *q++ = (ch << 4) | cl; 518 } 519 520 if (len) 521 *len = q - hexbuf; 522 523 return hexbuf; 524 525 err: 526 free(hexbuf); 527 X509V3error(ERR_R_MALLOC_FAILURE); 528 return NULL; 529 530 badhex: 531 free(hexbuf); 532 X509V3error(X509V3_R_ILLEGAL_HEX_DIGIT); 533 return NULL; 534 } 535 LCRYPTO_ALIAS(string_to_hex) 536 537 /* V2I name comparison function: returns zero if 'name' matches 538 * cmp or cmp.* 539 */ 540 541 int 542 name_cmp(const char *name, const char *cmp) 543 { 544 int len, ret; 545 char c; 546 547 len = strlen(cmp); 548 if ((ret = strncmp(name, cmp, len))) 549 return ret; 550 c = name[len]; 551 if (!c || (c=='.')) 552 return 0; 553 return 1; 554 } 555 556 static int 557 sk_strcmp(const char * const *a, const char * const *b) 558 { 559 return strcmp(*a, *b); 560 } 561 562 STACK_OF(OPENSSL_STRING) * 563 X509_get1_email(X509 *x) 564 { 565 GENERAL_NAMES *gens; 566 STACK_OF(OPENSSL_STRING) *ret; 567 568 gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); 569 ret = get_email(X509_get_subject_name(x), gens); 570 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 571 return ret; 572 } 573 LCRYPTO_ALIAS(X509_get1_email) 574 575 STACK_OF(OPENSSL_STRING) * 576 X509_get1_ocsp(X509 *x) 577 { 578 AUTHORITY_INFO_ACCESS *info; 579 STACK_OF(OPENSSL_STRING) *ret = NULL; 580 int i; 581 582 info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL); 583 if (!info) 584 return NULL; 585 for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) { 586 ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i); 587 if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) { 588 if (ad->location->type == GEN_URI) { 589 if (!append_ia5(&ret, 590 ad->location->d.uniformResourceIdentifier)) 591 break; 592 } 593 } 594 } 595 AUTHORITY_INFO_ACCESS_free(info); 596 return ret; 597 } 598 LCRYPTO_ALIAS(X509_get1_ocsp) 599 600 STACK_OF(OPENSSL_STRING) * 601 X509_REQ_get1_email(X509_REQ *x) 602 { 603 GENERAL_NAMES *gens; 604 STACK_OF(X509_EXTENSION) *exts; 605 STACK_OF(OPENSSL_STRING) *ret; 606 607 exts = X509_REQ_get_extensions(x); 608 gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL); 609 ret = get_email(X509_REQ_get_subject_name(x), gens); 610 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 611 sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); 612 return ret; 613 } 614 LCRYPTO_ALIAS(X509_REQ_get1_email) 615 616 617 static STACK_OF(OPENSSL_STRING) * 618 get_email(X509_NAME *name, GENERAL_NAMES *gens) 619 { 620 STACK_OF(OPENSSL_STRING) *ret = NULL; 621 X509_NAME_ENTRY *ne; 622 ASN1_IA5STRING *email; 623 GENERAL_NAME *gen; 624 int i; 625 626 /* Now add any email address(es) to STACK */ 627 i = -1; 628 629 /* First supplied X509_NAME */ 630 while ((i = X509_NAME_get_index_by_NID(name, 631 NID_pkcs9_emailAddress, i)) >= 0) { 632 ne = X509_NAME_get_entry(name, i); 633 email = X509_NAME_ENTRY_get_data(ne); 634 if (!append_ia5(&ret, email)) 635 return NULL; 636 } 637 for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { 638 gen = sk_GENERAL_NAME_value(gens, i); 639 if (gen->type != GEN_EMAIL) 640 continue; 641 if (!append_ia5(&ret, gen->d.ia5)) 642 return NULL; 643 } 644 return ret; 645 } 646 647 static void 648 str_free(OPENSSL_STRING str) 649 { 650 free(str); 651 } 652 653 static int 654 append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email) 655 { 656 char *emtmp; 657 658 /* First some sanity checks */ 659 if (email->type != V_ASN1_IA5STRING) 660 return 1; 661 if (!email->data || !email->length) 662 return 1; 663 if (!*sk) 664 *sk = sk_OPENSSL_STRING_new(sk_strcmp); 665 if (!*sk) 666 return 0; 667 /* Don't add duplicates */ 668 if (sk_OPENSSL_STRING_find(*sk, (char *)email->data) != -1) 669 return 1; 670 emtmp = strdup((char *)email->data); 671 if (!emtmp || !sk_OPENSSL_STRING_push(*sk, emtmp)) { 672 X509_email_free(*sk); 673 *sk = NULL; 674 return 0; 675 } 676 return 1; 677 } 678 679 void 680 X509_email_free(STACK_OF(OPENSSL_STRING) *sk) 681 { 682 sk_OPENSSL_STRING_pop_free(sk, str_free); 683 } 684 LCRYPTO_ALIAS(X509_email_free) 685 686 typedef int (*equal_fn)(const unsigned char *pattern, size_t pattern_len, 687 const unsigned char *subject, size_t subject_len, unsigned int flags); 688 689 /* Skip pattern prefix to match "wildcard" subject */ 690 static void 691 skip_prefix(const unsigned char **p, size_t *plen, const unsigned char *subject, 692 size_t subject_len, unsigned int flags) 693 { 694 const unsigned char *pattern = *p; 695 size_t pattern_len = *plen; 696 697 /* 698 * If subject starts with a leading '.' followed by more octets, and 699 * pattern is longer, compare just an equal-length suffix with the 700 * full subject (starting at the '.'), provided the prefix contains 701 * no NULs. 702 */ 703 if ((flags & _X509_CHECK_FLAG_DOT_SUBDOMAINS) == 0) 704 return; 705 706 while (pattern_len > subject_len && *pattern) { 707 if ((flags & X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS) && 708 *pattern == '.') 709 break; 710 ++pattern; 711 --pattern_len; 712 } 713 714 /* Skip if entire prefix acceptable */ 715 if (pattern_len == subject_len) { 716 *p = pattern; 717 *plen = pattern_len; 718 } 719 } 720 721 /* 722 * Open/BoringSSL uses memcmp for "equal_case" while their 723 * "equal_nocase" function is a hand-rolled strncasecmp that does not 724 * allow \0 in the pattern. Since an embedded \0 is likely a sign of 725 * problems, we simply don't allow it in either case, and then we use 726 * standard libc functions. 727 */ 728 729 /* Compare using strncasecmp */ 730 static int 731 equal_nocase(const unsigned char *pattern, size_t pattern_len, 732 const unsigned char *subject, size_t subject_len, unsigned int flags) 733 { 734 if (memchr(pattern, '\0', pattern_len) != NULL) 735 return 0; 736 if (memchr(subject, '\0', subject_len) != NULL) 737 return 0; 738 skip_prefix(&pattern, &pattern_len, subject, subject_len, flags); 739 if (pattern_len != subject_len) 740 return 0; 741 return (strncasecmp(pattern, subject, pattern_len) == 0); 742 } 743 744 /* Compare using strncmp. */ 745 static int 746 equal_case(const unsigned char *pattern, size_t pattern_len, 747 const unsigned char *subject, size_t subject_len, unsigned int flags) 748 { 749 if (memchr(pattern, 0, pattern_len) != NULL) 750 return 0; 751 if (memchr(subject, 0, subject_len) != NULL) 752 return 0; 753 skip_prefix(&pattern, &pattern_len, subject, subject_len, flags); 754 if (pattern_len != subject_len) 755 return 0; 756 return (strncmp(pattern, subject, pattern_len) == 0); 757 } 758 759 /* 760 * RFC 5280, section 7.5, requires that only the domain is compared in a 761 * case-insensitive manner. 762 */ 763 static int 764 equal_email(const unsigned char *a, size_t a_len, const unsigned char *b, 765 size_t b_len, unsigned int unused_flags) 766 { 767 size_t pos = a_len; 768 if (a_len != b_len) 769 return 0; 770 /* 771 * We search backwards for the '@' character, so that we do not have to 772 * deal with quoted local-parts. The domain part is compared in a 773 * case-insensitive manner. 774 */ 775 while (pos > 0) { 776 pos--; 777 if (a[pos] == '@' || b[pos] == '@') { 778 if (!equal_nocase(a + pos, a_len - pos, b + pos, 779 a_len - pos, 0)) 780 return 0; 781 break; 782 } 783 } 784 if (pos == 0) 785 pos = a_len; 786 return equal_case(a, pos, b, pos, 0); 787 } 788 789 /* 790 * Compare the prefix and suffix with the subject, and check that the 791 * characters in-between are valid. 792 */ 793 static int 794 wildcard_match(const unsigned char *prefix, size_t prefix_len, 795 const unsigned char *suffix, size_t suffix_len, 796 const unsigned char *subject, size_t subject_len, unsigned int flags) 797 { 798 const unsigned char *wildcard_start; 799 const unsigned char *wildcard_end; 800 const unsigned char *p; 801 int allow_multi = 0; 802 int allow_idna = 0; 803 804 if (subject_len < prefix_len + suffix_len) 805 return 0; 806 if (!equal_nocase(prefix, prefix_len, subject, prefix_len, flags)) 807 return 0; 808 wildcard_start = subject + prefix_len; 809 wildcard_end = subject + (subject_len - suffix_len); 810 if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len, flags)) 811 return 0; 812 /* 813 * If the wildcard makes up the entire first label, it must match at 814 * least one character. 815 */ 816 if (prefix_len == 0 && *suffix == '.') { 817 if (wildcard_start == wildcard_end) 818 return 0; 819 allow_idna = 1; 820 if (flags & X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS) 821 allow_multi = 1; 822 } 823 /* IDNA labels cannot match partial wildcards */ 824 if (!allow_idna && 825 subject_len >= 4 826 && strncasecmp((char *)subject, "xn--", 4) == 0) 827 return 0; 828 /* The wildcard may match a literal '*' */ 829 if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*') 830 return 1; 831 /* 832 * Check that the part matched by the wildcard contains only 833 * permitted characters and only matches a single label unless 834 * allow_multi is set. 835 */ 836 for (p = wildcard_start; p != wildcard_end; ++p) 837 if (!(('0' <= *p && *p <= '9') || ('A' <= *p && *p <= 'Z') || 838 ('a' <= *p && *p <= 'z') || *p == '-' || 839 (allow_multi && *p == '.'))) 840 return 0; 841 return 1; 842 } 843 844 #define LABEL_START (1 << 0) 845 #define LABEL_END (1 << 1) 846 #define LABEL_HYPHEN (1 << 2) 847 #define LABEL_IDNA (1 << 3) 848 849 static const unsigned char * 850 valid_star(const unsigned char *p, size_t len, unsigned int flags) 851 { 852 const unsigned char *star = 0; 853 size_t i; 854 int state = LABEL_START; 855 int dots = 0; 856 for (i = 0; i < len; ++i) { 857 /* 858 * Locate first and only legal wildcard, either at the start 859 * or end of a non-IDNA first and not final label. 860 */ 861 if (p[i] == '*') { 862 int atstart = (state & LABEL_START); 863 int atend = (i == len - 1 || p[i + 1] == '.'); 864 /* 865 * At most one wildcard per pattern. 866 * No wildcards in IDNA labels. 867 * No wildcards after the first label. 868 */ 869 if (star != NULL || (state & LABEL_IDNA) != 0 || dots) 870 return NULL; 871 /* Only full-label '*.example.com' wildcards? */ 872 if ((flags & X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS) 873 && (!atstart || !atend)) 874 return NULL; 875 /* No 'foo*bar' wildcards */ 876 if (!atstart && !atend) 877 return NULL; 878 star = &p[i]; 879 state &= ~LABEL_START; 880 } else if ((state & LABEL_START) != 0) { 881 /* 882 * At the start of a label, skip any "xn--" and 883 * remain in the LABEL_START state, but set the 884 * IDNA label state 885 */ 886 if ((state & LABEL_IDNA) == 0 && len - i >= 4 887 && strncasecmp((char *)&p[i], "xn--", 4) == 0) { 888 i += 3; 889 state |= LABEL_IDNA; 890 continue; 891 } 892 /* Labels must start with a letter or digit */ 893 state &= ~LABEL_START; 894 if (('a' <= p[i] && p[i] <= 'z') 895 || ('A' <= p[i] && p[i] <= 'Z') 896 || ('0' <= p[i] && p[i] <= '9')) 897 continue; 898 return NULL; 899 } else if (('a' <= p[i] && p[i] <= 'z') 900 || ('A' <= p[i] && p[i] <= 'Z') 901 || ('0' <= p[i] && p[i] <= '9')) { 902 state &= LABEL_IDNA; 903 continue; 904 } else if (p[i] == '.') { 905 if (state & (LABEL_HYPHEN | LABEL_START)) 906 return NULL; 907 state = LABEL_START; 908 ++dots; 909 } else if (p[i] == '-') { 910 /* no domain/subdomain starts with '-' */ 911 if ((state & LABEL_START) != 0) 912 return NULL; 913 state |= LABEL_HYPHEN; 914 } else 915 return NULL; 916 } 917 918 /* 919 * The final label must not end in a hyphen or ".", and 920 * there must be at least two dots after the star. 921 */ 922 if ((state & (LABEL_START | LABEL_HYPHEN)) != 0 || dots < 2) 923 return NULL; 924 return star; 925 } 926 927 /* Compare using wildcards. */ 928 static int 929 equal_wildcard(const unsigned char *pattern, size_t pattern_len, 930 const unsigned char *subject, size_t subject_len, unsigned int flags) 931 { 932 const unsigned char *star = NULL; 933 934 /* 935 * Subject names starting with '.' can only match a wildcard pattern 936 * via a subject sub-domain pattern suffix match. 937 */ 938 if (!(subject_len > 1 && subject[0] == '.')) 939 star = valid_star(pattern, pattern_len, flags); 940 if (star == NULL) 941 return equal_nocase(pattern, pattern_len, 942 subject, subject_len, flags); 943 return wildcard_match(pattern, star - pattern, 944 star + 1, (pattern + pattern_len) - star - 1, 945 subject, subject_len, flags); 946 } 947 948 /* 949 * Compare an ASN1_STRING to a supplied string. If they match return 1. If 950 * cmp_type > 0 only compare if string matches the type, otherwise convert it 951 * to UTF8. 952 */ 953 954 static int 955 do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal, 956 unsigned int flags, const char *b, size_t blen, char **peername) 957 { 958 int rv = 0; 959 960 if (!a->data || !a->length) 961 return 0; 962 if (cmp_type > 0) { 963 if (cmp_type != a->type) 964 return 0; 965 if (cmp_type == V_ASN1_IA5STRING) 966 rv = equal(a->data, a->length, (unsigned char *)b, 967 blen, flags); 968 else if (a->length == (int)blen && !memcmp(a->data, b, blen)) 969 rv = 1; 970 if (rv > 0 && peername && 971 (*peername = strndup((char *)a->data, a->length)) == NULL) 972 rv = -1; 973 } else { 974 int astrlen; 975 unsigned char *astr = NULL; 976 astrlen = ASN1_STRING_to_UTF8(&astr, a); 977 if (astrlen < 0) 978 return -1; 979 rv = equal(astr, astrlen, (unsigned char *)b, blen, flags); 980 if (rv > 0 && peername && 981 (*peername = strndup((char *)astr, astrlen)) == NULL) 982 rv = -1; 983 free(astr); 984 } 985 return rv; 986 } 987 988 static int 989 do_x509_check(X509 *x, const char *chk, size_t chklen, unsigned int flags, 990 int check_type, char **peername) 991 { 992 GENERAL_NAMES *gens = NULL; 993 X509_NAME *name = NULL; 994 size_t i; 995 int j; 996 int cnid = NID_undef; 997 int alt_type; 998 int san_present = 0; 999 int rv = 0; 1000 equal_fn equal; 1001 1002 /* See below, this flag is internal-only */ 1003 flags &= ~_X509_CHECK_FLAG_DOT_SUBDOMAINS; 1004 if (check_type == GEN_EMAIL) { 1005 cnid = NID_pkcs9_emailAddress; 1006 alt_type = V_ASN1_IA5STRING; 1007 equal = equal_email; 1008 } else if (check_type == GEN_DNS) { 1009 if (!(flags & X509_CHECK_FLAG_NEVER_CHECK_SUBJECT)) 1010 cnid = NID_commonName; 1011 /* Implicit client-side DNS sub-domain pattern */ 1012 if (chklen > 1 && chk[0] == '.') 1013 flags |= _X509_CHECK_FLAG_DOT_SUBDOMAINS; 1014 alt_type = V_ASN1_IA5STRING; 1015 if (flags & X509_CHECK_FLAG_NO_WILDCARDS) 1016 equal = equal_nocase; 1017 else 1018 equal = equal_wildcard; 1019 } else { 1020 alt_type = V_ASN1_OCTET_STRING; 1021 equal = equal_case; 1022 } 1023 1024 gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); 1025 if (gens != NULL) { 1026 for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { 1027 GENERAL_NAME *gen; 1028 ASN1_STRING *cstr; 1029 gen = sk_GENERAL_NAME_value(gens, i); 1030 if (gen->type != check_type) 1031 continue; 1032 san_present = 1; 1033 if (check_type == GEN_EMAIL) 1034 cstr = gen->d.rfc822Name; 1035 else if (check_type == GEN_DNS) 1036 cstr = gen->d.dNSName; 1037 else 1038 cstr = gen->d.iPAddress; 1039 /* Positive on success, negative on error! */ 1040 if ((rv = do_check_string(cstr, alt_type, equal, flags, 1041 chk, chklen, peername)) != 0) 1042 break; 1043 } 1044 GENERAL_NAMES_free(gens); 1045 if (rv != 0) 1046 return rv; 1047 if (cnid == NID_undef || 1048 (san_present && 1049 !(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT))) 1050 return 0; 1051 } 1052 1053 /* We're done if CN-ID is not pertinent */ 1054 if (cnid == NID_undef) 1055 return 0; 1056 1057 j = -1; 1058 name = X509_get_subject_name(x); 1059 while ((j = X509_NAME_get_index_by_NID(name, cnid, j)) >= 0) { 1060 X509_NAME_ENTRY *ne; 1061 ASN1_STRING *str; 1062 if ((ne = X509_NAME_get_entry(name, j)) == NULL) 1063 return -1; 1064 if ((str = X509_NAME_ENTRY_get_data(ne)) == NULL) 1065 return -1; 1066 /* Positive on success, negative on error! */ 1067 if ((rv = do_check_string(str, -1, equal, flags, 1068 chk, chklen, peername)) != 0) 1069 return rv; 1070 } 1071 return 0; 1072 } 1073 1074 int 1075 X509_check_host(X509 *x, const char *chk, size_t chklen, unsigned int flags, 1076 char **peername) 1077 { 1078 if (chk == NULL) 1079 return -2; 1080 if (chklen == 0) 1081 chklen = strlen(chk); 1082 else if (memchr(chk, '\0', chklen)) 1083 return -2; 1084 return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername); 1085 } 1086 LCRYPTO_ALIAS(X509_check_host) 1087 1088 int 1089 X509_check_email(X509 *x, const char *chk, size_t chklen, unsigned int flags) 1090 { 1091 if (chk == NULL) 1092 return -2; 1093 if (chklen == 0) 1094 chklen = strlen(chk); 1095 else if (memchr(chk, '\0', chklen)) 1096 return -2; 1097 return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL); 1098 } 1099 LCRYPTO_ALIAS(X509_check_email) 1100 1101 int 1102 X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen, 1103 unsigned int flags) 1104 { 1105 if (chk == NULL) 1106 return -2; 1107 return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL); 1108 } 1109 LCRYPTO_ALIAS(X509_check_ip) 1110 1111 int 1112 X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags) 1113 { 1114 unsigned char ipout[16]; 1115 size_t iplen; 1116 1117 if (ipasc == NULL) 1118 return -2; 1119 iplen = (size_t)a2i_ipadd(ipout, ipasc); 1120 if (iplen == 0) 1121 return -2; 1122 return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL); 1123 } 1124 LCRYPTO_ALIAS(X509_check_ip_asc) 1125 1126 /* Convert IP addresses both IPv4 and IPv6 into an 1127 * OCTET STRING compatible with RFC3280. 1128 */ 1129 1130 ASN1_OCTET_STRING * 1131 a2i_IPADDRESS(const char *ipasc) 1132 { 1133 unsigned char ipout[16]; 1134 ASN1_OCTET_STRING *ret; 1135 int iplen; 1136 1137 /* If string contains a ':' assume IPv6 */ 1138 1139 iplen = a2i_ipadd(ipout, ipasc); 1140 1141 if (!iplen) 1142 return NULL; 1143 1144 ret = ASN1_OCTET_STRING_new(); 1145 if (!ret) 1146 return NULL; 1147 if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) { 1148 ASN1_OCTET_STRING_free(ret); 1149 return NULL; 1150 } 1151 return ret; 1152 } 1153 LCRYPTO_ALIAS(a2i_IPADDRESS) 1154 1155 ASN1_OCTET_STRING * 1156 a2i_IPADDRESS_NC(const char *ipasc) 1157 { 1158 ASN1_OCTET_STRING *ret = NULL; 1159 unsigned char ipout[32]; 1160 char *iptmp = NULL, *p; 1161 int iplen1, iplen2; 1162 1163 p = strchr(ipasc, '/'); 1164 if (!p) 1165 return NULL; 1166 iptmp = strdup(ipasc); 1167 if (!iptmp) 1168 return NULL; 1169 p = iptmp + (p - ipasc); 1170 *p++ = 0; 1171 1172 iplen1 = a2i_ipadd(ipout, iptmp); 1173 1174 if (!iplen1) 1175 goto err; 1176 1177 iplen2 = a2i_ipadd(ipout + iplen1, p); 1178 1179 free(iptmp); 1180 iptmp = NULL; 1181 1182 if (!iplen2 || (iplen1 != iplen2)) 1183 goto err; 1184 1185 ret = ASN1_OCTET_STRING_new(); 1186 if (!ret) 1187 goto err; 1188 if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2)) 1189 goto err; 1190 1191 return ret; 1192 1193 err: 1194 free(iptmp); 1195 if (ret) 1196 ASN1_OCTET_STRING_free(ret); 1197 return NULL; 1198 } 1199 LCRYPTO_ALIAS(a2i_IPADDRESS_NC) 1200 1201 1202 int 1203 a2i_ipadd(unsigned char *ipout, const char *ipasc) 1204 { 1205 /* If string contains a ':' assume IPv6 */ 1206 1207 if (strchr(ipasc, ':')) { 1208 if (!ipv6_from_asc(ipout, ipasc)) 1209 return 0; 1210 return 16; 1211 } else { 1212 if (!ipv4_from_asc(ipout, ipasc)) 1213 return 0; 1214 return 4; 1215 } 1216 } 1217 LCRYPTO_ALIAS(a2i_ipadd) 1218 1219 static int 1220 ipv4_from_asc(unsigned char *v4, const char *in) 1221 { 1222 int a0, a1, a2, a3; 1223 if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4) 1224 return 0; 1225 if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) || 1226 (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255)) 1227 return 0; 1228 v4[0] = a0; 1229 v4[1] = a1; 1230 v4[2] = a2; 1231 v4[3] = a3; 1232 return 1; 1233 } 1234 1235 typedef struct { 1236 /* Temporary store for IPV6 output */ 1237 unsigned char tmp[16]; 1238 /* Total number of bytes in tmp */ 1239 int total; 1240 /* The position of a zero (corresponding to '::') */ 1241 int zero_pos; 1242 /* Number of zeroes */ 1243 int zero_cnt; 1244 } IPV6_STAT; 1245 1246 1247 static int 1248 ipv6_from_asc(unsigned char *v6, const char *in) 1249 { 1250 IPV6_STAT v6stat; 1251 1252 v6stat.total = 0; 1253 v6stat.zero_pos = -1; 1254 v6stat.zero_cnt = 0; 1255 1256 /* Treat the IPv6 representation as a list of values 1257 * separated by ':'. The presence of a '::' will parse 1258 * as one, two or three zero length elements. 1259 */ 1260 if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat)) 1261 return 0; 1262 1263 /* Now for some sanity checks */ 1264 1265 if (v6stat.zero_pos == -1) { 1266 /* If no '::' must have exactly 16 bytes */ 1267 if (v6stat.total != 16) 1268 return 0; 1269 } else { 1270 /* If '::' must have less than 16 bytes */ 1271 if (v6stat.total == 16) 1272 return 0; 1273 /* More than three zeroes is an error */ 1274 if (v6stat.zero_cnt > 3) 1275 return 0; 1276 /* Can only have three zeroes if nothing else present */ 1277 else if (v6stat.zero_cnt == 3) { 1278 if (v6stat.total > 0) 1279 return 0; 1280 } 1281 /* Can only have two zeroes if at start or end */ 1282 else if (v6stat.zero_cnt == 2) { 1283 if ((v6stat.zero_pos != 0) && 1284 (v6stat.zero_pos != v6stat.total)) 1285 return 0; 1286 } else 1287 /* Can only have one zero if *not* start or end */ 1288 { 1289 if ((v6stat.zero_pos == 0) || 1290 (v6stat.zero_pos == v6stat.total)) 1291 return 0; 1292 } 1293 } 1294 1295 /* Format result */ 1296 1297 if (v6stat.zero_pos >= 0) { 1298 /* Copy initial part */ 1299 memcpy(v6, v6stat.tmp, v6stat.zero_pos); 1300 /* Zero middle */ 1301 memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total); 1302 /* Copy final part */ 1303 if (v6stat.total != v6stat.zero_pos) 1304 memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total, 1305 v6stat.tmp + v6stat.zero_pos, 1306 v6stat.total - v6stat.zero_pos); 1307 } else 1308 memcpy(v6, v6stat.tmp, 16); 1309 1310 return 1; 1311 } 1312 1313 static int 1314 ipv6_cb(const char *elem, int len, void *usr) 1315 { 1316 IPV6_STAT *s = usr; 1317 1318 /* Error if 16 bytes written */ 1319 if (s->total == 16) 1320 return 0; 1321 if (len == 0) { 1322 /* Zero length element, corresponds to '::' */ 1323 if (s->zero_pos == -1) 1324 s->zero_pos = s->total; 1325 /* If we've already got a :: its an error */ 1326 else if (s->zero_pos != s->total) 1327 return 0; 1328 s->zero_cnt++; 1329 } else { 1330 /* If more than 4 characters could be final a.b.c.d form */ 1331 if (len > 4) { 1332 /* Need at least 4 bytes left */ 1333 if (s->total > 12) 1334 return 0; 1335 /* Must be end of string */ 1336 if (elem[len]) 1337 return 0; 1338 if (!ipv4_from_asc(s->tmp + s->total, elem)) 1339 return 0; 1340 s->total += 4; 1341 } else { 1342 if (!ipv6_hex(s->tmp + s->total, elem, len)) 1343 return 0; 1344 s->total += 2; 1345 } 1346 } 1347 return 1; 1348 } 1349 1350 /* Convert a string of up to 4 hex digits into the corresponding 1351 * IPv6 form. 1352 */ 1353 1354 static int 1355 ipv6_hex(unsigned char *out, const char *in, int inlen) 1356 { 1357 unsigned char c; 1358 unsigned int num = 0; 1359 1360 if (inlen > 4) 1361 return 0; 1362 while (inlen--) { 1363 c = *in++; 1364 num <<= 4; 1365 if ((c >= '0') && (c <= '9')) 1366 num |= c - '0'; 1367 else if ((c >= 'A') && (c <= 'F')) 1368 num |= c - 'A' + 10; 1369 else if ((c >= 'a') && (c <= 'f')) 1370 num |= c - 'a' + 10; 1371 else 1372 return 0; 1373 } 1374 out[0] = num >> 8; 1375 out[1] = num & 0xff; 1376 return 1; 1377 } 1378 1379 int 1380 X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk, 1381 unsigned long chtype) 1382 { 1383 CONF_VALUE *v; 1384 int i, mval; 1385 char *p, *type; 1386 1387 if (!nm) 1388 return 0; 1389 1390 for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) { 1391 v = sk_CONF_VALUE_value(dn_sk, i); 1392 type = v->name; 1393 /* Skip past any leading X. X: X, etc to allow for 1394 * multiple instances 1395 */ 1396 for (p = type; *p; p++) 1397 if ((*p == ':') || (*p == ',') || (*p == '.')) { 1398 p++; 1399 if (*p) 1400 type = p; 1401 break; 1402 } 1403 if (*type == '+') { 1404 mval = -1; 1405 type++; 1406 } else 1407 mval = 0; 1408 if (!X509_NAME_add_entry_by_txt(nm, type, chtype, 1409 (unsigned char *) v->value, -1, -1, mval)) 1410 return 0; 1411 } 1412 return 1; 1413 } 1414 LCRYPTO_ALIAS(X509V3_NAME_from_section) 1415