xref: /openbsd-src/regress/lib/libcrypto/bn/bn_word.c (revision 6822f9c8033774f6aab00bcb43e8718e7034e67d)
1*6822f9c8Santon /* $OpenBSD: bn_word.c,v 1.2 2024/08/23 12:56:26 anton Exp $ */
2e3cbfed8Sjsing /*
3e3cbfed8Sjsing  * Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
4e3cbfed8Sjsing  *
5e3cbfed8Sjsing  * Permission to use, copy, modify, and distribute this software for any
6e3cbfed8Sjsing  * purpose with or without fee is hereby granted, provided that the above
7e3cbfed8Sjsing  * copyright notice and this permission notice appear in all copies.
8e3cbfed8Sjsing  *
9e3cbfed8Sjsing  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10e3cbfed8Sjsing  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11e3cbfed8Sjsing  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12e3cbfed8Sjsing  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13e3cbfed8Sjsing  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14e3cbfed8Sjsing  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15e3cbfed8Sjsing  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16e3cbfed8Sjsing  */
17e3cbfed8Sjsing 
18e3cbfed8Sjsing #include <err.h>
19e3cbfed8Sjsing #include <string.h>
20e3cbfed8Sjsing 
21e3cbfed8Sjsing #include <openssl/bn.h>
22e3cbfed8Sjsing 
23e3cbfed8Sjsing struct bn_word_test {
24e3cbfed8Sjsing 	const char *in_hex;
25e3cbfed8Sjsing 	BN_ULONG in_word;
26e3cbfed8Sjsing 	BN_ULONG mod_word;
27e3cbfed8Sjsing 	BN_ULONG out_word;
28e3cbfed8Sjsing 	const char *out_hex;
29e3cbfed8Sjsing 	int out_is_negative;
30e3cbfed8Sjsing };
31e3cbfed8Sjsing 
32e3cbfed8Sjsing static int
33e3cbfed8Sjsing check_bn_word_test(const char *op_name, const BIGNUM *bn,
34e3cbfed8Sjsing     const struct bn_word_test *bwt)
35e3cbfed8Sjsing {
36e3cbfed8Sjsing 	char *out_hex = NULL;
37e3cbfed8Sjsing 	BN_ULONG out_word;
38e3cbfed8Sjsing 	int failed = 1;
39e3cbfed8Sjsing 
40e3cbfed8Sjsing 	if ((out_word = BN_get_word(bn)) != bwt->out_word) {
41e3cbfed8Sjsing 		fprintf(stderr, "FAIL %s: Got word %lx, want %lx\n",
42e3cbfed8Sjsing 		    op_name, (unsigned long)out_word,
43e3cbfed8Sjsing 		    (unsigned long)bwt->out_word);
44e3cbfed8Sjsing 		goto failure;
45e3cbfed8Sjsing 	}
46e3cbfed8Sjsing 
47e3cbfed8Sjsing 	if (BN_is_negative(bn) != bwt->out_is_negative) {
48e3cbfed8Sjsing 		fprintf(stderr, "FAIL %s: Got is negative %d, want %d\n",
49e3cbfed8Sjsing 		    op_name, BN_is_negative(bn), bwt->out_is_negative);
50e3cbfed8Sjsing 		goto failure;
51e3cbfed8Sjsing 	}
52e3cbfed8Sjsing 
53e3cbfed8Sjsing 	if ((out_hex = BN_bn2hex(bn)) == NULL)
54*6822f9c8Santon 		errx(1, "BN_bn2hex() failed");
55e3cbfed8Sjsing 
56e3cbfed8Sjsing 	if (strcmp(out_hex, bwt->out_hex) != 0) {
57e3cbfed8Sjsing 		fprintf(stderr, "FAIL %s: Got hex %s, want %s\n",
58e3cbfed8Sjsing 		    op_name, out_hex, bwt->out_hex);
59e3cbfed8Sjsing 		goto failure;
60e3cbfed8Sjsing 	}
61e3cbfed8Sjsing 
62e3cbfed8Sjsing 	if (BN_is_zero(bn) && BN_is_negative(bn) != 0) {
63e3cbfed8Sjsing 		fprintf(stderr, "FAIL %s: Got negative zero\n", op_name);
64e3cbfed8Sjsing 		goto failure;
65e3cbfed8Sjsing 	}
66e3cbfed8Sjsing 
67e3cbfed8Sjsing 	failed = 0;
68e3cbfed8Sjsing 
69e3cbfed8Sjsing  failure:
70e3cbfed8Sjsing 	free(out_hex);
71e3cbfed8Sjsing 
72e3cbfed8Sjsing 	return failed;
73e3cbfed8Sjsing }
74e3cbfed8Sjsing 
75e3cbfed8Sjsing static int
76e3cbfed8Sjsing test_bn_word(int (*bn_word_op)(BIGNUM *, BN_ULONG), const char *op_name,
77e3cbfed8Sjsing     const struct bn_word_test *bwts, size_t num_tests)
78e3cbfed8Sjsing {
79e3cbfed8Sjsing 	const struct bn_word_test *bwt;
80e3cbfed8Sjsing 	BIGNUM *bn;
81e3cbfed8Sjsing 	size_t i;
82e3cbfed8Sjsing 	int failed = 0;
83e3cbfed8Sjsing 
84e3cbfed8Sjsing 	if ((bn = BN_new()) == NULL)
85*6822f9c8Santon 		errx(1, "BN_new() failed");
86e3cbfed8Sjsing 
87e3cbfed8Sjsing 	for (i = 0; i < num_tests; i++) {
88e3cbfed8Sjsing 		bwt = &bwts[i];
89e3cbfed8Sjsing 
90e3cbfed8Sjsing 		if (!BN_hex2bn(&bn, bwt->in_hex)) {
91e3cbfed8Sjsing 			fprintf(stderr, "FAIL: BN_hex2bn(\"%s\") failed\n",
92e3cbfed8Sjsing 			    bwt->in_hex);
93e3cbfed8Sjsing 			failed = 1;
94e3cbfed8Sjsing 			continue;
95e3cbfed8Sjsing 		}
96e3cbfed8Sjsing 
97e3cbfed8Sjsing 		if (!bn_word_op(bn, bwt->in_word)) {
98e3cbfed8Sjsing 			fprintf(stderr, "FAIL: %s(%lx) failed\n", op_name,
99e3cbfed8Sjsing 			     (unsigned long)bwt->in_word);
100e3cbfed8Sjsing 			failed = 1;
101e3cbfed8Sjsing 			continue;
102e3cbfed8Sjsing 		}
103e3cbfed8Sjsing 
104e3cbfed8Sjsing 		failed |= check_bn_word_test(op_name, bn, bwt);
105e3cbfed8Sjsing 	}
106e3cbfed8Sjsing 
107e3cbfed8Sjsing 	BN_free(bn);
108e3cbfed8Sjsing 
109e3cbfed8Sjsing 	return failed;
110e3cbfed8Sjsing }
111e3cbfed8Sjsing 
112e3cbfed8Sjsing static const struct bn_word_test bn_add_word_tests[] = {
113e3cbfed8Sjsing 	{
114e3cbfed8Sjsing 		.in_hex = "1",
115e3cbfed8Sjsing 		.in_word = 0,
116e3cbfed8Sjsing 		.out_word = 1,
117e3cbfed8Sjsing 		.out_hex = "01",
118e3cbfed8Sjsing 	},
119e3cbfed8Sjsing 	{
120e3cbfed8Sjsing 		.in_hex = "0",
121e3cbfed8Sjsing 		.in_word = 1,
122e3cbfed8Sjsing 		.out_word = 1,
123e3cbfed8Sjsing 		.out_hex = "01",
124e3cbfed8Sjsing 	},
125e3cbfed8Sjsing 	{
126e3cbfed8Sjsing 		.in_hex = "1",
127e3cbfed8Sjsing 		.in_word = 1,
128e3cbfed8Sjsing 		.out_word = 2,
129e3cbfed8Sjsing 		.out_hex = "02",
130e3cbfed8Sjsing 	},
131e3cbfed8Sjsing 	{
132e3cbfed8Sjsing 		.in_hex = "-1",
133e3cbfed8Sjsing 		.in_word = 2,
134e3cbfed8Sjsing 		.out_word = 1,
135e3cbfed8Sjsing 		.out_hex = "01",
136e3cbfed8Sjsing 	},
137e3cbfed8Sjsing 	{
138e3cbfed8Sjsing 		.in_hex = "-1",
139e3cbfed8Sjsing 		.in_word = 1,
140e3cbfed8Sjsing 		.out_word = 0,
141e3cbfed8Sjsing 		.out_hex = "0",
142e3cbfed8Sjsing 	},
143e3cbfed8Sjsing 	{
144e3cbfed8Sjsing 		.in_hex = "-3",
145e3cbfed8Sjsing 		.in_word = 2,
146e3cbfed8Sjsing 		.out_word = 1,
147e3cbfed8Sjsing 		.out_hex = "-01",
148e3cbfed8Sjsing 		.out_is_negative = 1,
149e3cbfed8Sjsing 	},
150e3cbfed8Sjsing 	{
151e3cbfed8Sjsing 		.in_hex = "1",
152e3cbfed8Sjsing 		.in_word = 0xfffffffeUL,
153e3cbfed8Sjsing 		.out_word = 0xffffffffUL,
154e3cbfed8Sjsing 		.out_hex = "FFFFFFFF",
155e3cbfed8Sjsing 	},
156e3cbfed8Sjsing 	{
157e3cbfed8Sjsing 		.in_hex = "FFFFFFFFFFFFFFFF",
158e3cbfed8Sjsing 		.in_word = 1,
159e3cbfed8Sjsing 		.out_word = BN_MASK2,
160e3cbfed8Sjsing 		.out_hex = "010000000000000000",
161e3cbfed8Sjsing 	},
162e3cbfed8Sjsing };
163e3cbfed8Sjsing 
164e3cbfed8Sjsing #define N_BN_ADD_WORD_TESTS \
165e3cbfed8Sjsing     (sizeof(bn_add_word_tests) / sizeof(bn_add_word_tests[0]))
166e3cbfed8Sjsing 
167e3cbfed8Sjsing static int
168e3cbfed8Sjsing test_bn_add_word(void)
169e3cbfed8Sjsing {
170e3cbfed8Sjsing 	return test_bn_word(BN_add_word, "BN_add_word", bn_add_word_tests,
171e3cbfed8Sjsing 	    N_BN_ADD_WORD_TESTS);
172e3cbfed8Sjsing }
173e3cbfed8Sjsing 
174e3cbfed8Sjsing static const struct bn_word_test bn_sub_word_tests[] = {
175e3cbfed8Sjsing 	{
176e3cbfed8Sjsing 		.in_hex = "1",
177e3cbfed8Sjsing 		.in_word = 0,
178e3cbfed8Sjsing 		.out_word = 1,
179e3cbfed8Sjsing 		.out_hex = "01",
180e3cbfed8Sjsing 	},
181e3cbfed8Sjsing 	{
182e3cbfed8Sjsing 		.in_hex = "0",
183e3cbfed8Sjsing 		.in_word = 1,
184e3cbfed8Sjsing 		.out_word = 1,
185e3cbfed8Sjsing 		.out_hex = "-01",
186e3cbfed8Sjsing 		.out_is_negative = 1,
187e3cbfed8Sjsing 	},
188e3cbfed8Sjsing 	{
189e3cbfed8Sjsing 		.in_hex = "1",
190e3cbfed8Sjsing 		.in_word = 1,
191e3cbfed8Sjsing 		.out_word = 0,
192e3cbfed8Sjsing 		.out_hex = "0",
193e3cbfed8Sjsing 	},
194e3cbfed8Sjsing 	{
195e3cbfed8Sjsing 		.in_hex = "2",
196e3cbfed8Sjsing 		.in_word = 1,
197e3cbfed8Sjsing 		.out_word = 1,
198e3cbfed8Sjsing 		.out_hex = "01",
199e3cbfed8Sjsing 	},
200e3cbfed8Sjsing 	{
201e3cbfed8Sjsing 		.in_hex = "-1",
202e3cbfed8Sjsing 		.in_word = 2,
203e3cbfed8Sjsing 		.out_word = 3,
204e3cbfed8Sjsing 		.out_hex = "-03",
205e3cbfed8Sjsing 		.out_is_negative = 1,
206e3cbfed8Sjsing 	},
207e3cbfed8Sjsing 	{
208e3cbfed8Sjsing 		.in_hex = "1",
209e3cbfed8Sjsing 		.in_word = 1,
210e3cbfed8Sjsing 		.out_word = 0,
211e3cbfed8Sjsing 		.out_hex = "0",
212e3cbfed8Sjsing 	},
213e3cbfed8Sjsing 	{
214e3cbfed8Sjsing 		.in_hex = "3",
215e3cbfed8Sjsing 		.in_word = 2,
216e3cbfed8Sjsing 		.out_word = 1,
217e3cbfed8Sjsing 		.out_hex = "01",
218e3cbfed8Sjsing 	},
219e3cbfed8Sjsing 	{
220e3cbfed8Sjsing 		.in_hex = "-3",
221e3cbfed8Sjsing 		.in_word = 2,
222e3cbfed8Sjsing 		.out_word = 5,
223e3cbfed8Sjsing 		.out_hex = "-05",
224e3cbfed8Sjsing 		.out_is_negative = 1,
225e3cbfed8Sjsing 	},
226e3cbfed8Sjsing 	{
227e3cbfed8Sjsing 		.in_hex = "-1",
228e3cbfed8Sjsing 		.in_word = 0xfffffffeUL,
229e3cbfed8Sjsing 		.out_word = 0xffffffffUL,
230e3cbfed8Sjsing 		.out_hex = "-FFFFFFFF",
231e3cbfed8Sjsing 		.out_is_negative = 1,
232e3cbfed8Sjsing 	},
233e3cbfed8Sjsing 	{
234e3cbfed8Sjsing 		.in_hex = "010000000000000000",
235e3cbfed8Sjsing 		.in_word = 1,
236e3cbfed8Sjsing 		.out_word = BN_MASK2,
237e3cbfed8Sjsing 		.out_hex = "FFFFFFFFFFFFFFFF",
238e3cbfed8Sjsing 	},
239e3cbfed8Sjsing };
240e3cbfed8Sjsing 
241e3cbfed8Sjsing #define N_BN_SUB_WORD_TESTS \
242e3cbfed8Sjsing     (sizeof(bn_sub_word_tests) / sizeof(bn_sub_word_tests[0]))
243e3cbfed8Sjsing 
244e3cbfed8Sjsing static int
245e3cbfed8Sjsing test_bn_sub_word(void)
246e3cbfed8Sjsing {
247e3cbfed8Sjsing 	return test_bn_word(BN_sub_word, "BN_sub_word", bn_sub_word_tests,
248e3cbfed8Sjsing 	    N_BN_SUB_WORD_TESTS);
249e3cbfed8Sjsing }
250e3cbfed8Sjsing 
251e3cbfed8Sjsing static const struct bn_word_test bn_mul_word_tests[] = {
252e3cbfed8Sjsing 	{
253e3cbfed8Sjsing 		.in_hex = "1",
254e3cbfed8Sjsing 		.in_word = 0,
255e3cbfed8Sjsing 		.out_word = 0,
256e3cbfed8Sjsing 		.out_hex = "0",
257e3cbfed8Sjsing 	},
258e3cbfed8Sjsing 	{
259e3cbfed8Sjsing 		.in_hex = "0",
260e3cbfed8Sjsing 		.in_word = 1,
261e3cbfed8Sjsing 		.out_word = 0,
262e3cbfed8Sjsing 		.out_hex = "0",
263e3cbfed8Sjsing 	},
264e3cbfed8Sjsing 	{
265e3cbfed8Sjsing 		.in_hex = "1",
266e3cbfed8Sjsing 		.in_word = 1,
267e3cbfed8Sjsing 		.out_word = 1,
268e3cbfed8Sjsing 		.out_hex = "01",
269e3cbfed8Sjsing 	},
270e3cbfed8Sjsing 	{
271e3cbfed8Sjsing 		.in_hex = "-1",
272e3cbfed8Sjsing 		.in_word = 0,
273e3cbfed8Sjsing 		.out_word = 0,
274e3cbfed8Sjsing 		.out_hex = "0",
275e3cbfed8Sjsing 	},
276e3cbfed8Sjsing 	{
277e3cbfed8Sjsing 		.in_hex = "-1",
278e3cbfed8Sjsing 		.in_word = 1,
279e3cbfed8Sjsing 		.out_word = 1,
280e3cbfed8Sjsing 		.out_hex = "-01",
281e3cbfed8Sjsing 		.out_is_negative = 1,
282e3cbfed8Sjsing 	},
283e3cbfed8Sjsing 	{
284e3cbfed8Sjsing 		.in_hex = "-3",
285e3cbfed8Sjsing 		.in_word = 2,
286e3cbfed8Sjsing 		.out_word = 6,
287e3cbfed8Sjsing 		.out_hex = "-06",
288e3cbfed8Sjsing 		.out_is_negative = 1,
289e3cbfed8Sjsing 	},
290e3cbfed8Sjsing 	{
291e3cbfed8Sjsing 		.in_hex = "1",
292e3cbfed8Sjsing 		.in_word = 0xfffffffeUL,
293e3cbfed8Sjsing 		.out_word = 0xfffffffeUL,
294e3cbfed8Sjsing 		.out_hex = "FFFFFFFE",
295e3cbfed8Sjsing 	},
296e3cbfed8Sjsing 	{
297e3cbfed8Sjsing 		.in_hex = "010000000000000000",
298e3cbfed8Sjsing 		.in_word = 2,
299e3cbfed8Sjsing 		.out_word = BN_MASK2,
300e3cbfed8Sjsing 		.out_hex = "020000000000000000",
301e3cbfed8Sjsing 	},
302e3cbfed8Sjsing };
303e3cbfed8Sjsing 
304e3cbfed8Sjsing #define N_BN_MUL_WORD_TESTS \
305e3cbfed8Sjsing     (sizeof(bn_mul_word_tests) / sizeof(bn_mul_word_tests[0]))
306e3cbfed8Sjsing 
307e3cbfed8Sjsing static int
308e3cbfed8Sjsing test_bn_mul_word(void)
309e3cbfed8Sjsing {
310e3cbfed8Sjsing 	return test_bn_word(BN_mul_word, "BN_mul_word", bn_mul_word_tests,
311e3cbfed8Sjsing 	    N_BN_MUL_WORD_TESTS);
312e3cbfed8Sjsing }
313e3cbfed8Sjsing 
314e3cbfed8Sjsing static const struct bn_word_test bn_div_word_tests[] = {
315e3cbfed8Sjsing 	{
316e3cbfed8Sjsing 		.in_hex = "1",
317e3cbfed8Sjsing 		.in_word = 0,
318e3cbfed8Sjsing 		.mod_word = BN_MASK2,
319e3cbfed8Sjsing 		.out_word = 1,
320e3cbfed8Sjsing 		.out_hex = "01",
321e3cbfed8Sjsing 	},
322e3cbfed8Sjsing 	{
323e3cbfed8Sjsing 		.in_hex = "0",
324e3cbfed8Sjsing 		.in_word = 1,
325e3cbfed8Sjsing 		.mod_word = 0,
326e3cbfed8Sjsing 		.out_word = 0,
327e3cbfed8Sjsing 		.out_hex = "0",
328e3cbfed8Sjsing 	},
329e3cbfed8Sjsing 	{
330e3cbfed8Sjsing 		.in_hex = "4",
331e3cbfed8Sjsing 		.in_word = 2,
332e3cbfed8Sjsing 		.mod_word = 0,
333e3cbfed8Sjsing 		.out_word = 2,
334e3cbfed8Sjsing 		.out_hex = "02",
335e3cbfed8Sjsing 	},
336e3cbfed8Sjsing 	{
337e3cbfed8Sjsing 		.in_hex = "7",
338e3cbfed8Sjsing 		.in_word = 3,
339e3cbfed8Sjsing 		.mod_word = 1,
340e3cbfed8Sjsing 		.out_word = 2,
341e3cbfed8Sjsing 		.out_hex = "02",
342e3cbfed8Sjsing 	},
343e3cbfed8Sjsing 	{
344e3cbfed8Sjsing 		.in_hex = "1",
345e3cbfed8Sjsing 		.in_word = 1,
346e3cbfed8Sjsing 		.mod_word = 0,
347e3cbfed8Sjsing 		.out_word = 1,
348e3cbfed8Sjsing 		.out_hex = "01",
349e3cbfed8Sjsing 	},
350e3cbfed8Sjsing 	{
351e3cbfed8Sjsing 		.in_hex = "-2",
352e3cbfed8Sjsing 		.in_word = 1,
353e3cbfed8Sjsing 		.mod_word = 0,
354e3cbfed8Sjsing 		.out_word = 2,
355e3cbfed8Sjsing 		.out_hex = "-02",
356e3cbfed8Sjsing 		.out_is_negative = 1,
357e3cbfed8Sjsing 	},
358e3cbfed8Sjsing 	{
359e3cbfed8Sjsing 		.in_hex = "-1",
360e3cbfed8Sjsing 		.in_word = 2,
361e3cbfed8Sjsing 		.mod_word = 1,
362e3cbfed8Sjsing 		.out_word = 0,
363e3cbfed8Sjsing 		.out_hex = "0",
364e3cbfed8Sjsing 	},
365e3cbfed8Sjsing 	{
366e3cbfed8Sjsing 		.in_hex = "-3",
367e3cbfed8Sjsing 		.in_word = 2,
368e3cbfed8Sjsing 		.mod_word = 1,
369e3cbfed8Sjsing 		.out_word = 1,
370e3cbfed8Sjsing 		.out_hex = "-01",
371e3cbfed8Sjsing 		.out_is_negative = 1,
372e3cbfed8Sjsing 	},
373e3cbfed8Sjsing 	{
374e3cbfed8Sjsing 		.in_hex = "1",
375e3cbfed8Sjsing 		.in_word = 0xffffffffUL,
376e3cbfed8Sjsing 		.mod_word = 1,
377e3cbfed8Sjsing 		.out_word = 0,
378e3cbfed8Sjsing 		.out_hex = "0",
379e3cbfed8Sjsing 	},
380e3cbfed8Sjsing 	{
381e3cbfed8Sjsing 		.in_hex = "FFFFFFFF",
382e3cbfed8Sjsing 		.in_word = 1,
383e3cbfed8Sjsing 		.mod_word = 0,
384e3cbfed8Sjsing 		.out_word = 0xffffffffUL,
385e3cbfed8Sjsing 		.out_hex = "FFFFFFFF",
386e3cbfed8Sjsing 	},
387e3cbfed8Sjsing 	{
388e3cbfed8Sjsing 		.in_hex = "FFFFFFFE",
389e3cbfed8Sjsing 		.in_word = 0xffffffffUL,
390e3cbfed8Sjsing 		.mod_word = 0xfffffffeUL,
391e3cbfed8Sjsing 		.out_word = 0,
392e3cbfed8Sjsing 		.out_hex = "0",
393e3cbfed8Sjsing 	},
394e3cbfed8Sjsing 	{
395e3cbfed8Sjsing 		.in_hex = "FFFFFFFFFFFFFFFF",
396e3cbfed8Sjsing 		.in_word = 1,
397e3cbfed8Sjsing 		.mod_word = 0,
398e3cbfed8Sjsing 		.out_word = BN_MASK2,
399e3cbfed8Sjsing 		.out_hex = "FFFFFFFFFFFFFFFF",
400e3cbfed8Sjsing 	},
401e3cbfed8Sjsing 	{
402e3cbfed8Sjsing 		.in_hex = "FFFFFFFF",
403e3cbfed8Sjsing 		.in_word = 0xff,
404e3cbfed8Sjsing 		.mod_word = 0,
405e3cbfed8Sjsing 		.out_word = 0x1010101UL,
406e3cbfed8Sjsing 		.out_hex = "01010101",
407e3cbfed8Sjsing 	},
408e3cbfed8Sjsing 	{
409e3cbfed8Sjsing 		.in_hex = "FFFFFFFF",
410e3cbfed8Sjsing 		.in_word = 0x10,
411e3cbfed8Sjsing 		.mod_word = 0xf,
412e3cbfed8Sjsing 		.out_word = 0xfffffffUL,
413e3cbfed8Sjsing 		.out_hex = "0FFFFFFF",
414e3cbfed8Sjsing 	},
415e3cbfed8Sjsing };
416e3cbfed8Sjsing 
417e3cbfed8Sjsing #define N_BN_DIV_WORD_TESTS \
418e3cbfed8Sjsing     (sizeof(bn_div_word_tests) / sizeof(bn_div_word_tests[0]))
419e3cbfed8Sjsing 
420e3cbfed8Sjsing static int
421e3cbfed8Sjsing test_bn_div_word(void)
422e3cbfed8Sjsing {
423e3cbfed8Sjsing 	const char *op_name = "BN_div_word";
424e3cbfed8Sjsing 	const struct bn_word_test *bwt;
425e3cbfed8Sjsing 	BN_ULONG mod_word;
426e3cbfed8Sjsing 	BIGNUM *bn;
427e3cbfed8Sjsing 	size_t i;
428e3cbfed8Sjsing 	int failed = 0;
429e3cbfed8Sjsing 
430e3cbfed8Sjsing 	if ((bn = BN_new()) == NULL)
431*6822f9c8Santon 		errx(1, "BN_new() failed");
432e3cbfed8Sjsing 
433e3cbfed8Sjsing 	for (i = 0; i < N_BN_DIV_WORD_TESTS; i++) {
434e3cbfed8Sjsing 		bwt = &bn_div_word_tests[i];
435e3cbfed8Sjsing 
436e3cbfed8Sjsing 		if (!BN_hex2bn(&bn, bwt->in_hex)) {
437e3cbfed8Sjsing 			fprintf(stderr, "FAIL: BN_hex2bn(\"%s\") failed\n",
438e3cbfed8Sjsing 			    bwt->in_hex);
439e3cbfed8Sjsing 			failed = 1;
440e3cbfed8Sjsing 			continue;
441e3cbfed8Sjsing 		}
442e3cbfed8Sjsing 
443e3cbfed8Sjsing 		if ((mod_word = BN_div_word(bn, bwt->in_word)) != bwt->mod_word) {
444e3cbfed8Sjsing 			fprintf(stderr, "FAIL %s: Got mod word %lx, want %lx\n",
445e3cbfed8Sjsing 			    op_name, (unsigned long)mod_word,
446e3cbfed8Sjsing 			    (unsigned long)bwt->mod_word);
447e3cbfed8Sjsing 			failed = 1;
448e3cbfed8Sjsing 			continue;
449e3cbfed8Sjsing 		}
450e3cbfed8Sjsing 
451e3cbfed8Sjsing 		failed |= check_bn_word_test(op_name, bn, bwt);
452e3cbfed8Sjsing 	}
453e3cbfed8Sjsing 
454e3cbfed8Sjsing 	BN_free(bn);
455e3cbfed8Sjsing 
456e3cbfed8Sjsing 	return failed;
457e3cbfed8Sjsing }
458e3cbfed8Sjsing 
459e3cbfed8Sjsing static const struct bn_word_test bn_mod_word_tests[] = {
460e3cbfed8Sjsing 	{
461e3cbfed8Sjsing 		.in_hex = "1",
462e3cbfed8Sjsing 		.in_word = 0,
463e3cbfed8Sjsing 		.mod_word = BN_MASK2,
464e3cbfed8Sjsing 		.out_word = 1,
465e3cbfed8Sjsing 		.out_hex = "01",
466e3cbfed8Sjsing 	},
467e3cbfed8Sjsing 	{
468e3cbfed8Sjsing 		.in_hex = "0",
469e3cbfed8Sjsing 		.in_word = 1,
470e3cbfed8Sjsing 		.mod_word = 0,
471e3cbfed8Sjsing 		.out_word = 0,
472e3cbfed8Sjsing 		.out_hex = "0",
473e3cbfed8Sjsing 	},
474e3cbfed8Sjsing 	{
475e3cbfed8Sjsing 		.in_hex = "4",
476e3cbfed8Sjsing 		.in_word = 2,
477e3cbfed8Sjsing 		.mod_word = 0,
478e3cbfed8Sjsing 		.out_word = 4,
479e3cbfed8Sjsing 		.out_hex = "04",
480e3cbfed8Sjsing 	},
481e3cbfed8Sjsing 	{
482e3cbfed8Sjsing 		.in_hex = "7",
483e3cbfed8Sjsing 		.in_word = 3,
484e3cbfed8Sjsing 		.mod_word = 1,
485e3cbfed8Sjsing 		.out_word = 7,
486e3cbfed8Sjsing 		.out_hex = "07",
487e3cbfed8Sjsing 	},
488e3cbfed8Sjsing 	{
489e3cbfed8Sjsing 		.in_hex = "1",
490e3cbfed8Sjsing 		.in_word = 1,
491e3cbfed8Sjsing 		.mod_word = 0,
492e3cbfed8Sjsing 		.out_word = 1,
493e3cbfed8Sjsing 		.out_hex = "01",
494e3cbfed8Sjsing 	},
495e3cbfed8Sjsing 	{
496e3cbfed8Sjsing 		.in_hex = "-2",
497e3cbfed8Sjsing 		.in_word = 1,
498e3cbfed8Sjsing 		.mod_word = 0,
499e3cbfed8Sjsing 		.out_word = 2,
500e3cbfed8Sjsing 		.out_hex = "-02",
501e3cbfed8Sjsing 		.out_is_negative = 1,
502e3cbfed8Sjsing 	},
503e3cbfed8Sjsing 	{
504e3cbfed8Sjsing 		.in_hex = "-1",
505e3cbfed8Sjsing 		.in_word = 2,
506e3cbfed8Sjsing 		.mod_word = 1,
507e3cbfed8Sjsing 		.out_word = 1,
508e3cbfed8Sjsing 		.out_hex = "-01",
509e3cbfed8Sjsing 		.out_is_negative = 1,
510e3cbfed8Sjsing 	},
511e3cbfed8Sjsing 	{
512e3cbfed8Sjsing 		.in_hex = "-3",
513e3cbfed8Sjsing 		.in_word = 2,
514e3cbfed8Sjsing 		.mod_word = 1,
515e3cbfed8Sjsing 		.out_word = 3,
516e3cbfed8Sjsing 		.out_hex = "-03",
517e3cbfed8Sjsing 		.out_is_negative = 1,
518e3cbfed8Sjsing 	},
519e3cbfed8Sjsing 	{
520e3cbfed8Sjsing 		.in_hex = "1",
521e3cbfed8Sjsing 		.in_word = 0xffffffffUL,
522e3cbfed8Sjsing 		.mod_word = 1,
523e3cbfed8Sjsing 		.out_word = 1,
524e3cbfed8Sjsing 		.out_hex = "01",
525e3cbfed8Sjsing 	},
526e3cbfed8Sjsing 	{
527e3cbfed8Sjsing 		.in_hex = "FFFFFFFF",
528e3cbfed8Sjsing 		.in_word = 1,
529e3cbfed8Sjsing 		.mod_word = 0,
530e3cbfed8Sjsing 		.out_word = 0xffffffffUL,
531e3cbfed8Sjsing 		.out_hex = "FFFFFFFF",
532e3cbfed8Sjsing 	},
533e3cbfed8Sjsing 	{
534e3cbfed8Sjsing 		.in_hex = "FFFFFFFE",
535e3cbfed8Sjsing 		.in_word = 0xffffffffUL,
536e3cbfed8Sjsing 		.mod_word = 0xfffffffeUL,
537e3cbfed8Sjsing 		.out_word = 0xfffffffeUL,
538e3cbfed8Sjsing 		.out_hex = "FFFFFFFE",
539e3cbfed8Sjsing 	},
540e3cbfed8Sjsing 	{
541e3cbfed8Sjsing 		.in_hex = "FFFFFFFFFFFFFFFF",
542e3cbfed8Sjsing 		.in_word = 1,
543e3cbfed8Sjsing 		.mod_word = 0,
544e3cbfed8Sjsing 		.out_word = BN_MASK2,
545e3cbfed8Sjsing 		.out_hex = "FFFFFFFFFFFFFFFF",
546e3cbfed8Sjsing 	},
547e3cbfed8Sjsing 	{
548e3cbfed8Sjsing 		.in_hex = "FFFFFFFF",
549e3cbfed8Sjsing 		.in_word = 0xff,
550e3cbfed8Sjsing 		.mod_word = 0,
551e3cbfed8Sjsing 		.out_word = 0xffffffff,
552e3cbfed8Sjsing 		.out_hex = "FFFFFFFF",
553e3cbfed8Sjsing 	},
554e3cbfed8Sjsing 	{
555e3cbfed8Sjsing 		.in_hex = "FFFFFFFF",
556e3cbfed8Sjsing 		.in_word = 0x10,
557e3cbfed8Sjsing 		.mod_word = 0xf,
558e3cbfed8Sjsing 		.out_word = 0xffffffffUL,
559e3cbfed8Sjsing 		.out_hex = "FFFFFFFF",
560e3cbfed8Sjsing 	},
561e3cbfed8Sjsing };
562e3cbfed8Sjsing 
563e3cbfed8Sjsing #define N_BN_MOD_WORD_TESTS \
564e3cbfed8Sjsing     (sizeof(bn_mod_word_tests) / sizeof(bn_mod_word_tests[0]))
565e3cbfed8Sjsing 
566e3cbfed8Sjsing static int
567e3cbfed8Sjsing test_bn_mod_word(void)
568e3cbfed8Sjsing {
569e3cbfed8Sjsing 	const char *op_name = "BN_mod_word";
570e3cbfed8Sjsing 	const struct bn_word_test *bwt;
571e3cbfed8Sjsing 	BN_ULONG mod_word;
572e3cbfed8Sjsing 	BIGNUM *bn;
573e3cbfed8Sjsing 	size_t i;
574e3cbfed8Sjsing 	int failed = 0;
575e3cbfed8Sjsing 
576e3cbfed8Sjsing 	if ((bn = BN_new()) == NULL)
577*6822f9c8Santon 		errx(1, "BN_new() failed");
578e3cbfed8Sjsing 
579e3cbfed8Sjsing 	for (i = 0; i < N_BN_MOD_WORD_TESTS; i++) {
580e3cbfed8Sjsing 		bwt = &bn_mod_word_tests[i];
581e3cbfed8Sjsing 
582e3cbfed8Sjsing 		if (!BN_hex2bn(&bn, bwt->in_hex)) {
583e3cbfed8Sjsing 			fprintf(stderr, "FAIL: BN_hex2bn(\"%s\") failed\n",
584e3cbfed8Sjsing 			    bwt->in_hex);
585e3cbfed8Sjsing 			failed = 1;
586e3cbfed8Sjsing 			continue;
587e3cbfed8Sjsing 		}
588e3cbfed8Sjsing 
589e3cbfed8Sjsing 		if ((mod_word = BN_mod_word(bn, bwt->in_word)) != bwt->mod_word) {
590e3cbfed8Sjsing 			fprintf(stderr, "FAIL %s: Got mod word %lx, want %lx\n",
591e3cbfed8Sjsing 			    op_name, (unsigned long)mod_word,
592e3cbfed8Sjsing 			    (unsigned long)bwt->mod_word);
593e3cbfed8Sjsing 			failed = 1;
594e3cbfed8Sjsing 			continue;
595e3cbfed8Sjsing 		}
596e3cbfed8Sjsing 
597e3cbfed8Sjsing 		failed |= check_bn_word_test(op_name, bn, bwt);
598e3cbfed8Sjsing 	}
599e3cbfed8Sjsing 
600e3cbfed8Sjsing 	BN_free(bn);
601e3cbfed8Sjsing 
602e3cbfed8Sjsing 	return failed;
603e3cbfed8Sjsing }
604e3cbfed8Sjsing 
605e3cbfed8Sjsing int
606e3cbfed8Sjsing main(int argc, char **argv)
607e3cbfed8Sjsing {
608e3cbfed8Sjsing 	int failed = 0;
609e3cbfed8Sjsing 
610e3cbfed8Sjsing 	failed |= test_bn_add_word();
611e3cbfed8Sjsing 	failed |= test_bn_sub_word();
612e3cbfed8Sjsing 	failed |= test_bn_mul_word();
613e3cbfed8Sjsing 	failed |= test_bn_div_word();
614e3cbfed8Sjsing 	failed |= test_bn_mod_word();
615e3cbfed8Sjsing 
616e3cbfed8Sjsing 	return failed;
617e3cbfed8Sjsing }
618