xref: /openbsd-src/regress/lib/libcrypto/asn1/asn1complex.c (revision 7bb1a6cf33c70622e249876e749b4a7ea7b98384)
1 /* $OpenBSD: asn1complex.c,v 1.4 2022/09/05 21:06:31 tb Exp $ */
2 /*
3  * Copyright (c) 2017, 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 <openssl/asn1.h>
19 #include <openssl/asn1t.h>
20 #include <openssl/err.h>
21 
22 #include <err.h>
23 #include <stdio.h>
24 #include <string.h>
25 
26 static void
hexdump(const unsigned char * buf,size_t len)27 hexdump(const unsigned char *buf, size_t len)
28 {
29 	size_t i;
30 
31 	for (i = 1; i <= len; i++)
32 		fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
33 
34 	fprintf(stderr, "\n");
35 }
36 
37 static int
asn1_compare_bytes(const char * label,const unsigned char * d1,int len1,const unsigned char * d2,int len2)38 asn1_compare_bytes(const char *label, const unsigned char *d1, int len1,
39     const unsigned char *d2, int len2)
40 {
41 	if (len1 != len2) {
42 		fprintf(stderr, "FAIL: %s - byte lengths differ "
43 		    "(%d != %d)\n", label, len1, len2);
44 		return 0;
45 	}
46 	if (memcmp(d1, d2, len1) != 0) {
47 		fprintf(stderr, "FAIL: %s - bytes differ\n", label);
48 		fprintf(stderr, "Got:\n");
49 		hexdump(d1, len1);
50 		fprintf(stderr, "Want:\n");
51 		hexdump(d2, len2);
52 		return 0;
53 	}
54 	return 1;
55 }
56 
57 /* Constructed octet string with length 12. */
58 const uint8_t asn1_constructed_basic_ber[] = {
59 	0x24, 0x0c,
60 	0x04, 0x01, 0x01,
61 	0x04, 0x02, 0x01, 0x02,
62 	0x04, 0x03, 0x01, 0x02, 0x03
63 };
64 const uint8_t asn1_constructed_basic_content[] = {
65 	0x01, 0x01, 0x02, 0x01, 0x02, 0x03,
66 };
67 
68 /* Nested constructed octet string. */
69 const uint8_t asn1_constructed_nested_ber[] = {
70 	0x24, 0x1a,
71 	0x04, 0x01, 0x01,
72 	0x24, 0x15,
73 	0x04, 0x02, 0x02, 0x03,
74 	0x24, 0x0f,
75 	0x24, 0x0d,
76 	0x04, 0x03, 0x04, 0x05, 0x06,
77 	0x24, 0x06,
78 	0x24, 0x04,
79 	0x04, 0x02, 0x07, 0x08,
80 };
81 const uint8_t asn1_constructed_nested_content[] = {
82 	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
83 };
84 
85 /* Deeply nested constructed octet string. */
86 const uint8_t asn1_constructed_deep_nested_ber[] = {
87 	0x24, 0x1b,
88 	0x04, 0x01, 0x01,
89 	0x24, 0x16,
90 	0x04, 0x02, 0x02, 0x03,
91 	0x24, 0x10,
92 	0x24, 0x0e,
93 	0x04, 0x03, 0x04, 0x05, 0x06,
94 	0x24, 0x07,
95 	0x24, 0x05,
96 	0x24, 0x03,
97 	0x04, 0x01, 0x07,
98 };
99 
100 /* Constructed octet string with indefinite length. */
101 const uint8_t asn1_constructed_indefinite_ber[] = {
102 	0x24, 0x80,
103 	0x04, 0x01, 0x01,
104 	0x04, 0x02, 0x01, 0x02,
105 	0x04, 0x03, 0x01, 0x02, 0x03,
106 	0x00, 0x00,
107 };
108 const uint8_t asn1_constructed_indefinite_content[] = {
109 	0x01, 0x01, 0x02, 0x01, 0x02, 0x03,
110 };
111 
112 struct asn1_constructed_test {
113 	const char *name;
114 	const uint8_t *asn1;
115 	size_t asn1_len;
116 	const uint8_t *want;
117 	size_t want_len;
118 	int want_error;
119 	int valid;
120 };
121 
122 const struct asn1_constructed_test asn1_constructed_tests[] = {
123 	{
124 		.name = "basic constructed",
125 		.asn1 = asn1_constructed_basic_ber,
126 		.asn1_len = sizeof(asn1_constructed_basic_ber),
127 		.want = asn1_constructed_basic_content,
128 		.want_len = sizeof(asn1_constructed_basic_content),
129 		.valid = 1,
130 	},
131 	{
132 		.name = "nested constructed",
133 		.asn1 = asn1_constructed_nested_ber,
134 		.asn1_len = sizeof(asn1_constructed_nested_ber),
135 		.want = asn1_constructed_nested_content,
136 		.want_len = sizeof(asn1_constructed_nested_content),
137 		.valid = 1,
138 	},
139 	{
140 		.name = "deep nested constructed",
141 		.asn1 = asn1_constructed_deep_nested_ber,
142 		.asn1_len = sizeof(asn1_constructed_deep_nested_ber),
143 		.want_error = ASN1_R_NESTED_ASN1_STRING,
144 		.valid = 0,
145 	},
146 	{
147 		.name = "indefinite length constructed",
148 		.asn1 = asn1_constructed_indefinite_ber,
149 		.asn1_len = sizeof(asn1_constructed_indefinite_ber),
150 		.want = asn1_constructed_indefinite_content,
151 		.want_len = sizeof(asn1_constructed_indefinite_content),
152 		.valid = 1,
153 	},
154 };
155 
156 #define N_CONSTRUCTED_TESTS \
157     (sizeof(asn1_constructed_tests) / sizeof(*asn1_constructed_tests))
158 
159 static int
do_asn1_constructed_test(const struct asn1_constructed_test * act)160 do_asn1_constructed_test(const struct asn1_constructed_test *act)
161 {
162 	ASN1_OCTET_STRING *aos = NULL;
163 	const uint8_t *p;
164 	long err;
165 	int failed = 1;
166 
167 	ERR_clear_error();
168 
169 	p = act->asn1;
170 	aos = d2i_ASN1_OCTET_STRING(NULL, &p, act->asn1_len);
171 	if (!act->valid) {
172 		if (aos != NULL) {
173 			fprintf(stderr, "FAIL: invalid ASN.1 decoded\n");
174 			goto failed;
175 		}
176 		if (act->want_error != 0) {
177 			err = ERR_peek_error();
178 			if (ERR_GET_REASON(err) != act->want_error) {
179 				fprintf(stderr, "FAIL: got error reason %d,"
180 				    "want %d", ERR_GET_REASON(err),
181 				    act->want_error);
182 				goto failed;
183 			}
184 		}
185 		goto done;
186 	}
187 	if (aos == NULL) {
188 		fprintf(stderr, "FAIL: failed to decode ASN.1 constructed "
189 		    "octet string\n");
190 		ERR_print_errors_fp(stderr);
191 		goto failed;
192 	}
193 	if (!asn1_compare_bytes(act->name, ASN1_STRING_data(aos),
194 	    ASN1_STRING_length(aos), act->want, act->want_len))
195 		goto failed;
196 
197  done:
198 	failed = 0;
199 
200  failed:
201 	ASN1_OCTET_STRING_free(aos);
202 
203 	return failed;
204 }
205 
206 static int
do_asn1_constructed_tests(void)207 do_asn1_constructed_tests(void)
208 {
209 	const struct asn1_constructed_test *act;
210 	int failed = 0;
211 	size_t i;
212 
213 	for (i = 0; i < N_CONSTRUCTED_TESTS; i++) {
214 		act = &asn1_constructed_tests[i];
215 		failed |= do_asn1_constructed_test(act);
216 	}
217 
218 	return failed;
219 }
220 
221 /* Sequence with length. */
222 const uint8_t asn1_sequence_ber[] = {
223 	0x30, 0x16,
224 	0x04, 0x01, 0x01,
225 	0x04, 0x02, 0x01, 0x02,
226 	0x04, 0x03, 0x01, 0x02, 0x03,
227 	0x30, 0x80, 0x04, 0x01, 0x01, 0x00, 0x00,
228 	0x04, 0x01, 0x01,
229 
230 	0x04, 0x01, 0x01, /* Trailing data. */
231 };
232 
233 const uint8_t asn1_sequence_content[] = {
234 	0x30, 0x16, 0x04, 0x01, 0x01, 0x04, 0x02, 0x01,
235 	0x02, 0x04, 0x03, 0x01, 0x02, 0x03, 0x30, 0x80,
236 	0x04, 0x01, 0x01, 0x00, 0x00, 0x04, 0x01, 0x01,
237 };
238 
239 /* Sequence with indefinite length. */
240 const uint8_t asn1_sequence_indefinite_ber[] = {
241 	0x30, 0x80,
242 	0x04, 0x01, 0x01,
243 	0x04, 0x02, 0x01, 0x02,
244 	0x04, 0x03, 0x01, 0x02, 0x03,
245 	0x30, 0x80, 0x04, 0x01, 0x01, 0x00, 0x00,
246 	0x04, 0x01, 0x01,
247 	0x00, 0x00,
248 
249 	0x04, 0x01, 0x01, /* Trailing data. */
250 };
251 
252 const uint8_t asn1_sequence_indefinite_content[] = {
253 	0x30, 0x80, 0x04, 0x01, 0x01, 0x04, 0x02, 0x01,
254 	0x02, 0x04, 0x03, 0x01, 0x02, 0x03, 0x30, 0x80,
255 	0x04, 0x01, 0x01, 0x00, 0x00, 0x04, 0x01, 0x01,
256 	0x00, 0x00,
257 };
258 
259 static int
do_asn1_sequence_string_tests(void)260 do_asn1_sequence_string_tests(void)
261 {
262 	ASN1_STRING *astr = NULL;
263 	const uint8_t *p;
264 	long len;
265 	int failed = 1;
266 
267 	ERR_clear_error();
268 
269 	/*
270 	 * Test decoding of sequence with length and indefinite length into
271 	 * a string - in this case the ASN.1 is not decoded and is stored
272 	 * directly as the content for the string.
273 	 */
274 	if ((astr = ASN1_STRING_new()) == NULL) {
275 		fprintf(stderr, "FAIL: ASN1_STRING_new() returned NULL\n");
276 		goto failed;
277 	}
278 
279 	p = asn1_sequence_ber;
280 	len = sizeof(asn1_sequence_ber);
281 	if (ASN1_item_d2i((ASN1_VALUE **)&astr, &p, len,
282 	    &ASN1_SEQUENCE_it) == NULL) {
283 		fprintf(stderr, "FAIL: failed to decode ASN1_SEQUENCE\n");
284 		ERR_print_errors_fp(stderr);
285 		goto failed;
286 	}
287 
288 	if (!asn1_compare_bytes("sequence", ASN1_STRING_data(astr),
289 	    ASN1_STRING_length(astr), asn1_sequence_content,
290 	    sizeof(asn1_sequence_content)))
291 		goto failed;
292 
293 	p = asn1_sequence_indefinite_ber;
294 	len = sizeof(asn1_sequence_indefinite_ber);
295 	if (ASN1_item_d2i((ASN1_VALUE **)&astr, &p, len,
296 	    &ASN1_SEQUENCE_it) == NULL) {
297 		fprintf(stderr, "FAIL: failed to decode ASN1_SEQUENCE\n");
298 		ERR_print_errors_fp(stderr);
299 		goto failed;
300 	}
301 
302 	if (!asn1_compare_bytes("sequence indefinite", ASN1_STRING_data(astr),
303 	    ASN1_STRING_length(astr), asn1_sequence_indefinite_content,
304 	    sizeof(asn1_sequence_indefinite_content)))
305 		goto failed;
306 
307 	failed = 0;
308 
309  failed:
310 	ASN1_STRING_free(astr);
311 
312 	return failed;
313 }
314 
315 int
main(int argc,char ** argv)316 main(int argc, char **argv)
317 {
318 	int failed = 0;
319 
320 	failed |= do_asn1_constructed_tests();
321 	failed |= do_asn1_sequence_string_tests();
322 
323 	return (failed);
324 }
325