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