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