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