summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/bn/bn_mont.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/bn/bn_mont.c')
-rw-r--r--src/lib/libcrypto/bn/bn_mont.c335
1 files changed, 189 insertions, 146 deletions
diff --git a/src/lib/libcrypto/bn/bn_mont.c b/src/lib/libcrypto/bn/bn_mont.c
index e435df61f8..c9ebdbaabe 100644
--- a/src/lib/libcrypto/bn/bn_mont.c
+++ b/src/lib/libcrypto/bn/bn_mont.c
@@ -56,59 +56,67 @@
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://security.ece.orst.edu/publications.html, e.g.
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
64 */
65
59#include <stdio.h> 66#include <stdio.h>
60#include "cryptlib.h" 67#include "cryptlib.h"
61#include "bn_lcl.h" 68#include "bn_lcl.h"
62 69
63int BN_mod_mul_montgomery(r,a,b,mont,ctx) 70#define MONT_WORD /* use the faster word-based algorithm */
64BIGNUM *r,*a,*b; 71
65BN_MONT_CTX *mont; 72int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
66BN_CTX *ctx; 73 BN_MONT_CTX *mont, BN_CTX *ctx)
67 { 74 {
68 BIGNUM *tmp; 75 BIGNUM *tmp;
76 int ret=0;
69 77
70 tmp=ctx->bn[ctx->tos++]; 78 BN_CTX_start(ctx);
79 tmp = BN_CTX_get(ctx);
80 if (tmp == NULL) goto err;
71 81
82 bn_check_top(tmp);
72 if (a == b) 83 if (a == b)
73 { 84 {
74 if (!BN_sqr(tmp,a,ctx)) goto err; 85 if (!BN_sqr(tmp,a,ctx)) goto err;
75 } 86 }
76 else 87 else
77 { 88 {
78 if (!BN_mul(tmp,a,b)) goto err; 89 if (!BN_mul(tmp,a,b,ctx)) goto err;
79 } 90 }
80 /* reduce from aRR to aR */ 91 /* reduce from aRR to aR */
81 if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err; 92 if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err;
82 ctx->tos--; 93 ret=1;
83 return(1);
84err: 94err:
85 return(0); 95 BN_CTX_end(ctx);
96 return(ret);
86 } 97 }
87 98
88#define MONT_WORD 99int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont,
100 BN_CTX *ctx)
101 {
102 int retn=0;
89 103
90#ifdef MONT_WORD 104#ifdef MONT_WORD
91int BN_from_montgomery(ret,a,mont,ctx) 105 BIGNUM *n,*r;
92BIGNUM *ret; 106 BN_ULONG *ap,*np,*rp,n0,v,*nrp;
93BIGNUM *a;
94BN_MONT_CTX *mont;
95BN_CTX *ctx;
96 {
97 BIGNUM *n,*t1,*r;
98 BN_ULONG *ap,*np,*rp,n0,v;
99 int al,nl,max,i,x,ri; 107 int al,nl,max,i,x,ri;
100 int retn=0;
101 108
102 t1=ctx->bn[ctx->tos]; 109 BN_CTX_start(ctx);
103 r=ctx->bn[ctx->tos+1]; 110 if ((r = BN_CTX_get(ctx)) == NULL) goto err;
104 111
105 if (!BN_copy(r,a)) goto err; 112 if (!BN_copy(r,a)) goto err;
106 n=mont->N; 113 n= &(mont->N);
107 114
108 ap=a->d; 115 ap=a->d;
109 /* mont->ri is the size of mont->N in bits/words */ 116 /* mont->ri is the size of mont->N in bits (rounded up
117 to the word size) */
110 al=ri=mont->ri/BN_BITS2; 118 al=ri=mont->ri/BN_BITS2;
111 119
112 nl=n->top; 120 nl=n->top;
113 if ((al == 0) || (nl == 0)) { r->top=0; return(1); } 121 if ((al == 0) || (nl == 0)) { r->top=0; return(1); }
114 122
@@ -119,6 +127,7 @@ BN_CTX *ctx;
119 r->neg=a->neg^n->neg; 127 r->neg=a->neg^n->neg;
120 np=n->d; 128 np=n->d;
121 rp=r->d; 129 rp=r->d;
130 nrp= &(r->d[nl]);
122 131
123 /* clear the top words of T */ 132 /* clear the top words of T */
124#if 1 133#if 1
@@ -131,176 +140,210 @@ BN_CTX *ctx;
131 r->top=max; 140 r->top=max;
132 n0=mont->n0; 141 n0=mont->n0;
133 142
143#ifdef BN_COUNT
144 fprintf(stderr,"word BN_from_montgomery %d * %d\n",nl,nl);
145#endif
134 for (i=0; i<nl; i++) 146 for (i=0; i<nl; i++)
135 { 147 {
136#if 0 148#ifdef __TANDEM
137 int x1,x2; 149 {
138 150 long long t1;
139 if (i+4 > nl) 151 long long t2;
140 { 152 long long t3;
141 x2=nl; 153 t1 = rp[0] * (n0 & 0177777);
142 x1=0; 154 t2 = 037777600000l;
143 } 155 t2 = n0 & t2;
144 else 156 t3 = rp[0] & 0177777;
145 { 157 t2 = (t3 * t2) & BN_MASK2;
146 x2=i+4; 158 t1 = t1 + t2;
147 x1=nl-x2; 159 v=bn_mul_add_words(rp,np,nl,(BN_ULONG) t1);
148 } 160 }
149 v=bn_mul_add_words(&(rp[x1]),&(np[x1]),x2,(rp[x1]*n0)&BN_MASK2);
150#else 161#else
151 v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2); 162 v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
152#endif 163#endif
153 164 nrp++;
154 if (((rp[nl]+=v)&BN_MASK2) < v) 165 rp++;
166 if (((nrp[-1]+=v)&BN_MASK2) >= v)
167 continue;
168 else
155 { 169 {
156 for (x=(nl+1); (((++rp[x])&BN_MASK2) == 0); x++) 170 if (((++nrp[0])&BN_MASK2) != 0) continue;
157 ; 171 if (((++nrp[1])&BN_MASK2) != 0) continue;
172 for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ;
158 } 173 }
159 rp++;
160 } 174 }
161 while (r->d[r->top-1] == 0) 175 bn_fix_top(r);
162 r->top--; 176
163
164 /* mont->ri will be a multiple of the word size */ 177 /* mont->ri will be a multiple of the word size */
165#if 0 178#if 0
166 BN_rshift(ret,r,mont->ri); 179 BN_rshift(ret,r,mont->ri);
167#else 180#else
168 ap=r->d; 181 ret->neg = r->neg;
169 rp=ret->d;
170 x=ri; 182 x=ri;
171 al=r->top-x; 183 rp=ret->d;
172 for (i=0; i<al; i++) 184 ap= &(r->d[x]);
173 { 185 if (r->top < x)
174 rp[i]=ap[i+x]; 186 al=0;
175 } 187 else
188 al=r->top-x;
176 ret->top=al; 189 ret->top=al;
177#endif 190 al-=4;
178 191 for (i=0; i<al; i+=4)
179 if (BN_ucmp(ret,mont->N) >= 0)
180 { 192 {
181 bn_qsub(ret,ret,mont->N); /* XXX */ 193 BN_ULONG t1,t2,t3,t4;
194
195 t1=ap[i+0];
196 t2=ap[i+1];
197 t3=ap[i+2];
198 t4=ap[i+3];
199 rp[i+0]=t1;
200 rp[i+1]=t2;
201 rp[i+2]=t3;
202 rp[i+3]=t4;
182 } 203 }
183 retn=1; 204 al+=4;
184err: 205 for (; i<al; i++)
185 return(retn); 206 rp[i]=ap[i];
186 } 207#endif
187#else 208#else /* !MONT_WORD */
188int BN_from_montgomery(r,a,mont,ctx)
189BIGNUM *r;
190BIGNUM *a;
191BN_MONT_CTX *mont;
192BN_CTX *ctx;
193 {
194 BIGNUM *t1,*t2; 209 BIGNUM *t1,*t2;
195 210
196 t1=ctx->bn[ctx->tos]; 211 BN_CTX_start(ctx);
197 t2=ctx->bn[ctx->tos+1]; 212 t1 = BN_CTX_get(ctx);
198 213 t2 = BN_CTX_get(ctx);
214 if (t1 == NULL || t2 == NULL) goto err;
215
199 if (!BN_copy(t1,a)) goto err; 216 if (!BN_copy(t1,a)) goto err;
200 /* can cheat */
201 BN_mask_bits(t1,mont->ri); 217 BN_mask_bits(t1,mont->ri);
202 218
203 if (!BN_mul(t2,t1,mont->Ni)) goto err; 219 if (!BN_mul(t2,t1,&mont->Ni,ctx)) goto err;
204 BN_mask_bits(t2,mont->ri); 220 BN_mask_bits(t2,mont->ri);
205 221
206 if (!BN_mul(t1,t2,mont->N)) goto err; 222 if (!BN_mul(t1,t2,&mont->N,ctx)) goto err;
207 if (!BN_add(t2,a,t1)) goto err; 223 if (!BN_add(t2,a,t1)) goto err;
208 BN_rshift(r,t2,mont->ri); 224 if (!BN_rshift(ret,t2,mont->ri)) goto err;
225#endif /* MONT_WORD */
209 226
210 if (BN_ucmp(r,mont->N) >= 0) 227 if (BN_ucmp(ret, &(mont->N)) >= 0)
211 bn_qsub(r,r,mont->N); 228 {
212 229 if (!BN_usub(ret,ret,&(mont->N))) goto err;
213 return(1); 230 }
214err: 231 retn=1;
215 return(0); 232 err:
233 BN_CTX_end(ctx);
234 return(retn);
216 } 235 }
217#endif
218 236
219BN_MONT_CTX *BN_MONT_CTX_new() 237BN_MONT_CTX *BN_MONT_CTX_new(void)
220 { 238 {
221 BN_MONT_CTX *ret; 239 BN_MONT_CTX *ret;
222 240
223 if ((ret=(BN_MONT_CTX *)Malloc(sizeof(BN_MONT_CTX))) == NULL) 241 if ((ret=(BN_MONT_CTX *)OPENSSL_malloc(sizeof(BN_MONT_CTX))) == NULL)
224 return(NULL);
225 ret->ri=0;
226 ret->RR=BN_new();
227 ret->N=BN_new();
228 ret->Ni=NULL;
229 if ((ret->RR == NULL) || (ret->N == NULL))
230 {
231 BN_MONT_CTX_free(ret);
232 return(NULL); 242 return(NULL);
233 } 243
244 BN_MONT_CTX_init(ret);
245 ret->flags=BN_FLG_MALLOCED;
234 return(ret); 246 return(ret);
235 } 247 }
236 248
237void BN_MONT_CTX_free(mont) 249void BN_MONT_CTX_init(BN_MONT_CTX *ctx)
238BN_MONT_CTX *mont;
239 { 250 {
240 if (mont->RR != NULL) BN_free(mont->RR); 251 ctx->ri=0;
241 if (mont->N != NULL) BN_free(mont->N); 252 BN_init(&(ctx->RR));
242 if (mont->Ni != NULL) BN_free(mont->Ni); 253 BN_init(&(ctx->N));
243 Free(mont); 254 BN_init(&(ctx->Ni));
255 ctx->flags=0;
244 } 256 }
245 257
246int BN_MONT_CTX_set(mont,mod,ctx) 258void BN_MONT_CTX_free(BN_MONT_CTX *mont)
247BN_MONT_CTX *mont;
248BIGNUM *mod;
249BN_CTX *ctx;
250 { 259 {
251 BIGNUM *Ri=NULL,*R=NULL; 260 if(mont == NULL)
261 return;
262
263 BN_free(&(mont->RR));
264 BN_free(&(mont->N));
265 BN_free(&(mont->Ni));
266 if (mont->flags & BN_FLG_MALLOCED)
267 OPENSSL_free(mont);
268 }
252 269
253 if (mont->RR == NULL) mont->RR=BN_new(); 270int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
254 if (mont->N == NULL) mont->N=BN_new(); 271 {
272 BIGNUM Ri,*R;
255 273
256 R=mont->RR; /* grab RR as a temp */ 274 BN_init(&Ri);
257 BN_copy(mont->N,mod); /* Set N */ 275 R= &(mont->RR); /* grab RR as a temp */
276 BN_copy(&(mont->N),mod); /* Set N */
277 mont->N.neg = 0;
258 278
259#ifdef MONT_WORD 279#ifdef MONT_WORD
260{ 280 {
261 BIGNUM tmod; 281 BIGNUM tmod;
262 BN_ULONG buf[2]; 282 BN_ULONG buf[2];
263 /* int z; */ 283
264 284 mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2;
265 mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2; 285 if (!(BN_zero(R))) goto err;
266 BN_lshift(R,BN_value_one(),BN_BITS2); /* R */ 286 if (!(BN_set_bit(R,BN_BITS2))) goto err; /* R */
267 /* I was bad, this modification of a passed variable was 287
268 * breaking the multithreaded stuff :-( 288 buf[0]=mod->d[0]; /* tmod = N mod word size */
269 * z=mod->top; 289 buf[1]=0;
270 * mod->top=1; */ 290 tmod.d=buf;
271 291 tmod.top=1;
272 buf[0]=mod->d[0]; 292 tmod.dmax=2;
273 buf[1]=0; 293 tmod.neg=0;
274 tmod.d=buf; 294 /* Ri = R^-1 mod N*/
275 tmod.top=1; 295 if ((BN_mod_inverse(&Ri,R,&tmod,ctx)) == NULL)
276 tmod.max=mod->max; 296 goto err;
277 tmod.neg=mod->neg; 297 if (!BN_lshift(&Ri,&Ri,BN_BITS2)) goto err; /* R*Ri */
278 298 if (!BN_is_zero(&Ri))
279 if ((Ri=BN_mod_inverse(R,&tmod,ctx)) == NULL) goto err; /* Ri */ 299 {
280 BN_lshift(Ri,Ri,BN_BITS2); /* R*Ri */ 300 if (!BN_sub_word(&Ri,1)) goto err;
281 bn_qsub(Ri,Ri,BN_value_one()); /* R*Ri - 1 */ 301 }
282 BN_div(Ri,NULL,Ri,&tmod,ctx); 302 else /* if N mod word size == 1 */
283 mont->n0=Ri->d[0]; 303 {
284 BN_free(Ri); 304 if (!BN_set_word(&Ri,BN_MASK2)) goto err; /* Ri-- (mod word size) */
285 /* mod->top=z; */ 305 }
286} 306 if (!BN_div(&Ri,NULL,&Ri,&tmod,ctx)) goto err;
287#else 307 /* Ni = (R*Ri-1)/N,
288 mont->ri=BN_num_bits(mod); 308 * keep only least significant word: */
289 BN_lshift(R,BN_value_one(),mont->ri); /* R */ 309 mont->n0 = (Ri.top > 0) ? Ri.d[0] : 0;
290 if ((Ri=BN_mod_inverse(R,mod,ctx)) == NULL) goto err; /* Ri */ 310 BN_free(&Ri);
291 BN_lshift(Ri,Ri,mont->ri); /* R*Ri */ 311 }
292 bn_qsub(Ri,Ri,BN_value_one()); /* R*Ri - 1 */ 312#else /* !MONT_WORD */
293 BN_div(Ri,NULL,Ri,mod,ctx); 313 { /* bignum version */
294 if (mont->Ni != NULL) BN_free(mont->Ni); 314 mont->ri=BN_num_bits(&mont->N);
295 mont->Ni=Ri; /* Ni=(R*Ri-1)/N */ 315 if (!BN_zero(R)) goto err;
316 if (!BN_set_bit(R,mont->ri)) goto err; /* R = 2^ri */
317 /* Ri = R^-1 mod N*/
318 if ((BN_mod_inverse(&Ri,R,&mont->N,ctx)) == NULL)
319 goto err;
320 if (!BN_lshift(&Ri,&Ri,mont->ri)) goto err; /* R*Ri */
321 if (!BN_sub_word(&Ri,1)) goto err;
322 /* Ni = (R*Ri-1) / N */
323 if (!BN_div(&(mont->Ni),NULL,&Ri,&mont->N,ctx)) goto err;
324 BN_free(&Ri);
325 }
296#endif 326#endif
297 327
298 /* setup RR for conversions */ 328 /* setup RR for conversions */
299 BN_lshift(mont->RR,BN_value_one(),mont->ri*2); 329 if (!BN_zero(&(mont->RR))) goto err;
300 BN_mod(mont->RR,mont->RR,mont->N,ctx); 330 if (!BN_set_bit(&(mont->RR),mont->ri*2)) goto err;
331 if (!BN_mod(&(mont->RR),&(mont->RR),&(mont->N),ctx)) goto err;
301 332
302 return(1); 333 return(1);
303err: 334err:
304 return(0); 335 return(0);
305 } 336 }
306 337
338BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from)
339 {
340 if (to == from) return(to);
341
342 if (!BN_copy(&(to->RR),&(from->RR))) return NULL;
343 if (!BN_copy(&(to->N),&(from->N))) return NULL;
344 if (!BN_copy(&(to->Ni),&(from->Ni))) return NULL;
345 to->ri=from->ri;
346 to->n0=from->n0;
347 return(to);
348 }
349