bn_mont.c 15.4 KB
Newer Older
1
/* crypto/bn/bn_mont.c */
2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
 * All rights reserved.
 *
 * This package is an SSL implementation written
 * by Eric Young (eay@cryptsoft.com).
 * The implementation was written so as to conform with Netscapes SSL.
 * 
 * This library is free for commercial and non-commercial use as long as
 * the following conditions are aheared to.  The following conditions
 * apply to all code found in this distribution, be it the RC4, RSA,
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
 * included with this distribution is covered by the same copyright terms
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
 * 
 * Copyright remains Eric Young's, and as such any Copyright notices in
 * the code are not to be removed.
 * If this package is used in a product, Eric Young should be given attribution
 * as the author of the parts of the library used.
 * This can be in the form of a textual message at program startup or
 * in documentation (online or textual) provided with the package.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    "This product includes cryptographic software written by
 *     Eric Young (eay@cryptsoft.com)"
 *    The word 'cryptographic' can be left out if the rouines from the library
 *    being used are not cryptographic related :-).
 * 4. If you include any Windows specific code (or a derivative thereof) from 
 *    the apps directory (application code) you must include an acknowledgement:
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
 * 
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * 
 * The licence and distribution terms for any publically available version or
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
 * copied and put under another distribution licence
 * [including the GNU Public Licence.]
 */
B
Bodo Möller 已提交
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
/* ====================================================================
 * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
 *
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
 *    endorse or promote products derived from this software without
 *    prior written permission. For written permission, please contact
 *    openssl-core@openssl.org.
 *
 * 5. Products derived from this software may not be called "OpenSSL"
 *    nor may "OpenSSL" appear in their names without prior written
 *    permission of the OpenSSL Project.
 *
 * 6. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
 *
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 * ====================================================================
 *
 * This product includes cryptographic software written by Eric Young
 * (eay@cryptsoft.com).  This product includes software written by Tim
 * Hudson (tjh@cryptsoft.com).
 *
 */
111

112
/*
113 114 115 116
 * Details about Montgomery multiplication algorithms can be found at
 * http://security.ece.orst.edu/publications.html, e.g.
 * http://security.ece.orst.edu/koc/papers/j37acmon.pdf and
 * sections 3.8 and 4.2 in http://security.ece.orst.edu/koc/papers/r01rsasw.pdf
117 118
 */

119 120 121 122
#include <stdio.h>
#include "cryptlib.h"
#include "bn_lcl.h"

123 124
#define MONT_WORD /* use the faster word-based algorithm */

125 126 127 128
#ifdef MONT_WORD
static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont);
#endif

129
int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
130
			  BN_MONT_CTX *mont, BN_CTX *ctx)
131
	{
132
	BIGNUM *tmp;
U
Ulf Möller 已提交
133
	int ret=0;
134
#if defined(OPENSSL_BN_ASM_MONT) && defined(MONT_WORD)
135 136 137 138
	int num = mont->N.top;

	if (num>1 && a->top==num && b->top==num)
		{
139
		if (bn_wexpand(r,num) == NULL) return(0);
140 141 142 143
		if (bn_mul_mont(r->d,a->d,b->d,mont->N.d,mont->n0,num))
			{
			r->neg = a->neg^b->neg;
			r->top = num;
144 145
			bn_correct_top(r);
			return(1);
146
			}
147 148
		}
#endif
149

150 151
	BN_CTX_start(ctx);
	tmp = BN_CTX_get(ctx);
152
	if (tmp == NULL) goto err;
153

154
	bn_check_top(tmp);
155 156 157 158 159 160
	if (a == b)
		{
		if (!BN_sqr(tmp,a,ctx)) goto err;
		}
	else
		{
161
		if (!BN_mul(tmp,a,b,ctx)) goto err;
162 163
		}
	/* reduce from aRR to aR */
164 165 166
#ifdef MONT_WORD
	if (!BN_from_montgomery_word(r,tmp,mont)) goto err;
#else
167
	if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err;
168
#endif
169
	bn_check_top(r);
U
Ulf Möller 已提交
170
	ret=1;
171
err:
U
Ulf Möller 已提交
172 173
	BN_CTX_end(ctx);
	return(ret);
174 175
	}

