os/ossrv/ssl/libcrypto/src/crypto/bn/bn_mont.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/* crypto/bn/bn_mont.c */
sl@0
     2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
sl@0
     3
 * All rights reserved.
sl@0
     4
 *
sl@0
     5
 * This package is an SSL implementation written
sl@0
     6
 * by Eric Young (eay@cryptsoft.com).
sl@0
     7
 * The implementation was written so as to conform with Netscapes SSL.
sl@0
     8
 * 
sl@0
     9
 * This library is free for commercial and non-commercial use as long as
sl@0
    10
 * the following conditions are aheared to.  The following conditions
sl@0
    11
 * apply to all code found in this distribution, be it the RC4, RSA,
sl@0
    12
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
sl@0
    13
 * included with this distribution is covered by the same copyright terms
sl@0
    14
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
sl@0
    15
 * 
sl@0
    16
 * Copyright remains Eric Young's, and as such any Copyright notices in
sl@0
    17
 * the code are not to be removed.
sl@0
    18
 * If this package is used in a product, Eric Young should be given attribution
sl@0
    19
 * as the author of the parts of the library used.
sl@0
    20
 * This can be in the form of a textual message at program startup or
sl@0
    21
 * in documentation (online or textual) provided with the package.
sl@0
    22
 * 
sl@0
    23
 * Redistribution and use in source and binary forms, with or without
sl@0
    24
 * modification, are permitted provided that the following conditions
sl@0
    25
 * are met:
sl@0
    26
 * 1. Redistributions of source code must retain the copyright
sl@0
    27
 *    notice, this list of conditions and the following disclaimer.
sl@0
    28
 * 2. Redistributions in binary form must reproduce the above copyright
sl@0
    29
 *    notice, this list of conditions and the following disclaimer in the
sl@0
    30
 *    documentation and/or other materials provided with the distribution.
sl@0
    31
 * 3. All advertising materials mentioning features or use of this software
sl@0
    32
 *    must display the following acknowledgement:
sl@0
    33
 *    "This product includes cryptographic software written by
sl@0
    34
 *     Eric Young (eay@cryptsoft.com)"
sl@0
    35
 *    The word 'cryptographic' can be left out if the rouines from the library
sl@0
    36
 *    being used are not cryptographic related :-).
sl@0
    37
 * 4. If you include any Windows specific code (or a derivative thereof) from 
sl@0
    38
 *    the apps directory (application code) you must include an acknowledgement:
sl@0
    39
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
sl@0
    40
 * 
sl@0
    41
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
sl@0
    42
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
sl@0
    43
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
sl@0
    44
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
sl@0
    45
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
sl@0
    46
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
sl@0
    47
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
sl@0
    48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
sl@0
    49
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
sl@0
    50
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
sl@0
    51
 * SUCH DAMAGE.
sl@0
    52
 * 
sl@0
    53
 * The licence and distribution terms for any publically available version or
sl@0
    54
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
sl@0
    55
 * copied and put under another distribution licence
sl@0
    56
 * [including the GNU Public Licence.]
sl@0
    57
 */
sl@0
    58
