X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fec%2Fecp_nistz256.c;h=b0564bdbd04c56f9dc1bd63e3fd5ad9e5e9c5d8b;hp=6bae3d1f82497c069b7cf9feb3a5e22c837ded20;hb=453eccd63ad6ba19f6a3fcac37df05daf6cc1021;hpb=ab4f2026b7ff8902d70ddd75adc080fc66ffd642 diff --git a/crypto/ec/ecp_nistz256.c b/crypto/ec/ecp_nistz256.c index 6bae3d1f82..b0564bdbd0 100644 --- a/crypto/ec/ecp_nistz256.c +++ b/crypto/ec/ecp_nistz256.c @@ -1,5 +1,5 @@ /* - * Copyright 2014-2017 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2014, Intel Corporation. All Rights Reserved. * Copyright (c) 2015, CloudFlare, Inc. * @@ -1104,28 +1104,12 @@ __owur static int ecp_nistz256_set_from_affine(EC_POINT *out, const EC_GROUP *gr const P256_POINT_AFFINE *in, BN_CTX *ctx) { - BIGNUM *x, *y; - BN_ULONG d_x[P256_LIMBS], d_y[P256_LIMBS]; int ret = 0; - x = BN_new(); - if (x == NULL) - return 0; - y = BN_new(); - if (y == NULL) { - BN_free(x); - return 0; - } - memcpy(d_x, in->X, sizeof(d_x)); - bn_set_static_words(x, d_x, P256_LIMBS); - - memcpy(d_y, in->Y, sizeof(d_y)); - bn_set_static_words(y, d_y, P256_LIMBS); - - ret = EC_POINT_set_affine_coordinates_GFp(group, out, x, y, ctx); - - BN_free(x); - BN_free(y); + if ((ret = bn_set_words(out->X, in->X, P256_LIMBS)) + && (ret = bn_set_words(out->Y, in->Y, P256_LIMBS)) + && (ret = bn_set_words(out->Z, ONE, P256_LIMBS))) + out->Z_is_one = 1; return ret; } @@ -1139,12 +1123,10 @@ __owur static int ecp_nistz256_points_mul(const EC_GROUP *group, const BIGNUM *scalars[], BN_CTX *ctx) { int i = 0, ret = 0, no_precomp_for_generator = 0, p_is_infinity = 0; - size_t j; unsigned char p_str[33] = { 0 }; const PRECOMP256_ROW *preComputedTable = NULL; const NISTZ256_PRE_COMP *pre_comp = NULL; const EC_POINT *generator = NULL; - BN_CTX *new_ctx = NULL; const BIGNUM **new_scalars = NULL; const EC_POINT **new_points = NULL; unsigned int idx = 0; @@ -1162,27 +1144,6 @@ __owur static int ecp_nistz256_points_mul(const EC_GROUP *group, return 0; } - if (group->meth != r->meth) { - ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS); - return 0; - } - - if ((scalar == NULL) && (num == 0)) - return EC_POINT_set_to_infinity(group, r); - - for (j = 0; j < num; j++) { - if (group->meth != points[j]->meth) { - ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS); - return 0; - } - } - - if (ctx == NULL) { - ctx = new_ctx = BN_CTX_new(); - if (ctx == NULL) - goto err; - } - BN_CTX_start(ctx); if (scalar) { @@ -1204,9 +1165,9 @@ __owur static int ecp_nistz256_points_mul(const EC_GROUP *group, if (pre_comp_generator == NULL) goto err; + ecp_nistz256_gather_w7(&p.a, pre_comp->precomp[0], 1); if (!ecp_nistz256_set_from_affine(pre_comp_generator, - group, pre_comp->precomp[0], - ctx)) { + group, &p.a, ctx)) { EC_POINT_free(pre_comp_generator); goto err; } @@ -1378,9 +1339,7 @@ __owur static int ecp_nistz256_points_mul(const EC_GROUP *group, ret = 1; err: - if (ctx) - BN_CTX_end(ctx); - BN_CTX_free(new_ctx); + BN_CTX_end(ctx); OPENSSL_free(new_points); OPENSSL_free(new_scalars); return ret; @@ -1512,22 +1471,17 @@ void ecp_nistz256_ord_sqr_mont(BN_ULONG res[P256_LIMBS], int rep); static int ecp_nistz256_inv_mod_ord(const EC_GROUP *group, BIGNUM *r, - BIGNUM *x, BN_CTX *ctx) + const BIGNUM *x, BN_CTX *ctx) { /* RR = 2^512 mod ord(p256) */ - static const BN_ULONG RR[P256_LIMBS] = { TOBN(0x83244c95,0xbe79eea2), - TOBN(0x4699799c,0x49bd6fa6), - TOBN(0x2845b239,0x2b6bec59), - TOBN(0x66e12d94,0xf3d95620) }; + static const BN_ULONG RR[P256_LIMBS] = { + TOBN(0x83244c95,0xbe79eea2), TOBN(0x4699799c,0x49bd6fa6), + TOBN(0x2845b239,0x2b6bec59), TOBN(0x66e12d94,0xf3d95620) + }; /* The constant 1 (unlike ONE that is one in Montgomery representation) */ - static const BN_ULONG one[P256_LIMBS] = { TOBN(0,1),TOBN(0,0), - TOBN(0,0),TOBN(0,0) }; - /* expLo - the low 128bit of the exponent we use (ord(p256) - 2), - * split into 4bit windows */ - static const unsigned char expLo[32] = { 0xb,0xc,0xe,0x6,0xf,0xa,0xa,0xd, - 0xa,0x7,0x1,0x7,0x9,0xe,0x8,0x4, - 0xf,0x3,0xb,0x9,0xc,0xa,0xc,0x2, - 0xf,0xc,0x6,0x3,0x2,0x5,0x4,0xf }; + static const BN_ULONG one[P256_LIMBS] = { + TOBN(0,1), TOBN(0,0), TOBN(0,0), TOBN(0,0) + }; /* * We don't use entry 0 in the table, so we omit it and address * with -1 offset. @@ -1535,6 +1489,10 @@ static int ecp_nistz256_inv_mod_ord(const EC_GROUP *group, BIGNUM *r, BN_ULONG table[15][P256_LIMBS]; BN_ULONG out[P256_LIMBS], t[P256_LIMBS]; int i, ret = 0; + enum { + i_1 = 0, i_10, i_11, i_101, i_111, i_1010, i_1111, + i_10101, i_101010, i_101111, i_x6, i_x8, i_x16, i_x32 + }; /* * Catch allocation failure early. @@ -1561,6 +1519,10 @@ static int ecp_nistz256_inv_mod_ord(const EC_GROUP *group, BIGNUM *r, } ecp_nistz256_ord_mul_mont(table[0], t, RR); +#if 0 + /* + * Original sparse-then-fixed-window algorithm, retained for reference. + */ for (i = 2; i < 16; i += 2) { ecp_nistz256_ord_sqr_mont(table[i-1], table[i/2-1], 1); ecp_nistz256_ord_mul_mont(table[i], table[i-1], table[0]); @@ -1586,13 +1548,81 @@ static int ecp_nistz256_inv_mod_ord(const EC_GROUP *group, BIGNUM *r, ecp_nistz256_ord_mul_mont(out, out, t); /* ffffffff00000000ffffffffffffffff */ /* - * The bottom 128 bit of the exponent are easier done with a table + * The bottom 128 bit of the exponent are processed with fixed 4-bit window */ for(i = 0; i < 32; i++) { + /* expLo - the low 128 bits of the exponent we use (ord(p256) - 2), + * split into nibbles */ + static const unsigned char expLo[32] = { + 0xb,0xc,0xe,0x6,0xf,0xa,0xa,0xd,0xa,0x7,0x1,0x7,0x9,0xe,0x8,0x4, + 0xf,0x3,0xb,0x9,0xc,0xa,0xc,0x2,0xf,0xc,0x6,0x3,0x2,0x5,0x4,0xf + }; + ecp_nistz256_ord_sqr_mont(out, out, 4); /* The exponent is public, no need in constant-time access */ ecp_nistz256_ord_mul_mont(out, out, table[expLo[i]-1]); } +#else + /* + * https://briansmith.org/ecc-inversion-addition-chains-01#p256_scalar_inversion + * + * Even though this code path spares 12 squarings, 4.5%, and 13 + * multiplications, 25%, on grand scale sign operation is not that + * much faster, not more that 2%... + */ + + /* pre-calculate powers */ + ecp_nistz256_ord_sqr_mont(table[i_10], table[i_1], 1); + + ecp_nistz256_ord_mul_mont(table[i_11], table[i_1], table[i_10]); + + ecp_nistz256_ord_mul_mont(table[i_101], table[i_11], table[i_10]); + + ecp_nistz256_ord_mul_mont(table[i_111], table[i_101], table[i_10]); + + ecp_nistz256_ord_sqr_mont(table[i_1010], table[i_101], 1); + + ecp_nistz256_ord_mul_mont(table[i_1111], table[i_1010], table[i_101]); + + ecp_nistz256_ord_sqr_mont(table[i_10101], table[i_1010], 1); + ecp_nistz256_ord_mul_mont(table[i_10101], table[i_10101], table[i_1]); + + ecp_nistz256_ord_sqr_mont(table[i_101010], table[i_10101], 1); + + ecp_nistz256_ord_mul_mont(table[i_101111], table[i_101010], table[i_101]); + + ecp_nistz256_ord_mul_mont(table[i_x6], table[i_101010], table[i_10101]); + + ecp_nistz256_ord_sqr_mont(table[i_x8], table[i_x6], 2); + ecp_nistz256_ord_mul_mont(table[i_x8], table[i_x8], table[i_11]); + + ecp_nistz256_ord_sqr_mont(table[i_x16], table[i_x8], 8); + ecp_nistz256_ord_mul_mont(table[i_x16], table[i_x16], table[i_x8]); + + ecp_nistz256_ord_sqr_mont(table[i_x32], table[i_x16], 16); + ecp_nistz256_ord_mul_mont(table[i_x32], table[i_x32], table[i_x16]); + + /* calculations */ + ecp_nistz256_ord_sqr_mont(out, table[i_x32], 64); + ecp_nistz256_ord_mul_mont(out, out, table[i_x32]); + + for (i = 0; i < 27; i++) { + static const struct { unsigned char p, i; } chain[27] = { + { 32, i_x32 }, { 6, i_101111 }, { 5, i_111 }, + { 4, i_11 }, { 5, i_1111 }, { 5, i_10101 }, + { 4, i_101 }, { 3, i_101 }, { 3, i_101 }, + { 5, i_111 }, { 9, i_101111 }, { 6, i_1111 }, + { 2, i_1 }, { 5, i_1 }, { 6, i_1111 }, + { 5, i_111 }, { 4, i_111 }, { 5, i_111 }, + { 5, i_101 }, { 3, i_11 }, { 10, i_101111 }, + { 2, i_11 }, { 5, i_11 }, { 5, i_11 }, + { 3, i_1 }, { 7, i_10101 }, { 6, i_1111 } + }; + + ecp_nistz256_ord_sqr_mont(out, out, chain[i].p); + ecp_nistz256_ord_mul_mont(out, out, table[chain[i].i]); + } +#endif ecp_nistz256_ord_mul_mont(out, out, one); /* @@ -1659,7 +1689,11 @@ const EC_METHOD *EC_GFp_nistz256_method(void) 0, /* keycopy */ 0, /* keyfinish */ ecdh_simple_compute_key, - ecp_nistz256_inv_mod_ord /* can be #defined-ed NULL */ + ecp_nistz256_inv_mod_ord, /* can be #define-d NULL */ + 0, /* blind_coordinates */ + 0, /* ladder_pre */ + 0, /* ladder_step */ + 0 /* ladder_post */ }; return &ret;