176
#ifdef MONT_WORD
177 178 179
static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
	{
	BIGNUM *n;
180 181
	BN_ULONG *ap,*np,*rp,n0,v,*nrp;
	int al,nl,max,i,x,ri;
182

183 184 185 186
	n= &(mont->N);
	/* mont->ri is the size of mont->N in bits (rounded up
	   to the word size) */
	al=ri=mont->ri/BN_BITS2;
187

188
	nl=n->top;
189
	if ((al == 0) || (nl == 0)) { ret->top=0; return(1); }
190

191
	max=(nl+al+1); /* allow for overflow (no?) XXX */
192
	if (bn_wexpand(r,max) == NULL) return(0);
193

194
	r->neg^=n->neg;
195 196 197
	np=n->d;
	rp=r->d;
	nrp= &(r->d[nl]);
198

199
	/* clear the top words of T */
200
#if 1
201 202
	for (i=r->top; i<max; i++) /* memset? XXX */
		r->d[i]=0;
203
#else
204
	memset(&(r->d[r->top]),0,(max-r->top)*sizeof(BN_ULONG)); 
205
#endif
206

207
	r->top=max;
208
	n0=mont->n0[0];
209

210
#ifdef BN_COUNT
211
	fprintf(stderr,"word BN_from_montgomery_word %d * %d\n",nl,nl);
212
#endif
213 214
	for (i=0; i<nl; i++)
		{
215 216 217 218 219 220 221 222 223 224 225 226 227 228
#ifdef __TANDEM
                {
                   long long t1;
                   long long t2;
                   long long t3;
                   t1 = rp[0] * (n0 & 0177777);
                   t2 = 037777600000l;
                   t2 = n0 & t2;
                   t3 = rp[0] & 0177777;
                   t2 = (t3 * t2) & BN_MASK2;
                   t1 = t1 + t2;
                   v=bn_mul_add_words(rp,np,nl,(BN_ULONG) t1);
                }
#else
229
		v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
230
#endif
231 232 233 234 235
		nrp++;
		rp++;
		if (((nrp[-1]+=v)&BN_MASK2) >= v)
			continue;
		else
236
			{
237 238 239
			if (((++nrp[0])&BN_MASK2) != 0) continue;
			if (((++nrp[1])&BN_MASK2) != 0) continue;
			for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ;
240
			}
241
		}
242
	bn_correct_top(r);
243 244 245

	/* mont->ri will be a multiple of the word size and below code
	 * is kind of BN_rshift(ret,r,mont->ri) equivalent */
246
	if (r->top <= ri)
247 248 249 250 251
		{
		ret->top=0;
		return(1);
		}
	al=r->top-ri;
252 253 254 255 256 257

#define BRANCH_FREE 1
#if BRANCH_FREE
	if (bn_wexpand(ret,ri) == NULL) return(0);
	x=0-(((al-ri)>>(sizeof(al)*8-1))&1);
	ret->top=x=(ri&~x)|(al&x);	/* min(ri,al) */
258
	ret->neg=r->neg;
259 260 261 262

	rp=ret->d;
	ap=&(r->d[ri]);

263 264
	{
	size_t m1,m2;
265

266 267 268 269
	v=bn_sub_words(rp,ap,np,ri);
	/* this ----------------^^ works even in al<ri case
	 * thanks to zealous zeroing of top of the vector in the
	 * beginning. */
270

271 272 273 274 275 276 277 278 279 280 281
	/* if (al==ri && !v) || al>ri) nrp=rp; else nrp=ap; */
	/* in other words if subtraction result is real, then
	 * trick unconditional memcpy below to perform in-place
	 * "refresh" instead of actual copy. */
	m1=0-(size_t)(((al-ri)>>(sizeof(al)*8-1))&1);	/* al<ri */
	m2=0-(size_t)(((ri-al)>>(sizeof(al)*8-1))&1);	/* al>ri */
	m1|=m2;			/* (al!=ri) */
	m1|=(0-(size_t)v);	/* (al!=ri || v) */
	m1&=~m2;		/* (al!=ri || v) && !al>ri */
	nrp=(BN_ULONG *)(((size_t)rp&~m1)|((size_t)ap&m1));
	}
282

283 284
	/* 'i<ri' is chosen to eliminate dependency on input data, even
	 * though it results in redundant copy in al<ri case. */
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
	for (i=0,ri-=4; i<ri; i+=4)
		{
		BN_ULONG t1,t2,t3,t4;
		
		t1=nrp[i+0];
		t2=nrp[i+1];
		t3=nrp[i+2];	ap[i+0]=0;
		t4=nrp[i+3];	ap[i+1]=0;
		rp[i+0]=t1;	ap[i+2]=0;
		rp[i+1]=t2;	ap[i+3]=0;
		rp[i+2]=t3;
		rp[i+3]=t4;
		}
	for (ri+=4; i<ri; i++)
		rp[i]=nrp[i], ap[i]=0;
300 301
	bn_correct_top(r);
	bn_correct_top(ret);
302 303
#else
	if (bn_wexpand(ret,al) == NULL) return(0);
304
	ret->top=al;
305
	ret->neg=r->neg;
306 307 308

	rp=ret->d;
	ap=&(r->d[ri]);
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
	al-=4;
	for (i=0; i<al; i+=4)
		{
		BN_ULONG t1,t2,t3,t4;
		
		t1=ap[i+0];
		t2=ap[i+1];
		t3=ap[i+2];
		t4=ap[i+3];
		rp[i+0]=t1;
		rp[i+1]=t2;
		rp[i+2]=t3;
		rp[i+3]=t4;
		}
	al+=4;
	for (; i<al; i++)
		rp[i]=ap[i];
326 327 328 329 330

	if (BN_ucmp(ret, &(mont->N)) >= 0)
		{
		if (!BN_usub(ret,ret,&(mont->N))) return(0);
		}
331
#endif
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349
	bn_check_top(ret);

	return(1);
	}
