summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/bn/bn_mont.c
diff options
context:
space:
mode:
authorbeck <>2000-03-19 11:13:58 +0000
committerbeck <>2000-03-19 11:13:58 +0000
commit796d609550df3a33fc11468741c5d2f6d3df4c11 (patch)
tree6c6d539061caa20372dad0ac4ddb1dfae2fbe7fe /src/lib/libcrypto/bn/bn_mont.c
parent5be3114c1fd7e0dfea1e38d3abb4cbba75244419 (diff)
downloadopenbsd-796d609550df3a33fc11468741c5d2f6d3df4c11.tar.gz
openbsd-796d609550df3a33fc11468741c5d2f6d3df4c11.tar.bz2
openbsd-796d609550df3a33fc11468741c5d2f6d3df4c11.zip
OpenSSL 0.9.5 merge
*warning* this bumps shared lib minors for libssl and libcrypto from 2.1 to 2.2 if you are using the ssl26 packages for ssh and other things to work you will need to get new ones (see ~beck/libsslsnap/<arch>) on cvs or ~beck/src-patent.tar.gz on cvs
Diffstat (limited to 'src/lib/libcrypto/bn/bn_mont.c')
-rw-r--r--src/lib/libcrypto/bn/bn_mont.c313
1 files changed, 122 insertions, 191 deletions
diff --git a/src/lib/libcrypto/bn/bn_mont.c b/src/lib/libcrypto/bn/bn_mont.c
index ee0f410c22..7bb0b91223 100644
--- a/src/lib/libcrypto/bn/bn_mont.c
+++ b/src/lib/libcrypto/bn/bn_mont.c
@@ -57,25 +57,27 @@
57 */ 57 */
58 58
59/* 59/*
60 * Details about Montgomery multiplication algorithms can be found at: 60 * Details about Montgomery multiplication algorithms can be found at
61 * http://www.ece.orst.edu/ISL/Publications.html 61 * http://security.ece.orst.edu/publications.html, e.g.
62 * http://www.ece.orst.edu/ISL/Koc/papers/j37acmon.pdf 62 * http://security.ece.orst.edu/koc/papers/j37acmon.pdf and
63 * sections 3.8 and 4.2 in http://security.ece.orst.edu/koc/papers/r01rsasw.pdf
63 */ 64 */
64 65
65#include <stdio.h> 66#include <stdio.h>
66#include "cryptlib.h" 67#include "cryptlib.h"
67#include "bn_lcl.h" 68#include "bn_lcl.h"
68 69
69#define MONT_WORD 70#define MONT_WORD /* use the faster word-based algorithm */
70 71
71int BN_mod_mul_montgomery(BIGNUM *r, BIGNUM *a, BIGNUM *b, 72int BN_mod_mul_montgomery(BIGNUM *r, BIGNUM *a, BIGNUM *b,
72 BN_MONT_CTX *mont, BN_CTX *ctx) 73 BN_MONT_CTX *mont, BN_CTX *ctx)
73 { 74 {
74 BIGNUM *tmp,*tmp2; 75 BIGNUM *tmp,*tmp2;
75 76
76 tmp= &(ctx->bn[ctx->tos]); 77 BN_CTX_start(ctx);
77 tmp2= &(ctx->bn[ctx->tos]); 78 tmp = BN_CTX_get(ctx);
78 ctx->tos+=2; 79 tmp2 = BN_CTX_get(ctx);
80 if (tmp == NULL || tmp2 == NULL) goto err;
79 81
80 bn_check_top(tmp); 82 bn_check_top(tmp);
81 bn_check_top(tmp2); 83 bn_check_top(tmp2);
@@ -99,7 +101,7 @@ int BN_mod_mul_montgomery(BIGNUM *r, BIGNUM *a, BIGNUM *b,
99 } 101 }
100 /* reduce from aRR to aR */ 102 /* reduce from aRR to aR */
101 if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err; 103 if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err;
102 ctx->tos-=2; 104 BN_CTX_end(ctx);
103 return(1); 105 return(1);
104err: 106err:
105 return(0); 107 return(0);
@@ -108,160 +110,123 @@ err:
108int BN_from_montgomery(BIGNUM *ret, BIGNUM *a, BN_MONT_CTX *mont, 110int BN_from_montgomery(BIGNUM *ret, BIGNUM *a, BN_MONT_CTX *mont,
109 BN_CTX *ctx) 111 BN_CTX *ctx)
110 { 112 {
111#ifdef BN_RECURSION_MONT 113 int retn=0;
112 if (mont->use_word)
113#endif
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;
119 114
120 r= &(ctx->bn[ctx->tos]); 115#ifdef MONT_WORD
116 BIGNUM *n,*r;
117 BN_ULONG *ap,*np,*rp,n0,v,*nrp;
118 int al,nl,max,i,x,ri;
121 119
122 if (!BN_copy(r,a)) goto err1; 120 BN_CTX_start(ctx);
123 n= &(mont->N); 121 if ((r = BN_CTX_get(ctx)) == NULL) goto err;
124 122
125 ap=a->d; 123 if (!BN_copy(r,a)) goto err;
126 /* mont->ri is the size of mont->N in bits/words */ 124 n= &(mont->N);
127 al=ri=mont->ri/BN_BITS2;
128 125
129 nl=n->top; 126 ap=a->d;
130 if ((al == 0) || (nl == 0)) { r->top=0; return(1); } 127 /* mont->ri is the size of mont->N in bits (rounded up
128 to the word size) */
129 al=ri=mont->ri/BN_BITS2;
130
131 nl=n->top;
132 if ((al == 0) || (nl == 0)) { r->top=0; return(1); }
131 133
132 max=(nl+al+1); /* allow for overflow (no?) XXX */ 134 max=(nl+al+1); /* allow for overflow (no?) XXX */
133 if (bn_wexpand(r,max) == NULL) goto err1; 135 if (bn_wexpand(r,max) == NULL) goto err;
134 if (bn_wexpand(ret,max) == NULL) goto err1; 136 if (bn_wexpand(ret,max) == NULL) goto err;
135 137
136 r->neg=a->neg^n->neg; 138 r->neg=a->neg^n->neg;
137 np=n->d; 139 np=n->d;
138 rp=r->d; 140 rp=r->d;
139 nrp= &(r->d[nl]); 141 nrp= &(r->d[nl]);
140 142
141 /* clear the top words of T */ 143 /* clear the top words of T */
142#if 1 144#if 1
143 for (i=r->top; i<max; i++) /* memset? XXX */ 145 for (i=r->top; i<max; i++) /* memset? XXX */
144 r->d[i]=0; 146 r->d[i]=0;
145#else 147#else
146 memset(&(r->d[r->top]),0,(max-r->top)*sizeof(BN_ULONG)); 148 memset(&(r->d[r->top]),0,(max-r->top)*sizeof(BN_ULONG));
147#endif 149#endif
148 150
149 r->top=max; 151 r->top=max;
150 n0=mont->n0; 152 n0=mont->n0;
151 153
152#ifdef BN_COUNT 154#ifdef BN_COUNT
153printf("word BN_from_montgomery %d * %d\n",nl,nl); 155 printf("word BN_from_montgomery %d * %d\n",nl,nl);
154#endif 156#endif
155 for (i=0; i<nl; i++) 157 for (i=0; i<nl; i++)
156 { 158 {
157 v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2); 159 v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
158 nrp++; 160 nrp++;
159 rp++; 161 rp++;
160 if (((nrp[-1]+=v)&BN_MASK2) >= v) 162 if (((nrp[-1]+=v)&BN_MASK2) >= v)
161 continue; 163 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 }
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;
180 else 164 else
181 al=r->top-x;
182 ret->top=al;
183 al-=4;
184 for (i=0; i<al; i+=4)
185 { 165 {
186 BN_ULONG t1,t2,t3,t4; 166 if (((++nrp[0])&BN_MASK2) != 0) continue;
187 167 if (((++nrp[1])&BN_MASK2) != 0) continue;
188 t1=ap[i+0]; 168 for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ;
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;
196 } 169 }
197 al+=4;
198 for (; i<al; i++)
199 rp[i]=ap[i];
200#endif
201
202 if (BN_ucmp(ret, &(mont->N)) >= 0)
203 {
204 BN_usub(ret,ret,&(mont->N)); /* XXX */
205 }
206 retn=1;
207err1:
208 return(retn);
209 } 170 }
210#ifdef BN_RECURSION_MONT 171 bn_fix_top(r);
211 else /* bignum version */ 172
173 /* mont->ri will be a multiple of the word size */
174#if 0
175 BN_rshift(ret,r,mont->ri);
176#else
177 x=ri;
178 rp=ret->d;
179 ap= &(r->d[x]);
180 if (r->top < x)
181 al=0;
182 else
183 al=r->top-x;
184 ret->top=al;
185 al-=4;
186 for (i=0; i<al; i+=4)
212 { 187 {
213 BIGNUM *t1,*t2,*t3; 188 BN_ULONG t1,t2,t3,t4;
214 int j,i; 189
215 190 t1=ap[i+0];
216#ifdef BN_COUNT 191 t2=ap[i+1];
217printf("number BN_from_montgomery\n"); 192 t3=ap[i+2];
218#endif 193 t4=ap[i+3];
219 194 rp[i+0]=t1;
220 t1= &(ctx->bn[ctx->tos]); 195 rp[i+1]=t2;
221 t2= &(ctx->bn[ctx->tos+1]); 196 rp[i+2]=t3;
222 t3= &(ctx->bn[ctx->tos+2]); 197 rp[i+3]=t4;
223
224 i=mont->Ni.top;
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 */
228
229 bn_mul_low_recursive(t2->d,a->d,mont->Ni.d,i,t1->d);
230
231 BN_zero(t3);
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);
235
236 /* hmm... if a is between i and 2*i, things are bad */
237 if (a->top > i)
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 }
258
259 if (BN_ucmp(ret,&(mont->N)) >= 0)
260 BN_usub(ret,ret,&(mont->N));
261
262 return(1);
263 } 198 }
199 al+=4;
200 for (; i<al; i++)
201 rp[i]=ap[i];
264#endif 202#endif
203#else /* !MONT_WORD */
204 BIGNUM *t1,*t2;
205
206 BN_CTX_start(ctx);
207 t1 = BN_CTX_get(ctx);
208 t2 = BN_CTX_get(ctx);
209 if (t1 == NULL || t2 == NULL) goto err;
210
211 if (!BN_copy(t1,a)) goto err;
212 BN_mask_bits(t1,mont->ri);
213
214 if (!BN_mul(t2,t1,&mont->Ni,ctx)) goto err;
215 BN_mask_bits(t2,mont->ri);
216
217 if (!BN_mul(t1,t2,&mont->N,ctx)) goto err;
218 if (!BN_add(t2,a,t1)) goto err;
219 BN_rshift(ret,t2,mont->ri);
220#endif /* MONT_WORD */
221
222 if (BN_ucmp(ret, &(mont->N)) >= 0)
223 {
224 BN_usub(ret,ret,&(mont->N));
225 }
226 retn=1;
227 err:
228 BN_CTX_end(ctx);
229 return(retn);
265 } 230 }
266 231
267BN_MONT_CTX *BN_MONT_CTX_new(void) 232BN_MONT_CTX *BN_MONT_CTX_new(void)
@@ -278,7 +243,6 @@ BN_MONT_CTX *BN_MONT_CTX_new(void)
278 243
279void BN_MONT_CTX_init(BN_MONT_CTX *ctx) 244void BN_MONT_CTX_init(BN_MONT_CTX *ctx)
280 { 245 {
281 ctx->use_word=0;
282 ctx->ri=0; 246 ctx->ri=0;
283 BN_init(&(ctx->RR)); 247 BN_init(&(ctx->RR));
284 BN_init(&(ctx->N)); 248 BN_init(&(ctx->N));
@@ -306,85 +270,53 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
306 R= &(mont->RR); /* grab RR as a temp */ 270 R= &(mont->RR); /* grab RR as a temp */
307 BN_copy(&(mont->N),mod); /* Set N */ 271 BN_copy(&(mont->N),mod); /* Set N */
308 272
309#ifdef BN_RECURSION_MONT 273#ifdef MONT_WORD
310 if (mont->N.top < BN_MONT_CTX_SET_SIZE_WORD)
311#endif
312 { 274 {
313 BIGNUM tmod; 275 BIGNUM tmod;
314 BN_ULONG buf[2]; 276 BN_ULONG buf[2];
315 277
316 mont->use_word=1;
317
318 mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2; 278 mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2;
319 BN_zero(R); 279 BN_zero(R);
320 BN_set_bit(R,BN_BITS2); 280 BN_set_bit(R,BN_BITS2); /* R */
321 /* I was bad, this modification of a passed variable was
322 * breaking the multithreaded stuff :-(
323 * z=mod->top;
324 * mod->top=1; */
325 281
326 buf[0]=mod->d[0]; 282 buf[0]=mod->d[0]; /* tmod = N mod word size */
327 buf[1]=0; 283 buf[1]=0;
328 tmod.d=buf; 284 tmod.d=buf;
329 tmod.top=1; 285 tmod.top=1;
330 tmod.max=mod->max; 286 tmod.max=2;
331 tmod.neg=mod->neg; 287 tmod.neg=mod->neg;
332 288 /* Ri = R^-1 mod N*/
333 if ((BN_mod_inverse(&Ri,R,&tmod,ctx)) == NULL) 289 if ((BN_mod_inverse(&Ri,R,&tmod,ctx)) == NULL)
334 goto err; 290 goto err;
335 BN_lshift(&Ri,&Ri,BN_BITS2); /* R*Ri */ 291 BN_lshift(&Ri,&Ri,BN_BITS2); /* R*Ri */
336 if (!BN_is_zero(&Ri)) 292 if (!BN_is_zero(&Ri))
337 {
338#if 1
339 BN_sub_word(&Ri,1); 293 BN_sub_word(&Ri,1);
340#else 294 else /* if N mod word size == 1 */
341 BN_usub(&Ri,&Ri,BN_value_one()); /* R*Ri - 1 */ 295 BN_set_word(&Ri,BN_MASK2); /* Ri-- (mod word size) */
342#endif 296 BN_div(&Ri,NULL,&Ri,&tmod,ctx); /* Ni = (R*Ri-1)/N,
343 } 297 * keep only least significant word: */
344 else
345 {
346 /* This is not common..., 1 in BN_MASK2,
347 * It happens when buf[0] was == 1. So for 8 bit,
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]; 298 mont->n0=Ri.d[0];
354 BN_free(&Ri); 299 BN_free(&Ri);
355 /* mod->top=z; */
356 } 300 }
357#ifdef BN_RECURSION_MONT 301#else /* !MONT_WORD */
358 else 302 { /* bignum version */
359 { 303 mont->ri=BN_num_bits(mod);
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); 304 BN_zero(R);
364 BN_set_bit(R,mont->ri); 305 BN_set_bit(R,mont->ri); /* R = 2^ri */
365#else 306 /* Ri = R^-1 mod N*/
366 BN_lshift(R,BN_value_one(),mont->ri); /* R */
367#endif
368 if ((BN_mod_inverse(&Ri,R,mod,ctx)) == NULL) 307 if ((BN_mod_inverse(&Ri,R,mod,ctx)) == NULL)
369 goto err; 308 goto err;
370 BN_lshift(&Ri,&Ri,mont->ri); /* R*Ri */ 309 BN_lshift(&Ri,&Ri,mont->ri); /* R*Ri */
371#if 1
372 BN_sub_word(&Ri,1); 310 BN_sub_word(&Ri,1);
373#else 311 /* Ni = (R*Ri-1) / N */
374 BN_usub(&Ri,&Ri,BN_value_one()); /* R*Ri - 1 */
375#endif
376 BN_div(&(mont->Ni),NULL,&Ri,mod,ctx); 312 BN_div(&(mont->Ni),NULL,&Ri,mod,ctx);
377 BN_free(&Ri); 313 BN_free(&Ri);
378 } 314 }
379#endif 315#endif
380 316
381 /* setup RR for conversions */ 317 /* setup RR for conversions */
382#if 1
383 BN_zero(&(mont->RR)); 318 BN_zero(&(mont->RR));
384 BN_set_bit(&(mont->RR),mont->ri*2); 319 BN_set_bit(&(mont->RR),mont->ri*2);
385#else
386 BN_lshift(mont->RR,BN_value_one(),mont->ri*2);
387#endif
388 BN_mod(&(mont->RR),&(mont->RR),&(mont->N),ctx); 320 BN_mod(&(mont->RR),&(mont->RR),&(mont->N),ctx);
389 321
390 return(1); 322 return(1);
@@ -399,7 +331,6 @@ BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from)
399 BN_copy(&(to->RR),&(from->RR)); 331 BN_copy(&(to->RR),&(from->RR));
400 BN_copy(&(to->N),&(from->N)); 332 BN_copy(&(to->N),&(from->N));
401 BN_copy(&(to->Ni),&(from->Ni)); 333 BN_copy(&(to->Ni),&(from->Ni));
402 to->use_word=from->use_word;
403 to->ri=from->ri; 334 to->ri=from->ri;
404 to->n0=from->n0; 335 to->n0=from->n0;
405 return(to); 336 return(to);