xref: /openbsd-src/regress/lib/libcrypto/bn/bn_test.c (revision cbd9e74ce47bf54d30ed53df232ede22a88821f3)
1*cbd9e74cStb /*	$OpenBSD: bn_test.c,v 1.22 2025/01/22 13:02:14 tb Exp $	*/
2b8d22d11Stb /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3b8d22d11Stb  * All rights reserved.
4b8d22d11Stb  *
5b8d22d11Stb  * This package is an SSL implementation written
6b8d22d11Stb  * by Eric Young (eay@cryptsoft.com).
7b8d22d11Stb  * The implementation was written so as to conform with Netscapes SSL.
8b8d22d11Stb  *
9b8d22d11Stb  * This library is free for commercial and non-commercial use as long as
10b8d22d11Stb  * the following conditions are aheared to.  The following conditions
11b8d22d11Stb  * apply to all code found in this distribution, be it the RC4, RSA,
12b8d22d11Stb  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13b8d22d11Stb  * included with this distribution is covered by the same copyright terms
14b8d22d11Stb  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15b8d22d11Stb  *
16b8d22d11Stb  * Copyright remains Eric Young's, and as such any Copyright notices in
17b8d22d11Stb  * the code are not to be removed.
18b8d22d11Stb  * If this package is used in a product, Eric Young should be given attribution
19b8d22d11Stb  * as the author of the parts of the library used.
20b8d22d11Stb  * This can be in the form of a textual message at program startup or
21b8d22d11Stb  * in documentation (online or textual) provided with the package.
22b8d22d11Stb  *
23b8d22d11Stb  * Redistribution and use in source and binary forms, with or without
24b8d22d11Stb  * modification, are permitted provided that the following conditions
25b8d22d11Stb  * are met:
26b8d22d11Stb  * 1. Redistributions of source code must retain the copyright
27b8d22d11Stb  *    notice, this list of conditions and the following disclaimer.
28b8d22d11Stb  * 2. Redistributions in binary form must reproduce the above copyright
29b8d22d11Stb  *    notice, this list of conditions and the following disclaimer in the
30b8d22d11Stb  *    documentation and/or other materials provided with the distribution.
31b8d22d11Stb  * 3. All advertising materials mentioning features or use of this software
32b8d22d11Stb  *    must display the following acknowledgement:
33b8d22d11Stb  *    "This product includes cryptographic software written by
34b8d22d11Stb  *     Eric Young (eay@cryptsoft.com)"
35b8d22d11Stb  *    The word 'cryptographic' can be left out if the rouines from the library
36b8d22d11Stb  *    being used are not cryptographic related :-).
37b8d22d11Stb  * 4. If you include any Windows specific code (or a derivative thereof) from
38b8d22d11Stb  *    the apps directory (application code) you must include an acknowledgement:
39b8d22d11Stb  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40b8d22d11Stb  *
41b8d22d11Stb  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42b8d22d11Stb  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43b8d22d11Stb  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44b8d22d11Stb  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45b8d22d11Stb  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46b8d22d11Stb  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47b8d22d11Stb  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48b8d22d11Stb  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49b8d22d11Stb  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50b8d22d11Stb  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51b8d22d11Stb  * SUCH DAMAGE.
52b8d22d11Stb  *
53b8d22d11Stb  * The licence and distribution terms for any publically available version or
54b8d22d11Stb  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55b8d22d11Stb  * copied and put under another distribution licence
56b8d22d11Stb  * [including the GNU Public Licence.]
57b8d22d11Stb  */
58b8d22d11Stb /* ====================================================================
59b8d22d11Stb  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
60b8d22d11Stb  *
61b8d22d11Stb  * Portions of the attached software ("Contribution") are developed by
62b8d22d11Stb  * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
63b8d22d11Stb  *
64b8d22d11Stb  * The Contribution is licensed pursuant to the Eric Young open source
65b8d22d11Stb  * license provided above.
66b8d22d11Stb  *
67b8d22d11Stb  * The binary polynomial arithmetic software is originally written by
68b8d22d11Stb  * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
69b8d22d11Stb  *
70b8d22d11Stb  */
71b8d22d11Stb 
72b8d22d11Stb #include <stdio.h>
73b8d22d11Stb #include <stdlib.h>
74b8d22d11Stb #include <string.h>
75b8d22d11Stb 
76b8d22d11Stb #include <openssl/bio.h>
77b8d22d11Stb #include <openssl/bn.h>
78b8d22d11Stb #include <openssl/err.h>
79b8d22d11Stb 
8020c8b67dStb #include "bn_local.h"
81b8d22d11Stb 
82b8d22d11Stb const int num0 = 100; /* number of tests */
83b8d22d11Stb const int num1 = 50;  /* additional tests for some functions */
84b8d22d11Stb const int num2 = 5;   /* number of tests for slow functions */
85b8d22d11Stb 
860edabd22Stb int test_add(BIO *bp, BN_CTX *ctx);
870edabd22Stb int test_sub(BIO *bp, BN_CTX *ctx);
880edabd22Stb int test_lshift1(BIO *bp, BN_CTX *ctx);
894bbad1a5Stb int test_lshift(BIO *bp, BN_CTX *ctx, int use_lst);
900edabd22Stb int test_rshift1(BIO *bp, BN_CTX *ctx);
91b8d22d11Stb int test_rshift(BIO *bp, BN_CTX *ctx);
92b8d22d11Stb int test_div(BIO *bp, BN_CTX *ctx);
930edabd22Stb int test_div_word(BIO *bp, BN_CTX *ctx);
94b8d22d11Stb int test_div_recp(BIO *bp, BN_CTX *ctx);
950edabd22Stb int test_mul(BIO *bp, BN_CTX *ctx);
96b8d22d11Stb int test_sqr(BIO *bp, BN_CTX *ctx);
97b8d22d11Stb int test_mont(BIO *bp, BN_CTX *ctx);
98b8d22d11Stb int test_mod(BIO *bp, BN_CTX *ctx);
99b8d22d11Stb int test_mod_mul(BIO *bp, BN_CTX *ctx);
100b8d22d11Stb int test_mod_exp(BIO *bp, BN_CTX *ctx);
101b8d22d11Stb int test_mod_exp_mont_consttime(BIO *bp, BN_CTX *ctx);
102b8d22d11Stb int test_mod_exp_mont5(BIO *bp, BN_CTX *ctx);
103b8d22d11Stb int test_mod_exp_sizes(BIO *bp, BN_CTX *ctx);
104b8d22d11Stb int test_exp(BIO *bp, BN_CTX *ctx);
105b8d22d11Stb int test_kron(BIO *bp, BN_CTX *ctx);
106b8d22d11Stb int test_sqrt(BIO *bp, BN_CTX *ctx);
107b8d22d11Stb int rand_neg(void);
108b8d22d11Stb static int results = 0;
109b8d22d11Stb 
110b8d22d11Stb #define PRINT_ERROR printf("Error in %s [%s:%d]\n", __func__, __FILE__,	\
111b8d22d11Stb 		__LINE__)
112b8d22d11Stb 
113b8d22d11Stb #define CHECK_GOTO(a) do {						\
114b8d22d11Stb 	if (!(a)) {							\
115b8d22d11Stb 		PRINT_ERROR;						\
116b8d22d11Stb 		goto err;						\
117b8d22d11Stb 	}								\
118b8d22d11Stb } while (0)
119b8d22d11Stb 
120b8d22d11Stb static void
121b8d22d11Stb message(BIO *out, char *m)
122b8d22d11Stb {
1235550240dStb 	ERR_print_errors_fp(stderr);
1245550240dStb 	ERR_clear_error();
1255550240dStb 
126b8d22d11Stb 	fprintf(stderr, "test %s\n", m);
127b8d22d11Stb 	BIO_puts(out, "print \"test ");
128b8d22d11Stb 	BIO_puts(out, m);
129b8d22d11Stb 	BIO_puts(out, "\\n\"\n");
130b8d22d11Stb }
131b8d22d11Stb 
132b8d22d11Stb int
133b8d22d11Stb main(int argc, char *argv[])
134b8d22d11Stb {
135b8d22d11Stb 	BN_CTX *ctx;
136b8d22d11Stb 	BIO *out;
137b8d22d11Stb 	char *outfile = NULL;
138b8d22d11Stb 
139b8d22d11Stb 	results = 0;
140b8d22d11Stb 
141b8d22d11Stb 	argc--;
142b8d22d11Stb 	argv++;
143b8d22d11Stb 	while (argc >= 1) {
144b8d22d11Stb 		if (strcmp(*argv, "-results") == 0)
145b8d22d11Stb 			results = 1;
146b8d22d11Stb 		else if (strcmp(*argv, "-out") == 0) {
147b8d22d11Stb 			if (--argc < 1)
148b8d22d11Stb 				break;
149b8d22d11Stb 			outfile= *(++argv);
150b8d22d11Stb 		}
151b8d22d11Stb 		argc--;
152b8d22d11Stb 		argv++;
153b8d22d11Stb 	}
154b8d22d11Stb 
1551604cb40Stb 	if ((ctx = BN_CTX_new()) == NULL)
156b8d22d11Stb 		exit(1);
157b8d22d11Stb 
1581604cb40Stb 	if ((out = BIO_new(BIO_s_file())) == NULL)
159b8d22d11Stb 		exit(1);
160b8d22d11Stb 	if (outfile == NULL) {
161b8d22d11Stb 		BIO_set_fp(out, stdout, BIO_NOCLOSE);
162b8d22d11Stb 	} else {
163b8d22d11Stb 		if (!BIO_write_filename(out, outfile)) {
164b8d22d11Stb 			perror(outfile);
165b8d22d11Stb 			exit(1);
166b8d22d11Stb 		}
167b8d22d11Stb 	}
168b8d22d11Stb 
169b8d22d11Stb 	if (!results)
170b8d22d11Stb 		BIO_puts(out, "obase=16\nibase=16\n");
171b8d22d11Stb 
172b8d22d11Stb 	message(out, "BN_add");
1730edabd22Stb 	if (!test_add(out, ctx))
174b8d22d11Stb 		goto err;
175b8d22d11Stb 	(void)BIO_flush(out);
176b8d22d11Stb 
177b8d22d11Stb 	message(out, "BN_sub");
1780edabd22Stb 	if (!test_sub(out, ctx))
179b8d22d11Stb 		goto err;
180b8d22d11Stb 	(void)BIO_flush(out);
181b8d22d11Stb 
182b8d22d11Stb 	message(out, "BN_lshift1");
1830edabd22Stb 	if (!test_lshift1(out, ctx))
184b8d22d11Stb 		goto err;
185b8d22d11Stb 	(void)BIO_flush(out);
186b8d22d11Stb 
187b8d22d11Stb 	message(out, "BN_lshift (fixed)");
1884bbad1a5Stb 	if (!test_lshift(out, ctx, 0))
189b8d22d11Stb 		goto err;
190b8d22d11Stb 	(void)BIO_flush(out);
191b8d22d11Stb 
1920edabd22Stb 	message(out, "BN_lshift");
1930edabd22Stb 	if (!test_lshift(out, ctx, 1))
1940edabd22Stb 		goto err;
1950edabd22Stb 	(void)BIO_flush(out);
1960edabd22Stb 
197b8d22d11Stb 	message(out, "BN_rshift1");
1980edabd22Stb 	if (!test_rshift1(out, ctx))
199b8d22d11Stb 		goto err;
200b8d22d11Stb 	(void)BIO_flush(out);
201b8d22d11Stb 
202b8d22d11Stb 	message(out, "BN_rshift");
203b8d22d11Stb 	if (!test_rshift(out, ctx))
204b8d22d11Stb 		goto err;
205b8d22d11Stb 	(void)BIO_flush(out);
206b8d22d11Stb 
207b8d22d11Stb 	message(out, "BN_sqr");
208b8d22d11Stb 	if (!test_sqr(out, ctx))
209b8d22d11Stb 		goto err;
210b8d22d11Stb 	(void)BIO_flush(out);
211b8d22d11Stb 
212b8d22d11Stb 	message(out, "BN_mul");
2130edabd22Stb 	if (!test_mul(out, ctx))
214b8d22d11Stb 		goto err;
215b8d22d11Stb 	(void)BIO_flush(out);
216b8d22d11Stb 
217b8d22d11Stb 	message(out, "BN_div");
218b8d22d11Stb 	if (!test_div(out, ctx))
219b8d22d11Stb 		goto err;
220b8d22d11Stb 	(void)BIO_flush(out);
221b8d22d11Stb 
222b8d22d11Stb 	message(out, "BN_div_word");
2230edabd22Stb 	if (!test_div_word(out, ctx))
224b8d22d11Stb 		goto err;
225b8d22d11Stb 	(void)BIO_flush(out);
226b8d22d11Stb 
2272d506d2eStb 	message(out, "BN_div_reciprocal");
228b8d22d11Stb 	if (!test_div_recp(out, ctx))
229b8d22d11Stb 		goto err;
230b8d22d11Stb 	(void)BIO_flush(out);
231b8d22d11Stb 
232b8d22d11Stb 	message(out, "BN_mod");
233b8d22d11Stb 	if (!test_mod(out, ctx))
234b8d22d11Stb 		goto err;
235b8d22d11Stb 	(void)BIO_flush(out);
236b8d22d11Stb 
237b8d22d11Stb 	message(out, "BN_mod_mul");
238b8d22d11Stb 	if (!test_mod_mul(out, ctx))
239b8d22d11Stb 		goto err;
240b8d22d11Stb 	(void)BIO_flush(out);
241b8d22d11Stb 
242b8d22d11Stb 	message(out, "BN_mont");
243b8d22d11Stb 	if (!test_mont(out, ctx))
244b8d22d11Stb 		goto err;
245b8d22d11Stb 	(void)BIO_flush(out);
246b8d22d11Stb 
247b8d22d11Stb 	message(out, "BN_mod_exp");
248b8d22d11Stb 	if (!test_mod_exp(out, ctx))
249b8d22d11Stb 		goto err;
250b8d22d11Stb 	(void)BIO_flush(out);
251b8d22d11Stb 
252b8d22d11Stb 	message(out, "BN_mod_exp_mont_consttime");
253b8d22d11Stb 	if (!test_mod_exp_mont_consttime(out, ctx))
254b8d22d11Stb 		goto err;
255b8d22d11Stb 	(void)BIO_flush(out);
256b8d22d11Stb 
257b8d22d11Stb 	message(out, "BN_mod_exp_mont5");
258b8d22d11Stb 	if (!test_mod_exp_mont5(out, ctx))
259b8d22d11Stb 		goto err;
260b8d22d11Stb 	(void)BIO_flush(out);
261b8d22d11Stb 
262b8d22d11Stb 	message(out, "BN_exp");
263b8d22d11Stb 	if (!test_exp(out, ctx))
264b8d22d11Stb 		goto err;
265b8d22d11Stb 	(void)BIO_flush(out);
266b8d22d11Stb 
267b8d22d11Stb 	message(out, "BN_kronecker");
268b8d22d11Stb 	if (!test_kron(out, ctx))
269b8d22d11Stb 		goto err;
270b8d22d11Stb 	(void)BIO_flush(out);
271b8d22d11Stb 
272b8d22d11Stb 	message(out, "BN_mod_sqrt");
273b8d22d11Stb 	if (!test_sqrt(out, ctx))
274b8d22d11Stb 		goto err;
275b8d22d11Stb 	(void)BIO_flush(out);
276b8d22d11Stb 
277b8d22d11Stb 	message(out, "Modexp with different sizes");
278b8d22d11Stb 	if (!test_mod_exp_sizes(out, ctx))
279b8d22d11Stb 		goto err;
280b8d22d11Stb 	(void)BIO_flush(out);
281b8d22d11Stb 
282b8d22d11Stb 	BN_CTX_free(ctx);
283b8d22d11Stb 	BIO_free(out);
284b8d22d11Stb 
285b8d22d11Stb 	exit(0);
286b8d22d11Stb  err:
287b8d22d11Stb 	BIO_puts(out, "1\n"); /* make sure the Perl script fed by bc notices
288b8d22d11Stb 	                       * the failure, see test_bn in test/Makefile.ssl*/
289b8d22d11Stb 
290b8d22d11Stb 	(void)BIO_flush(out);
291b8d22d11Stb 	ERR_load_crypto_strings();
292b8d22d11Stb 	ERR_print_errors_fp(stderr);
293b8d22d11Stb 	exit(1);
294b8d22d11Stb }
295b8d22d11Stb 
296b8d22d11Stb int
2970edabd22Stb test_add(BIO *bp, BN_CTX *ctx)
298b8d22d11Stb {
2990edabd22Stb 	BIGNUM *a, *b, *c;
300b8d22d11Stb 	int i;
301f7264475Stb 	int ret = 0;
302b8d22d11Stb 
3030edabd22Stb 	BN_CTX_start(ctx);
3040edabd22Stb 
3050edabd22Stb 	if ((a = BN_CTX_get(ctx)) == NULL)
306b8d22d11Stb 		goto err;
3070edabd22Stb 	if ((b = BN_CTX_get(ctx)) == NULL)
308b8d22d11Stb 		goto err;
3090edabd22Stb 	if ((c = BN_CTX_get(ctx)) == NULL)
310b8d22d11Stb 		goto err;
311b8d22d11Stb 
312b8d22d11Stb 	CHECK_GOTO(BN_bntest_rand(a, 512, 0, 0));
313b8d22d11Stb 	for (i = 0; i < num0; i++) {
314b8d22d11Stb 		CHECK_GOTO(BN_bntest_rand(b, 450 + i, 0, 0));
315b8d22d11Stb 		BN_set_negative(a, rand_neg());
316b8d22d11Stb 		BN_set_negative(b, rand_neg());
317b8d22d11Stb 		CHECK_GOTO(BN_add(c, a, b));
318b8d22d11Stb 		if (bp != NULL) {
319b8d22d11Stb 			if (!results) {
320b8d22d11Stb 				CHECK_GOTO(BN_print(bp, a));
321b8d22d11Stb 				BIO_puts(bp, " + ");
322b8d22d11Stb 				CHECK_GOTO(BN_print(bp, b));
323b8d22d11Stb 				BIO_puts(bp, " - ");
324b8d22d11Stb 			}
325b8d22d11Stb 			CHECK_GOTO(BN_print(bp, c));
326b8d22d11Stb 			BIO_puts(bp, "\n");
327b8d22d11Stb 		}
328b8d22d11Stb 		BN_set_negative(a, !BN_is_negative(a));
329b8d22d11Stb 		BN_set_negative(b, !BN_is_negative(b));
330b8d22d11Stb 		CHECK_GOTO(BN_add(c, c, b));
331b8d22d11Stb 		CHECK_GOTO(BN_add(c, c, a));
332b8d22d11Stb 		if (!BN_is_zero(c)) {
333b8d22d11Stb 			fprintf(stderr, "Add test failed!\n");
3342e7cce5eStb 			goto err;
335b8d22d11Stb 		}
336b8d22d11Stb 	}
337b8d22d11Stb 
338f7264475Stb 	ret = 1;
339b8d22d11Stb  err:
3400edabd22Stb 	BN_CTX_end(ctx);
341b8d22d11Stb 
342f7264475Stb 	return ret;
343b8d22d11Stb }
344b8d22d11Stb 
345b8d22d11Stb int
3460edabd22Stb test_sub(BIO *bp, BN_CTX *ctx)
347b8d22d11Stb {
3480edabd22Stb 	BIGNUM *a, *b, *c;
349b8d22d11Stb 	int i;
350f7264475Stb 	int ret = 0;
351b8d22d11Stb 
3520edabd22Stb 	BN_CTX_start(ctx);
3530edabd22Stb 
3540edabd22Stb 	if ((a = BN_CTX_get(ctx)) == NULL)
355b8d22d11Stb 		goto err;
3560edabd22Stb 	if ((b = BN_CTX_get(ctx)) == NULL)
357b8d22d11Stb 		goto err;
3580edabd22Stb 	if ((c = BN_CTX_get(ctx)) == NULL)
359b8d22d11Stb 		goto err;
360b8d22d11Stb 
361b8d22d11Stb 	for (i = 0; i < num0 + num1; i++) {
362b8d22d11Stb 		if (i < num1) {
363b8d22d11Stb 			CHECK_GOTO(BN_bntest_rand(a, 512, 0, 0));
3648e84e241Stb 			CHECK_GOTO(bn_copy(b, a));
365457e5092Stb 			if (BN_set_bit(a, i) == 0)
3662e7cce5eStb 				goto err;
367b8d22d11Stb 			CHECK_GOTO(BN_add_word(b, i));
368b8d22d11Stb 		} else {
369b8d22d11Stb 			CHECK_GOTO(BN_bntest_rand(b, 400 + i - num1, 0, 0));
370b8d22d11Stb 			BN_set_negative(a, rand_neg());
371b8d22d11Stb 			BN_set_negative(b, rand_neg());
372b8d22d11Stb 		}
373b8d22d11Stb 		CHECK_GOTO(BN_sub(c, a, b));
374b8d22d11Stb 		if (bp != NULL) {
375b8d22d11Stb 			if (!results) {
376b8d22d11Stb 				CHECK_GOTO(BN_print(bp, a));
377b8d22d11Stb 				BIO_puts(bp, " - ");
378b8d22d11Stb 				CHECK_GOTO(BN_print(bp, b));
379b8d22d11Stb 				BIO_puts(bp, " - ");
380b8d22d11Stb 			}
381b8d22d11Stb 			CHECK_GOTO(BN_print(bp, c));
382b8d22d11Stb 			BIO_puts(bp, "\n");
383b8d22d11Stb 		}
384b8d22d11Stb 		CHECK_GOTO(BN_add(c, c, b));
385b8d22d11Stb 		CHECK_GOTO(BN_sub(c, c, a));
386b8d22d11Stb 		if (!BN_is_zero(c)) {
387b8d22d11Stb 			fprintf(stderr, "Subtract test failed!\n");
3882e7cce5eStb 			goto err;
389b8d22d11Stb 		}
390b8d22d11Stb 	}
3912e7cce5eStb 
392f7264475Stb 	ret = 1;
393b8d22d11Stb  err:
3940edabd22Stb 	BN_CTX_end(ctx);
3952e7cce5eStb 
396f7264475Stb 	return ret;
397b8d22d11Stb }
398b8d22d11Stb 
399b8d22d11Stb int
400b8d22d11Stb test_div(BIO *bp, BN_CTX *ctx)
401b8d22d11Stb {
4020edabd22Stb 	BIGNUM *a, *b, *c, *d, *e;
403b8d22d11Stb 	int i;
404f7264475Stb 	int ret = 0;
405b8d22d11Stb 
4060edabd22Stb 	BN_CTX_start(ctx);
4070edabd22Stb 
4080edabd22Stb 	if ((a = BN_CTX_get(ctx)) == NULL)
409b8d22d11Stb 		goto err;
4100edabd22Stb 	if ((b = BN_CTX_get(ctx)) == NULL)
411b8d22d11Stb 		goto err;
4120edabd22Stb 	if ((c = BN_CTX_get(ctx)) == NULL)
413b8d22d11Stb 		goto err;
4140edabd22Stb 	if ((d = BN_CTX_get(ctx)) == NULL)
415b8d22d11Stb 		goto err;
4160edabd22Stb 	if ((e = BN_CTX_get(ctx)) == NULL)
417b8d22d11Stb 		goto err;
418b8d22d11Stb 
419b8d22d11Stb 	CHECK_GOTO(BN_one(a));
42030ad135cStb 	BN_zero(b);
421b8d22d11Stb 
422b8d22d11Stb 	if (BN_div(d, c, a, b, ctx)) {
423b8d22d11Stb 		fprintf(stderr, "Division by zero succeeded!\n");
424bb44b87cStb 		goto err;
425b8d22d11Stb 	}
4265550240dStb 	ERR_clear_error();
427b8d22d11Stb 
428b8d22d11Stb 	for (i = 0; i < num0 + num1; i++) {
429b8d22d11Stb 		if (i < num1) {
430b8d22d11Stb 			CHECK_GOTO(BN_bntest_rand(a, 400, 0, 0));
4318e84e241Stb 			CHECK_GOTO(bn_copy(b, a));
432b8d22d11Stb 			CHECK_GOTO(BN_lshift(a, a, i));
433b8d22d11Stb 			CHECK_GOTO(BN_add_word(a, i));
434b8d22d11Stb 		} else
435b8d22d11Stb 			CHECK_GOTO(BN_bntest_rand(b, 50 + 3 * (i - num1), 0, 0));
436b8d22d11Stb 		BN_set_negative(a, rand_neg());
437b8d22d11Stb 		BN_set_negative(b, rand_neg());
438b8d22d11Stb 		CHECK_GOTO(BN_div(d, c, a, b, ctx));
439b8d22d11Stb 		if (bp != NULL) {
440b8d22d11Stb 			if (!results) {
441b8d22d11Stb 				CHECK_GOTO(BN_print(bp, a));
442b8d22d11Stb 				BIO_puts(bp, " / ");
443b8d22d11Stb 				CHECK_GOTO(BN_print(bp, b));
444b8d22d11Stb 				BIO_puts(bp, " - ");
445b8d22d11Stb 			}
446b8d22d11Stb 			CHECK_GOTO(BN_print(bp, d));
447b8d22d11Stb 			BIO_puts(bp, "\n");
448b8d22d11Stb 
449b8d22d11Stb 			if (!results) {
450b8d22d11Stb 				CHECK_GOTO(BN_print(bp, a));
451b8d22d11Stb 				BIO_puts(bp, " % ");
452b8d22d11Stb 				CHECK_GOTO(BN_print(bp, b));
453b8d22d11Stb 				BIO_puts(bp, " - ");
454b8d22d11Stb 			}
455b8d22d11Stb 			CHECK_GOTO(BN_print(bp, c));
456b8d22d11Stb 			BIO_puts(bp, "\n");
457b8d22d11Stb 		}
458b8d22d11Stb 		CHECK_GOTO(BN_mul(e, d, b, ctx));
459b8d22d11Stb 		CHECK_GOTO(BN_add(d, e, c));
460b8d22d11Stb 		CHECK_GOTO(BN_sub(d, d, a));
461b8d22d11Stb 		if (!BN_is_zero(d)) {
462b8d22d11Stb 			fprintf(stderr, "Division test failed!\n");
4632e7cce5eStb 			goto err;
464b8d22d11Stb 		}
465b8d22d11Stb 	}
4662e7cce5eStb 
467f7264475Stb 	ret = 1;
468b8d22d11Stb  err:
4690edabd22Stb 	BN_CTX_end(ctx);
4702e7cce5eStb 
471f7264475Stb 	return ret;
472b8d22d11Stb }
473b8d22d11Stb 
474b8d22d11Stb static void
475b8d22d11Stb print_word(BIO *bp, BN_ULONG w)
476b8d22d11Stb {
477b8d22d11Stb #ifdef SIXTY_FOUR_BIT
478b8d22d11Stb 	if (sizeof(w) > sizeof(unsigned long)) {
479b8d22d11Stb 		unsigned long h = (unsigned long)(w >> 32), l = (unsigned long)(w);
480b8d22d11Stb 
481b8d22d11Stb 		if (h)
482b8d22d11Stb 			BIO_printf(bp, "%lX%08lX", h, l);
483b8d22d11Stb 		else
484b8d22d11Stb 			BIO_printf(bp, "%lX", l);
485b8d22d11Stb 		return;
486b8d22d11Stb 	}
487b8d22d11Stb #endif
488b8d22d11Stb 	BIO_printf(bp, BN_HEX_FMT1, w);
489b8d22d11Stb }
490b8d22d11Stb 
491b8d22d11Stb int
4920edabd22Stb test_div_word(BIO *bp, BN_CTX *ctx)
493b8d22d11Stb {
4940edabd22Stb 	BIGNUM *a, *b;
495b8d22d11Stb 	BN_ULONG r, rmod, s = 0;
496b8d22d11Stb 	int i;
497f7264475Stb 	int ret = 0;
498b8d22d11Stb 
4990edabd22Stb 	BN_CTX_start(ctx);
5000edabd22Stb 
5010edabd22Stb 	if ((a = BN_CTX_get(ctx)) == NULL)
502b8d22d11Stb 		goto err;
5030edabd22Stb 	if ((b = BN_CTX_get(ctx)) == NULL)
504b8d22d11Stb 		goto err;
505b8d22d11Stb 
506b8d22d11Stb 	for (i = 0; i < num0; i++) {
507b8d22d11Stb 		do {
508b8d22d11Stb 			if (!BN_bntest_rand(a, 512, -1, 0) ||
509457e5092Stb 			    !BN_bntest_rand(b, BN_BITS2, -1, 0))
5102e7cce5eStb 				goto err;
511b8d22d11Stb 			s = BN_get_word(b);
512b8d22d11Stb 		} while (!s);
513b8d22d11Stb 
514457e5092Stb 		if (!bn_copy(b, a))
5152e7cce5eStb 			goto err;
516b8d22d11Stb 
517b8d22d11Stb 		rmod = BN_mod_word(b, s);
518b8d22d11Stb 		r = BN_div_word(b, s);
519b8d22d11Stb 
520457e5092Stb 		if (r == (BN_ULONG)-1 || rmod == (BN_ULONG)-1)
5212e7cce5eStb 			goto err;
522b8d22d11Stb 
523b8d22d11Stb 		if (rmod != r) {
524b8d22d11Stb 			fprintf(stderr, "Mod (word) test failed!\n");
5252e7cce5eStb 			goto err;
526b8d22d11Stb 		}
527b8d22d11Stb 
528b8d22d11Stb 		if (bp != NULL) {
529b8d22d11Stb 			if (!results) {
530b8d22d11Stb 				CHECK_GOTO(BN_print(bp, a));
531b8d22d11Stb 				BIO_puts(bp, " / ");
532b8d22d11Stb 				print_word(bp, s);
533b8d22d11Stb 				BIO_puts(bp, " - ");
534b8d22d11Stb 			}
535b8d22d11Stb 			CHECK_GOTO(BN_print(bp, b));
536b8d22d11Stb 			BIO_puts(bp, "\n");
537b8d22d11Stb 
538b8d22d11Stb 			if (!results) {
539b8d22d11Stb 				CHECK_GOTO(BN_print(bp, a));
540b8d22d11Stb 				BIO_puts(bp, " % ");
541b8d22d11Stb 				print_word(bp, s);
542b8d22d11Stb 				BIO_puts(bp, " - ");
543b8d22d11Stb 			}
544b8d22d11Stb 			print_word(bp, r);
545b8d22d11Stb 			BIO_puts(bp, "\n");
546b8d22d11Stb 		}
547b8d22d11Stb 		CHECK_GOTO(BN_mul_word(b, s));
548b8d22d11Stb 		CHECK_GOTO(BN_add_word(b, r));
549b8d22d11Stb 		CHECK_GOTO(BN_sub(b, a, b));
550b8d22d11Stb 		if (!BN_is_zero(b)) {
551b8d22d11Stb 			fprintf(stderr, "Division (word) test failed!\n");
5522e7cce5eStb 			goto err;
553b8d22d11Stb 		}
554b8d22d11Stb 	}
5552e7cce5eStb 
556f7264475Stb 	ret = 1;
557b8d22d11Stb  err:
5580edabd22Stb 	BN_CTX_end(ctx);
559b8d22d11Stb 
560f7264475Stb 	return ret;
561b8d22d11Stb }
562b8d22d11Stb 
563b8d22d11Stb int
564b8d22d11Stb test_div_recp(BIO *bp, BN_CTX *ctx)
565b8d22d11Stb {
566b8d22d11Stb 	BN_RECP_CTX *recp = NULL;
5670edabd22Stb 	BIGNUM *a, *b, *c, *d, *e;
568b8d22d11Stb 	int i;
569f7264475Stb 	int ret = 0;
570b8d22d11Stb 
5710edabd22Stb 	BN_CTX_start(ctx);
5720edabd22Stb 
5730edabd22Stb 	if ((a = BN_CTX_get(ctx)) == NULL)
574b8d22d11Stb 		goto err;
5750edabd22Stb 	if ((b = BN_CTX_get(ctx)) == NULL)
576b8d22d11Stb 		goto err;
5770edabd22Stb 	if ((c = BN_CTX_get(ctx)) == NULL)
578b8d22d11Stb 		goto err;
5790edabd22Stb 	if ((d = BN_CTX_get(ctx)) == NULL)
580b8d22d11Stb 		goto err;
5810edabd22Stb 	if ((e = BN_CTX_get(ctx)) == NULL)
582b8d22d11Stb 		goto err;
583b8d22d11Stb 
584b8d22d11Stb 	for (i = 0; i < num0 + num1; i++) {
585b8d22d11Stb 		if (i < num1) {
586b8d22d11Stb 			CHECK_GOTO(BN_bntest_rand(a, 400, 0, 0));
5878e84e241Stb 			CHECK_GOTO(bn_copy(b, a));
588b8d22d11Stb 			CHECK_GOTO(BN_lshift(a, a, i));
589b8d22d11Stb 			CHECK_GOTO(BN_add_word(a, i));
590b8d22d11Stb 		} else
591b8d22d11Stb 			CHECK_GOTO(BN_bntest_rand(b, 50 + 3 * (i - num1), 0, 0));
5926a951d55Stb 		BN_RECP_CTX_free(recp);
5936a951d55Stb 		CHECK_GOTO(recp = BN_RECP_CTX_create(b));
5942d506d2eStb 		CHECK_GOTO(BN_div_reciprocal(d, c, a, recp, ctx));
595b8d22d11Stb 		if (bp != NULL) {
596b8d22d11Stb 			if (!results) {
597b8d22d11Stb 				CHECK_GOTO(BN_print(bp, a));
598b8d22d11Stb 				BIO_puts(bp, " / ");
599b8d22d11Stb 				CHECK_GOTO(BN_print(bp, b));
600b8d22d11Stb 				BIO_puts(bp, " - ");
601b8d22d11Stb 			}
602b8d22d11Stb 			CHECK_GOTO(BN_print(bp, d));
603b8d22d11Stb 			BIO_puts(bp, "\n");
604b8d22d11Stb 
605b8d22d11Stb 			if (!results) {
606b8d22d11Stb 				CHECK_GOTO(BN_print(bp, a));
607b8d22d11Stb 				BIO_puts(bp, " % ");
608b8d22d11Stb 				CHECK_GOTO(BN_print(bp, b));
609b8d22d11Stb 				BIO_puts(bp, " - ");
610b8d22d11Stb 			}
611b8d22d11Stb 			CHECK_GOTO(BN_print(bp, c));
612b8d22d11Stb 			BIO_puts(bp, "\n");
613b8d22d11Stb 		}
614b8d22d11Stb 		CHECK_GOTO(BN_mul(e, d, b, ctx));
615b8d22d11Stb 		CHECK_GOTO(BN_add(d, e, c));
616b8d22d11Stb 		CHECK_GOTO(BN_sub(d, d, a));
617b8d22d11Stb 		if (!BN_is_zero(d)) {
618b8d22d11Stb 			fprintf(stderr, "Reciprocal division test failed!\n");
619b8d22d11Stb 			fprintf(stderr, "a=");
620b8d22d11Stb 			CHECK_GOTO(BN_print_fp(stderr, a));
621b8d22d11Stb 			fprintf(stderr, "\nb=");
622b8d22d11Stb 			CHECK_GOTO(BN_print_fp(stderr, b));
623b8d22d11Stb 			fprintf(stderr, "\n");
6242e7cce5eStb 			goto err;
625b8d22d11Stb 		}
626b8d22d11Stb 	}
6272e7cce5eStb 
628f7264475Stb 	ret = 1;
629b8d22d11Stb  err:
6300edabd22Stb 	BN_CTX_end(ctx);
631b8d22d11Stb 	BN_RECP_CTX_free(recp);
6322e7cce5eStb 
633f7264475Stb 	return ret;
634b8d22d11Stb }
635b8d22d11Stb 
636b8d22d11Stb int
6370edabd22Stb test_mul(BIO *bp, BN_CTX *ctx)
638b8d22d11Stb {
6390edabd22Stb 	BIGNUM *a, *b, *c, *d, *e;
640b8d22d11Stb 	int i;
641f7264475Stb 	int ret = 0;
642b8d22d11Stb 
6430edabd22Stb 	BN_CTX_start(ctx);
644b8d22d11Stb 
6450edabd22Stb 	if ((a = BN_CTX_get(ctx)) == NULL)
646b8d22d11Stb 		goto err;
6470edabd22Stb 	if ((b = BN_CTX_get(ctx)) == NULL)
648b8d22d11Stb 		goto err;
6490edabd22Stb 	if ((c = BN_CTX_get(ctx)) == NULL)
650b8d22d11Stb 		goto err;
6510edabd22Stb 	if ((d = BN_CTX_get(ctx)) == NULL)
652b8d22d11Stb 		goto err;
6530edabd22Stb 	if ((e = BN_CTX_get(ctx)) == NULL)
654b8d22d11Stb 		goto err;
655b8d22d11Stb 
656b8d22d11Stb 	for (i = 0; i < num0 + num1; i++) {
657b8d22d11Stb 		if (i <= num1) {
658b8d22d11Stb 			CHECK_GOTO(BN_bntest_rand(a, 100, 0, 0));
659b8d22d11Stb 			CHECK_GOTO(BN_bntest_rand(b, 100, 0, 0));
660b8d22d11Stb 		} else
661b8d22d11Stb 			CHECK_GOTO(BN_bntest_rand(b, i - num1, 0, 0));
662b8d22d11Stb 		BN_set_negative(a, rand_neg());
663b8d22d11Stb 		BN_set_negative(b, rand_neg());
664b8d22d11Stb 		CHECK_GOTO(BN_mul(c, a, b, ctx));
665b8d22d11Stb 		if (bp != NULL) {
666b8d22d11Stb 			if (!results) {
667b8d22d11Stb 				CHECK_GOTO(BN_print(bp, a));
668b8d22d11Stb 				BIO_puts(bp, " * ");
669b8d22d11Stb 				CHECK_GOTO(BN_print(bp, b));
670b8d22d11Stb 				BIO_puts(bp, " - ");
671b8d22d11Stb 			}
672b8d22d11Stb 			CHECK_GOTO(BN_print(bp, c));
673b8d22d11Stb 			BIO_puts(bp, "\n");
674b8d22d11Stb 		}
675b8d22d11Stb 		CHECK_GOTO(BN_div(d, e, c, a, ctx));
676b8d22d11Stb 		CHECK_GOTO(BN_sub(d, d, b));
677b8d22d11Stb 		if (!BN_is_zero(d) || !BN_is_zero(e)) {
678b8d22d11Stb 			fprintf(stderr, "Multiplication test failed!\n");
6792e7cce5eStb 			goto err;
680b8d22d11Stb 		}
681b8d22d11Stb 	}
6822e7cce5eStb 
683f7264475Stb 	ret = 1;
684b8d22d11Stb  err:
6850edabd22Stb 	BN_CTX_end(ctx);
6862e7cce5eStb 
687f7264475Stb 	return ret;
688b8d22d11Stb }
689b8d22d11Stb 
690b8d22d11Stb int
691b8d22d11Stb test_sqr(BIO *bp, BN_CTX *ctx)
692b8d22d11Stb {
6930edabd22Stb 	BIGNUM *a, *c, *d, *e;
694568ce9ecStb 	int i;
695f7264475Stb 	int ret = 0;
696b8d22d11Stb 
6970edabd22Stb 	BN_CTX_start(ctx);
6980edabd22Stb 
6990edabd22Stb 	if ((a = BN_CTX_get(ctx)) == NULL)
700b8d22d11Stb 		goto err;
7010edabd22Stb 	if ((c = BN_CTX_get(ctx)) == NULL)
702b8d22d11Stb 		goto err;
7030edabd22Stb 	if ((d = BN_CTX_get(ctx)) == NULL)
704b8d22d11Stb 		goto err;
7050edabd22Stb 	if ((e = BN_CTX_get(ctx)) == NULL)
706b8d22d11Stb 		goto err;
707b8d22d11Stb 
708b8d22d11Stb 	for (i = 0; i < num0; i++) {
709b8d22d11Stb 		CHECK_GOTO(BN_bntest_rand(a, 40 + i * 10, 0, 0));
710b8d22d11Stb 		BN_set_negative(a, rand_neg());
711b8d22d11Stb 		CHECK_GOTO(BN_sqr(c, a, ctx));
712b8d22d11Stb 		if (bp != NULL) {
713b8d22d11Stb 			if (!results) {
714b8d22d11Stb 				CHECK_GOTO(BN_print(bp, a));
715b8d22d11Stb 				BIO_puts(bp, " * ");
716b8d22d11Stb 				CHECK_GOTO(BN_print(bp, a));
717b8d22d11Stb 				BIO_puts(bp, " - ");
718b8d22d11Stb 			}
719b8d22d11Stb 			CHECK_GOTO(BN_print(bp, c));
720b8d22d11Stb 			BIO_puts(bp, "\n");
721b8d22d11Stb 		}
722b8d22d11Stb 		CHECK_GOTO(BN_div(d, e, c, a, ctx));
723b8d22d11Stb 		CHECK_GOTO(BN_sub(d, d, a));
724b8d22d11Stb 		if (!BN_is_zero(d) || !BN_is_zero(e)) {
725b8d22d11Stb 			fprintf(stderr, "Square test failed!\n");
726b8d22d11Stb 			goto err;
727b8d22d11Stb 		}
728b8d22d11Stb 	}
729b8d22d11Stb 
730b8d22d11Stb 	/* Regression test for a BN_sqr overflow bug. */
731b8d22d11Stb 	if (!BN_hex2bn(&a, "80000000000000008000000000000001"
732b8d22d11Stb 	    "FFFFFFFFFFFFFFFE0000000000000000")) {
733b8d22d11Stb 		fprintf(stderr, "BN_hex2bn failed\n");
734b8d22d11Stb 		goto err;
735b8d22d11Stb 	}
736b8d22d11Stb 	CHECK_GOTO(BN_sqr(c, a, ctx));
737b8d22d11Stb 	if (bp != NULL) {
738b8d22d11Stb 		if (!results) {
739b8d22d11Stb 			CHECK_GOTO(BN_print(bp, a));
740b8d22d11Stb 			BIO_puts(bp, " * ");
741b8d22d11Stb 			CHECK_GOTO(BN_print(bp, a));
742b8d22d11Stb 			BIO_puts(bp, " - ");
743b8d22d11Stb 		}
744b8d22d11Stb 		CHECK_GOTO(BN_print(bp, c));
745b8d22d11Stb 		BIO_puts(bp, "\n");
746b8d22d11Stb 	}
747b8d22d11Stb 	CHECK_GOTO(BN_mul(d, a, a, ctx));
748b8d22d11Stb 	if (BN_cmp(c, d)) {
749b8d22d11Stb 		fprintf(stderr,
750b8d22d11Stb 		    "Square test failed: BN_sqr and BN_mul produce "
751b8d22d11Stb 		    "different results!\n");
752b8d22d11Stb 		goto err;
753b8d22d11Stb 	}
754b8d22d11Stb 
755b8d22d11Stb 	/* Regression test for a BN_sqr overflow bug. */
756b8d22d11Stb 	if (!BN_hex2bn(&a, "80000000000000000000000080000001"
757b8d22d11Stb 	    "FFFFFFFE000000000000000000000000")) {
758b8d22d11Stb 		fprintf(stderr, "BN_hex2bn failed\n");
759b8d22d11Stb 		goto err;
760b8d22d11Stb 	}
761b8d22d11Stb 	CHECK_GOTO(BN_sqr(c, a, ctx));
762b8d22d11Stb 	if (bp != NULL) {
763b8d22d11Stb 		if (!results) {
764b8d22d11Stb 			CHECK_GOTO(BN_print(bp, a));
765b8d22d11Stb 			BIO_puts(bp, " * ");
766b8d22d11Stb 			CHECK_GOTO(BN_print(bp, a));
767b8d22d11Stb 			BIO_puts(bp, " - ");
768b8d22d11Stb 		}
769b8d22d11Stb 		CHECK_GOTO(BN_print(bp, c));
770b8d22d11Stb 		BIO_puts(bp, "\n");
771b8d22d11Stb 	}
772b8d22d11Stb 	CHECK_GOTO(BN_mul(d, a, a, ctx));
773b8d22d11Stb 	if (BN_cmp(c, d)) {
774b8d22d11Stb 		fprintf(stderr, "Square test failed: BN_sqr and BN_mul produce "
775b8d22d11Stb 				"different results!\n");
776b8d22d11Stb 		goto err;
777b8d22d11Stb 	}
7782e7cce5eStb 
779f7264475Stb 	ret = 1;
780b8d22d11Stb  err:
7810edabd22Stb 	BN_CTX_end(ctx);
7822e7cce5eStb 
783f7264475Stb 	return ret;
784b8d22d11Stb }
785b8d22d11Stb 
786b8d22d11Stb int
787b8d22d11Stb test_mont(BIO *bp, BN_CTX *ctx)
788b8d22d11Stb {
7890edabd22Stb 	BN_MONT_CTX *mont = NULL;
7900edabd22Stb 	BIGNUM *a, *b, *c, *d, *A, *B, *n;
791b8d22d11Stb 	int i;
792f7264475Stb 	int ret = 0;
793b8d22d11Stb 
7940edabd22Stb 	BN_CTX_start(ctx);
795b8d22d11Stb 
7960edabd22Stb 	if ((a = BN_CTX_get(ctx)) == NULL)
797b8d22d11Stb 		goto err;
7980edabd22Stb 	if ((b = BN_CTX_get(ctx)) == NULL)
799b8d22d11Stb 		goto err;
8000edabd22Stb 	if ((c = BN_CTX_get(ctx)) == NULL)
801b8d22d11Stb 		goto err;
8020edabd22Stb 	if ((d = BN_CTX_get(ctx)) == NULL)
803b8d22d11Stb 		goto err;
8040edabd22Stb 	if ((A = BN_CTX_get(ctx)) == NULL)
805b8d22d11Stb 		goto err;
8060edabd22Stb 	if ((B = BN_CTX_get(ctx)) == NULL)
807b8d22d11Stb 		goto err;
8080edabd22Stb 	if ((n = BN_CTX_get(ctx)) == NULL)
8090edabd22Stb 		goto err;
8100edabd22Stb 
8110edabd22Stb 	if ((mont = BN_MONT_CTX_new()) == NULL)
812b8d22d11Stb 		goto err;
813b8d22d11Stb 
81430ad135cStb 	BN_zero(n);
815b8d22d11Stb 	if (BN_MONT_CTX_set(mont, n, ctx)) {
816b8d22d11Stb 		fprintf(stderr, "BN_MONT_CTX_set succeeded for zero modulus!\n");
817bb44b87cStb 		goto err;
818b8d22d11Stb 	}
8195550240dStb 	ERR_clear_error();
820b8d22d11Stb 
821b8d22d11Stb 	CHECK_GOTO(BN_set_word(n, 16));
822b8d22d11Stb 	if (BN_MONT_CTX_set(mont, n, ctx)) {
823b8d22d11Stb 		fprintf(stderr, "BN_MONT_CTX_set succeeded for even modulus!\n");
824bb44b87cStb 		goto err;
825b8d22d11Stb 	}
8265550240dStb 	ERR_clear_error();
827b8d22d11Stb 
828b8d22d11Stb 	CHECK_GOTO(BN_bntest_rand(a, 100, 0, 0));
829b8d22d11Stb 	CHECK_GOTO(BN_bntest_rand(b, 100, 0, 0));
830b8d22d11Stb 	for (i = 0; i < num2; i++) {
831b8d22d11Stb 		int bits = (200 * (i + 1)) / num2;
832b8d22d11Stb 
833b8d22d11Stb 		if (bits == 0)
834b8d22d11Stb 			continue;
835b8d22d11Stb 		CHECK_GOTO(BN_bntest_rand(n, bits, 0, 1));
836b8d22d11Stb 		CHECK_GOTO(BN_MONT_CTX_set(mont, n, ctx));
837b8d22d11Stb 
838b8d22d11Stb 		CHECK_GOTO(BN_nnmod(a, a, n, ctx));
839b8d22d11Stb 		CHECK_GOTO(BN_nnmod(b, b, n, ctx));
840b8d22d11Stb 
841b8d22d11Stb 		CHECK_GOTO(BN_to_montgomery(A, a, mont, ctx));
842b8d22d11Stb 		CHECK_GOTO(BN_to_montgomery(B, b, mont, ctx));
843b8d22d11Stb 
844b8d22d11Stb 		CHECK_GOTO(BN_mod_mul_montgomery(c, A, B, mont, ctx));
845b8d22d11Stb 		CHECK_GOTO(BN_from_montgomery(A, c, mont, ctx));
846b8d22d11Stb 		if (bp != NULL) {
847b8d22d11Stb 			if (!results) {
848b8d22d11Stb 				CHECK_GOTO(BN_print(bp, a));
849b8d22d11Stb 				BIO_puts(bp, " * ");
850b8d22d11Stb 				CHECK_GOTO(BN_print(bp, b));
851b8d22d11Stb 				BIO_puts(bp, " % ");
852b8d22d11Stb 				/* n == &mont->N */
853b8d22d11Stb 				CHECK_GOTO(BN_print(bp, n));
854b8d22d11Stb 				BIO_puts(bp, " - ");
855b8d22d11Stb 			}
856b8d22d11Stb 			CHECK_GOTO(BN_print(bp, A));
857b8d22d11Stb 			BIO_puts(bp, "\n");
858b8d22d11Stb 		}
859b8d22d11Stb 		CHECK_GOTO(BN_mod_mul(d, a, b, n, ctx));
860b8d22d11Stb 		CHECK_GOTO(BN_sub(d, d, A));
861b8d22d11Stb 		if (!BN_is_zero(d)) {
862b8d22d11Stb 			fprintf(stderr, "Montgomery multiplication test failed!\n");
8632e7cce5eStb 			goto err;
864b8d22d11Stb 		}
865b8d22d11Stb 	}
8662e7cce5eStb 
867f7264475Stb 	ret = 1;
868b8d22d11Stb  err:
8690edabd22Stb 	BN_CTX_end(ctx);
870b8d22d11Stb 	BN_MONT_CTX_free(mont);
8712e7cce5eStb 
872f7264475Stb 	return ret;
873b8d22d11Stb }
874b8d22d11Stb 
875b8d22d11Stb int
876b8d22d11Stb test_mod(BIO *bp, BN_CTX *ctx)
877b8d22d11Stb {
8780edabd22Stb 	BIGNUM *a, *b, *c, *d, *e;
879b8d22d11Stb 	int i;
880f7264475Stb 	int ret = 0;
881b8d22d11Stb 
8820edabd22Stb 	BN_CTX_start(ctx);
8830edabd22Stb 
8840edabd22Stb 	if ((a = BN_CTX_get(ctx)) == NULL)
885b8d22d11Stb 		goto err;
8860edabd22Stb 	if ((b = BN_CTX_get(ctx)) == NULL)
887b8d22d11Stb 		goto err;
8880edabd22Stb 	if ((c = BN_CTX_get(ctx)) == NULL)
889b8d22d11Stb 		goto err;
8900edabd22Stb 	if ((d = BN_CTX_get(ctx)) == NULL)
891b8d22d11Stb 		goto err;
8920edabd22Stb 	if ((e = BN_CTX_get(ctx)) == NULL)
893b8d22d11Stb 		goto err;
894b8d22d11Stb 
895b8d22d11Stb 	CHECK_GOTO(BN_bntest_rand(a, 1024, 0, 0));
896b8d22d11Stb 	for (i = 0; i < num0; i++) {
897b8d22d11Stb 		CHECK_GOTO(BN_bntest_rand(b, 450 + i * 10, 0, 0));
898b8d22d11Stb 		BN_set_negative(a, rand_neg());
899b8d22d11Stb 		BN_set_negative(b, rand_neg());
900b8d22d11Stb 		CHECK_GOTO(BN_mod(c, a, b, ctx));
901b8d22d11Stb 		if (bp != NULL) {
902b8d22d11Stb 			if (!results) {
903b8d22d11Stb 				CHECK_GOTO(BN_print(bp, a));
904b8d22d11Stb 				BIO_puts(bp, " % ");
905b8d22d11Stb 				CHECK_GOTO(BN_print(bp, b));
906b8d22d11Stb 				BIO_puts(bp, " - ");
907b8d22d11Stb 			}
908b8d22d11Stb 			CHECK_GOTO(BN_print(bp, c));
909b8d22d11Stb 			BIO_puts(bp, "\n");
910b8d22d11Stb 		}
911b8d22d11Stb 		CHECK_GOTO(BN_div(d, e, a, b, ctx));
912b8d22d11Stb 		CHECK_GOTO(BN_sub(e, e, c));
913b8d22d11Stb 		if (!BN_is_zero(e)) {
914b8d22d11Stb 			fprintf(stderr, "Modulo test failed!\n");
9152e7cce5eStb 			goto err;
916b8d22d11Stb 		}
917b8d22d11Stb 	}
9182e7cce5eStb 
919f7264475Stb 	ret = 1;
920b8d22d11Stb  err:
9210edabd22Stb 	BN_CTX_end(ctx);
9222e7cce5eStb 
923f7264475Stb 	return ret;
924b8d22d11Stb }
925b8d22d11Stb 
926b8d22d11Stb int
927b8d22d11Stb test_mod_mul(BIO *bp, BN_CTX *ctx)
928b8d22d11Stb {
9290edabd22Stb 	BIGNUM *a, *b, *c, *d, *e;
930b8d22d11Stb 	int i, j;
931f7264475Stb 	int ret = 0;
932b8d22d11Stb 
9330edabd22Stb 	BN_CTX_start(ctx);
9340edabd22Stb 
9350edabd22Stb 	if ((a = BN_CTX_get(ctx)) == NULL)
936b8d22d11Stb 		goto err;
9370edabd22Stb 	if ((b = BN_CTX_get(ctx)) == NULL)
938b8d22d11Stb 		goto err;
9390edabd22Stb 	if ((c = BN_CTX_get(ctx)) == NULL)
940b8d22d11Stb 		goto err;
9410edabd22Stb 	if ((d = BN_CTX_get(ctx)) == NULL)
942b8d22d11Stb 		goto err;
9430edabd22Stb 	if ((e = BN_CTX_get(ctx)) == NULL)
944b8d22d11Stb 		goto err;
945b8d22d11Stb 
946b8d22d11Stb 	CHECK_GOTO(BN_one(a));
947b8d22d11Stb 	CHECK_GOTO(BN_one(b));
94830ad135cStb 	BN_zero(c);
949b8d22d11Stb 	if (BN_mod_mul(e, a, b, c, ctx)) {
950b8d22d11Stb 		fprintf(stderr, "BN_mod_mul with zero modulus succeeded!\n");
951bb44b87cStb 		goto err;
952b8d22d11Stb 	}
9535550240dStb 	ERR_clear_error();
954b8d22d11Stb 
955b8d22d11Stb 	for (j = 0; j < 3; j++) {
956b8d22d11Stb 		CHECK_GOTO(BN_bntest_rand(c, 1024, 0, 0));
957b8d22d11Stb 		for (i = 0; i < num0; i++) {
958b8d22d11Stb 			CHECK_GOTO(BN_bntest_rand(a, 475 + i * 10, 0, 0));
959b8d22d11Stb 			CHECK_GOTO(BN_bntest_rand(b, 425 + i * 11, 0, 0));
960b8d22d11Stb 			BN_set_negative(a, rand_neg());
961b8d22d11Stb 			BN_set_negative(b, rand_neg());
962b8d22d11Stb 			if (!BN_mod_mul(e, a, b, c, ctx)) {
963b8d22d11Stb 				unsigned long l;
964b8d22d11Stb 
965b8d22d11Stb 				while ((l = ERR_get_error()))
966b8d22d11Stb 					fprintf(stderr, "ERROR:%s\n",
967b8d22d11Stb 					    ERR_error_string(l, NULL));
968b8d22d11Stb 				exit(1);
969b8d22d11Stb 			}
970b8d22d11Stb 			if (bp != NULL) {
971b8d22d11Stb 				if (!results) {
972b8d22d11Stb 					CHECK_GOTO(BN_print(bp, a));
973b8d22d11Stb 					BIO_puts(bp, " * ");
974b8d22d11Stb 					CHECK_GOTO(BN_print(bp, b));
975b8d22d11Stb 					BIO_puts(bp, " % ");
976b8d22d11Stb 					CHECK_GOTO(BN_print(bp, c));
977b8d22d11Stb 					if ((BN_is_negative(a) ^ BN_is_negative(b)) &&
978b8d22d11Stb 					    !BN_is_zero(e)) {
979b8d22d11Stb 						/* If  (a*b) % c  is negative,  c  must be added
980b8d22d11Stb 						 * in order to obtain the normalized remainder
981b8d22d11Stb 						 * (new with OpenSSL 0.9.7, previous versions of
982b8d22d11Stb 						 * BN_mod_mul could generate negative results)
983b8d22d11Stb 						 */
984b8d22d11Stb 						BIO_puts(bp, " + ");
985b8d22d11Stb 						CHECK_GOTO(BN_print(bp, c));
986b8d22d11Stb 					}
987b8d22d11Stb 					BIO_puts(bp, " - ");
988b8d22d11Stb 				}
989b8d22d11Stb 				CHECK_GOTO(BN_print(bp, e));
990b8d22d11Stb 				BIO_puts(bp, "\n");
991b8d22d11Stb 			}
992b8d22d11Stb 			CHECK_GOTO(BN_mul(d, a, b, ctx));
993b8d22d11Stb 			CHECK_GOTO(BN_sub(d, d, e));
994b8d22d11Stb 			CHECK_GOTO(BN_div(a, b, d, c, ctx));
995b8d22d11Stb 			if (!BN_is_zero(b)) {
996b8d22d11Stb 				fprintf(stderr, "Modulo multiply test failed!\n");
997b8d22d11Stb 				ERR_print_errors_fp(stderr);
998b8d22d11Stb 				goto err;
999b8d22d11Stb 			}
1000b8d22d11Stb 		}
1001b8d22d11Stb 	}
10022e7cce5eStb 
1003f7264475Stb 	ret = 1;
1004b8d22d11Stb  err:
10050edabd22Stb 	BN_CTX_end(ctx);
10062e7cce5eStb 
1007f7264475Stb 	return ret;
1008b8d22d11Stb }
1009b8d22d11Stb 
1010b8d22d11Stb int
1011b8d22d11Stb test_mod_exp(BIO *bp, BN_CTX *ctx)
1012b8d22d11Stb {
10130edabd22Stb 	BIGNUM *a, *b, *c, *d, *e;
1014b8d22d11Stb 	int i;
1015f7264475Stb 	int ret = 0;
1016b8d22d11Stb 
10170edabd22Stb 	BN_CTX_start(ctx);
10180edabd22Stb 
10190edabd22Stb 	if ((a = BN_CTX_get(ctx)) == NULL)
1020b8d22d11Stb 		goto err;
10210edabd22Stb 	if ((b = BN_CTX_get(ctx)) == NULL)
1022b8d22d11Stb 		goto err;
10230edabd22Stb 	if ((c = BN_CTX_get(ctx)) == NULL)
1024b8d22d11Stb 		goto err;
10250edabd22Stb 	if ((d = BN_CTX_get(ctx)) == NULL)
1026b8d22d11Stb 		goto err;
10270edabd22Stb 	if ((e = BN_CTX_get(ctx)) == NULL)
1028b8d22d11Stb 		goto err;
1029b8d22d11Stb 
1030b8d22d11Stb 	CHECK_GOTO(BN_one(a));
1031b8d22d11Stb 	CHECK_GOTO(BN_one(b));
103230ad135cStb 	BN_zero(c);
1033b8d22d11Stb 	if (BN_mod_exp(d, a, b, c, ctx)) {
1034b8d22d11Stb 		fprintf(stderr, "BN_mod_exp with zero modulus succeeded!\n");
1035b8d22d11Stb 		goto err;
1036b8d22d11Stb 	}
10375550240dStb 	ERR_clear_error();
1038b8d22d11Stb 	if (BN_mod_exp_ct(d, a, b, c, ctx)) {
1039b8d22d11Stb 		fprintf(stderr, "BN_mod_exp_ct with zero modulus succeeded!\n");
1040b8d22d11Stb 		goto err;
1041b8d22d11Stb 	}
10425550240dStb 	ERR_clear_error();
1043b8d22d11Stb 	if (BN_mod_exp_nonct(d, a, b, c, ctx)) {
1044b8d22d11Stb 		fprintf(stderr, "BN_mod_exp_nonct with zero modulus succeeded!\n");
1045b8d22d11Stb 		goto err;
1046b8d22d11Stb 	}
10475550240dStb 	ERR_clear_error();
1048b8d22d11Stb 
1049b8d22d11Stb 	CHECK_GOTO(BN_bntest_rand(c, 30, 0, 1)); /* must be odd for montgomery */
1050b8d22d11Stb 	for (i = 0; i < num2; i++) {
1051b8d22d11Stb 		CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0));
1052b8d22d11Stb 		CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0));
1053b8d22d11Stb 
1054457e5092Stb 		if (!BN_mod_exp(d, a, b, c, ctx))
10552e7cce5eStb 			goto err;
1056b8d22d11Stb 
1057b8d22d11Stb 		if (bp != NULL) {
1058b8d22d11Stb 			if (!results) {
1059b8d22d11Stb 				CHECK_GOTO(BN_print(bp, a));
1060b8d22d11Stb 				BIO_puts(bp, " ^ ");
1061b8d22d11Stb 				CHECK_GOTO(BN_print(bp, b));
1062b8d22d11Stb 				BIO_puts(bp, " % ");
1063b8d22d11Stb 				CHECK_GOTO(BN_print(bp, c));
1064b8d22d11Stb 				BIO_puts(bp, " - ");
1065b8d22d11Stb 			}
1066b8d22d11Stb 			CHECK_GOTO(BN_print(bp, d));
1067b8d22d11Stb 			BIO_puts(bp, "\n");
1068b8d22d11Stb 		}
1069b8d22d11Stb 		CHECK_GOTO(BN_exp(e, a, b, ctx));
1070b8d22d11Stb 		CHECK_GOTO(BN_sub(e, e, d));
1071b8d22d11Stb 		CHECK_GOTO(BN_div(a, b, e, c, ctx));
1072b8d22d11Stb 		if (!BN_is_zero(b)) {
1073b8d22d11Stb 			fprintf(stderr, "Modulo exponentiation test failed!\n");
10742e7cce5eStb 			goto err;
1075b8d22d11Stb 		}
1076b8d22d11Stb 	}
1077b8d22d11Stb 
1078b8d22d11Stb 	CHECK_GOTO(BN_bntest_rand(c, 30, 0, 1)); /* must be odd for montgomery */
1079b8d22d11Stb 	for (i = 0; i < num2; i++) {
1080b8d22d11Stb 		CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0));
1081b8d22d11Stb 		CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0));
1082b8d22d11Stb 
1083457e5092Stb 		if (!BN_mod_exp_ct(d, a, b, c, ctx))
10842e7cce5eStb 			goto err;
1085b8d22d11Stb 
1086b8d22d11Stb 		if (bp != NULL) {
1087b8d22d11Stb 			if (!results) {
1088b8d22d11Stb 				CHECK_GOTO(BN_print(bp, a));
1089b8d22d11Stb 				BIO_puts(bp, " ^ ");
1090b8d22d11Stb 				CHECK_GOTO(BN_print(bp, b));
1091b8d22d11Stb 				BIO_puts(bp, " % ");
1092b8d22d11Stb 				CHECK_GOTO(BN_print(bp, c));
1093b8d22d11Stb 				BIO_puts(bp, " - ");
1094b8d22d11Stb 			}
1095b8d22d11Stb 			CHECK_GOTO(BN_print(bp, d));
1096b8d22d11Stb 			BIO_puts(bp, "\n");
1097b8d22d11Stb 		}
1098b8d22d11Stb 		CHECK_GOTO(BN_exp(e, a, b, ctx));
1099b8d22d11Stb 		CHECK_GOTO(BN_sub(e, e, d));
1100b8d22d11Stb 		CHECK_GOTO(BN_div(a, b, e, c, ctx));
1101b8d22d11Stb 		if (!BN_is_zero(b)) {
1102b8d22d11Stb 			fprintf(stderr, "Modulo exponentiation test failed!\n");
11032e7cce5eStb 			goto err;
1104b8d22d11Stb 		}
1105b8d22d11Stb 	}
1106b8d22d11Stb 
1107b8d22d11Stb 	CHECK_GOTO(BN_bntest_rand(c, 30, 0, 1)); /* must be odd for montgomery */
1108b8d22d11Stb 	for (i = 0; i < num2; i++) {
1109b8d22d11Stb 		CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0));
1110b8d22d11Stb 		CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0));
1111b8d22d11Stb 
1112457e5092Stb 		if (!BN_mod_exp_nonct(d, a, b, c, ctx))
11132e7cce5eStb 			goto err;
1114b8d22d11Stb 
1115b8d22d11Stb 		if (bp != NULL) {
1116b8d22d11Stb 			if (!results) {
1117b8d22d11Stb 				CHECK_GOTO(BN_print(bp, a));
1118b8d22d11Stb 				BIO_puts(bp, " ^ ");
1119b8d22d11Stb 				CHECK_GOTO(BN_print(bp, b));
1120b8d22d11Stb 				BIO_puts(bp, " % ");
1121b8d22d11Stb 				CHECK_GOTO(BN_print(bp, c));
1122b8d22d11Stb 				BIO_puts(bp, " - ");
1123b8d22d11Stb 			}
1124b8d22d11Stb 			CHECK_GOTO(BN_print(bp, d));
1125b8d22d11Stb 			BIO_puts(bp, "\n");
1126b8d22d11Stb 		}
1127b8d22d11Stb 		CHECK_GOTO(BN_exp(e, a, b, ctx));
1128b8d22d11Stb 		CHECK_GOTO(BN_sub(e, e, d));
1129b8d22d11Stb 		CHECK_GOTO(BN_div(a, b, e, c, ctx));
1130b8d22d11Stb 		if (!BN_is_zero(b)) {
1131b8d22d11Stb 			fprintf(stderr, "Modulo exponentiation test failed!\n");
11322e7cce5eStb 			goto err;
1133b8d22d11Stb 		}
1134b8d22d11Stb 	}
11352e7cce5eStb 
1136f7264475Stb 	ret = 1;
1137b8d22d11Stb  err:
11380edabd22Stb 	BN_CTX_end(ctx);
11392e7cce5eStb 
1140f7264475Stb 	return ret;
1141b8d22d11Stb }
1142b8d22d11Stb 
1143b8d22d11Stb int
1144b8d22d11Stb test_mod_exp_mont_consttime(BIO *bp, BN_CTX *ctx)
1145b8d22d11Stb {
11460edabd22Stb 	BIGNUM *a, *b, *c, *d, *e;
1147b8d22d11Stb 	int i;
1148f7264475Stb 	int ret = 0;
1149b8d22d11Stb 
11500edabd22Stb 	BN_CTX_start(ctx);
11510edabd22Stb 
11520edabd22Stb 	if ((a = BN_CTX_get(ctx)) == NULL)
1153b8d22d11Stb 		goto err;
11540edabd22Stb 	if ((b = BN_CTX_get(ctx)) == NULL)
1155b8d22d11Stb 		goto err;
11560edabd22Stb 	if ((c = BN_CTX_get(ctx)) == NULL)
1157b8d22d11Stb 		goto err;
11580edabd22Stb 	if ((d = BN_CTX_get(ctx)) == NULL)
1159b8d22d11Stb 		goto err;
11600edabd22Stb 	if ((e = BN_CTX_get(ctx)) == NULL)
1161b8d22d11Stb 		goto err;
1162b8d22d11Stb 
1163b8d22d11Stb 	CHECK_GOTO(BN_one(a));
1164b8d22d11Stb 	CHECK_GOTO(BN_one(b));
116530ad135cStb 	BN_zero(c);
1166b8d22d11Stb 	if (BN_mod_exp_mont_consttime(d, a, b, c, ctx, NULL)) {
1167b8d22d11Stb 		fprintf(stderr, "BN_mod_exp_mont_consttime with zero modulus "
1168b8d22d11Stb 				"succeeded\n");
1169b8d22d11Stb 		goto err;
1170b8d22d11Stb 	}
11715550240dStb 	ERR_clear_error();
1172b8d22d11Stb 
1173b8d22d11Stb 	CHECK_GOTO(BN_set_word(c, 16));
1174b8d22d11Stb 	if (BN_mod_exp_mont_consttime(d, a, b, c, ctx, NULL)) {
1175b8d22d11Stb 		fprintf(stderr, "BN_mod_exp_mont_consttime with even modulus "
1176b8d22d11Stb 				"succeeded\n");
1177b8d22d11Stb 		goto err;
1178b8d22d11Stb 	}
11795550240dStb 	ERR_clear_error();
1180b8d22d11Stb 
1181b8d22d11Stb 	CHECK_GOTO(BN_bntest_rand(c, 30, 0, 1)); /* must be odd for montgomery */
1182b8d22d11Stb 	for (i = 0; i < num2; i++) {
1183b8d22d11Stb 		CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0));
1184b8d22d11Stb 		CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0));
1185b8d22d11Stb 
1186457e5092Stb 		if (!BN_mod_exp_mont_consttime(d, a, b, c, ctx, NULL))
11872e7cce5eStb 			goto err;
1188b8d22d11Stb 
1189b8d22d11Stb 		if (bp != NULL) {
1190b8d22d11Stb 			if (!results) {
1191b8d22d11Stb 				CHECK_GOTO(BN_print(bp, a));
1192b8d22d11Stb 				BIO_puts(bp, " ^ ");
1193b8d22d11Stb 				CHECK_GOTO(BN_print(bp, b));
1194b8d22d11Stb 				BIO_puts(bp, " % ");
1195b8d22d11Stb 				CHECK_GOTO(BN_print(bp, c));
1196b8d22d11Stb 				BIO_puts(bp, " - ");
1197b8d22d11Stb 			}
1198b8d22d11Stb 			CHECK_GOTO(BN_print(bp, d));
1199b8d22d11Stb 			BIO_puts(bp, "\n");
1200b8d22d11Stb 		}
1201b8d22d11Stb 		CHECK_GOTO(BN_exp(e, a, b, ctx));
1202b8d22d11Stb 		CHECK_GOTO(BN_sub(e, e, d));
1203b8d22d11Stb 		CHECK_GOTO(BN_div(a, b, e, c, ctx));
1204b8d22d11Stb 		if (!BN_is_zero(b)) {
1205b8d22d11Stb 			fprintf(stderr, "Modulo exponentiation test failed!\n");
12062e7cce5eStb 			goto err;
1207b8d22d11Stb 		}
1208b8d22d11Stb 	}
12092e7cce5eStb 
1210f7264475Stb 	ret = 1;
1211b8d22d11Stb  err:
12120edabd22Stb 	BN_CTX_end(ctx);
12132e7cce5eStb 
1214f7264475Stb 	return ret;
1215b8d22d11Stb }
1216b8d22d11Stb 
1217b8d22d11Stb /*
1218b8d22d11Stb  * Test constant-time modular exponentiation with 1024-bit inputs, which on
1219b8d22d11Stb  * x86_64 cause a different code branch to be taken.
1220b8d22d11Stb  */
1221b8d22d11Stb int
1222b8d22d11Stb test_mod_exp_mont5(BIO *bp, BN_CTX *ctx)
1223b8d22d11Stb {
12240edabd22Stb 	BIGNUM *a, *p, *m, *d, *e;
12250edabd22Stb 	BIGNUM *b, *n, *c;
1226b8d22d11Stb 	BN_MONT_CTX *mont = NULL;
1227b8d22d11Stb 	int len;
1228f7264475Stb 	int ret = 0;
1229b8d22d11Stb 
12300edabd22Stb 	BN_CTX_start(ctx);
12310edabd22Stb 
12320edabd22Stb 	if ((a = BN_CTX_get(ctx)) == NULL)
1233b8d22d11Stb 		goto err;
12340edabd22Stb 	if ((p = BN_CTX_get(ctx)) == NULL)
1235b8d22d11Stb 		goto err;
12360edabd22Stb 	if ((m = BN_CTX_get(ctx)) == NULL)
1237b8d22d11Stb 		goto err;
12380edabd22Stb 	if ((d = BN_CTX_get(ctx)) == NULL)
1239b8d22d11Stb 		goto err;
12400edabd22Stb 	if ((e = BN_CTX_get(ctx)) == NULL)
1241b8d22d11Stb 		goto err;
12420edabd22Stb 	if ((b = BN_CTX_get(ctx)) == NULL)
1243b8d22d11Stb 		goto err;
12440edabd22Stb 	if ((n = BN_CTX_get(ctx)) == NULL)
1245b8d22d11Stb 		goto err;
12460edabd22Stb 	if ((c = BN_CTX_get(ctx)) == NULL)
1247b8d22d11Stb 		goto err;
1248b8d22d11Stb 
1249b8d22d11Stb 	CHECK_GOTO(mont = BN_MONT_CTX_new());
1250b8d22d11Stb 
1251b8d22d11Stb 	CHECK_GOTO(BN_bntest_rand(m, 1024, 0, 1)); /* must be odd for montgomery */
1252b8d22d11Stb 	/* Zero exponent */
1253b8d22d11Stb 	CHECK_GOTO(BN_bntest_rand(a, 1024, 0, 0));
125430ad135cStb 	BN_zero(p);
1255457e5092Stb 	if (!BN_mod_exp_mont_consttime(d, a, p, m, ctx, NULL))
1256b8d22d11Stb 		goto err;
1257b8d22d11Stb 	if (!BN_is_one(d)) {
1258b8d22d11Stb 		fprintf(stderr, "Modular exponentiation test failed!\n");
1259b8d22d11Stb 		goto err;
1260b8d22d11Stb 	}
1261b8d22d11Stb 	/* Regression test for carry bug in mulx4x_mont */
1262b8d22d11Stb 	len = BN_hex2bn(&a,
1263b8d22d11Stb 	    "7878787878787878787878787878787878787878787878787878787878787878"
1264b8d22d11Stb 	    "7878787878787878787878787878787878787878787878787878787878787878"
1265b8d22d11Stb 	    "7878787878787878787878787878787878787878787878787878787878787878"
1266b8d22d11Stb 	    "7878787878787878787878787878787878787878787878787878787878787878");
1267b8d22d11Stb 	CHECK_GOTO(len);
1268b8d22d11Stb 	len = BN_hex2bn(&b,
1269b8d22d11Stb 	    "095D72C08C097BA488C5E439C655A192EAFB6380073D8C2664668EDDB4060744"
1270b8d22d11Stb 	    "E16E57FB4EDB9AE10A0CEFCDC28A894F689A128379DB279D48A2E20849D68593"
1271b8d22d11Stb 	    "9B7803BCF46CEBF5C533FB0DD35B080593DE5472E3FE5DB951B8BFF9B4CB8F03"
1272b8d22d11Stb 	    "9CC638A5EE8CDD703719F8000E6A9F63BEED5F2FCD52FF293EA05A251BB4AB81");
1273b8d22d11Stb 	CHECK_GOTO(len);
1274b8d22d11Stb 	len = BN_hex2bn(&n,
1275b8d22d11Stb 	    "D78AF684E71DB0C39CFF4E64FB9DB567132CB9C50CC98009FEB820B26F2DED9B"
1276b8d22d11Stb 	    "91B9B5E2B83AE0AE4EB4E0523CA726BFBE969B89FD754F674CE99118C3F2D1C5"
1277b8d22d11Stb 	    "D81FDC7C54E02B60262B241D53C040E99E45826ECA37A804668E690E1AFC1CA4"
1278b8d22d11Stb 	    "2C9A15D84D4954425F0B7642FC0BD9D7B24E2618D2DCC9B729D944BADACFDDAF");
1279b8d22d11Stb 	CHECK_GOTO(len);
1280b8d22d11Stb 	CHECK_GOTO(BN_MONT_CTX_set(mont, n, ctx));
1281b8d22d11Stb 	CHECK_GOTO(BN_mod_mul_montgomery(c, a, b, mont, ctx));
1282b8d22d11Stb 	CHECK_GOTO(BN_mod_mul_montgomery(d, b, a, mont, ctx));
1283b8d22d11Stb 	if (BN_cmp(c, d)) {
1284b8d22d11Stb 		fprintf(stderr, "Montgomery multiplication test failed:"
1285b8d22d11Stb 		    " a*b != b*a.\n");
1286b8d22d11Stb 		goto err;
1287b8d22d11Stb 	}
1288b8d22d11Stb 	/* Regression test for carry bug in sqr[x]8x_mont */
1289b8d22d11Stb 	len = BN_hex2bn(&n,
1290b8d22d11Stb 	    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
1291b8d22d11Stb 	    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
1292b8d22d11Stb 	    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
1293b8d22d11Stb 	    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
1294b8d22d11Stb 	    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
1295b8d22d11Stb 	    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
1296b8d22d11Stb 	    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
1297b8d22d11Stb 	    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000FFFFFFFF00"
1298b8d22d11Stb 	    "0000000000000000000000000000000000000000000000000000000000000000"
1299b8d22d11Stb 	    "0000000000000000000000000000000000000000000000000000000000000000"
1300b8d22d11Stb 	    "0000000000000000000000000000000000000000000000000000000000000000"
1301b8d22d11Stb 	    "0000000000000000000000000000000000000000000000000000000000000000"
1302b8d22d11Stb 	    "0000000000000000000000000000000000000000000000000000000000000000"
1303b8d22d11Stb 	    "0000000000000000000000000000000000000000000000000000000000000000"
1304b8d22d11Stb 	    "0000000000000000000000000000000000000000000000000000000000000000"
1305b8d22d11Stb 	    "00000000000000000000000000000000000000000000000000FFFFFFFFFFFFFF");
1306b8d22d11Stb 	CHECK_GOTO(len);
1307b8d22d11Stb 	len = BN_hex2bn(&a,
1308b8d22d11Stb 	    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
1309b8d22d11Stb 	    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
1310b8d22d11Stb 	    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
1311b8d22d11Stb 	    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
1312b8d22d11Stb 	    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
1313b8d22d11Stb 	    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
1314b8d22d11Stb 	    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
1315b8d22d11Stb 	    "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000FFFFFFFF0000000000"
1316b8d22d11Stb 	    "0000000000000000000000000000000000000000000000000000000000000000"
1317b8d22d11Stb 	    "0000000000000000000000000000000000000000000000000000000000000000"
1318b8d22d11Stb 	    "0000000000000000000000000000000000000000000000000000000000000000"
1319b8d22d11Stb 	    "0000000000000000000000000000000000000000000000000000000000000000"
1320b8d22d11Stb 	    "0000000000000000000000000000000000000000000000000000000000000000"
1321b8d22d11Stb 	    "0000000000000000000000000000000000000000000000000000000000000000"
1322b8d22d11Stb 	    "0000000000000000000000000000000000000000000000000000000000000000"
1323b8d22d11Stb 	    "000000000000000000000000000000000000000000FFFFFFFFFFFFFF00000000");
1324b8d22d11Stb 	CHECK_GOTO(len);
132580ef34bcStb 	CHECK_GOTO(bn_copy(b, a));
1326b8d22d11Stb 	CHECK_GOTO(BN_MONT_CTX_set(mont, n, ctx));
1327b8d22d11Stb 	CHECK_GOTO(BN_mod_mul_montgomery(c, a, a, mont, ctx));
1328b8d22d11Stb 	CHECK_GOTO(BN_mod_mul_montgomery(d, a, b, mont, ctx));
1329b8d22d11Stb 	if (BN_cmp(c, d)) {
1330b8d22d11Stb 		fprintf(stderr, "Montgomery multiplication test failed:"
1331b8d22d11Stb 		    " a**2 != a*a.\n");
1332b8d22d11Stb 		goto err;
1333b8d22d11Stb 	}
1334b8d22d11Stb 	/* Zero input */
1335b8d22d11Stb 	CHECK_GOTO(BN_bntest_rand(p, 1024, 0, 0));
133630ad135cStb 	BN_zero(a);
1337457e5092Stb 	if (!BN_mod_exp_mont_consttime(d, a, p, m, ctx, NULL))
1338b8d22d11Stb 		goto err;
1339b8d22d11Stb 	if (!BN_is_zero(d)) {
1340b8d22d11Stb 		fprintf(stderr, "Modular exponentiation test failed!\n");
1341b8d22d11Stb 		goto err;
1342b8d22d11Stb 	}
1343b8d22d11Stb 	/*
1344b8d22d11Stb 	 * Craft an input whose Montgomery representation is 1, i.e., shorter
1345b8d22d11Stb 	 * than the modulus m, in order to test the const time precomputation
1346b8d22d11Stb 	 * scattering/gathering.
1347b8d22d11Stb 	 */
1348b8d22d11Stb 	CHECK_GOTO(BN_one(a));
1349b8d22d11Stb 	CHECK_GOTO(BN_MONT_CTX_set(mont, m, ctx));
1350457e5092Stb 	if (!BN_from_montgomery(e, a, mont, ctx))
1351b8d22d11Stb 		goto err;
1352457e5092Stb 	if (!BN_mod_exp_mont_consttime(d, e, p, m, ctx, NULL))
1353b8d22d11Stb 		goto err;
1354457e5092Stb 	if (!BN_mod_exp_simple(a, e, p, m, ctx))
1355b8d22d11Stb 		goto err;
1356b8d22d11Stb 	if (BN_cmp(a, d) != 0) {
1357b8d22d11Stb 		fprintf(stderr, "Modular exponentiation test failed!\n");
1358b8d22d11Stb 		goto err;
1359b8d22d11Stb 	}
1360b8d22d11Stb 	/* Finally, some regular test vectors. */
1361b8d22d11Stb 	CHECK_GOTO(BN_bntest_rand(e, 1024, 0, 0));
1362457e5092Stb 	if (!BN_mod_exp_mont_consttime(d, e, p, m, ctx, NULL))
1363b8d22d11Stb 		goto err;
1364457e5092Stb 	if (!BN_mod_exp_simple(a, e, p, m, ctx))
1365b8d22d11Stb 		goto err;
1366b8d22d11Stb 	if (BN_cmp(a, d) != 0) {
1367b8d22d11Stb 		fprintf(stderr, "Modular exponentiation test failed!\n");
1368b8d22d11Stb 		goto err;
1369b8d22d11Stb 	}
13702e7cce5eStb 
1371f7264475Stb 	ret = 1;
1372b8d22d11Stb  err:
13730edabd22Stb 	BN_CTX_end(ctx);
1374b8d22d11Stb 	BN_MONT_CTX_free(mont);
13752e7cce5eStb 
1376f7264475Stb 	return ret;
1377b8d22d11Stb }
1378b8d22d11Stb 
1379b8d22d11Stb int
1380b8d22d11Stb test_exp(BIO *bp, BN_CTX *ctx)
1381b8d22d11Stb {
13820edabd22Stb 	BIGNUM *a, *b, *d, *e;
1383b8d22d11Stb 	int i;
1384f7264475Stb 	int ret = 0;
1385b8d22d11Stb 
13860edabd22Stb 	BN_CTX_start(ctx);
13870edabd22Stb 
13880edabd22Stb 	if ((a = BN_CTX_get(ctx)) == NULL)
1389b8d22d11Stb 		goto err;
13900edabd22Stb 	if ((b = BN_CTX_get(ctx)) == NULL)
1391b8d22d11Stb 		goto err;
13920edabd22Stb 	if ((d = BN_CTX_get(ctx)) == NULL)
1393b8d22d11Stb 		goto err;
13940edabd22Stb 	if ((e = BN_CTX_get(ctx)) == NULL)
1395b8d22d11Stb 		goto err;
1396b8d22d11Stb 
1397b8d22d11Stb 	for (i = 0; i < num2; i++) {
1398b8d22d11Stb 		CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0));
1399b8d22d11Stb 		CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0));
1400b8d22d11Stb 
1401457e5092Stb 		if (BN_exp(d, a, b, ctx) <= 0)
14022e7cce5eStb 			goto err;
1403b8d22d11Stb 
1404b8d22d11Stb 		if (bp != NULL) {
1405b8d22d11Stb 			if (!results) {
1406b8d22d11Stb 				CHECK_GOTO(BN_print(bp, a));
1407b8d22d11Stb 				BIO_puts(bp, " ^ ");
1408b8d22d11Stb 				CHECK_GOTO(BN_print(bp, b));
1409b8d22d11Stb 				BIO_puts(bp, " - ");
1410b8d22d11Stb 			}
1411b8d22d11Stb 			CHECK_GOTO(BN_print(bp, d));
1412b8d22d11Stb 			BIO_puts(bp, "\n");
1413b8d22d11Stb 		}
1414b8d22d11Stb 		CHECK_GOTO(BN_one(e));
14150edabd22Stb 		for (; !BN_is_zero(b); BN_sub_word(b, 1))
1416b8d22d11Stb 			CHECK_GOTO(BN_mul(e, e, a, ctx));
1417b8d22d11Stb 		CHECK_GOTO(BN_sub(e, e, d));
1418b8d22d11Stb 		if (!BN_is_zero(e)) {
1419b8d22d11Stb 			fprintf(stderr, "Exponentiation test failed!\n");
14202e7cce5eStb 			goto err;
1421b8d22d11Stb 		}
1422b8d22d11Stb 	}
14232e7cce5eStb 
1424f7264475Stb 	ret = 1;
1425b8d22d11Stb  err:
14260edabd22Stb 	BN_CTX_end(ctx);
14272e7cce5eStb 
1428f7264475Stb 	return ret;
1429b8d22d11Stb }
1430b8d22d11Stb 
1431b8d22d11Stb static int
1432b8d22d11Stb genprime_cb(int p, int n, BN_GENCB *arg)
1433b8d22d11Stb {
1434b8d22d11Stb 	char c = '*';
1435b8d22d11Stb 
1436b8d22d11Stb 	if (p == 0)
1437b8d22d11Stb 		c = '.';
1438b8d22d11Stb 	if (p == 1)
1439b8d22d11Stb 		c = '+';
1440b8d22d11Stb 	if (p == 2)
1441b8d22d11Stb 		c = '*';
1442b8d22d11Stb 	if (p == 3)
1443b8d22d11Stb 		c = '\n';
1444b8d22d11Stb 	putc(c, stderr);
14452e7cce5eStb 	return 1;
1446b8d22d11Stb }
1447b8d22d11Stb 
1448b8d22d11Stb int
1449b8d22d11Stb test_kron(BIO *bp, BN_CTX *ctx)
1450b8d22d11Stb {
14510edabd22Stb 	BIGNUM *a, *b, *r, *t;
1452b8d22d11Stb 	BN_GENCB *cb = NULL;
1453b8d22d11Stb 	int i;
1454b8d22d11Stb 	int legendre, kronecker;
1455f7264475Stb 	int ret = 0;
1456b8d22d11Stb 
14570edabd22Stb 	BN_CTX_start(ctx);
14580edabd22Stb 
14590edabd22Stb 	if ((a = BN_CTX_get(ctx)) == NULL)
1460b8d22d11Stb 		goto err;
14610edabd22Stb 	if ((b = BN_CTX_get(ctx)) == NULL)
1462b8d22d11Stb 		goto err;
14630edabd22Stb 	if ((r = BN_CTX_get(ctx)) == NULL)
1464b8d22d11Stb 		goto err;
14650edabd22Stb 	if ((t = BN_CTX_get(ctx)) == NULL)
1466b8d22d11Stb 		goto err;
1467b8d22d11Stb 
1468b8d22d11Stb 	if ((cb = BN_GENCB_new()) == NULL)
1469b8d22d11Stb 		goto err;
1470b8d22d11Stb 
1471b8d22d11Stb 	BN_GENCB_set(cb, genprime_cb, NULL);
1472b8d22d11Stb 
1473b8d22d11Stb 	/*
1474b8d22d11Stb 	 * We test BN_kronecker(a, b, ctx) just for b odd (Jacobi symbol). In
1475b8d22d11Stb 	 * this case we know that if b is prime, then BN_kronecker(a, b, ctx) is
1476b8d22d11Stb 	 * congruent to $a^{(b-1)/2}$, modulo $b$ (Legendre symbol). So we
1477b8d22d11Stb 	 * generate a random prime b and compare these values for a number of
1478b8d22d11Stb 	 * random a's.  (That is, we run the Solovay-Strassen primality test to
1479b8d22d11Stb 	 * confirm that b is prime, except that we don't want to test whether b
1480b8d22d11Stb 	 * is prime but whether BN_kronecker works.)
1481b8d22d11Stb 	 */
1482b8d22d11Stb 
1483b8d22d11Stb 	if (!BN_generate_prime_ex(b, 512, 0, NULL, NULL, cb))
1484b8d22d11Stb 		goto err;
1485b8d22d11Stb 	BN_set_negative(b, rand_neg());
1486b8d22d11Stb 	putc('\n', stderr);
1487b8d22d11Stb 
1488b8d22d11Stb 	for (i = 0; i < num0; i++) {
1489b8d22d11Stb 		if (!BN_bntest_rand(a, 512, 0, 0))
1490b8d22d11Stb 			goto err;
1491b8d22d11Stb 		BN_set_negative(a, rand_neg());
1492b8d22d11Stb 
1493b8d22d11Stb 		/* t := (|b|-1)/2  (note that b is odd) */
14948e84e241Stb 		if (!bn_copy(t, b))
1495b8d22d11Stb 			goto err;
1496b8d22d11Stb 		BN_set_negative(t, 0);
1497b8d22d11Stb 		if (!BN_sub_word(t, 1))
1498b8d22d11Stb 			goto err;
1499b8d22d11Stb 		if (!BN_rshift1(t, t))
1500b8d22d11Stb 			goto err;
1501b8d22d11Stb 		/* r := a^t mod b */
1502b8d22d11Stb 		BN_set_negative(b, 0);
1503b8d22d11Stb 
1504b8d22d11Stb 		if (!BN_mod_exp_recp(r, a, t, b, ctx))
1505b8d22d11Stb 			goto err;
1506b8d22d11Stb 		BN_set_negative(b, 1);
1507b8d22d11Stb 
1508b8d22d11Stb 		if (BN_is_word(r, 1))
1509b8d22d11Stb 			legendre = 1;
1510b8d22d11Stb 		else if (BN_is_zero(r))
1511b8d22d11Stb 			legendre = 0;
1512b8d22d11Stb 		else {
1513b8d22d11Stb 			if (!BN_add_word(r, 1))
1514b8d22d11Stb 				goto err;
1515b8d22d11Stb 			if (0 != BN_ucmp(r, b)) {
1516b8d22d11Stb 				fprintf(stderr, "Legendre symbol computation failed\n");
1517b8d22d11Stb 				goto err;
1518b8d22d11Stb 			}
1519b8d22d11Stb 			legendre = -1;
1520b8d22d11Stb 		}
1521b8d22d11Stb 
1522b8d22d11Stb 		kronecker = BN_kronecker(a, b, ctx);
1523b8d22d11Stb 		if (kronecker < -1)
1524b8d22d11Stb 			goto err;
1525b8d22d11Stb 		/* we actually need BN_kronecker(a, |b|) */
1526b8d22d11Stb 		if (BN_is_negative(a) && BN_is_negative(b))
1527b8d22d11Stb 			kronecker = -kronecker;
1528b8d22d11Stb 
1529b8d22d11Stb 		if (legendre != kronecker) {
1530b8d22d11Stb 			fprintf(stderr, "legendre != kronecker; a = ");
1531b8d22d11Stb 			CHECK_GOTO(BN_print_fp(stderr, a));
1532b8d22d11Stb 			fprintf(stderr, ", b = ");
1533b8d22d11Stb 			CHECK_GOTO(BN_print_fp(stderr, b));
1534b8d22d11Stb 			fprintf(stderr, "\n");
1535b8d22d11Stb 			goto err;
1536b8d22d11Stb 		}
1537b8d22d11Stb 
1538b8d22d11Stb 		putc('.', stderr);
1539b8d22d11Stb 	}
1540b8d22d11Stb 
1541b8d22d11Stb 	putc('\n', stderr);
1542b8d22d11Stb 
1543f7264475Stb 	ret = 1;
1544b8d22d11Stb  err:
1545b8d22d11Stb 	BN_GENCB_free(cb);
15460edabd22Stb 	BN_CTX_end(ctx);
15472e7cce5eStb 
1548f7264475Stb 	return ret;
1549b8d22d11Stb }
1550b8d22d11Stb 
1551b8d22d11Stb int
1552b8d22d11Stb test_sqrt(BIO *bp, BN_CTX *ctx)
1553b8d22d11Stb {
15540edabd22Stb 	BIGNUM *a, *p, *r;
1555b8d22d11Stb 	BN_GENCB *cb = NULL;
1556b8d22d11Stb 	int i, j;
1557f7264475Stb 	int ret = 0;
1558b8d22d11Stb 
15590edabd22Stb 	BN_CTX_start(ctx);
15600edabd22Stb 
15610edabd22Stb 	if ((a = BN_CTX_get(ctx)) == NULL)
1562b8d22d11Stb 		goto err;
15630edabd22Stb 	if ((p = BN_CTX_get(ctx)) == NULL)
1564b8d22d11Stb 		goto err;
15650edabd22Stb 	if ((r = BN_CTX_get(ctx)) == NULL)
1566b8d22d11Stb 		goto err;
1567b8d22d11Stb 
1568b8d22d11Stb 	if ((cb = BN_GENCB_new()) == NULL)
1569b8d22d11Stb 		goto err;
1570b8d22d11Stb 
1571b8d22d11Stb 	BN_GENCB_set(cb, genprime_cb, NULL);
1572b8d22d11Stb 
1573b8d22d11Stb 	for (i = 0; i < 16; i++) {
1574b8d22d11Stb 		if (i < 8) {
1575b8d22d11Stb 			unsigned primes[8] = { 2, 3, 5, 7, 11, 13, 17, 19 };
1576b8d22d11Stb 
1577b8d22d11Stb 			if (!BN_set_word(p, primes[i]))
1578b8d22d11Stb 				goto err;
1579b8d22d11Stb 		} else {
1580b8d22d11Stb 			if (!BN_set_word(a, 32))
1581b8d22d11Stb 				goto err;
1582b8d22d11Stb 			if (!BN_set_word(r, 2 * i + 1))
1583b8d22d11Stb 				goto err;
1584b8d22d11Stb 
1585b8d22d11Stb 			if (!BN_generate_prime_ex(p, 256, 0, a, r, cb))
1586b8d22d11Stb 				goto err;
1587b8d22d11Stb 			putc('\n', stderr);
1588b8d22d11Stb 		}
1589b8d22d11Stb 		BN_set_negative(p, rand_neg());
1590b8d22d11Stb 
1591b8d22d11Stb 		for (j = 0; j < num2; j++) {
1592b8d22d11Stb 			/*
1593b8d22d11Stb 			 * construct 'a' such that it is a square modulo p, but in
1594b8d22d11Stb 			 * general not a proper square and not reduced modulo p
1595b8d22d11Stb 			 */
1596b8d22d11Stb 			if (!BN_bntest_rand(r, 256, 0, 3))
1597b8d22d11Stb 				goto err;
1598b8d22d11Stb 			if (!BN_nnmod(r, r, p, ctx))
1599b8d22d11Stb 				goto err;
1600b8d22d11Stb 			if (!BN_mod_sqr(r, r, p, ctx))
1601b8d22d11Stb 				goto err;
1602b8d22d11Stb 			if (!BN_bntest_rand(a, 256, 0, 3))
1603b8d22d11Stb 				goto err;
1604b8d22d11Stb 			if (!BN_nnmod(a, a, p, ctx))
1605b8d22d11Stb 				goto err;
1606b8d22d11Stb 			if (!BN_mod_sqr(a, a, p, ctx))
1607b8d22d11Stb 				goto err;
1608b8d22d11Stb 			if (!BN_mul(a, a, r, ctx))
1609b8d22d11Stb 				goto err;
1610b8d22d11Stb 			if (rand_neg())
1611b8d22d11Stb 				if (!BN_sub(a, a, p))
1612b8d22d11Stb 					goto err;
1613b8d22d11Stb 
1614b8d22d11Stb 			if (!BN_mod_sqrt(r, a, p, ctx))
1615b8d22d11Stb 				goto err;
1616b8d22d11Stb 			if (!BN_mod_sqr(r, r, p, ctx))
1617b8d22d11Stb 				goto err;
1618b8d22d11Stb 
1619b8d22d11Stb 			if (!BN_nnmod(a, a, p, ctx))
1620b8d22d11Stb 				goto err;
1621b8d22d11Stb 
1622b8d22d11Stb 			if (BN_cmp(a, r) != 0) {
1623b8d22d11Stb 				fprintf(stderr, "BN_mod_sqrt failed: a = ");
1624b8d22d11Stb 				CHECK_GOTO(BN_print_fp(stderr, a));
1625b8d22d11Stb 				fprintf(stderr, ", r = ");
1626b8d22d11Stb 				CHECK_GOTO(BN_print_fp(stderr, r));
1627b8d22d11Stb 				fprintf(stderr, ", p = ");
1628b8d22d11Stb 				CHECK_GOTO(BN_print_fp(stderr, p));
1629b8d22d11Stb 				fprintf(stderr, "\n");
1630b8d22d11Stb 				goto err;
1631b8d22d11Stb 			}
1632b8d22d11Stb 
1633b8d22d11Stb 			putc('.', stderr);
1634b8d22d11Stb 		}
1635b8d22d11Stb 
1636b8d22d11Stb 		putc('\n', stderr);
1637b8d22d11Stb 	}
1638b8d22d11Stb 
1639f7264475Stb 	ret = 1;
1640b8d22d11Stb  err:
1641b8d22d11Stb 	BN_GENCB_free(cb);
16420edabd22Stb 	BN_CTX_end(ctx);
16432e7cce5eStb 
1644f7264475Stb 	return ret;
1645b8d22d11Stb }
1646b8d22d11Stb 
1647b8d22d11Stb int
16484bbad1a5Stb test_lshift(BIO *bp, BN_CTX *ctx, int use_lst)
1649b8d22d11Stb {
16500edabd22Stb 	BIGNUM *a, *b, *c, *d;
1651b8d22d11Stb 	int i;
1652f7264475Stb 	int ret = 0;
1653b8d22d11Stb 
16540edabd22Stb 	BN_CTX_start(ctx);
16550edabd22Stb 
16560edabd22Stb 	if ((a = BN_CTX_get(ctx)) == NULL)
16574bbad1a5Stb 		goto err;
16580edabd22Stb 	if ((b = BN_CTX_get(ctx)) == NULL)
1659b8d22d11Stb 		goto err;
16600edabd22Stb 	if ((c = BN_CTX_get(ctx)) == NULL)
1661b8d22d11Stb 		goto err;
16620edabd22Stb 	if ((d = BN_CTX_get(ctx)) == NULL)
1663b8d22d11Stb 		goto err;
1664b8d22d11Stb 	CHECK_GOTO(BN_one(c));
1665b8d22d11Stb 
16664bbad1a5Stb 	if (use_lst) {
16674bbad1a5Stb 		if (!BN_hex2bn(&a, "C64F43042AEACA6E5836805BE8C99B04"
16684bbad1a5Stb 		    "5D4836C2FD16C964F0"))
1669b8d22d11Stb 			goto err;
16704bbad1a5Stb 	} else {
1671b8d22d11Stb 		CHECK_GOTO(BN_bntest_rand(a, 200, 0, 0));
1672b8d22d11Stb 		BN_set_negative(a, rand_neg());
1673b8d22d11Stb 	}
1674b8d22d11Stb 	for (i = 0; i < num0; i++) {
1675b8d22d11Stb 		CHECK_GOTO(BN_lshift(b, a, i + 1));
1676b8d22d11Stb 		CHECK_GOTO(BN_add(c, c, c));
1677b8d22d11Stb 		if (bp != NULL) {
1678b8d22d11Stb 			if (!results) {
1679b8d22d11Stb 				CHECK_GOTO(BN_print(bp, a));
1680b8d22d11Stb 				BIO_puts(bp, " * ");
1681b8d22d11Stb 				CHECK_GOTO(BN_print(bp, c));
1682b8d22d11Stb 				BIO_puts(bp, " - ");
1683b8d22d11Stb 			}
1684b8d22d11Stb 			CHECK_GOTO(BN_print(bp, b));
1685b8d22d11Stb 			BIO_puts(bp, "\n");
1686b8d22d11Stb 		}
1687b8d22d11Stb 		CHECK_GOTO(BN_mul(d, a, c, ctx));
1688b8d22d11Stb 		CHECK_GOTO(BN_sub(d, d, b));
1689b8d22d11Stb 		if (!BN_is_zero(d)) {
1690b8d22d11Stb 			fprintf(stderr, "Left shift test failed!\n");
1691b8d22d11Stb 			fprintf(stderr, "a=");
1692b8d22d11Stb 			CHECK_GOTO(BN_print_fp(stderr, a));
1693b8d22d11Stb 			fprintf(stderr, "\nb=");
1694b8d22d11Stb 			CHECK_GOTO(BN_print_fp(stderr, b));
1695b8d22d11Stb 			fprintf(stderr, "\nc=");
1696b8d22d11Stb 			CHECK_GOTO(BN_print_fp(stderr, c));
1697b8d22d11Stb 			fprintf(stderr, "\nd=");
1698b8d22d11Stb 			CHECK_GOTO(BN_print_fp(stderr, d));
1699b8d22d11Stb 			fprintf(stderr, "\n");
17002e7cce5eStb 			goto err;
1701b8d22d11Stb 		}
1702b8d22d11Stb 	}
17032e7cce5eStb 
1704f7264475Stb 	ret = 1;
1705b8d22d11Stb  err:
17060edabd22Stb 	BN_CTX_end(ctx);
17072e7cce5eStb 
1708f7264475Stb 	return ret;
1709b8d22d11Stb }
1710b8d22d11Stb 
1711b8d22d11Stb int
17120edabd22Stb test_lshift1(BIO *bp, BN_CTX *ctx)
1713b8d22d11Stb {
17140edabd22Stb 	BIGNUM *a, *b, *c;
1715b8d22d11Stb 	int i;
1716f7264475Stb 	int ret = 0;
1717b8d22d11Stb 
17180edabd22Stb 	BN_CTX_start(ctx);
17190edabd22Stb 
17200edabd22Stb 	if ((a = BN_CTX_get(ctx)) == NULL)
1721b8d22d11Stb 		goto err;
17220edabd22Stb 	if ((b = BN_CTX_get(ctx)) == NULL)
1723b8d22d11Stb 		goto err;
17240edabd22Stb 	if ((c = BN_CTX_get(ctx)) == NULL)
1725b8d22d11Stb 		goto err;
1726b8d22d11Stb 
1727b8d22d11Stb 	CHECK_GOTO(BN_bntest_rand(a, 200, 0, 0));
1728b8d22d11Stb 	BN_set_negative(a, rand_neg());
1729b8d22d11Stb 	for (i = 0; i < num0; i++) {
1730b8d22d11Stb 		CHECK_GOTO(BN_lshift1(b, a));
1731b8d22d11Stb 		if (bp != NULL) {
1732b8d22d11Stb 			if (!results) {
1733b8d22d11Stb 				CHECK_GOTO(BN_print(bp, a));
1734b8d22d11Stb 				BIO_puts(bp, " * 2");
1735b8d22d11Stb 				BIO_puts(bp, " - ");
1736b8d22d11Stb 			}
1737b8d22d11Stb 			CHECK_GOTO(BN_print(bp, b));
1738b8d22d11Stb 			BIO_puts(bp, "\n");
1739b8d22d11Stb 		}
1740b8d22d11Stb 		CHECK_GOTO(BN_add(c, a, a));
1741b8d22d11Stb 		CHECK_GOTO(BN_sub(a, b, c));
1742b8d22d11Stb 		if (!BN_is_zero(a)) {
1743b8d22d11Stb 			fprintf(stderr, "Left shift one test failed!\n");
17442e7cce5eStb 			goto err;
1745b8d22d11Stb 		}
1746b8d22d11Stb 
17478e84e241Stb 		CHECK_GOTO(bn_copy(a, b));
1748b8d22d11Stb 	}
17492e7cce5eStb 
1750f7264475Stb 	ret = 1;
1751b8d22d11Stb  err:
17520edabd22Stb 	BN_CTX_end(ctx);
17532e7cce5eStb 
1754f7264475Stb 	return ret;
1755b8d22d11Stb }
1756b8d22d11Stb 
1757b8d22d11Stb int
1758b8d22d11Stb test_rshift(BIO *bp, BN_CTX *ctx)
1759b8d22d11Stb {
17600edabd22Stb 	BIGNUM *a, *b, *c, *d, *e;
1761b8d22d11Stb 	int i;
1762f7264475Stb 	int ret = 0;
1763b8d22d11Stb 
17640edabd22Stb 	BN_CTX_start(ctx);
17650edabd22Stb 
17660edabd22Stb 	if ((a = BN_CTX_get(ctx)) == NULL)
1767b8d22d11Stb 		goto err;
17680edabd22Stb 	if ((b = BN_CTX_get(ctx)) == NULL)
1769b8d22d11Stb 		goto err;
17700edabd22Stb 	if ((c = BN_CTX_get(ctx)) == NULL)
1771b8d22d11Stb 		goto err;
17720edabd22Stb 	if ((d = BN_CTX_get(ctx)) == NULL)
1773b8d22d11Stb 		goto err;
17740edabd22Stb 	if ((e = BN_CTX_get(ctx)) == NULL)
1775b8d22d11Stb 		goto err;
1776b8d22d11Stb 	CHECK_GOTO(BN_one(c));
1777b8d22d11Stb 
1778b8d22d11Stb 	CHECK_GOTO(BN_bntest_rand(a, 200, 0, 0));
1779b8d22d11Stb 	BN_set_negative(a, rand_neg());
1780b8d22d11Stb 	for (i = 0; i < num0; i++) {
1781b8d22d11Stb 		CHECK_GOTO(BN_rshift(b, a, i + 1));
1782b8d22d11Stb 		CHECK_GOTO(BN_add(c, c, c));
1783b8d22d11Stb 		if (bp != NULL) {
1784b8d22d11Stb 			if (!results) {
1785b8d22d11Stb 				CHECK_GOTO(BN_print(bp, a));
1786b8d22d11Stb 				BIO_puts(bp, " / ");
1787b8d22d11Stb 				CHECK_GOTO(BN_print(bp, c));
1788b8d22d11Stb 				BIO_puts(bp, " - ");
1789b8d22d11Stb 			}
1790b8d22d11Stb 			CHECK_GOTO(BN_print(bp, b));
1791b8d22d11Stb 			BIO_puts(bp, "\n");
1792b8d22d11Stb 		}
1793b8d22d11Stb 		CHECK_GOTO(BN_div(d, e, a, c, ctx));
1794b8d22d11Stb 		CHECK_GOTO(BN_sub(d, d, b));
1795b8d22d11Stb 		if (!BN_is_zero(d)) {
1796b8d22d11Stb 			fprintf(stderr, "Right shift test failed!\n");
17972e7cce5eStb 			goto err;
1798b8d22d11Stb 		}
1799b8d22d11Stb 	}
18002e7cce5eStb 
1801f7264475Stb 	ret = 1;
1802b8d22d11Stb  err:
18030edabd22Stb 	BN_CTX_end(ctx);
18042e7cce5eStb 
1805f7264475Stb 	return ret;
1806b8d22d11Stb }
1807b8d22d11Stb 
1808b8d22d11Stb int
18090edabd22Stb test_rshift1(BIO *bp, BN_CTX *ctx)
1810b8d22d11Stb {
18110edabd22Stb 	BIGNUM *a, *b, *c;
1812b8d22d11Stb 	int i;
1813f7264475Stb 	int ret = 0;
1814b8d22d11Stb 
18150edabd22Stb 	BN_CTX_start(ctx);
18160edabd22Stb 
18170edabd22Stb 	if ((a = BN_CTX_get(ctx)) == NULL)
1818b8d22d11Stb 		goto err;
18190edabd22Stb 	if ((b = BN_CTX_get(ctx)) == NULL)
1820b8d22d11Stb 		goto err;
18210edabd22Stb 	if ((c = BN_CTX_get(ctx)) == NULL)
1822b8d22d11Stb 		goto err;
1823b8d22d11Stb 
1824b8d22d11Stb 	CHECK_GOTO(BN_bntest_rand(a, 200, 0, 0));
1825b8d22d11Stb 	BN_set_negative(a, rand_neg());
1826b8d22d11Stb 	for (i = 0; i < num0; i++) {
1827b8d22d11Stb 		CHECK_GOTO(BN_rshift1(b, a));
1828b8d22d11Stb 		if (bp != NULL) {
1829b8d22d11Stb 			if (!results) {
1830b8d22d11Stb 				CHECK_GOTO(BN_print(bp, a));
1831b8d22d11Stb 				BIO_puts(bp, " / 2");
1832b8d22d11Stb 				BIO_puts(bp, " - ");
1833b8d22d11Stb 			}
1834b8d22d11Stb 			CHECK_GOTO(BN_print(bp, b));
1835b8d22d11Stb 			BIO_puts(bp, "\n");
1836b8d22d11Stb 		}
1837b8d22d11Stb 		CHECK_GOTO(BN_sub(c, a, b));
1838b8d22d11Stb 		CHECK_GOTO(BN_sub(c, c, b));
1839b8d22d11Stb 		if (!BN_is_zero(c) && !BN_abs_is_word(c, 1)) {
1840b8d22d11Stb 			fprintf(stderr, "Right shift one test failed!\n");
18412e7cce5eStb 			goto err;
1842b8d22d11Stb 		}
18438e84e241Stb 		CHECK_GOTO(bn_copy(a, b));
1844b8d22d11Stb 	}
18452e7cce5eStb 
1846f7264475Stb 	ret = 1;
1847b8d22d11Stb  err:
18480edabd22Stb 	BN_CTX_end(ctx);
18492e7cce5eStb 
1850f7264475Stb 	return ret;
1851b8d22d11Stb }
1852b8d22d11Stb 
1853b8d22d11Stb int
1854b8d22d11Stb rand_neg(void)
1855b8d22d11Stb {
1856b8d22d11Stb 	static unsigned int neg = 0;
1857b8d22d11Stb 	static int sign[8] = { 0, 0, 0, 1, 1, 0, 1, 1 };
1858b8d22d11Stb 
18590f386146Stb 	return sign[neg++ % 8];
1860b8d22d11Stb }
1861b8d22d11Stb 
1862b8d22d11Stb int
1863b8d22d11Stb test_mod_exp_sizes(BIO *bp, BN_CTX *ctx)
1864b8d22d11Stb {
1865b8d22d11Stb 	BN_MONT_CTX *mont_ctx = NULL;
18660edabd22Stb 	BIGNUM *p, *x, *y, *r, *r2;
1867b8d22d11Stb 	int size;
1868f7264475Stb 	int ret = 0;
1869b8d22d11Stb 
1870b8d22d11Stb 	BN_CTX_start(ctx);
1871b8d22d11Stb 	CHECK_GOTO(p = BN_CTX_get(ctx));
1872b8d22d11Stb 	CHECK_GOTO(x = BN_CTX_get(ctx));
1873b8d22d11Stb 	CHECK_GOTO(y = BN_CTX_get(ctx));
1874b8d22d11Stb 	CHECK_GOTO(r = BN_CTX_get(ctx));
1875b8d22d11Stb 	CHECK_GOTO(r2 = BN_CTX_get(ctx));
1876b8d22d11Stb 	mont_ctx = BN_MONT_CTX_new();
1877b8d22d11Stb 
1878b8d22d11Stb 	if (r2 == NULL || mont_ctx == NULL)
1879b8d22d11Stb 		goto err;
1880b8d22d11Stb 
1881b8d22d11Stb 	if (!BN_generate_prime_ex(p, 32, 0, NULL, NULL, NULL) ||
1882b8d22d11Stb 	    !BN_MONT_CTX_set(mont_ctx, p, ctx))
1883b8d22d11Stb 		goto err;
1884b8d22d11Stb 
1885b8d22d11Stb 	for (size = 32; size < 1024; size += 8) {
1886b8d22d11Stb 		if (!BN_rand(x, size, -1, 0) ||
1887b8d22d11Stb 		    !BN_rand(y, size, -1, 0) ||
1888b8d22d11Stb 		    !BN_mod_exp_mont_consttime(r, x, y, p, ctx, mont_ctx) ||
1889b8d22d11Stb 		    !BN_mod_exp(r2, x, y, p, ctx))
1890b8d22d11Stb 			goto err;
1891b8d22d11Stb 
1892b8d22d11Stb 		if (BN_cmp(r, r2) != 0) {
1893b8d22d11Stb 			char *r_str = NULL;
1894b8d22d11Stb 			char *r2_str = NULL;
1895b8d22d11Stb 			CHECK_GOTO(r_str = BN_bn2hex(r));
1896b8d22d11Stb 			CHECK_GOTO(r2_str = BN_bn2hex(r2));
1897b8d22d11Stb 
1898b8d22d11Stb 			printf("Incorrect answer at size %d: %s vs %s\n",
1899b8d22d11Stb 			    size, r_str, r2_str);
1900b8d22d11Stb 			free(r_str);
1901b8d22d11Stb 			free(r2_str);
1902b8d22d11Stb 			goto err;
1903b8d22d11Stb 		}
1904b8d22d11Stb 	}
1905b8d22d11Stb 
1906f7264475Stb 	ret = 1;
1907b8d22d11Stb  err:
1908b8d22d11Stb 	BN_CTX_end(ctx);
19090edabd22Stb 	BN_MONT_CTX_free(mont_ctx);
19102e7cce5eStb 
1911f7264475Stb 	return ret;
1912b8d22d11Stb }
1913