OLD | NEW |
1 /* crypto/ec/ec2_mult.c */ | 1 /* crypto/ec/ec2_mult.c */ |
2 /* ==================================================================== | 2 /* ==================================================================== |
3 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. | 3 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. |
4 * | 4 * |
5 * The Elliptic Curve Public-Key Crypto Library (ECC Code) included | 5 * The Elliptic Curve Public-Key Crypto Library (ECC Code) included |
6 * herein is developed by SUN MICROSYSTEMS, INC., and is contributed | 6 * herein is developed by SUN MICROSYSTEMS, INC., and is contributed |
7 * to the OpenSSL project. | 7 * to the OpenSSL project. |
8 * | 8 * |
9 * The ECC Code is licensed pursuant to the OpenSSL open source | 9 * The ECC Code is licensed pursuant to the OpenSSL open source |
10 * license provided below. | 10 * license provided below. |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 | 69 |
70 #include <openssl/err.h> | 70 #include <openssl/err.h> |
71 | 71 |
72 #include "ec_lcl.h" | 72 #include "ec_lcl.h" |
73 | 73 |
74 | 74 |
75 /* Compute the x-coordinate x/z for the point 2*(x/z) in Montgomery projective | 75 /* Compute the x-coordinate x/z for the point 2*(x/z) in Montgomery projective |
76 * coordinates. | 76 * coordinates. |
77 * Uses algorithm Mdouble in appendix of | 77 * Uses algorithm Mdouble in appendix of |
78 * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over | 78 * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over |
79 * GF(2^m) without precomputation". | 79 * GF(2^m) without precomputation" (CHES '99, LNCS 1717). |
80 * modified to not require precomputation of c=b^{2^{m-1}}. | 80 * modified to not require precomputation of c=b^{2^{m-1}}. |
81 */ | 81 */ |
82 static int gf2m_Mdouble(const EC_GROUP *group, BIGNUM *x, BIGNUM *z, BN_CTX *ctx
) | 82 static int gf2m_Mdouble(const EC_GROUP *group, BIGNUM *x, BIGNUM *z, BN_CTX *ctx
) |
83 { | 83 { |
84 BIGNUM *t1; | 84 BIGNUM *t1; |
85 int ret = 0; | 85 int ret = 0; |
86 | 86 |
87 /* Since Mdouble is static we can guarantee that ctx != NULL. */ | 87 /* Since Mdouble is static we can guarantee that ctx != NULL. */ |
88 BN_CTX_start(ctx); | 88 BN_CTX_start(ctx); |
89 t1 = BN_CTX_get(ctx); | 89 t1 = BN_CTX_get(ctx); |
(...skipping 10 matching lines...) Expand all Loading... |
100 ret = 1; | 100 ret = 1; |
101 | 101 |
102 err: | 102 err: |
103 BN_CTX_end(ctx); | 103 BN_CTX_end(ctx); |
104 return ret; | 104 return ret; |
105 } | 105 } |
106 | 106 |
107 /* Compute the x-coordinate x1/z1 for the point (x1/z1)+(x2/x2) in Montgomery | 107 /* Compute the x-coordinate x1/z1 for the point (x1/z1)+(x2/x2) in Montgomery |
108 * projective coordinates. | 108 * projective coordinates. |
109 * Uses algorithm Madd in appendix of | 109 * Uses algorithm Madd in appendix of |
110 * Lopex, J. and Dahab, R. "Fast multiplication on elliptic curves over | 110 * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over |
111 * GF(2^m) without precomputation". | 111 * GF(2^m) without precomputation" (CHES '99, LNCS 1717). |
112 */ | 112 */ |
113 static int gf2m_Madd(const EC_GROUP *group, const BIGNUM *x, BIGNUM *x1, BIGNUM
*z1, | 113 static int gf2m_Madd(const EC_GROUP *group, const BIGNUM *x, BIGNUM *x1, BIGNUM
*z1, |
114 const BIGNUM *x2, const BIGNUM *z2, BN_CTX *ctx) | 114 const BIGNUM *x2, const BIGNUM *z2, BN_CTX *ctx) |
115 { | 115 { |
116 BIGNUM *t1, *t2; | 116 BIGNUM *t1, *t2; |
117 int ret = 0; | 117 int ret = 0; |
118 | 118 |
119 /* Since Madd is static we can guarantee that ctx != NULL. */ | 119 /* Since Madd is static we can guarantee that ctx != NULL. */ |
120 BN_CTX_start(ctx); | 120 BN_CTX_start(ctx); |
121 t1 = BN_CTX_get(ctx); | 121 t1 = BN_CTX_get(ctx); |
(...skipping 11 matching lines...) Expand all Loading... |
133 | 133 |
134 ret = 1; | 134 ret = 1; |
135 | 135 |
136 err: | 136 err: |
137 BN_CTX_end(ctx); | 137 BN_CTX_end(ctx); |
138 return ret; | 138 return ret; |
139 } | 139 } |
140 | 140 |
141 /* Compute the x, y affine coordinates from the point (x1, z1) (x2, z2) | 141 /* Compute the x, y affine coordinates from the point (x1, z1) (x2, z2) |
142 * using Montgomery point multiplication algorithm Mxy() in appendix of | 142 * using Montgomery point multiplication algorithm Mxy() in appendix of |
143 * Lopex, J. and Dahab, R. "Fast multiplication on elliptic curves over | 143 * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over |
144 * GF(2^m) without precomputation". | 144 * GF(2^m) without precomputation" (CHES '99, LNCS 1717). |
145 * Returns: | 145 * Returns: |
146 * 0 on error | 146 * 0 on error |
147 * 1 if return value should be the point at infinity | 147 * 1 if return value should be the point at infinity |
148 * 2 otherwise | 148 * 2 otherwise |
149 */ | 149 */ |
150 static int gf2m_Mxy(const EC_GROUP *group, const BIGNUM *x, const BIGNUM *y, BIG
NUM *x1, | 150 static int gf2m_Mxy(const EC_GROUP *group, const BIGNUM *x, const BIGNUM *y, BIG
NUM *x1, |
151 BIGNUM *z1, BIGNUM *x2, BIGNUM *z2, BN_CTX *ctx) | 151 BIGNUM *z1, BIGNUM *x2, BIGNUM *z2, BN_CTX *ctx) |
152 { | 152 { |
153 BIGNUM *t3, *t4, *t5; | 153 BIGNUM *t3, *t4, *t5; |
154 int ret = 0; | 154 int ret = 0; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 ret = 2; | 202 ret = 2; |
203 | 203 |
204 err: | 204 err: |
205 BN_CTX_end(ctx); | 205 BN_CTX_end(ctx); |
206 return ret; | 206 return ret; |
207 } | 207 } |
208 | 208 |
209 /* Computes scalar*point and stores the result in r. | 209 /* Computes scalar*point and stores the result in r. |
210 * point can not equal r. | 210 * point can not equal r. |
211 * Uses algorithm 2P of | 211 * Uses algorithm 2P of |
212 * Lopex, J. and Dahab, R. "Fast multiplication on elliptic curves over | 212 * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over |
213 * GF(2^m) without precomputation". | 213 * GF(2^m) without precomputation" (CHES '99, LNCS 1717). |
214 */ | 214 */ |
215 static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group, EC_POINT *r,
const BIGNUM *scalar, | 215 static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group, EC_POINT *r,
const BIGNUM *scalar, |
216 const EC_POINT *point, BN_CTX *ctx) | 216 const EC_POINT *point, BN_CTX *ctx) |
217 { | 217 { |
218 BIGNUM *x1, *x2, *z1, *z2; | 218 BIGNUM *x1, *x2, *z1, *z2; |
219 » int ret = 0, i, j; | 219 » int ret = 0, i; |
220 » BN_ULONG mask; | 220 » BN_ULONG mask,word; |
221 | 221 |
222 if (r == point) | 222 if (r == point) |
223 { | 223 { |
224 ECerr(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, EC_R_INVALID_ARGUM
ENT); | 224 ECerr(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, EC_R_INVALID_ARGUM
ENT); |
225 return 0; | 225 return 0; |
226 } | 226 } |
227 | 227 |
228 /* if result should be point at infinity */ | 228 /* if result should be point at infinity */ |
229 if ((scalar == NULL) || BN_is_zero(scalar) || (point == NULL) || | 229 if ((scalar == NULL) || BN_is_zero(scalar) || (point == NULL) || |
230 EC_POINT_is_at_infinity(group, point)) | 230 EC_POINT_is_at_infinity(group, point)) |
(...skipping 13 matching lines...) Expand all Loading... |
244 x2 = &r->X; | 244 x2 = &r->X; |
245 z2 = &r->Y; | 245 z2 = &r->Y; |
246 | 246 |
247 if (!BN_GF2m_mod_arr(x1, &point->X, group->poly)) goto err; /* x1 = x */ | 247 if (!BN_GF2m_mod_arr(x1, &point->X, group->poly)) goto err; /* x1 = x */ |
248 if (!BN_one(z1)) goto err; /* z1 = 1 */ | 248 if (!BN_one(z1)) goto err; /* z1 = 1 */ |
249 if (!group->meth->field_sqr(group, z2, x1, ctx)) goto err; /* z2 = x1^2
= x^2 */ | 249 if (!group->meth->field_sqr(group, z2, x1, ctx)) goto err; /* z2 = x1^2
= x^2 */ |
250 if (!group->meth->field_sqr(group, x2, z2, ctx)) goto err; | 250 if (!group->meth->field_sqr(group, x2, z2, ctx)) goto err; |
251 if (!BN_GF2m_add(x2, x2, &group->b)) goto err; /* x2 = x^4 + b */ | 251 if (!BN_GF2m_add(x2, x2, &group->b)) goto err; /* x2 = x^4 + b */ |
252 | 252 |
253 /* find top most bit and go one past it */ | 253 /* find top most bit and go one past it */ |
254 » i = scalar->top - 1; j = BN_BITS2 - 1; | 254 » i = scalar->top - 1; |
255 mask = BN_TBIT; | 255 mask = BN_TBIT; |
256 » while (!(scalar->d[i] & mask)) { mask >>= 1; j--; } | 256 » word = scalar->d[i]; |
257 » mask >>= 1; j--; | 257 » while (!(word & mask)) mask >>= 1; |
| 258 » mask >>= 1; |
258 /* if top most bit was at word break, go to next word */ | 259 /* if top most bit was at word break, go to next word */ |
259 if (!mask) | 260 if (!mask) |
260 { | 261 { |
261 » » i--; j = BN_BITS2 - 1; | 262 » » i--; |
262 mask = BN_TBIT; | 263 mask = BN_TBIT; |
263 } | 264 } |
264 | 265 |
265 for (; i >= 0; i--) | 266 for (; i >= 0; i--) |
266 { | 267 { |
267 » » for (; j >= 0; j--) | 268 » » word = scalar->d[i]; |
| 269 » » while (mask) |
268 { | 270 { |
269 » » » if (scalar->d[i] & mask) | 271 » » » if (word & mask) |
270 { | 272 { |
271 if (!gf2m_Madd(group, &point->X, x1, z1, x2, z2,
ctx)) goto err; | 273 if (!gf2m_Madd(group, &point->X, x1, z1, x2, z2,
ctx)) goto err; |
272 if (!gf2m_Mdouble(group, x2, z2, ctx)) goto err; | 274 if (!gf2m_Mdouble(group, x2, z2, ctx)) goto err; |
273 } | 275 } |
274 else | 276 else |
275 { | 277 { |
276 if (!gf2m_Madd(group, &point->X, x2, z2, x1, z1,
ctx)) goto err; | 278 if (!gf2m_Madd(group, &point->X, x2, z2, x1, z1,
ctx)) goto err; |
277 if (!gf2m_Mdouble(group, x1, z1, ctx)) goto err; | 279 if (!gf2m_Mdouble(group, x1, z1, ctx)) goto err; |
278 } | 280 } |
279 mask >>= 1; | 281 mask >>= 1; |
280 } | 282 } |
281 j = BN_BITS2 - 1; | |
282 mask = BN_TBIT; | 283 mask = BN_TBIT; |
283 } | 284 } |
284 | 285 |
285 /* convert out of "projective" coordinates */ | 286 /* convert out of "projective" coordinates */ |
286 i = gf2m_Mxy(group, &point->X, &point->Y, x1, z1, x2, z2, ctx); | 287 i = gf2m_Mxy(group, &point->X, &point->Y, x1, z1, x2, z2, ctx); |
287 if (i == 0) goto err; | 288 if (i == 0) goto err; |
288 else if (i == 1) | 289 else if (i == 1) |
289 { | 290 { |
290 if (!EC_POINT_set_to_infinity(group, r)) goto err; | 291 if (!EC_POINT_set_to_infinity(group, r)) goto err; |
291 } | 292 } |
(...skipping 19 matching lines...) Expand all Loading... |
311 * scalar*group->generator + scalars[0]*points[0] + ... + scalars[num-1]*poi
nts[num-1] | 312 * scalar*group->generator + scalars[0]*points[0] + ... + scalars[num-1]*poi
nts[num-1] |
312 * gracefully ignoring NULL scalar values. | 313 * gracefully ignoring NULL scalar values. |
313 */ | 314 */ |
314 int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, | 315 int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, |
315 size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *c
tx) | 316 size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *c
tx) |
316 { | 317 { |
317 BN_CTX *new_ctx = NULL; | 318 BN_CTX *new_ctx = NULL; |
318 int ret = 0; | 319 int ret = 0; |
319 size_t i; | 320 size_t i; |
320 EC_POINT *p=NULL; | 321 EC_POINT *p=NULL; |
| 322 EC_POINT *acc = NULL; |
321 | 323 |
322 if (ctx == NULL) | 324 if (ctx == NULL) |
323 { | 325 { |
324 ctx = new_ctx = BN_CTX_new(); | 326 ctx = new_ctx = BN_CTX_new(); |
325 if (ctx == NULL) | 327 if (ctx == NULL) |
326 return 0; | 328 return 0; |
327 } | 329 } |
328 | 330 |
329 /* This implementation is more efficient than the wNAF implementation fo
r 2 | 331 /* This implementation is more efficient than the wNAF implementation fo
r 2 |
330 * or fewer points. Use the ec_wNAF_mul implementation for 3 or more po
ints, | 332 * or fewer points. Use the ec_wNAF_mul implementation for 3 or more po
ints, |
331 * or if we can perform a fast multiplication based on precomputation. | 333 * or if we can perform a fast multiplication based on precomputation. |
332 */ | 334 */ |
333 if ((scalar && (num > 1)) || (num > 2) || (num == 0 && EC_GROUP_have_pre
compute_mult(group))) | 335 if ((scalar && (num > 1)) || (num > 2) || (num == 0 && EC_GROUP_have_pre
compute_mult(group))) |
334 { | 336 { |
335 ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); | 337 ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); |
336 goto err; | 338 goto err; |
337 } | 339 } |
338 | 340 |
339 if ((p = EC_POINT_new(group)) == NULL) goto err; | 341 if ((p = EC_POINT_new(group)) == NULL) goto err; |
| 342 if ((acc = EC_POINT_new(group)) == NULL) goto err; |
340 | 343 |
341 » if (!EC_POINT_set_to_infinity(group, r)) goto err; | 344 » if (!EC_POINT_set_to_infinity(group, acc)) goto err; |
342 | 345 |
343 if (scalar) | 346 if (scalar) |
344 { | 347 { |
345 if (!ec_GF2m_montgomery_point_multiply(group, p, scalar, group->
generator, ctx)) goto err; | 348 if (!ec_GF2m_montgomery_point_multiply(group, p, scalar, group->
generator, ctx)) goto err; |
346 » » if (BN_is_negative(scalar)) | 349 » » if (BN_is_negative(scalar)) |
347 if (!group->meth->invert(group, p, ctx)) goto err; | 350 if (!group->meth->invert(group, p, ctx)) goto err; |
348 » » if (!group->meth->add(group, r, r, p, ctx)) goto err; | 351 » » if (!group->meth->add(group, acc, acc, p, ctx)) goto err; |
349 } | 352 } |
350 | 353 |
351 for (i = 0; i < num; i++) | 354 for (i = 0; i < num; i++) |
352 { | 355 { |
353 if (!ec_GF2m_montgomery_point_multiply(group, p, scalars[i], poi
nts[i], ctx)) goto err; | 356 if (!ec_GF2m_montgomery_point_multiply(group, p, scalars[i], poi
nts[i], ctx)) goto err; |
354 if (BN_is_negative(scalars[i])) | 357 if (BN_is_negative(scalars[i])) |
355 if (!group->meth->invert(group, p, ctx)) goto err; | 358 if (!group->meth->invert(group, p, ctx)) goto err; |
356 » » if (!group->meth->add(group, r, r, p, ctx)) goto err; | 359 » » if (!group->meth->add(group, acc, acc, p, ctx)) goto err; |
357 } | 360 } |
358 | 361 |
| 362 if (!EC_POINT_copy(r, acc)) goto err; |
| 363 |
359 ret = 1; | 364 ret = 1; |
360 | 365 |
361 err: | 366 err: |
362 if (p) EC_POINT_free(p); | 367 if (p) EC_POINT_free(p); |
| 368 if (acc) EC_POINT_free(acc); |
363 if (new_ctx != NULL) | 369 if (new_ctx != NULL) |
364 BN_CTX_free(new_ctx); | 370 BN_CTX_free(new_ctx); |
365 return ret; | 371 return ret; |
366 } | 372 } |
367 | 373 |
368 | 374 |
369 /* Precomputation for point multiplication: fall back to wNAF methods | 375 /* Precomputation for point multiplication: fall back to wNAF methods |
370 * because ec_GF2m_simple_mul() uses ec_wNAF_mul() if appropriate */ | 376 * because ec_GF2m_simple_mul() uses ec_wNAF_mul() if appropriate */ |
371 | 377 |
372 int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx) | 378 int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx) |
373 { | 379 { |
374 return ec_wNAF_precompute_mult(group, ctx); | 380 return ec_wNAF_precompute_mult(group, ctx); |
375 } | 381 } |
376 | 382 |
377 int ec_GF2m_have_precompute_mult(const EC_GROUP *group) | 383 int ec_GF2m_have_precompute_mult(const EC_GROUP *group) |
378 { | 384 { |
379 return ec_wNAF_have_precompute_mult(group); | 385 return ec_wNAF_have_precompute_mult(group); |
380 } | 386 } |
OLD | NEW |