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