1*9b0855c6Stb /* $OpenBSD: asn1oct.c,v 1.4 2023/05/13 07:17:32 tb Exp $ */
251de66fbStb
351de66fbStb /*
451de66fbStb * Copyright (c) 2023 Theo Buehler <tb@openbsd.org>
551de66fbStb *
651de66fbStb * Permission to use, copy, modify, and distribute this software for any
751de66fbStb * purpose with or without fee is hereby granted, provided that the above
851de66fbStb * copyright notice and this permission notice appear in all copies.
951de66fbStb *
1051de66fbStb * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1151de66fbStb * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1251de66fbStb * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1351de66fbStb * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1451de66fbStb * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1551de66fbStb * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1651de66fbStb * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1751de66fbStb */
1851de66fbStb
19*9b0855c6Stb #include <assert.h>
2051de66fbStb #include <err.h>
2151de66fbStb #include <string.h>
2251de66fbStb
2351de66fbStb #include <openssl/asn1.h>
2451de66fbStb #include <openssl/x509v3.h>
2551de66fbStb
2651de66fbStb #define TESTBUFFER_SIZE 20
2751de66fbStb
2851de66fbStb static const struct i2s_asn1_octet_string_test {
2951de66fbStb const char *desc;
3051de66fbStb const uint8_t buf[TESTBUFFER_SIZE];
3151de66fbStb long len;
3251de66fbStb const char *want;
3351de66fbStb } i2s_test[] = {
3451de66fbStb {
3551de66fbStb .desc = "Empty buffer gives empty string",
3651de66fbStb .buf = { 0x00, },
3751de66fbStb .len = 0,
3851de66fbStb .want = "",
3951de66fbStb },
4051de66fbStb {
4151de66fbStb .desc = "all hex digits",
4251de66fbStb .buf = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, },
4351de66fbStb .len = 8,
4451de66fbStb .want = "01:23:45:67:89:AB:CD:EF",
4551de66fbStb },
4651de66fbStb {
4751de66fbStb .desc = "all hex digits, scrambled",
4851de66fbStb .buf = { 0x98, 0x24, 0xbf, 0x3a, 0xc7, 0xd6, 0x01, 0x5e, },
4951de66fbStb .len = 8,
5051de66fbStb .want = "98:24:BF:3A:C7:D6:01:5E",
5151de66fbStb },
5251de66fbStb {
5351de66fbStb .desc = "Embedded 0 byte",
5451de66fbStb .buf = { 0x7a, 0x00, 0xbb, },
5551de66fbStb .len = 3,
5651de66fbStb .want = "7A:00:BB",
5751de66fbStb },
5851de66fbStb {
5951de66fbStb .desc = "All zeroes",
6051de66fbStb .buf = { 0x00, 0x00, 0x00, 0x00, 0x00, },
6151de66fbStb .len = 4,
6251de66fbStb .want = "00:00:00:00",
6351de66fbStb },
6451de66fbStb {
6551de66fbStb .desc = "All bits set",
6651de66fbStb .buf = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, },
6751de66fbStb .len = 8,
6851de66fbStb .want = "FF:FF:FF:FF:FF:FF:FF:FF",
6951de66fbStb },
7051de66fbStb {
7151de66fbStb .desc = "negative length",
7251de66fbStb .buf = { 0x00, },
7351de66fbStb .len = -1,
7451de66fbStb },
7551de66fbStb };
7651de66fbStb
7751de66fbStb #define N_I2S_TESTS (sizeof(i2s_test) / sizeof(i2s_test[0]))
7851de66fbStb
7951de66fbStb static int
test_i2s_ASN1_OCTET_STRING(const struct i2s_asn1_octet_string_test * test)8051de66fbStb test_i2s_ASN1_OCTET_STRING(const struct i2s_asn1_octet_string_test *test)
8151de66fbStb {
8251de66fbStb ASN1_OCTET_STRING *aos = NULL;
8351de66fbStb int should_fail = test->want == NULL;
8451de66fbStb char *got = NULL;
8551de66fbStb int failed = 0;
8651de66fbStb
8751de66fbStb if ((aos = ASN1_OCTET_STRING_new()) == NULL)
8851de66fbStb errx(1, "ASN1_OCTET_STRING_new");
8951de66fbStb
9051de66fbStb if (!ASN1_STRING_set(aos, (void *)test->buf, test->len))
9151de66fbStb errx(1, "ASN1_STRING_set");
9251de66fbStb
9351de66fbStb if ((got = i2s_ASN1_OCTET_STRING(NULL, aos)) == NULL) {
9451de66fbStb if (!should_fail)
9551de66fbStb errx(1, "i2s_ASN1_OCTET_STRING");
9651de66fbStb }
9751de66fbStb
9851de66fbStb if (!should_fail && strcmp(test->want, got) != 0) {
9951de66fbStb fprintf(stderr, "%s: \"%s\" failed: want \"%s\", got \"%s\"\n",
10051de66fbStb __func__, test->desc, test->want, got);
10151de66fbStb failed |= 1;
10251de66fbStb }
10351de66fbStb
10451de66fbStb ASN1_OCTET_STRING_free(aos);
10551de66fbStb free(got);
10651de66fbStb
10751de66fbStb return failed;
10851de66fbStb }
10951de66fbStb
11051de66fbStb static int
test_new_ASN1_OCTET_STRING(void)11151de66fbStb test_new_ASN1_OCTET_STRING(void)
11251de66fbStb {
11351de66fbStb ASN1_OCTET_STRING *aos = NULL;
11451de66fbStb char *got;
11551de66fbStb int failed = 0;
11651de66fbStb
11751de66fbStb if ((aos = ASN1_OCTET_STRING_new()) == NULL)
11852bf25b2Stb errx(1, "%s: ASN1_OCTET_STRING_new", __func__);
11951de66fbStb if ((got = i2s_ASN1_OCTET_STRING(NULL, aos)) == NULL)
12052bf25b2Stb errx(1, "%s: i2s_ASN1_OCTET_STRING", __func__);
12151de66fbStb
12251de66fbStb if (strcmp("", got) != 0) {
12351de66fbStb fprintf(stderr, "%s failed: want \"\", got \"%s\"\n",
12451de66fbStb __func__, got);
12551de66fbStb failed |= 1;
12651de66fbStb }
12751de66fbStb
12851de66fbStb ASN1_OCTET_STRING_free(aos);
12951de66fbStb free(got);
13051de66fbStb
13151de66fbStb return failed;
13251de66fbStb }
13351de66fbStb
13451de66fbStb static int
run_i2s_ASN1_OCTET_STRING_tests(void)13551de66fbStb run_i2s_ASN1_OCTET_STRING_tests(void)
13651de66fbStb {
13751de66fbStb size_t i;
13851de66fbStb int failed = 0;
13951de66fbStb
14051de66fbStb failed |= test_new_ASN1_OCTET_STRING();
14151de66fbStb
14251de66fbStb for (i = 0; i < N_I2S_TESTS; i++)
14351de66fbStb failed |= test_i2s_ASN1_OCTET_STRING(&i2s_test[i]);
14451de66fbStb
14551de66fbStb return failed;
14651de66fbStb }
14751de66fbStb
14851de66fbStb static const struct s2i_asn1_octet_string_test {
14951de66fbStb const char *desc;
15051de66fbStb const char *in;
15151de66fbStb const char *want;
15251de66fbStb } s2i_test[] = {
15351de66fbStb /* Tests that should succeed. */
15451de66fbStb {
15551de66fbStb .desc = "empty string",
15651de66fbStb .in = "",
15751de66fbStb .want = "",
15851de66fbStb },
15951de66fbStb {
160193c6483Stb .desc = "only colons",
161193c6483Stb .in = ":::::::",
162193c6483Stb .want = "",
163193c6483Stb },
164193c6483Stb {
16551de66fbStb .desc = "a 0 octet",
16651de66fbStb .in = "00",
16751de66fbStb .want = "00",
16851de66fbStb },
16951de66fbStb {
17051de66fbStb .desc = "a 0 octet with stupid colons",
17151de66fbStb .in = ":::00:::::",
17251de66fbStb .want = "00",
17351de66fbStb },
17451de66fbStb {
17551de66fbStb .desc = "more stupid colons",
17651de66fbStb .in = ":::C0fF::Ee:::::",
17751de66fbStb .want = "C0:FF:EE",
17851de66fbStb },
17951de66fbStb {
18051de66fbStb .desc = "all hex digits",
18151de66fbStb .in = "0123456789abcdef",
18251de66fbStb .want = "01:23:45:67:89:AB:CD:EF",
18351de66fbStb },
18451de66fbStb
18551de66fbStb /* Tests that should fail. */
18651de66fbStb {
18751de66fbStb .desc = "colons between hex digits",
18851de66fbStb .in = "A:F",
18951de66fbStb },
19051de66fbStb {
19151de66fbStb .desc = "more colons between hex digits",
19251de66fbStb .in = "5:7",
19351de66fbStb },
19451de66fbStb {
19551de66fbStb .desc = "one hex digit",
19651de66fbStb .in = "1",
19751de66fbStb },
19851de66fbStb {
19951de66fbStb .desc = "three hex digits",
20051de66fbStb .in = "bad",
20151de66fbStb },
20251de66fbStb {
20351de66fbStb .desc = "three hex digits, colon after first digit",
20451de66fbStb .in = "b:ad",
20551de66fbStb },
20651de66fbStb {
20751de66fbStb .desc = "three hex digits, colon after second digit",
20851de66fbStb .in = "ba:d",
20951de66fbStb },
21051de66fbStb {
21151de66fbStb .desc = "non-hex digit",
21251de66fbStb .in = "g00d",
21351de66fbStb },
21451de66fbStb {
215193c6483Stb .desc = "non-hex digits",
216193c6483Stb .in = "d0gged",
217193c6483Stb },
218193c6483Stb {
21951de66fbStb .desc = "trailing non-hex digit",
22051de66fbStb .in = "d00der",
22151de66fbStb },
22251de66fbStb };
22351de66fbStb
22451de66fbStb #define N_S2I_TESTS (sizeof(s2i_test) / sizeof(s2i_test[0]))
22551de66fbStb
22651de66fbStb static int
test_s2i_ASN1_OCTET_STRING(const struct s2i_asn1_octet_string_test * test)22751de66fbStb test_s2i_ASN1_OCTET_STRING(const struct s2i_asn1_octet_string_test *test)
22851de66fbStb {
22951de66fbStb ASN1_OCTET_STRING *aos = NULL;
23051de66fbStb char *got = NULL;
23151de66fbStb int should_fail = test->want == NULL;
23251de66fbStb int failed = 0;
23351de66fbStb
23451de66fbStb if ((aos = s2i_ASN1_OCTET_STRING(NULL, NULL, test->in)) == NULL) {
23551de66fbStb if (!should_fail)
23651de66fbStb errx(1, "%s: s2i_ASN1_OCTET_STRING", test->desc);
23751de66fbStb goto done;
23851de66fbStb }
23951de66fbStb
24051de66fbStb if ((got = i2s_ASN1_OCTET_STRING(NULL, aos)) == NULL)
24151de66fbStb errx(1, "%s: i2s_ASN1_OCTET_STRING", test->desc);
24251de66fbStb
243*9b0855c6Stb assert(test->want != NULL);
24451de66fbStb if (strcmp(test->want, got) != 0) {
24551de66fbStb fprintf(stderr, "%s: \"%s\" failed: want \"%s\", got \"%s\"\n",
24651de66fbStb __func__, test->desc, test->want, got);
24751de66fbStb failed |= 1;
24851de66fbStb }
24951de66fbStb
25051de66fbStb done:
25151de66fbStb ASN1_OCTET_STRING_free(aos);
25251de66fbStb free(got);
25351de66fbStb
25451de66fbStb return failed;
25551de66fbStb }
25651de66fbStb
25751de66fbStb static int
run_s2i_ASN1_OCTET_STRING_tests(void)25851de66fbStb run_s2i_ASN1_OCTET_STRING_tests(void)
25951de66fbStb {
26051de66fbStb size_t i;
26151de66fbStb int failed = 0;
26251de66fbStb
26351de66fbStb failed |= test_new_ASN1_OCTET_STRING();
26451de66fbStb
26551de66fbStb for (i = 0; i < N_S2I_TESTS; i++)
26651de66fbStb failed |= test_s2i_ASN1_OCTET_STRING(&s2i_test[i]);
26751de66fbStb
26851de66fbStb return failed;
26951de66fbStb }
27051de66fbStb
27151de66fbStb int
main(void)27251de66fbStb main(void)
27351de66fbStb {
27451de66fbStb int failed = 0;
27551de66fbStb
27651de66fbStb failed |= run_i2s_ASN1_OCTET_STRING_tests();
27751de66fbStb failed |= run_s2i_ASN1_OCTET_STRING_tests();
27851de66fbStb
27951de66fbStb return failed;
28051de66fbStb }
281