/src/openssl30/crypto/asn1/a_strnid.c
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | /* | 
| 2 |  |  * Copyright 1999-2023 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 |  | #include <stdio.h> | 
| 11 |  | #include "internal/cryptlib.h" | 
| 12 |  | #include <openssl/asn1.h> | 
| 13 |  | #include <openssl/objects.h> | 
| 14 |  |  | 
| 15 |  | static STACK_OF(ASN1_STRING_TABLE) *stable = NULL; | 
| 16 |  | static void st_free(ASN1_STRING_TABLE *tbl); | 
| 17 |  | static int sk_table_cmp(const ASN1_STRING_TABLE *const *a, | 
| 18 |  |                         const ASN1_STRING_TABLE *const *b); | 
| 19 |  |  | 
| 20 |  | /* | 
| 21 |  |  * This is the global mask for the mbstring functions: this is use to mask | 
| 22 |  |  * out certain types (such as BMPString and UTF8String) because certain | 
| 23 |  |  * software (e.g. Netscape) has problems with them. | 
| 24 |  |  */ | 
| 25 |  |  | 
| 26 |  | static unsigned long global_mask = B_ASN1_UTF8STRING; | 
| 27 |  |  | 
| 28 |  | void ASN1_STRING_set_default_mask(unsigned long mask) | 
| 29 | 0 | { | 
| 30 | 0 |     global_mask = mask; | 
| 31 | 0 | } | 
| 32 |  |  | 
| 33 |  | unsigned long ASN1_STRING_get_default_mask(void) | 
| 34 | 0 | { | 
| 35 | 0 |     return global_mask; | 
| 36 | 0 | } | 
| 37 |  |  | 
| 38 |  | /*- | 
| 39 |  |  * This function sets the default to various "flavours" of configuration. | 
| 40 |  |  * based on an ASCII string. Currently this is: | 
| 41 |  |  * MASK:XXXX : a numerical mask value. | 
| 42 |  |  * nobmp : Don't use BMPStrings (just Printable, T61). | 
| 43 |  |  * pkix : PKIX recommendation in RFC2459. | 
| 44 |  |  * utf8only : only use UTF8Strings (RFC2459 recommendation for 2004). | 
| 45 |  |  * default:   the default value, Printable, T61, BMP. | 
| 46 |  |  */ | 
| 47 |  |  | 
| 48 |  | int ASN1_STRING_set_default_mask_asc(const char *p) | 
| 49 | 0 | { | 
| 50 | 0 |     unsigned long mask; | 
| 51 | 0 |     char *end; | 
| 52 |  | 
 | 
| 53 | 0 |     if (strncmp(p, "MASK:", 5) == 0) { | 
| 54 | 0 |         if (p[5] == '\0') | 
| 55 | 0 |             return 0; | 
| 56 | 0 |         mask = strtoul(p + 5, &end, 0); | 
| 57 | 0 |         if (*end) | 
| 58 | 0 |             return 0; | 
| 59 | 0 |     } else if (strcmp(p, "nombstr") == 0) | 
| 60 | 0 |         mask = ~((unsigned long)(B_ASN1_BMPSTRING | B_ASN1_UTF8STRING)); | 
| 61 | 0 |     else if (strcmp(p, "pkix") == 0) | 
| 62 | 0 |         mask = ~((unsigned long)B_ASN1_T61STRING); | 
| 63 | 0 |     else if (strcmp(p, "utf8only") == 0) | 
| 64 | 0 |         mask = B_ASN1_UTF8STRING; | 
| 65 | 0 |     else if (strcmp(p, "default") == 0) | 
| 66 | 0 |         mask = 0xFFFFFFFFL; | 
| 67 | 0 |     else | 
| 68 | 0 |         return 0; | 
| 69 | 0 |     ASN1_STRING_set_default_mask(mask); | 
| 70 | 0 |     return 1; | 
| 71 | 0 | } | 
| 72 |  |  | 
| 73 |  | /* | 
| 74 |  |  * The following function generates an ASN1_STRING based on limits in a | 
| 75 |  |  * table. Frequently the types and length of an ASN1_STRING are restricted by | 
| 76 |  |  * a corresponding OID. For example certificates and certificate requests. | 
| 77 |  |  */ | 
| 78 |  |  | 
| 79 |  | ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, | 
| 80 |  |                                     const unsigned char *in, int inlen, | 
| 81 |  |                                     int inform, int nid) | 
| 82 | 0 | { | 
| 83 | 0 |     ASN1_STRING_TABLE *tbl; | 
| 84 | 0 |     ASN1_STRING *str = NULL; | 
| 85 | 0 |     unsigned long mask; | 
| 86 | 0 |     int ret; | 
| 87 |  | 
 | 
| 88 | 0 |     if (out == NULL) | 
| 89 | 0 |         out = &str; | 
| 90 | 0 |     tbl = ASN1_STRING_TABLE_get(nid); | 
| 91 | 0 |     if (tbl != NULL) { | 
| 92 | 0 |         mask = tbl->mask; | 
| 93 | 0 |         if (!(tbl->flags & STABLE_NO_MASK)) | 
| 94 | 0 |             mask &= global_mask; | 
| 95 | 0 |         ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask, | 
| 96 | 0 |                                   tbl->minsize, tbl->maxsize); | 
| 97 | 0 |     } else { | 
| 98 | 0 |         ret = ASN1_mbstring_copy(out, in, inlen, inform, | 
| 99 | 0 |                                  DIRSTRING_TYPE & global_mask); | 
| 100 | 0 |     } | 
| 101 | 0 |     if (ret <= 0) | 
| 102 | 0 |         return NULL; | 
| 103 | 0 |     return *out; | 
| 104 | 0 | } | 
| 105 |  |  | 
| 106 |  | /* | 
| 107 |  |  * Now the tables and helper functions for the string table: | 
| 108 |  |  */ | 
| 109 |  |  | 
| 110 |  | #include "tbl_standard.h" | 
| 111 |  |  | 
| 112 |  | static int sk_table_cmp(const ASN1_STRING_TABLE *const *a, | 
| 113 |  |                         const ASN1_STRING_TABLE *const *b) | 
| 114 | 0 | { | 
| 115 | 0 |     return (*a)->nid - (*b)->nid; | 
| 116 | 0 | } | 
| 117 |  |  | 
| 118 |  | DECLARE_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table); | 
| 119 |  |  | 
| 120 |  | static int table_cmp(const ASN1_STRING_TABLE *a, const ASN1_STRING_TABLE *b) | 
| 121 | 0 | { | 
| 122 | 0 |     return a->nid - b->nid; | 
| 123 | 0 | } | 
| 124 |  |  | 
| 125 |  | IMPLEMENT_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table); | 
| 126 |  |  | 
| 127 |  | ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid) | 
| 128 | 0 | { | 
| 129 | 0 |     int idx; | 
| 130 | 0 |     ASN1_STRING_TABLE fnd; | 
| 131 |  | 
 | 
| 132 | 0 | #ifndef OPENSSL_NO_AUTOLOAD_CONFIG | 
| 133 |  |     /* "stable" can be impacted by config, so load the config file first */ | 
| 134 | 0 |     OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL); | 
| 135 | 0 | #endif | 
| 136 |  | 
 | 
