1 /* $OpenBSD: asn1_types.c,v 1.2 2022/09/03 18:52:18 jsing Exp $ */
2 /*
3  * Copyright (c) 2021 Joel Sing <jsing@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <stddef.h>
19 
20 #include <openssl/asn1.h>
21 
22 #define ASN1_ENCODING_CONSTRUCTED_ONLY	1
23 #define ASN1_ENCODING_PRIMITIVE_ONLY	2
24 
25 struct asn1_type {
26 	const char *name;
27 	uint32_t bit_value;
28 	int char_width;
29 	int encoding;
30 };
31 
32 /*
33  * Universal class tag types - ITU X.680.
34  */
35 static const struct asn1_type asn1_types[31] = {
36 	[0] = {
37 		/* Tag 0 (0x00) - Reserved for use by encoding rules */
38 		.name = "EOC",
39 		.bit_value = 0,
40 		.char_width = -1,
41 	},
42 	[1] = {
43 		/* Tag 1 (0x01) - Boolean */
44 		.name = "BOOLEAN",
45 		.bit_value = 0,
46 		.char_width = -1,
47 		.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
48 	},
49 	[2] = {
50 		/* Tag 2 (0x02) - Integer */
51 		.name = "INTEGER",
52 		.bit_value = 0,
53 		.char_width = -1,
54 		.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
55 	},
56 	[3] = {
57 		/* Tag 3 (0x03) - BitString */
58 		.name = "BIT STRING",
59 		.bit_value = B_ASN1_BIT_STRING,
60 		.char_width = -1,
61 	},
62 	[4] = {
63 		/* Tag 4 (0x04) - OctetString */
64 		.name = "OCTET STRING",
65 		.bit_value = B_ASN1_OCTET_STRING,
66 		.char_width = -1,
67 	},
68 	[5] = {
69 		/* Tag 5 (0x05) - Null */
70 		.name = "NULL",
71 		.bit_value = 0,
72 		.char_width = -1,
73 		.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
74 	},
75 	[6] = {
76 		/* Tag 6 (0x06) - Object Identifier */
77 		.name = "OBJECT",
78 		.bit_value = 0,
79 		.char_width = -1,
80 		.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
81 	},
82 	[7] = {
83 		/* Tag 7 (0x07) - Object Descriptor */
84 		.name = "OBJECT DESCRIPTOR",
85 		.bit_value = B_ASN1_UNKNOWN,
86 		.char_width = -1,
87 	},
88 	[8] = {
89 		/* Tag 8 (0x08) - External */
90 		.name = "EXTERNAL",
91 		.bit_value = B_ASN1_UNKNOWN,
92 		.char_width = -1,
93 	},
94 	[9] = {
95 		/* Tag 9 (0x09) - Real */
96 		.name = "REAL",
97 		.bit_value = B_ASN1_UNKNOWN,
98 		.char_width = -1,
99 		.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
100 	},
101 	[10] = {
102 		/* Tag 10 (0x0a) - Enumerated */
103 		.name = "ENUMERATED",
104 		.bit_value = B_ASN1_UNKNOWN,
105 		.char_width = -1,
106 		.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
107 	},
108 	[11] = {
109 		/* Tag 11 (0x0b) - Embedded PDV */
110 		.name = "<ASN1 11 EMBEDDED PDV>",
111 		.bit_value = B_ASN1_UNKNOWN,
112 		.char_width = -1,
113 	},
114 	[12] = {
115 		/* Tag 12 (0x0c) - UTF8String */
116 		.name = "UTF8STRING",
117 		.bit_value = B_ASN1_UTF8STRING,
118 		.char_width = 0,
119 	},
120 	[13] = {
121 		/* Tag 13 (0x0d) - Relative Object Identifier */
122 		.name = "<ASN1 13 RELATIVE OID>",
123 		.bit_value = B_ASN1_UNKNOWN,
124 		.char_width = -1,
125 		.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
126 	},
127 	[14] = {
128 		/* Tag 14 (0x0e) - Time */
129 		.name = "<ASN1 14 TIME>",
130 		.bit_value = B_ASN1_UNKNOWN,
131 		.char_width = -1,
132 		.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
133 	},
134 	[15] = {
135 		/* Tag 15 (0x0f) - Reserved */
136 		.name = "<ASN1 15 RESERVED>",
137 		.bit_value = B_ASN1_UNKNOWN,
138 		.char_width = -1,
139 	},
140 	[16] = {
141 		/* Tag 16 (0x10)- Sequence */
142 		.name = "SEQUENCE",
143 		.bit_value = B_ASN1_SEQUENCE,
144 		.char_width = -1,
145 		.encoding = ASN1_ENCODING_CONSTRUCTED_ONLY,
146 	},
147 	[17] = {
148 		/* Tag 17 (0x11) - Set */
149 		.name = "SET",
150 		.bit_value = 0,
151 		.char_width = -1,
152 		.encoding = ASN1_ENCODING_CONSTRUCTED_ONLY,
153 	},
154 	[18] = {
155 		/* Tag 18 (0x12) - NumericString */
156 		.name = "NUMERICSTRING",
157 		.bit_value = B_ASN1_NUMERICSTRING,
158 		.char_width = -1,
159 	},
160 	[19] = {
161 		/* Tag 19 (0x13) - PrintableString */
162 		.name = "PRINTABLESTRING",
163 		.bit_value = B_ASN1_PRINTABLESTRING,
164 		.char_width = 1,
165 	},
166 	[20] = {
167 		/* Tag 20 (0x14) - TeletexString (T61String) */
168 		.name = "T61STRING",
169 		.bit_value = B_ASN1_T61STRING,
170 		.char_width = 1,
171 	},
172 	[21] = {
173 		/* Tag 21 (0x15) - VideotexString */
174 		.name = "VIDEOTEXSTRING",
175 		.bit_value = B_ASN1_VIDEOTEXSTRING,
176 		.char_width = -1,
177 	},
178 	[22] = {
179 		/* Tag 22 (0x16) - IA5String */
180 		.name = "IA5STRING",
181 		.bit_value = B_ASN1_IA5STRING,
182 		.char_width = 1,
183 	},
184 	[23] = {
185 		/* Tag 23 (0x17) - UTCTime */
186 		.name = "UTCTIME",
187 		.bit_value = B_ASN1_UTCTIME,
188 		.char_width = 1,
189 	},
190 	[24] = {
191 		/* Tag 24 (0x18) - GeneralizedTime */
192 		.name = "GENERALIZEDTIME",
193 		.bit_value = B_ASN1_GENERALIZEDTIME,
194 		.char_width = 1,
195 	},
196 	[25] = {
197 		/* Tag 25 (0x19) - GraphicString */
198 		.name = "GRAPHICSTRING",
199 		.bit_value = B_ASN1_GRAPHICSTRING,
200 		.char_width = -1,
201 	},
202 	[26] = {
203 		/* Tag 26 (0x1a) - VisibleString (ISO646String) */
204 		.name = "VISIBLESTRING",
205 		.bit_value = B_ASN1_ISO64STRING,
206 		.char_width = 1,
207 	},
208 	[27] = {
209 		/* Tag 27 (0x1b) - GeneralString */
210 		.name = "GENERALSTRING",
211 		.bit_value = B_ASN1_GENERALSTRING,
212 		.char_width = -1,
213 	},
214 	[28] = {
215 		/* Tag 28 (0x1c) - UniversalString */
216 		.name = "UNIVERSALSTRING",
217 		.bit_value = B_ASN1_UNIVERSALSTRING,
218 		.char_width = 4,
219 	},
220 	[29] = {
221 		/* Tag 29 (0x1d) - Unallocated */
222 		.name = "<ASN1 29>",
223 		.bit_value = B_ASN1_UNKNOWN,
224 		.char_width = -1,
225 	},
226 	[30] = {
227 		/* Tag 30 (0x1e) - BMPString */
228 		.name = "BMPSTRING",
229 		.bit_value = B_ASN1_BMPSTRING,
230 		.char_width = 2,
231 	},
232 };
233 
234 static const struct asn1_type *
235 asn1_type_by_tag(int tag)
236 {
237 	if (tag < 0 || tag > 30)
238 		return NULL;
239 
240 	return &asn1_types[tag];
241 }
242 
243 int
244 asn1_must_be_constructed(int tag)
245 {
246 	const struct asn1_type *at;
247 
248 	if (tag == V_ASN1_NEG_INTEGER || tag == V_ASN1_NEG_ENUMERATED)
249 		tag &= ~V_ASN1_NEG;
250 	if ((at = asn1_type_by_tag(tag)) != NULL)
251 		return at->encoding == ASN1_ENCODING_CONSTRUCTED_ONLY;
252 
253 	return 0;
254 }
255 
256 int
257 asn1_must_be_primitive(int tag)
258 {
259 	const struct asn1_type *at;
260 
261 	if (tag == V_ASN1_NEG_INTEGER || tag == V_ASN1_NEG_ENUMERATED)
262 		tag &= ~V_ASN1_NEG;
263 	if ((at = asn1_type_by_tag(tag)) != NULL)
264 		return at->encoding == ASN1_ENCODING_PRIMITIVE_ONLY;
265 
266 	return 0;
267 }
268 
269 int
270 asn1_tag2charwidth(int tag)
271 {
272 	const struct asn1_type *at;
273 
274 	if ((at = asn1_type_by_tag(tag)) != NULL)
275 		return at->char_width;
276 
277 	return -1;
278 }
279 
280 unsigned long
281 ASN1_tag2bit(int tag)
282 {
283 	const struct asn1_type *at;
284 
285 	if ((at = asn1_type_by_tag(tag)) != NULL)
286 		return (unsigned long)at->bit_value;
287 
288 	return 0;
289 }
290 
291 const char *
292 ASN1_tag2str(int tag)
293 {
294 	const struct asn1_type *at;
295 
296 	if (tag == V_ASN1_NEG_INTEGER || tag == V_ASN1_NEG_ENUMERATED)
297 		tag &= ~V_ASN1_NEG;
298 
299 	if ((at = asn1_type_by_tag(tag)) != NULL)
300 		return at->name;
301 
302 	return "(unknown)";
303 }
304