Add simple regression tests for BN_{,u}{add,sub}(3). With input from jca
authortb <tb@openbsd.org>
Tue, 10 Jul 2018 16:57:50 +0000 (16:57 +0000)
committertb <tb@openbsd.org>
Tue, 10 Jul 2018 16:57:50 +0000 (16:57 +0000)
regress/lib/libcrypto/bn/addsub/Makefile [new file with mode: 0644]
regress/lib/libcrypto/bn/addsub/bnaddsub.c [new file with mode: 0644]

diff --git a/regress/lib/libcrypto/bn/addsub/Makefile b/regress/lib/libcrypto/bn/addsub/Makefile
new file mode 100644 (file)
index 0000000..c35182d
--- /dev/null
@@ -0,0 +1,11 @@
+#      $OpenBSD: Makefile,v 1.1 2018/07/10 16:57:50 tb Exp $
+
+.include "../../Makefile.inc"
+
+PROG=          bnaddsub
+LDADD=         ${CRYPTO_INT}
+DPADD=         ${LIBCRYPTO}
+WARNINGS=      Yes
+CFLAGS+=       -Werror
+
+.include <bsd.regress.mk>
diff --git a/regress/lib/libcrypto/bn/addsub/bnaddsub.c b/regress/lib/libcrypto/bn/addsub/bnaddsub.c
new file mode 100644 (file)
index 0000000..6c47708
--- /dev/null
@@ -0,0 +1,237 @@
+/*     $OpenBSD: bnaddsub.c,v 1.1 2018/07/10 16:57:50 tb Exp $ */
+/*
+ * Copyright (c) 2018 Theo Buehler <tb@openbsd.org>
+ *
+ * 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.
+ */
+
+/* Test basic functionality of BN_add(), BN_sub(), BN_uadd() and BN_usub() */
+
+#include <err.h>
+#include <stdio.h>
+
+#include <openssl/bio.h>
+#include <openssl/bn.h>
+#include <openssl/err.h>
+
+#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
+
+BIO *bio_err;
+
+struct hexinput_st {
+       const char      *a_hex;
+       const char      *b_hex;
+       const char      *e_hex;         /* expected result */
+       const char       ret;           /* check return value */
+       int              compare;       /* use BN_cmp() to verify results */
+};
+
+int bn_op_test(int (*)(BIGNUM *, const BIGNUM *, const BIGNUM *),
+    struct hexinput_st[], unsigned int, const char *);
+void print_failure_case(BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, int,
+    const char *);
+
+struct hexinput_st test_bn_add[] = {
+       {
+               "F",
+               "F",
+               "1E",
+               1,
+               1,
+       },
+       {
+               "FFFFFFFFFFFFFFFFFFF",
+               "1",
+               "10000000000000000000",
+               1,
+               1,
+       },
+       {
+               "7878787878787878",
+               "1010101010101010",
+               "8888888888888888",
+               1,
+               1,
+       },
+       {
+               "FFFFFFFFFFFFFFFF0000000000000000",
+               "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+               "1FFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
+               1,
+               1,
+       },
+       {
+               "F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0",
+               "10101010101010101010101010101010",
+               "101010101010101010101010101010100",
+               1,
+               1,
+       },
+};
+
+struct hexinput_st test_bn_sub[] = {
+       {
+               "10",
+               "1",
+               "F",
+               1,
+               1,
+       },
+       {
+               "10",
+               "1",
+               "E",
+               1,
+               0,
+       },
+       {
+               "100000000001000000000",
+               "11100000001",
+               "FFFFFFFFFEFEFFFFFFFF",
+               1,
+               1,
+       },
+       {
+               "-FFFFFFFFFFFFFFFFFFFF",
+               "1",
+               "-100000000000000000000",
+               1,
+               1,
+       },
+};
+
+struct hexinput_st test_bn_usub[] = {
+       {
+               "10",
+               "1",
+               "F",
+               1,
+               1,
+       },
+       {
+               "10",
+               "1",
+               "E",
+               1,
+               0,
+       },
+       {
+               "100000000001000000000",
+               "11100000001",
+               "FFFFFFFFFEFEFFFFFFFF",
+               1,
+               1,
+       },
+       {
+               "100000000000000000000",
+               "1",
+               "FFFFFFFFFFFFFFFFFFFF",
+               1,
+               1,
+       },
+       {
+               "0",
+               "1",
+               "0",
+               0,
+               0,
+       },
+};
+
+void
+print_failure_case(BIGNUM *a, BIGNUM *b, BIGNUM *e, BIGNUM *r, int i,
+    const char *testname)
+{
+       BIO_printf(bio_err, "%s #%d failed:", testname, i);
+       BIO_printf(bio_err, "\na = ");
+       BN_print(bio_err, a);
+       BIO_printf(bio_err, "\nb = ");
+       BN_print(bio_err, b);
+       BIO_printf(bio_err, "\nexpected: e = ");
+       BN_print(bio_err, e);
+       BIO_printf(bio_err, "\nobtained: r = ");
+       BN_print(bio_err, r);
+       BIO_printf(bio_err, "\n");
+}
+
+int
+bn_op_test(int (*bn_op)(BIGNUM *, const BIGNUM *, const BIGNUM *),
+    struct hexinput_st tests[], unsigned int ntests, const char *testname)
+{
+       BIGNUM          *a = NULL, *b = NULL, *e = NULL, *r = NULL;
+       unsigned int     i;
+       int              failed = 0;
+
+       if (((a = BN_new()) == NULL) ||
+           ((b = BN_new()) == NULL) ||
+           ((e = BN_new()) == NULL) ||
+           ((r = BN_new()) == NULL)) {
+               failed = 1;
+               ERR_print_errors(bio_err);
+               goto err;
+       }
+
+       for (i = 0; i < ntests; i++) {
+               int print = 0;
+
+               if (!BN_hex2bn(&a, tests[i].a_hex) ||
+                   !BN_hex2bn(&b, tests[i].b_hex) ||
+                   !BN_hex2bn(&e, tests[i].e_hex)) {
+                       print = 1;
+                       ERR_print_errors(bio_err);
+               }
+
+               if (tests[i].ret != bn_op(r, a, b))
+                       print = 1;
+               if (tests[i].compare == 1 && BN_cmp(e, r) != 0)
+                       print = 1;
+               if (print) {
+                       failed = 1;
+                       print_failure_case(a, b, e, r, i, testname);
+               }
+       }
+
+ err:
+       BN_free(a);
+       BN_free(b);
+       BN_free(e);
+       BN_free(r);
+       return failed;
+}
+
+int
+main(int argc, char *argv[])
+{
+       int failed = 0;
+
+       if ((bio_err = BIO_new_fp(stderr, BIO_NOCLOSE)) == NULL) {
+               fprintf(stderr, "%s: failed to initialize bio_err",
+                   getprogname());
+               return 1;
+       }
+
+       if (bn_op_test(BN_add, test_bn_add, nitems(test_bn_add),
+           "BN_add with test_bn_add[]"))
+               failed = 1;
+       if (bn_op_test(BN_uadd, test_bn_add, nitems(test_bn_add),
+           "BN_uadd with test_bn_add[]"))
+               failed = 1;
+       if (bn_op_test(BN_sub, test_bn_sub, nitems(test_bn_sub),
+           "BN_sub with test_bn_sub[]"))
+               failed = 1;
+       if (bn_op_test(BN_usub, test_bn_usub, nitems(test_bn_usub),
+           "BN_usub with test_bn_usub[]"))
+               failed = 1;
+
+       return failed;
+}