Branch data Line data Source code
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 : : #define OPENSSL_FIPSAPI
120 : :
121 : : #include <stdio.h>
122 : : #include "cryptlib.h"
123 : : #include "bn_lcl.h"
124 : :
125 : : #define MONT_WORD /* use the faster word-based algorithm */
126 : :
127 : : #ifdef MONT_WORD
128 : : static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont);
129 : : #endif
130 : :
131 : 2724090 : int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
132 : : BN_MONT_CTX *mont, BN_CTX *ctx)
133 : : {
134 : : BIGNUM *tmp;
135 : 2724090 : int ret=0;
136 : : #if defined(OPENSSL_BN_ASM_MONT) && defined(MONT_WORD)
137 : 2724090 : int num = mont->N.top;
138 : :
139 [ + + ][ + + ]: 2724090 : if (num>1 && a->top==num && b->top==num)
[ + + ]
140 : : {
141 [ + + ][ + - ]: 2695302 : if (bn_wexpand(r,num) == NULL) return(0);
142 [ + - ]: 2695302 : if (bn_mul_mont(r->d,a->d,b->d,mont->N.d,mont->n0,num))
143 : : {
144 : 2695302 : r->neg = a->neg^b->neg;
145 : 2695302 : r->top = num;
146 [ + - ][ + + ]: 2697261 : bn_correct_top(r);
[ + - ]
147 : : return(1);
148 : : }
149 : : }
150 : : #endif
151 : :
152 : 28788 : BN_CTX_start(ctx);
153 : 28788 : tmp = BN_CTX_get(ctx);
154 [ + - ]: 28788 : if (tmp == NULL) goto err;
155 : :
156 : : bn_check_top(tmp);
157 [ + + ]: 28788 : if (a == b)
158 : : {
159 [ + - ]: 10187 : if (!BN_sqr(tmp,a,ctx)) goto err;
160 : : }
161 : : else
162 : : {
163 [ + - ]: 18601 : if (!BN_mul(tmp,a,b,ctx)) goto err;
164 : : }
165 : : /* reduce from aRR to aR */
166 : : #ifdef MONT_WORD
167 [ + - ]: 28788 : if (!BN_from_montgomery_word(r,tmp,mont)) goto err;
168 : : #else
169 : : if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err;
170 : : #endif
171 : : bn_check_top(r);
172 : 28788 : ret=1;
173 : : err:
174 : 28788 : BN_CTX_end(ctx);
175 : 28788 : return(ret);
176 : : }
177 : :
178 : : #ifdef MONT_WORD
179 : 37371 : static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
180 : : {
181 : : BIGNUM *n;
182 : : BN_ULONG *ap,*np,*rp,n0,v,carry;
183 : : int nl,max,i;
184 : :
185 : 37371 : n= &(mont->N);
186 : 37371 : nl=n->top;
187 [ - + ]: 37371 : if (nl == 0) { ret->top=0; return(1); }
188 : :
189 : 37371 : max=(2*nl); /* carry is stored separately */
190 [ + + ][ + - ]: 37371 : if (bn_wexpand(r,max) == NULL) return(0);
191 : :
192 : 37371 : r->neg^=n->neg;
193 : 37371 : np=n->d;
194 : 37371 : rp=r->d;
195 : :
196 : : /* clear the top words of T */
197 : : #if 1
198 [ + + ]: 256014 : for (i=r->top; i<max; i++) /* memset? XXX */
199 : 218643 : rp[i]=0;
200 : : #else
201 : : memset(&(rp[r->top]),0,(max-r->top)*sizeof(BN_ULONG));
202 : : #endif
203 : :
204 : 37371 : r->top=max;
205 : 37371 : n0=mont->n0[0];
206 : :
207 : : #ifdef BN_COUNT
208 : : fprintf(stderr,"word BN_from_montgomery_word %d * %d\n",nl,nl);
209 : : #endif
210 [ + + ]: 245871 : for (carry=0, i=0; i<nl; i++, rp++)
211 : : {
212 : : #ifdef __TANDEM
213 : : {
214 : : long long t1;
215 : : long long t2;
216 : : long long t3;
217 : : t1 = rp[0] * (n0 & 0177777);
218 : : t2 = 037777600000l;
219 : : t2 = n0 & t2;
220 : : t3 = rp[0] & 0177777;
221 : : t2 = (t3 * t2) & BN_MASK2;
222 : : t1 = t1 + t2;
223 : : v=bn_mul_add_words(rp,np,nl,(BN_ULONG) t1);
224 : : }
225 : : #else
226 : 208500 : v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
227 : : #endif
228 : 208500 : v = (v+carry+rp[nl])&BN_MASK2;
229 : 208500 : carry |= (v != rp[nl]);
230 : 208500 : carry &= (v <= rp[nl]);
231 : 208500 : rp[nl]=v;
232 : : }
233 : :
234 [ + + ][ + - ]: 37371 : if (bn_wexpand(ret,nl) == NULL) return(0);
235 : 37371 : ret->top=nl;
236 : 37371 : ret->neg=r->neg;
237 : :
238 : 37371 : rp=ret->d;
239 : 37371 : ap=&(r->d[nl]);
240 : :
241 : : #define BRANCH_FREE 1
242 : : #if BRANCH_FREE
243 : : {
244 : : BN_ULONG *nrp;
245 : : size_t m;
246 : :
247 : 37371 : v=bn_sub_words(rp,ap,np,nl)-carry;
248 : : /* if subtraction result is real, then
249 : : * trick unconditional memcpy below to perform in-place
250 : : * "refresh" instead of actual copy. */
251 : 37371 : m=(0-(size_t)v);
252 : 37371 : nrp=(BN_ULONG *)(((PTR_SIZE_INT)rp&~m)|((PTR_SIZE_INT)ap&m));
253 : :
254 [ + + ]: 63890 : for (i=0,nl-=4; i<nl; i+=4)
255 : : {
256 : : BN_ULONG t1,t2,t3,t4;
257 : :
258 : 26519 : t1=nrp[i+0];
259 : 26519 : t2=nrp[i+1];
260 : 26519 : t3=nrp[i+2]; ap[i+0]=0;
261 : 26519 : t4=nrp[i+3]; ap[i+1]=0;
262 : 26519 : rp[i+0]=t1; ap[i+2]=0;
263 : 26519 : rp[i+1]=t2; ap[i+3]=0;
264 : 26519 : rp[i+2]=t3;
265 : 26519 : rp[i+3]=t4;
266 : : }
267 [ + + ]: 139795 : for (nl+=4; i<nl; i++)
268 : 102424 : rp[i]=nrp[i], ap[i]=0;
269 : : }
270 : : #else
271 : : if (bn_sub_words (rp,ap,np,nl)-carry)
272 : : memcpy(rp,ap,nl*sizeof(BN_ULONG));
273 : : #endif
274 [ + - ][ + - ]: 454371 : bn_correct_top(r);
[ + + ]
275 [ + - ][ + + ]: 80935 : bn_correct_top(ret);
[ + + ]
276 : : bn_check_top(ret);
277 : :
278 : : return(1);
279 : : }
280 : : #endif /* MONT_WORD */
281 : :
282 : 8583 : int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont,
283 : : BN_CTX *ctx)
284 : : {
285 : 8583 : int retn=0;
286 : : #ifdef MONT_WORD
287 : : BIGNUM *t;
288 : :
289 : 8583 : BN_CTX_start(ctx);
290 [ + - ][ + - ]: 8583 : if ((t = BN_CTX_get(ctx)) && BN_copy(t,a))
291 : 8583 : retn = BN_from_montgomery_word(ret,t,mont);
292 : 8583 : BN_CTX_end(ctx);
293 : : #else /* !MONT_WORD */
294 : : BIGNUM *t1,*t2;
295 : :
296 : : BN_CTX_start(ctx);
297 : : t1 = BN_CTX_get(ctx);
298 : : t2 = BN_CTX_get(ctx);
299 : : if (t1 == NULL || t2 == NULL) goto err;
300 : :
301 : : if (!BN_copy(t1,a)) goto err;
302 : : BN_mask_bits(t1,mont->ri);
303 : :
304 : : if (!BN_mul(t2,t1,&mont->Ni,ctx)) goto err;
305 : : BN_mask_bits(t2,mont->ri);
306 : :
307 : : if (!BN_mul(t1,t2,&mont->N,ctx)) goto err;
308 : : if (!BN_add(t2,a,t1)) goto err;
309 : : if (!BN_rshift(ret,t2,mont->ri)) goto err;
310 : :
311 : : if (BN_ucmp(ret, &(mont->N)) >= 0)
312 : : {
313 : : if (!BN_usub(ret,ret,&(mont->N))) goto err;
314 : : }
315 : : retn=1;
316 : : bn_check_top(ret);
317 : : err:
318 : : BN_CTX_end(ctx);
319 : : #endif /* MONT_WORD */
320 : 8583 : return(retn);
321 : : }
322 : :
323 : 9885 : BN_MONT_CTX *BN_MONT_CTX_new(void)
324 : : {
325 : : BN_MONT_CTX *ret;
326 : :
327 [ + - ]: 9885 : if ((ret=(BN_MONT_CTX *)OPENSSL_malloc(sizeof(BN_MONT_CTX))) == NULL)
328 : : return(NULL);
329 : :
330 : 9885 : BN_MONT_CTX_init(ret);
331 : 9885 : ret->flags=BN_FLG_MALLOCED;
332 : 9885 : return(ret);
333 : : }
334 : :
335 : 9885 : void BN_MONT_CTX_init(BN_MONT_CTX *ctx)
336 : : {
337 : 9885 : ctx->ri=0;
338 : 9885 : BN_init(&(ctx->RR));
339 : 9885 : BN_init(&(ctx->N));
340 : 9885 : BN_init(&(ctx->Ni));
341 : 9885 : ctx->n0[0] = ctx->n0[1] = 0;
342 : 9885 : ctx->flags=0;
343 : 9885 : }
344 : :
345 : 9884 : void BN_MONT_CTX_free(BN_MONT_CTX *mont)
346 : : {
347 [ + - ]: 9884 : if(mont == NULL)
348 : 9884 : return;
349 : :
350 : 9884 : BN_free(&(mont->RR));
351 : 9884 : BN_free(&(mont->N));
352 : 9884 : BN_free(&(mont->Ni));
353 [ + - ]: 9884 : if (mont->flags & BN_FLG_MALLOCED)
354 : 9884 : OPENSSL_free(mont);
355 : : }
356 : :
357 : 9800 : int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
358 : : {
359 : 9800 : int ret = 0;
360 : : BIGNUM *Ri,*R;
361 : :
362 : 9800 : BN_CTX_start(ctx);
363 [ + - ]: 9800 : if((Ri = BN_CTX_get(ctx)) == NULL) goto err;
364 : 9800 : R= &(mont->RR); /* grab RR as a temp */
365 [ + - ]: 9800 : if (!BN_copy(&(mont->N),mod)) goto err; /* Set N */
366 : 9800 : mont->N.neg = 0;
367 : :
368 : : #ifdef MONT_WORD
369 : : {
370 : : BIGNUM tmod;
371 : : BN_ULONG buf[2];
372 : :
373 : 9800 : BN_init(&tmod);
374 : 9800 : tmod.d=buf;
375 : 9800 : tmod.dmax=2;
376 : 9800 : tmod.neg=0;
377 : :
378 : 9800 : mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2;
379 : :
380 : : #if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2<=32)
381 : : /* Only certain BN_BITS2<=32 platforms actually make use of
382 : : * n0[1], and we could use the #else case (with a shorter R
383 : : * value) for the others. However, currently only the assembler
384 : : * files do know which is which. */
385 : :
386 : : BN_zero(R);
387 : : if (!(BN_set_bit(R,2*BN_BITS2))) goto err;
388 : :
389 : : tmod.top=0;
390 : : if ((buf[0] = mod->d[0])) tmod.top=1;
391 : : if ((buf[1] = mod->top>1 ? mod->d[1] : 0)) tmod.top=2;
392 : :
393 : : if ((BN_mod_inverse(Ri,R,&tmod,ctx)) == NULL)
394 : : goto err;
395 : : if (!BN_lshift(Ri,Ri,2*BN_BITS2)) goto err; /* R*Ri */
396 : : if (!BN_is_zero(Ri))
397 : : {
398 : : if (!BN_sub_word(Ri,1)) goto err;
399 : : }
400 : : else /* if N mod word size == 1 */
401 : : {
402 : : if (bn_expand(Ri,(int)sizeof(BN_ULONG)*2) == NULL)
403 : : goto err;
404 : : /* Ri-- (mod double word size) */
405 : : Ri->neg=0;
406 : : Ri->d[0]=BN_MASK2;
407 : : Ri->d[1]=BN_MASK2;
408 : : Ri->top=2;
409 : : }
410 : : if (!BN_div(Ri,NULL,Ri,&tmod,ctx)) goto err;
411 : : /* Ni = (R*Ri-1)/N,
412 : : * keep only couple of least significant words: */
413 : : mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
414 : : mont->n0[1] = (Ri->top > 1) ? Ri->d[1] : 0;
415 : : #else
416 : 9800 : BN_zero(R);
417 [ + - ]: 9800 : if (!(BN_set_bit(R,BN_BITS2))) goto err; /* R */
418 : :
419 : 9800 : buf[0]=mod->d[0]; /* tmod = N mod word size */
420 : 9800 : buf[1]=0;
421 : 9800 : tmod.top = buf[0] != 0 ? 1 : 0;
422 : : /* Ri = R^-1 mod N*/
423 [ + - ]: 9800 : if ((BN_mod_inverse(Ri,R,&tmod,ctx)) == NULL)
424 : : goto err;
425 [ + - ]: 9800 : if (!BN_lshift(Ri,Ri,BN_BITS2)) goto err; /* R*Ri */
426 [ + + ]: 9800 : if (!BN_is_zero(Ri))
427 : : {
428 [ + - ]: 9788 : if (!BN_sub_word(Ri,1)) goto err;
429 : : }
430 : : else /* if N mod word size == 1 */
431 : : {
432 [ + - ]: 12 : if (!BN_set_word(Ri,BN_MASK2)) goto err; /* Ri-- (mod word size) */
433 : : }
434 [ + - ]: 9800 : if (!BN_div(Ri,NULL,Ri,&tmod,ctx)) goto err;
435 : : /* Ni = (R*Ri-1)/N,
436 : : * keep only least significant word: */
437 [ + - ]: 9800 : mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
438 : 9800 : mont->n0[1] = 0;
439 : : #endif
440 : : }
441 : : #else /* !MONT_WORD */
442 : : { /* bignum version */
443 : : mont->ri=BN_num_bits(&mont->N);
444 : : BN_zero(R);
445 : : if (!BN_set_bit(R,mont->ri)) goto err; /* R = 2^ri */
446 : : /* Ri = R^-1 mod N*/
447 : : if ((BN_mod_inverse(Ri,R,&mont->N,ctx)) == NULL)
448 : : goto err;
449 : : if (!BN_lshift(Ri,Ri,mont->ri)) goto err; /* R*Ri */
450 : : if (!BN_sub_word(Ri,1)) goto err;
451 : : /* Ni = (R*Ri-1) / N */
452 : : if (!BN_div(&(mont->Ni),NULL,Ri,&mont->N,ctx)) goto err;
453 : : }
454 : : #endif
455 : :
456 : : /* setup RR for conversions */
457 : 9800 : BN_zero(&(mont->RR));
458 [ + - ]: 9800 : if (!BN_set_bit(&(mont->RR),mont->ri*2)) goto err;
459 [ + - ]: 9800 : if (!BN_mod(&(mont->RR),&(mont->RR),&(mont->N),ctx)) goto err;
460 : :
461 : 9800 : ret = 1;
462 : : err:
463 : 9800 : BN_CTX_end(ctx);
464 : 9800 : return ret;
465 : : }
466 : :
467 : 89 : BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from)
468 : : {
469 [ + - ]: 89 : if (to == from) return(to);
470 : :
471 [ + - ]: 89 : if (!BN_copy(&(to->RR),&(from->RR))) return NULL;
472 [ + - ]: 89 : if (!BN_copy(&(to->N),&(from->N))) return NULL;
473 [ + - ]: 89 : if (!BN_copy(&(to->Ni),&(from->Ni))) return NULL;
474 : 89 : to->ri=from->ri;
475 : 89 : to->n0[0]=from->n0[0];
476 : 89 : to->n0[1]=from->n0[1];
477 : 89 : return(to);
478 : : }
479 : :
480 : 7687 : BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, int lock,
481 : : const BIGNUM *mod, BN_CTX *ctx)
482 : : {
483 : : BN_MONT_CTX *ret;
484 : :
485 : 7687 : CRYPTO_r_lock(lock);
486 : 7687 : ret = *pmont;
487 : 7687 : CRYPTO_r_unlock(lock);
488 [ + + ]: 7687 : if (ret)
489 : : return ret;
490 : :
491 : : /* We don't want to serialise globally while doing our lazy-init math in
492 : : * BN_MONT_CTX_set. That punishes threads that are doing independent
493 : : * things. Instead, punish the case where more than one thread tries to
494 : : * lazy-init the same 'pmont', by having each do the lazy-init math work
495 : : * independently and only use the one from the thread that wins the race
496 : : * (the losers throw away the work they've done). */
497 : 6606 : ret = BN_MONT_CTX_new();
498 [ + - ]: 6606 : if (!ret)
499 : : return NULL;
500 [ - + ]: 6606 : if (!BN_MONT_CTX_set(ret, mod, ctx))
501 : : {
502 : 0 : BN_MONT_CTX_free(ret);
503 : 0 : return NULL;
504 : : }
505 : :
506 : : /* The locked compare-and-set, after the local work is done. */
507 : 6606 : CRYPTO_w_lock(lock);
508 [ - + ]: 6606 : if (*pmont)
509 : : {
510 : 0 : BN_MONT_CTX_free(ret);
511 : 0 : ret = *pmont;
512 : : }
513 : : else
514 : 6606 : *pmont = ret;
515 : 6606 : CRYPTO_w_unlock(lock);
516 : 6606 : return ret;
517 : : }
|