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