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