/* ====================================================================
sl@0
    59
 * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
sl@0
    60
 *
sl@0
    61
 * Redistribution and use in source and binary forms, with or without
sl@0
    62
 * modification, are permitted provided that the following conditions
sl@0
    63
 * are met:
sl@0
    64
 *
sl@0
    65
 * 1. Redistributions of source code must retain the above copyright
sl@0
    66
 *    notice, this list of conditions and the following disclaimer. 
sl@0
    67
 *
sl@0
    68
 * 2. Redistributions in binary form must reproduce the above copyright
sl@0
    69
 *    notice, this list of conditions and the following disclaimer in
sl@0
    70
 *    the documentation and/or other materials provided with the
sl@0
    71
 *    distribution.
sl@0
    72
 *
sl@0
    73
 * 3. All advertising materials mentioning features or use of this
sl@0
    74
 *    software must display the following acknowledgment:
sl@0
    75
 *    "This product includes software developed by the OpenSSL Project
sl@0
    76
 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
sl@0
    77
 *
sl@0
    78
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
sl@0
    79
 *    endorse or promote products derived from this software without
sl@0
    80
 *    prior written permission. For written permission, please contact
sl@0
    81
 *    openssl-core@openssl.org.
sl@0
    82
 *
sl@0
    83
 * 5. Products derived from this software may not be called "OpenSSL"
sl@0
    84
 *    nor may "OpenSSL" appear in their names without prior written
sl@0
    85
 *    permission of the OpenSSL Project.
sl@0
    86
 *
sl@0
    87
 * 6. Redistributions of any form whatsoever must retain the following
sl@0
    88
 *    acknowledgment:
sl@0
    89
 *    "This product includes software developed by the OpenSSL Project
sl@0
    90
 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
sl@0
    91
 *
sl@0
    92
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
sl@0
    93
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
sl@0
    94
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
sl@0
    95
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
sl@0
    96
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
sl@0
    97
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
sl@0
    98
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
sl@0
    99
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
sl@0
   100
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
sl@0
   101
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
sl@0
   102
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
sl@0
   103
 * OF THE POSSIBILITY OF SUCH DAMAGE.
sl@0
   104
 * ====================================================================
sl@0
   105
 *
sl@0
   106
 * This product includes cryptographic software written by Eric Young
sl@0
   107
 * (eay@cryptsoft.com).  This product includes software written by Tim
sl@0
   108
 * Hudson (tjh@cryptsoft.com).
sl@0
   109
 *
sl@0
   110
 */
sl@0
   111
sl@0
   112
/*
sl@0
   113
 * Details about Montgomery multiplication algorithms can be found at
sl@0
   114
 * http://security.ece.orst.edu/publications.html, e.g.
sl@0
   115
 * http://security.ece.orst.edu/koc/papers/j37acmon.pdf and
sl@0
   116
 * sections 3.8 and 4.2 in http://security.ece.orst.edu/koc/papers/r01rsasw.pdf
sl@0
   117
 */
sl@0
   118
sl@0
   119
#include <stdio.h>
sl@0
   120
#include "cryptlib.h"
sl@0
   121
#include "bn_lcl.h"
sl@0
   122
sl@0
   123
#define MONT_WORD /* use the faster word-based algorithm */
sl@0
   124
sl@0
   125
EXPORT_C int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
sl@0
   126
			  BN_MONT_CTX *mont, BN_CTX *ctx)
sl@0
   127
	{
sl@0
   128
	BIGNUM *tmp;
sl@0
   129
	int ret=0;
sl@0
   130
sl@0
   131
	BN_CTX_start(ctx);
sl@0
   132
	tmp = BN_CTX_get(ctx);
sl@0
   133
	if (tmp == NULL) goto err;
sl@0
   134
sl@0
   135
	bn_check_top(tmp);
sl@0
   136
	if (a == b)
sl@0
   137
		{
sl@0
   138
		if (!BN_sqr(tmp,a,ctx)) goto err;
sl@0
   139
		}
sl@0
   140
	else
sl@0
   141
		{
sl@0
   142
		if (!BN_mul(tmp,a,b,ctx)) goto err;
sl@0
   143
		}
sl@0
   144
	/* reduce from aRR to aR */
sl@0
   145
	if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err;
sl@0
   146
	bn_check_top(r);
sl@0
   147
	ret=1;
sl@0
   148
err:
sl@0
   149
	BN_CTX_end(ctx);
sl@0
   150
	return(ret);
sl@0
   151
	}
sl@0
   152
sl@0
   153
EXPORT_C int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont,
sl@0
   154
	     BN_CTX *ctx)