| 137 | 0 |     fnd.nid = nid; | 
| 138 | 0 |     if (stable) { | 
| 139 | 0 |         idx = sk_ASN1_STRING_TABLE_find(stable, &fnd); | 
| 140 | 0 |         if (idx >= 0) | 
| 141 | 0 |             return sk_ASN1_STRING_TABLE_value(stable, idx); | 
| 142 | 0 |     } | 
| 143 | 0 |     return OBJ_bsearch_table(&fnd, tbl_standard, OSSL_NELEM(tbl_standard)); | 
| 144 | 0 | } | 
| 145 |  |  | 
| 146 |  | /* | 
| 147 |  |  * Return a string table pointer which can be modified: either directly from | 
| 148 |  |  * table or a copy of an internal value added to the table. | 
| 149 |  |  */ | 
| 150 |  |  | 
| 151 |  | static ASN1_STRING_TABLE *stable_get(int nid) | 
| 152 | 0 | { | 
| 153 | 0 |     ASN1_STRING_TABLE *tmp, *rv; | 
| 154 |  |  | 
| 155 |  |     /* Always need a string table so allocate one if NULL */ | 
| 156 | 0 |     if (stable == NULL) { | 
| 157 | 0 |         stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp); | 
| 158 | 0 |         if (stable == NULL) | 
| 159 | 0 |             return NULL; | 
| 160 | 0 |     } | 
| 161 | 0 |     tmp = ASN1_STRING_TABLE_get(nid); | 
| 162 | 0 |     if (tmp != NULL && tmp->flags & STABLE_FLAGS_MALLOC) | 
| 163 | 0 |         return tmp; | 
| 164 | 0 |     if ((rv = OPENSSL_zalloc(sizeof(*rv))) == NULL) { | 
| 165 | 0 |         ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); | 
| 166 | 0 |         return NULL; | 
| 167 | 0 |     } | 
| 168 | 0 |     if (!sk_ASN1_STRING_TABLE_push(stable, rv)) { | 
| 169 | 0 |         OPENSSL_free(rv); | 
| 170 | 0 |         return NULL; | 
| 171 | 0 |     } | 
| 172 | 0 |     if (tmp != NULL) { | 
| 173 | 0 |         rv->nid = tmp->nid; | 
| 174 | 0 |         rv->minsize = tmp->minsize; | 
| 175 | 0 |         rv->maxsize = tmp->maxsize; | 
| 176 | 0 |         rv->mask = tmp->mask; | 
| 177 | 0 |         rv->flags = tmp->flags | STABLE_FLAGS_MALLOC; | 
| 178 | 0 |     } else { | 
| 179 | 0 |         rv->nid = nid; | 
| 180 | 0 |         rv->minsize = -1; | 
| 181 | 0 |         rv->maxsize = -1; | 
| 182 | 0 |         rv->flags = STABLE_FLAGS_MALLOC; | 
| 183 | 0 |     } | 
| 184 | 0 |     return rv; | 
| 185 | 0 | } | 
| 186 |  |  | 
| 187 |  | int ASN1_STRING_TABLE_add(int nid, | 
| 188 |  |                           long minsize, long maxsize, unsigned long mask, | 
| 189 |  |                           unsigned long flags) | 
| 190 | 0 | { | 
| 191 | 0 |     ASN1_STRING_TABLE *tmp; | 
| 192 |  | 
 | 
| 193 | 0 |     tmp = stable_get(nid); | 
| 194 | 0 |     if (tmp == NULL) { | 
| 195 | 0 |         ERR_raise(ERR_LIB_ASN1, ERR_R_MALLOC_FAILURE); | 
| 196 | 0 |         return 0; | 
| 197 | 0 |     } | 
| 198 | 0 |     if (minsize >= 0) | 
| 199 | 0 |         tmp->minsize = minsize; | 
| 200 | 0 |     if (maxsize >= 0) | 
| 201 | 0 |         tmp->maxsize = maxsize; | 
| 202 | 0 |     if (mask) | 
| 203 | 0 |         tmp->mask = mask; | 
| 204 | 0 |     if (flags) | 
| 205 | 0 |         tmp->flags = STABLE_FLAGS_MALLOC | flags; | 
| 206 | 0 |     return 1; | 
| 207 | 0 | } | 
| 208 |  |  | 
| 209 |  | void ASN1_STRING_TABLE_cleanup(void) | 
| 210 | 0 | { | 
| 211 | 0 |     STACK_OF(ASN1_STRING_TABLE) *tmp; | 
| 212 |  | 
 | 
| 213 | 0 |     tmp = stable; | 
| 214 | 0 |     if (tmp == NULL) | 
| 215 | 0 |         return; | 
| 216 | 0 |     stable = NULL; | 
| 217 | 0 |     sk_ASN1_STRING_TABLE_pop_free(tmp, st_free); | 
| 218 | 0 | } | 
| 219 |  |  | 
| 220 |  | static void st_free(ASN1_STRING_TABLE *tbl) | 
| 221 | 0 | { | 
| 222 | 0 |     if (tbl->flags & STABLE_FLAGS_MALLOC) | 
| 223 | 0 |         OPENSSL_free(tbl); | 
| 224 | 0 | } |