• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2  * All rights reserved.
3  *
4  * This package is an SSL implementation written
5  * by Eric Young (eay@cryptsoft.com).
6  * The implementation was written so as to conform with Netscapes SSL.
7  *
8  * This library is free for commercial and non-commercial use as long as
9  * the following conditions are aheared to.  The following conditions
10  * apply to all code found in this distribution, be it the RC4, RSA,
11  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12  * included with this distribution is covered by the same copyright terms
13  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14  *
15  * Copyright remains Eric Young's, and as such any Copyright notices in
16  * the code are not to be removed.
17  * If this package is used in a product, Eric Young should be given attribution
18  * as the author of the parts of the library used.
19  * This can be in the form of a textual message at program startup or
20  * in documentation (online or textual) provided with the package.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the copyright
26  *    notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *    notice, this list of conditions and the following disclaimer in the
29  *    documentation and/or other materials provided with the distribution.
30  * 3. All advertising materials mentioning features or use of this software
31  *    must display the following acknowledgement:
32  *    "This product includes cryptographic software written by
33  *     Eric Young (eay@cryptsoft.com)"
34  *    The word 'cryptographic' can be left out if the rouines from the library
35  *    being used are not cryptographic related :-).
36  * 4. If you include any Windows specific code (or a derivative thereof) from
37  *    the apps directory (application code) you must include an acknowledgement:
38  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  *
52  * The licence and distribution terms for any publically available version or
53  * derivative of this code cannot be changed.  i.e. this code cannot simply be
54  * copied and put under another distribution licence
55  * [including the GNU Public Licence.]
56  */
57 /* ====================================================================
58  * Copyright (c) 1998-2006 The OpenSSL Project.  All rights reserved.
59  *
60  * Redistribution and use in source and binary forms, with or without
61  * modification, are permitted provided that the following conditions
62  * are met:
63  *
64  * 1. Redistributions of source code must retain the above copyright
65  *    notice, this list of conditions and the following disclaimer.
66  *
67  * 2. Redistributions in binary form must reproduce the above copyright
68  *    notice, this list of conditions and the following disclaimer in
69  *    the documentation and/or other materials provided with the
70  *    distribution.
71  *
72  * 3. All advertising materials mentioning features or use of this
73  *    software must display the following acknowledgment:
74  *    "This product includes software developed by the OpenSSL Project
75  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
76  *
77  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
78  *    endorse or promote products derived from this software without
79  *    prior written permission. For written permission, please contact
80  *    openssl-core@openssl.org.
81  *
82  * 5. Products derived from this software may not be called "OpenSSL"
83  *    nor may "OpenSSL" appear in their names without prior written
84  *    permission of the OpenSSL Project.
85  *
86  * 6. Redistributions of any form whatsoever must retain the following
87  *    acknowledgment:
88  *    "This product includes software developed by the OpenSSL Project
89  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
90  *
91  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
92  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
93  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
94  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
95  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
96  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
97  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
98  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
99  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
100  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
101  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
102  * OF THE POSSIBILITY OF SUCH DAMAGE.
103  * ====================================================================
104  *
105  * This product includes cryptographic software written by Eric Young
106  * (eay@cryptsoft.com).  This product includes software written by Tim
107  * Hudson (tjh@cryptsoft.com). */
108 
109 #include <openssl/bn.h>
110 
111 #include <openssl/mem.h>
112 #include <openssl/thread.h>
113 
114 #include "internal.h"
115 
116 
117 #if !defined(OPENSSL_NO_ASM) && \
118     (defined(OPENSSL_X86) || defined(OPENSSL_X86_64))
119 #define OPENSSL_BN_ASM_MONT
120 #endif
121 
BN_MONT_CTX_new(void)122 BN_MONT_CTX *BN_MONT_CTX_new(void) {
123   BN_MONT_CTX *ret = OPENSSL_malloc(sizeof(BN_MONT_CTX));
124 
125   if (ret == NULL) {
126     return NULL;
127   }
128 
129   BN_MONT_CTX_init(ret);
130   ret->flags = BN_FLG_MALLOCED;
131   return ret;
132 }
133 
BN_MONT_CTX_init(BN_MONT_CTX * mont)134 void BN_MONT_CTX_init(BN_MONT_CTX *mont) {
135   memset(mont, 0, sizeof(BN_MONT_CTX));
136   BN_init(&mont->RR);
137   BN_init(&mont->N);
138   BN_init(&mont->Ni);
139 }
140 
BN_MONT_CTX_free(BN_MONT_CTX * mont)141 void BN_MONT_CTX_free(BN_MONT_CTX *mont) {
142   if (mont == NULL) {
143     return;
144   }
145 
146   BN_free(&mont->RR);
147   BN_free(&mont->N);
148   BN_free(&mont->Ni);
149   if (mont->flags & BN_FLG_MALLOCED) {
150     OPENSSL_free(mont);
151   }
152 }
153 
BN_MONT_CTX_copy(BN_MONT_CTX * to,BN_MONT_CTX * from)154 BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from) {
155   if (to == from) {
156     return to;
157   }
158 
159   if (!BN_copy(&to->RR, &from->RR) ||
160       !BN_copy(&to->N, &from->N) ||
161       !BN_copy(&to->Ni, &from->Ni)) {
162     return NULL;
163   }
164   to->ri = from->ri;
165   to->n0[0] = from->n0[0];
166   to->n0[1] = from->n0[1];
167   return to;
168 }
169 
BN_MONT_CTX_set(BN_MONT_CTX * mont,const BIGNUM * mod,BN_CTX * ctx)170 int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) {
171   int ret = 0;
172   BIGNUM *Ri, *R;
173   BIGNUM tmod;
174   BN_ULONG buf[2];
175 
176   BN_CTX_start(ctx);
177   Ri = BN_CTX_get(ctx);
178   if (Ri == NULL) {
179     goto err;
180   }
181   R = &mont->RR; /* grab RR as a temp */
182   if (!BN_copy(&mont->N, mod)) {
183     goto err; /* Set N */
184   }
185   mont->N.neg = 0;
186 
187   BN_init(&tmod);
188   tmod.d = buf;
189   tmod.dmax = 2;
190   tmod.neg = 0;
191 
192   mont->ri = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2;
193 
194 #if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2 <= 32)
195   /* Only certain BN_BITS2<=32 platforms actually make use of
196    * n0[1], and we could use the #else case (with a shorter R
197    * value) for the others.  However, currently only the assembler
198    * files do know which is which. */
199 
200   BN_zero(R);
201   if (!BN_set_bit(R, 2 * BN_BITS2)) {
202     goto err;
203   }
204 
205   tmod.top = 0;
206   if ((buf[0] = mod->d[0])) {
207     tmod.top = 1;
208   }
209   if ((buf[1] = mod->top > 1 ? mod->d[1] : 0)) {
210     tmod.top = 2;
211   }
212 
213   if (BN_mod_inverse(Ri, R, &tmod, ctx) == NULL) {
214     goto err;
215   }
216   if (!BN_lshift(Ri, Ri, 2 * BN_BITS2)) {
217     goto err; /* R*Ri */
218   }
219   if (!BN_is_zero(Ri)) {
220     if (!BN_sub_word(Ri, 1)) {
221       goto err;
222     }
223   } else {
224     /* if N mod word size == 1 */
225     if (bn_expand(Ri, (int)sizeof(BN_ULONG) * 2) == NULL) {
226       goto err;
227     }
228     /* Ri-- (mod double word size) */
229     Ri->neg = 0;
230     Ri->d[0] = BN_MASK2;
231     Ri->d[1] = BN_MASK2;
232     Ri->top = 2;
233   }
234 
235   if (!BN_div(Ri, NULL, Ri, &tmod, ctx)) {
236     goto err;
237   }
238   /* Ni = (R*Ri-1)/N,
239    * keep only couple of least significant words: */
240   mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
241   mont->n0[1] = (Ri->top > 1) ? Ri->d[1] : 0;
242 #else
243   BN_zero(R);
244   if (!BN_set_bit(R, BN_BITS2)) {
245     goto err; /* R */
246   }
247 
248   buf[0] = mod->d[0]; /* tmod = N mod word size */
249   buf[1] = 0;
250   tmod.top = buf[0] != 0 ? 1 : 0;
251   /* Ri = R^-1 mod N*/
252   if (BN_mod_inverse(Ri, R, &tmod, ctx) == NULL) {
253     goto err;
254   }
255   if (!BN_lshift(Ri, Ri, BN_BITS2)) {
256     goto err; /* R*Ri */
257   }
258   if (!BN_is_zero(Ri)) {
259     if (!BN_sub_word(Ri, 1)) {
260       goto err;
261     }
262   } else {
263     /* if N mod word size == 1 */
264     if (!BN_set_word(Ri, BN_MASK2)) {
265       goto err; /* Ri-- (mod word size) */
266     }
267   }
268   if (!BN_div(Ri, NULL, Ri, &tmod, ctx)) {
269     goto err;
270   }
271   /* Ni = (R*Ri-1)/N,
272    * keep only least significant word: */
273   mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
274   mont->n0[1] = 0;
275 #endif
276 
277   /* setup RR for conversions */
278   BN_zero(&(mont->RR));
279   if (!BN_set_bit(&(mont->RR), mont->ri * 2)) {
280     goto err;
281   }
282   if (!BN_mod(&(mont->RR), &(mont->RR), &(mont->N), ctx)) {
283     goto err;
284   }
285 
286   ret = 1;
287 
288 err:
289   BN_CTX_end(ctx);
290   return ret;
291 }
292 
BN_MONT_CTX_set_locked(BN_MONT_CTX ** pmont,int lock,const BIGNUM * mod,BN_CTX * ctx)293 BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, int lock,
294                                     const BIGNUM *mod, BN_CTX *ctx) {
295   BN_MONT_CTX *ret;
296 
297   CRYPTO_r_lock(lock);
298   ret = *pmont;
299   CRYPTO_r_unlock(lock);
300   if (ret) {
301     return ret;
302   }
303 
304   /* We don't want to serialise globally while doing our lazy-init math in
305    * BN_MONT_CTX_set. That punishes threads that are doing independent
306    * things. Instead, punish the case where more than one thread tries to
307    * lazy-init the same 'pmont', by having each do the lazy-init math work
308    * independently and only use the one from the thread that wins the race
309    * (the losers throw away the work they've done). */
310   ret = BN_MONT_CTX_new();
311   if (!ret) {
312     return NULL;
313   }
314   if (!BN_MONT_CTX_set(ret, mod, ctx)) {
315     BN_MONT_CTX_free(ret);
316     return NULL;
317   }
318 
319   /* The locked compare-and-set, after the local work is done. */
320   CRYPTO_w_lock(lock);
321   if (*pmont) {
322     BN_MONT_CTX_free(ret);
323     ret = *pmont;
324   } else {
325     *pmont = ret;
326   }
327 
328   CRYPTO_w_unlock(lock);
329 
330   return ret;
331 }
332 
BN_to_montgomery(BIGNUM * ret,const BIGNUM * a,const BN_MONT_CTX * mont,BN_CTX * ctx)333 int BN_to_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont,
334                      BN_CTX *ctx) {
335   return BN_mod_mul_montgomery(ret, a, &mont->RR, mont, ctx);
336 }
337 
338 #if 0
339 static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r,
340                                    const BN_MONT_CTX *mont) {
341   const BIGNUM *n;
342   BN_ULONG *ap, *np, *rp, n0, v, carry;
343   int nl, max, i;
344 
345   n = &mont->N;
346   nl = n->top;
347   if (nl == 0) {
348     ret->top = 0;
349     return 1;
350   }
351 
352   max = (2 * nl); /* carry is stored separately */
353   if (bn_wexpand(r, max) == NULL) {
354     return 0;
355   }
356 
357   r->neg ^= n->neg;
358   np = n->d;
359   rp = r->d;
360 
361   /* clear the top words of T */
362   if (max > r->top) {
363     memset(&rp[r->top], 0, (max - r->top) * sizeof(BN_ULONG));
364   }
365 
366   r->top = max;
367   n0 = mont->n0[0];
368 
369   for (carry = 0, i = 0; i < nl; i++, rp++) {
370     v = bn_mul_add_words(rp, np, nl, (rp[0] * n0) & BN_MASK2);
371     v = (v + carry + rp[nl]) & BN_MASK2;
372     carry |= (v != rp[nl]);
373     carry &= (v <= rp[nl]);
374     rp[nl] = v;
375   }
376 
377   if (bn_wexpand(ret, nl) == NULL) {
378     return 0;
379   }
380   ret->top = nl;
381   ret->neg = r->neg;
382 
383   rp = ret->d;
384   ap = &(r->d[nl]);
385 
386   {
387     BN_ULONG *nrp;
388     size_t m;
389 
390     v = bn_sub_words(rp, ap, np, nl) - carry;
391     /* if subtraction result is real, then trick unconditional memcpy below to
392      * perform in-place "refresh" instead of actual copy. */
393     m = (0 - (size_t)v);
394     nrp = (BN_ULONG *)(((intptr_t)rp & ~m) | ((intptr_t)ap & m));
395 
396     for (i = 0, nl -= 4; i < nl; i += 4) {
397       BN_ULONG t1, t2, t3, t4;
398 
399       t1 = nrp[i + 0];
400       t2 = nrp[i + 1];
401       t3 = nrp[i + 2];
402       ap[i + 0] = 0;
403       t4 = nrp[i + 3];
404       ap[i + 1] = 0;
405       rp[i + 0] = t1;
406       ap[i + 2] = 0;
407       rp[i + 1] = t2;
408       ap[i + 3] = 0;
409       rp[i + 2] = t3;
410       rp[i + 3] = t4;
411     }
412 
413     for (nl += 4; i < nl; i++) {
414       rp[i] = nrp[i], ap[i] = 0;
415     }
416   }
417 
418   bn_correct_top(r);
419   bn_correct_top(ret);
420 
421   return 1;
422 }
423 #endif
424 
425 #define PTR_SIZE_INT size_t
426 
BN_from_montgomery_word(BIGNUM * ret,BIGNUM * r,const BN_MONT_CTX * mont)427 static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, const BN_MONT_CTX *mont)
428 	{
429 	BIGNUM *n;
430 	BN_ULONG *ap,*np,*rp,n0,v,carry;
431 	int nl,max,i;
432 
433 	n= (BIGNUM*) &(mont->N);
434 	nl=n->top;
435 	if (nl == 0) { ret->top=0; return(1); }
436 
437 	max=(2*nl); /* carry is stored separately */
438 	if (bn_wexpand(r,max) == NULL) return(0);
439 
440 	r->neg^=n->neg;
441 	np=n->d;
442 	rp=r->d;
443 
444 	/* clear the top words of T */
445 #if 1
446 	for (i=r->top; i<max; i++) /* memset? XXX */
447 		rp[i]=0;
448 #else
449 	memset(&(rp[r->top]),0,(max-r->top)*sizeof(BN_ULONG));
450 #endif
451 
452 	r->top=max;
453 	n0=mont->n0[0];
454 
455 	for (carry=0, i=0; i<nl; i++, rp++)
456 		{
457 		v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
458 		v = (v+carry+rp[nl])&BN_MASK2;
459 		carry |= (v != rp[nl]);
460 		carry &= (v <= rp[nl]);
461 		rp[nl]=v;
462 		}
463 
464 	if (bn_wexpand(ret,nl) == NULL) return(0);
465 	ret->top=nl;
466 	ret->neg=r->neg;
467 
468 	rp=ret->d;
469 	ap=&(r->d[nl]);
470 
471 	{
472 	BN_ULONG *nrp;
473 	size_t m;
474 
475 	v=bn_sub_words(rp,ap,np,nl)-carry;
476 	/* if subtraction result is real, then
477 	 * trick unconditional memcpy below to perform in-place
478 	 * "refresh" instead of actual copy. */
479 	m=(0-(size_t)v);
480 	nrp=(BN_ULONG *)(((PTR_SIZE_INT)rp&~m)|((PTR_SIZE_INT)ap&m));
481 
482 	for (i=0,nl-=4; i<nl; i+=4)
483 		{
484 		BN_ULONG t1,t2,t3,t4;
485 
486 		t1=nrp[i+0];
487 		t2=nrp[i+1];
488 		t3=nrp[i+2];	ap[i+0]=0;
489 		t4=nrp[i+3];	ap[i+1]=0;
490 		rp[i+0]=t1;	ap[i+2]=0;
491 		rp[i+1]=t2;	ap[i+3]=0;
492 		rp[i+2]=t3;
493 		rp[i+3]=t4;
494 		}
495 	for (nl+=4; i<nl; i++)
496 		rp[i]=nrp[i], ap[i]=0;
497 	}
498 	bn_correct_top(r);
499 	bn_correct_top(ret);
500 
501 	return(1);
502 	}
503 
BN_from_montgomery(BIGNUM * ret,const BIGNUM * a,const BN_MONT_CTX * mont,BN_CTX * ctx)504 int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont,
505                        BN_CTX *ctx) {
506   int retn = 0;
507   BIGNUM *t;
508 
509   BN_CTX_start(ctx);
510   t = BN_CTX_get(ctx);
511   if (t == NULL) {
512     return 0;
513   }
514 
515   if (BN_copy(t, a))
516     retn = BN_from_montgomery_word(ret, t, mont);
517   BN_CTX_end(ctx);
518 
519   return retn;
520 }
521 
BN_mod_mul_montgomery(BIGNUM * r,const BIGNUM * a,const BIGNUM * b,const BN_MONT_CTX * mont,BN_CTX * ctx)522 int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
523                           const BN_MONT_CTX *mont, BN_CTX *ctx) {
524   BIGNUM *tmp;
525   int ret = 0;
526 
527 #if defined(OPENSSL_BN_ASM_MONT)
528   int num = mont->N.top;
529 
530   if (num > 1 && a->top == num && b->top == num) {
531     if (bn_wexpand(r, num) == NULL) {
532       return 0;
533     }
534     if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
535       r->neg = a->neg ^ b->neg;
536       r->top = num;
537       bn_correct_top(r);
538       return 1;
539     }
540   }
541 #endif
542 
543   BN_CTX_start(ctx);
544   tmp = BN_CTX_get(ctx);
545   if (tmp == NULL) {
546     goto err;
547   }
548 
549   if (a == b) {
550     if (!BN_sqr(tmp, a, ctx)) {
551       goto err;
552     }
553   } else {
554     if (!BN_mul(tmp, a, b, ctx)) {
555       goto err;
556     }
557   }
558 
559   /* reduce from aRR to aR */
560   if (!BN_from_montgomery_word(r, tmp, mont)) {
561     goto err;
562   }
563 
564   ret = 1;
565 
566 err:
567   BN_CTX_end(ctx);
568   return ret;
569 }
570