xref: /openbsd/regress/lib/libcrypto/bn/bn_cmp.c (revision da50f9d5)
1*da50f9d5Sjsing /*	$OpenBSD: bn_cmp.c,v 1.2 2023/06/21 07:16:08 jsing Exp $ */
2e34544d2Sjsing /*
3e34544d2Sjsing  * Copyright (c) 2022 Joel Sing <jsing@openbsd.org>
4e34544d2Sjsing  *
5e34544d2Sjsing  * Permission to use, copy, modify, and distribute this software for any
6e34544d2Sjsing  * purpose with or without fee is hereby granted, provided that the above
7e34544d2Sjsing  * copyright notice and this permission notice appear in all copies.
8e34544d2Sjsing  *
9e34544d2Sjsing  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10e34544d2Sjsing  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11e34544d2Sjsing  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12e34544d2Sjsing  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13e34544d2Sjsing  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14e34544d2Sjsing  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15e34544d2Sjsing  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16e34544d2Sjsing  */
17e34544d2Sjsing 
18e34544d2Sjsing #include <stdio.h>
19e34544d2Sjsing 
20e34544d2Sjsing #include <openssl/bn.h>
21e34544d2Sjsing 
22e34544d2Sjsing struct bn_cmp_test {
23e34544d2Sjsing 	const char *a;
24e34544d2Sjsing 	const char *b;
25e34544d2Sjsing 	int cmp;
26e34544d2Sjsing 	int ucmp;
27e34544d2Sjsing };
28e34544d2Sjsing 
29e34544d2Sjsing struct bn_cmp_test bn_cmp_tests[] = {
30e34544d2Sjsing 	{
31e34544d2Sjsing 		.a = "0",
32e34544d2Sjsing 		.b = "0",
33e34544d2Sjsing 		.cmp = 0,
34e34544d2Sjsing 		.ucmp = 0,
35e34544d2Sjsing 	},
36e34544d2Sjsing 	{
37e34544d2Sjsing 		.a = "-1",
38e34544d2Sjsing 		.b = "0",
39e34544d2Sjsing 		.cmp = -1,
40e34544d2Sjsing 		.ucmp = 1,
41e34544d2Sjsing 	},
42e34544d2Sjsing 	{
43e34544d2Sjsing 		.a = "1ffffffffffffffff",
44e34544d2Sjsing 		.b = "1ffffffffffffffff",
45e34544d2Sjsing 		.cmp = 0,
46e34544d2Sjsing 		.ucmp = 0,
47e34544d2Sjsing 	},
48e34544d2Sjsing 	{
49e34544d2Sjsing 		.a = "1fffffffffffffffe",
50e34544d2Sjsing 		.b = "1ffffffffffffffff",
51e34544d2Sjsing 		.cmp = -1,
52e34544d2Sjsing 		.ucmp = -1,
53e34544d2Sjsing 	},
54e34544d2Sjsing 	{
55e34544d2Sjsing 		.a = "1ffffffffffffffff",
56e34544d2Sjsing 		.b = "1fffffffffffffffe",
57e34544d2Sjsing 		.cmp = 1,
58e34544d2Sjsing 		.ucmp = 1,
59e34544d2Sjsing 	},
60e34544d2Sjsing 	{
61e34544d2Sjsing 		.a = "0",
62e34544d2Sjsing 		.b = "1ffffffffffffffff",
63e34544d2Sjsing 		.cmp = -1,
64e34544d2Sjsing 		.ucmp = -1,
65e34544d2Sjsing 	},
66e34544d2Sjsing 	{
67e34544d2Sjsing 		.a = "1ffffffffffffffff",
68e34544d2Sjsing 		.b = "0",
69e34544d2Sjsing 		.cmp = 1,
70e34544d2Sjsing 		.ucmp = 1,
71e34544d2Sjsing 	},
72e34544d2Sjsing 	{
73e34544d2Sjsing 		.a = "-1ffffffffffffffff",
74e34544d2Sjsing 		.b = "0",
75e34544d2Sjsing 		.cmp = -1,
76e34544d2Sjsing 		.ucmp = 1,
77e34544d2Sjsing 	},
78*da50f9d5Sjsing 	{
79*da50f9d5Sjsing 		.a = "1ffffffffffffffff",
80*da50f9d5Sjsing 		.b = "00000000000000001ffffffffffffffff",
81*da50f9d5Sjsing 		.cmp = 0,
82*da50f9d5Sjsing 		.ucmp = 0,
83*da50f9d5Sjsing 	},
84*da50f9d5Sjsing 	{
85*da50f9d5Sjsing 		.a = "-1ffffffffffffffff",
86*da50f9d5Sjsing 		.b = "-00000000000000001ffffffffffffffff",
87*da50f9d5Sjsing 		.cmp = 0,
88*da50f9d5Sjsing 		.ucmp = 0,
89*da50f9d5Sjsing 	},
90*da50f9d5Sjsing 	{
91*da50f9d5Sjsing 		.a = "1ffffffffffffffff",
92*da50f9d5Sjsing 		.b = "-00000000000000001ffffffffffffffff",
93*da50f9d5Sjsing 		.cmp = 1,
94*da50f9d5Sjsing 		.ucmp = 0,
95*da50f9d5Sjsing 	},
96*da50f9d5Sjsing 	{
97*da50f9d5Sjsing 		.a = "-1ffffffffffffffff",
98*da50f9d5Sjsing 		.b = "00000000000000001ffffffffffffffff",
99*da50f9d5Sjsing 		.cmp = -1,
100*da50f9d5Sjsing 		.ucmp = 0,
101*da50f9d5Sjsing 	},
102e34544d2Sjsing };
103e34544d2Sjsing 
104e34544d2Sjsing #define N_BN_CMP_TESTS \
105e34544d2Sjsing     (sizeof(bn_cmp_tests) / sizeof(*bn_cmp_tests))
106e34544d2Sjsing 
107e34544d2Sjsing static int
test_bn_cmp(void)108e34544d2Sjsing test_bn_cmp(void)
109e34544d2Sjsing {
110e34544d2Sjsing 	struct bn_cmp_test *bct;
111e34544d2Sjsing 	BIGNUM *a = NULL, *b = NULL;
112e34544d2Sjsing 	size_t i;
113e34544d2Sjsing 	int ret;
114e34544d2Sjsing 	int failed = 1;
115e34544d2Sjsing 
116e34544d2Sjsing 	if ((a = BN_new()) == NULL) {
117e34544d2Sjsing 		fprintf(stderr, "FAIL: failed to create BN\n");
118e34544d2Sjsing 		goto failure;
119e34544d2Sjsing 	}
120e34544d2Sjsing 	if ((b = BN_new()) == NULL) {
121e34544d2Sjsing 		fprintf(stderr, "FAIL: failed to create BN\n");
122e34544d2Sjsing 		goto failure;
123e34544d2Sjsing 	}
124e34544d2Sjsing 
125e34544d2Sjsing 	for (i = 0; i < N_BN_CMP_TESTS; i++) {
126e34544d2Sjsing 		bct = &bn_cmp_tests[i];
127e34544d2Sjsing 
128e34544d2Sjsing 		if (!BN_hex2bn(&a, bct->a)) {
129e34544d2Sjsing 			fprintf(stderr, "FAIL: failed to set a from hex\n");
130e34544d2Sjsing 			goto failure;
131e34544d2Sjsing 		}
132e34544d2Sjsing 		if (!BN_hex2bn(&b, bct->b)) {
133e34544d2Sjsing 			fprintf(stderr, "FAIL: failed to set b from hex\n");
134e34544d2Sjsing 			goto failure;
135e34544d2Sjsing 		}
136e34544d2Sjsing 
137e34544d2Sjsing 		if ((ret = BN_cmp(a, b)) != bct->cmp) {
138e34544d2Sjsing 			fprintf(stderr, "FAIL: BN_cmp(%s, %s) = %d, want %d\n",
139e34544d2Sjsing 			    bct->a, bct->b, ret, bct->cmp);
140e34544d2Sjsing 			goto failure;
141e34544d2Sjsing 		}
142e34544d2Sjsing 		if ((ret = BN_ucmp(a, b)) != bct->ucmp) {
143e34544d2Sjsing 			fprintf(stderr, "FAIL: BN_ucmp(%s, %s) = %d, want %d\n",
144e34544d2Sjsing 			    bct->a, bct->b, ret, bct->ucmp);
145e34544d2Sjsing 			goto failure;
146e34544d2Sjsing 		}
147e34544d2Sjsing 	}
148e34544d2Sjsing 
149e34544d2Sjsing 	failed = 0;
150e34544d2Sjsing 
151e34544d2Sjsing  failure:
152e34544d2Sjsing 	BN_free(a);
153e34544d2Sjsing 	BN_free(b);
154e34544d2Sjsing 
155e34544d2Sjsing 	return failed;
156e34544d2Sjsing }
157e34544d2Sjsing 
158e34544d2Sjsing static int
test_bn_cmp_null(void)159e34544d2Sjsing test_bn_cmp_null(void)
160e34544d2Sjsing {
161e34544d2Sjsing 	BIGNUM *a = NULL;
162e34544d2Sjsing 	int ret;
163e34544d2Sjsing 	int failed = 1;
164e34544d2Sjsing 
165e34544d2Sjsing 	if ((a = BN_new()) == NULL) {
166e34544d2Sjsing 		fprintf(stderr, "FAIL: failed to create BN\n");
167e34544d2Sjsing 		goto failure;
168e34544d2Sjsing 	}
169e34544d2Sjsing 
170e34544d2Sjsing 	/*
171e34544d2Sjsing 	 * Comparison to NULL.
172e34544d2Sjsing 	 */
173e34544d2Sjsing 	if ((ret = BN_cmp(NULL, NULL)) != 0) {
174e34544d2Sjsing 		fprintf(stderr, "FAIL: BN_cmp(NULL, NULL) == %d, want 0\n", ret);
175e34544d2Sjsing 		goto failure;
176e34544d2Sjsing 	}
177e34544d2Sjsing 
178e34544d2Sjsing 	if ((ret = BN_cmp(a, NULL)) != -1) {
179e34544d2Sjsing 		fprintf(stderr, "FAIL: BN_cmp(0, NULL) == %d, want -1\n", ret);
180e34544d2Sjsing 		goto failure;
181e34544d2Sjsing 	}
182e34544d2Sjsing 	if ((ret = BN_cmp(NULL, a)) != 1) {
183e34544d2Sjsing 		fprintf(stderr, "FAIL: BN_cmp(NULL, 0) == %d, want 1\n", ret);
184e34544d2Sjsing 		goto failure;
185e34544d2Sjsing 	}
186e34544d2Sjsing 
187e34544d2Sjsing 	if (!BN_set_word(a, 1)) {
188e34544d2Sjsing 		fprintf(stderr, "FAIL: failed to set BN to 1\n");
189e34544d2Sjsing 		goto failure;
190e34544d2Sjsing 	}
191e34544d2Sjsing 	if ((ret = BN_cmp(a, NULL)) != -1) {
192e34544d2Sjsing 		fprintf(stderr, "FAIL: BN_cmp(1, NULL) == %d, want -1\n", ret);
193e34544d2Sjsing 		goto failure;
194e34544d2Sjsing 	}
195e34544d2Sjsing 	if ((ret = BN_cmp(NULL, a)) != 1) {
196e34544d2Sjsing 		fprintf(stderr, "FAIL: BN_cmp(NULL, 1) == %d, want 1\n", ret);
197e34544d2Sjsing 		goto failure;
198e34544d2Sjsing 	}
199e34544d2Sjsing 
200e34544d2Sjsing 	BN_set_negative(a, 1);
201e34544d2Sjsing 	if ((ret = BN_cmp(a, NULL)) != -1) {
202e34544d2Sjsing 		fprintf(stderr, "FAIL: BN_cmp(-1, NULL) == %d, want -1\n", ret);
203e34544d2Sjsing 		goto failure;
204e34544d2Sjsing 	}
205e34544d2Sjsing 	if ((ret = BN_cmp(NULL, a)) != 1) {
206e34544d2Sjsing 		fprintf(stderr, "FAIL: BN_cmp(NULL, -1) == %d, want 1\n", ret);
207e34544d2Sjsing 		goto failure;
208e34544d2Sjsing 	}
209e34544d2Sjsing 
210e34544d2Sjsing 	failed = 0;
211e34544d2Sjsing 
212e34544d2Sjsing  failure:
213e34544d2Sjsing 	BN_free(a);
214e34544d2Sjsing 
215e34544d2Sjsing 	return failed;
216e34544d2Sjsing }
217e34544d2Sjsing 
218e34544d2Sjsing struct bn_cmp_word_test {
219e34544d2Sjsing 	int a;
220e34544d2Sjsing 	int b;
221e34544d2Sjsing 	int cmp;
222e34544d2Sjsing 	int ucmp;
223e34544d2Sjsing };
224e34544d2Sjsing 
225e34544d2Sjsing struct bn_cmp_word_test bn_cmp_word_tests[] = {
226e34544d2Sjsing 	{
227e34544d2Sjsing 		.a = -1,
228e34544d2Sjsing 		.b = -1,
229e34544d2Sjsing 		.cmp = 0,
230e34544d2Sjsing 		.ucmp = 0,
231e34544d2Sjsing 	},
232e34544d2Sjsing 	{
233e34544d2Sjsing 		.a = 0,
234e34544d2Sjsing 		.b = 0,
235e34544d2Sjsing 		.cmp = 0,
236e34544d2Sjsing 		.ucmp = 0,
237e34544d2Sjsing 	},
238e34544d2Sjsing 	{
239e34544d2Sjsing 		.a = 1,
240e34544d2Sjsing 		.b = 1,
241e34544d2Sjsing 		.cmp = 0,
242e34544d2Sjsing 		.ucmp = 0,
243e34544d2Sjsing 	},
244e34544d2Sjsing 	{
245e34544d2Sjsing 		.a = 0,
246e34544d2Sjsing 		.b = 1,
247e34544d2Sjsing 		.cmp = -1,
248e34544d2Sjsing 		.ucmp = -1,
249e34544d2Sjsing 	},
250e34544d2Sjsing 	{
251e34544d2Sjsing 		.a = 1,
252e34544d2Sjsing 		.b = 0,
253e34544d2Sjsing 		.cmp = 1,
254e34544d2Sjsing 		.ucmp = 1,
255e34544d2Sjsing 	},
256e34544d2Sjsing 	{
257e34544d2Sjsing 		.a = -1,
258e34544d2Sjsing 		.b = 0,
259e34544d2Sjsing 		.cmp = -1,
260e34544d2Sjsing 		.ucmp = 1,
261e34544d2Sjsing 	},
262e34544d2Sjsing 	{
263e34544d2Sjsing 		.a = 0,
264e34544d2Sjsing 		.b = -1,
265e34544d2Sjsing 		.cmp = 1,
266e34544d2Sjsing 		.ucmp = -1,
267e34544d2Sjsing 	},
268e34544d2Sjsing 	{
269e34544d2Sjsing 		.a = -1,
270e34544d2Sjsing 		.b = 1,
271e34544d2Sjsing 		.cmp = -1,
272e34544d2Sjsing 		.ucmp = 0,
273e34544d2Sjsing 	},
274e34544d2Sjsing 	{
275e34544d2Sjsing 		.a = 1,
276e34544d2Sjsing 		.b = -1,
277e34544d2Sjsing 		.cmp = 1,
278e34544d2Sjsing 		.ucmp = 0,
279e34544d2Sjsing 	},
280e34544d2Sjsing };
281e34544d2Sjsing 
282e34544d2Sjsing #define N_BN_CMP_WORD_TESTS \
283e34544d2Sjsing     (sizeof(bn_cmp_word_tests) / sizeof(*bn_cmp_word_tests))
284e34544d2Sjsing 
285e34544d2Sjsing static int
test_bn_cmp_word(void)286e34544d2Sjsing test_bn_cmp_word(void)
287e34544d2Sjsing {
288e34544d2Sjsing 	struct bn_cmp_word_test *bcwt;
289e34544d2Sjsing 	BIGNUM *a = NULL, *b = NULL;
290e34544d2Sjsing 	BN_ULONG v;
291e34544d2Sjsing 	size_t i;
292e34544d2Sjsing 	int ret;
293e34544d2Sjsing 	int failed = 1;
294e34544d2Sjsing 
295e34544d2Sjsing 	if ((a = BN_new()) == NULL) {
296e34544d2Sjsing 		fprintf(stderr, "FAIL: failed to create BN\n");
297e34544d2Sjsing 		goto failure;
298e34544d2Sjsing 	}
299e34544d2Sjsing 	if ((b = BN_new()) == NULL) {
300e34544d2Sjsing 		fprintf(stderr, "FAIL: failed to create BN\n");
301e34544d2Sjsing 		goto failure;
302e34544d2Sjsing 	}
303e34544d2Sjsing 
304e34544d2Sjsing 	for (i = 0; i < N_BN_CMP_WORD_TESTS; i++) {
305e34544d2Sjsing 		bcwt = &bn_cmp_word_tests[i];
306e34544d2Sjsing 
307e34544d2Sjsing 		if (bcwt->a >= 0) {
308e34544d2Sjsing 			v = bcwt->a;
309e34544d2Sjsing 		} else {
310e34544d2Sjsing 			v = 0 - bcwt->a;
311e34544d2Sjsing 		}
312e34544d2Sjsing 		if (!BN_set_word(a, v)) {
313e34544d2Sjsing 			fprintf(stderr, "FAIL: failed to set a\n");
314e34544d2Sjsing 			goto failure;
315e34544d2Sjsing 		}
316e34544d2Sjsing 		BN_set_negative(a, (bcwt->a < 0));
317e34544d2Sjsing 
318e34544d2Sjsing 		if (bcwt->b >= 0) {
319e34544d2Sjsing 			v = bcwt->b;
320e34544d2Sjsing 		} else {
321e34544d2Sjsing 			v = 0 - bcwt->b;
322e34544d2Sjsing 		}
323e34544d2Sjsing 		if (!BN_set_word(b, v)) {
324e34544d2Sjsing 			fprintf(stderr, "FAIL: failed to set b\n");
325e34544d2Sjsing 			goto failure;
326e34544d2Sjsing 		}
327e34544d2Sjsing 		BN_set_negative(b, (bcwt->b < 0));
328e34544d2Sjsing 
329e34544d2Sjsing 		if ((ret = BN_cmp(a, b)) != bcwt->cmp) {
330e34544d2Sjsing 			fprintf(stderr, "FAIL: BN_cmp(%d, %d) = %d, want %d\n",
331e34544d2Sjsing 			    bcwt->a, bcwt->b, ret, bcwt->cmp);
332e34544d2Sjsing 			goto failure;
333e34544d2Sjsing 		}
334e34544d2Sjsing 		if ((ret = BN_ucmp(a, b)) != bcwt->ucmp) {
335e34544d2Sjsing 			fprintf(stderr, "FAIL: BN_ucmp(%d, %d) = %d, want %d\n",
336e34544d2Sjsing 			    bcwt->a, bcwt->b, ret, bcwt->ucmp);
337e34544d2Sjsing 			goto failure;
338e34544d2Sjsing 		}
339e34544d2Sjsing 	}
340e34544d2Sjsing 
341e34544d2Sjsing 	failed = 0;
342e34544d2Sjsing 
343e34544d2Sjsing  failure:
344e34544d2Sjsing 	BN_free(a);
345e34544d2Sjsing 	BN_free(b);
346e34544d2Sjsing 
347e34544d2Sjsing 	return failed;
348e34544d2Sjsing }
349e34544d2Sjsing 
350e34544d2Sjsing int
main(int argc,char ** argv)351e34544d2Sjsing main(int argc, char **argv)
352e34544d2Sjsing {
353e34544d2Sjsing 	int failed = 0;
354e34544d2Sjsing 
355e34544d2Sjsing 	failed |= test_bn_cmp();
356e34544d2Sjsing 	failed |= test_bn_cmp_null();
357e34544d2Sjsing 	failed |= test_bn_cmp_word();
358e34544d2Sjsing 
359e34544d2Sjsing 	return failed;
360e34544d2Sjsing }
361