xref: /openbsd-src/regress/lib/libcrypto/asn1/asn1basic.c (revision 9badb9ad8932c12f4ece484255eb2703a2518c17)
1 /* $OpenBSD: asn1basic.c,v 1.7 2022/06/25 13:57:17 jsing 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 
20 #include <err.h>
21 #include <stdio.h>
22 #include <string.h>
23 
24 #include "asn1_locl.h"
25 
26 static void
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
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 		    "(%i != %i)\n", label, len1, len2);
44 		fprintf(stderr, "Got:\n");
45 		hexdump(d1, len1);
46 		fprintf(stderr, "Want:\n");
47 		hexdump(d2, len2);
48 		return 0;
49 	}
50 	if (memcmp(d1, d2, len1) != 0) {
51 		fprintf(stderr, "FAIL: %s - bytes differ\n", label);
52 		fprintf(stderr, "Got:\n");
53 		hexdump(d1, len1);
54 		fprintf(stderr, "Want:\n");
55 		hexdump(d2, len2);
56 		return 0;
57 	}
58 	return 1;
59 }
60 
61 const uint8_t asn1_bit_string_primitive[] = {
62 	0x03, 0x07,
63 	0x04, 0x0a, 0x3b, 0x5f, 0x29, 0x1c, 0xd0,
64 };
65 
66 static int
67 asn1_bit_string_test(void)
68 {
69 	uint8_t bs[] = {0x0a, 0x3b, 0x5f, 0x29, 0x1c, 0xd0};
70 	ASN1_BIT_STRING *abs;
71 	uint8_t *p = NULL, *pp;
72 	const uint8_t *q;
73 	int bit, i, len;
74 	int failed = 1;
75 
76 	if ((abs = ASN1_BIT_STRING_new()) == NULL) {
77 		fprintf(stderr, "FAIL: ASN1_BIT_STRING_new() == NULL\n");
78 		goto failed;
79 	}
80 	if (!ASN1_BIT_STRING_set(abs, bs, sizeof(bs))) {
81 		fprintf(stderr, "FAIL: failed to set bit string\n");
82 		goto failed;
83 	}
84 
85 	if ((len = i2d_ASN1_BIT_STRING(abs, NULL)) < 0) {
86 		fprintf(stderr, "FAIL: i2d_ASN1_BIT_STRING with NULL\n");
87 		goto failed;
88 	}
89 	if ((p = malloc(len)) == NULL)
90 		errx(1, "malloc");
91 	memset(p, 0xbd, len);
92 	pp = p;
93 	if ((i2d_ASN1_BIT_STRING(abs, &pp)) != len) {
94 		fprintf(stderr, "FAIL: i2d_ASN1_BIT_STRING\n");
95 		goto failed;
96 	}
97 
98 	if (!asn1_compare_bytes("BIT_STRING", p, len, asn1_bit_string_primitive,
99 	    sizeof(asn1_bit_string_primitive)))
100 		goto failed;
101 
102 	/* Test primitive decoding. */
103 	q = p;
104 	if (d2i_ASN1_BIT_STRING(&abs, &q, len) == NULL) {
105 		fprintf(stderr, "FAIL: d2i_ASN1_BIT_STRING primitive\n");
106 		goto failed;
107 	}
108 	if (!asn1_compare_bytes("BIT_STRING primitive data", abs->data, abs->length,
109 	    bs, sizeof(bs)))
110 		goto failed;
111 
112 	/* Test ASN1_BIT_STRING_get_bit(). */
113 	for (i = 0; i < ((int)sizeof(bs) * 8); i++) {
114 		bit = (bs[i / 8] >> (7 - i % 8)) & 1;
115 
116 		if (ASN1_BIT_STRING_get_bit(abs, i) != bit) {
117 			fprintf(stderr, "FAIL: ASN1_BIT_STRING_get_bit(_, %d) "
118 			    "= %d, want %d\n", i,
119 			    ASN1_BIT_STRING_get_bit(abs, i), bit);
120 			goto failed;
121 		}
122 	}
123 
124 	/* Test ASN1_BIT_STRING_set_bit(). */
125 	for (i = 0; i < ((int)sizeof(bs) * 8); i++) {
126 		if (!ASN1_BIT_STRING_set_bit(abs, i, 1)) {
127 			fprintf(stderr, "FAIL: ASN1_BIT_STRING_set_bit 1\n");
128 			goto failed;
129 		}
130 	}
131 	for (i = ((int)sizeof(bs) * 8) - 1; i >= 0; i--) {
132 		bit = (bs[i / 8] >> (7 - i % 8)) & 1;
133 		if (bit == 1)
134 			continue;
135 		if (!ASN1_BIT_STRING_set_bit(abs, i, 0)) {
136 			fprintf(stderr, "FAIL: ASN1_BIT_STRING_set_bit\n");
137 			goto failed;
138 		}
139 	}
140 
141 	if ((i2d_ASN1_BIT_STRING(abs, NULL)) != len) {
142 		fprintf(stderr, "FAIL: i2d_ASN1_BIT_STRING\n");
143 		goto failed;
144 	}
145 
146 	memset(p, 0xbd, len);
147 	pp = p;
148 	if ((i2d_ASN1_BIT_STRING(abs, &pp)) != len) {
149 		fprintf(stderr, "FAIL: i2d_ASN1_BIT_STRING\n");
150 		goto failed;
151 	}
152 
153 	if (!asn1_compare_bytes("BIT_STRING set", p, len, asn1_bit_string_primitive,
154 	    sizeof(asn1_bit_string_primitive)))
155 		goto failed;
156 
157 	failed = 0;
158 
159  failed:
160 	ASN1_BIT_STRING_free(abs);
161 	free(p);
162 
163 	return failed;
164 }
165 
166 const uint8_t asn1_boolean_false[] = {
167 	0x01, 0x01, 0x00,
168 };
169 const uint8_t asn1_boolean_true[] = {
170 	0x01, 0x01, 0x01,
171 };
172 
173 static int
174 asn1_boolean_test(void)
175 {
176 	uint8_t *p = NULL, *pp;
177 	const uint8_t *q;
178 	int len;
179 	int failed = 1;
180 
181 	if ((len = i2d_ASN1_BOOLEAN(0, NULL)) < 0) {
182 		fprintf(stderr, "FAIL: i2d_ASN1_BOOLEAN false with NULL\n");
183 		goto failed;
184 	}
185 	if ((p = malloc(len)) == NULL)
186 		errx(1, "calloc");
187 	memset(p, 0xbd, len);
188 	pp = p;
189 	if ((i2d_ASN1_BOOLEAN(0, &pp)) != len) {
190 		fprintf(stderr, "FAIL: i2d_ASN1_BOOLEAN false\n");
191 		goto failed;
192 	}
193 
194 	if (!asn1_compare_bytes("BOOLEAN false", p, len, asn1_boolean_false,
195 	    sizeof(asn1_boolean_false)))
196 		goto failed;
197 
198 	q = p;
199 	if (d2i_ASN1_BOOLEAN(NULL, &q, len) != 0) {
200 		fprintf(stderr, "FAIL: BOOLEAN false did not decode to 0\n");
201 		goto failed;
202 	}
203 
204 	free(p);
205 	p = NULL;
206 
207 	if ((len = i2d_ASN1_BOOLEAN(1, NULL)) < 0) {
208 		fprintf(stderr, "FAIL: i2d_ASN1_BOOLEAN true with NULL\n");
209 		goto failed;
210 	}
211 	if ((p = calloc(1, len)) == NULL)
212 		errx(1, "calloc");
213 	pp = p;
214 	if ((i2d_ASN1_BOOLEAN(1, &pp)) != len) {
215 		fprintf(stderr, "FAIL: i2d_ASN1_BOOLEAN true\n");
216 		goto failed;
217 	}
218 
219 	if (!asn1_compare_bytes("BOOLEAN true", p, len, asn1_boolean_true,
220 	    sizeof(asn1_boolean_true)))
221 		goto failed;
222 
223 	q = p;
224 	if (d2i_ASN1_BOOLEAN(NULL, &q, len) != 1) {
225 		fprintf(stderr, "FAIL: BOOLEAN true did not decode to 1\n");
226 		goto failed;
227 	}
228 
229 	failed = 0;
230 
231  failed:
232 	free(p);
233 
234 	return failed;
235 }
236 
237 struct asn1_integer_test {
238 	long value;
239 	uint8_t content[64];
240 	size_t content_len;
241 	int content_neg;
242 	uint8_t der[64];
243 	size_t der_len;
244 	int want_error;
245 };
246 
247 struct asn1_integer_test asn1_integer_tests[] = {
248 	{
249 		.value = 0,
250 		.content = {0x00},
251 		.content_len = 1,
252 		.der = {0x02, 0x01, 0x00},
253 		.der_len = 3,
254 	},
255 	{
256 		.value = 1,
257 		.content = {0x01},
258 		.content_len = 1,
259 		.der = {0x02, 0x01, 0x01},
260 		.der_len = 3,
261 	},
262 	{
263 		.value = -1,
264 		.content = {0x01},
265 		.content_len = 1,
266 		.content_neg = 1,
267 		.der = {0x02, 0x01, 0xff},
268 		.der_len = 3,
269 	},
270 	{
271 		.value = 127,
272 		.content = {0x7f},
273 		.content_len = 1,
274 		.der = {0x02, 0x01, 0x7f},
275 		.der_len = 3,
276 	},
277 	{
278 		.value = -127,
279 		.content = {0x7f},
280 		.content_len = 1,
281 		.content_neg = 1,
282 		.der = {0x02, 0x01, 0x81},
283 		.der_len = 3,
284 	},
285 	{
286 		.value = 128,
287 		.content = {0x80},
288 		.content_len = 1,
289 		.der = {0x02, 0x02, 0x00, 0x80},
290 		.der_len = 4,
291 	},
292 	{
293 		.value = -128,
294 		.content = {0x80},
295 		.content_len = 1,
296 		.content_neg = 1,
297 		.der = {0x02, 0x01, 0x80},
298 		.der_len = 3,
299 	},
300 	{
301 		/* 2^64 */
302 		.content = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
303 		.content_len = 9,
304 		.der = {0x02, 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
305 		.der_len = 11,
306 	},
307 	{
308 		/* -2^64 */
309 		.content = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
310 		.content_len = 9,
311 		.content_neg = 1,
312 		.der = {0x02, 0x09, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
313 		.der_len = 11,
314 	},
315 	{
316 		/* Invalid length. */
317 		.der = {0x02, 0x00},
318 		.der_len = 2,
319 		.want_error = 1,
320 	},
321 	{
322 		/* Invalid padding. */
323 		.der = {0x02, 0x09, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
324 		.der_len = 11,
325 		.want_error = 1,
326 	},
327 	{
328 		/* Invalid padding. */
329 		.der = {0x02, 0x09, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
330 		.der_len = 11,
331 		.want_error = 1,
332 	},
333 };
334 
335 #define N_ASN1_INTEGER_TESTS \
336     (sizeof(asn1_integer_tests) / sizeof(*asn1_integer_tests))
337 
338 static int
339 asn1_integer_set_test(struct asn1_integer_test *ait)
340 {
341 	ASN1_INTEGER *aint = NULL;
342 	uint8_t *p = NULL, *pp;
343 	int len;
344 	int failed = 1;
345 
346 	if ((aint = ASN1_INTEGER_new()) == NULL) {
347 		fprintf(stderr, "FAIL: ASN1_INTEGER_new() == NULL\n");
348 		goto failed;
349 	}
350 	if (!ASN1_INTEGER_set(aint, ait->value)) {
351 		fprintf(stderr, "FAIL: ASN1_INTEGER_(%ld) failed\n",
352 		    ait->value);
353 		goto failed;
354 	}
355 	if (ait->value != 0 &&
356 	    !asn1_compare_bytes("INTEGER set", aint->data, aint->length,
357 	    ait->content, ait->content_len))
358 		goto failed;
359 	if (ait->content_neg && aint->type != V_ASN1_NEG_INTEGER) {
360 		fprintf(stderr, "FAIL: Not V_ASN1_NEG_INTEGER\n");
361 		goto failed;
362 	}
363 	if ((len = i2d_ASN1_INTEGER(aint, NULL)) < 0) {
364 		fprintf(stderr, "FAIL: i2d_ASN1_INTEGER() failed\n");
365 		goto failed;
366 	}
367 	if ((p = malloc(len)) == NULL)
368 		errx(1, "malloc");
369 	memset(p, 0xbd, len);
370 	pp = p;
371 	if ((len = i2d_ASN1_INTEGER(aint, &pp)) < 0) {
372 		fprintf(stderr, "FAIL: i2d_ASN1_INTEGER() failed\n");
373 		goto failed;
374 	}
375 	if (!asn1_compare_bytes("INTEGER set", p, len, ait->der,
376 	    ait->der_len))
377 		goto failed;
378 
379 	failed = 0;
380 
381  failed:
382 	ASN1_INTEGER_free(aint);
383 	free(p);
384 
385 	return failed;
386 }
387 
388 static int
389 asn1_integer_content_test(struct asn1_integer_test *ait)
390 {
391 	ASN1_INTEGER *aint = NULL;
392 	uint8_t *p = NULL, *pp;
393 	int len;
394 	int failed = 1;
395 
396 	if ((aint = ASN1_INTEGER_new()) == NULL) {
397 		fprintf(stderr, "FAIL: ASN1_INTEGER_new() == NULL\n");
398 		goto failed;
399 	}
400 	if ((aint->data = malloc(ait->content_len)) == NULL)
401 		errx(1, "malloc");
402 	memcpy(aint->data, ait->content, ait->content_len);
403 	aint->length = ait->content_len;
404 	if (ait->content_neg)
405 		aint->type = V_ASN1_NEG_INTEGER;
406 
407 	if ((len = i2d_ASN1_INTEGER(aint, NULL)) < 0) {
408 		fprintf(stderr, "FAIL: i2d_ASN1_INTEGER() failed\n");
409 		goto failed;
410 	}
411 	if ((p = malloc(len)) == NULL)
412 		errx(1, "malloc");
413 	memset(p, 0xbd, len);
414 	pp = p;
415 	if ((len = i2d_ASN1_INTEGER(aint, &pp)) < 0) {
416 		fprintf(stderr, "FAIL: i2d_ASN1_INTEGER() failed\n");
417 		goto failed;
418 	}
419 	if (!asn1_compare_bytes("INTEGER content", p, len, ait->der,
420 	    ait->der_len))
421 		goto failed;
422 
423 	failed = 0;
424 
425  failed:
426 	ASN1_INTEGER_free(aint);
427 	free(p);
428 
429 	return failed;
430 }
431 
432 static int
433 asn1_integer_decode_test(struct asn1_integer_test *ait)
434 {
435 	ASN1_INTEGER *aint = NULL;
436 	const uint8_t *q;
437 	int failed = 1;
438 
439 	q = ait->der;
440 	if (d2i_ASN1_INTEGER(&aint, &q, ait->der_len) != NULL) {
441 		if (ait->want_error != 0) {
442 			fprintf(stderr, "FAIL: INTEGER decoded when it should "
443 			    "have failed\n");
444 			goto failed;
445 		}
446 		if (!asn1_compare_bytes("INTEGER content", aint->data,
447 		    aint->length, ait->content, ait->content_len))
448 			goto failed;
449 	} else if (ait->want_error == 0) {
450 		fprintf(stderr, "FAIL: INTEGER failed to decode\n");
451 		goto failed;
452 	}
453 
454 	failed = 0;
455 
456  failed:
457 	ASN1_INTEGER_free(aint);
458 
459 	return failed;
460 }
461 
462 static int
463 asn1_integer_cmp_test(void)
464 {
465 	ASN1_INTEGER *a = NULL, *b = NULL;
466 	int failed = 1;
467 
468 	if ((a = ASN1_INTEGER_new()) == NULL)
469 		goto failed;
470 	if ((b = ASN1_INTEGER_new()) == NULL)
471 		goto failed;
472 
473 	if (ASN1_INTEGER_cmp(a, b) != 0) {
474 		fprintf(stderr, "FAIL: INTEGER 0 == 0");
475 		goto failed;
476 	}
477 
478 	if (!ASN1_INTEGER_set(b, 1)) {
479 		fprintf(stderr, "FAIL: failed to set INTEGER");
480 		goto failed;
481 	}
482 	if (ASN1_INTEGER_cmp(a, b) >= 0) {
483 		fprintf(stderr, "FAIL: INTEGER 0 < 1");
484 		goto failed;
485 	}
486 	if (ASN1_INTEGER_cmp(b, a) <= 0) {
487 		fprintf(stderr, "FAIL: INTEGER 1 > 0");
488 		goto failed;
489 	}
490 
491 	if (!ASN1_INTEGER_set(b, -1)) {
492 		fprintf(stderr, "FAIL: failed to set INTEGER");
493 		goto failed;
494 	}
495 	if (ASN1_INTEGER_cmp(a, b) <= 0) {
496 		fprintf(stderr, "FAIL: INTEGER 0 > -1");
497 		goto failed;
498 	}
499 	if (ASN1_INTEGER_cmp(b, a) >= 0) {
500 		fprintf(stderr, "FAIL: INTEGER -1 < 0");
501 		goto failed;
502 	}
503 
504 	if (!ASN1_INTEGER_set(a, 1)) {
505 		fprintf(stderr, "FAIL: failed to set INTEGER");
506 		goto failed;
507 	}
508 	if (ASN1_INTEGER_cmp(a, b) <= 0) {
509 		fprintf(stderr, "FAIL: INTEGER 1 > -1");
510 		goto failed;
511 	}
512 	if (ASN1_INTEGER_cmp(b, a) >= 0) {
513 		fprintf(stderr, "FAIL: INTEGER -1 < 1");
514 		goto failed;
515 	}
516 
517 	if (!ASN1_INTEGER_set(b, 1)) {
518 		fprintf(stderr, "FAIL: failed to set INTEGER");
519 		goto failed;
520 	}
521 	if (ASN1_INTEGER_cmp(a, b) != 0) {
522 		fprintf(stderr, "FAIL: INTEGER 1 == 1");
523 		goto failed;
524 	}
525 
526 	failed = 0;
527 
528  failed:
529 	ASN1_INTEGER_free(a);
530 	ASN1_INTEGER_free(b);
531 
532 	return failed;
533 }
534 
535 static int
536 asn1_integer_test(void)
537 {
538 	struct asn1_integer_test *ait;
539 	int failed = 0;
540 	size_t i;
541 
542 	for (i = 0; i < N_ASN1_INTEGER_TESTS; i++) {
543 		ait = &asn1_integer_tests[i];
544 		if (ait->content_len > 0 && ait->content_len <= 4)
545 			failed |= asn1_integer_set_test(ait);
546 		if (ait->content_len > 0)
547 			failed |= asn1_integer_content_test(ait);
548 		failed |= asn1_integer_decode_test(ait);
549 	}
550 
551 	failed |= asn1_integer_cmp_test();
552 
553 	return failed;
554 }
555 
556 int
557 main(int argc, char **argv)
558 {
559 	int failed = 0;
560 
561 	failed |= asn1_bit_string_test();
562 	failed |= asn1_boolean_test();
563 	failed |= asn1_integer_test();
564 
565 	return (failed);
566 }
567