xref: /openbsd-src/regress/lib/libcrypto/bn/bn_add_sub.c (revision 3879165ed9e5a93bd2045caa856e4bf3d699a16a)
1 /*	$OpenBSD: bn_add_sub.c,v 1.3 2023/01/31 05:12:16 jsing Exp $	*/
2 /*
3  * Copyright (c) 2018 Theo Buehler <tb@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /* Test basic functionality of BN_add(), BN_sub(), BN_uadd() and BN_usub() */
19 
20 #include <err.h>
21 #include <stdio.h>
22 
23 #include <openssl/bn.h>
24 #include <openssl/err.h>
25 
26 #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
27 
28 struct hexinput_st {
29 	const char	*a_hex;
30 	const char	*b_hex;
31 	const char	*e_hex;		/* expected result */
32 	const char	 ret;		/* check return value */
33 	int		 compare;	/* use BN_cmp() to verify results */
34 };
35 
36 int bn_op_test(int (*)(BIGNUM *, const BIGNUM *, const BIGNUM *),
37     struct hexinput_st[], unsigned int, const char *);
38 void print_failure_case(BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, int,
39     const char *);
40 
41 struct hexinput_st test_bn_add[] = {
42 	{
43 		"F",
44 		"F",
45 		"1E",
46 		1,
47 		1,
48 	},
49 	{
50 		"FFFFFFFFFFFFFFFFFFF",
51 		"1",
52 		"10000000000000000000",
53 		1,
54 		1,
55 	},
56 	{
57 		"7878787878787878",
58 		"1010101010101010",
59 		"8888888888888888",
60 		1,
61 		1,
62 	},
63 	{
64 		"FFFFFFFFFFFFFFFF0000000000000000",
65 		"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
66 		"1FFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
67 		1,
68 		1,
69 	},
70 	{
71 		"F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0",
72 		"10101010101010101010101010101010",
73 		"101010101010101010101010101010100",
74 		1,
75 		1,
76 	},
77 };
78 
79 struct hexinput_st test_bn_sub[] = {
80 	{
81 		"10",
82 		"1",
83 		"F",
84 		1,
85 		1,
86 	},
87 	{
88 		"10",
89 		"1",
90 		"E",
91 		1,
92 		0,
93 	},
94 	{
95 		"100000000001000000000",
96 		"11100000001",
97 		"FFFFFFFFFEFEFFFFFFFF",
98 		1,
99 		1,
100 	},
101 	{
102 		"-FFFFFFFFFFFFFFFFFFFF",
103 		"1",
104 		"-100000000000000000000",
105 		1,
106 		1,
107 	},
108 };
109 
110 struct hexinput_st test_bn_usub[] = {
111 	{
112 		"10",
113 		"1",
114 		"F",
115 		1,
116 		1,
117 	},
118 	{
119 		"10",
120 		"1",
121 		"E",
122 		1,
123 		0,
124 	},
125 	{
126 		"100000000001000000000",
127 		"11100000001",
128 		"FFFFFFFFFEFEFFFFFFFF",
129 		1,
130 		1,
131 	},
132 	{
133 		"11100000001",
134 		"100000000001000000000",
135 		"0",
136 		0,
137 		0,
138 	},
139 	{
140 		"100000000000000000000",
141 		"1",
142 		"FFFFFFFFFFFFFFFFFFFF",
143 		1,
144 		1,
145 	},
146 	{
147 		"1",
148 		"0",
149 		"1",
150 		1,
151 		1,
152 	},
153 	{
154 		"1",
155 		"2",
156 		"FFFFFFFFFFFFFFFF",
157 		0,
158 		0,
159 	},
160 	{
161 		"0",
162 		"1",
163 		"0",
164 		0,
165 		0,
166 	},
167 };
168 
169 void
print_failure_case(BIGNUM * a,BIGNUM * b,BIGNUM * e,BIGNUM * r,int i,const char * testname)170 print_failure_case(BIGNUM *a, BIGNUM *b, BIGNUM *e, BIGNUM *r, int i,
171     const char *testname)
172 {
173 	fprintf(stderr, "%s #%d failed:", testname, i);
174 	fprintf(stderr, "\na = ");
175 	BN_print_fp(stderr, a);
176 	fprintf(stderr, "\nb = ");
177 	BN_print_fp(stderr, b);
178 	fprintf(stderr, "\nexpected: e = ");
179 	BN_print_fp(stderr, e);
180 	fprintf(stderr, "\nobtained: r = ");
181 	BN_print_fp(stderr, r);
182 	fprintf(stderr, "\n");
183 }
184 
185 int
bn_op_test(int (* bn_op)(BIGNUM *,const BIGNUM *,const BIGNUM *),struct hexinput_st tests[],unsigned int ntests,const char * testname)186 bn_op_test(int (*bn_op)(BIGNUM *, const BIGNUM *, const BIGNUM *),
187     struct hexinput_st tests[], unsigned int ntests, const char *testname)
188 {
189 	BIGNUM		*a = NULL, *b = NULL, *e = NULL, *r = NULL;
190 	unsigned int	 i;
191 	int		 failed = 0;
192 
193 	if (((a = BN_new()) == NULL) ||
194 	    ((b = BN_new()) == NULL) ||
195 	    ((e = BN_new()) == NULL) ||
196 	    ((r = BN_new()) == NULL)) {
197 		failed = 1;
198 		ERR_print_errors_fp(stderr);
199 		goto err;
200 	}
201 
202 	for (i = 0; i < ntests; i++) {
203 		int print = 0;
204 
205 		if (!BN_hex2bn(&a, tests[i].a_hex) ||
206 		    !BN_hex2bn(&b, tests[i].b_hex) ||
207 		    !BN_hex2bn(&e, tests[i].e_hex)) {
208 			print = 1;
209 			ERR_print_errors_fp(stderr);
210 		}
211 
212 		if (tests[i].ret != bn_op(r, a, b))
213 			print = 1;
214 		if (tests[i].compare == 1 && BN_cmp(e, r) != 0)
215 			print = 1;
216 		if (print) {
217 			failed = 1;
218 			print_failure_case(a, b, e, r, i, testname);
219 		}
220 	}
221 
222  err:
223 	BN_free(a);
224 	BN_free(b);
225 	BN_free(e);
226 	BN_free(r);
227 	return failed;
228 }
229 
230 int
main(int argc,char * argv[])231 main(int argc, char *argv[])
232 {
233 	int failed = 0;
234 
235 	if (bn_op_test(BN_add, test_bn_add, nitems(test_bn_add),
236 	    "BN_add with test_bn_add[]"))
237 		failed = 1;
238 	if (bn_op_test(BN_uadd, test_bn_add, nitems(test_bn_add),
239 	    "BN_uadd with test_bn_add[]"))
240 		failed = 1;
241 	if (bn_op_test(BN_sub, test_bn_sub, nitems(test_bn_sub),
242 	    "BN_sub with test_bn_sub[]"))
243 		failed = 1;
244 	if (bn_op_test(BN_usub, test_bn_usub, nitems(test_bn_usub),
245 	    "BN_usub with test_bn_usub[]"))
246 		failed = 1;
247 
248 	return failed;
249 }
250