sl@0
   155
	{
sl@0
   156
	int retn=0;
sl@0
   157
sl@0
   158
#ifdef MONT_WORD
sl@0
   159
	BIGNUM *n,*r;
sl@0
   160
	BN_ULONG *ap,*np,*rp,n0,v,*nrp;
sl@0
   161
	int al,nl,max,i,x,ri;
sl@0
   162
sl@0
   163
	BN_CTX_start(ctx);
sl@0
   164
	if ((r = BN_CTX_get(ctx)) == NULL) goto err;
sl@0
   165
sl@0
   166
	if (!BN_copy(r,a)) goto err;
sl@0
   167
	n= &(mont->N);
sl@0
   168
sl@0
   169
	ap=a->d;
sl@0
   170
	/* mont->ri is the size of mont->N in bits (rounded up
sl@0
   171
	   to the word size) */
sl@0
   172
	al=ri=mont->ri/BN_BITS2;
sl@0
   173
	
sl@0
   174
	nl=n->top;
sl@0
   175
	if ((al == 0) || (nl == 0)) { r->top=0; return(1); }
sl@0
   176
sl@0
   177
	max=(nl+al+1); /* allow for overflow (no?) XXX */
sl@0
   178
	if (bn_wexpand(r,max) == NULL) goto err;
sl@0
   179
sl@0
   180
	r->neg=a->neg^n->neg;
sl@0
   181
	np=n->d;
sl@0
   182
	rp=r->d;
sl@0
   183
	nrp= &(r->d[nl]);
sl@0
   184
sl@0
   185
	/* clear the top words of T */
sl@0
   186
#if 1
sl@0
   187
	for (i=r->top; i<max; i++) /* memset? XXX */
sl@0
   188
		r->d[i]=0;
sl@0
   189
#else
sl@0
   190
	memset(&(r->d[r->top]),0,(max-r->top)*sizeof(BN_ULONG)); 
sl@0
   191
#endif
sl@0
   192
sl@0
   193
	r->top=max;
sl@0
   194
	n0=mont->n0;
sl@0
   195
sl@0
   196
#ifdef BN_COUNT
sl@0
   197
	fprintf(stderr,"word BN_from_montgomery %d * %d\n",nl,nl);
sl@0
   198
#endif
sl@0
   199
	for (i=0; i<nl; i++)
sl@0
   200
		{
sl@0
   201
#ifdef __TANDEM
sl@0
   202
                {
sl@0
   203
                   long long t1;
sl@0
   204
                   long long t2;
sl@0
   205
                   long long t3;
sl@0
   206
                   t1 = rp[0] * (n0 & 0177777);
sl@0
   207
                   t2 = 037777600000l;
sl@0
   208
                   t2 = n0 & t2;
sl@0
   209
                   t3 = rp[0] & 0177777;
sl@0
   210
                   t2 = (t3 * t2) & BN_MASK2;
sl@0
   211
                   t1 = t1 + t2;
sl@0
   212
                   v=bn_mul_add_words(rp,np,nl,(BN_ULONG) t1);
sl@0
   213
                }
sl@0
   214
#else
sl@0
   215
		v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
sl@0
   216
#endif
sl@0
   217
		nrp++;
sl@0
   218
		rp++;
sl@0
   219
		if (((nrp[-1]+=v)&BN_MASK2) >= v)
sl@0
   220
			continue;
sl@0
   221
		else
sl@0
   222
			{
sl@0
   223
			if (((++nrp[0])&BN_MASK2) != 0) continue;
sl@0
   224
			if (((++nrp[1])&BN_MASK2) != 0) continue;
sl@0
   225
			for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ;
sl@0
   226
			}
sl@0
   227
		}
sl@0
   228
	bn_correct_top(r);
sl@0
   229
	
sl@0
   230
	/* mont->ri will be a multiple of the word size and below code
sl@0
   231
	 * is kind of BN_rshift(ret,r,mont->ri) equivalent */
sl@0
   232
	if (r->top <= ri)
sl@0
   233
		{
sl@0
   234
		ret->top=0;
sl@0
   235
		retn=1;
sl@0
   236
		goto err;
sl@0
   237
		}
sl@0
   238
	al=r->top-ri;
sl@0
   239
sl@0
   240
# define BRANCH_FREE 1
sl@0
   241
# if BRANCH_FREE
sl@0
   242
	if (bn_wexpand(ret,ri) == NULL) goto err;
sl@0
   243
	x=0-(((al-ri)>>(sizeof(al)*8-1))&1);
sl@0
   244
	ret->top=x=(ri&~x)|(al&x);	/* min(ri,al) */
sl@0
   245
	ret->neg=r->neg;
sl@0
   246
sl@0
   247
	rp=ret->d;
sl@0
   248
	ap=&(r->d[ri]);
sl@0
   249
sl@0
   250
	{
sl@0
   251
	size_t m1,m2;
sl@0
   252
sl@0
   253
	v=bn_sub_words(rp,ap,np,ri);
sl@0
   254
	/* this ----------------^^ works even in al<ri case
sl@0
   255
	 * thanks to zealous zeroing of top of the vector in the
sl@0
   256
	 * beginning. */
sl@0
   257
sl@0
   258
	/* if (al==ri && !v) || al>ri) nrp=rp; else nrp=ap; */
sl@0
   259
	/* in other words if subtraction result is real, then
sl@0
   260
	 * trick unconditional memcpy below to perform in-place
sl@0
   261
	 * "refresh" instead of actual copy. */
sl@0
   262
	m1=0-(size_t)(((al-ri)>>(sizeof(al)*8-1))&1);	/* al<ri */
sl@0
   263
	m2=0-(size_t)(((ri-al)>>(sizeof(al)*8-1))&1);	/* al>ri */
sl@0
   264
	m1|=m2;			/* (al!=ri) */
sl@0
   265
	m1|=(0-(size_t)v);	/* (al!=ri || v) */
sl@0
   266
	m1&=~m2;		/* (al!=ri || v) && !al>ri */
sl@0
   267
	nrp=(BN_ULONG *)(((size_t)rp&~m1)|((size_t)ap&m1));
sl@0
   268
	}
sl@0
   269
sl@0
   270
	/* 'i<ri' is chosen to eliminate dependency on input data, even
sl@0
   271
	 * though it results in redundant copy in al<ri case. */
sl@0
   272
	for (i=0,ri-=4; i<ri; i+=4)
sl@0
   273
		{
sl@0
   274
		BN_ULONG t1,t2,t3,t4;
sl@0
   275
		
sl@0
   276
		t1=nrp[i+0];
sl@0
   277
		t2=nrp[i+1];
sl@0
   278
		t3=nrp[i+2];	ap[i+0]=0;
sl@0
   279
		t4=nrp[i+3];	ap[i+1]=0;
sl@0
   280
		rp[i+0]=t1;	ap[i+2]=0;
sl@0
   281
		rp[i+1]=t2;	ap[i+3]=0;
sl@0
   282
		rp[i+2]=t3;
sl@0
   283
		rp[i+3]=t4;
sl@0
   284
		}
sl@0
   285
	for (ri+=4; i<ri; i++)
sl@0
   286
		rp[i]=nrp[i], ap[i]=0;
sl@0
   287
	bn_correct_top(r);
sl@0
   288
	bn_correct_top(ret);
sl@0
   289
# else
sl@0
   290
	if (bn_wexpand(ret,al) == NULL) goto err;
sl@0
   291
	ret->top=al;
sl@0
   292
	ret->neg=r->neg;
sl@0
   293
sl@0
   294
	rp=ret->d;
sl@0
   295
	ap=&(r->d[ri]);
sl@0
   296
	al-=4;
sl@0
   297
	for (i=0; i<al; i+=4)
sl@0
   298
		{
sl@0
   299
		BN_ULONG t1,t2,t3,t4;
sl@0
   300
		
sl@0
   301
		t1=ap[i+0];
sl@0
   302
		t2=ap[i+1];
sl@0
   303
		t3=ap[i+2];
sl@0
   304
		t4=ap[i+3];
sl@0
   305
		rp[i+0]=t1;
sl@0
   306
		rp[i+1]=t2;
sl@0
   307
		rp[i+2]=t3;
sl@0
   308
		rp[i+3]=t4;
sl@0
   309
		}
sl@0
   310
	al+=4;
sl@0
   311
	for (; i<al; i++)
sl@0
   312
		rp[i]=ap[i];
sl@0
   313
#endif
sl@0
   314
#else /* !MONT_WORD */ 
sl@0
   315
	BIGNUM *t1,*t2;
sl@0
   316
sl@0
   317
	BN_CTX_start(ctx);
sl@0
   318
	t1 = BN_CTX_get(ctx);
sl@0
   319
	t2 = BN_CTX_get(ctx);
sl@0
   320
	if (t1 == NULL || t2 == NULL) goto err;
sl@0
   321
	
sl@0
   322
	if (!BN_copy(t1,a)) goto err;
sl@0
   323
	BN_mask_bits(t1,mont->ri);
sl@0
   324
sl@0
   325
	if (!BN_mul(t2,t1,&mont->Ni,ctx)) goto err;
sl@0
   326
	BN_mask_bits(t2,mont->ri);
sl@0
   327
sl@0
   328
	if (!BN_mul(t1,t2,&mont->N,ctx)) goto err;
sl@0
   329
	if (!BN_add(t2,a,t1)) goto err;
sl@0
   330
	if (!BN_rshift(ret,t2,mont->ri)) goto err;
sl@0
   331
#endif /* MONT_WORD */
sl@0
   332
sl@0
   333
#if !defined(BRANCH_FREE) || BRANCH_FREE==0
sl@0
   334
	if (BN_ucmp(ret, &(mont->N)) >= 0)
sl@0
   335
		{
sl@0
   336
		if (!BN_usub(ret,ret,&(mont->N))) goto err;
sl@0
   337
		}
sl@0
   338
#endif
sl@0
   339
	retn=1;
sl@0
   340
	bn_check_top(ret);
sl@0
   341
 err:
sl@0
   342
	BN_CTX_end(ctx);
sl@0
   343
	return(retn);
sl@0
   344
	}
