xref: /openbsd-src/regress/lib/libcrypto/asn1/asn1object.c (revision 00aa7573f64b4273640bbffaa33078f0ebe4f4e8)
1*00aa7573Stb /* $OpenBSD: asn1object.c,v 1.14 2024/05/29 17:23:05 tb Exp $ */
259af3462Sjsing /*
359af3462Sjsing  * Copyright (c) 2017, 2021, 2022 Joel Sing <jsing@openbsd.org>
459af3462Sjsing  *
559af3462Sjsing  * Permission to use, copy, modify, and distribute this software for any
659af3462Sjsing  * purpose with or without fee is hereby granted, provided that the above
759af3462Sjsing  * copyright notice and this permission notice appear in all copies.
859af3462Sjsing  *
959af3462Sjsing  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1059af3462Sjsing  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1159af3462Sjsing  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1259af3462Sjsing  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1359af3462Sjsing  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1459af3462Sjsing  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1559af3462Sjsing  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1659af3462Sjsing  */
1759af3462Sjsing 
1859af3462Sjsing #include <openssl/asn1.h>
1959af3462Sjsing #include <openssl/err.h>
20e23a4dcfStb #include <openssl/objects.h>
2159af3462Sjsing 
2259af3462Sjsing #include <err.h>
2359af3462Sjsing #include <stdio.h>
2459af3462Sjsing #include <string.h>
2559af3462Sjsing 
26c9675a23Stb #include "asn1_local.h"
2759af3462Sjsing 
2859af3462Sjsing static void
hexdump(const unsigned char * buf,int len)29bd9c0476Stb hexdump(const unsigned char *buf, int len)
3059af3462Sjsing {
31bd9c0476Stb 	int i;
32bd9c0476Stb 
33bd9c0476Stb 	if (len <= 0) {
34bd9c0476Stb 		fprintf(stderr, "<negative length %d>\n", len);
35bd9c0476Stb 		return;
36bd9c0476Stb 	}
3759af3462Sjsing 
3859af3462Sjsing 	for (i = 1; i <= len; i++)
3959af3462Sjsing 		fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
4059af3462Sjsing 
4159af3462Sjsing 	fprintf(stderr, "\n");
4259af3462Sjsing }
4359af3462Sjsing 
4459af3462Sjsing static int
asn1_compare_bytes(const char * label,const unsigned char * d1,int len1,const unsigned char * d2,int len2)4559af3462Sjsing asn1_compare_bytes(const char *label, const unsigned char *d1, int len1,
4659af3462Sjsing     const unsigned char *d2, int len2)
4759af3462Sjsing {
4859af3462Sjsing 	if (len1 != len2) {
4959af3462Sjsing 		fprintf(stderr, "FAIL: %s - byte lengths differ "
507bb1a6cfStb 		    "(%d != %d)\n", label, len1, len2);
5159af3462Sjsing 		fprintf(stderr, "Got:\n");
5259af3462Sjsing 		hexdump(d1, len1);
5359af3462Sjsing 		fprintf(stderr, "Want:\n");
5459af3462Sjsing 		hexdump(d2, len2);
5559af3462Sjsing 		return 0;
5659af3462Sjsing 	}
5759af3462Sjsing 	if (memcmp(d1, d2, len1) != 0) {
5859af3462Sjsing 		fprintf(stderr, "FAIL: %s - bytes differ\n", label);
5959af3462Sjsing 		fprintf(stderr, "Got:\n");
6059af3462Sjsing 		hexdump(d1, len1);
6159af3462Sjsing 		fprintf(stderr, "Want:\n");
6259af3462Sjsing 		hexdump(d2, len2);
6359af3462Sjsing 		return 0;
6459af3462Sjsing 	}
6559af3462Sjsing 	return 1;
6659af3462Sjsing }
6759af3462Sjsing 
6859af3462Sjsing struct asn1_object_test {
6959af3462Sjsing 	const char *oid;
7059af3462Sjsing 	const char *txt;
7159af3462Sjsing 	const uint8_t content[255];
7259af3462Sjsing 	size_t content_len;
7359af3462Sjsing 	const uint8_t der[255];
7459af3462Sjsing 	size_t der_len;
7559af3462Sjsing 	int want_error;
7659af3462Sjsing };
7759af3462Sjsing 
7859af3462Sjsing struct asn1_object_test asn1_object_tests[] = {
7959af3462Sjsing 	{
80566d66a5Sjsing 		.oid = "2.5",
81566d66a5Sjsing 		.txt = "directory services (X.500)",
82566d66a5Sjsing 		.content = {
83566d66a5Sjsing 			0x55,
84566d66a5Sjsing 		},
85566d66a5Sjsing 		.content_len = 1,
86566d66a5Sjsing 		.der = {
87566d66a5Sjsing 			0x06, 0x01, 0x55,
88566d66a5Sjsing 		},
89566d66a5Sjsing 		.der_len = 3,
90566d66a5Sjsing 	},
91566d66a5Sjsing 	{
92566d66a5Sjsing 		.oid = "2.5.4",
93566d66a5Sjsing 		.txt = "X509",
94566d66a5Sjsing 		.content = {
95566d66a5Sjsing 			0x55, 0x04,
96566d66a5Sjsing 		},
97566d66a5Sjsing 		.content_len = 2,
98566d66a5Sjsing 		.der = {
99566d66a5Sjsing 			0x06, 0x02, 0x55, 0x04,
100566d66a5Sjsing 		},
101566d66a5Sjsing 		.der_len = 4,
102566d66a5Sjsing 	},
103566d66a5Sjsing 	{
10459af3462Sjsing 		.oid = "2.5.4.10",
10559af3462Sjsing 		.txt = "organizationName",
10659af3462Sjsing 		.content = {
10759af3462Sjsing 			0x55, 0x04, 0x0a,
10859af3462Sjsing 		},
10959af3462Sjsing 		.content_len = 3,
11059af3462Sjsing 		.der = {
11159af3462Sjsing 			0x06, 0x03, 0x55, 0x04, 0x0a,
11259af3462Sjsing 		},
11359af3462Sjsing 		.der_len = 5,
11459af3462Sjsing 	},
11559af3462Sjsing 	{
11659af3462Sjsing 		.oid = "2 5 4 10",
11759af3462Sjsing 		.txt = "organizationName",
11859af3462Sjsing 		.content = {
11959af3462Sjsing 			0x55, 0x04, 0x0a,
12059af3462Sjsing 		},
12159af3462Sjsing 		.content_len = 3,
12259af3462Sjsing 		.der = {
12359af3462Sjsing 			0x06, 0x03, 0x55, 0x04, 0x0a,
12459af3462Sjsing 		},
12559af3462Sjsing 		.der_len = 5,
12659af3462Sjsing 	},
12759af3462Sjsing 	{
128566d66a5Sjsing 		.oid = "2.5.0.0",
129566d66a5Sjsing 		.txt = "2.5.0.0",
130566d66a5Sjsing 		.content = {
131566d66a5Sjsing 			0x55, 0x00, 0x00,
132566d66a5Sjsing 		},
133566d66a5Sjsing 		.content_len = 3,
134566d66a5Sjsing 		.der = {
135566d66a5Sjsing 			0x06, 0x03, 0x55, 0x00, 0x00,
136566d66a5Sjsing 		},
137566d66a5Sjsing 		.der_len = 5,
138566d66a5Sjsing 	},
139566d66a5Sjsing 	{
140566d66a5Sjsing 		.oid = "0.0.0.0",
141566d66a5Sjsing 		.txt = "0.0.0.0",
142566d66a5Sjsing 		.content = {
143566d66a5Sjsing 			0x00, 0x00, 0x00,
144566d66a5Sjsing 		},
145566d66a5Sjsing 		.content_len = 3,
146566d66a5Sjsing 		.der = {
147566d66a5Sjsing 			0x06, 0x03, 0x00, 0x00, 0x00,
148566d66a5Sjsing 		},
149566d66a5Sjsing 		.der_len = 5,
150566d66a5Sjsing 	},
151566d66a5Sjsing 	{
15259af3462Sjsing 		.oid = "1.3.6.1.4.1.11129.2.4.5",
15359af3462Sjsing 		.txt = "CT Certificate SCTs",
15459af3462Sjsing 		.content = {
15559af3462Sjsing 			0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02,
15659af3462Sjsing 			0x04, 0x05,
15759af3462Sjsing 		},
15859af3462Sjsing 		.content_len = 10,
15959af3462Sjsing 		.der = {
16059af3462Sjsing 			0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6,
16159af3462Sjsing 			0x79, 0x02, 0x04, 0x05,
16259af3462Sjsing 		},
16359af3462Sjsing 		.der_len = 12,
16459af3462Sjsing 	},
16559af3462Sjsing 	{
166566d66a5Sjsing 		.oid = "2.00005.0000000000004.10",
167d612c80bSjsing 		.want_error = ASN1_R_INVALID_NUMBER,
168566d66a5Sjsing 	},
169566d66a5Sjsing 	{
17059af3462Sjsing 		.oid = "2..5.4.10",
171d612c80bSjsing 		.want_error = ASN1_R_INVALID_NUMBER,
17259af3462Sjsing 	},
17359af3462Sjsing 	{
17459af3462Sjsing 		.oid = "2.5..4.10",
175d612c80bSjsing 		.want_error = ASN1_R_INVALID_NUMBER,
17659af3462Sjsing 	},
17759af3462Sjsing 	{
17859af3462Sjsing 		.oid = "2.5.4..10",
179d612c80bSjsing 		.want_error = ASN1_R_INVALID_NUMBER,
18059af3462Sjsing 	},
18159af3462Sjsing 	{
18259af3462Sjsing 		.oid = "2.5.4.10.",
183d612c80bSjsing 		.want_error = ASN1_R_INVALID_NUMBER,
18459af3462Sjsing 	},
18559af3462Sjsing 	{
18659af3462Sjsing 		.oid = "3.5.4.10",
18759af3462Sjsing 		.want_error = ASN1_R_FIRST_NUM_TOO_LARGE,
18859af3462Sjsing 	},
18959af3462Sjsing 	{
190566d66a5Sjsing 		.oid = "0.40.4.10",
191566d66a5Sjsing 		.want_error = ASN1_R_SECOND_NUMBER_TOO_LARGE,
192566d66a5Sjsing 	},
193566d66a5Sjsing 	{
194566d66a5Sjsing 		.oid = "1.40.4.10",
195566d66a5Sjsing 		.want_error = ASN1_R_SECOND_NUMBER_TOO_LARGE,
196566d66a5Sjsing 	},
197566d66a5Sjsing 	{
19859af3462Sjsing 		.oid = "2",
19959af3462Sjsing 		.want_error = ASN1_R_MISSING_SECOND_NUMBER,
20059af3462Sjsing 	},
20159af3462Sjsing 	{
202d612c80bSjsing 		.oid = "2.5 4.10",
203d612c80bSjsing 		.want_error = ASN1_R_INVALID_SEPARATOR,
204d612c80bSjsing 	},
205d612c80bSjsing 	{
20659af3462Sjsing 		.oid = "2,5,4,10",
20759af3462Sjsing 		.want_error = ASN1_R_INVALID_SEPARATOR,
20859af3462Sjsing 	},
209566d66a5Sjsing 	{
210566d66a5Sjsing 		.oid = "2.5,4.10",
211566d66a5Sjsing 		.want_error = ASN1_R_INVALID_DIGIT,
212566d66a5Sjsing 	},
213566d66a5Sjsing 	{
214537fbc0eSjsing 		.oid = "2a.5.4.10",
215537fbc0eSjsing 		.want_error = ASN1_R_INVALID_SEPARATOR,
216537fbc0eSjsing 	},
217537fbc0eSjsing 	{
218566d66a5Sjsing 		.oid = "2.5a.4.10",
219566d66a5Sjsing 		.want_error = ASN1_R_INVALID_DIGIT,
220566d66a5Sjsing 	},
22159af3462Sjsing };
22259af3462Sjsing 
22359af3462Sjsing #define N_ASN1_OBJECT_TESTS \
22459af3462Sjsing     (sizeof(asn1_object_tests) / sizeof(*asn1_object_tests))
22559af3462Sjsing 
22659af3462Sjsing static int
do_asn1_object_test(struct asn1_object_test * aot)22759af3462Sjsing do_asn1_object_test(struct asn1_object_test *aot)
22859af3462Sjsing {
22959af3462Sjsing 	ASN1_OBJECT *aobj = NULL;
23059af3462Sjsing 	uint8_t buf[1024];
23159af3462Sjsing 	const uint8_t *p;
232bd9c0476Stb 	uint8_t *der = NULL;
23359af3462Sjsing 	uint8_t *q;
23459af3462Sjsing 	int err, ret;
23559af3462Sjsing 	int failed = 1;
23659af3462Sjsing 
23759af3462Sjsing 	ERR_clear_error();
23859af3462Sjsing 
239566d66a5Sjsing 	ret = a2d_ASN1_OBJECT(NULL, 0, aot->oid, -1);
240566d66a5Sjsing 	if (ret < 0 || (size_t)ret != aot->content_len) {
241566d66a5Sjsing 		fprintf(stderr, "FAIL: a2d_ASN1_OBJECT('%s') = %d, want %zu\n",
242566d66a5Sjsing 		    aot->oid, ret, aot->content_len);
243566d66a5Sjsing 		goto failed;
244566d66a5Sjsing 	}
24559af3462Sjsing 	ret = a2d_ASN1_OBJECT(buf, sizeof(buf), aot->oid, -1);
24659af3462Sjsing 	if (ret < 0 || (size_t)ret != aot->content_len) {
247566d66a5Sjsing 		fprintf(stderr, "FAIL: a2d_ASN1_OBJECT('%s') = %d, want %zu\n",
248566d66a5Sjsing 		    aot->oid, ret, aot->content_len);
24959af3462Sjsing 		goto failed;
25059af3462Sjsing 	}
25159af3462Sjsing 	if (aot->content_len == 0) {
25259af3462Sjsing 		err = ERR_peek_error();
25359af3462Sjsing 		if (ERR_GET_REASON(err) != aot->want_error) {
254566d66a5Sjsing 			fprintf(stderr, "FAIL: a2d_ASN1_OBJECT('%s') - got "
255566d66a5Sjsing 			    "error reason %d, want %d\n", aot->oid,
256566d66a5Sjsing 			    ERR_GET_REASON(err), aot->want_error);
25759af3462Sjsing 			goto failed;
25859af3462Sjsing 		}
25959af3462Sjsing 		goto done;
26059af3462Sjsing 	}
26159af3462Sjsing 
262566d66a5Sjsing 	if (!asn1_compare_bytes("ASN1_OBJECT content", buf, ret, aot->content,
263566d66a5Sjsing 	    aot->content_len))
264566d66a5Sjsing 		goto failed;
265566d66a5Sjsing 
26659af3462Sjsing 	p = aot->content;
26759af3462Sjsing 	if ((aobj = c2i_ASN1_OBJECT(NULL, &p, aot->content_len)) == NULL) {
26859af3462Sjsing 		fprintf(stderr, "FAIL: c2i_ASN1_OBJECT() failed\n");
26959af3462Sjsing 		goto failed;
27059af3462Sjsing 	}
27159af3462Sjsing 
27259af3462Sjsing 	q = buf;
27359af3462Sjsing 	ret = i2d_ASN1_OBJECT(aobj, &q);
27459af3462Sjsing 	if (!asn1_compare_bytes("ASN1_OBJECT DER", buf, ret, aot->der,
27559af3462Sjsing 	    aot->der_len))
27659af3462Sjsing 		goto failed;
27759af3462Sjsing 
278bd9c0476Stb 	der = NULL;
279bd9c0476Stb 	ret = i2d_ASN1_OBJECT(aobj, &der);
280bd9c0476Stb 	if (!asn1_compare_bytes("ASN1_OBJECT DER", der, ret, aot->der,
281bd9c0476Stb 	    aot->der_len))
282bd9c0476Stb 		goto failed;
283bd9c0476Stb 
284bd9c0476Stb 	free(der);
285bd9c0476Stb 	der = NULL;
286bd9c0476Stb 
28759af3462Sjsing 	ASN1_OBJECT_free(aobj);
28859af3462Sjsing 	aobj = NULL;
28959af3462Sjsing 
29059af3462Sjsing 	p = aot->der;
29159af3462Sjsing 	if ((aobj = d2i_ASN1_OBJECT(NULL, &p, aot->der_len)) == NULL) {
29259af3462Sjsing 		fprintf(stderr, "FAIL: d2i_ASN1_OBJECT() failed\n");
29359af3462Sjsing 		goto failed;
29459af3462Sjsing 	}
295dac92472Stb 	if (p != aot->der + aot->der_len) {
296dac92472Stb 		fprintf(stderr, "FAIL: d2i_ASN1_OBJECT() p = %p, want %p\n",
297dac92472Stb 		    p, aot->der + aot->der_len);
298dac92472Stb 		goto failed;
299dac92472Stb 	}
30059af3462Sjsing 
30159af3462Sjsing 	if (aot->txt != NULL) {
30259af3462Sjsing 		ret = i2t_ASN1_OBJECT(buf, sizeof(buf), aobj);
30359af3462Sjsing 		if (ret <= 0 || (size_t)ret >= sizeof(buf)) {
30459af3462Sjsing 			fprintf(stderr, "FAIL: i2t_ASN1_OBJECT() failed\n");
30559af3462Sjsing 			goto failed;
30659af3462Sjsing 		}
30759af3462Sjsing 		if (strcmp(aot->txt, buf) != 0) {
30859af3462Sjsing 			fprintf(stderr, "FAIL: i2t_ASN1_OBJECT() = '%s', "
30959af3462Sjsing 			    "want '%s'\n", buf, aot->txt);
31059af3462Sjsing 			goto failed;
31159af3462Sjsing 		}
31259af3462Sjsing 	}
31359af3462Sjsing 
31459af3462Sjsing  done:
31559af3462Sjsing 	failed = 0;
31659af3462Sjsing 
31759af3462Sjsing  failed:
31859af3462Sjsing 	ASN1_OBJECT_free(aobj);
319bd9c0476Stb 	free(der);
32059af3462Sjsing 
32159af3462Sjsing 	return failed;
32259af3462Sjsing }
32359af3462Sjsing 
32459af3462Sjsing static int
asn1_object_test(void)32559af3462Sjsing asn1_object_test(void)
32659af3462Sjsing {
32759af3462Sjsing 	int failed = 0;
32859af3462Sjsing 	size_t i;
32959af3462Sjsing 
33059af3462Sjsing 	for (i = 0; i < N_ASN1_OBJECT_TESTS; i++)
33159af3462Sjsing 		failed |= do_asn1_object_test(&asn1_object_tests[i]);
33259af3462Sjsing 
33359af3462Sjsing 	return failed;
33459af3462Sjsing }
33559af3462Sjsing 
33659af3462Sjsing const uint8_t asn1_object_bad_content1[] = {
33759af3462Sjsing 	0x55, 0x80, 0x04, 0x0a,
33859af3462Sjsing };
33959af3462Sjsing const uint8_t asn1_object_bad_content2[] = {
34059af3462Sjsing 	0x55, 0x04, 0x8a,
34159af3462Sjsing };
34259af3462Sjsing 
34359af3462Sjsing static int
asn1_object_bad_content_test(void)34459af3462Sjsing asn1_object_bad_content_test(void)
34559af3462Sjsing {
34659af3462Sjsing 	ASN1_OBJECT *aobj = NULL;
34759af3462Sjsing 	const uint8_t *p;
34859af3462Sjsing 	size_t len;
34959af3462Sjsing 	int failed = 1;
35059af3462Sjsing 
35159af3462Sjsing 	p = asn1_object_bad_content1;
35259af3462Sjsing 	len = sizeof(asn1_object_bad_content1);
35359af3462Sjsing 	if ((aobj = c2i_ASN1_OBJECT(NULL, &p, len)) != NULL) {
35459af3462Sjsing 		fprintf(stderr, "FAIL: c2i_ASN1_OBJECT() succeeded with bad "
35559af3462Sjsing 		    "content 1\n");
35659af3462Sjsing 		goto failed;
35759af3462Sjsing 	}
35859af3462Sjsing 
35959af3462Sjsing 	p = asn1_object_bad_content2;
36059af3462Sjsing 	len = sizeof(asn1_object_bad_content2);
36159af3462Sjsing 	if ((aobj = c2i_ASN1_OBJECT(NULL, &p, len)) != NULL) {
36259af3462Sjsing 		fprintf(stderr, "FAIL: c2i_ASN1_OBJECT() succeeded with bad "
36359af3462Sjsing 		    "content 2\n");
36459af3462Sjsing 		goto failed;
36559af3462Sjsing 	}
36659af3462Sjsing 
36759af3462Sjsing 	failed = 0;
36859af3462Sjsing 
36959af3462Sjsing  failed:
37059af3462Sjsing 	ASN1_OBJECT_free(aobj);
37159af3462Sjsing 
37259af3462Sjsing 	return failed;
37359af3462Sjsing }
37459af3462Sjsing 
37559af3462Sjsing static int
asn1_object_txt_test(void)37659af3462Sjsing asn1_object_txt_test(void)
37759af3462Sjsing {
378a4cc8787Sjsing 	const char *obj_txt = "organizationName";
37959af3462Sjsing 	ASN1_OBJECT *aobj = NULL;
38059af3462Sjsing 	uint8_t small_buf[2];
38159af3462Sjsing 	const uint8_t *p;
38259af3462Sjsing 	int err, len, ret;
383a4cc8787Sjsing 	BIO *bio = NULL;
384a4cc8787Sjsing 	char *data;
385a4cc8787Sjsing 	long data_len;
38659af3462Sjsing 	int failed = 1;
38759af3462Sjsing 
38859af3462Sjsing 	ERR_clear_error();
38959af3462Sjsing 
39059af3462Sjsing 	ret = a2d_ASN1_OBJECT(small_buf, sizeof(small_buf), "1.2.3.4", -1);
39159af3462Sjsing 	if (ret != 0) {
39259af3462Sjsing 		fprintf(stderr, "FAIL: a2d_ASN1_OBJECT() with small buffer "
39359af3462Sjsing 		    "returned %d, want %d\n", ret, 0);
39459af3462Sjsing 		goto failed;
39559af3462Sjsing 	}
39659af3462Sjsing 	err = ERR_peek_error();
39759af3462Sjsing 	if (ERR_GET_REASON(err) != ASN1_R_BUFFER_TOO_SMALL) {
39859af3462Sjsing 		fprintf(stderr, "FAIL: Got error reason %d, want %d\n",
39959af3462Sjsing 		    ERR_GET_REASON(err), ASN1_R_BUFFER_TOO_SMALL);
40059af3462Sjsing 		goto failed;
40159af3462Sjsing 	}
40259af3462Sjsing 
403566d66a5Sjsing 	p = &asn1_object_tests[2].der[0];
404566d66a5Sjsing 	len = asn1_object_tests[2].der_len;
40559af3462Sjsing 	aobj = d2i_ASN1_OBJECT(NULL, &p, len);
40659af3462Sjsing 	if (aobj == NULL) {
40759af3462Sjsing 		fprintf(stderr, "FAIL: d2i_ASN1_OBJECT() failed\n");
40859af3462Sjsing 		goto failed;
40959af3462Sjsing 	}
41059af3462Sjsing 	ret = i2t_ASN1_OBJECT(small_buf, sizeof(small_buf), aobj);
411a4cc8787Sjsing 	if (ret < 0 || (unsigned long)ret != strlen(obj_txt)) {
41259af3462Sjsing 		fprintf(stderr, "FAIL: i2t_ASN1_OBJECT() with small buffer "
41334929b0aStb 		    "returned %d, want %zu\n", ret, strlen(obj_txt));
414a4cc8787Sjsing 		goto failed;
415a4cc8787Sjsing 	}
416a4cc8787Sjsing 
417a4cc8787Sjsing 	if ((bio = BIO_new(BIO_s_mem())) == NULL) {
418a4cc8787Sjsing 		fprintf(stderr, "FAIL: BIO_new() returned NULL\n");
419a4cc8787Sjsing 		goto failed;
420a4cc8787Sjsing 	}
421a4cc8787Sjsing 	ret = i2a_ASN1_OBJECT(bio, NULL);
422a4cc8787Sjsing 	if (ret != 4) {
423a4cc8787Sjsing 		fprintf(stderr, "FAIL: i2a_ASN1_OBJECT(_, NULL) returned %d, "
424a4cc8787Sjsing 		    "want 4\n", ret);
425a4cc8787Sjsing 		goto failed;
426a4cc8787Sjsing 	}
427a4cc8787Sjsing 	data_len = BIO_get_mem_data(bio, &data);
428a4cc8787Sjsing 	if (ret != data_len || memcmp("NULL", data, data_len) != 0) {
429a4cc8787Sjsing 		fprintf(stderr, "FAIL: i2a_ASN1_OBJECT(_, NULL) did not return "
430a4cc8787Sjsing 		    "'NULL'\n");
431a4cc8787Sjsing 		goto failed;
432a4cc8787Sjsing 	}
433a4cc8787Sjsing 
4344141bb4bStb 	if ((ret = BIO_reset(bio)) <= 0) {
4354141bb4bStb 		fprintf(stderr, "FAIL: BIO_reset failed: ret = %d\n", ret);
4364141bb4bStb 		goto failed;
4374141bb4bStb 	}
438a4cc8787Sjsing 	ret = i2a_ASN1_OBJECT(bio, aobj);
439a4cc8787Sjsing 	if (ret < 0 || (unsigned long)ret != strlen(obj_txt)) {
440a4cc8787Sjsing 		fprintf(stderr, "FAIL: i2a_ASN1_OBJECT() returned %d, "
44134929b0aStb 		    "want %zu\n", ret, strlen(obj_txt));
442a4cc8787Sjsing 		goto failed;
443a4cc8787Sjsing 	}
444a4cc8787Sjsing 	data_len = BIO_get_mem_data(bio, &data);
445a4cc8787Sjsing 	if (ret != data_len || memcmp(obj_txt, data, data_len) != 0) {
446a4cc8787Sjsing 		fprintf(stderr, "FAIL: i2a_ASN1_OBJECT() did not return "
447a4cc8787Sjsing 		    "'%s'\n", obj_txt);
44859af3462Sjsing 		goto failed;
44959af3462Sjsing 	}
45059af3462Sjsing 
45159af3462Sjsing 	failed = 0;
45259af3462Sjsing 
45359af3462Sjsing  failed:
45459af3462Sjsing 	ASN1_OBJECT_free(aobj);
455a4cc8787Sjsing 	BIO_free(bio);
45659af3462Sjsing 
45759af3462Sjsing 	return failed;
45859af3462Sjsing }
45959af3462Sjsing 
46059af3462Sjsing const uint8_t asn1_large_oid_der[] = {
46159af3462Sjsing 	0x06, 0x26,
46259af3462Sjsing 	0x2b, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
46359af3462Sjsing 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
46459af3462Sjsing 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
46559af3462Sjsing 	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
46659af3462Sjsing 	0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
46759af3462Sjsing };
46859af3462Sjsing 
46959af3462Sjsing static int
asn1_object_large_oid_test(void)47059af3462Sjsing asn1_object_large_oid_test(void)
47159af3462Sjsing {
47259af3462Sjsing 	ASN1_OBJECT *aobj = NULL;
47359af3462Sjsing 	uint8_t buf[1024];
47459af3462Sjsing 	const uint8_t *p;
475bd9c0476Stb 	uint8_t *der = NULL;
47659af3462Sjsing 	uint8_t *q;
47759af3462Sjsing 	int ret;
47859af3462Sjsing 	int failed = 1;
47959af3462Sjsing 
48059af3462Sjsing 	p = asn1_large_oid_der;
48159af3462Sjsing 	aobj = d2i_ASN1_OBJECT(NULL, &p, sizeof(asn1_large_oid_der));
48259af3462Sjsing 	if (aobj == NULL) {
48359af3462Sjsing 		fprintf(stderr, "FAIL: d2i_ASN1_OBJECT() failed with "
48459af3462Sjsing 		    "large oid\n");
48559af3462Sjsing 		goto failed;
48659af3462Sjsing 	}
48759af3462Sjsing 
48859af3462Sjsing 	q = buf;
48959af3462Sjsing 	ret = i2d_ASN1_OBJECT(aobj, &q);
49059af3462Sjsing 	if (!asn1_compare_bytes("ASN1_OBJECT DER", buf, ret, asn1_large_oid_der,
49159af3462Sjsing 	    sizeof(asn1_large_oid_der)))
49259af3462Sjsing 		goto failed;
49359af3462Sjsing 
494bd9c0476Stb 	der = NULL;
495bd9c0476Stb 	ret = i2d_ASN1_OBJECT(aobj, &der);
496bd9c0476Stb 	if (!asn1_compare_bytes("ASN1_OBJECT DER", der, ret, asn1_large_oid_der,
497bd9c0476Stb 	    sizeof(asn1_large_oid_der)))
498bd9c0476Stb 		goto failed;
499bd9c0476Stb 
50006a01064Stb 	failed = 0;
50106a01064Stb 
50259af3462Sjsing  failed:
50359af3462Sjsing 	ASN1_OBJECT_free(aobj);
504bd9c0476Stb 	free(der);
50559af3462Sjsing 
50659af3462Sjsing 	return failed;
50759af3462Sjsing }
50859af3462Sjsing 
509e23a4dcfStb static int
asn1_object_i2d_errors(void)510e23a4dcfStb asn1_object_i2d_errors(void)
511e23a4dcfStb {
512e23a4dcfStb 	ASN1_OBJECT *aobj = NULL;
513e23a4dcfStb 	int ret;
514e23a4dcfStb 	int failed = 1;
515e23a4dcfStb 
516e23a4dcfStb 	if ((ret = i2d_ASN1_OBJECT(NULL, NULL)) > 0) {
517e23a4dcfStb 		fprintf(stderr, "FAIL: i2d_ASN1_OBJECT(NULL, NULL) returned %d, "
518e23a4dcfStb 		    "want <= 0\n", ret);
519e23a4dcfStb 		goto failed;
520e23a4dcfStb 	}
521e23a4dcfStb 
522e23a4dcfStb 	if ((aobj = OBJ_nid2obj(NID_undef)) == NULL) {
523e23a4dcfStb 		fprintf(stderr, "FAIL: OBJ_nid2obj() failed\n");
524e23a4dcfStb 		goto failed;
525e23a4dcfStb 	}
526e23a4dcfStb 
527e23a4dcfStb 	if (OBJ_get0_data(aobj) != NULL) {
528e23a4dcfStb 		fprintf(stderr, "FAIL: undefined obj didn't have NULL data\n");
529e23a4dcfStb 		goto failed;
530e23a4dcfStb 	}
531e23a4dcfStb 
532e23a4dcfStb 	if ((ret = i2d_ASN1_OBJECT(aobj, NULL)) > 0) {
533e23a4dcfStb 		fprintf(stderr, "FAIL: i2d_ASN1_OBJECT() succeeded on undefined "
534e23a4dcfStb 		    "object\n");
535e23a4dcfStb 		goto failed;
536e23a4dcfStb 	}
537e23a4dcfStb 
538e23a4dcfStb 	failed = 0;
539e23a4dcfStb 
540e23a4dcfStb  failed:
541e23a4dcfStb 	ASN1_OBJECT_free(aobj);
542e23a4dcfStb 
543e23a4dcfStb 	return failed;
544e23a4dcfStb }
545e23a4dcfStb 
54659af3462Sjsing int
main(int argc,char ** argv)54759af3462Sjsing main(int argc, char **argv)
54859af3462Sjsing {
54959af3462Sjsing 	int failed = 0;
55059af3462Sjsing 
55159af3462Sjsing 	failed |= asn1_object_test();
55259af3462Sjsing 	failed |= asn1_object_bad_content_test();
55359af3462Sjsing 	failed |= asn1_object_txt_test();
55459af3462Sjsing 	failed |= asn1_object_large_oid_test();
555e23a4dcfStb 	failed |= asn1_object_i2d_errors();
55659af3462Sjsing 
55759af3462Sjsing 	return (failed);
55859af3462Sjsing }
559