xref: /openbsd/regress/lib/libcrypto/asn1/asn1oct.c (revision 9b0855c6)
1 /*	$OpenBSD: asn1oct.c,v 1.4 2023/05/13 07:17:32 tb Exp $ */
2 
3 /*
4  * Copyright (c) 2023 Theo Buehler <tb@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <assert.h>
20 #include <err.h>
21 #include <string.h>
22 
23 #include <openssl/asn1.h>
24 #include <openssl/x509v3.h>
25 
26 #define TESTBUFFER_SIZE		20
27 
28 static const struct i2s_asn1_octet_string_test {
29 	const char *desc;
30 	const uint8_t buf[TESTBUFFER_SIZE];
31 	long len;
32 	const char *want;
33 } i2s_test[] = {
34 	{
35 		.desc = "Empty buffer gives empty string",
36 		.buf = { 0x00, },
37 		.len = 0,
38 		.want = "",
39 	},
40 	{
41 		.desc = "all hex digits",
42 		.buf = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, },
43 		.len = 8,
44 		.want = "01:23:45:67:89:AB:CD:EF",
45 	},
46 	{
47 		.desc = "all hex digits, scrambled",
48 		.buf = { 0x98, 0x24, 0xbf, 0x3a, 0xc7, 0xd6, 0x01, 0x5e, },
49 		.len = 8,
50 		.want = "98:24:BF:3A:C7:D6:01:5E",
51 	},
52 	{
53 		.desc = "Embedded 0 byte",
54 		.buf = { 0x7a, 0x00, 0xbb, },
55 		.len = 3,
56 		.want = "7A:00:BB",
57 	},
58 	{
59 		.desc = "All zeroes",
60 		.buf = { 0x00, 0x00, 0x00, 0x00, 0x00, },
61 		.len = 4,
62 		.want = "00:00:00:00",
63 	},
64 	{
65 		.desc = "All bits set",
66 		.buf = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, },
67 		.len = 8,
68 		.want = "FF:FF:FF:FF:FF:FF:FF:FF",
69 	},
70 	{
71 		.desc = "negative length",
72 		.buf = { 0x00, },
73 		.len = -1,
74 	},
75 };
76 
77 #define N_I2S_TESTS (sizeof(i2s_test) / sizeof(i2s_test[0]))
78 
79 static int
test_i2s_ASN1_OCTET_STRING(const struct i2s_asn1_octet_string_test * test)80 test_i2s_ASN1_OCTET_STRING(const struct i2s_asn1_octet_string_test *test)
81 {
82 	ASN1_OCTET_STRING *aos = NULL;
83 	int should_fail = test->want == NULL;
84 	char *got = NULL;
85 	int failed = 0;
86 
87 	if ((aos = ASN1_OCTET_STRING_new()) == NULL)
88 		errx(1, "ASN1_OCTET_STRING_new");
89 
90 	if (!ASN1_STRING_set(aos, (void *)test->buf, test->len))
91 		errx(1, "ASN1_STRING_set");
92 
93 	if ((got = i2s_ASN1_OCTET_STRING(NULL, aos)) == NULL) {
94 		if (!should_fail)
95 			errx(1, "i2s_ASN1_OCTET_STRING");
96 	}
97 
98 	if (!should_fail && strcmp(test->want, got) != 0) {
99 		fprintf(stderr, "%s: \"%s\" failed: want \"%s\", got \"%s\"\n",
100 		    __func__, test->desc, test->want, got);
101 		failed |= 1;
102 	}
103 
104 	ASN1_OCTET_STRING_free(aos);
105 	free(got);
106 
107 	return failed;
108 }
109 
110 static int
test_new_ASN1_OCTET_STRING(void)111 test_new_ASN1_OCTET_STRING(void)
112 {
113 	ASN1_OCTET_STRING *aos = NULL;
114 	char *got;
115 	int failed = 0;
116 
117 	if ((aos = ASN1_OCTET_STRING_new()) == NULL)
118 		errx(1, "%s: ASN1_OCTET_STRING_new", __func__);
119 	if ((got = i2s_ASN1_OCTET_STRING(NULL, aos)) == NULL)
120 		errx(1, "%s: i2s_ASN1_OCTET_STRING", __func__);
121 
122 	if (strcmp("", got) != 0) {
123 		fprintf(stderr, "%s failed: want \"\", got \"%s\"\n",
124 		    __func__, got);
125 		failed |= 1;
126 	}
127 
128 	ASN1_OCTET_STRING_free(aos);
129 	free(got);
130 
131 	return failed;
132 }
133 
134 static int
run_i2s_ASN1_OCTET_STRING_tests(void)135 run_i2s_ASN1_OCTET_STRING_tests(void)
136 {
137 	size_t i;
138 	int failed = 0;
139 
140 	failed |= test_new_ASN1_OCTET_STRING();
141 
142 	for (i = 0; i < N_I2S_TESTS; i++)
143 		failed |= test_i2s_ASN1_OCTET_STRING(&i2s_test[i]);
144 
145 	return failed;
146 }
147 
148 static const struct s2i_asn1_octet_string_test {
149 	const char *desc;
150 	const char *in;
151 	const char *want;
152 } s2i_test[] = {
153 	/* Tests that should succeed. */
154 	{
155 		.desc = "empty string",
156 		.in = "",
157 		.want = "",
158 	},
159 	{
160 		.desc = "only colons",
161 		.in = ":::::::",
162 		.want = "",
163 	},
164 	{
165 		.desc = "a 0 octet",
166 		.in = "00",
167 		.want = "00",
168 	},
169 	{
170 		.desc = "a 0 octet with stupid colons",
171 		.in = ":::00:::::",
172 		.want = "00",
173 	},
174 	{
175 		.desc = "more stupid colons",
176 		.in = ":::C0fF::Ee:::::",
177 		.want = "C0:FF:EE",
178 	},
179 	{
180 		.desc = "all hex digits",
181 		.in = "0123456789abcdef",
182 		.want = "01:23:45:67:89:AB:CD:EF",
183 	},
184 
185 	/* Tests that should fail. */
186 	{
187 		.desc = "colons between hex digits",
188 		.in = "A:F",
189 	},
190 	{
191 		.desc = "more colons between hex digits",
192 		.in = "5:7",
193 	},
194 	{
195 		.desc = "one hex digit",
196 		.in = "1",
197 	},
198 	{
199 		.desc = "three hex digits",
200 		.in = "bad",
201 	},
202 	{
203 		.desc = "three hex digits, colon after first digit",
204 		.in = "b:ad",
205 	},
206 	{
207 		.desc = "three hex digits, colon after second digit",
208 		.in = "ba:d",
209 	},
210 	{
211 		.desc = "non-hex digit",
212 		.in = "g00d",
213 	},
214 	{
215 		.desc = "non-hex digits",
216 		.in = "d0gged",
217 	},
218 	{
219 		.desc = "trailing non-hex digit",
220 		.in = "d00der",
221 	},
222 };
223 
224 #define N_S2I_TESTS (sizeof(s2i_test) / sizeof(s2i_test[0]))
225 
226 static int
test_s2i_ASN1_OCTET_STRING(const struct s2i_asn1_octet_string_test * test)227 test_s2i_ASN1_OCTET_STRING(const struct s2i_asn1_octet_string_test *test)
228 {
229 	ASN1_OCTET_STRING *aos = NULL;
230 	char *got = NULL;
231 	int should_fail = test->want == NULL;
232 	int failed = 0;
233 
234 	if ((aos = s2i_ASN1_OCTET_STRING(NULL, NULL, test->in)) == NULL) {
235 		if (!should_fail)
236 			errx(1, "%s: s2i_ASN1_OCTET_STRING", test->desc);
237 		goto done;
238 	}
239 
240 	if ((got = i2s_ASN1_OCTET_STRING(NULL, aos)) == NULL)
241 		errx(1, "%s: i2s_ASN1_OCTET_STRING", test->desc);
242 
243 	assert(test->want != NULL);
244 	if (strcmp(test->want, got) != 0) {
245 		fprintf(stderr, "%s: \"%s\" failed: want \"%s\", got \"%s\"\n",
246 		    __func__, test->desc, test->want, got);
247 		failed |= 1;
248 	}
249 
250  done:
251 	ASN1_OCTET_STRING_free(aos);
252 	free(got);
253 
254 	return failed;
255 }
256 
257 static int
run_s2i_ASN1_OCTET_STRING_tests(void)258 run_s2i_ASN1_OCTET_STRING_tests(void)
259 {
260 	size_t i;
261 	int failed = 0;
262 
263 	failed |= test_new_ASN1_OCTET_STRING();
264 
265 	for (i = 0; i < N_S2I_TESTS; i++)
266 		failed |= test_s2i_ASN1_OCTET_STRING(&s2i_test[i]);
267 
268 	return failed;
269 }
270 
271 int
main(void)272 main(void)
273 {
274 	int failed = 0;
275 
276 	failed |= run_i2s_ASN1_OCTET_STRING_tests();
277 	failed |= run_s2i_ASN1_OCTET_STRING_tests();
278 
279 	return failed;
280 }
281