From 3f4089c48468d187eaa6b693d30aed4855a25bda Mon Sep 17 00:00:00 2001 From: jsing Date: Fri, 11 Feb 2022 16:34:23 +0000 Subject: [PATCH] Add initial regress for objects. --- regress/lib/libcrypto/Makefile | 3 +- regress/lib/libcrypto/objects/Makefile | 9 + regress/lib/libcrypto/objects/objectstest.c | 438 ++++++++++++++++++++ 3 files changed, 449 insertions(+), 1 deletion(-) create mode 100644 regress/lib/libcrypto/objects/Makefile create mode 100644 regress/lib/libcrypto/objects/objectstest.c diff --git a/regress/lib/libcrypto/Makefile b/regress/lib/libcrypto/Makefile index 1c346f6e3be..f29e594535f 100644 --- a/regress/lib/libcrypto/Makefile +++ b/regress/lib/libcrypto/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.42 2021/12/05 13:01:08 jsing Exp $ +# $OpenBSD: Makefile,v 1.43 2022/02/11 16:34:23 jsing Exp $ SUBDIR += aead SUBDIR += aeswrap @@ -34,6 +34,7 @@ SUBDIR += ige SUBDIR += init SUBDIR += md4 SUBDIR += md5 +SUBDIR += objects SUBDIR += pbkdf2 SUBDIR += pem SUBDIR += pkcs7 diff --git a/regress/lib/libcrypto/objects/Makefile b/regress/lib/libcrypto/objects/Makefile new file mode 100644 index 00000000000..363023e13c8 --- /dev/null +++ b/regress/lib/libcrypto/objects/Makefile @@ -0,0 +1,9 @@ +# $OpenBSD: Makefile,v 1.1 2022/02/11 16:34:23 jsing Exp $ + +PROG= objectstest +LDADD= -lcrypto +DPADD= ${LIBCRYPTO} +WARNINGS= Yes +CFLAGS+= -DLIBRESSL_INTERNAL -Werror + +.include diff --git a/regress/lib/libcrypto/objects/objectstest.c b/regress/lib/libcrypto/objects/objectstest.c new file mode 100644 index 00000000000..1a9674cb484 --- /dev/null +++ b/regress/lib/libcrypto/objects/objectstest.c @@ -0,0 +1,438 @@ +/* $OpenBSD: objectstest.c,v 1.1 2022/02/11 16:34:23 jsing Exp $ */ +/* + * Copyright (c) 2017, 2022 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include + +static void +hexdump(const unsigned char *buf, size_t len) +{ + size_t i; + + for (i = 1; i <= len; i++) + fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); + + fprintf(stderr, "\n"); +} + +static int +obj_compare_bytes(const char *label, const unsigned char *d1, int len1, + const unsigned char *d2, int len2) +{ + if (len1 != len2) { + fprintf(stderr, "FAIL: %s - byte lengths differ " + "(%i != %i)\n", label, len1, len2); + fprintf(stderr, "Got:\n"); + hexdump(d1, len1); + fprintf(stderr, "Want:\n"); + hexdump(d2, len2); + return 0; + } + if (memcmp(d1, d2, len1) != 0) { + fprintf(stderr, "FAIL: %s - bytes differ\n", label); + fprintf(stderr, "Got:\n"); + hexdump(d1, len1); + fprintf(stderr, "Want:\n"); + hexdump(d2, len2); + return 0; + } + return 1; +} + +struct obj_test { + const char *oid; + const char *sn; + const char *ln; + int nid; + uint8_t data[255]; + size_t data_len; +}; + +struct obj_test obj_tests[] = { + { + .oid = NULL, + .sn = "UNDEF", + .ln = "undefined", + .nid = NID_undef, + }, + { + .oid = "2.5.4.10", + .sn = "O", + .ln = "organizationName", + .nid = NID_organizationName, + .data = { + 0x55, 0x04, 0x0a, + }, + .data_len = 3, + }, + { + .oid = "2.5.4.8", + .sn = "ST", + .ln = "stateOrProvinceName", + .nid = NID_stateOrProvinceName, + .data = { + 0x55, 0x04, 0x08, + }, + .data_len = 3, + }, + { + .oid = "1.3.6.1.4.1.11129.2.4.5", + .sn = "ct_cert_scts", + .ln = "CT Certificate SCTs", + .nid = NID_ct_cert_scts, + .data = { + 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, + 0x04, 0x05, + }, + .data_len = 10, + }, + { + .oid = "1.3.6.1.4.1", + .sn = "enterprises", + .ln = "Enterprises", + .nid = NID_Enterprises, + .data = { + 0x2b, 0x06, 0x01, 0x04, 0x01, + }, + .data_len = 5, + }, + { + .oid = "1.3.6.1.4.1.5454.1.70.6.11.2", + .nid = NID_undef, + .data = { + 0x2b, 0x06, 0x01, 0x04, 0x01, 0xaa, 0x4e, 0x01, + 0x46, 0x06, 0x0b, 0x02, + }, + .data_len = 12, + }, + { + .oid = "1.3.6.1.4.1.890.1.5.8.60.102.2", + .nid = NID_undef, + .data = { + 0x2b, 0x06, 0x01, 0x04, 0x01, 0x86, 0x7a, 0x01, + 0x05, 0x08, 0x3c, 0x66, 0x02, + }, + .data_len = 13, + }, + { + .oid = "1.3.6.1.4.1.173.7.3.4.1.1.26", + .nid = NID_undef, + .data = { + 0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0x2d, 0x07, + 0x03, 0x04, 0x01, 0x01, 0x1a, + }, + .data_len = 13, + }, +}; + +#define N_OBJ_TESTS (sizeof(obj_tests) / sizeof(*obj_tests)) + +static int +obj_name_test(struct obj_test *ot) +{ + const char *ln, *sn; + int nid; + int failed = 1; + + if (ot->ln != NULL) { + if ((nid = OBJ_ln2nid(ot->ln)) != ot->nid) { + fprintf(stderr, "FAIL: OBJ_ln2nid() for '%s' = %d, " + "want %d\n", ot->ln, nid, ot->nid); + goto failed; + } + if ((ln = OBJ_nid2ln(ot->nid)) == NULL) { + fprintf(stderr, "FAIL: OBJ_nid2ln() for '%s' returned " + "NULL\n", ot->oid); + goto failed; + } + if (strcmp(ln, ot->ln) != 0) { + fprintf(stderr, "FAIL: OBJ_nid2ln() for '%s' = '%s', " + "want '%s'\n", ot->oid, ln, ot->ln); + goto failed; + } + } + if (ot->sn != NULL) { + if ((nid = OBJ_sn2nid(ot->sn)) != ot->nid) { + fprintf(stderr, "FAIL: OBJ_sn2nid() for '%s' = %d, " + "want %d\n", ot->sn, nid, ot->nid); + goto failed; + } + if ((sn = OBJ_nid2sn(ot->nid)) == NULL) { + fprintf(stderr, "FAIL: OBJ_nid2sn() for '%s' returned " + "NULL\n", ot->oid); + goto failed; + } + if (strcmp(sn, ot->sn) != 0) { + fprintf(stderr, "FAIL: OBJ_nid2sn() for '%s' = '%s', " + "want '%s'\n", ot->oid, sn, ot->sn); + goto failed; + } + } + + failed = 0; + + failed: + return failed; +} + +static int +obj_name_tests(void) +{ + int failed = 0; + size_t i; + + for (i = 0; i < N_OBJ_TESTS; i++) + failed |= obj_name_test(&obj_tests[i]); + + return failed; +} + +static int +obj_nid_test(struct obj_test *ot) +{ + ASN1_OBJECT *obj = NULL; + int nid; + int failed = 1; + + if (ot->nid == NID_undef) + return 0; + + if ((obj = OBJ_nid2obj(ot->nid)) == NULL) { + fprintf(stderr, "FAIL: OBJ_nid2obj() failed for '%s' (NID %d)\n", + ot->oid, ot->nid); + goto failed; + } + if ((nid = OBJ_obj2nid(obj)) != ot->nid) { + fprintf(stderr, "FAIL: OBJ_obj2nid() failed for '%s' - got %d, " + "want %d\n", ot->oid ? ot->oid : "undef", nid, ot->nid); + goto failed; + } + + failed = 0; + + failed: + ASN1_OBJECT_free(obj); + + return failed; +} + +static int +obj_nid_tests(void) +{ + int failed = 0; + size_t i; + + for (i = 0; i < N_OBJ_TESTS; i++) + failed |= obj_nid_test(&obj_tests[i]); + + return failed; +} + +static int +obj_oid_test(struct obj_test *ot) +{ + ASN1_OBJECT *obj = NULL; + char buf[1024]; + int len, nid; + int failed = 1; + + if (ot->oid == NULL) + return 0; + + /* XXX - need to also test with no_name == 0. */ + + if ((obj = OBJ_txt2obj(ot->oid, 1)) == NULL) { + fprintf(stderr, "FAIL: OBJ_txt2obj() failed for '%s'\n", ot->oid); + goto failed; + } + if ((nid = OBJ_txt2nid(ot->oid)) != ot->nid) { + fprintf(stderr, "FAIL: OBJ_txt2nid() failed for '%s', got %d " + "want %d\n", ot->oid, nid, ot->nid); + goto failed; + } + + if (!obj_compare_bytes("object data", OBJ_get0_data(obj), OBJ_length(obj), + ot->data, ot->data_len)) + goto failed; + + len = OBJ_obj2txt(buf, sizeof(buf), obj, 1); + if (len <= 0 || (size_t)len >= sizeof(buf)) { + fprintf(stderr, "FAIL: OBJ_obj2txt() failed for '%s'\n", ot->oid); + goto failed; + } + if (strcmp(buf, ot->oid) != 0) { + fprintf(stderr, "FAIL: OBJ_obj2txt() returned '%s', want '%s'\n", + buf, ot->oid); + goto failed; + } + + failed = 0; + + failed: + ASN1_OBJECT_free(obj); + + return failed; +} + +static int +obj_oid_tests(void) +{ + int failed = 0; + size_t i; + + for (i = 0; i < N_OBJ_TESTS; i++) + failed |= obj_oid_test(&obj_tests[i]); + + return failed; +} + +/* OID 1.3.18446744073709551615 (64 bits). */ +const uint8_t asn1_large_oid1[] = { + 0x06, 0x0b, + 0x2b, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f, +}; + +/* OID 1.3.18446744073709551616 (65 bits). */ +const uint8_t asn1_large_oid2[] = { + 0x06, 0x0b, + 0x2b, 0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, + 0x80, 0x80, 0x00, +}; + +/* OID 1.3.340282366920938463463374607431768211455 (128 bits). */ +const uint8_t asn1_large_oid3[] = { + 0x06, 0x14, + 0x2b, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x7f, +}; + +/* OID 1.3.115792089237316195423570985008687907853269984665640564039457584007913129639935 (256 bits). */ +const uint8_t asn1_large_oid4[] = { + 0x06, 0x26, + 0x2b, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, +}; + +struct oid_large_test { + const char *oid; + const uint8_t *asn1_der; + size_t asn1_der_len; + int obj2txt; +}; + +struct oid_large_test oid_large_tests[] = { + { + .oid = "1.3.18446744073709551615", + .asn1_der = asn1_large_oid1, + .asn1_der_len = sizeof(asn1_large_oid1), + .obj2txt = 1, + }, + { + .oid = "1.3.18446744073709551616", + .asn1_der = asn1_large_oid2, + .asn1_der_len = sizeof(asn1_large_oid2), + .obj2txt = 1, + }, + { + .oid = "1.3.340282366920938463463374607431768211455", + .asn1_der = asn1_large_oid3, + .asn1_der_len = sizeof(asn1_large_oid3), + .obj2txt = 1, + }, + { + .oid = "1.3.115792089237316195423570985008687907853269984665640" + "564039457584007913129639935", + .asn1_der = asn1_large_oid4, + .asn1_der_len = sizeof(asn1_large_oid4), + .obj2txt = 1, + }, +}; + +#define N_OID_LARGE_TESTS (sizeof(oid_large_tests) / sizeof(*oid_large_tests)) + +static int +obj_oid_large_test(size_t test_no, struct oid_large_test *olt) +{ + ASN1_OBJECT *obj = NULL; + const uint8_t *p; + char buf[1024]; + int len; + int failed = 1; + + p = olt->asn1_der; + if ((obj = d2i_ASN1_OBJECT(NULL, &p, olt->asn1_der_len)) == NULL) { + fprintf(stderr, "FAIL: d2i_ASN1_OBJECT() failed for large " + "oid %zu\n", test_no); + goto failed; + } + len = OBJ_obj2txt(buf, sizeof(buf), obj, 1); + if (len < 0 || (size_t)len >= sizeof(buf)) { + fprintf(stderr, "FAIL: OBJ_obj2txt() failed for large " + "oid %zu\n", test_no); + goto failed; + } + if ((len != 0) != olt->obj2txt) { + fprintf(stderr, "FAIL: OBJ_obj2txt() failed for large " + "oid %zu\n", test_no); + goto failed; + } + if (len != 0 && strcmp(buf, olt->oid) != 0) { + fprintf(stderr, "FAIL: OBJ_obj2txt() returned '%s', want '%s'\n", + buf, olt->oid); + goto failed; + } + + failed = 0; + + failed: + ASN1_OBJECT_free(obj); + + return failed; +} + +static int +obj_oid_large_tests(void) +{ + int failed = 0; + size_t i; + + for (i = 0; i < N_OID_LARGE_TESTS; i++) + failed |= obj_oid_large_test(i, &oid_large_tests[i]); + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= obj_name_tests(); + failed |= obj_nid_tests(); + failed |= obj_oid_tests(); + failed |= obj_oid_large_tests(); + + return (failed); +} -- 2.20.1