#endif	/* MONT_WORD */

int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont,
	     BN_CTX *ctx)
	{
	int retn=0;
#ifdef MONT_WORD
	BIGNUM *t;

	BN_CTX_start(ctx);
	if ((t = BN_CTX_get(ctx)) && BN_copy(t,a))
		retn = BN_from_montgomery_word(ret,t,mont);
	BN_CTX_end(ctx);
#else /* !MONT_WORD */
350
	BIGNUM *t1,*t2;
351

352 353 354 355 356 357 358 359 360 361 362 363 364
	BN_CTX_start(ctx);
	t1 = BN_CTX_get(ctx);
	t2 = BN_CTX_get(ctx);
	if (t1 == NULL || t2 == NULL) goto err;
	
	if (!BN_copy(t1,a)) goto err;
	BN_mask_bits(t1,mont->ri);

	if (!BN_mul(t2,t1,&mont->Ni,ctx)) goto err;
	BN_mask_bits(t2,mont->ri);

	if (!BN_mul(t1,t2,&mont->N,ctx)) goto err;
	if (!BN_add(t2,a,t1)) goto err;
365
	if (!BN_rshift(ret,t2,mont->ri)) goto err;
366 367

	if (BN_ucmp(ret, &(mont->N)) >= 0)
368
		{
369
		if (!BN_usub(ret,ret,&(mont->N))) goto err;
370
		}
371
	retn=1;
372
	bn_check_top(ret);
U
Ulf Möller 已提交
373
 err:
374
	BN_CTX_end(ctx);
375
#endif /* MONT_WORD */
U
Ulf Möller 已提交
376
	return(retn);
377
	}
