bn_mont.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  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. * Details about Montgomery multiplication algorithms can be found at
  60. * http://security.ece.orst.edu/publications.html, e.g.
  61. * http://security.ece.orst.edu/koc/papers/j37acmon.pdf and
  62. * sections 3.8 and 4.2 in http://security.ece.orst.edu/koc/papers/r01rsasw.pdf
  63. */
  64. #include <stdio.h>
  65. #include "cryptlib.h"
  66. #include "bn_lcl.h"
  67. #define MONT_WORD /* use the faster word-based algorithm */
  68. int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
  69. BN_MONT_CTX *mont, BN_CTX *ctx)
  70. {
  71. BIGNUM *tmp;
  72. int ret=0;
  73. BN_CTX_start(ctx);
  74. tmp = BN_CTX_get(ctx);
  75. if (tmp == NULL) goto err;
  76. bn_check_top(tmp);
  77. if (a == b)
  78. {
  79. if (!BN_sqr(tmp,a,ctx)) goto err;
  80. }
  81. else
  82. {
  83. if (!BN_mul(tmp,a,b,ctx)) goto err;
  84. }
  85. /* reduce from aRR to aR */
  86. if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err;
  87. ret=1;
  88. err:
  89. BN_CTX_end(ctx);
  90. return(ret);
  91. }
  92. int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont,
  93. BN_CTX *ctx)
  94. {
  95. int retn=0;
  96. #ifdef MONT_WORD
  97. BIGNUM *n,*r;
  98. BN_ULONG *ap,*np,*rp,n0,v,*nrp;
  99. int al,nl,max,i,x,ri;
  100. BN_CTX_start(ctx);
  101. if ((r = BN_CTX_get(ctx)) == NULL) goto err;
  102. if (!BN_copy(r,a)) goto err;
  103. n= &(mont->N);
  104. ap=a->d;
  105. /* mont->ri is the size of mont->N in bits (rounded up
  106. to the word size) */
  107. al=ri=mont->ri/BN_BITS2;
  108. nl=n->top;
  109. if ((al == 0) || (nl == 0)) { r->top=0; return(1); }
  110. max=(nl+al+1); /* allow for overflow (no?) XXX */
  111. if (bn_wexpand(r,max) == NULL) goto err;
  112. if (bn_wexpand(ret,max) == NULL) goto err;
  113. r->neg=a->neg^n->neg;
  114. np=n->d;
  115. rp=r->d;
  116. nrp= &(r->d[nl]);
  117. /* clear the top words of T */
  118. #if 1
  119. for (i=r->top; i<max; i++) /* memset? XXX */
  120. r->d[i]=0;
  121. #else
  122. memset(&(r->d[r->top]),0,(max-r->top)*sizeof(BN_ULONG));
  123. #endif
  124. r->top=max;
  125. n0=mont->n0;
  126. #ifdef BN_COUNT
  127. fprintf(stderr,"word BN_from_montgomery %d * %d\n",nl,nl);
  128. #endif
  129. for (i=0; i<nl; i++)
  130. {
  131. #ifdef __TANDEM
  132. {
  133. long long t1;
  134. long long t2;
  135. long long t3;
  136. t1 = rp[0] * (n0 & 0177777);
  137. t2 = 037777600000l;
  138. t2 = n0 & t2;
  139. t3 = rp[0] & 0177777;
  140. t2 = (t3 * t2) & BN_MASK2;
  141. t1 = t1 + t2;
  142. v=bn_mul_add_words(rp,np,nl,(BN_ULONG) t1);
  143. }
  144. #else
  145. v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
  146. #endif
  147. nrp++;
  148. rp++;
  149. if (((nrp[-1]+=v)&BN_MASK2) >= v)
  150. continue;
  151. else
  152. {
  153. if (((++nrp[0])&BN_MASK2) != 0) continue;
  154. if (((++nrp[1])&BN_MASK2) != 0) continue;
  155. for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ;
  156. }
  157. }
  158. bn_fix_top(r);
  159. /* mont->ri will be a multiple of the word size */
  160. #if 0
  161. BN_rshift(ret,r,mont->ri);
  162. #else
  163. ret->neg = r->neg;
  164. x=ri;
  165. rp=ret->d;
  166. ap= &(r->d[x]);
  167. if (r->top < x)
  168. al=0;
  169. else
  170. al=r->top-x;
  171. ret->top=al;
  172. al-=4;
  173. for (i=0; i<al; i+=4)
  174. {
  175. BN_ULONG t1,t2,t3,t4;
  176. t1=ap[i+0];
  177. t2=ap[i+1];
  178. t3=ap[i+2];
  179. t4=ap[i+3];
  180. rp[i+0]=t1;
  181. rp[i+1]=t2;
  182. rp[i+2]=t3;
  183. rp[i+3]=t4;
  184. }
  185. al+=4;
  186. for (; i<al; i++)
  187. rp[i]=ap[i];
  188. #endif
  189. #else /* !MONT_WORD */
  190. BIGNUM *t1,*t2;
  191. BN_CTX_start(ctx);
  192. t1 = BN_CTX_get(ctx);
  193. t2 = BN_CTX_get(ctx);
  194. if (t1 == NULL || t2 == NULL) goto err;
  195. if (!BN_copy(t1,a)) goto err;
  196. BN_mask_bits(t1,mont->ri);
  197. if (!BN_mul(t2,t1,&mont->Ni,ctx)) goto err;
  198. BN_mask_bits(t2,mont->ri);
  199. if (!BN_mul(t1,t2,&mont->N,ctx)) goto err;
  200. if (!BN_add(t2,a,t1)) goto err;
  201. BN_rshift(ret,t2,mont->ri);
  202. #endif /* MONT_WORD */
  203. if (BN_ucmp(ret, &(mont->N)) >= 0)
  204. {
  205. if (!BN_usub(ret,ret,&(mont->N))) goto err;
  206. }
  207. retn=1;
  208. err:
  209. BN_CTX_end(ctx);
  210. return(retn);
  211. }
  212. BN_MONT_CTX *BN_MONT_CTX_new(void)
  213. {
  214. BN_MONT_CTX *ret;
  215. if ((ret=(BN_MONT_CTX *)OPENSSL_malloc(sizeof(BN_MONT_CTX))) == NULL)
  216. return(NULL);
  217. BN_MONT_CTX_init(ret);
  218. ret->flags=BN_FLG_MALLOCED;
  219. return(ret);
  220. }
  221. void BN_MONT_CTX_init(BN_MONT_CTX *ctx)
  222. {
  223. ctx->ri=0;
  224. BN_init(&(ctx->RR));
  225. BN_init(&(ctx->N));
  226. BN_init(&(ctx->Ni));
  227. ctx->flags=0;
  228. }
  229. void BN_MONT_CTX_free(BN_MONT_CTX *mont)
  230. {
  231. if(mont == NULL)
  232. return;
  233. BN_free(&(mont->RR));
  234. BN_free(&(mont->N));
  235. BN_free(&(mont->Ni));
  236. if (mont->flags & BN_FLG_MALLOCED)
  237. OPENSSL_free(mont);
  238. }
  239. int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
  240. {
  241. BIGNUM Ri,*R;
  242. BN_init(&Ri);
  243. R= &(mont->RR); /* grab RR as a temp */
  244. BN_copy(&(mont->N),mod); /* Set N */
  245. mont->N.neg = 0;
  246. #ifdef MONT_WORD
  247. {
  248. BIGNUM tmod;
  249. BN_ULONG buf[2];
  250. mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2;
  251. BN_zero(R);
  252. BN_set_bit(R,BN_BITS2); /* R */
  253. buf[0]=mod->d[0]; /* tmod = N mod word size */
  254. buf[1]=0;
  255. tmod.d=buf;
  256. tmod.top=1;
  257. tmod.dmax=2;
  258. tmod.neg=0;
  259. /* Ri = R^-1 mod N*/
  260. if ((BN_mod_inverse(&Ri,R,&tmod,ctx)) == NULL)
  261. goto err;
  262. if (!BN_lshift(&Ri,&Ri,BN_BITS2)) goto err; /* R*Ri */
  263. if (!BN_is_zero(&Ri))
  264. {
  265. if (!BN_sub_word(&Ri,1)) goto err;
  266. }
  267. else /* if N mod word size == 1 */
  268. {
  269. if (!BN_set_word(&Ri,BN_MASK2)) goto err; /* Ri-- (mod word size) */
  270. }
  271. if (!BN_div(&Ri,NULL,&Ri,&tmod,ctx)) goto err;
  272. /* Ni = (R*Ri-1)/N,
  273. * keep only least significant word: */
  274. mont->n0 = (Ri.top > 0) ? Ri.d[0] : 0;
  275. BN_free(&Ri);
  276. }
  277. #else /* !MONT_WORD */
  278. { /* bignum version */
  279. mont->ri=BN_num_bits(&mont->N);
  280. if (!BN_zero(R)) goto err;
  281. if (!BN_set_bit(R,mont->ri)) goto err; /* R = 2^ri */
  282. /* Ri = R^-1 mod N*/
  283. if ((BN_mod_inverse(&Ri,R,&mont->N,ctx)) == NULL)
  284. goto err;
  285. if (!BN_lshift(&Ri,&Ri,mont->ri)) goto err; /* R*Ri */
  286. if (!BN_sub_word(&Ri,1)) goto err;
  287. /* Ni = (R*Ri-1) / N */
  288. if (!BN_div(&(mont->Ni),NULL,&Ri,&mont->N,ctx)) goto err;
  289. BN_free(&Ri);
  290. }
  291. #endif
  292. /* setup RR for conversions */
  293. if (!BN_zero(&(mont->RR))) goto err;
  294. if (!BN_set_bit(&(mont->RR),mont->ri*2)) goto err;
  295. if (!BN_mod(&(mont->RR),&(mont->RR),&(mont->N),ctx)) goto err;
  296. return(1);
  297. err:
  298. return(0);
  299. }
  300. BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from)
  301. {
  302. if (to == from) return(to);
  303. BN_copy(&(to->RR),&(from->RR));
  304. BN_copy(&(to->N),&(from->N));
  305. BN_copy(&(to->Ni),&(from->Ni));
  306. to->ri=from->ri;
  307. to->n0=from->n0;
  308. return(to);
  309. }