Home | History | Annotate | Line # | Download | only in x509
      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