]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/asn1/a_strnid.c
Add CRYPTO_atomic_store api
[thirdparty/openssl.git] / crypto / asn1 / a_strnid.c
CommitLineData
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
15static STACK_OF(ASN1_STRING_TABLE) *stable = NULL;
16static void st_free(ASN1_STRING_TABLE *tbl);
0f113f3e
MC
17static 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 26static unsigned long global_mask = B_ASN1_UTF8STRING;
b38f9f66
DSH
27
28void ASN1_STRING_set_default_mask(unsigned long mask)
29{
0f113f3e 30 global_mask = mask;
b38f9f66
DSH
31}
32
33unsigned 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 48int 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
79ASN1_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
112static 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 118DECLARE_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table);
babb3798
BL
119
120static 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 125IMPLEMENT_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table);
babb3798 126
f769ce3e 127ASN1_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
153static 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 187int 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
209void 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
220static void st_free(ASN1_STRING_TABLE *tbl)
221{
0f113f3e
MC
222 if (tbl->flags & STABLE_FLAGS_MALLOC)
223 OPENSSL_free(tbl);
f769ce3e 224}