1*a201dd64Stb /* $OpenBSD: asn1_string_to_utf8.c,v 1.2 2022/11/23 08:51:05 tb Exp $ */
2eabc5796Stb /*
3eabc5796Stb * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
4eabc5796Stb *
5eabc5796Stb * Permission to use, copy, modify, and distribute this software for any
6eabc5796Stb * purpose with or without fee is hereby granted, provided that the above
7eabc5796Stb * copyright notice and this permission notice appear in all copies.
8eabc5796Stb *
9eabc5796Stb * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10eabc5796Stb * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11eabc5796Stb * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12eabc5796Stb * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13eabc5796Stb * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14eabc5796Stb * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15eabc5796Stb * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16eabc5796Stb */
17eabc5796Stb
18eabc5796Stb #include <err.h>
19eabc5796Stb #include <string.h>
20eabc5796Stb
21eabc5796Stb #include <openssl/asn1.h>
22eabc5796Stb
23eabc5796Stb struct asn1_string_to_utf8_test_case {
24eabc5796Stb const char *description;
25eabc5796Stb const ASN1_ITEM *item;
26eabc5796Stb const uint8_t der[32];
27eabc5796Stb size_t der_len;
28eabc5796Stb const uint8_t want[32];
29eabc5796Stb int want_len;
30eabc5796Stb };
31eabc5796Stb
32eabc5796Stb static const struct asn1_string_to_utf8_test_case tests[] = {
33eabc5796Stb {
34eabc5796Stb .description = "hello",
35eabc5796Stb .item = &ASN1_PRINTABLESTRING_it,
36eabc5796Stb .der = {
37eabc5796Stb 0x13, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f,
38eabc5796Stb },
39eabc5796Stb .der_len = 7,
40eabc5796Stb .want = {
41eabc5796Stb 0x68, 0x65, 0x6c, 0x6c, 0x6f,
42eabc5796Stb },
43eabc5796Stb .want_len = 5,
44eabc5796Stb },
45eabc5796Stb {
46eabc5796Stb .description = "face with tears of joy",
47eabc5796Stb .item = &ASN1_UTF8STRING_it,
48eabc5796Stb .der = {
49eabc5796Stb 0x0c, 0x04, 0xF0, 0x9F, 0x98, 0x82,
50eabc5796Stb },
51eabc5796Stb .der_len = 6,
52eabc5796Stb .want = {
53eabc5796Stb 0xF0, 0x9F, 0x98, 0x82,
54eabc5796Stb },
55eabc5796Stb .want_len = 4,
56eabc5796Stb },
57eabc5796Stb {
58eabc5796Stb .description = "hi",
59eabc5796Stb .item = &ASN1_IA5STRING_it,
60eabc5796Stb .der = {
61eabc5796Stb 0x16, 0x02, 0x68, 0x69,
62eabc5796Stb },
63eabc5796Stb .der_len = 4,
64eabc5796Stb .want = {
65eabc5796Stb 0x68, 0x69,
66eabc5796Stb },
67eabc5796Stb .want_len = 2,
68eabc5796Stb },
69eabc5796Stb };
70eabc5796Stb
71eabc5796Stb const size_t N_TESTS = sizeof(tests) / sizeof(tests[0]);
72eabc5796Stb
73eabc5796Stb static int
asn1_string_to_utf8_test(const struct asn1_string_to_utf8_test_case * test)74eabc5796Stb asn1_string_to_utf8_test(const struct asn1_string_to_utf8_test_case *test)
75eabc5796Stb {
76eabc5796Stb ASN1_STRING *str = NULL;
77eabc5796Stb const unsigned char *der;
78eabc5796Stb unsigned char *out = NULL;
79eabc5796Stb int ret;
80eabc5796Stb int failed = 1;
81eabc5796Stb
82eabc5796Stb der = test->der;
83eabc5796Stb if ((str = (ASN1_STRING *)ASN1_item_d2i(NULL, &der, test->der_len,
84eabc5796Stb test->item)) == NULL) {
85eabc5796Stb warnx("ASN1_item_d2i failed");
86eabc5796Stb goto err;
87eabc5796Stb }
88eabc5796Stb
89*a201dd64Stb if ((ret = ASN1_STRING_to_UTF8(&out, str)) < 0) {
90eabc5796Stb warnx("ASN1_STRING_to_UTF8 failed: got %d, want %d", ret,
91eabc5796Stb test->want_len);
92eabc5796Stb goto err;
93eabc5796Stb }
94eabc5796Stb
95*a201dd64Stb if (ret != test->want_len) {
96*a201dd64Stb warnx("ASN1_STRING_to_UTF8: got %d, want %d", ret,
97*a201dd64Stb test->want_len);
98*a201dd64Stb goto err;
99*a201dd64Stb }
100*a201dd64Stb
101eabc5796Stb if (memcmp(out, test->want, test->want_len) != 0) {
102eabc5796Stb warnx("memcmp failed");
103eabc5796Stb goto err;
104eabc5796Stb }
105eabc5796Stb
106eabc5796Stb failed = 0;
107eabc5796Stb err:
108eabc5796Stb ASN1_STRING_free(str);
109eabc5796Stb free(out);
110eabc5796Stb
111eabc5796Stb return failed;
112eabc5796Stb }
113eabc5796Stb
114eabc5796Stb static int
asn1_string_to_utf8_tests(void)115eabc5796Stb asn1_string_to_utf8_tests(void)
116eabc5796Stb {
117eabc5796Stb size_t i;
118eabc5796Stb int failed = 0;
119eabc5796Stb
120eabc5796Stb for (i = 0; i < N_TESTS; i++)
121eabc5796Stb failed |= asn1_string_to_utf8_test(&tests[i]);
122eabc5796Stb
123eabc5796Stb return failed;
124eabc5796Stb }
125eabc5796Stb
126eabc5796Stb int
main(void)127eabc5796Stb main(void)
128eabc5796Stb {
129eabc5796Stb int failed = 0;
130eabc5796Stb
131eabc5796Stb failed |= asn1_string_to_utf8_tests();
132eabc5796Stb
133eabc5796Stb return failed;
134eabc5796Stb }
135