xref: /onnv-gate/usr/src/common/openssl/crypto/bn/bn_sqrt.c (revision 2139:6243c3338933)
1*2139Sjp161948 /* crypto/bn/bn_sqrt.c */
20Sstevel@tonic-gate /* Written by Lenka Fibikova <fibikova@exp-math.uni-essen.de>
30Sstevel@tonic-gate  * and Bodo Moeller for the OpenSSL project. */
40Sstevel@tonic-gate /* ====================================================================
50Sstevel@tonic-gate  * Copyright (c) 1998-2000 The OpenSSL Project.  All rights reserved.
60Sstevel@tonic-gate  *
70Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
80Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
90Sstevel@tonic-gate  * are met:
100Sstevel@tonic-gate  *
110Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
120Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
150Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
160Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
170Sstevel@tonic-gate  *    distribution.
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this
200Sstevel@tonic-gate  *    software must display the following acknowledgment:
210Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
220Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
230Sstevel@tonic-gate  *
240Sstevel@tonic-gate  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
250Sstevel@tonic-gate  *    endorse or promote products derived from this software without
260Sstevel@tonic-gate  *    prior written permission. For written permission, please contact
270Sstevel@tonic-gate  *    openssl-core@openssl.org.
280Sstevel@tonic-gate  *
290Sstevel@tonic-gate  * 5. Products derived from this software may not be called "OpenSSL"
300Sstevel@tonic-gate  *    nor may "OpenSSL" appear in their names without prior written
310Sstevel@tonic-gate  *    permission of the OpenSSL Project.
320Sstevel@tonic-gate  *
330Sstevel@tonic-gate  * 6. Redistributions of any form whatsoever must retain the following
340Sstevel@tonic-gate  *    acknowledgment:
350Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
360Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
370Sstevel@tonic-gate  *
380Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
390Sstevel@tonic-gate  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
400Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
410Sstevel@tonic-gate  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
420Sstevel@tonic-gate  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
430Sstevel@tonic-gate  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
440Sstevel@tonic-gate  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
450Sstevel@tonic-gate  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
460Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
470Sstevel@tonic-gate  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
480Sstevel@tonic-gate  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
490Sstevel@tonic-gate  * OF THE POSSIBILITY OF SUCH DAMAGE.
500Sstevel@tonic-gate  * ====================================================================
510Sstevel@tonic-gate  *
520Sstevel@tonic-gate  * This product includes cryptographic software written by Eric Young
530Sstevel@tonic-gate  * (eay@cryptsoft.com).  This product includes software written by Tim
540Sstevel@tonic-gate  * Hudson (tjh@cryptsoft.com).
550Sstevel@tonic-gate  *
560Sstevel@tonic-gate  */
570Sstevel@tonic-gate 
580Sstevel@tonic-gate #include "cryptlib.h"
590Sstevel@tonic-gate #include "bn_lcl.h"
600Sstevel@tonic-gate 
610Sstevel@tonic-gate 
BN_mod_sqrt(BIGNUM * in,const BIGNUM * a,const BIGNUM * p,BN_CTX * ctx)620Sstevel@tonic-gate BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
630Sstevel@tonic-gate /* Returns 'ret' such that
640Sstevel@tonic-gate  *      ret^2 == a (mod p),
650Sstevel@tonic-gate  * using the Tonelli/Shanks algorithm (cf. Henri Cohen, "A Course
660Sstevel@tonic-gate  * in Algebraic Computational Number Theory", algorithm 1.5.1).
670Sstevel@tonic-gate  * 'p' must be prime!
680Sstevel@tonic-gate  */
690Sstevel@tonic-gate 	{
700Sstevel@tonic-gate 	BIGNUM *ret = in;
710Sstevel@tonic-gate 	int err = 1;
720Sstevel@tonic-gate 	int r;
73*2139Sjp161948 	BIGNUM *A, *b, *q, *t, *x, *y;
740Sstevel@tonic-gate 	int e, i, j;
750Sstevel@tonic-gate 
760Sstevel@tonic-gate 	if (!BN_is_odd(p) || BN_abs_is_word(p, 1))
770Sstevel@tonic-gate 		{
780Sstevel@tonic-gate 		if (BN_abs_is_word(p, 2))
790Sstevel@tonic-gate 			{
800Sstevel@tonic-gate 			if (ret == NULL)
810Sstevel@tonic-gate 				ret = BN_new();
820Sstevel@tonic-gate 			if (ret == NULL)
830Sstevel@tonic-gate 				goto end;
840Sstevel@tonic-gate 			if (!BN_set_word(ret, BN_is_bit_set(a, 0)))
850Sstevel@tonic-gate 				{
86*2139Sjp161948 				if (ret != in)
87*2139Sjp161948 					BN_free(ret);
880Sstevel@tonic-gate 				return NULL;
890Sstevel@tonic-gate 				}
90*2139Sjp161948 			bn_check_top(ret);
910Sstevel@tonic-gate 			return ret;
920Sstevel@tonic-gate 			}
930Sstevel@tonic-gate 
940Sstevel@tonic-gate 		BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME);
950Sstevel@tonic-gate 		return(NULL);
960Sstevel@tonic-gate 		}
970Sstevel@tonic-gate 
980Sstevel@tonic-gate 	if (BN_is_zero(a) || BN_is_one(a))
990Sstevel@tonic-gate 		{
1000Sstevel@tonic-gate 		if (ret == NULL)
1010Sstevel@tonic-gate 			ret = BN_new();
1020Sstevel@tonic-gate 		if (ret == NULL)
1030Sstevel@tonic-gate 			goto end;
1040Sstevel@tonic-gate 		if (!BN_set_word(ret, BN_is_one(a)))
1050Sstevel@tonic-gate 			{
106*2139Sjp161948 			if (ret != in)
107*2139Sjp161948 				BN_free(ret);
1080Sstevel@tonic-gate 			return NULL;
1090Sstevel@tonic-gate 			}
110*2139Sjp161948 		bn_check_top(ret);
1110Sstevel@tonic-gate 		return ret;
1120Sstevel@tonic-gate 		}
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate 	BN_CTX_start(ctx);
115*2139Sjp161948 	A = BN_CTX_get(ctx);
1160Sstevel@tonic-gate 	b = BN_CTX_get(ctx);
1170Sstevel@tonic-gate 	q = BN_CTX_get(ctx);
1180Sstevel@tonic-gate 	t = BN_CTX_get(ctx);
1190Sstevel@tonic-gate 	x = BN_CTX_get(ctx);
1200Sstevel@tonic-gate 	y = BN_CTX_get(ctx);
1210Sstevel@tonic-gate 	if (y == NULL) goto end;
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 	if (ret == NULL)
1240Sstevel@tonic-gate 		ret = BN_new();
1250Sstevel@tonic-gate 	if (ret == NULL) goto end;
1260Sstevel@tonic-gate 
127*2139Sjp161948 	/* A = a mod p */
128*2139Sjp161948 	if (!BN_nnmod(A, a, p, ctx)) goto end;
129*2139Sjp161948 
1300Sstevel@tonic-gate 	/* now write  |p| - 1  as  2^e*q  where  q  is odd */
1310Sstevel@tonic-gate 	e = 1;
1320Sstevel@tonic-gate 	while (!BN_is_bit_set(p, e))
1330Sstevel@tonic-gate 		e++;
1340Sstevel@tonic-gate 	/* we'll set  q  later (if needed) */
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate 	if (e == 1)
1370Sstevel@tonic-gate 		{
1380Sstevel@tonic-gate 		/* The easy case:  (|p|-1)/2  is odd, so 2 has an inverse
1390Sstevel@tonic-gate 		 * modulo  (|p|-1)/2,  and square roots can be computed
1400Sstevel@tonic-gate 		 * directly by modular exponentiation.
1410Sstevel@tonic-gate 		 * We have
1420Sstevel@tonic-gate 		 *     2 * (|p|+1)/4 == 1   (mod (|p|-1)/2),
1430Sstevel@tonic-gate 		 * so we can use exponent  (|p|+1)/4,  i.e.  (|p|-3)/4 + 1.
1440Sstevel@tonic-gate 		 */
1450Sstevel@tonic-gate 		if (!BN_rshift(q, p, 2)) goto end;
1460Sstevel@tonic-gate 		q->neg = 0;
1470Sstevel@tonic-gate 		if (!BN_add_word(q, 1)) goto end;
148*2139Sjp161948 		if (!BN_mod_exp(ret, A, q, p, ctx)) goto end;
1490Sstevel@tonic-gate 		err = 0;
150*2139Sjp161948 		goto vrfy;
1510Sstevel@tonic-gate 		}
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 	if (e == 2)
1540Sstevel@tonic-gate 		{
1550Sstevel@tonic-gate 		/* |p| == 5  (mod 8)
1560Sstevel@tonic-gate 		 *
1570Sstevel@tonic-gate 		 * In this case  2  is always a non-square since
1580Sstevel@tonic-gate 		 * Legendre(2,p) = (-1)^((p^2-1)/8)  for any odd prime.
1590Sstevel@tonic-gate 		 * So if  a  really is a square, then  2*a  is a non-square.
1600Sstevel@tonic-gate 		 * Thus for
1610Sstevel@tonic-gate 		 *      b := (2*a)^((|p|-5)/8),
1620Sstevel@tonic-gate 		 *      i := (2*a)*b^2
1630Sstevel@tonic-gate 		 * we have
1640Sstevel@tonic-gate 		 *     i^2 = (2*a)^((1 + (|p|-5)/4)*2)
1650Sstevel@tonic-gate 		 *         = (2*a)^((p-1)/2)
1660Sstevel@tonic-gate 		 *         = -1;
1670Sstevel@tonic-gate 		 * so if we set
1680Sstevel@tonic-gate 		 *      x := a*b*(i-1),
1690Sstevel@tonic-gate 		 * then
1700Sstevel@tonic-gate 		 *     x^2 = a^2 * b^2 * (i^2 - 2*i + 1)
1710Sstevel@tonic-gate 		 *         = a^2 * b^2 * (-2*i)
1720Sstevel@tonic-gate 		 *         = a*(-i)*(2*a*b^2)
1730Sstevel@tonic-gate 		 *         = a*(-i)*i
1740Sstevel@tonic-gate 		 *         = a.
1750Sstevel@tonic-gate 		 *
1760Sstevel@tonic-gate 		 * (This is due to A.O.L. Atkin,
1770Sstevel@tonic-gate 		 * <URL: http://listserv.nodak.edu/scripts/wa.exe?A2=ind9211&L=nmbrthry&O=T&P=562>,
1780Sstevel@tonic-gate 		 * November 1992.)
1790Sstevel@tonic-gate 		 */
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 		/* t := 2*a */
182*2139Sjp161948 		if (!BN_mod_lshift1_quick(t, A, p)) goto end;
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 		/* b := (2*a)^((|p|-5)/8) */
1850Sstevel@tonic-gate 		if (!BN_rshift(q, p, 3)) goto end;
1860Sstevel@tonic-gate 		q->neg = 0;
1870Sstevel@tonic-gate 		if (!BN_mod_exp(b, t, q, p, ctx)) goto end;
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate 		/* y := b^2 */
1900Sstevel@tonic-gate 		if (!BN_mod_sqr(y, b, p, ctx)) goto end;
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate 		/* t := (2*a)*b^2 - 1*/
1930Sstevel@tonic-gate 		if (!BN_mod_mul(t, t, y, p, ctx)) goto end;
1940Sstevel@tonic-gate 		if (!BN_sub_word(t, 1)) goto end;
1950Sstevel@tonic-gate 
1960Sstevel@tonic-gate 		/* x = a*b*t */
197*2139Sjp161948 		if (!BN_mod_mul(x, A, b, p, ctx)) goto end;
1980Sstevel@tonic-gate 		if (!BN_mod_mul(x, x, t, p, ctx)) goto end;
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 		if (!BN_copy(ret, x)) goto end;
2010Sstevel@tonic-gate 		err = 0;
202*2139Sjp161948 		goto vrfy;
2030Sstevel@tonic-gate 		}
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 	/* e > 2, so we really have to use the Tonelli/Shanks algorithm.
2060Sstevel@tonic-gate 	 * First, find some  y  that is not a square. */
2070Sstevel@tonic-gate 	if (!BN_copy(q, p)) goto end; /* use 'q' as temp */
2080Sstevel@tonic-gate 	q->neg = 0;
2090Sstevel@tonic-gate 	i = 2;
2100Sstevel@tonic-gate 	do
2110Sstevel@tonic-gate 		{
2120Sstevel@tonic-gate 		/* For efficiency, try small numbers first;
2130Sstevel@tonic-gate 		 * if this fails, try random numbers.
2140Sstevel@tonic-gate 		 */
2150Sstevel@tonic-gate 		if (i < 22)
2160Sstevel@tonic-gate 			{
2170Sstevel@tonic-gate 			if (!BN_set_word(y, i)) goto end;
2180Sstevel@tonic-gate 			}
2190Sstevel@tonic-gate 		else
2200Sstevel@tonic-gate 			{
2210Sstevel@tonic-gate 			if (!BN_pseudo_rand(y, BN_num_bits(p), 0, 0)) goto end;
2220Sstevel@tonic-gate 			if (BN_ucmp(y, p) >= 0)
2230Sstevel@tonic-gate 				{
2240Sstevel@tonic-gate 				if (!(p->neg ? BN_add : BN_sub)(y, y, p)) goto end;
2250Sstevel@tonic-gate 				}
2260Sstevel@tonic-gate 			/* now 0 <= y < |p| */
2270Sstevel@tonic-gate 			if (BN_is_zero(y))
2280Sstevel@tonic-gate 				if (!BN_set_word(y, i)) goto end;
2290Sstevel@tonic-gate 			}
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate 		r = BN_kronecker(y, q, ctx); /* here 'q' is |p| */
2320Sstevel@tonic-gate 		if (r < -1) goto end;
2330Sstevel@tonic-gate 		if (r == 0)
2340Sstevel@tonic-gate 			{
2350Sstevel@tonic-gate 			/* m divides p */
2360Sstevel@tonic-gate 			BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME);
2370Sstevel@tonic-gate 			goto end;
2380Sstevel@tonic-gate 			}
2390Sstevel@tonic-gate 		}
2400Sstevel@tonic-gate 	while (r == 1 && ++i < 82);
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate 	if (r != -1)
2430Sstevel@tonic-gate 		{
2440Sstevel@tonic-gate 		/* Many rounds and still no non-square -- this is more likely
2450Sstevel@tonic-gate 		 * a bug than just bad luck.
2460Sstevel@tonic-gate 		 * Even if  p  is not prime, we should have found some  y
2470Sstevel@tonic-gate 		 * such that r == -1.
2480Sstevel@tonic-gate 		 */
2490Sstevel@tonic-gate 		BNerr(BN_F_BN_MOD_SQRT, BN_R_TOO_MANY_ITERATIONS);
2500Sstevel@tonic-gate 		goto end;
2510Sstevel@tonic-gate 		}
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 	/* Here's our actual 'q': */
2540Sstevel@tonic-gate 	if (!BN_rshift(q, q, e)) goto end;
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate 	/* Now that we have some non-square, we can find an element
2570Sstevel@tonic-gate 	 * of order  2^e  by computing its q'th power. */
2580Sstevel@tonic-gate 	if (!BN_mod_exp(y, y, q, p, ctx)) goto end;
2590Sstevel@tonic-gate 	if (BN_is_one(y))
2600Sstevel@tonic-gate 		{
2610Sstevel@tonic-gate 		BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME);
2620Sstevel@tonic-gate 		goto end;
2630Sstevel@tonic-gate 		}
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate 	/* Now we know that (if  p  is indeed prime) there is an integer
2660Sstevel@tonic-gate 	 * k,  0 <= k < 2^e,  such that
2670Sstevel@tonic-gate 	 *
2680Sstevel@tonic-gate 	 *      a^q * y^k == 1   (mod p).
2690Sstevel@tonic-gate 	 *
2700Sstevel@tonic-gate 	 * As  a^q  is a square and  y  is not,  k  must be even.
2710Sstevel@tonic-gate 	 * q+1  is even, too, so there is an element
2720Sstevel@tonic-gate 	 *
2730Sstevel@tonic-gate 	 *     X := a^((q+1)/2) * y^(k/2),
2740Sstevel@tonic-gate 	 *
2750Sstevel@tonic-gate 	 * and it satisfies
2760Sstevel@tonic-gate 	 *
2770Sstevel@tonic-gate 	 *     X^2 = a^q * a     * y^k
2780Sstevel@tonic-gate 	 *         = a,
2790Sstevel@tonic-gate 	 *
2800Sstevel@tonic-gate 	 * so it is the square root that we are looking for.
2810Sstevel@tonic-gate 	 */
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 	/* t := (q-1)/2  (note that  q  is odd) */
2840Sstevel@tonic-gate 	if (!BN_rshift1(t, q)) goto end;
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate 	/* x := a^((q-1)/2) */
2870Sstevel@tonic-gate 	if (BN_is_zero(t)) /* special case: p = 2^e + 1 */
2880Sstevel@tonic-gate 		{
289*2139Sjp161948 		if (!BN_nnmod(t, A, p, ctx)) goto end;
2900Sstevel@tonic-gate 		if (BN_is_zero(t))
2910Sstevel@tonic-gate 			{
2920Sstevel@tonic-gate 			/* special case: a == 0  (mod p) */
293*2139Sjp161948 			BN_zero(ret);
2940Sstevel@tonic-gate 			err = 0;
2950Sstevel@tonic-gate 			goto end;
2960Sstevel@tonic-gate 			}
2970Sstevel@tonic-gate 		else
2980Sstevel@tonic-gate 			if (!BN_one(x)) goto end;
2990Sstevel@tonic-gate 		}
3000Sstevel@tonic-gate 	else
3010Sstevel@tonic-gate 		{
302*2139Sjp161948 		if (!BN_mod_exp(x, A, t, p, ctx)) goto end;
3030Sstevel@tonic-gate 		if (BN_is_zero(x))
3040Sstevel@tonic-gate 			{
3050Sstevel@tonic-gate 			/* special case: a == 0  (mod p) */
306*2139Sjp161948 			BN_zero(ret);
3070Sstevel@tonic-gate 			err = 0;
3080Sstevel@tonic-gate 			goto end;
3090Sstevel@tonic-gate 			}
3100Sstevel@tonic-gate 		}
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 	/* b := a*x^2  (= a^q) */
3130Sstevel@tonic-gate 	if (!BN_mod_sqr(b, x, p, ctx)) goto end;
314*2139Sjp161948 	if (!BN_mod_mul(b, b, A, p, ctx)) goto end;
3150Sstevel@tonic-gate 
3160Sstevel@tonic-gate 	/* x := a*x    (= a^((q+1)/2)) */
317*2139Sjp161948 	if (!BN_mod_mul(x, x, A, p, ctx)) goto end;
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate 	while (1)
3200Sstevel@tonic-gate 		{
3210Sstevel@tonic-gate 		/* Now  b  is  a^q * y^k  for some even  k  (0 <= k < 2^E
3220Sstevel@tonic-gate 		 * where  E  refers to the original value of  e,  which we
3230Sstevel@tonic-gate 		 * don't keep in a variable),  and  x  is  a^((q+1)/2) * y^(k/2).
3240Sstevel@tonic-gate 		 *
3250Sstevel@tonic-gate 		 * We have  a*b = x^2,
3260Sstevel@tonic-gate 		 *    y^2^(e-1) = -1,
3270Sstevel@tonic-gate 		 *    b^2^(e-1) = 1.
3280Sstevel@tonic-gate 		 */
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate 		if (BN_is_one(b))
3310Sstevel@tonic-gate 			{
3320Sstevel@tonic-gate 			if (!BN_copy(ret, x)) goto end;
3330Sstevel@tonic-gate 			err = 0;
334*2139Sjp161948 			goto vrfy;
3350Sstevel@tonic-gate 			}
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate 		/* find smallest  i  such that  b^(2^i) = 1 */
3390Sstevel@tonic-gate 		i = 1;
3400Sstevel@tonic-gate 		if (!BN_mod_sqr(t, b, p, ctx)) goto end;
3410Sstevel@tonic-gate 		while (!BN_is_one(t))
3420Sstevel@tonic-gate 			{
3430Sstevel@tonic-gate 			i++;
3440Sstevel@tonic-gate 			if (i == e)
3450Sstevel@tonic-gate 				{
3460Sstevel@tonic-gate 				BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE);
3470Sstevel@tonic-gate 				goto end;
3480Sstevel@tonic-gate 				}
3490Sstevel@tonic-gate 			if (!BN_mod_mul(t, t, t, p, ctx)) goto end;
3500Sstevel@tonic-gate 			}
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate 		/* t := y^2^(e - i - 1) */
3540Sstevel@tonic-gate 		if (!BN_copy(t, y)) goto end;
3550Sstevel@tonic-gate 		for (j = e - i - 1; j > 0; j--)
3560Sstevel@tonic-gate 			{
3570Sstevel@tonic-gate 			if (!BN_mod_sqr(t, t, p, ctx)) goto end;
3580Sstevel@tonic-gate 			}
3590Sstevel@tonic-gate 		if (!BN_mod_mul(y, t, t, p, ctx)) goto end;
3600Sstevel@tonic-gate 		if (!BN_mod_mul(x, x, t, p, ctx)) goto end;
3610Sstevel@tonic-gate 		if (!BN_mod_mul(b, b, y, p, ctx)) goto end;
3620Sstevel@tonic-gate 		e = i;
3630Sstevel@tonic-gate 		}
3640Sstevel@tonic-gate 
365*2139Sjp161948  vrfy:
366*2139Sjp161948 	if (!err)
367*2139Sjp161948 		{
368*2139Sjp161948 		/* verify the result -- the input might have been not a square
369*2139Sjp161948 		 * (test added in 0.9.8) */
370*2139Sjp161948 
371*2139Sjp161948 		if (!BN_mod_sqr(x, ret, p, ctx))
372*2139Sjp161948 			err = 1;
373*2139Sjp161948 
374*2139Sjp161948 		if (!err && 0 != BN_cmp(x, A))
375*2139Sjp161948 			{
376*2139Sjp161948 			BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE);
377*2139Sjp161948 			err = 1;
378*2139Sjp161948 			}
379*2139Sjp161948 		}
380*2139Sjp161948 
3810Sstevel@tonic-gate  end:
3820Sstevel@tonic-gate 	if (err)
3830Sstevel@tonic-gate 		{
3840Sstevel@tonic-gate 		if (ret != NULL && ret != in)
3850Sstevel@tonic-gate 			{
3860Sstevel@tonic-gate 			BN_clear_free(ret);
3870Sstevel@tonic-gate 			}
3880Sstevel@tonic-gate 		ret = NULL;
3890Sstevel@tonic-gate 		}
3900Sstevel@tonic-gate 	BN_CTX_end(ctx);
391*2139Sjp161948 	bn_check_top(ret);
3920Sstevel@tonic-gate 	return ret;
3930Sstevel@tonic-gate 	}
394