summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/bn/bn_mont.c
diff options
context:
space:
mode:
authorbeck <>1999-09-29 04:37:45 +0000
committerbeck <>1999-09-29 04:37:45 +0000
commitde8f24ea083384bb66b32ec105dc4743c5663cdf (patch)
tree1412176ae62a3cab2cf2b0b92150fcbceaac6092 /src/lib/libcrypto/bn/bn_mont.c
parentcb929d29896bcb87c2a97417fbd03e50078fc178 (diff)
downloadopenbsd-de8f24ea083384bb66b32ec105dc4743c5663cdf.tar.gz
openbsd-de8f24ea083384bb66b32ec105dc4743c5663cdf.tar.bz2
openbsd-de8f24ea083384bb66b32ec105dc4743c5663cdf.zip
OpenSSL 0.9.4 merge
Diffstat (limited to 'src/lib/libcrypto/bn/bn_mont.c')
-rw-r--r--src/lib/libcrypto/bn/bn_mont.c441
1 files changed, 271 insertions, 170 deletions
diff --git a/src/lib/libcrypto/bn/bn_mont.c b/src/lib/libcrypto/bn/bn_mont.c
index e435df61f8..ee0f410c22 100644
--- a/src/lib/libcrypto/bn/bn_mont.c
+++ b/src/lib/libcrypto/bn/bn_mont.c
@@ -56,251 +56,352 @@
56 * [including the GNU Public Licence.] 56 * [including the GNU Public Licence.]
57 */ 57 */
58 58
59/*
60 * Details about Montgomery multiplication algorithms can be found at:
61 * http://www.ece.orst.edu/ISL/Publications.html
62 * http://www.ece.orst.edu/ISL/Koc/papers/j37acmon.pdf
63 */
64
59#include <stdio.h> 65#include <stdio.h>
60#include "cryptlib.h" 66#include "cryptlib.h"
61#include "bn_lcl.h" 67#include "bn_lcl.h"
62 68
63int BN_mod_mul_montgomery(r,a,b,mont,ctx) 69#define MONT_WORD
64BIGNUM *r,*a,*b; 70
65BN_MONT_CTX *mont; 71int BN_mod_mul_montgomery(BIGNUM *r, BIGNUM *a, BIGNUM *b,
66BN_CTX *ctx; 72 BN_MONT_CTX *mont, BN_CTX *ctx)
67 { 73 {
68 BIGNUM *tmp; 74 BIGNUM *tmp,*tmp2;
75
76 tmp= &(ctx->bn[ctx->tos]);
77 tmp2= &(ctx->bn[ctx->tos]);
78 ctx->tos+=2;
69 79
70 tmp=ctx->bn[ctx->tos++]; 80 bn_check_top(tmp);
81 bn_check_top(tmp2);
71 82
72 if (a == b) 83 if (a == b)
73 { 84 {
85#if 0
86 bn_wexpand(tmp,a->top*2);
87 bn_wexpand(tmp2,a->top*4);
88 bn_sqr_recursive(tmp->d,a->d,a->top,tmp2->d);
89 tmp->top=a->top*2;
90 if (tmp->d[tmp->top-1] == 0)
91 tmp->top--;
92#else
74 if (!BN_sqr(tmp,a,ctx)) goto err; 93 if (!BN_sqr(tmp,a,ctx)) goto err;
94#endif
75 } 95 }
76 else 96 else
77 { 97 {
78 if (!BN_mul(tmp,a,b)) goto err; 98 if (!BN_mul(tmp,a,b,ctx)) goto err;
79 } 99 }
80 /* reduce from aRR to aR */ 100 /* reduce from aRR to aR */
81 if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err; 101 if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err;
82 ctx->tos--; 102 ctx->tos-=2;
83 return(1); 103 return(1);
84err: 104err:
85 return(0); 105 return(0);
86 } 106 }
87 107
88#define MONT_WORD 108int BN_from_montgomery(BIGNUM *ret, BIGNUM *a, BN_MONT_CTX *mont,
89 109 BN_CTX *ctx)
90#ifdef MONT_WORD
91int BN_from_montgomery(ret,a,mont,ctx)
92BIGNUM *ret;
93BIGNUM *a;
94BN_MONT_CTX *mont;
95BN_CTX *ctx;
96 { 110 {
97 BIGNUM *n,*t1,*r; 111#ifdef BN_RECURSION_MONT
98 BN_ULONG *ap,*np,*rp,n0,v; 112 if (mont->use_word)
99 int al,nl,max,i,x,ri; 113#endif
100 int retn=0; 114 {
115 BIGNUM *n,*r;
116 BN_ULONG *ap,*np,*rp,n0,v,*nrp;
117 int al,nl,max,i,x,ri;
118 int retn=0;
101 119
102 t1=ctx->bn[ctx->tos]; 120 r= &(ctx->bn[ctx->tos]);
103 r=ctx->bn[ctx->tos+1];
104 121
105 if (!BN_copy(r,a)) goto err; 122 if (!BN_copy(r,a)) goto err1;
106 n=mont->N; 123 n= &(mont->N);
107 124
108 ap=a->d; 125 ap=a->d;
109 /* mont->ri is the size of mont->N in bits/words */ 126 /* mont->ri is the size of mont->N in bits/words */
110 al=ri=mont->ri/BN_BITS2; 127 al=ri=mont->ri/BN_BITS2;
111 128
112 nl=n->top; 129 nl=n->top;
113 if ((al == 0) || (nl == 0)) { r->top=0; return(1); } 130 if ((al == 0) || (nl == 0)) { r->top=0; return(1); }
114 131
115 max=(nl+al+1); /* allow for overflow (no?) XXX */ 132 max=(nl+al+1); /* allow for overflow (no?) XXX */
116 if (bn_wexpand(r,max) == NULL) goto err; 133 if (bn_wexpand(r,max) == NULL) goto err1;
117 if (bn_wexpand(ret,max) == NULL) goto err; 134 if (bn_wexpand(ret,max) == NULL) goto err1;
118 135
119 r->neg=a->neg^n->neg; 136 r->neg=a->neg^n->neg;
120 np=n->d; 137 np=n->d;
121 rp=r->d; 138 rp=r->d;
139 nrp= &(r->d[nl]);
122 140
123 /* clear the top words of T */ 141 /* clear the top words of T */
124#if 1 142#if 1
125 for (i=r->top; i<max; i++) /* memset? XXX */ 143 for (i=r->top; i<max; i++) /* memset? XXX */
126 r->d[i]=0; 144 r->d[i]=0;
127#else 145#else
128 memset(&(r->d[r->top]),0,(max-r->top)*sizeof(BN_ULONG)); 146 memset(&(r->d[r->top]),0,(max-r->top)*sizeof(BN_ULONG));
129#endif 147#endif
130 148
131 r->top=max; 149 r->top=max;
132 n0=mont->n0; 150 n0=mont->n0;
133
134 for (i=0; i<nl; i++)
135 {
136#if 0
137 int x1,x2;
138 151
139 if (i+4 > nl) 152#ifdef BN_COUNT
153printf("word BN_from_montgomery %d * %d\n",nl,nl);
154#endif
155 for (i=0; i<nl; i++)
140 { 156 {
141 x2=nl; 157 v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
142 x1=0; 158 nrp++;
159 rp++;
160 if (((nrp[-1]+=v)&BN_MASK2) >= v)
161 continue;
162 else
163 {
164 if (((++nrp[0])&BN_MASK2) != 0) continue;
165 if (((++nrp[1])&BN_MASK2) != 0) continue;
166 for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ;
167 }
143 } 168 }
169 bn_fix_top(r);
170
171 /* mont->ri will be a multiple of the word size */
172#if 0
173 BN_rshift(ret,r,mont->ri);
174#else
175 x=ri;
176 rp=ret->d;
177 ap= &(r->d[x]);
178 if (r->top < x)
179 al=0;
144 else 180 else
181 al=r->top-x;
182 ret->top=al;
183 al-=4;
184 for (i=0; i<al; i+=4)
145 { 185 {
146 x2=i+4; 186 BN_ULONG t1,t2,t3,t4;
147 x1=nl-x2; 187
188 t1=ap[i+0];
189 t2=ap[i+1];
190 t3=ap[i+2];
191 t4=ap[i+3];
192 rp[i+0]=t1;
193 rp[i+1]=t2;
194 rp[i+2]=t3;
195 rp[i+3]=t4;
148 } 196 }
149 v=bn_mul_add_words(&(rp[x1]),&(np[x1]),x2,(rp[x1]*n0)&BN_MASK2); 197 al+=4;
150#else 198 for (; i<al; i++)
151 v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2); 199 rp[i]=ap[i];
152#endif 200#endif
153 201
154 if (((rp[nl]+=v)&BN_MASK2) < v) 202 if (BN_ucmp(ret, &(mont->N)) >= 0)
155 { 203 {
156 for (x=(nl+1); (((++rp[x])&BN_MASK2) == 0); x++) 204 BN_usub(ret,ret,&(mont->N)); /* XXX */
157 ;
158 } 205 }
159 rp++; 206 retn=1;
207err1:
208 return(retn);
160 } 209 }
161 while (r->d[r->top-1] == 0) 210#ifdef BN_RECURSION_MONT
162 r->top--; 211 else /* bignum version */
163
164 /* mont->ri will be a multiple of the word size */
165#if 0
166 BN_rshift(ret,r,mont->ri);
167#else
168 ap=r->d;
169 rp=ret->d;
170 x=ri;
171 al=r->top-x;
172 for (i=0; i<al; i++)
173 { 212 {
174 rp[i]=ap[i+x]; 213 BIGNUM *t1,*t2,*t3;
175 } 214 int j,i;
176 ret->top=al; 215
216#ifdef BN_COUNT
217printf("number BN_from_montgomery\n");
177#endif 218#endif
178 219
179 if (BN_ucmp(ret,mont->N) >= 0) 220 t1= &(ctx->bn[ctx->tos]);
180 { 221 t2= &(ctx->bn[ctx->tos+1]);
181 bn_qsub(ret,ret,mont->N); /* XXX */ 222 t3= &(ctx->bn[ctx->tos+2]);
182 }
183 retn=1;
184err:
185 return(retn);
186 }
187#else
188int BN_from_montgomery(r,a,mont,ctx)
189BIGNUM *r;
190BIGNUM *a;
191BN_MONT_CTX *mont;
192BN_CTX *ctx;
193 {
194 BIGNUM *t1,*t2;
195 223
196 t1=ctx->bn[ctx->tos]; 224 i=mont->Ni.top;
197 t2=ctx->bn[ctx->tos+1]; 225 bn_wexpand(ret,i); /* perhaps only i*2 */
226 bn_wexpand(t1,i*4); /* perhaps only i*2 */
227 bn_wexpand(t2,i*2); /* perhaps only i */
198 228
199 if (!BN_copy(t1,a)) goto err; 229 bn_mul_low_recursive(t2->d,a->d,mont->Ni.d,i,t1->d);
200 /* can cheat */
201 BN_mask_bits(t1,mont->ri);
202 230
203 if (!BN_mul(t2,t1,mont->Ni)) goto err; 231 BN_zero(t3);
204 BN_mask_bits(t2,mont->ri); 232 BN_set_bit(t3,mont->N.top*BN_BITS2);
233 bn_sub_words(t3->d,t3->d,a->d,i);
234 bn_mul_high(ret->d,t2->d,mont->N.d,t3->d,i,t1->d);
205 235
206 if (!BN_mul(t1,t2,mont->N)) goto err; 236 /* hmm... if a is between i and 2*i, things are bad */
207 if (!BN_add(t2,a,t1)) goto err; 237 if (a->top > i)
208 BN_rshift(r,t2,mont->ri); 238 {
239 j=(int)(bn_add_words(ret->d,ret->d,&(a->d[i]),i));
240 if (j) /* overflow */
241 bn_sub_words(ret->d,ret->d,mont->N.d,i);
242 }
243 ret->top=i;
244 bn_fix_top(ret);
245 if (a->d[0])
246 BN_add_word(ret,1); /* Always? */
247 else /* Very very rare */
248 {
249 for (i=1; i<mont->N.top-1; i++)
250 {
251 if (a->d[i])
252 {
253 BN_add_word(ret,1); /* Always? */
254 break;
255 }
256 }
257 }
209 258
210 if (BN_ucmp(r,mont->N) >= 0) 259 if (BN_ucmp(ret,&(mont->N)) >= 0)
211 bn_qsub(r,r,mont->N); 260 BN_usub(ret,ret,&(mont->N));
212 261
213 return(1); 262 return(1);
214err: 263 }
215 return(0);
216 }
217#endif 264#endif
265 }
218 266
219BN_MONT_CTX *BN_MONT_CTX_new() 267BN_MONT_CTX *BN_MONT_CTX_new(void)
220 { 268 {
221 BN_MONT_CTX *ret; 269 BN_MONT_CTX *ret;
222 270
223 if ((ret=(BN_MONT_CTX *)Malloc(sizeof(BN_MONT_CTX))) == NULL) 271 if ((ret=(BN_MONT_CTX *)Malloc(sizeof(BN_MONT_CTX))) == NULL)
224 return(NULL); 272 return(NULL);
225 ret->ri=0; 273
226 ret->RR=BN_new(); 274 BN_MONT_CTX_init(ret);
227 ret->N=BN_new(); 275 ret->flags=BN_FLG_MALLOCED;
228 ret->Ni=NULL;
229 if ((ret->RR == NULL) || (ret->N == NULL))
230 {
231 BN_MONT_CTX_free(ret);
232 return(NULL);
233 }
234 return(ret); 276 return(ret);
235 } 277 }
236 278
237void BN_MONT_CTX_free(mont) 279void BN_MONT_CTX_init(BN_MONT_CTX *ctx)
238BN_MONT_CTX *mont; 280 {
281 ctx->use_word=0;
282 ctx->ri=0;
283 BN_init(&(ctx->RR));
284 BN_init(&(ctx->N));
285 BN_init(&(ctx->Ni));
286 ctx->flags=0;
287 }
288
289void BN_MONT_CTX_free(BN_MONT_CTX *mont)
239 { 290 {
240 if (mont->RR != NULL) BN_free(mont->RR); 291 if(mont == NULL)
241 if (mont->N != NULL) BN_free(mont->N); 292 return;
242 if (mont->Ni != NULL) BN_free(mont->Ni); 293
243 Free(mont); 294 BN_free(&(mont->RR));
295 BN_free(&(mont->N));
296 BN_free(&(mont->Ni));
297 if (mont->flags & BN_FLG_MALLOCED)
298 Free(mont);
244 } 299 }
245 300
246int BN_MONT_CTX_set(mont,mod,ctx) 301int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
247BN_MONT_CTX *mont;
248BIGNUM *mod;
249BN_CTX *ctx;
250 { 302 {
251 BIGNUM *Ri=NULL,*R=NULL; 303 BIGNUM Ri,*R;
252 304
253 if (mont->RR == NULL) mont->RR=BN_new(); 305 BN_init(&Ri);
254 if (mont->N == NULL) mont->N=BN_new(); 306 R= &(mont->RR); /* grab RR as a temp */
255 307 BN_copy(&(mont->N),mod); /* Set N */
256 R=mont->RR; /* grab RR as a temp */ 308
257 BN_copy(mont->N,mod); /* Set N */ 309#ifdef BN_RECURSION_MONT
258 310 if (mont->N.top < BN_MONT_CTX_SET_SIZE_WORD)
259#ifdef MONT_WORD 311#endif
260{ 312 {
261 BIGNUM tmod; 313 BIGNUM tmod;
262 BN_ULONG buf[2]; 314 BN_ULONG buf[2];
263 /* int z; */ 315
264 316 mont->use_word=1;
265 mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2; 317
266 BN_lshift(R,BN_value_one(),BN_BITS2); /* R */ 318 mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2;
267 /* I was bad, this modification of a passed variable was 319 BN_zero(R);
268 * breaking the multithreaded stuff :-( 320 BN_set_bit(R,BN_BITS2);
269 * z=mod->top; 321 /* I was bad, this modification of a passed variable was
270 * mod->top=1; */ 322 * breaking the multithreaded stuff :-(
271 323 * z=mod->top;
272 buf[0]=mod->d[0]; 324 * mod->top=1; */
273 buf[1]=0; 325
274 tmod.d=buf; 326 buf[0]=mod->d[0];
275 tmod.top=1; 327 buf[1]=0;
276 tmod.max=mod->max; 328 tmod.d=buf;
277 tmod.neg=mod->neg; 329 tmod.top=1;
278 330 tmod.max=mod->max;
279 if ((Ri=BN_mod_inverse(R,&tmod,ctx)) == NULL) goto err; /* Ri */ 331 tmod.neg=mod->neg;
280 BN_lshift(Ri,Ri,BN_BITS2); /* R*Ri */ 332
281 bn_qsub(Ri,Ri,BN_value_one()); /* R*Ri - 1 */ 333 if ((BN_mod_inverse(&Ri,R,&tmod,ctx)) == NULL)
282 BN_div(Ri,NULL,Ri,&tmod,ctx); 334 goto err;
283 mont->n0=Ri->d[0]; 335 BN_lshift(&Ri,&Ri,BN_BITS2); /* R*Ri */
284 BN_free(Ri); 336 if (!BN_is_zero(&Ri))
285 /* mod->top=z; */ 337 {
286} 338#if 1
339 BN_sub_word(&Ri,1);
287#else 340#else
288 mont->ri=BN_num_bits(mod); 341 BN_usub(&Ri,&Ri,BN_value_one()); /* R*Ri - 1 */
289 BN_lshift(R,BN_value_one(),mont->ri); /* R */ 342#endif
290 if ((Ri=BN_mod_inverse(R,mod,ctx)) == NULL) goto err; /* Ri */ 343 }
291 BN_lshift(Ri,Ri,mont->ri); /* R*Ri */ 344 else
292 bn_qsub(Ri,Ri,BN_value_one()); /* R*Ri - 1 */ 345 {
293 BN_div(Ri,NULL,Ri,mod,ctx); 346 /* This is not common..., 1 in BN_MASK2,
294 if (mont->Ni != NULL) BN_free(mont->Ni); 347 * It happens when buf[0] was == 1. So for 8 bit,
295 mont->Ni=Ri; /* Ni=(R*Ri-1)/N */ 348 * this is 1/256, 16bit, 1 in 2^16 etc.
349 */
350 BN_set_word(&Ri,BN_MASK2);
351 }
352 BN_div(&Ri,NULL,&Ri,&tmod,ctx);
353 mont->n0=Ri.d[0];
354 BN_free(&Ri);
355 /* mod->top=z; */
356 }
357#ifdef BN_RECURSION_MONT
358 else
359 {
360 mont->use_word=0;
361 mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2;
362#if 1
363 BN_zero(R);
364 BN_set_bit(R,mont->ri);
365#else
366 BN_lshift(R,BN_value_one(),mont->ri); /* R */
367#endif
368 if ((BN_mod_inverse(&Ri,R,mod,ctx)) == NULL)
369 goto err;
370 BN_lshift(&Ri,&Ri,mont->ri); /* R*Ri */
371#if 1
372 BN_sub_word(&Ri,1);
373#else
374 BN_usub(&Ri,&Ri,BN_value_one()); /* R*Ri - 1 */
375#endif
376 BN_div(&(mont->Ni),NULL,&Ri,mod,ctx);
377 BN_free(&Ri);
378 }
296#endif 379#endif
297 380
298 /* setup RR for conversions */ 381 /* setup RR for conversions */
382#if 1
383 BN_zero(&(mont->RR));
384 BN_set_bit(&(mont->RR),mont->ri*2);
385#else
299 BN_lshift(mont->RR,BN_value_one(),mont->ri*2); 386 BN_lshift(mont->RR,BN_value_one(),mont->ri*2);
300 BN_mod(mont->RR,mont->RR,mont->N,ctx); 387#endif
388 BN_mod(&(mont->RR),&(mont->RR),&(mont->N),ctx);
301 389
302 return(1); 390 return(1);
303err: 391err:
304 return(0); 392 return(0);
305 } 393 }
306 394
395BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from)
396 {
397 if (to == from) return(to);
398
399 BN_copy(&(to->RR),&(from->RR));
400 BN_copy(&(to->N),&(from->N));
401 BN_copy(&(to->Ni),&(from->Ni));
402 to->use_word=from->use_word;
403 to->ri=from->ri;
404 to->n0=from->n0;
405 return(to);
406 }
407