]>
Commit | Line | Data |
---|---|---|
0f113f3e | 1 | /* |
da1c088f | 2 | * Copyright 1999-2023 The OpenSSL Project Authors. All Rights Reserved. |
f769ce3e | 3 | * |
365a2d99 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
2039c421 RS |
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 | |
f769ce3e DSH |
8 | */ |
9 | ||
10 | #include <stdio.h> | |
b39fc560 | 11 | #include "internal/cryptlib.h" |
f769ce3e DSH |
12 | #include <openssl/asn1.h> |
13 | #include <openssl/objects.h> | |
14 | ||
f769ce3e DSH |
15 | static STACK_OF(ASN1_STRING_TABLE) *stable = NULL; |
16 | static void st_free(ASN1_STRING_TABLE *tbl); | |
0f113f3e MC |
17 | static int sk_table_cmp(const ASN1_STRING_TABLE *const *a, |
18 | const ASN1_STRING_TABLE *const *b); | |
b38f9f66 | 19 | |
0f113f3e MC |
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. | |
b38f9f66 DSH |
24 | */ |
25 | ||
3009244d | 26 | static unsigned long global_mask = B_ASN1_UTF8STRING; |
b38f9f66 DSH |
27 | |
28 | void ASN1_STRING_set_default_mask(unsigned long mask) | |
29 | { | |
0f113f3e | 30 | global_mask = mask; |
b38f9f66 DSH |
31 | } |
32 | ||
33 | unsigned long ASN1_STRING_get_default_mask(void) | |
34 | { | |
0f113f3e | 35 | return global_mask; |
b38f9f66 DSH |
36 | } |
37 | ||
c80fd6b2 MC |
38 | /*- |
39 | * This function sets the default to various "flavours" of configuration. | |
b38f9f66 DSH |
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 | ||
7d05edd1 | 48 | int ASN1_STRING_set_default_mask_asc(const char *p) |
b38f9f66 | 49 | { |
0f113f3e MC |
50 | unsigned long mask; |
51 | char *end; | |
3ca1f892 | 52 | |
2ff286c2 DDO |
53 | if (CHECK_AND_SKIP_PREFIX(p, "MASK:")) { |
54 | if (*p == '\0') | |
0f113f3e | 55 | return 0; |
2ff286c2 | 56 | mask = strtoul(p, &end, 0); |
0f113f3e MC |
57 | if (*end) |
58 | return 0; | |
86885c28 | 59 | } else if (strcmp(p, "nombstr") == 0) |
0f113f3e | 60 | mask = ~((unsigned long)(B_ASN1_BMPSTRING | B_ASN1_UTF8STRING)); |
86885c28 | 61 | else if (strcmp(p, "pkix") == 0) |
0f113f3e | 62 | mask = ~((unsigned long)B_ASN1_T61STRING); |
86885c28 | 63 | else if (strcmp(p, "utf8only") == 0) |
0f113f3e | 64 | mask = B_ASN1_UTF8STRING; |
86885c28 | 65 | else if (strcmp(p, "default") == 0) |
0f113f3e MC |
66 | mask = 0xFFFFFFFFL; |
67 | else | |
68 | return 0; | |
69 | ASN1_STRING_set_default_mask(mask); | |
70 | return 1; | |
b38f9f66 DSH |
71 | } |
72 | ||
0f113f3e MC |
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. | |
f769ce3e DSH |
77 | */ |
78 | ||
0f113f3e MC |
79 | ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, |
80 | const unsigned char *in, int inlen, | |
81 | int inform, int nid) | |
f769ce3e | 82 | { |
0f113f3e MC |
83 | ASN1_STRING_TABLE *tbl; |
84 | ASN1_STRING *str = NULL; | |
85 | unsigned long mask; | |
86 | int ret; | |
3ca1f892 PY |
87 | |
88 | if (out == NULL) | |
0f113f3e MC |
89 | out = &str; |
90 | tbl = ASN1_STRING_TABLE_get(nid); | |
3ca1f892 | 91 | if (tbl != NULL) { |
0f113f3e MC |
92 | mask = tbl->mask; |
93 | if (!(tbl->flags & STABLE_NO_MASK)) | |
94 | mask &= global_mask; | |
95 | ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask, | |
96 | tbl->minsize, tbl->maxsize); | |
3ca1f892 PY |
97 | } else { |
98 | ret = ASN1_mbstring_copy(out, in, inlen, inform, | |
99 | DIRSTRING_TYPE & global_mask); | |
100 | } | |
0f113f3e MC |
101 | if (ret <= 0) |
102 | return NULL; | |
103 | return *out; | |
f769ce3e DSH |
104 | } |
105 | ||
0f113f3e MC |
106 | /* |
107 | * Now the tables and helper functions for the string table: | |
f769ce3e DSH |
108 | */ |
109 | ||
2c166171 | 110 | #include "tbl_standard.h" |
f769ce3e | 111 | |
0f113f3e MC |
112 | static int sk_table_cmp(const ASN1_STRING_TABLE *const *a, |
113 | const ASN1_STRING_TABLE *const *b) | |
f769ce3e | 114 | { |
0f113f3e | 115 | return (*a)->nid - (*b)->nid; |
f769ce3e DSH |
116 | } |
117 | ||
e19106f5 | 118 | DECLARE_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table); |
babb3798 BL |
119 | |
120 | static int table_cmp(const ASN1_STRING_TABLE *a, const ASN1_STRING_TABLE *b) | |
f769ce3e | 121 | { |
0f113f3e | 122 | return a->nid - b->nid; |
f769ce3e DSH |
123 | } |
124 | ||
e19106f5 | 125 | IMPLEMENT_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table); |
babb3798 | 126 | |
f769ce3e | 127 | ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid) |
0f113f3e MC |
128 | { |
129 | int idx; | |
130 | ASN1_STRING_TABLE fnd; | |
3ca1f892 | 131 | |
cb8e6413 | 132 | #ifndef OPENSSL_NO_AUTOLOAD_CONFIG |
29dc6e00 MC |
133 | /* "stable" can be impacted by config, so load the config file first */ |
134 | OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL); | |
cb8e6413 | 135 | #endif |
29dc6e00 | 136 | |
0f113f3e | 137 | fnd.nid = nid; |
0feb90ba P |
138 | if (stable != NULL) { |
139 | /* Ideally, this would be done under lock */ | |
140 | sk_ASN1_STRING_TABLE_sort(stable); | |
0f113f3e MC |
141 | idx = sk_ASN1_STRING_TABLE_find(stable, &fnd); |
142 | if (idx >= 0) | |
143 | return sk_ASN1_STRING_TABLE_value(stable, idx); | |
144 | } | |
b6eb9827 | 145 | return OBJ_bsearch_table(&fnd, tbl_standard, OSSL_NELEM(tbl_standard)); |
0f113f3e MC |
146 | } |
147 | ||
148 | /* | |
149 | * Return a string table pointer which can be modified: either directly from | |
150 | * table or a copy of an internal value added to the table. | |
d35c0ff3 DSH |
151 | */ |
152 | ||
153 | static ASN1_STRING_TABLE *stable_get(int nid) | |
0f113f3e MC |
154 | { |
155 | ASN1_STRING_TABLE *tmp, *rv; | |
3ca1f892 | 156 | |
0f113f3e | 157 | /* Always need a string table so allocate one if NULL */ |
90945fa3 | 158 | if (stable == NULL) { |
0f113f3e | 159 | stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp); |
90945fa3 | 160 | if (stable == NULL) |
0f113f3e MC |
161 | return NULL; |
162 | } | |
163 | tmp = ASN1_STRING_TABLE_get(nid); | |
3ca1f892 | 164 | if (tmp != NULL && tmp->flags & STABLE_FLAGS_MALLOC) |
0f113f3e | 165 | return tmp; |
e077455e | 166 | if ((rv = OPENSSL_zalloc(sizeof(*rv))) == NULL) |
0f113f3e MC |
167 | return NULL; |
168 | if (!sk_ASN1_STRING_TABLE_push(stable, rv)) { | |
169 | OPENSSL_free(rv); | |
170 | return NULL; | |
171 | } | |
3ca1f892 | 172 | if (tmp != NULL) { |
0f113f3e MC |
173 | rv->nid = tmp->nid; |
174 | rv->minsize = tmp->minsize; | |
175 | rv->maxsize = tmp->maxsize; | |
176 | rv->mask = tmp->mask; | |
177 | rv->flags = tmp->flags | STABLE_FLAGS_MALLOC; | |
178 | } else { | |
386e9169 | 179 | rv->nid = nid; |
0f113f3e MC |
180 | rv->minsize = -1; |
181 | rv->maxsize = -1; | |
0f113f3e MC |
182 | rv->flags = STABLE_FLAGS_MALLOC; |
183 | } | |
184 | return rv; | |
185 | } | |
d35c0ff3 | 186 | |
f769ce3e | 187 | int ASN1_STRING_TABLE_add(int nid, |
0f113f3e MC |
188 | long minsize, long maxsize, unsigned long mask, |
189 | unsigned long flags) | |
190 | { | |
191 | ASN1_STRING_TABLE *tmp; | |
3ca1f892 | 192 | |
0f113f3e | 193 | tmp = stable_get(nid); |
3ca1f892 | 194 | if (tmp == NULL) { |
e077455e | 195 | ERR_raise(ERR_LIB_ASN1, ERR_R_ASN1_LIB); |
0f113f3e MC |
196 | return 0; |
197 | } | |
198 | if (minsize >= 0) | |
199 | tmp->minsize = minsize; | |
200 | if (maxsize >= 0) | |
201 | tmp->maxsize = maxsize; | |
202 | if (mask) | |
203 | tmp->mask = mask; | |
204 | if (flags) | |
205 | tmp->flags = STABLE_FLAGS_MALLOC | flags; | |
206 | return 1; | |
207 | } | |
f769ce3e DSH |
208 | |
209 | void ASN1_STRING_TABLE_cleanup(void) | |
210 | { | |
0f113f3e | 211 | STACK_OF(ASN1_STRING_TABLE) *tmp; |
3ca1f892 | 212 | |
0f113f3e | 213 | tmp = stable; |
3ca1f892 | 214 | if (tmp == NULL) |
0f113f3e MC |
215 | return; |
216 | stable = NULL; | |
217 | sk_ASN1_STRING_TABLE_pop_free(tmp, st_free); | |
f769ce3e DSH |
218 | } |
219 | ||
220 | static void st_free(ASN1_STRING_TABLE *tbl) | |
221 | { | |
0f113f3e MC |
222 | if (tbl->flags & STABLE_FLAGS_MALLOC) |
223 | OPENSSL_free(tbl); | |
f769ce3e | 224 | } |