summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjsing <>2022-02-26 16:45:31 +0000
committerjsing <>2022-02-26 16:45:31 +0000
commite7a4c5c29f0809ffb65ae98c57b691e57987c9db (patch)
tree22681111a48c5d66c0343de2753ce438e3e0019c
parentc5273921395aa49c913ac5a1325c7eb78a50292c (diff)
downloadopenbsd-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/Makefile3
-rw-r--r--src/regress/lib/libcrypto/asn1/asn1object.c397
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
3PROGS = \ 3PROGS = \
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
27static void
28hexdump(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
38static int
39asn1_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
62struct 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
72struct 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
176static int
177do_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
248static int
249asn1_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
260const uint8_t asn1_object_bad_content1[] = {
261 0x55, 0x80, 0x04, 0x0a,
262};
263const uint8_t asn1_object_bad_content2[] = {
264 0x55, 0x04, 0x8a,
265};
266
267static int
268asn1_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
299static int
300asn1_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
345const 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
354static int
355asn1_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
386int
387main(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}