sl@0
   345
sl@0
   346
EXPORT_C BN_MONT_CTX *BN_MONT_CTX_new(void)
sl@0
   347
	{
sl@0
   348
	BN_MONT_CTX *ret;
sl@0
   349
sl@0
   350
	if ((ret=(BN_MONT_CTX *)OPENSSL_malloc(sizeof(BN_MONT_CTX))) == NULL)
sl@0
   351
		return(NULL);
sl@0
   352
sl@0
   353
	BN_MONT_CTX_init(ret);
sl@0
   354
	ret->flags=BN_FLG_MALLOCED;
sl@0
   355
	return(ret);
sl@0
   356
	}
sl@0
   357
sl@0
   358
EXPORT_C void BN_MONT_CTX_init(BN_MONT_CTX *ctx)
sl@0
   359
	{
sl@0
   360
	ctx->ri=0;
sl@0
   361
	BN_init(&(ctx->RR));
sl@0
   362
	BN_init(&(ctx->N));
sl@0
   363
	BN_init(&(ctx->Ni));
sl@0
   364
	ctx->flags=0;
sl@0
   365
	}
sl@0
   366
sl@0
   367
EXPORT_C void BN_MONT_CTX_free(BN_MONT_CTX *mont)
sl@0
   368
	{
sl@0
   369
	if(mont == NULL)
sl@0
   370
	    return;
sl@0
   371
sl@0
   372
	BN_free(&(mont->RR));
sl@0
   373
	BN_free(&(mont->N));
sl@0
   374
	BN_free(&(mont->Ni));
sl@0
   375
	if (mont->flags & BN_FLG_MALLOCED)
sl@0
   376
		OPENSSL_free(mont);
sl@0
   377
	}