378

U
Ulf Möller 已提交
379
BN_MONT_CTX *BN_MONT_CTX_new(void)
380 381 382
	{
	BN_MONT_CTX *ret;

383
	if ((ret=(BN_MONT_CTX *)OPENSSL_malloc(sizeof(BN_MONT_CTX))) == NULL)
384
		return(NULL);
385 386 387

	BN_MONT_CTX_init(ret);
	ret->flags=BN_FLG_MALLOCED;
388 389 390
	return(ret);
	}

U
Ulf Möller 已提交
391
void BN_MONT_CTX_init(BN_MONT_CTX *ctx)
392 393 394 395 396 397 398 399
	{
	ctx->ri=0;
	BN_init(&(ctx->RR));
	BN_init(&(ctx->N));
	BN_init(&(ctx->Ni));
	ctx->flags=0;
	}

U
Ulf Möller 已提交
400
void BN_MONT_CTX_free(BN_MONT_CTX *mont)
401
	{
B
Ben Laurie 已提交
402 403 404
	if(mont == NULL)
	    return;

405 406 407 408
	BN_free(&(mont->RR));
	BN_free(&(mont->N));
	BN_free(&(mont->Ni));
	if (mont->flags & BN_FLG_MALLOCED)
409
		OPENSSL_free(mont);
410 411
	}

412
int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
413
	{
414 415
	int ret = 0;
	BIGNUM *Ri,*R;
416

417 418
	BN_CTX_start(ctx);
	if((Ri = BN_CTX_get(ctx)) == NULL) goto err;
419
	R= &(mont->RR);					/* grab RR as a temp */
420
	if (!BN_copy(&(mont->N),mod)) goto err;		/* Set N */
421
	mont->N.neg = 0;
422

423
#ifdef MONT_WORD
424 425 426 427
		{
		BIGNUM tmod;
		BN_ULONG buf[2];

428 429 430 431
		tmod.d=buf;
		tmod.dmax=2;
		tmod.neg=0;

432
		mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2;
433 434 435 436 437 438

#if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2<=32)
		BN_zero(R);
		if (!(BN_set_bit(R,2*BN_BITS2))) goto err;

								tmod.top=0;
439 440
		if ((buf[0] = mod->d[0]))			tmod.top=1;
		if ((buf[1] = mod->top>1 ? mod->d[1] : 0))	tmod.top=2;
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464

		if ((BN_mod_inverse(Ri,R,&tmod,ctx)) == NULL)
			goto err;
		if (!BN_lshift(Ri,Ri,2*BN_BITS2)) goto err; /* R*Ri */
		if (!BN_is_zero(Ri))
			{
			if (!BN_sub_word(Ri,1)) goto err;
			}
		else /* if N mod word size == 1 */
			{
			if (bn_expand(Ri,(int)sizeof(BN_ULONG)*2) == NULL)
				goto err;
			/* Ri-- (mod double word size) */
			Ri->neg=0;
			Ri->d[0]=BN_MASK2;
			Ri->d[1]=BN_MASK2;
			Ri->top=2;
			}
		if (!BN_div(Ri,NULL,Ri,&tmod,ctx)) goto err;
		/* Ni = (R*Ri-1)/N,
		 * keep only couple of least significant words: */
		mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
		mont->n0[1] = (Ri->top > 1) ? Ri->d[1] : 0;
#else
465
		BN_zero(R);
466
		if (!(BN_set_bit(R,BN_BITS2))) goto err;	/* R */
467

U
Ulf Möller 已提交
468
		buf[0]=mod->d[0]; /* tmod = N mod word size */
469
		buf[1]=0;
N
Nils Larsch 已提交
470
		tmod.top = buf[0] != 0 ? 1 : 0;
U
Ulf Möller 已提交
471
							/* Ri = R^-1 mod N*/
472
		if ((BN_mod_inverse(Ri,R,&tmod,ctx)) == NULL)
473
			goto err;
474 475
		if (!BN_lshift(Ri,Ri,BN_BITS2)) goto err; /* R*Ri */
		if (!BN_is_zero(Ri))
476
			{
477
			if (!BN_sub_word(Ri,1)) goto err;
478
			}
U
Ulf Möller 已提交
479
		else /* if N mod word size == 1 */
480
			{
481
			if (!BN_set_word(Ri,BN_MASK2)) goto err;  /* Ri-- (mod word size) */
482
			}
483
		if (!BN_div(Ri,NULL,Ri,&tmod,ctx)) goto err;
484 485
		/* Ni = (R*Ri-1)/N,
		 * keep only least significant word: */
486 487 488
		mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
		mont->n0[1] = 0;
#endif
489
		}
490
#else /* !MONT_WORD */
U
Ulf Möller 已提交
491
		{ /* bignum version */
492
		mont->ri=BN_num_bits(&mont->N);
493
		BN_zero(R);
494 495
		if (!BN_set_bit(R,mont->ri)) goto err;  /* R = 2^ri */
		                                        /* Ri = R^-1 mod N*/
496
		if ((BN_mod_inverse(Ri,R,&mont->N,ctx)) == NULL)
497
			goto err;
498 499
		if (!BN_lshift(Ri,Ri,mont->ri)) goto err; /* R*Ri */
		if (!BN_sub_word(Ri,1)) goto err;
U
Ulf Möller 已提交
500
							/* Ni = (R*Ri-1) / N */
501
		if (!BN_div(&(mont->Ni),NULL,Ri,&mont->N,ctx)) goto err;
502
		}
503 504 505
#endif

	/* setup RR for conversions */
506
	BN_zero(&(mont->RR));
507 508
	if (!BN_set_bit(&(mont->RR),mont->ri*2)) goto err;
	if (!BN_mod(&(mont->RR),&(mont->RR),&(mont->N),ctx)) goto err;
509

510
	ret = 1;
511
err:
512 513
	BN_CTX_end(ctx);
	return ret;
514 515
	}

