250 lines
4.5 KiB
C
250 lines
4.5 KiB
C
/* $OpenBSD: bn_add_sub.c,v 1.3 2023/01/31 05:12:16 jsing 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/bn.h>
|
|
#include <openssl/err.h>
|
|
|
|
#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
|
|
|
|
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,
|
|
},
|
|
{
|
|
"11100000001",
|
|
"100000000001000000000",
|
|
"0",
|
|
0,
|
|
0,
|
|
},
|
|
{
|
|
"100000000000000000000",
|
|
"1",
|
|
"FFFFFFFFFFFFFFFFFFFF",
|
|
1,
|
|
1,
|
|
},
|
|
{
|
|
"1",
|
|
"0",
|
|
"1",
|
|
1,
|
|
1,
|
|
},
|
|
{
|
|
"1",
|
|
"2",
|
|
"FFFFFFFFFFFFFFFF",
|
|
0,
|
|
0,
|
|
},
|
|
{
|
|
"0",
|
|
"1",
|
|
"0",
|
|
0,
|
|
0,
|
|
},
|
|
};
|
|
|
|
void
|
|
print_failure_case(BIGNUM *a, BIGNUM *b, BIGNUM *e, BIGNUM *r, int i,
|
|
const char *testname)
|
|
{
|
|
fprintf(stderr, "%s #%d failed:", testname, i);
|
|
fprintf(stderr, "\na = ");
|
|
BN_print_fp(stderr, a);
|
|
fprintf(stderr, "\nb = ");
|
|
BN_print_fp(stderr, b);
|
|
fprintf(stderr, "\nexpected: e = ");
|
|
BN_print_fp(stderr, e);
|
|
fprintf(stderr, "\nobtained: r = ");
|
|
BN_print_fp(stderr, r);
|
|
fprintf(stderr, "\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_fp(stderr);
|
|
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_fp(stderr);
|
|
}
|
|
|
|
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 (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;
|
|
}
|