xref: /openbsd/lib/libcrypto/asn1/a_strnid.c (revision cf3aa6ad)
1 /* $OpenBSD: a_strnid.c,v 1.29 2023/12/16 12:56:20 tb Exp $ */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project 1999.
4  */
5 /* ====================================================================
6  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58 
59 #include <errno.h>
60 #include <limits.h>
61 #include <stdlib.h>
62 #include <string.h>
63 
64 #include <openssl/asn1.h>
65 #include <openssl/err.h>
66 #include <openssl/objects.h>
67 
68 /*
69  * XXX - unprotected global state
70  *
71  * This is the global mask for the mbstring functions: this is used to
72  * mask out certain types (such as BMPString and UTF8String) because
73  * certain software (e.g. Netscape) has problems with them.
74  */
75 static unsigned long global_mask = B_ASN1_UTF8STRING;
76 
77 void
78 ASN1_STRING_set_default_mask(unsigned long mask)
79 {
80 	global_mask = mask;
81 }
82 LCRYPTO_ALIAS(ASN1_STRING_set_default_mask);
83 
84 unsigned long
85 ASN1_STRING_get_default_mask(void)
86 {
87 	return global_mask;
88 }
89 LCRYPTO_ALIAS(ASN1_STRING_get_default_mask);
90 
91 /*
92  * This function sets the default to various "flavours" of configuration
93  * based on an ASCII string. Currently this is:
94  * MASK:XXXX : a numerical mask value.
95  * nobmp : Don't use BMPStrings (just Printable, T61).
96  * pkix : PKIX recommendation in RFC2459.
97  * utf8only : only use UTF8Strings (RFC2459 recommendation for 2004).
98  * default:   the default value, Printable, T61, BMP.
99  */
100 
101 int
102 ASN1_STRING_set_default_mask_asc(const char *p)
103 {
104 	unsigned long mask;
105 	char *end;
106 	int save_errno;
107 
108 	if (strncmp(p, "MASK:", 5) == 0) {
109 		if (p[5] == '\0')
110 			return 0;
111 		save_errno = errno;
112 		errno = 0;
113 		mask = strtoul(p + 5, &end, 0);
114 		if (errno == ERANGE && mask == ULONG_MAX)
115 			return 0;
116 		errno = save_errno;
117 		if (*end != '\0')
118 			return 0;
119 	} else if (strcmp(p, "nombstr") == 0)
120 		mask = ~((unsigned long)(B_ASN1_BMPSTRING|B_ASN1_UTF8STRING));
121 	else if (strcmp(p, "pkix") == 0)
122 		mask = ~((unsigned long)B_ASN1_T61STRING);
123 	else if (strcmp(p, "utf8only") == 0)
124 		mask = B_ASN1_UTF8STRING;
125 	else if (strcmp(p, "default") == 0)
126 		mask = 0xFFFFFFFFL;
127 	else
128 		return 0;
129 	ASN1_STRING_set_default_mask(mask);
130 	return 1;
131 }
132 LCRYPTO_ALIAS(ASN1_STRING_set_default_mask_asc);
133 
134 /*
135  * The following function generates an ASN1_STRING based on limits in a table.
136  * Frequently the types and length of an ASN1_STRING are restricted by a
137  * corresponding OID. For example certificates and certificate requests.
138  */
139 
140 ASN1_STRING *
141 ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in, int inlen,
142     int inform, int nid)
143 {
144 	ASN1_STRING_TABLE *tbl;
145 	ASN1_STRING *str = NULL;
146 	unsigned long mask;
147 	int ret;
148 
149 	if (out == NULL)
150 		out = &str;
151 	tbl = ASN1_STRING_TABLE_get(nid);
152 	if (tbl != NULL) {
153 		mask = tbl->mask;
154 		if ((tbl->flags & STABLE_NO_MASK) == 0)
155 			mask &= global_mask;
156 		ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask,
157 		    tbl->minsize, tbl->maxsize);
158 	} else
159 		ret = ASN1_mbstring_copy(out, in, inlen, inform,
160 		    DIRSTRING_TYPE & global_mask);
161 	if (ret <= 0)
162 		return NULL;
163 	return *out;
164 }
165 LCRYPTO_ALIAS(ASN1_STRING_set_by_NID);
166 
167 /* From RFC 5280, Appendix A.1. */
168 #define ub_name				32768
169 #define ub_common_name			64
170 #define ub_locality_name		128
171 #define ub_state_name			128
172 #define ub_organization_name		64
173 #define ub_organization_unit_name	64
174 #define ub_title			64
175 #define ub_email_address		128 /* XXX - bumped to 255 in RFC 5280 */
176 #define ub_serial_number		64
177 
178 static const ASN1_STRING_TABLE tbl_standard[] = {
179 	{
180 		.nid = NID_commonName,
181 		.minsize = 1,
182 		.maxsize = ub_common_name,
183 		.mask = DIRSTRING_TYPE,
184 		.flags = 0,
185 	},
186 	{
187 		.nid = NID_countryName,
188 		.minsize = 2,
189 		.maxsize = 2,
190 		.mask = B_ASN1_PRINTABLESTRING,
191 		.flags = STABLE_NO_MASK,
192 	},
193 	{
194 		.nid = NID_localityName,
195 		.minsize = 1,
196 		.maxsize = ub_locality_name,
197 		.mask = DIRSTRING_TYPE,
198 		.flags = 0,
199 	},
200 	{
201 		.nid = NID_stateOrProvinceName,
202 		.minsize = 1,
203 		.maxsize = ub_state_name,
204 		.mask = DIRSTRING_TYPE,
205 		.flags = 0,
206 	},
207 	{
208 		.nid = NID_organizationName,
209 		.minsize = 1,
210 		.maxsize = ub_organization_name,
211 		.mask = DIRSTRING_TYPE,
212 		.flags = 0,
213 	},
214 	{
215 		.nid = NID_organizationalUnitName,
216 		.minsize = 1,
217 		.maxsize = ub_organization_unit_name,
218 		.mask = DIRSTRING_TYPE,
219 		.flags = 0,
220 	},
221 	{
222 		.nid = NID_pkcs9_emailAddress,
223 		.minsize = 1,
224 		.maxsize = ub_email_address,
225 		.mask = B_ASN1_IA5STRING,
226 		.flags = STABLE_NO_MASK,
227 	},
228 	{
229 		.nid = NID_pkcs9_unstructuredName,
230 		.minsize = 1,
231 		.maxsize = -1,
232 		.mask = PKCS9STRING_TYPE,
233 		.flags = 0,
234 	},
235 	{
236 		.nid = NID_pkcs9_challengePassword,
237 		.minsize = 1,
238 		.maxsize = -1,
239 		.mask = PKCS9STRING_TYPE,
240 		.flags = 0,
241 	},
242 	{
243 		.nid = NID_pkcs9_unstructuredAddress,
244 		.minsize = 1,
245 		.maxsize = -1,
246 		.mask = DIRSTRING_TYPE,
247 		.flags = 0,
248 	},
249 	{
250 		.nid = NID_givenName,
251 		.minsize = 1,
252 		.maxsize = ub_name,
253 		.mask = DIRSTRING_TYPE,
254 		.flags = 0,
255 	},
256 	{
257 		.nid = NID_surname,
258 		.minsize = 1,
259 		.maxsize = ub_name,
260 		.mask = DIRSTRING_TYPE,
261 		.flags = 0,
262 	},
263 	{
264 		.nid = NID_initials,
265 		.minsize = 1,
266 		.maxsize = ub_name,
267 		.mask = DIRSTRING_TYPE,
268 		.flags = 0,
269 	},
270 	{
271 		.nid = NID_serialNumber,
272 		.minsize = 1,
273 		.maxsize = ub_serial_number,
274 		.mask = B_ASN1_PRINTABLESTRING,
275 		.flags = STABLE_NO_MASK,
276 	},
277 	{
278 		.nid = NID_friendlyName,
279 		.minsize = -1,
280 		.maxsize = -1,
281 		.mask = B_ASN1_BMPSTRING,
282 		.flags = STABLE_NO_MASK,
283 	},
284 	{
285 		.nid = NID_name,
286 		.minsize = 1,
287 		.maxsize = ub_name,
288 		.mask = DIRSTRING_TYPE,
289 		.flags = 0,
290 	},
291 	{
292 		.nid = NID_dnQualifier,
293 		.minsize = -1,
294 		.maxsize = -1,
295 		.mask = B_ASN1_PRINTABLESTRING,
296 		.flags = STABLE_NO_MASK,
297 	},
298 	{
299 		.nid = NID_domainComponent,
300 		.minsize = 1,
301 		.maxsize = -1,
302 		.mask = B_ASN1_IA5STRING,
303 		.flags = STABLE_NO_MASK,
304 	},
305 	{
306 		.nid = NID_ms_csp_name,
307 		.minsize = -1,
308 		.maxsize = -1,
309 		.mask = B_ASN1_BMPSTRING,
310 		.flags = STABLE_NO_MASK,
311 	},
312 };
313 
314 #define N_STRING_TABLE_ENTRIES (sizeof(tbl_standard) / sizeof(tbl_standard[0]))
315 
316 /* XXX - const */
317 ASN1_STRING_TABLE *
318 ASN1_STRING_TABLE_get(int nid)
319 {
320 	size_t i;
321 
322 	for (i = 0; i < N_STRING_TABLE_ENTRIES; i++) {
323 		const ASN1_STRING_TABLE *entry = &tbl_standard[i];
324 		if (entry->nid == nid)
325 			return (ASN1_STRING_TABLE *)entry;
326 	}
327 
328 	return NULL;
329 }
330 LCRYPTO_ALIAS(ASN1_STRING_TABLE_get);
331 
332 int
333 ASN1_STRING_TABLE_add(int nid, long minsize, long maxsize, unsigned long mask,
334     unsigned long flags)
335 {
336 	ASN1error(ERR_R_DISABLED);
337 	return 0;
338 }
339 LCRYPTO_ALIAS(ASN1_STRING_TABLE_add);
340 
341 void
342 ASN1_STRING_TABLE_cleanup(void)
343 {
344 	ASN1error(ERR_R_DISABLED);
345 }
346 LCRYPTO_ALIAS(ASN1_STRING_TABLE_cleanup);
347