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