sl@0
   378
sl@0
   379
EXPORT_C int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
sl@0
   380
	{
sl@0
   381
	int ret = 0;
sl@0
   382
	BIGNUM *Ri,*R;
sl@0
   383
sl@0
   384
	BN_CTX_start(ctx);
sl@0
   385
	if((Ri = BN_CTX_get(ctx)) == NULL) goto err;
sl@0
   386
	R= &(mont->RR);					/* grab RR as a temp */
sl@0
   387
	if (!BN_copy(&(mont->N),mod)) goto err;		/* Set N */
sl@0
   388
	mont->N.neg = 0;
sl@0
   389
sl@0
   390
#ifdef MONT_WORD
sl@0
   391
		{
sl@0
   392
		BIGNUM tmod;
sl@0
   393
		BN_ULONG buf[2];
sl@0
   394
sl@0
   395
		mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2;
sl@0
   396
		BN_zero(R);
sl@0
   397
		if (!(BN_set_bit(R,BN_BITS2))) goto err;	/* R */
sl@0
   398
sl@0
   399
		buf[0]=mod->d[0]; /* tmod = N mod word size */
sl@0
   400
		buf[1]=0;
sl@0
   401
		tmod.d=buf;
sl@0
   402
		tmod.top = buf[0] != 0 ? 1 : 0;
sl@0
   403
		tmod.dmax=2;
sl@0
   404
		tmod.neg=0;
sl@0
   405
							/* Ri = R^-1 mod N*/
sl@0
   406
		if ((BN_mod_inverse(Ri,R,&tmod,ctx)) == NULL)
sl@0
   407
			goto err;
sl@0
   408
		if (!BN_lshift(Ri,Ri,BN_BITS2)) goto err; /* R*Ri */
sl@0
   409
		if (!BN_is_zero(Ri))
sl@0
   410
			{
sl@0
   411
			if (!BN_sub_word(Ri,1)) goto err;
sl@0
   412
			}
sl@0
   413
		else /* if N mod word size == 1 */
sl@0
   414
			{
sl@0
   415
			if (!BN_set_word(Ri,BN_MASK2)) goto err;  /* Ri-- (mod word size) */
sl@0
   416
			}
sl@0
   417
		if (!BN_div(Ri,NULL,Ri,&tmod,ctx)) goto err;
sl@0
   418
		/* Ni = (R*Ri-1)/N,
sl@0
   419
		 * keep only least significant word: */
sl@0
   420
		mont->n0 = (Ri->top > 0) ? Ri->d[0] : 0;
sl@0
   421
		}
sl@0
   422
#else /* !MONT_WORD */
sl@0
   423
		{ /* bignum version */
sl@0
   424
		mont->ri=BN_num_bits(&mont->N);
sl@0
   425
		BN_zero(R);
sl@0
   426
		if (!BN_set_bit(R,mont->ri)) goto err;  /* R = 2^ri */
sl@0
   427
		                                        /* Ri = R^-1 mod N*/
sl@0
   428
		if ((BN_mod_inverse(Ri,R,&mont->N,ctx)) == NULL)
sl@0
   429
			goto err;
sl@0
   430
		if (!BN_lshift(Ri,Ri,mont->ri)) goto err; /* R*Ri */
sl@0
   431
		if (!BN_sub_word(Ri,1)) goto err;
sl@0
   432
							/* Ni = (R*Ri-1) / N */
sl@0
   433
		if (!BN_div(&(mont->Ni),NULL,Ri,&mont->N,ctx)) goto err;
sl@0
   434
		}
sl@0
   435
#endif
sl@0
   436
sl@0
   437
	/* setup RR for conversions */
sl@0
   438
	BN_zero(&(mont->RR));
sl@0
   439
	if (!BN_set_bit(&(mont->RR),mont->ri*2)) goto err;
sl@0
   440
	if (!BN_mod(&(mont->RR),&(mont->RR),&(mont->N),ctx)) goto err;
sl@0
   441
sl@0
   442
	ret = 1;
sl@0
   443
err:
sl@0
   444
	BN_CTX_end(ctx);
sl@0
   445
	return ret;
sl@0
   446
	}
