xref: /onnv-gate/usr/src/common/openssl/crypto/bn/bn_exp.c (revision 2139:6243c3338933)
10Sstevel@tonic-gate /* crypto/bn/bn_exp.c */
20Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
30Sstevel@tonic-gate  * All rights reserved.
40Sstevel@tonic-gate  *
50Sstevel@tonic-gate  * This package is an SSL implementation written
60Sstevel@tonic-gate  * by Eric Young (eay@cryptsoft.com).
70Sstevel@tonic-gate  * The implementation was written so as to conform with Netscapes SSL.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * This library is free for commercial and non-commercial use as long as
100Sstevel@tonic-gate  * the following conditions are aheared to.  The following conditions
110Sstevel@tonic-gate  * apply to all code found in this distribution, be it the RC4, RSA,
120Sstevel@tonic-gate  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
130Sstevel@tonic-gate  * included with this distribution is covered by the same copyright terms
140Sstevel@tonic-gate  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
150Sstevel@tonic-gate  *
160Sstevel@tonic-gate  * Copyright remains Eric Young's, and as such any Copyright notices in
170Sstevel@tonic-gate  * the code are not to be removed.
180Sstevel@tonic-gate  * If this package is used in a product, Eric Young should be given attribution
190Sstevel@tonic-gate  * as the author of the parts of the library used.
200Sstevel@tonic-gate  * This can be in the form of a textual message at program startup or
210Sstevel@tonic-gate  * in documentation (online or textual) provided with the package.
220Sstevel@tonic-gate  *
230Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
240Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
250Sstevel@tonic-gate  * are met:
260Sstevel@tonic-gate  * 1. Redistributions of source code must retain the copyright
270Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
280Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
290Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
300Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
310Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this software
320Sstevel@tonic-gate  *    must display the following acknowledgement:
330Sstevel@tonic-gate  *    "This product includes cryptographic software written by
340Sstevel@tonic-gate  *     Eric Young (eay@cryptsoft.com)"
350Sstevel@tonic-gate  *    The word 'cryptographic' can be left out if the rouines from the library
360Sstevel@tonic-gate  *    being used are not cryptographic related :-).
370Sstevel@tonic-gate  * 4. If you include any Windows specific code (or a derivative thereof) from
380Sstevel@tonic-gate  *    the apps directory (application code) you must include an acknowledgement:
390Sstevel@tonic-gate  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
400Sstevel@tonic-gate  *
410Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
420Sstevel@tonic-gate  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
430Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
440Sstevel@tonic-gate  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
450Sstevel@tonic-gate  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
460Sstevel@tonic-gate  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
470Sstevel@tonic-gate  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
480Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
490Sstevel@tonic-gate  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
500Sstevel@tonic-gate  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
510Sstevel@tonic-gate  * SUCH DAMAGE.
520Sstevel@tonic-gate  *
530Sstevel@tonic-gate  * The licence and distribution terms for any publically available version or
540Sstevel@tonic-gate  * derivative of this code cannot be changed.  i.e. this code cannot simply be
550Sstevel@tonic-gate  * copied and put under another distribution licence
560Sstevel@tonic-gate  * [including the GNU Public Licence.]
570Sstevel@tonic-gate  */
580Sstevel@tonic-gate /* ====================================================================
59*2139Sjp161948  * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
600Sstevel@tonic-gate  *
610Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
620Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
630Sstevel@tonic-gate  * are met:
640Sstevel@tonic-gate  *
650Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
660Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
670Sstevel@tonic-gate  *
680Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
690Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
700Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
710Sstevel@tonic-gate  *    distribution.
720Sstevel@tonic-gate  *
730Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this
740Sstevel@tonic-gate  *    software must display the following acknowledgment:
750Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
760Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
770Sstevel@tonic-gate  *
780Sstevel@tonic-gate  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
790Sstevel@tonic-gate  *    endorse or promote products derived from this software without
800Sstevel@tonic-gate  *    prior written permission. For written permission, please contact
810Sstevel@tonic-gate  *    openssl-core@openssl.org.
820Sstevel@tonic-gate  *
830Sstevel@tonic-gate  * 5. Products derived from this software may not be called "OpenSSL"
840Sstevel@tonic-gate  *    nor may "OpenSSL" appear in their names without prior written
850Sstevel@tonic-gate  *    permission of the OpenSSL Project.
860Sstevel@tonic-gate  *
870Sstevel@tonic-gate  * 6. Redistributions of any form whatsoever must retain the following
880Sstevel@tonic-gate  *    acknowledgment:
890Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
900Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
910Sstevel@tonic-gate  *
920Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
930Sstevel@tonic-gate  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
940Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
950Sstevel@tonic-gate  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
960Sstevel@tonic-gate  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
970Sstevel@tonic-gate  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
980Sstevel@tonic-gate  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
990Sstevel@tonic-gate  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1000Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
1010Sstevel@tonic-gate  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1020Sstevel@tonic-gate  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
1030Sstevel@tonic-gate  * OF THE POSSIBILITY OF SUCH DAMAGE.
1040Sstevel@tonic-gate  * ====================================================================
1050Sstevel@tonic-gate  *
1060Sstevel@tonic-gate  * This product includes cryptographic software written by Eric Young
1070Sstevel@tonic-gate  * (eay@cryptsoft.com).  This product includes software written by Tim
1080Sstevel@tonic-gate  * Hudson (tjh@cryptsoft.com).
1090Sstevel@tonic-gate  *
1100Sstevel@tonic-gate  */
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate #include "cryptlib.h"
1140Sstevel@tonic-gate #include "bn_lcl.h"
1150Sstevel@tonic-gate 
116*2139Sjp161948 /* maximum precomputation table size for *variable* sliding windows */
1170Sstevel@tonic-gate #define TABLE_SIZE	32
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate /* this one works - simple but works */
BN_exp(BIGNUM * r,const BIGNUM * a,const BIGNUM * p,BN_CTX * ctx)1200Sstevel@tonic-gate int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
1210Sstevel@tonic-gate 	{
1220Sstevel@tonic-gate 	int i,bits,ret=0;
1230Sstevel@tonic-gate 	BIGNUM *v,*rr;
1240Sstevel@tonic-gate 
125*2139Sjp161948 	if (BN_get_flags(p, BN_FLG_EXP_CONSTTIME) != 0)
126*2139Sjp161948 		{
127*2139Sjp161948 		/* BN_FLG_EXP_CONSTTIME only supported by BN_mod_exp_mont() */
128*2139Sjp161948 		BNerr(BN_F_BN_EXP,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
129*2139Sjp161948 		return -1;
130*2139Sjp161948 		}
131*2139Sjp161948 
1320Sstevel@tonic-gate 	BN_CTX_start(ctx);
1330Sstevel@tonic-gate 	if ((r == a) || (r == p))
1340Sstevel@tonic-gate 		rr = BN_CTX_get(ctx);
1350Sstevel@tonic-gate 	else
1360Sstevel@tonic-gate 		rr = r;
1370Sstevel@tonic-gate 	if ((v = BN_CTX_get(ctx)) == NULL) goto err;
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 	if (BN_copy(v,a) == NULL) goto err;
1400Sstevel@tonic-gate 	bits=BN_num_bits(p);
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate 	if (BN_is_odd(p))
1430Sstevel@tonic-gate 		{ if (BN_copy(rr,a) == NULL) goto err; }
1440Sstevel@tonic-gate 	else	{ if (!BN_one(rr)) goto err; }
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate 	for (i=1; i<bits; i++)
1470Sstevel@tonic-gate 		{
1480Sstevel@tonic-gate 		if (!BN_sqr(v,v,ctx)) goto err;
1490Sstevel@tonic-gate 		if (BN_is_bit_set(p,i))
1500Sstevel@tonic-gate 			{
1510Sstevel@tonic-gate 			if (!BN_mul(rr,rr,v,ctx)) goto err;
1520Sstevel@tonic-gate 			}
1530Sstevel@tonic-gate 		}
1540Sstevel@tonic-gate 	ret=1;
1550Sstevel@tonic-gate err:
1560Sstevel@tonic-gate 	if (r != rr) BN_copy(r,rr);
1570Sstevel@tonic-gate 	BN_CTX_end(ctx);
158*2139Sjp161948 	bn_check_top(r);
1590Sstevel@tonic-gate 	return(ret);
1600Sstevel@tonic-gate 	}
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate 
BN_mod_exp(BIGNUM * r,const BIGNUM * a,const BIGNUM * p,const BIGNUM * m,BN_CTX * ctx)1630Sstevel@tonic-gate int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
1640Sstevel@tonic-gate 	       BN_CTX *ctx)
1650Sstevel@tonic-gate 	{
1660Sstevel@tonic-gate 	int ret;
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 	bn_check_top(a);
1690Sstevel@tonic-gate 	bn_check_top(p);
1700Sstevel@tonic-gate 	bn_check_top(m);
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate 	/* For even modulus  m = 2^k*m_odd,  it might make sense to compute
1730Sstevel@tonic-gate 	 * a^p mod m_odd  and  a^p mod 2^k  separately (with Montgomery
1740Sstevel@tonic-gate 	 * exponentiation for the odd part), using appropriate exponent
1750Sstevel@tonic-gate 	 * reductions, and combine the results using the CRT.
1760Sstevel@tonic-gate 	 *
1770Sstevel@tonic-gate 	 * For now, we use Montgomery only if the modulus is odd; otherwise,
1780Sstevel@tonic-gate 	 * exponentiation using the reciprocal-based quick remaindering
1790Sstevel@tonic-gate 	 * algorithm is used.
1800Sstevel@tonic-gate 	 *
1810Sstevel@tonic-gate 	 * (Timing obtained with expspeed.c [computations  a^p mod m
1820Sstevel@tonic-gate 	 * where  a, p, m  are of the same length: 256, 512, 1024, 2048,
1830Sstevel@tonic-gate 	 * 4096, 8192 bits], compared to the running time of the
1840Sstevel@tonic-gate 	 * standard algorithm:
1850Sstevel@tonic-gate 	 *
1860Sstevel@tonic-gate 	 *   BN_mod_exp_mont   33 .. 40 %  [AMD K6-2, Linux, debug configuration]
1870Sstevel@tonic-gate          *                     55 .. 77 %  [UltraSparc processor, but
1880Sstevel@tonic-gate 	 *                                  debug-solaris-sparcv8-gcc conf.]
1890Sstevel@tonic-gate 	 *
1900Sstevel@tonic-gate 	 *   BN_mod_exp_recp   50 .. 70 %  [AMD K6-2, Linux, debug configuration]
1910Sstevel@tonic-gate 	 *                     62 .. 118 % [UltraSparc, debug-solaris-sparcv8-gcc]
1920Sstevel@tonic-gate 	 *
1930Sstevel@tonic-gate 	 * On the Sparc, BN_mod_exp_recp was faster than BN_mod_exp_mont
1940Sstevel@tonic-gate 	 * at 2048 and more bits, but at 512 and 1024 bits, it was
1950Sstevel@tonic-gate 	 * slower even than the standard algorithm!
1960Sstevel@tonic-gate 	 *
1970Sstevel@tonic-gate 	 * "Real" timings [linux-elf, solaris-sparcv9-gcc configurations]
1980Sstevel@tonic-gate 	 * should be obtained when the new Montgomery reduction code
1990Sstevel@tonic-gate 	 * has been integrated into OpenSSL.)
2000Sstevel@tonic-gate 	 */
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate #define MONT_MUL_MOD
2030Sstevel@tonic-gate #define MONT_EXP_WORD
2040Sstevel@tonic-gate #define RECP_MUL_MOD
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate #ifdef MONT_MUL_MOD
2070Sstevel@tonic-gate 	/* I have finally been able to take out this pre-condition of
2080Sstevel@tonic-gate 	 * the top bit being set.  It was caused by an error in BN_div
2090Sstevel@tonic-gate 	 * with negatives.  There was also another problem when for a^b%m
2100Sstevel@tonic-gate 	 * a >= m.  eay 07-May-97 */
2110Sstevel@tonic-gate /*	if ((m->d[m->top-1]&BN_TBIT) && BN_is_odd(m)) */
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate 	if (BN_is_odd(m))
2140Sstevel@tonic-gate 		{
2150Sstevel@tonic-gate #  ifdef MONT_EXP_WORD
216*2139Sjp161948 		if (a->top == 1 && !a->neg && (BN_get_flags(p, BN_FLG_EXP_CONSTTIME) == 0))
2170Sstevel@tonic-gate 			{
2180Sstevel@tonic-gate 			BN_ULONG A = a->d[0];
2190Sstevel@tonic-gate 			ret=BN_mod_exp_mont_word(r,A,p,m,ctx,NULL);
2200Sstevel@tonic-gate 			}
2210Sstevel@tonic-gate 		else
2220Sstevel@tonic-gate #  endif
2230Sstevel@tonic-gate 			ret=BN_mod_exp_mont(r,a,p,m,ctx,NULL);
2240Sstevel@tonic-gate 		}
2250Sstevel@tonic-gate 	else
2260Sstevel@tonic-gate #endif
2270Sstevel@tonic-gate #ifdef RECP_MUL_MOD
2280Sstevel@tonic-gate 		{ ret=BN_mod_exp_recp(r,a,p,m,ctx); }
2290Sstevel@tonic-gate #else
2300Sstevel@tonic-gate 		{ ret=BN_mod_exp_simple(r,a,p,m,ctx); }
2310Sstevel@tonic-gate #endif
2320Sstevel@tonic-gate 
233*2139Sjp161948 	bn_check_top(r);
2340Sstevel@tonic-gate 	return(ret);
2350Sstevel@tonic-gate 	}
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate 
BN_mod_exp_recp(BIGNUM * r,const BIGNUM * a,const BIGNUM * p,const BIGNUM * m,BN_CTX * ctx)2380Sstevel@tonic-gate int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
2390Sstevel@tonic-gate 		    const BIGNUM *m, BN_CTX *ctx)
2400Sstevel@tonic-gate 	{
2410Sstevel@tonic-gate 	int i,j,bits,ret=0,wstart,wend,window,wvalue;
242*2139Sjp161948 	int start=1;
2430Sstevel@tonic-gate 	BIGNUM *aa;
244*2139Sjp161948 	/* Table of variables obtained from 'ctx' */
245*2139Sjp161948 	BIGNUM *val[TABLE_SIZE];
2460Sstevel@tonic-gate 	BN_RECP_CTX recp;
2470Sstevel@tonic-gate 
248*2139Sjp161948 	if (BN_get_flags(p, BN_FLG_EXP_CONSTTIME) != 0)
249*2139Sjp161948 		{
250*2139Sjp161948 		/* BN_FLG_EXP_CONSTTIME only supported by BN_mod_exp_mont() */
251*2139Sjp161948 		BNerr(BN_F_BN_MOD_EXP_RECP,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
252*2139Sjp161948 		return -1;
253*2139Sjp161948 		}
254*2139Sjp161948 
2550Sstevel@tonic-gate 	bits=BN_num_bits(p);
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate 	if (bits == 0)
2580Sstevel@tonic-gate 		{
2590Sstevel@tonic-gate 		ret = BN_one(r);
2600Sstevel@tonic-gate 		return ret;
2610Sstevel@tonic-gate 		}
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	BN_CTX_start(ctx);
264*2139Sjp161948 	aa = BN_CTX_get(ctx);
265*2139Sjp161948 	val[0] = BN_CTX_get(ctx);
266*2139Sjp161948 	if(!aa || !val[0]) goto err;
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate 	BN_RECP_CTX_init(&recp);
2690Sstevel@tonic-gate 	if (m->neg)
2700Sstevel@tonic-gate 		{
2710Sstevel@tonic-gate 		/* ignore sign of 'm' */
2720Sstevel@tonic-gate 		if (!BN_copy(aa, m)) goto err;
2730Sstevel@tonic-gate 		aa->neg = 0;
2740Sstevel@tonic-gate 		if (BN_RECP_CTX_set(&recp,aa,ctx) <= 0) goto err;
2750Sstevel@tonic-gate 		}
2760Sstevel@tonic-gate 	else
2770Sstevel@tonic-gate 		{
2780Sstevel@tonic-gate 		if (BN_RECP_CTX_set(&recp,m,ctx) <= 0) goto err;
2790Sstevel@tonic-gate 		}
2800Sstevel@tonic-gate 
281*2139Sjp161948 	if (!BN_nnmod(val[0],a,m,ctx)) goto err;		/* 1 */
282*2139Sjp161948 	if (BN_is_zero(val[0]))
2830Sstevel@tonic-gate 		{
284*2139Sjp161948 		BN_zero(r);
285*2139Sjp161948 		ret = 1;
2860Sstevel@tonic-gate 		goto err;
2870Sstevel@tonic-gate 		}
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 	window = BN_window_bits_for_exponent_size(bits);
2900Sstevel@tonic-gate 	if (window > 1)
2910Sstevel@tonic-gate 		{
292*2139Sjp161948 		if (!BN_mod_mul_reciprocal(aa,val[0],val[0],&recp,ctx))
2930Sstevel@tonic-gate 			goto err;				/* 2 */
2940Sstevel@tonic-gate 		j=1<<(window-1);
2950Sstevel@tonic-gate 		for (i=1; i<j; i++)
2960Sstevel@tonic-gate 			{
297*2139Sjp161948 			if(((val[i] = BN_CTX_get(ctx)) == NULL) ||
298*2139Sjp161948 					!BN_mod_mul_reciprocal(val[i],val[i-1],
299*2139Sjp161948 						aa,&recp,ctx))
3000Sstevel@tonic-gate 				goto err;
3010Sstevel@tonic-gate 			}
3020Sstevel@tonic-gate 		}
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate 	start=1;	/* This is used to avoid multiplication etc
3050Sstevel@tonic-gate 			 * when there is only the value '1' in the
3060Sstevel@tonic-gate 			 * buffer. */
3070Sstevel@tonic-gate 	wvalue=0;	/* The 'value' of the window */
3080Sstevel@tonic-gate 	wstart=bits-1;	/* The top bit of the window */
3090Sstevel@tonic-gate 	wend=0;		/* The bottom bit of the window */
3100Sstevel@tonic-gate 
3110Sstevel@tonic-gate 	if (!BN_one(r)) goto err;
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate 	for (;;)
3140Sstevel@tonic-gate 		{
3150Sstevel@tonic-gate 		if (BN_is_bit_set(p,wstart) == 0)
3160Sstevel@tonic-gate 			{
3170Sstevel@tonic-gate 			if (!start)
3180Sstevel@tonic-gate 				if (!BN_mod_mul_reciprocal(r,r,r,&recp,ctx))
3190Sstevel@tonic-gate 				goto err;
3200Sstevel@tonic-gate 			if (wstart == 0) break;
3210Sstevel@tonic-gate 			wstart--;
3220Sstevel@tonic-gate 			continue;
3230Sstevel@tonic-gate 			}
3240Sstevel@tonic-gate 		/* We now have wstart on a 'set' bit, we now need to work out
3250Sstevel@tonic-gate 		 * how bit a window to do.  To do this we need to scan
3260Sstevel@tonic-gate 		 * forward until the last set bit before the end of the
3270Sstevel@tonic-gate 		 * window */
3280Sstevel@tonic-gate 		j=wstart;
3290Sstevel@tonic-gate 		wvalue=1;
3300Sstevel@tonic-gate 		wend=0;
3310Sstevel@tonic-gate 		for (i=1; i<window; i++)
3320Sstevel@tonic-gate 			{
3330Sstevel@tonic-gate 			if (wstart-i < 0) break;
3340Sstevel@tonic-gate 			if (BN_is_bit_set(p,wstart-i))
3350Sstevel@tonic-gate 				{
3360Sstevel@tonic-gate 				wvalue<<=(i-wend);
3370Sstevel@tonic-gate 				wvalue|=1;
3380Sstevel@tonic-gate 				wend=i;
3390Sstevel@tonic-gate 				}
3400Sstevel@tonic-gate 			}
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate 		/* wend is the size of the current window */
3430Sstevel@tonic-gate 		j=wend+1;
3440Sstevel@tonic-gate 		/* add the 'bytes above' */
3450Sstevel@tonic-gate 		if (!start)
3460Sstevel@tonic-gate 			for (i=0; i<j; i++)
3470Sstevel@tonic-gate 				{
3480Sstevel@tonic-gate 				if (!BN_mod_mul_reciprocal(r,r,r,&recp,ctx))
3490Sstevel@tonic-gate 					goto err;
3500Sstevel@tonic-gate 				}
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate 		/* wvalue will be an odd number < 2^window */
353*2139Sjp161948 		if (!BN_mod_mul_reciprocal(r,r,val[wvalue>>1],&recp,ctx))
3540Sstevel@tonic-gate 			goto err;
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate 		/* move the 'window' down further */
3570Sstevel@tonic-gate 		wstart-=wend+1;
3580Sstevel@tonic-gate 		wvalue=0;
3590Sstevel@tonic-gate 		start=0;
3600Sstevel@tonic-gate 		if (wstart < 0) break;
3610Sstevel@tonic-gate 		}
3620Sstevel@tonic-gate 	ret=1;
3630Sstevel@tonic-gate err:
3640Sstevel@tonic-gate 	BN_CTX_end(ctx);
3650Sstevel@tonic-gate 	BN_RECP_CTX_free(&recp);
366*2139Sjp161948 	bn_check_top(r);
3670Sstevel@tonic-gate 	return(ret);
3680Sstevel@tonic-gate 	}
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate 
BN_mod_exp_mont(BIGNUM * rr,const BIGNUM * a,const BIGNUM * p,const BIGNUM * m,BN_CTX * ctx,BN_MONT_CTX * in_mont)3710Sstevel@tonic-gate int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
3720Sstevel@tonic-gate 		    const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
3730Sstevel@tonic-gate 	{
3740Sstevel@tonic-gate 	int i,j,bits,ret=0,wstart,wend,window,wvalue;
375*2139Sjp161948 	int start=1;
3760Sstevel@tonic-gate 	BIGNUM *d,*r;
3770Sstevel@tonic-gate 	const BIGNUM *aa;
378*2139Sjp161948 	/* Table of variables obtained from 'ctx' */
379*2139Sjp161948 	BIGNUM *val[TABLE_SIZE];
3800Sstevel@tonic-gate 	BN_MONT_CTX *mont=NULL;
3810Sstevel@tonic-gate 
382*2139Sjp161948 	if (BN_get_flags(p, BN_FLG_EXP_CONSTTIME) != 0)
383*2139Sjp161948 		{
384*2139Sjp161948 		return BN_mod_exp_mont_consttime(rr, a, p, m, ctx, in_mont);
385*2139Sjp161948 		}
386*2139Sjp161948 
3870Sstevel@tonic-gate 	bn_check_top(a);
3880Sstevel@tonic-gate 	bn_check_top(p);
3890Sstevel@tonic-gate 	bn_check_top(m);
3900Sstevel@tonic-gate 
391*2139Sjp161948 	if (!BN_is_odd(m))
3920Sstevel@tonic-gate 		{
3930Sstevel@tonic-gate 		BNerr(BN_F_BN_MOD_EXP_MONT,BN_R_CALLED_WITH_EVEN_MODULUS);
3940Sstevel@tonic-gate 		return(0);
3950Sstevel@tonic-gate 		}
3960Sstevel@tonic-gate 	bits=BN_num_bits(p);
3970Sstevel@tonic-gate 	if (bits == 0)
3980Sstevel@tonic-gate 		{
3990Sstevel@tonic-gate 		ret = BN_one(rr);
4000Sstevel@tonic-gate 		return ret;
4010Sstevel@tonic-gate 		}
4020Sstevel@tonic-gate 
4030Sstevel@tonic-gate 	BN_CTX_start(ctx);
4040Sstevel@tonic-gate 	d = BN_CTX_get(ctx);
4050Sstevel@tonic-gate 	r = BN_CTX_get(ctx);
406*2139Sjp161948 	val[0] = BN_CTX_get(ctx);
407*2139Sjp161948 	if (!d || !r || !val[0]) goto err;
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate 	/* If this is not done, things will break in the montgomery
4100Sstevel@tonic-gate 	 * part */
4110Sstevel@tonic-gate 
4120Sstevel@tonic-gate 	if (in_mont != NULL)
4130Sstevel@tonic-gate 		mont=in_mont;
4140Sstevel@tonic-gate 	else
4150Sstevel@tonic-gate 		{
4160Sstevel@tonic-gate 		if ((mont=BN_MONT_CTX_new()) == NULL) goto err;
4170Sstevel@tonic-gate 		if (!BN_MONT_CTX_set(mont,m,ctx)) goto err;
4180Sstevel@tonic-gate 		}
4190Sstevel@tonic-gate 
4200Sstevel@tonic-gate 	if (a->neg || BN_ucmp(a,m) >= 0)
4210Sstevel@tonic-gate 		{
422*2139Sjp161948 		if (!BN_nnmod(val[0],a,m,ctx))
4230Sstevel@tonic-gate 			goto err;
424*2139Sjp161948 		aa= val[0];
4250Sstevel@tonic-gate 		}
4260Sstevel@tonic-gate 	else
4270Sstevel@tonic-gate 		aa=a;
4280Sstevel@tonic-gate 	if (BN_is_zero(aa))
4290Sstevel@tonic-gate 		{
430*2139Sjp161948 		BN_zero(rr);
431*2139Sjp161948 		ret = 1;
4320Sstevel@tonic-gate 		goto err;
4330Sstevel@tonic-gate 		}
434*2139Sjp161948 	if (!BN_to_montgomery(val[0],aa,mont,ctx)) goto err; /* 1 */
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate 	window = BN_window_bits_for_exponent_size(bits);
4370Sstevel@tonic-gate 	if (window > 1)
4380Sstevel@tonic-gate 		{
439*2139Sjp161948 		if (!BN_mod_mul_montgomery(d,val[0],val[0],mont,ctx)) goto err; /* 2 */
4400Sstevel@tonic-gate 		j=1<<(window-1);
4410Sstevel@tonic-gate 		for (i=1; i<j; i++)
4420Sstevel@tonic-gate 			{
443*2139Sjp161948 			if(((val[i] = BN_CTX_get(ctx)) == NULL) ||
444*2139Sjp161948 					!BN_mod_mul_montgomery(val[i],val[i-1],
445*2139Sjp161948 						d,mont,ctx))
4460Sstevel@tonic-gate 				goto err;
4470Sstevel@tonic-gate 			}
4480Sstevel@tonic-gate 		}
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate 	start=1;	/* This is used to avoid multiplication etc
4510Sstevel@tonic-gate 			 * when there is only the value '1' in the
4520Sstevel@tonic-gate 			 * buffer. */
4530Sstevel@tonic-gate 	wvalue=0;	/* The 'value' of the window */
4540Sstevel@tonic-gate 	wstart=bits-1;	/* The top bit of the window */
4550Sstevel@tonic-gate 	wend=0;		/* The bottom bit of the window */
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate 	if (!BN_to_montgomery(r,BN_value_one(),mont,ctx)) goto err;
4580Sstevel@tonic-gate 	for (;;)
4590Sstevel@tonic-gate 		{
4600Sstevel@tonic-gate 		if (BN_is_bit_set(p,wstart) == 0)
4610Sstevel@tonic-gate 			{
4620Sstevel@tonic-gate 			if (!start)
4630Sstevel@tonic-gate 				{
4640Sstevel@tonic-gate 				if (!BN_mod_mul_montgomery(r,r,r,mont,ctx))
4650Sstevel@tonic-gate 				goto err;
4660Sstevel@tonic-gate 				}
4670Sstevel@tonic-gate 			if (wstart == 0) break;
4680Sstevel@tonic-gate 			wstart--;
4690Sstevel@tonic-gate 			continue;
4700Sstevel@tonic-gate 			}
4710Sstevel@tonic-gate 		/* We now have wstart on a 'set' bit, we now need to work out
4720Sstevel@tonic-gate 		 * how bit a window to do.  To do this we need to scan
4730Sstevel@tonic-gate 		 * forward until the last set bit before the end of the
4740Sstevel@tonic-gate 		 * window */
4750Sstevel@tonic-gate 		j=wstart;
4760Sstevel@tonic-gate 		wvalue=1;
4770Sstevel@tonic-gate 		wend=0;
4780Sstevel@tonic-gate 		for (i=1; i<window; i++)
4790Sstevel@tonic-gate 			{
4800Sstevel@tonic-gate 			if (wstart-i < 0) break;
4810Sstevel@tonic-gate 			if (BN_is_bit_set(p,wstart-i))
4820Sstevel@tonic-gate 				{
4830Sstevel@tonic-gate 				wvalue<<=(i-wend);
4840Sstevel@tonic-gate 				wvalue|=1;
4850Sstevel@tonic-gate 				wend=i;
4860Sstevel@tonic-gate 				}
4870Sstevel@tonic-gate 			}
4880Sstevel@tonic-gate 
4890Sstevel@tonic-gate 		/* wend is the size of the current window */
4900Sstevel@tonic-gate 		j=wend+1;
4910Sstevel@tonic-gate 		/* add the 'bytes above' */
4920Sstevel@tonic-gate 		if (!start)
4930Sstevel@tonic-gate 			for (i=0; i<j; i++)
4940Sstevel@tonic-gate 				{
4950Sstevel@tonic-gate 				if (!BN_mod_mul_montgomery(r,r,r,mont,ctx))
4960Sstevel@tonic-gate 					goto err;
4970Sstevel@tonic-gate 				}
4980Sstevel@tonic-gate 
4990Sstevel@tonic-gate 		/* wvalue will be an odd number < 2^window */
500*2139Sjp161948 		if (!BN_mod_mul_montgomery(r,r,val[wvalue>>1],mont,ctx))
5010Sstevel@tonic-gate 			goto err;
5020Sstevel@tonic-gate 
5030Sstevel@tonic-gate 		/* move the 'window' down further */
5040Sstevel@tonic-gate 		wstart-=wend+1;
5050Sstevel@tonic-gate 		wvalue=0;
5060Sstevel@tonic-gate 		start=0;
5070Sstevel@tonic-gate 		if (wstart < 0) break;
5080Sstevel@tonic-gate 		}
5090Sstevel@tonic-gate 	if (!BN_from_montgomery(rr,r,mont,ctx)) goto err;
5100Sstevel@tonic-gate 	ret=1;
5110Sstevel@tonic-gate err:
5120Sstevel@tonic-gate 	if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont);
5130Sstevel@tonic-gate 	BN_CTX_end(ctx);
514*2139Sjp161948 	bn_check_top(rr);
515*2139Sjp161948 	return(ret);
516*2139Sjp161948 	}
517*2139Sjp161948 
518*2139Sjp161948 
519*2139Sjp161948 /* BN_mod_exp_mont_consttime() stores the precomputed powers in a specific layout
520*2139Sjp161948  * so that accessing any of these table values shows the same access pattern as far
521*2139Sjp161948  * as cache lines are concerned.  The following functions are used to transfer a BIGNUM
522*2139Sjp161948  * from/to that table. */
523*2139Sjp161948 
MOD_EXP_CTIME_COPY_TO_PREBUF(BIGNUM * b,int top,unsigned char * buf,int idx,int width)524*2139Sjp161948 static int MOD_EXP_CTIME_COPY_TO_PREBUF(BIGNUM *b, int top, unsigned char *buf, int idx, int width)
525*2139Sjp161948 	{
526*2139Sjp161948 	size_t i, j;
527*2139Sjp161948 
528*2139Sjp161948 	if (bn_wexpand(b, top) == NULL)
529*2139Sjp161948 		return 0;
530*2139Sjp161948 	while (b->top < top)
531*2139Sjp161948 		{
532*2139Sjp161948 		b->d[b->top++] = 0;
533*2139Sjp161948 		}
534*2139Sjp161948 
535*2139Sjp161948 	for (i = 0, j=idx; i < top * sizeof b->d[0]; i++, j+=width)
536*2139Sjp161948 		{
537*2139Sjp161948 		buf[j] = ((unsigned char*)b->d)[i];
538*2139Sjp161948 		}
539*2139Sjp161948 
540*2139Sjp161948 	bn_correct_top(b);
541*2139Sjp161948 	return 1;
542*2139Sjp161948 	}
543*2139Sjp161948 
MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM * b,int top,unsigned char * buf,int idx,int width)544*2139Sjp161948 static int MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top, unsigned char *buf, int idx, int width)
545*2139Sjp161948 	{
546*2139Sjp161948 	size_t i, j;
547*2139Sjp161948 
548*2139Sjp161948 	if (bn_wexpand(b, top) == NULL)
549*2139Sjp161948 		return 0;
550*2139Sjp161948 
551*2139Sjp161948 	for (i=0, j=idx; i < top * sizeof b->d[0]; i++, j+=width)
552*2139Sjp161948 		{
553*2139Sjp161948 		((unsigned char*)b->d)[i] = buf[j];
554*2139Sjp161948 		}
555*2139Sjp161948 
556*2139Sjp161948 	b->top = top;
557*2139Sjp161948 	bn_correct_top(b);
558*2139Sjp161948 	return 1;
559*2139Sjp161948 	}
560*2139Sjp161948 
561*2139Sjp161948 /* Given a pointer value, compute the next address that is a cache line multiple. */
562*2139Sjp161948 #define MOD_EXP_CTIME_ALIGN(x_) \
563*2139Sjp161948 	((unsigned char*)(x_) + (MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH - (((BN_ULONG)(x_)) & (MOD_EXP_CTIME_MIN_CACHE_LINE_MASK))))
564*2139Sjp161948 
565*2139Sjp161948 /* This variant of BN_mod_exp_mont() uses fixed windows and the special
566*2139Sjp161948  * precomputation memory layout to limit data-dependency to a minimum
567*2139Sjp161948  * to protect secret exponents (cf. the hyper-threading timing attacks
568*2139Sjp161948  * pointed out by Colin Percival,
569*2139Sjp161948  * http://www.daemonology.net/hyperthreading-considered-harmful/)
570*2139Sjp161948  */
BN_mod_exp_mont_consttime(BIGNUM * rr,const BIGNUM * a,const BIGNUM * p,const BIGNUM * m,BN_CTX * ctx,BN_MONT_CTX * in_mont)571*2139Sjp161948 int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
572*2139Sjp161948 		    const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
573*2139Sjp161948 	{
574*2139Sjp161948 	int i,bits,ret=0,idx,window,wvalue;
575*2139Sjp161948 	int top;
576*2139Sjp161948  	BIGNUM *r;
577*2139Sjp161948 	const BIGNUM *aa;
578*2139Sjp161948 	BN_MONT_CTX *mont=NULL;
579*2139Sjp161948 
580*2139Sjp161948 	int numPowers;
581*2139Sjp161948 	unsigned char *powerbufFree=NULL;
582*2139Sjp161948 	int powerbufLen = 0;
583*2139Sjp161948 	unsigned char *powerbuf=NULL;
584*2139Sjp161948 	BIGNUM *computeTemp=NULL, *am=NULL;
585*2139Sjp161948 
586*2139Sjp161948 	bn_check_top(a);
587*2139Sjp161948 	bn_check_top(p);
588*2139Sjp161948 	bn_check_top(m);
589*2139Sjp161948 
590*2139Sjp161948 	top = m->top;
591*2139Sjp161948 
592*2139Sjp161948 	if (!(m->d[0] & 1))
593*2139Sjp161948 		{
594*2139Sjp161948 		BNerr(BN_F_BN_MOD_EXP_MONT_CONSTTIME,BN_R_CALLED_WITH_EVEN_MODULUS);
595*2139Sjp161948 		return(0);
596*2139Sjp161948 		}
597*2139Sjp161948 	bits=BN_num_bits(p);
598*2139Sjp161948 	if (bits == 0)
599*2139Sjp161948 		{
600*2139Sjp161948 		ret = BN_one(rr);
601*2139Sjp161948 		return ret;
602*2139Sjp161948 		}
603*2139Sjp161948 
604*2139Sjp161948  	/* Initialize BIGNUM context and allocate intermediate result */
605*2139Sjp161948 	BN_CTX_start(ctx);
606*2139Sjp161948 	r = BN_CTX_get(ctx);
607*2139Sjp161948 	if (r == NULL) goto err;
608*2139Sjp161948 
609*2139Sjp161948 	/* Allocate a montgomery context if it was not supplied by the caller.
610*2139Sjp161948 	 * If this is not done, things will break in the montgomery part.
611*2139Sjp161948  	 */
612*2139Sjp161948 	if (in_mont != NULL)
613*2139Sjp161948 		mont=in_mont;
614*2139Sjp161948 	else
615*2139Sjp161948 		{
616*2139Sjp161948 		if ((mont=BN_MONT_CTX_new()) == NULL) goto err;
617*2139Sjp161948 		if (!BN_MONT_CTX_set(mont,m,ctx)) goto err;
618*2139Sjp161948 		}
619*2139Sjp161948 
620*2139Sjp161948 	/* Get the window size to use with size of p. */
621*2139Sjp161948 	window = BN_window_bits_for_ctime_exponent_size(bits);
622*2139Sjp161948 
623*2139Sjp161948 	/* Allocate a buffer large enough to hold all of the pre-computed
624*2139Sjp161948 	 * powers of a.
625*2139Sjp161948 	 */
626*2139Sjp161948 	numPowers = 1 << window;
627*2139Sjp161948 	powerbufLen = sizeof(m->d[0])*top*numPowers;
628*2139Sjp161948 	if ((powerbufFree=(unsigned char*)OPENSSL_malloc(powerbufLen+MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH)) == NULL)
629*2139Sjp161948 		goto err;
630*2139Sjp161948 
631*2139Sjp161948 	powerbuf = MOD_EXP_CTIME_ALIGN(powerbufFree);
632*2139Sjp161948 	memset(powerbuf, 0, powerbufLen);
633*2139Sjp161948 
634*2139Sjp161948  	/* Initialize the intermediate result. Do this early to save double conversion,
635*2139Sjp161948 	 * once each for a^0 and intermediate result.
636*2139Sjp161948 	 */
637*2139Sjp161948  	if (!BN_to_montgomery(r,BN_value_one(),mont,ctx)) goto err;
638*2139Sjp161948 	if (!MOD_EXP_CTIME_COPY_TO_PREBUF(r, top, powerbuf, 0, numPowers)) goto err;
639*2139Sjp161948 
640*2139Sjp161948 	/* Initialize computeTemp as a^1 with montgomery precalcs */
641*2139Sjp161948 	computeTemp = BN_CTX_get(ctx);
642*2139Sjp161948 	am = BN_CTX_get(ctx);
643*2139Sjp161948 	if (computeTemp==NULL || am==NULL) goto err;
644*2139Sjp161948 
645*2139Sjp161948 	if (a->neg || BN_ucmp(a,m) >= 0)
646*2139Sjp161948 		{
647*2139Sjp161948 		if (!BN_mod(am,a,m,ctx))
648*2139Sjp161948 			goto err;
649*2139Sjp161948 		aa= am;
650*2139Sjp161948 		}
651*2139Sjp161948 	else
652*2139Sjp161948 		aa=a;
653*2139Sjp161948 	if (!BN_to_montgomery(am,aa,mont,ctx)) goto err;
654*2139Sjp161948 	if (!BN_copy(computeTemp, am)) goto err;
655*2139Sjp161948 	if (!MOD_EXP_CTIME_COPY_TO_PREBUF(am, top, powerbuf, 1, numPowers)) goto err;
656*2139Sjp161948 
657*2139Sjp161948 	/* If the window size is greater than 1, then calculate
658*2139Sjp161948 	 * val[i=2..2^winsize-1]. Powers are computed as a*a^(i-1)
659*2139Sjp161948 	 * (even powers could instead be computed as (a^(i/2))^2
660*2139Sjp161948 	 * to use the slight performance advantage of sqr over mul).
661*2139Sjp161948 	 */
662*2139Sjp161948 	if (window > 1)
663*2139Sjp161948 		{
664*2139Sjp161948 		for (i=2; i<numPowers; i++)
665*2139Sjp161948 			{
666*2139Sjp161948 			/* Calculate a^i = a^(i-1) * a */
667*2139Sjp161948 			if (!BN_mod_mul_montgomery(computeTemp,am,computeTemp,mont,ctx))
668*2139Sjp161948 				goto err;
669*2139Sjp161948 			if (!MOD_EXP_CTIME_COPY_TO_PREBUF(computeTemp, top, powerbuf, i, numPowers)) goto err;
670*2139Sjp161948 			}
671*2139Sjp161948 		}
672*2139Sjp161948 
673*2139Sjp161948  	/* Adjust the number of bits up to a multiple of the window size.
674*2139Sjp161948  	 * If the exponent length is not a multiple of the window size, then
675*2139Sjp161948  	 * this pads the most significant bits with zeros to normalize the
676*2139Sjp161948  	 * scanning loop to there's no special cases.
677*2139Sjp161948  	 *
678*2139Sjp161948  	 * * NOTE: Making the window size a power of two less than the native
679*2139Sjp161948 	 * * word size ensures that the padded bits won't go past the last
680*2139Sjp161948  	 * * word in the internal BIGNUM structure. Going past the end will
681*2139Sjp161948  	 * * still produce the correct result, but causes a different branch
682*2139Sjp161948  	 * * to be taken in the BN_is_bit_set function.
683*2139Sjp161948  	 */
684*2139Sjp161948  	bits = ((bits+window-1)/window)*window;
685*2139Sjp161948  	idx=bits-1;	/* The top bit of the window */
686*2139Sjp161948 
687*2139Sjp161948  	/* Scan the exponent one window at a time starting from the most
688*2139Sjp161948  	 * significant bits.
689*2139Sjp161948  	 */
690*2139Sjp161948  	while (idx >= 0)
691*2139Sjp161948   		{
692*2139Sjp161948  		wvalue=0; /* The 'value' of the window */
693*2139Sjp161948 
694*2139Sjp161948  		/* Scan the window, squaring the result as we go */
695*2139Sjp161948  		for (i=0; i<window; i++,idx--)
696*2139Sjp161948  			{
697*2139Sjp161948 			if (!BN_mod_mul_montgomery(r,r,r,mont,ctx))	goto err;
698*2139Sjp161948 			wvalue = (wvalue<<1)+BN_is_bit_set(p,idx);
699*2139Sjp161948   			}
700*2139Sjp161948 
701*2139Sjp161948 		/* Fetch the appropriate pre-computed value from the pre-buf */
702*2139Sjp161948 		if (!MOD_EXP_CTIME_COPY_FROM_PREBUF(computeTemp, top, powerbuf, wvalue, numPowers)) goto err;
703*2139Sjp161948 
704*2139Sjp161948  		/* Multiply the result into the intermediate result */
705*2139Sjp161948  		if (!BN_mod_mul_montgomery(r,r,computeTemp,mont,ctx)) goto err;
706*2139Sjp161948   		}
707*2139Sjp161948 
708*2139Sjp161948  	/* Convert the final result from montgomery to standard format */
709*2139Sjp161948 	if (!BN_from_montgomery(rr,r,mont,ctx)) goto err;
710*2139Sjp161948 	ret=1;
711*2139Sjp161948 err:
712*2139Sjp161948 	if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont);
713*2139Sjp161948 	if (powerbuf!=NULL)
714*2139Sjp161948 		{
715*2139Sjp161948 		OPENSSL_cleanse(powerbuf,powerbufLen);
716*2139Sjp161948 		OPENSSL_free(powerbufFree);
717*2139Sjp161948 		}
718*2139Sjp161948  	if (am!=NULL) BN_clear(am);
719*2139Sjp161948  	if (computeTemp!=NULL) BN_clear(computeTemp);
720*2139Sjp161948 	BN_CTX_end(ctx);
7210Sstevel@tonic-gate 	return(ret);
7220Sstevel@tonic-gate 	}
7230Sstevel@tonic-gate 
BN_mod_exp_mont_word(BIGNUM * rr,BN_ULONG a,const BIGNUM * p,const BIGNUM * m,BN_CTX * ctx,BN_MONT_CTX * in_mont)7240Sstevel@tonic-gate int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
7250Sstevel@tonic-gate                          const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
7260Sstevel@tonic-gate 	{
7270Sstevel@tonic-gate 	BN_MONT_CTX *mont = NULL;
7280Sstevel@tonic-gate 	int b, bits, ret=0;
7290Sstevel@tonic-gate 	int r_is_one;
7300Sstevel@tonic-gate 	BN_ULONG w, next_w;
7310Sstevel@tonic-gate 	BIGNUM *d, *r, *t;
7320Sstevel@tonic-gate 	BIGNUM *swap_tmp;
7330Sstevel@tonic-gate #define BN_MOD_MUL_WORD(r, w, m) \
7340Sstevel@tonic-gate 		(BN_mul_word(r, (w)) && \
7350Sstevel@tonic-gate 		(/* BN_ucmp(r, (m)) < 0 ? 1 :*/  \
7360Sstevel@tonic-gate 			(BN_mod(t, r, m, ctx) && (swap_tmp = r, r = t, t = swap_tmp, 1))))
7370Sstevel@tonic-gate 		/* BN_MOD_MUL_WORD is only used with 'w' large,
7380Sstevel@tonic-gate 		 * so the BN_ucmp test is probably more overhead
7390Sstevel@tonic-gate 		 * than always using BN_mod (which uses BN_copy if
7400Sstevel@tonic-gate 		 * a similar test returns true). */
7410Sstevel@tonic-gate 		/* We can use BN_mod and do not need BN_nnmod because our
7420Sstevel@tonic-gate 		 * accumulator is never negative (the result of BN_mod does
7430Sstevel@tonic-gate 		 * not depend on the sign of the modulus).
7440Sstevel@tonic-gate 		 */
7450Sstevel@tonic-gate #define BN_TO_MONTGOMERY_WORD(r, w, mont) \
7460Sstevel@tonic-gate 		(BN_set_word(r, (w)) && BN_to_montgomery(r, r, (mont), ctx))
7470Sstevel@tonic-gate 
748*2139Sjp161948 	if (BN_get_flags(p, BN_FLG_EXP_CONSTTIME) != 0)
749*2139Sjp161948 		{
750*2139Sjp161948 		/* BN_FLG_EXP_CONSTTIME only supported by BN_mod_exp_mont() */
751*2139Sjp161948 		BNerr(BN_F_BN_MOD_EXP_MONT_WORD,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
752*2139Sjp161948 		return -1;
753*2139Sjp161948 		}
754*2139Sjp161948 
7550Sstevel@tonic-gate 	bn_check_top(p);
7560Sstevel@tonic-gate 	bn_check_top(m);
7570Sstevel@tonic-gate 
758*2139Sjp161948 	if (!BN_is_odd(m))
7590Sstevel@tonic-gate 		{
7600Sstevel@tonic-gate 		BNerr(BN_F_BN_MOD_EXP_MONT_WORD,BN_R_CALLED_WITH_EVEN_MODULUS);
7610Sstevel@tonic-gate 		return(0);
7620Sstevel@tonic-gate 		}
7630Sstevel@tonic-gate 	if (m->top == 1)
7640Sstevel@tonic-gate 		a %= m->d[0]; /* make sure that 'a' is reduced */
7650Sstevel@tonic-gate 
7660Sstevel@tonic-gate 	bits = BN_num_bits(p);
7670Sstevel@tonic-gate 	if (bits == 0)
7680Sstevel@tonic-gate 		{
7690Sstevel@tonic-gate 		ret = BN_one(rr);
7700Sstevel@tonic-gate 		return ret;
7710Sstevel@tonic-gate 		}
7720Sstevel@tonic-gate 	if (a == 0)
7730Sstevel@tonic-gate 		{
774*2139Sjp161948 		BN_zero(rr);
775*2139Sjp161948 		ret = 1;
7760Sstevel@tonic-gate 		return ret;
7770Sstevel@tonic-gate 		}
7780Sstevel@tonic-gate 
7790Sstevel@tonic-gate 	BN_CTX_start(ctx);
7800Sstevel@tonic-gate 	d = BN_CTX_get(ctx);
7810Sstevel@tonic-gate 	r = BN_CTX_get(ctx);
7820Sstevel@tonic-gate 	t = BN_CTX_get(ctx);
7830Sstevel@tonic-gate 	if (d == NULL || r == NULL || t == NULL) goto err;
7840Sstevel@tonic-gate 
7850Sstevel@tonic-gate 	if (in_mont != NULL)
7860Sstevel@tonic-gate 		mont=in_mont;
7870Sstevel@tonic-gate 	else
7880Sstevel@tonic-gate 		{
7890Sstevel@tonic-gate 		if ((mont = BN_MONT_CTX_new()) == NULL) goto err;
7900Sstevel@tonic-gate 		if (!BN_MONT_CTX_set(mont, m, ctx)) goto err;
7910Sstevel@tonic-gate 		}
7920Sstevel@tonic-gate 
7930Sstevel@tonic-gate 	r_is_one = 1; /* except for Montgomery factor */
7940Sstevel@tonic-gate 
7950Sstevel@tonic-gate 	/* bits-1 >= 0 */
7960Sstevel@tonic-gate 
7970Sstevel@tonic-gate 	/* The result is accumulated in the product r*w. */
7980Sstevel@tonic-gate 	w = a; /* bit 'bits-1' of 'p' is always set */
7990Sstevel@tonic-gate 	for (b = bits-2; b >= 0; b--)
8000Sstevel@tonic-gate 		{
8010Sstevel@tonic-gate 		/* First, square r*w. */
8020Sstevel@tonic-gate 		next_w = w*w;
8030Sstevel@tonic-gate 		if ((next_w/w) != w) /* overflow */
8040Sstevel@tonic-gate 			{
8050Sstevel@tonic-gate 			if (r_is_one)
8060Sstevel@tonic-gate 				{
8070Sstevel@tonic-gate 				if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) goto err;
8080Sstevel@tonic-gate 				r_is_one = 0;
8090Sstevel@tonic-gate 				}
8100Sstevel@tonic-gate 			else
8110Sstevel@tonic-gate 				{
8120Sstevel@tonic-gate 				if (!BN_MOD_MUL_WORD(r, w, m)) goto err;
8130Sstevel@tonic-gate 				}
8140Sstevel@tonic-gate 			next_w = 1;
8150Sstevel@tonic-gate 			}
8160Sstevel@tonic-gate 		w = next_w;
8170Sstevel@tonic-gate 		if (!r_is_one)
8180Sstevel@tonic-gate 			{
8190Sstevel@tonic-gate 			if (!BN_mod_mul_montgomery(r, r, r, mont, ctx)) goto err;
8200Sstevel@tonic-gate 			}
8210Sstevel@tonic-gate 
8220Sstevel@tonic-gate 		/* Second, multiply r*w by 'a' if exponent bit is set. */
8230Sstevel@tonic-gate 		if (BN_is_bit_set(p, b))
8240Sstevel@tonic-gate 			{
8250Sstevel@tonic-gate 			next_w = w*a;
8260Sstevel@tonic-gate 			if ((next_w/a) != w) /* overflow */
8270Sstevel@tonic-gate 				{
8280Sstevel@tonic-gate 				if (r_is_one)
8290Sstevel@tonic-gate 					{
8300Sstevel@tonic-gate 					if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) goto err;
8310Sstevel@tonic-gate 					r_is_one = 0;
8320Sstevel@tonic-gate 					}
8330Sstevel@tonic-gate 				else
8340Sstevel@tonic-gate 					{
8350Sstevel@tonic-gate 					if (!BN_MOD_MUL_WORD(r, w, m)) goto err;
8360Sstevel@tonic-gate 					}
8370Sstevel@tonic-gate 				next_w = a;
8380Sstevel@tonic-gate 				}
8390Sstevel@tonic-gate 			w = next_w;
8400Sstevel@tonic-gate 			}
8410Sstevel@tonic-gate 		}
8420Sstevel@tonic-gate 
8430Sstevel@tonic-gate 	/* Finally, set r:=r*w. */
8440Sstevel@tonic-gate 	if (w != 1)
8450Sstevel@tonic-gate 		{
8460Sstevel@tonic-gate 		if (r_is_one)
8470Sstevel@tonic-gate 			{
8480Sstevel@tonic-gate 			if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) goto err;
8490Sstevel@tonic-gate 			r_is_one = 0;
8500Sstevel@tonic-gate 			}
8510Sstevel@tonic-gate 		else
8520Sstevel@tonic-gate 			{
8530Sstevel@tonic-gate 			if (!BN_MOD_MUL_WORD(r, w, m)) goto err;
8540Sstevel@tonic-gate 			}
8550Sstevel@tonic-gate 		}
8560Sstevel@tonic-gate 
8570Sstevel@tonic-gate 	if (r_is_one) /* can happen only if a == 1*/
8580Sstevel@tonic-gate 		{
8590Sstevel@tonic-gate 		if (!BN_one(rr)) goto err;
8600Sstevel@tonic-gate 		}
8610Sstevel@tonic-gate 	else
8620Sstevel@tonic-gate 		{
8630Sstevel@tonic-gate 		if (!BN_from_montgomery(rr, r, mont, ctx)) goto err;
8640Sstevel@tonic-gate 		}
8650Sstevel@tonic-gate 	ret = 1;
8660Sstevel@tonic-gate err:
8670Sstevel@tonic-gate 	if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont);
8680Sstevel@tonic-gate 	BN_CTX_end(ctx);
869*2139Sjp161948 	bn_check_top(rr);
8700Sstevel@tonic-gate 	return(ret);
8710Sstevel@tonic-gate 	}
8720Sstevel@tonic-gate 
8730Sstevel@tonic-gate 
8740Sstevel@tonic-gate /* The old fallback, simple version :-) */
BN_mod_exp_simple(BIGNUM * r,const BIGNUM * a,const BIGNUM * p,const BIGNUM * m,BN_CTX * ctx)875*2139Sjp161948 int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
876*2139Sjp161948 		const BIGNUM *m, BN_CTX *ctx)
8770Sstevel@tonic-gate 	{
878*2139Sjp161948 	int i,j,bits,ret=0,wstart,wend,window,wvalue;
8790Sstevel@tonic-gate 	int start=1;
8800Sstevel@tonic-gate 	BIGNUM *d;
881*2139Sjp161948 	/* Table of variables obtained from 'ctx' */
882*2139Sjp161948 	BIGNUM *val[TABLE_SIZE];
883*2139Sjp161948 
884*2139Sjp161948 	if (BN_get_flags(p, BN_FLG_EXP_CONSTTIME) != 0)
885*2139Sjp161948 		{
886*2139Sjp161948 		/* BN_FLG_EXP_CONSTTIME only supported by BN_mod_exp_mont() */
887*2139Sjp161948 		BNerr(BN_F_BN_MOD_EXP_SIMPLE,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
888*2139Sjp161948 		return -1;
889*2139Sjp161948 		}
8900Sstevel@tonic-gate 
8910Sstevel@tonic-gate 	bits=BN_num_bits(p);
8920Sstevel@tonic-gate 
8930Sstevel@tonic-gate 	if (bits == 0)
8940Sstevel@tonic-gate 		{
8950Sstevel@tonic-gate 		ret = BN_one(r);
8960Sstevel@tonic-gate 		return ret;
8970Sstevel@tonic-gate 		}
8980Sstevel@tonic-gate 
8990Sstevel@tonic-gate 	BN_CTX_start(ctx);
900*2139Sjp161948 	d = BN_CTX_get(ctx);
901*2139Sjp161948 	val[0] = BN_CTX_get(ctx);
902*2139Sjp161948 	if(!d || !val[0]) goto err;
9030Sstevel@tonic-gate 
904*2139Sjp161948 	if (!BN_nnmod(val[0],a,m,ctx)) goto err;		/* 1 */
905*2139Sjp161948 	if (BN_is_zero(val[0]))
9060Sstevel@tonic-gate 		{
907*2139Sjp161948 		BN_zero(r);
908*2139Sjp161948 		ret = 1;
9090Sstevel@tonic-gate 		goto err;
9100Sstevel@tonic-gate 		}
9110Sstevel@tonic-gate 
9120Sstevel@tonic-gate 	window = BN_window_bits_for_exponent_size(bits);
9130Sstevel@tonic-gate 	if (window > 1)
9140Sstevel@tonic-gate 		{
915*2139Sjp161948 		if (!BN_mod_mul(d,val[0],val[0],m,ctx))
9160Sstevel@tonic-gate 			goto err;				/* 2 */
9170Sstevel@tonic-gate 		j=1<<(window-1);
9180Sstevel@tonic-gate 		for (i=1; i<j; i++)
9190Sstevel@tonic-gate 			{
920*2139Sjp161948 			if(((val[i] = BN_CTX_get(ctx)) == NULL) ||
921*2139Sjp161948 					!BN_mod_mul(val[i],val[i-1],d,m,ctx))
9220Sstevel@tonic-gate 				goto err;
9230Sstevel@tonic-gate 			}
9240Sstevel@tonic-gate 		}
9250Sstevel@tonic-gate 
9260Sstevel@tonic-gate 	start=1;	/* This is used to avoid multiplication etc
9270Sstevel@tonic-gate 			 * when there is only the value '1' in the
9280Sstevel@tonic-gate 			 * buffer. */
9290Sstevel@tonic-gate 	wvalue=0;	/* The 'value' of the window */
9300Sstevel@tonic-gate 	wstart=bits-1;	/* The top bit of the window */
9310Sstevel@tonic-gate 	wend=0;		/* The bottom bit of the window */
9320Sstevel@tonic-gate 
9330Sstevel@tonic-gate 	if (!BN_one(r)) goto err;
9340Sstevel@tonic-gate 
9350Sstevel@tonic-gate 	for (;;)
9360Sstevel@tonic-gate 		{
9370Sstevel@tonic-gate 		if (BN_is_bit_set(p,wstart) == 0)
9380Sstevel@tonic-gate 			{
9390Sstevel@tonic-gate 			if (!start)
9400Sstevel@tonic-gate 				if (!BN_mod_mul(r,r,r,m,ctx))
9410Sstevel@tonic-gate 				goto err;
9420Sstevel@tonic-gate 			if (wstart == 0) break;
9430Sstevel@tonic-gate 			wstart--;
9440Sstevel@tonic-gate 			continue;
9450Sstevel@tonic-gate 			}
9460Sstevel@tonic-gate 		/* We now have wstart on a 'set' bit, we now need to work out
9470Sstevel@tonic-gate 		 * how bit a window to do.  To do this we need to scan
9480Sstevel@tonic-gate 		 * forward until the last set bit before the end of the
9490Sstevel@tonic-gate 		 * window */
9500Sstevel@tonic-gate 		j=wstart;
9510Sstevel@tonic-gate 		wvalue=1;
9520Sstevel@tonic-gate 		wend=0;
9530Sstevel@tonic-gate 		for (i=1; i<window; i++)
9540Sstevel@tonic-gate 			{
9550Sstevel@tonic-gate 			if (wstart-i < 0) break;
9560Sstevel@tonic-gate 			if (BN_is_bit_set(p,wstart-i))
9570Sstevel@tonic-gate 				{
9580Sstevel@tonic-gate 				wvalue<<=(i-wend);
9590Sstevel@tonic-gate 				wvalue|=1;
9600Sstevel@tonic-gate 				wend=i;
9610Sstevel@tonic-gate 				}
9620Sstevel@tonic-gate 			}
9630Sstevel@tonic-gate 
9640Sstevel@tonic-gate 		/* wend is the size of the current window */
9650Sstevel@tonic-gate 		j=wend+1;
9660Sstevel@tonic-gate 		/* add the 'bytes above' */
9670Sstevel@tonic-gate 		if (!start)
9680Sstevel@tonic-gate 			for (i=0; i<j; i++)
9690Sstevel@tonic-gate 				{
9700Sstevel@tonic-gate 				if (!BN_mod_mul(r,r,r,m,ctx))
9710Sstevel@tonic-gate 					goto err;
9720Sstevel@tonic-gate 				}
9730Sstevel@tonic-gate 
9740Sstevel@tonic-gate 		/* wvalue will be an odd number < 2^window */
975*2139Sjp161948 		if (!BN_mod_mul(r,r,val[wvalue>>1],m,ctx))
9760Sstevel@tonic-gate 			goto err;
9770Sstevel@tonic-gate 
9780Sstevel@tonic-gate 		/* move the 'window' down further */
9790Sstevel@tonic-gate 		wstart-=wend+1;
9800Sstevel@tonic-gate 		wvalue=0;
9810Sstevel@tonic-gate 		start=0;
9820Sstevel@tonic-gate 		if (wstart < 0) break;
9830Sstevel@tonic-gate 		}
9840Sstevel@tonic-gate 	ret=1;
9850Sstevel@tonic-gate err:
9860Sstevel@tonic-gate 	BN_CTX_end(ctx);
987*2139Sjp161948 	bn_check_top(r);
9880Sstevel@tonic-gate 	return(ret);
9890Sstevel@tonic-gate 	}
9900Sstevel@tonic-gate 
991