| 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 |