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