bn_exp.c revision 6b7257f756eb0530cdf54df9a7fab8d51a5001c3
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley/* crypto/bn/bn_exp.c */
ca41b452ede6feaa9d8739ec3cae19389a7b0d03Bob Halley/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * All rights reserved.
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley *
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * This package is an SSL implementation written
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * by Eric Young (eay@cryptsoft.com).
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * The implementation was written so as to conform with Netscapes SSL.
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley *
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * This library is free for commercial and non-commercial use as long as
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * the following conditions are aheared to. The following conditions
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * apply to all code found in this distribution, be it the RC4, RSA,
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * lhash, DES, etc., code; not just the SSL code. The SSL documentation
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * included with this distribution is covered by the same copyright terms
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * except that the holder is Tim Hudson (tjh@cryptsoft.com).
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley *
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * Copyright remains Eric Young's, and as such any Copyright notices in
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * the code are not to be removed.
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * If this package is used in a product, Eric Young should be given attribution
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * as the author of the parts of the library used.
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * This can be in the form of a textual message at program startup or
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * in documentation (online or textual) provided with the package.
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley *
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * Redistribution and use in source and binary forms, with or without
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * modification, are permitted provided that the following conditions
6a759e38699d133302d0df120d7afcd4af721951David Lawrence * are met:
1d9b3491ab3216c8f278dd821455a7a3b08ddfeeBob Halley * 1. Redistributions of source code must retain the copyright
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * notice, this list of conditions and the following disclaimer.
f73e404eb9e1d314f85128cae48cdee036b405ecAndreas Gustafsson * 2. Redistributions in binary form must reproduce the above copyright
f73e404eb9e1d314f85128cae48cdee036b405ecAndreas Gustafsson * notice, this list of conditions and the following disclaimer in the
7df0472d8a76c83d2137bd9549414a30787d58cfBrian Wellington * documentation and/or other materials provided with the distribution.
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * 3. All advertising materials mentioning features or use of this software
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * must display the following acknowledgement:
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * "This product includes cryptographic software written by
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * Eric Young (eay@cryptsoft.com)"
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * The word 'cryptographic' can be left out if the rouines from the library
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * being used are not cryptographic related :-).
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * 4. If you include any Windows specific code (or a derivative thereof) from
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * the apps directory (application code) you must include an acknowledgement:
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley *
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
941f41d6139c868e357892869c94c4693b943373Bob Halley * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * SUCH DAMAGE.
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley *
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * The licence and distribution terms for any publically available version or
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * derivative of this code cannot be changed. i.e. this code cannot simply be
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * copied and put under another distribution licence
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley * [including the GNU Public Licence.]
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley */
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley#include <config.h>
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley#include "../rename.h"
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley#include <stdio.h>
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley#include "cryptlib.h"
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley#include "bn_lcl.h"
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley#ifdef ATALLA
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley# include <alloca.h>
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley# include <atasi.h>
01cc5813ca716d48c46960302d9845ef7c984f93Bob Halley# include <assert.h>
01cc5813ca716d48c46960302d9845ef7c984f93Bob Halley# include <dlfcn.h>
01cc5813ca716d48c46960302d9845ef7c984f93Bob Halley#endif
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley
1d9b3491ab3216c8f278dd821455a7a3b08ddfeeBob Halley#define TABLE_SIZE 16
1d9b3491ab3216c8f278dd821455a7a3b08ddfeeBob Halley
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley/* slow but works */
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halleyint BN_mod_mul(BIGNUM *ret, BIGNUM *a, BIGNUM *b, const BIGNUM *m, BN_CTX *ctx)
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley {
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley BIGNUM *t;
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley int r=0;
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley bn_check_top(a);
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley bn_check_top(b);
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley bn_check_top(m);
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley BN_CTX_start(ctx);
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley if ((t = BN_CTX_get(ctx)) == NULL) goto err;
01cc5813ca716d48c46960302d9845ef7c984f93Bob Halley if (a == b)
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley { if (!BN_sqr(t,a,ctx)) goto err; }
6a759e38699d133302d0df120d7afcd4af721951David Lawrence else
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley { if (!BN_mul(t,a,b,ctx)) goto err; }
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley if (!BN_mod(ret,t,m,ctx)) goto err;
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley r=1;
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halleyerr:
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley BN_CTX_end(ctx);
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley return(r);
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley }
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley#if 0
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley/* this one works - simple but works */
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halleyint BN_mod_exp(BIGNUM *r, BIGNUM *a, BIGNUM *p, BIGNUM *m, BN_CTX *ctx)
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley {
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley int i,bits,ret=0;
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley BIGNUM *v,*tmp;
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley BN_CTX_start(ctx);
1d9b3491ab3216c8f278dd821455a7a3b08ddfeeBob Halley v = BN_CTX_get(ctx);
1d9b3491ab3216c8f278dd821455a7a3b08ddfeeBob Halley tmp = BN_CTX_get(ctx);
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley if (v == NULL || tmp == NULL) goto err;
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley if (BN_copy(v,a) == NULL) goto err;
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley bits=BN_num_bits(p);
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley if (BN_is_odd(p))
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley { if (BN_copy(r,a) == NULL) goto err; }
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley else { if (!BN_one(r)) goto err; }
c1bfdd299587e790f59378351df66f6168f1e09eAndreas Gustafsson
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley for (i=1; i<bits; i++)
01cc5813ca716d48c46960302d9845ef7c984f93Bob Halley {
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley if (!BN_sqr(tmp,v,ctx)) goto err;
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley if (!BN_mod(v,tmp,m,ctx)) goto err;
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley if (BN_is_bit_set(p,i))
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley {
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley if (!BN_mul(tmp,r,v,ctx)) goto err;
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley if (!BN_mod(r,tmp,m,ctx)) goto err;
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley }
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley }
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley ret=1;
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halleyerr:
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley BN_CTX_end(ctx);
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley return(ret);
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley }
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley
01cc5813ca716d48c46960302d9845ef7c984f93Bob Halley#endif
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley/* this one works - simple but works */
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halleyint BN_exp(BIGNUM *r, BIGNUM *a, BIGNUM *p, BN_CTX *ctx)
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley {
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley int i,bits,ret=0;
1d9b3491ab3216c8f278dd821455a7a3b08ddfeeBob Halley BIGNUM *v,*rr;
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley BN_CTX_start(ctx);
01cc5813ca716d48c46960302d9845ef7c984f93Bob Halley if ((r == a) || (r == p))
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley rr = BN_CTX_get(ctx);
e4653123ecc6cdbfc0b9eda6e98e44af3b1f9a08Mark Andrews else
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley rr = r;
e4653123ecc6cdbfc0b9eda6e98e44af3b1f9a08Mark Andrews if ((v = BN_CTX_get(ctx)) == NULL) goto err;
e4653123ecc6cdbfc0b9eda6e98e44af3b1f9a08Mark Andrews
e4653123ecc6cdbfc0b9eda6e98e44af3b1f9a08Mark Andrews if (BN_copy(v,a) == NULL) goto err;
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley bits=BN_num_bits(p);
01cc5813ca716d48c46960302d9845ef7c984f93Bob Halley
01cc5813ca716d48c46960302d9845ef7c984f93Bob Halley if (BN_is_odd(p))
01cc5813ca716d48c46960302d9845ef7c984f93Bob Halley { if (BN_copy(rr,a) == NULL) goto err; }
01cc5813ca716d48c46960302d9845ef7c984f93Bob Halley else { if (!BN_one(rr)) goto err; }
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley
01cc5813ca716d48c46960302d9845ef7c984f93Bob Halley for (i=1; i<bits; i++)
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley {
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley if (!BN_sqr(v,v,ctx)) goto err;
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley if (BN_is_bit_set(p,i))
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley {
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley if (!BN_mul(rr,rr,v,ctx)) goto err;
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley }
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley }
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley ret=1;
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halleyerr:
68d654930939926e4ddbe2b68234dd7c2da97de5Bob Halley if (r != rr) BN_copy(r,rr);
BN_CTX_end(ctx);
return(ret);
}
#ifdef ATALLA
/*
* This routine will dynamically check for the existance of an Atalla AXL-200
* SSL accelerator module. If one is found, the variable
* asi_accelerator_present is set to 1 and the function pointers
* ptr_ASI_xxxxxx above will be initialized to corresponding ASI API calls.
*/
typedef int tfnASI_GetPerformanceStatistics(int reset_flag,
unsigned int *ret_buf);
typedef int tfnASI_GetHardwareConfig(long card_num, unsigned int *ret_buf);
typedef int tfnASI_RSAPrivateKeyOpFn(RSAPrivateKey * rsaKey,
unsigned char *output,
unsigned char *input,
unsigned int modulus_len);
static tfnASI_GetHardwareConfig *ptr_ASI_GetHardwareConfig;
static tfnASI_RSAPrivateKeyOpFn *ptr_ASI_RSAPrivateKeyOpFn;
static tfnASI_GetPerformanceStatistics *ptr_ASI_GetPerformanceStatistics;
static int asi_accelerator_present;
static int tried_atalla;
void atalla_initialize_accelerator_handle(void)
{
void *dl_handle;
int status;
unsigned int config_buf[1024];
static int tested;
if(tested)
return;
tested=1;
bzero((void *)config_buf, 1024);
/*
* Check to see if the library is present on the system
*/
dl_handle = dlopen("atasi.so", RTLD_NOW);
if (dl_handle == (void *) NULL)
{
/* printf("atasi.so library is not present on the system\n");
printf("No HW acceleration available\n");*/
return;
}
/*
* The library is present. Now we'll check to insure that the
* LDM is up and running. First we'll get the address of the
* function in the atasi library that we need to see if the
* LDM is operating.
*/
ptr_ASI_GetHardwareConfig =
(tfnASI_GetHardwareConfig *)dlsym(dl_handle,"ASI_GetHardwareConfig");
if (ptr_ASI_GetHardwareConfig)
{
/*
* We found the call, now we'll get our config
* status. If we get a non 0 result, the LDM is not
* running and we cannot use the Atalla ASI *
* library.
*/
status = (*ptr_ASI_GetHardwareConfig)(0L, config_buf);
if (status != 0)
{
printf("atasi.so library is present but not initialized\n");
printf("No HW acceleration available\n");
return;
}
}
else
{
/* printf("We found the library, but not the function. Very Strange!\n");*/
return ;
}
/*
* It looks like we have acceleration capabilities. Load up the
* pointers to our ASI API calls.
*/
ptr_ASI_RSAPrivateKeyOpFn=
(tfnASI_RSAPrivateKeyOpFn *)dlsym(dl_handle, "ASI_RSAPrivateKeyOpFn");
if (ptr_ASI_RSAPrivateKeyOpFn == NULL)
{
/* printf("We found the library, but no RSA function. Very Strange!\n");*/
return;
}
ptr_ASI_GetPerformanceStatistics =
(tfnASI_GetPerformanceStatistics *)dlsym(dl_handle, "ASI_GetPerformanceStatistics");
if (ptr_ASI_GetPerformanceStatistics == NULL)
{
/* printf("We found the library, but no stat function. Very Strange!\n");*/
return;
}
/*
* Indicate that acceleration is available
*/
asi_accelerator_present = 1;
/* printf("This system has acceleration!\n");*/
return;
}
/* make sure this only gets called once when bn_mod_exp calls bn_mod_exp_mont */
int BN_mod_exp_atalla(BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m)
{
unsigned char *abin;
unsigned char *pbin;
unsigned char *mbin;
unsigned char *rbin;
int an,pn,mn,ret;
RSAPrivateKey keydata;
atalla_initialize_accelerator_handle();
if(!asi_accelerator_present)
return 0;
/* We should be able to run without size testing */
# define ASIZE 128
an=BN_num_bytes(a);
pn=BN_num_bytes(p);
mn=BN_num_bytes(m);
if(an <= ASIZE && pn <= ASIZE && mn <= ASIZE)
{
int size=mn;
assert(an <= mn);
abin=alloca(size);
memset(abin,'\0',mn);
BN_bn2bin(a,abin+size-an);
pbin=alloca(pn);
BN_bn2bin(p,pbin);
mbin=alloca(size);
memset(mbin,'\0',mn);
BN_bn2bin(m,mbin+size-mn);
rbin=alloca(size);
memset(&keydata,'\0',sizeof keydata);
keydata.privateExponent.data=pbin;
keydata.privateExponent.len=pn;
keydata.modulus.data=mbin;
keydata.modulus.len=size;
ret=(*ptr_ASI_RSAPrivateKeyOpFn)(&keydata,rbin,abin,keydata.modulus.len);
/*fprintf(stderr,"!%s\n",BN_bn2hex(a));*/
if(!ret)
{
BN_bin2bn(rbin,keydata.modulus.len,r);
/*fprintf(stderr,"?%s\n",BN_bn2hex(r));*/
return 1;
}
}
return 0;
}
#endif /* def ATALLA */
int BN_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
BN_CTX *ctx)
{
int ret;
bn_check_top(a);
bn_check_top(p);
bn_check_top(m);
#ifdef ATALLA
if(BN_mod_exp_atalla(r,a,p,m))
return 1;
/* If it fails, try the other methods (but don't try atalla again) */
tried_atalla=1;
#endif
#ifdef MONT_MUL_MOD
/* I have finally been able to take out this pre-condition of
* the top bit being set. It was caused by an error in BN_div
* with negatives. There was also another problem when for a^b%m
* a >= m. eay 07-May-97 */
/* if ((m->d[m->top-1]&BN_TBIT) && BN_is_odd(m)) */
if (BN_is_odd(m))
{ ret=BN_mod_exp_mont(r,a,p,m,ctx,NULL); }
else
#endif
#ifdef RECP_MUL_MOD
{ ret=BN_mod_exp_recp(r,a,p,m,ctx); }
#else
{ ret=BN_mod_exp_simple(r,a,p,m,ctx); }
#endif
#ifdef ATALLA
tried_atalla=0;
#endif
return(ret);
}
/* #ifdef RECP_MUL_MOD */
int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx)
{
int i,j,bits,ret=0,wstart,wend,window,wvalue;
int start=1,ts=0;
BIGNUM *aa;
BIGNUM val[TABLE_SIZE];
BN_RECP_CTX recp;
bits=BN_num_bits(p);
if (bits == 0)
{
BN_one(r);
return(1);
}
BN_CTX_start(ctx);
if ((aa = BN_CTX_get(ctx)) == NULL) goto err;
BN_RECP_CTX_init(&recp);
if (BN_RECP_CTX_set(&recp,m,ctx) <= 0) goto err;
BN_init(&(val[0]));
ts=1;
if (!BN_mod(&(val[0]),a,m,ctx)) goto err; /* 1 */
if (!BN_mod_mul_reciprocal(aa,&(val[0]),&(val[0]),&recp,ctx))
goto err; /* 2 */
if (bits <= 17) /* This is probably 3 or 0x10001, so just do singles */
window=1;
else if (bits >= 256)
window=5; /* max size of window */
else if (bits >= 128)
window=4;
else
window=3;
j=1<<(window-1);
for (i=1; i<j; i++)
{
BN_init(&val[i]);
if (!BN_mod_mul_reciprocal(&(val[i]),&(val[i-1]),aa,&recp,ctx))
goto err;
}
ts=i;
start=1; /* This is used to avoid multiplication etc
* when there is only the value '1' in the
* buffer. */
wvalue=0; /* The 'value' of the window */
wstart=bits-1; /* The top bit of the window */
wend=0; /* The bottom bit of the window */
if (!BN_one(r)) goto err;
for (;;)
{
if (BN_is_bit_set(p,wstart) == 0)
{
if (!start)
if (!BN_mod_mul_reciprocal(r,r,r,&recp,ctx))
goto err;
if (wstart == 0) break;
wstart--;
continue;
}
/* We now have wstart on a 'set' bit, we now need to work out
* how bit a window to do. To do this we need to scan
* forward until the last set bit before the end of the
* window */
j=wstart;
wvalue=1;
wend=0;
for (i=1; i<window; i++)
{
if (wstart-i < 0) break;
if (BN_is_bit_set(p,wstart-i))
{
wvalue<<=(i-wend);
wvalue|=1;
wend=i;
}
}
/* wend is the size of the current window */
j=wend+1;
/* add the 'bytes above' */
if (!start)
for (i=0; i<j; i++)
{
if (!BN_mod_mul_reciprocal(r,r,r,&recp,ctx))
goto err;
}
/* wvalue will be an odd number < 2^window */
if (!BN_mod_mul_reciprocal(r,r,&(val[wvalue>>1]),&recp,ctx))
goto err;
/* move the 'window' down further */
wstart-=wend+1;
wvalue=0;
start=0;
if (wstart < 0) break;
}
ret=1;
err:
BN_CTX_end(ctx);
for (i=0; i<ts; i++)
BN_clear_free(&(val[i]));
BN_RECP_CTX_free(&recp);
return(ret);
}
/* #endif */
/* #ifdef MONT_MUL_MOD */
int BN_mod_exp_mont(BIGNUM *rr, BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
{
int i,j,bits,ret=0,wstart,wend,window,wvalue;
int start=1,ts=0;
BIGNUM *d,*r;
BIGNUM *aa;
BIGNUM val[TABLE_SIZE];
BN_MONT_CTX *mont=NULL;
bn_check_top(a);
bn_check_top(p);
bn_check_top(m);
#ifdef ATALLA
if(!tried_atalla && BN_mod_exp_atalla(rr,a,p,m))
return 1;
/* If it fails, try the other methods */
#endif
if (!(m->d[0] & 1))
{
BNerr(BN_F_BN_MOD_EXP_MONT,BN_R_CALLED_WITH_EVEN_MODULUS);
return(0);
}
bits=BN_num_bits(p);
if (bits == 0)
{
BN_one(rr);
return(1);
}
BN_CTX_start(ctx);
d = BN_CTX_get(ctx);
r = BN_CTX_get(ctx);
if (d == NULL || r == NULL) goto err;
/* If this is not done, things will break in the montgomery
* part */
#if 1
if (in_mont != NULL)
mont=in_mont;
else
#endif
{
if ((mont=BN_MONT_CTX_new()) == NULL) goto err;
if (!BN_MONT_CTX_set(mont,m,ctx)) goto err;
}
BN_init(&val[0]);
ts=1;
if (BN_ucmp(a,m) >= 0)
{
BN_mod(&(val[0]),a,m,ctx);
aa= &(val[0]);
}
else
aa=a;
if (!BN_to_montgomery(&(val[0]),aa,mont,ctx)) goto err; /* 1 */
if (!BN_mod_mul_montgomery(d,&(val[0]),&(val[0]),mont,ctx)) goto err; /* 2 */
if (bits <= 20) /* This is probably 3 or 0x10001, so just do singles */
window=1;
else if (bits >= 256)
window=5; /* max size of window */
else if (bits >= 128)
window=4;
else
window=3;
j=1<<(window-1);
for (i=1; i<j; i++)
{
BN_init(&(val[i]));
if (!BN_mod_mul_montgomery(&(val[i]),&(val[i-1]),d,mont,ctx))
goto err;
}
ts=i;
start=1; /* This is used to avoid multiplication etc
* when there is only the value '1' in the
* buffer. */
wvalue=0; /* The 'value' of the window */
wstart=bits-1; /* The top bit of the window */
wend=0; /* The bottom bit of the window */
if (!BN_to_montgomery(r,BN_value_one(),mont,ctx)) goto err;
for (;;)
{
if (BN_is_bit_set(p,wstart) == 0)
{
if (!start)
{
if (!BN_mod_mul_montgomery(r,r,r,mont,ctx))
goto err;
}
if (wstart == 0) break;
wstart--;
continue;
}
/* We now have wstart on a 'set' bit, we now need to work out
* how bit a window to do. To do this we need to scan
* forward until the last set bit before the end of the
* window */
j=wstart;
wvalue=1;
wend=0;
for (i=1; i<window; i++)
{
if (wstart-i < 0) break;
if (BN_is_bit_set(p,wstart-i))
{
wvalue<<=(i-wend);
wvalue|=1;
wend=i;
}
}
/* wend is the size of the current window */
j=wend+1;
/* add the 'bytes above' */
if (!start)
for (i=0; i<j; i++)
{
if (!BN_mod_mul_montgomery(r,r,r,mont,ctx))
goto err;
}
/* wvalue will be an odd number < 2^window */
if (!BN_mod_mul_montgomery(r,r,&(val[wvalue>>1]),mont,ctx))
goto err;
/* move the 'window' down further */
wstart-=wend+1;
wvalue=0;
start=0;
if (wstart < 0) break;
}
BN_from_montgomery(rr,r,mont,ctx);
ret=1;
err:
if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont);
BN_CTX_end(ctx);
for (i=0; i<ts; i++)
BN_clear_free(&(val[i]));
return(ret);
}
/* #endif */
/* The old fallback, simple version :-) */
int BN_mod_exp_simple(BIGNUM *r, BIGNUM *a, BIGNUM *p, BIGNUM *m,
BN_CTX *ctx)
{
int i,j,bits,ret=0,wstart,wend,window,wvalue,ts=0;
int start=1;
BIGNUM *d;
BIGNUM val[TABLE_SIZE];
bits=BN_num_bits(p);
if (bits == 0)
{
BN_one(r);
return(1);
}
BN_CTX_start(ctx);
if ((d = BN_CTX_get(ctx)) == NULL) goto err;
BN_init(&(val[0]));
ts=1;
if (!BN_mod(&(val[0]),a,m,ctx)) goto err; /* 1 */
if (!BN_mod_mul(d,&(val[0]),&(val[0]),m,ctx))
goto err; /* 2 */
if (bits <= 17) /* This is probably 3 or 0x10001, so just do singles */
window=1;
else if (bits >= 256)
window=5; /* max size of window */
else if (bits >= 128)
window=4;
else
window=3;
j=1<<(window-1);
for (i=1; i<j; i++)
{
BN_init(&(val[i]));
if (!BN_mod_mul(&(val[i]),&(val[i-1]),d,m,ctx))
goto err;
}
ts=i;
start=1; /* This is used to avoid multiplication etc
* when there is only the value '1' in the
* buffer. */
wvalue=0; /* The 'value' of the window */
wstart=bits-1; /* The top bit of the window */
wend=0; /* The bottom bit of the window */
if (!BN_one(r)) goto err;
for (;;)
{
if (BN_is_bit_set(p,wstart) == 0)
{
if (!start)
if (!BN_mod_mul(r,r,r,m,ctx))
goto err;
if (wstart == 0) break;
wstart--;
continue;
}
/* We now have wstart on a 'set' bit, we now need to work out
* how bit a window to do. To do this we need to scan
* forward until the last set bit before the end of the
* window */
j=wstart;
wvalue=1;
wend=0;
for (i=1; i<window; i++)
{
if (wstart-i < 0) break;
if (BN_is_bit_set(p,wstart-i))
{
wvalue<<=(i-wend);
wvalue|=1;
wend=i;
}
}
/* wend is the size of the current window */
j=wend+1;
/* add the 'bytes above' */
if (!start)
for (i=0; i<j; i++)
{
if (!BN_mod_mul(r,r,r,m,ctx))
goto err;
}
/* wvalue will be an odd number < 2^window */
if (!BN_mod_mul(r,r,&(val[wvalue>>1]),m,ctx))
goto err;
/* move the 'window' down further */
wstart-=wend+1;
wvalue=0;
start=0;
if (wstart < 0) break;
}
ret=1;
err:
BN_CTX_end(ctx);
for (i=0; i<ts; i++)
BN_clear_free(&(val[i]));
return(ret);
}