xref: /openbsd-src/regress/lib/libcrypto/bn/bn_unit.c (revision 36ba240090a6df24c201bdfd6f435983e6ced3a4)
1*36ba2400Sjsing /*	$OpenBSD: bn_unit.c,v 1.7 2023/06/21 07:15:38 jsing Exp $ */
2b8d22d11Stb 
3b8d22d11Stb /*
4b8d22d11Stb  * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
5b8d22d11Stb  *
6b8d22d11Stb  * Permission to use, copy, modify, and distribute this software for any
7b8d22d11Stb  * purpose with or without fee is hereby granted, provided that the above
8b8d22d11Stb  * copyright notice and this permission notice appear in all copies.
9b8d22d11Stb  *
10b8d22d11Stb  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11b8d22d11Stb  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12b8d22d11Stb  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13b8d22d11Stb  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14b8d22d11Stb  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15b8d22d11Stb  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16b8d22d11Stb  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17b8d22d11Stb  */
18b8d22d11Stb 
19b8d22d11Stb #include <err.h>
20b8d22d11Stb #include <limits.h>
2120c8b67dStb #include <stdio.h>
22b8d22d11Stb #include <stdlib.h>
23b8d22d11Stb #include <string.h>
24b8d22d11Stb 
25b8d22d11Stb #include <openssl/bn.h>
26b8d22d11Stb 
27b8d22d11Stb static int
test_bn_print_wrapper(char * a,size_t size,const char * descr,int (* to_bn)(BIGNUM **,const char *))28b8d22d11Stb test_bn_print_wrapper(char *a, size_t size, const char *descr,
29b8d22d11Stb     int (*to_bn)(BIGNUM **, const char *))
30b8d22d11Stb {
31b8d22d11Stb 	int ret;
32b8d22d11Stb 
33b8d22d11Stb 	ret = to_bn(NULL, a);
34b8d22d11Stb 	if (ret != 0 && (ret < 0 || (size_t)ret != size - 1)) {
35b8d22d11Stb 		fprintf(stderr, "unexpected %s() return"
36b8d22d11Stb 		    "want 0 or %zu, got %d\n", descr, size - 1, ret);
37b8d22d11Stb 		return 1;
38b8d22d11Stb 	}
39b8d22d11Stb 
40b8d22d11Stb 	return 0;
41b8d22d11Stb }
42b8d22d11Stb 
43b8d22d11Stb static int
test_bn_print_null_derefs(void)44b8d22d11Stb test_bn_print_null_derefs(void)
45b8d22d11Stb {
46b8d22d11Stb 	size_t size = INT_MAX / 4 + 4;
47b8d22d11Stb 	size_t datalimit = (size + 500 * 1024) / 1024;
48b8d22d11Stb 	char *a;
49b8d22d11Stb 	char digit;
50b8d22d11Stb 	int failed = 0;
51b8d22d11Stb 
52b8d22d11Stb 	if ((a = malloc(size)) == NULL) {
53b8d22d11Stb 		warn("malloc(%zu) failed (make sure data limit is >= %zu KiB)",
54b8d22d11Stb 		    size, datalimit);
55b8d22d11Stb 		return 0;
56b8d22d11Stb 	}
57b8d22d11Stb 
58b8d22d11Stb 	/* Fill with a random digit since coverity doesn't like us using '0'. */
59b8d22d11Stb 	digit = '0' + arc4random_uniform(10);
60b8d22d11Stb 
61b8d22d11Stb 	memset(a, digit, size - 1);
62b8d22d11Stb 	a[size - 1] = '\0';
63b8d22d11Stb 
64b8d22d11Stb 	failed |= test_bn_print_wrapper(a, size, "BN_dec2bn", BN_dec2bn);
65b8d22d11Stb 	failed |= test_bn_print_wrapper(a, size, "BN_hex2bn", BN_hex2bn);
66b8d22d11Stb 
67b8d22d11Stb 	free(a);
68b8d22d11Stb 
69b8d22d11Stb 	return failed;
70b8d22d11Stb }
71b8d22d11Stb 
72ed0e3043Stb static int
test_bn_num_bits(void)730d31acbaSjsing test_bn_num_bits(void)
740d31acbaSjsing {
750d31acbaSjsing 	BIGNUM *bn;
760d31acbaSjsing 	int i, num_bits;
770d31acbaSjsing 	int failed = 0;
780d31acbaSjsing 
790d31acbaSjsing 	if ((bn = BN_new()) == NULL)
800d31acbaSjsing 		errx(1, "BN_new");
810d31acbaSjsing 
820d31acbaSjsing 	if ((num_bits = BN_num_bits(bn)) != 0) {
83*36ba2400Sjsing 		warnx("BN_num_bits(0): got %d, want 0", num_bits);
840d31acbaSjsing 		failed |= 1;
850d31acbaSjsing 	}
860d31acbaSjsing 
870d31acbaSjsing 	if (!BN_set_word(bn, 1))
880d31acbaSjsing 		errx(1, "BN_set_word");
890d31acbaSjsing 
900d31acbaSjsing 	for (i = 0; i <= 5 * BN_BITS2; i++) {
910d31acbaSjsing 		if ((num_bits = BN_num_bits(bn)) != i + 1) {
92*36ba2400Sjsing 			warnx("BN_num_bits(1 << %d): got %d, want %d",
93*36ba2400Sjsing 			    i, num_bits, i + 1);
940d31acbaSjsing 			failed |= 1;
950d31acbaSjsing 		}
960d31acbaSjsing 		if (!BN_lshift1(bn, bn))
970d31acbaSjsing 			errx(1, "BN_lshift1");
980d31acbaSjsing 	}
990d31acbaSjsing 
100*36ba2400Sjsing 	if (BN_hex2bn(&bn, "0000000000000000010000000000000000") != 34)
101*36ba2400Sjsing 		errx(1, "BN_hex2bn");
102*36ba2400Sjsing 
103*36ba2400Sjsing 	if ((num_bits = BN_num_bits(bn)) != 65) {
104*36ba2400Sjsing 		warnx("BN_num_bits(1 << 64) padded: got %d, want %d",
105*36ba2400Sjsing 		    num_bits, 65);
106*36ba2400Sjsing 		failed |= 1;
107*36ba2400Sjsing 	}
108*36ba2400Sjsing 
1090d31acbaSjsing 	BN_free(bn);
1100d31acbaSjsing 
1110d31acbaSjsing 	return failed;
1120d31acbaSjsing }
1130d31acbaSjsing 
1140d31acbaSjsing static int
test_bn_num_bits_word(void)115ed0e3043Stb test_bn_num_bits_word(void)
116ed0e3043Stb {
117ed0e3043Stb 	BN_ULONG w = 1;
118ed0e3043Stb 	int i, num_bits;
119ed0e3043Stb 	int failed = 0;
120ed0e3043Stb 
121ed0e3043Stb 	if ((num_bits = BN_num_bits_word(0)) != 0) {
122ed0e3043Stb 		warnx("BN_num_bits_word(0): want 0, got %d", num_bits);
123ed0e3043Stb 		failed |= 1;
124ed0e3043Stb 	}
125ed0e3043Stb 
126ed0e3043Stb 	for (i = 0; i < BN_BITS2; i++) {
127ed0e3043Stb 		if ((num_bits = BN_num_bits_word(w << i)) != i + 1) {
128ed0e3043Stb 			warnx("BN_num_bits_word(0x%llx): want %d, got %d",
129ed0e3043Stb 			    (unsigned long long)(w << i), i + 1, num_bits);
130ed0e3043Stb 			failed |= 1;
131ed0e3043Stb 		}
132ed0e3043Stb 	}
133ed0e3043Stb 
134ed0e3043Stb 	return failed;
135ed0e3043Stb }
136ed0e3043Stb 
137e4e7a30cStb #define BN_FLG_ALL_KNOWN \
138e4e7a30cStb     (BN_FLG_STATIC_DATA | BN_FLG_CONSTTIME | BN_FLG_MALLOCED)
139e4e7a30cStb 
140e4e7a30cStb static int
bn_check_expected_flags(const BIGNUM * bn,int expected,const char * fn,const char * descr)141e4e7a30cStb bn_check_expected_flags(const BIGNUM *bn, int expected, const char *fn,
142e4e7a30cStb     const char *descr)
143e4e7a30cStb {
144e4e7a30cStb 	int flags, got;
145e4e7a30cStb 	int ret = 1;
146e4e7a30cStb 
147e4e7a30cStb 	flags = BN_get_flags(bn, BN_FLG_ALL_KNOWN);
148e4e7a30cStb 
149e4e7a30cStb 	if ((got = flags & expected) != expected) {
150e4e7a30cStb 		fprintf(stderr, "%s: %s: expected flags: want %x, got %x\n",
151e4e7a30cStb 		    fn, descr, expected, got);
152e4e7a30cStb 		ret = 0;
153e4e7a30cStb 	}
154e4e7a30cStb 
155e4e7a30cStb 	if ((got = flags & ~expected) != 0) {
156e4e7a30cStb 		fprintf(stderr, "%s: %s: unexpected flags: want %x, got %x\n",
157e4e7a30cStb 		    fn, descr, 0, got);
158e4e7a30cStb 		ret = 0;
159e4e7a30cStb 	}
160e4e7a30cStb 
161e4e7a30cStb 	return ret;
162e4e7a30cStb }
163e4e7a30cStb 
164e4e7a30cStb static int
test_bn_copy_copies_flags(void)165e4e7a30cStb test_bn_copy_copies_flags(void)
166e4e7a30cStb {
167e4e7a30cStb 	BIGNUM *dst, *src;
168e4e7a30cStb 	int failed = 0;
169e4e7a30cStb 
170e4e7a30cStb 	if ((dst = BN_new()) == NULL)
171e4e7a30cStb 		errx(1, "%s: src = BN_new()", __func__);
172e4e7a30cStb 
173e4e7a30cStb 	if (!bn_check_expected_flags(dst, BN_FLG_MALLOCED,
174e4e7a30cStb 	    __func__, "dst after BN_new"))
175e4e7a30cStb 		failed |= 1;
176e4e7a30cStb 
177e4e7a30cStb 	if (BN_copy(dst, BN_value_one()) == NULL)
178e4e7a30cStb 		errx(1, "%s: bn_copy()", __func__);
179e4e7a30cStb 
180e4e7a30cStb 	if (!bn_check_expected_flags(dst, BN_FLG_MALLOCED,
181e4e7a30cStb 	    __func__, "dst after bn_copy"))
182e4e7a30cStb 		failed |= 1;
183e4e7a30cStb 
184e4e7a30cStb 	if ((src = BN_new()) == NULL)
185e4e7a30cStb 		errx(1, "%s: src = BN_new()", __func__);
186e4e7a30cStb 
187e4e7a30cStb 	BN_set_flags(src, BN_FLG_CONSTTIME);
188e4e7a30cStb 
189e4e7a30cStb 	if (!bn_check_expected_flags(src, BN_FLG_MALLOCED | BN_FLG_CONSTTIME,
190e4e7a30cStb 	    __func__, "src after BN_set_flags"))
191e4e7a30cStb 		failed |= 1;
192e4e7a30cStb 
193e4e7a30cStb 	if (!BN_set_word(src, 57))
194e4e7a30cStb 		errx(1, "%s: BN_set_word(src, 57)", __func__);
195e4e7a30cStb 
196e4e7a30cStb 	if (BN_copy(dst, src) == NULL)
197e4e7a30cStb 		errx(1, "%s: BN_copy(dst, src)", __func__);
198e4e7a30cStb 
199e4e7a30cStb 	if (BN_cmp(src, dst) != 0) {
200e4e7a30cStb 		fprintf(stderr, "copy not equal to original\n");
201e4e7a30cStb 		failed |= 1;
202e4e7a30cStb 	}
203e4e7a30cStb 
204e4e7a30cStb 	if (!bn_check_expected_flags(dst, BN_FLG_MALLOCED | BN_FLG_CONSTTIME,
205e4e7a30cStb 	    __func__, "dst after BN_copy(dst, src)"))
206e4e7a30cStb 		failed |= 1;
207e4e7a30cStb 
208e4e7a30cStb 	BN_free(dst);
209e4e7a30cStb 	BN_free(src);
210e4e7a30cStb 
211e4e7a30cStb 	return failed;
212e4e7a30cStb }
213e4e7a30cStb 
214e4e7a30cStb static int
test_bn_copy_consttime_is_sticky(void)215e4e7a30cStb test_bn_copy_consttime_is_sticky(void)
216e4e7a30cStb {
217e4e7a30cStb 	BIGNUM *src, *dst;
218e4e7a30cStb 	int failed = 0;
219e4e7a30cStb 
220e4e7a30cStb 	if ((src = BN_new()) == NULL)
221e4e7a30cStb 		errx(1, "%s: src = BN_new()", __func__);
222e4e7a30cStb 
223e4e7a30cStb 	if (!bn_check_expected_flags(src, BN_FLG_MALLOCED,
224e4e7a30cStb 	    __func__, "src after BN_new"))
225e4e7a30cStb 		failed |= 1;
226e4e7a30cStb 
227e4e7a30cStb 	if ((dst = BN_new()) == NULL)
228e4e7a30cStb 		errx(1, "%s: dst = BN_new()", __func__);
229e4e7a30cStb 
230e4e7a30cStb 	if (!bn_check_expected_flags(dst, BN_FLG_MALLOCED,
231e4e7a30cStb 	    __func__, "dst after BN_new"))
232e4e7a30cStb 		failed |= 1;
233e4e7a30cStb 
234e4e7a30cStb 	BN_set_flags(dst, BN_FLG_CONSTTIME);
235e4e7a30cStb 
236e4e7a30cStb 	if (!bn_check_expected_flags(dst, BN_FLG_MALLOCED | BN_FLG_CONSTTIME,
237e4e7a30cStb 	    __func__, "src after BN_new"))
238e4e7a30cStb 		failed |= 1;
239e4e7a30cStb 
240e4e7a30cStb 	if (BN_copy(dst, BN_value_one()) == NULL)
241e4e7a30cStb 		errx(1, "%s: bn_copy()", __func__);
242e4e7a30cStb 
243e4e7a30cStb 	if (!bn_check_expected_flags(dst, BN_FLG_MALLOCED | BN_FLG_CONSTTIME,
244e4e7a30cStb 	    __func__, "dst after bn_copy"))
245e4e7a30cStb 		failed |= 1;
246e4e7a30cStb 
247e4e7a30cStb 	BN_free(dst);
248e4e7a30cStb 	BN_free(src);
249e4e7a30cStb 
250e4e7a30cStb 	return failed;
251e4e7a30cStb }
252e4e7a30cStb 
253e4e7a30cStb static int
test_bn_dup_consttime_is_sticky(void)254e4e7a30cStb test_bn_dup_consttime_is_sticky(void)
255e4e7a30cStb {
256e4e7a30cStb 	BIGNUM *src, *dst;
257e4e7a30cStb 	int failed = 0;
258e4e7a30cStb 
259e4e7a30cStb 	if (!bn_check_expected_flags(BN_value_one(), BN_FLG_STATIC_DATA,
260e4e7a30cStb 	    __func__, "flags on BN_value_one()"))
261e4e7a30cStb 		failed |= 1;
262e4e7a30cStb 
263e4e7a30cStb 	if ((dst = BN_dup(BN_value_one())) == NULL)
264e4e7a30cStb 		errx(1, "%s: dst = BN_dup(BN_value_one())", __func__);
265e4e7a30cStb 
266e4e7a30cStb 	if (!bn_check_expected_flags(dst, BN_FLG_MALLOCED,
267e4e7a30cStb 	    __func__, "dst after BN_dup(BN_value_one())"))
268e4e7a30cStb 		failed |= 1;
269e4e7a30cStb 
270e4e7a30cStb 	BN_free(dst);
271e4e7a30cStb 
272e4e7a30cStb 	if ((src = BN_new()) == NULL)
273e4e7a30cStb 		errx(1, "%s: src = BN_new()", __func__);
274e4e7a30cStb 
275e4e7a30cStb 	BN_set_flags(src, BN_FLG_CONSTTIME);
276e4e7a30cStb 
277e4e7a30cStb 	if (!bn_check_expected_flags(src, BN_FLG_MALLOCED | BN_FLG_CONSTTIME,
278e4e7a30cStb 	    __func__, "src after BN_new"))
279e4e7a30cStb 		failed |= 1;
280e4e7a30cStb 
281e4e7a30cStb 	if ((dst = BN_dup(src)) == NULL)
282e4e7a30cStb 		errx(1, "%s: dst = BN_dup(src)", __func__);
283e4e7a30cStb 
284e4e7a30cStb 	if (!bn_check_expected_flags(dst, BN_FLG_MALLOCED | BN_FLG_CONSTTIME,
285e4e7a30cStb 	    __func__, "dst after bn_copy"))
286e4e7a30cStb 		failed |= 1;
287e4e7a30cStb 
288e4e7a30cStb 	BN_free(dst);
289e4e7a30cStb 	BN_free(src);
290e4e7a30cStb 
291e4e7a30cStb 	return failed;
292e4e7a30cStb }
293e4e7a30cStb 
294b8d22d11Stb int
main(void)295b8d22d11Stb main(void)
296b8d22d11Stb {
297b8d22d11Stb 	int failed = 0;
298b8d22d11Stb 
299b8d22d11Stb 	failed |= test_bn_print_null_derefs();
3000d31acbaSjsing 	failed |= test_bn_num_bits();
301ed0e3043Stb 	failed |= test_bn_num_bits_word();
302e4e7a30cStb 	failed |= test_bn_copy_copies_flags();
303e4e7a30cStb 	failed |= test_bn_copy_consttime_is_sticky();
304e4e7a30cStb 	failed |= test_bn_dup_consttime_is_sticky();
305b8d22d11Stb 
306b8d22d11Stb 	return failed;
307b8d22d11Stb }
308