U
Ulf Möller 已提交
516
BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from)
517 518 519
	{
	if (to == from) return(to);

B
Bodo Möller 已提交
520 521 522
	if (!BN_copy(&(to->RR),&(from->RR))) return NULL;
	if (!BN_copy(&(to->N),&(from->N))) return NULL;
	if (!BN_copy(&(to->Ni),&(from->Ni))) return NULL;
523
	to->ri=from->ri;
524 525
	to->n0[0]=from->n0[0];
	to->n0[1]=from->n0[1];
526 527 528
	return(to);
	}

529 530 531
BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, int lock,
					const BIGNUM *mod, BN_CTX *ctx)
	{
B
Bodo Möller 已提交
532
	int got_write_lock = 0;
B
Bodo Möller 已提交
533
	BN_MONT_CTX *ret;
B
Bodo Möller 已提交
534 535

	CRYPTO_r_lock(lock);
536 537
	if (!*pmont)
		{
B
Bodo Möller 已提交
538 539 540 541 542 543
		CRYPTO_r_unlock(lock);
		CRYPTO_w_lock(lock);
		got_write_lock = 1;

		if (!*pmont)
			{
B
Bodo Möller 已提交
544 545 546
			ret = BN_MONT_CTX_new();
			if (ret && !BN_MONT_CTX_set(ret, mod, ctx))
				BN_MONT_CTX_free(ret);
B
Bodo Möller 已提交
547
			else
B
Bodo Möller 已提交
548
				*pmont = ret;
B
Bodo Möller 已提交
549
			}
550
		}
B
Bodo Möller 已提交
551
	
B
Bodo Möller 已提交
552 553
	ret = *pmont;
	
B
Bodo Möller 已提交
554 555 556 557 558
	if (got_write_lock)
		CRYPTO_w_unlock(lock);
	else
		CRYPTO_r_unlock(lock);
		
B
Bodo Möller 已提交
559
	return ret;
560
	}