sl@0
   447
sl@0
   448
EXPORT_C BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from)
sl@0
   449
	{
sl@0
   450
	if (to == from) return(to);
sl@0
   451
sl@0
   452
	if (!BN_copy(&(to->RR),&(from->RR))) return NULL;
sl@0
   453
	if (!BN_copy(&(to->N),&(from->N))) return NULL;
sl@0
   454
	if (!BN_copy(&(to->Ni),&(from->Ni))) return NULL;
sl@0
   455
	to->ri=from->ri;
sl@0
   456
	to->n0=from->n0;
sl@0
   457
	return(to);
sl@0
   458
	}
sl@0
   459
sl@0
   460
EXPORT_C BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, int lock,
sl@0
   461
					const BIGNUM *mod, BN_CTX *ctx)
sl@0
   462
	{
sl@0
   463
		int got_write_lock = 0;
sl@0
   464
	BN_MONT_CTX *ret;
sl@0
   465
sl@0
   466
	CRYPTO_r_lock(lock);
sl@0
   467
	if (!*pmont)
sl@0
   468
		{
sl@0
   469
		CRYPTO_r_unlock(lock);
sl@0
   470
		CRYPTO_w_lock(lock);
sl@0
   471
		got_write_lock = 1;
sl@0
   472
sl@0
   473
		if (!*pmont)
sl@0
   474
			{
sl@0
   475
			ret = BN_MONT_CTX_new();
sl@0
   476
			if (ret && !BN_MONT_CTX_set(ret, mod, ctx))
sl@0
   477
				BN_MONT_CTX_free(ret);
sl@0
   478
			else
sl@0
   479
				*pmont = ret;
sl@0
   480
			}
sl@0
   481
		}
sl@0
   482
	
sl@0
   483
	ret = *pmont;
sl@0
   484
	
sl@0
   485
	if (got_write_lock)
sl@0
   486
		CRYPTO_w_unlock(lock);
sl@0
   487
	else
sl@0
   488
		CRYPTO_r_unlock(lock);
sl@0
   489
		
sl@0
   490
	return ret;
sl@0
   491
	}