diff options
author | jsing <> | 2022-02-26 16:45:31 +0000 |
---|---|---|
committer | jsing <> | 2022-02-26 16:45:31 +0000 |
commit | e7a4c5c29f0809ffb65ae98c57b691e57987c9db (patch) | |
tree | 22681111a48c5d66c0343de2753ce438e3e0019c | |
parent | c5273921395aa49c913ac5a1325c7eb78a50292c (diff) | |
download | openbsd-e7a4c5c29f0809ffb65ae98c57b691e57987c9db.tar.gz openbsd-e7a4c5c29f0809ffb65ae98c57b691e57987c9db.tar.bz2 openbsd-e7a4c5c29f0809ffb65ae98c57b691e57987c9db.zip |
Add regress coverage for ASN1_OBJECT public interfaces.
-rw-r--r-- | src/regress/lib/libcrypto/asn1/Makefile | 3 | ||||
-rw-r--r-- | src/regress/lib/libcrypto/asn1/asn1object.c | 397 |
2 files changed, 399 insertions, 1 deletions
diff --git a/src/regress/lib/libcrypto/asn1/Makefile b/src/regress/lib/libcrypto/asn1/Makefile index 44de13520a..0cb0c58d95 100644 --- a/src/regress/lib/libcrypto/asn1/Makefile +++ b/src/regress/lib/libcrypto/asn1/Makefile | |||
@@ -1,10 +1,11 @@ | |||
1 | # $OpenBSD: Makefile,v 1.15 2022/01/14 09:38:50 tb Exp $ | 1 | # $OpenBSD: Makefile,v 1.16 2022/02/26 16:45:31 jsing Exp $ |
2 | 2 | ||
3 | PROGS = \ | 3 | PROGS = \ |
4 | asn1api \ | 4 | asn1api \ |
5 | asn1basic \ | 5 | asn1basic \ |
6 | asn1complex \ | 6 | asn1complex \ |
7 | asn1evp \ | 7 | asn1evp \ |
8 | asn1object \ | ||
8 | asn1string_copy \ | 9 | asn1string_copy \ |
9 | asn1time \ | 10 | asn1time \ |
10 | asn1x509 \ | 11 | asn1x509 \ |
diff --git a/src/regress/lib/libcrypto/asn1/asn1object.c b/src/regress/lib/libcrypto/asn1/asn1object.c new file mode 100644 index 0000000000..8a21ec39fb --- /dev/null +++ b/src/regress/lib/libcrypto/asn1/asn1object.c | |||
@@ -0,0 +1,397 @@ | |||
1 | /* $OpenBSD: asn1object.c,v 1.1 2022/02/26 16:45:31 jsing Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2017, 2021, 2022 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/err.h> | ||
20 | |||
21 | #include <err.h> | ||
22 | #include <stdio.h> | ||
23 | #include <string.h> | ||
24 | |||
25 | #include "asn1_locl.h" | ||
26 | |||
27 | static void | ||
28 | hexdump(const unsigned char *buf, size_t len) | ||
29 | { | ||
30 | size_t i; | ||
31 | |||
32 | for (i = 1; i <= len; i++) | ||
33 | fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); | ||
34 | |||
35 | fprintf(stderr, "\n"); | ||
36 | } | ||
37 | |||
38 | static int | ||
39 | asn1_compare_bytes(const char *label, const unsigned char *d1, int len1, | ||
40 | const unsigned char *d2, int len2) | ||
41 | { | ||
42 | if (len1 != len2) { | ||
43 | fprintf(stderr, "FAIL: %s - byte lengths differ " | ||
44 | "(%i != %i)\n", label, len1, len2); | ||
45 | fprintf(stderr, "Got:\n"); | ||
46 | hexdump(d1, len1); | ||
47 | fprintf(stderr, "Want:\n"); | ||
48 | hexdump(d2, len2); | ||
49 | return 0; | ||
50 | } | ||
51 | if (memcmp(d1, d2, len1) != 0) { | ||
52 | fprintf(stderr, "FAIL: %s - bytes differ\n", label); | ||
53 | fprintf(stderr, "Got:\n"); | ||
54 | hexdump(d1, len1); | ||
55 | fprintf(stderr, "Want:\n"); | ||
56 | hexdump(d2, len2); | ||
57 | return 0; | ||
58 | } | ||
59 | return 1; | ||
60 | } | ||
61 | |||
62 | struct asn1_object_test { | ||
63 | const char *oid; | ||
64 | const char *txt; | ||
65 | const uint8_t content[255]; | ||
66 | size_t content_len; | ||
67 | const uint8_t der[255]; | ||
68 | size_t der_len; | ||
69 | int want_error; | ||
70 | }; | ||
71 | |||
72 | struct asn1_object_test asn1_object_tests[] = { | ||
73 | { | ||
74 | .oid = "2.5.4.10", | ||
75 | .txt = "organizationName", | ||
76 | .content = { | ||
77 | 0x55, 0x04, 0x0a, | ||
78 | }, | ||
79 | .content_len = 3, | ||
80 | .der = { | ||
81 | 0x06, 0x03, 0x55, 0x04, 0x0a, | ||
82 | }, | ||
83 | .der_len = 5, | ||
84 | }, | ||
85 | { | ||
86 | .oid = "2 5 4 10", | ||
87 | .txt = "organizationName", | ||
88 | .content = { | ||
89 | 0x55, 0x04, 0x0a, | ||
90 | }, | ||
91 | .content_len = 3, | ||
92 | .der = { | ||
93 | 0x06, 0x03, 0x55, 0x04, 0x0a, | ||
94 | }, | ||
95 | .der_len = 5, | ||
96 | }, | ||
97 | { | ||
98 | .oid = "1.3.6.1.4.1.11129.2.4.5", | ||
99 | .txt = "CT Certificate SCTs", | ||
100 | .content = { | ||
101 | 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, | ||
102 | 0x04, 0x05, | ||
103 | }, | ||
104 | .content_len = 10, | ||
105 | .der = { | ||
106 | 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, | ||
107 | 0x79, 0x02, 0x04, 0x05, | ||
108 | }, | ||
109 | .der_len = 12, | ||
110 | }, | ||
111 | { | ||
112 | .oid = "2..5.4.10", | ||
113 | .content = { | ||
114 | 0x00, 0x00, 0x00, 0x00, | ||
115 | }, | ||
116 | .content_len = 4, | ||
117 | .der = { | ||
118 | 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, | ||
119 | }, | ||
120 | .der_len = 6, | ||
121 | .want_error = 0, /* XXX */ | ||
122 | }, | ||
123 | { | ||
124 | .oid = "2.5..4.10", | ||
125 | .content = { | ||
126 | 0x00, 0x00, 0x00, 0x00, | ||
127 | }, | ||
128 | .content_len = 4, | ||
129 | .der = { | ||
130 | 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, | ||
131 | }, | ||
132 | .der_len = 6, | ||
133 | .want_error = 0, /* XXX */ | ||
134 | }, | ||
135 | { | ||
136 | .oid = "2.5.4..10", | ||
137 | .content = { | ||
138 | 0x00, 0x00, 0x00, 0x00, | ||
139 | }, | ||
140 | .content_len = 4, | ||
141 | .der = { | ||
142 | 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, | ||
143 | }, | ||
144 | .der_len = 6, | ||
145 | .want_error = 0, /* XXX */ | ||
146 | }, | ||
147 | { | ||
148 | .oid = "2.5.4.10.", | ||
149 | .content = { | ||
150 | 0x00, 0x00, 0x00, | ||
151 | }, | ||
152 | .content_len = 3, | ||
153 | .der = { | ||
154 | 0x06, 0x03, 0x00, 0x00, 0x00, | ||
155 | }, | ||
156 | .der_len = 5, | ||
157 | .want_error = 0, /* XXX */ | ||
158 | }, | ||
159 | { | ||
160 | .oid = "3.5.4.10", | ||
161 | .want_error = ASN1_R_FIRST_NUM_TOO_LARGE, | ||
162 | }, | ||
163 | { | ||
164 | .oid = "2", | ||
165 | .want_error = ASN1_R_MISSING_SECOND_NUMBER, | ||
166 | }, | ||
167 | { | ||
168 | .oid = "2,5,4,10", | ||
169 | .want_error = ASN1_R_INVALID_SEPARATOR, | ||
170 | }, | ||
171 | }; | ||
172 | |||
173 | #define N_ASN1_OBJECT_TESTS \ | ||
174 | (sizeof(asn1_object_tests) / sizeof(*asn1_object_tests)) | ||
175 | |||
176 | static int | ||
177 | do_asn1_object_test(struct asn1_object_test *aot) | ||
178 | { | ||
179 | ASN1_OBJECT *aobj = NULL; | ||
180 | uint8_t buf[1024]; | ||
181 | const uint8_t *p; | ||
182 | uint8_t *q; | ||
183 | int err, ret; | ||
184 | int failed = 1; | ||
185 | |||
186 | ERR_clear_error(); | ||
187 | |||
188 | ret = a2d_ASN1_OBJECT(buf, sizeof(buf), aot->oid, -1); | ||
189 | if (ret < 0 || (size_t)ret != aot->content_len) { | ||
190 | fprintf(stderr, "FAIL: a2d_ASN1_OBJECT() = %d, want %zu\n", | ||
191 | ret, aot->content_len); | ||
192 | goto failed; | ||
193 | } | ||
194 | if (aot->content_len == 0) { | ||
195 | err = ERR_peek_error(); | ||
196 | if (ERR_GET_REASON(err) != aot->want_error) { | ||
197 | fprintf(stderr, "FAIL: Got error reason %d, " | ||
198 | "want %d\n", ERR_GET_REASON(err), | ||
199 | aot->want_error); | ||
200 | goto failed; | ||
201 | } | ||
202 | goto done; | ||
203 | } | ||
204 | |||
205 | p = aot->content; | ||
206 | if ((aobj = c2i_ASN1_OBJECT(NULL, &p, aot->content_len)) == NULL) { | ||
207 | fprintf(stderr, "FAIL: c2i_ASN1_OBJECT() failed\n"); | ||
208 | goto failed; | ||
209 | } | ||
210 | |||
211 | q = buf; | ||
212 | ret = i2d_ASN1_OBJECT(aobj, &q); | ||
213 | if (!asn1_compare_bytes("ASN1_OBJECT DER", buf, ret, aot->der, | ||
214 | aot->der_len)) | ||
215 | goto failed; | ||
216 | |||
217 | ASN1_OBJECT_free(aobj); | ||
218 | aobj = NULL; | ||
219 | |||
220 | p = aot->der; | ||
221 | if ((aobj = d2i_ASN1_OBJECT(NULL, &p, aot->der_len)) == NULL) { | ||
222 | fprintf(stderr, "FAIL: d2i_ASN1_OBJECT() failed\n"); | ||
223 | goto failed; | ||
224 | } | ||
225 | |||
226 | if (aot->txt != NULL) { | ||
227 | ret = i2t_ASN1_OBJECT(buf, sizeof(buf), aobj); | ||
228 | if (ret <= 0 || (size_t)ret >= sizeof(buf)) { | ||
229 | fprintf(stderr, "FAIL: i2t_ASN1_OBJECT() failed\n"); | ||
230 | goto failed; | ||
231 | } | ||
232 | if (strcmp(aot->txt, buf) != 0) { | ||
233 | fprintf(stderr, "FAIL: i2t_ASN1_OBJECT() = '%s', " | ||
234 | "want '%s'\n", buf, aot->txt); | ||
235 | goto failed; | ||
236 | } | ||
237 | } | ||
238 | |||
239 | done: | ||
240 | failed = 0; | ||
241 | |||
242 | failed: | ||
243 | ASN1_OBJECT_free(aobj); | ||
244 | |||
245 | return failed; | ||
246 | } | ||
247 | |||
248 | static int | ||
249 | asn1_object_test(void) | ||
250 | { | ||
251 | int failed = 0; | ||
252 | size_t i; | ||
253 | |||
254 | for (i = 0; i < N_ASN1_OBJECT_TESTS; i++) | ||
255 | failed |= do_asn1_object_test(&asn1_object_tests[i]); | ||
256 | |||
257 | return failed; | ||
258 | } | ||
259 | |||
260 | const uint8_t asn1_object_bad_content1[] = { | ||
261 | 0x55, 0x80, 0x04, 0x0a, | ||
262 | }; | ||
263 | const uint8_t asn1_object_bad_content2[] = { | ||
264 | 0x55, 0x04, 0x8a, | ||
265 | }; | ||
266 | |||
267 | static int | ||
268 | asn1_object_bad_content_test(void) | ||
269 | { | ||
270 | ASN1_OBJECT *aobj = NULL; | ||
271 | const uint8_t *p; | ||
272 | size_t len; | ||
273 | int failed = 1; | ||
274 | |||
275 | p = asn1_object_bad_content1; | ||
276 | len = sizeof(asn1_object_bad_content1); | ||
277 | if ((aobj = c2i_ASN1_OBJECT(NULL, &p, len)) != NULL) { | ||
278 | fprintf(stderr, "FAIL: c2i_ASN1_OBJECT() succeeded with bad " | ||
279 | "content 1\n"); | ||
280 | goto failed; | ||
281 | } | ||
282 | |||
283 | p = asn1_object_bad_content2; | ||
284 | len = sizeof(asn1_object_bad_content2); | ||
285 | if ((aobj = c2i_ASN1_OBJECT(NULL, &p, len)) != NULL) { | ||
286 | fprintf(stderr, "FAIL: c2i_ASN1_OBJECT() succeeded with bad " | ||
287 | "content 2\n"); | ||
288 | goto failed; | ||
289 | } | ||
290 | |||
291 | failed = 0; | ||
292 | |||
293 | failed: | ||
294 | ASN1_OBJECT_free(aobj); | ||
295 | |||
296 | return failed; | ||
297 | } | ||
298 | |||
299 | static int | ||
300 | asn1_object_txt_test(void) | ||
301 | { | ||
302 | ASN1_OBJECT *aobj = NULL; | ||
303 | uint8_t small_buf[2]; | ||
304 | const uint8_t *p; | ||
305 | int err, len, ret; | ||
306 | int failed = 1; | ||
307 | |||
308 | ERR_clear_error(); | ||
309 | |||
310 | ret = a2d_ASN1_OBJECT(small_buf, sizeof(small_buf), "1.2.3.4", -1); | ||
311 | if (ret != 0) { | ||
312 | fprintf(stderr, "FAIL: a2d_ASN1_OBJECT() with small buffer " | ||
313 | "returned %d, want %d\n", ret, 0); | ||
314 | goto failed; | ||
315 | } | ||
316 | err = ERR_peek_error(); | ||
317 | if (ERR_GET_REASON(err) != ASN1_R_BUFFER_TOO_SMALL) { | ||
318 | fprintf(stderr, "FAIL: Got error reason %d, want %d\n", | ||
319 | ERR_GET_REASON(err), ASN1_R_BUFFER_TOO_SMALL); | ||
320 | goto failed; | ||
321 | } | ||
322 | |||
323 | p = &asn1_object_tests[0].der[0]; | ||
324 | len = asn1_object_tests[0].der_len; | ||
325 | aobj = d2i_ASN1_OBJECT(NULL, &p, len); | ||
326 | if (aobj == NULL) { | ||
327 | fprintf(stderr, "FAIL: d2i_ASN1_OBJECT() failed\n"); | ||
328 | goto failed; | ||
329 | } | ||
330 | ret = i2t_ASN1_OBJECT(small_buf, sizeof(small_buf), aobj); | ||
331 | if (ret != 16) { | ||
332 | fprintf(stderr, "FAIL: i2t_ASN1_OBJECT() with small buffer " | ||
333 | "returned %d, want %d\n", ret, 16); | ||
334 | goto failed; | ||
335 | } | ||
336 | |||
337 | failed = 0; | ||
338 | |||
339 | failed: | ||
340 | ASN1_OBJECT_free(aobj); | ||
341 | |||
342 | return failed; | ||
343 | } | ||
344 | |||
345 | const uint8_t asn1_large_oid_der[] = { | ||
346 | 0x06, 0x26, | ||
347 | 0x2b, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
348 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
349 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
350 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
351 | 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, | ||
352 | }; | ||
353 | |||
354 | static int | ||
355 | asn1_object_large_oid_test(void) | ||
356 | { | ||
357 | ASN1_OBJECT *aobj = NULL; | ||
358 | uint8_t buf[1024]; | ||
359 | const uint8_t *p; | ||
360 | uint8_t *q; | ||
361 | int ret; | ||
362 | int failed = 1; | ||
363 | |||
364 | failed = 0; | ||
365 | |||
366 | p = asn1_large_oid_der; | ||
367 | aobj = d2i_ASN1_OBJECT(NULL, &p, sizeof(asn1_large_oid_der)); | ||
368 | if (aobj == NULL) { | ||
369 | fprintf(stderr, "FAIL: d2i_ASN1_OBJECT() failed with " | ||
370 | "large oid\n"); | ||
371 | goto failed; | ||
372 | } | ||
373 | |||
374 | q = buf; | ||
375 | ret = i2d_ASN1_OBJECT(aobj, &q); | ||
376 | if (!asn1_compare_bytes("ASN1_OBJECT DER", buf, ret, asn1_large_oid_der, | ||
377 | sizeof(asn1_large_oid_der))) | ||
378 | goto failed; | ||
379 | |||
380 | failed: | ||
381 | ASN1_OBJECT_free(aobj); | ||
382 | |||
383 | return failed; | ||
384 | } | ||
385 | |||
386 | int | ||
387 | main(int argc, char **argv) | ||
388 | { | ||
389 | int failed = 0; | ||
390 | |||
391 | failed |= asn1_object_test(); | ||
392 | failed |= asn1_object_bad_content_test(); | ||
393 | failed |= asn1_object_txt_test(); | ||
394 | failed |= asn1_object_large_oid_test(); | ||
395 | |||
396 | return (failed); | ||
397 | } | ||