X-Git-Url: https://git.openssl.org/?a=blobdiff_plain;f=crypto%2Fec%2Fecp_nistp224.c;h=89ea039b2cc8b8d16c6d891af2e167d1bfde956e;hb=9bf682f62bd819d2fbceb95eeabd61dd4532240f;hp=fdcf4503311a1470a5ab01d4d45ae32b941ee67c;hpb=23a1d5e97cd543d2b8e1b01dbf0f619b2e5ce540;p=openssl.git diff --git a/crypto/ec/ecp_nistp224.c b/crypto/ec/ecp_nistp224.c index fdcf450331..89ea039b2c 100644 --- a/crypto/ec/ecp_nistp224.c +++ b/crypto/ec/ecp_nistp224.c @@ -1,7 +1,12 @@ -/* crypto/ec/ecp_nistp224.c */ /* - * Written by Emilia Kasper (Google) for the OpenSSL project. + * Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ + /* Copyright 2011 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -26,24 +31,25 @@ */ #include -#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 +#ifdef OPENSSL_NO_EC_NISTP_64_GCC_128 +NON_EMPTY_TRANSLATION_UNIT +#else # include # include # include # include "ec_lcl.h" -# if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +# if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__==16 /* even with gcc, the typedef won't work for 32-bit platforms */ typedef __uint128_t uint128_t; /* nonstandard; implemented by gcc on 64-bit * platforms */ # else -# error "Need GCC 3.1 or later to define type uint128_t" +# error "Your compiler doesn't appear to support 128-bit integer types" # endif typedef uint8_t u8; typedef uint64_t u64; -typedef int64_t s64; /******************************************************************************/ /*- @@ -72,7 +78,7 @@ typedef limb felem[4]; typedef widelimb widefelem[7]; /* - * Field element represented as a byte arrary. 28*8 = 224 bits is also the + * Field element represented as a byte array. 28*8 = 224 bits is also the * group order size for the elliptic curve, and we also use this type for * scalars for point multiplication. */ @@ -227,10 +233,11 @@ static const felem gmul[2][16][3] = { }; /* Precomputation for the group generator. */ -typedef struct { +struct nistp224_pre_comp_st { felem g_pre_comp[2][16][3]; - int references; -} NISTP224_PRE_COMP; + CRYPTO_REF_COUNT references; + CRYPTO_RWLOCK *lock; +}; const EC_METHOD *EC_GFp_nistp224_method(void) { @@ -244,6 +251,7 @@ const EC_METHOD *EC_GFp_nistp224_method(void) ec_GFp_nistp224_group_set_curve, ec_GFp_simple_group_get_curve, ec_GFp_simple_group_get_degree, + ec_group_simple_order_bits, ec_GFp_simple_group_check_discriminant, ec_GFp_simple_point_init, ec_GFp_simple_point_finish, @@ -271,9 +279,27 @@ const EC_METHOD *EC_GFp_nistp224_method(void) ec_GFp_nist_field_mul, ec_GFp_nist_field_sqr, 0 /* field_div */ , + ec_GFp_simple_field_inv, 0 /* field_encode */ , 0 /* field_decode */ , - 0 /* field_set_to_one */ + 0, /* field_set_to_one */ + ec_key_simple_priv2oct, + ec_key_simple_oct2priv, + 0, /* set private */ + ec_key_simple_generate_key, + ec_key_simple_check_key, + ec_key_simple_generate_public_key, + 0, /* keycopy */ + 0, /* keyfinish */ + ecdsa_simple_sign_setup, + ecdsa_simple_sign_sig, + ecdsa_simple_verify_sig, + ecdh_simple_compute_key, + 0, /* field_inverse_mod_ord */ + 0, /* blind_coordinates */ + 0, /* ladder_pre */ + 0, /* ladder_step */ + 0 /* ladder_post */ }; return &ret; @@ -317,9 +343,9 @@ static int BN_to_felem(felem out, const BIGNUM *bn) unsigned num_bytes; /* BN_bn2bin eats leading zeroes */ - memset(b_out, 0, sizeof b_out); + memset(b_out, 0, sizeof(b_out)); num_bytes = BN_num_bytes(bn); - if (num_bytes > sizeof b_out) { + if (num_bytes > sizeof(b_out)) { ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); return 0; } @@ -338,8 +364,8 @@ static BIGNUM *felem_to_BN(BIGNUM *out, const felem in) { felem_bytearray b_in, b_out; felem_to_bin28(b_in, in); - flip_endian(b_out, b_in, sizeof b_out); - return BN_bin2bn(b_out, sizeof b_out, out); + flip_endian(b_out, b_in, sizeof(b_out)); + return BN_bin2bn(b_out, sizeof(b_out), out); } /******************************************************************************/ @@ -378,22 +404,6 @@ static void felem_sum(felem out, const felem in) out[3] += in[3]; } -/* Get negative value: out = -in */ -/* Assumes in[i] < 2^57 */ -static void felem_neg(felem out, const felem in) -{ - static const limb two58p2 = (((limb) 1) << 58) + (((limb) 1) << 2); - static const limb two58m2 = (((limb) 1) << 58) - (((limb) 1) << 2); - static const limb two58m42m2 = (((limb) 1) << 58) - - (((limb) 1) << 42) - (((limb) 1) << 2); - - /* Set to 0 mod 2^224-2^96+1 to ensure out > in */ - out[0] = two58p2 - in[0]; - out[1] = two58m42m2 - in[1]; - out[2] = two58m2 - in[2]; - out[3] = two58m2 - in[3]; -} - /* Subtract field elements: out -= in */ /* Assumes in[i] < 2^57 */ static void felem_diff(felem out, const felem in) @@ -662,6 +672,20 @@ static void felem_contract(felem out, const felem in) out[3] = tmp[3]; } +/* + * Get negative value: out = -in + * Requires in[i] < 2^63, + * ensures out[0] < 2^56, out[1] < 2^56, out[2] < 2^56, out[3] <= 2^56 + 2^16 + */ +static void felem_neg(felem out, const felem in) +{ + widefelem tmp; + + memset(tmp, 0, sizeof(tmp)); + felem_diff_128_64(tmp, in); + felem_reduce(out, tmp); +} + /* * Zero-check: returns 1 if input is 0, and 0 otherwise. We know that field * elements are reduced to in < 2^225, so we only need to check three cases: @@ -682,7 +706,7 @@ static limb felem_is_zero(const felem in) return (zero | two224m96p1 | two225m97p2); } -static limb felem_is_zero_int(const felem in) +static int felem_is_zero_int(const void *in) { return (int)(felem_is_zero(in) & ((limb) 1)); } @@ -800,7 +824,7 @@ static void copy_conditional(felem out, const felem in, limb icopy) * Double an elliptic curve point: * (X', Y', Z') = 2 * (X, Y, Z), where * X' = (3 * (X - Z^2) * (X + Z^2))^2 - 8 * X * Y^2 - * Y' = 3 * (X - Z^2) * (X + Z^2) * (4 * X * Y^2 - X') - 8 * Y^2 + * Y' = 3 * (X - Z^2) * (X + Z^2) * (4 * X * Y^2 - X') - 8 * Y^4 * Z' = (Y + Z)^2 - Y^2 - Z^2 = 2 * Y * Z * Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed, * while x_out == y_in is not (maybe this works, but it's not tested). @@ -1069,8 +1093,8 @@ static void select_point(const u64 idx, unsigned int size, { unsigned i, j; limb *outlimbs = &out[0][0]; - memset(outlimbs, 0, 3 * sizeof(felem)); + memset(out, 0, sizeof(*out) * 3); for (i = 0; i < size; i++) { const limb *inlimbs = &pre_comp[i][0][0]; u64 mask = i ^ idx; @@ -1113,7 +1137,7 @@ static void batch_mul(felem x_out, felem y_out, felem z_out, u8 sign, digit; /* set nq to the point at infinity */ - memset(nq, 0, 3 * sizeof(felem)); + memset(nq, 0, sizeof(nq)); /* * Loop over all scalars msb-to-lsb, interleaving additions of multiples @@ -1197,57 +1221,49 @@ static void batch_mul(felem x_out, felem y_out, felem z_out, * FUNCTIONS TO MANAGE PRECOMPUTATION */ -static NISTP224_PRE_COMP *nistp224_pre_comp_new() +static NISTP224_PRE_COMP *nistp224_pre_comp_new(void) { - NISTP224_PRE_COMP *ret = NULL; - ret = OPENSSL_malloc(sizeof *ret); + NISTP224_PRE_COMP *ret = OPENSSL_zalloc(sizeof(*ret)); + if (!ret) { ECerr(EC_F_NISTP224_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); return ret; } - memset(ret->g_pre_comp, 0, sizeof(ret->g_pre_comp)); - ret->references = 1; - return ret; -} - -static void *nistp224_pre_comp_dup(void *src_) -{ - NISTP224_PRE_COMP *src = src_; - /* no need to actually copy, these objects never change! */ - CRYPTO_add(&src->references, 1, CRYPTO_LOCK_EC_PRE_COMP); + ret->references = 1; - return src_; + ret->lock = CRYPTO_THREAD_lock_new(); + if (ret->lock == NULL) { + ECerr(EC_F_NISTP224_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + OPENSSL_free(ret); + return NULL; + } + return ret; } -static void nistp224_pre_comp_free(void *pre_) +NISTP224_PRE_COMP *EC_nistp224_pre_comp_dup(NISTP224_PRE_COMP *p) { int i; - NISTP224_PRE_COMP *pre = pre_; - - if (!pre) - return; - - i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP); - if (i > 0) - return; - - OPENSSL_free(pre); + if (p != NULL) + CRYPTO_UP_REF(&p->references, &i, p->lock); + return p; } -static void nistp224_pre_comp_clear_free(void *pre_) +void EC_nistp224_pre_comp_free(NISTP224_PRE_COMP *p) { int i; - NISTP224_PRE_COMP *pre = pre_; - if (!pre) + if (p == NULL) return; - i = CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP); + CRYPTO_DOWN_REF(&p->references, &i, p->lock); + REF_PRINT_COUNT("EC_nistp224", x); if (i > 0) return; + REF_ASSERT_ISNT(i < 0); - OPENSSL_clear_free(pre, sizeof *pre); + CRYPTO_THREAD_lock_free(p->lock); + OPENSSL_free(p); } /******************************************************************************/ @@ -1268,16 +1284,21 @@ int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p, BN_CTX *ctx) { int ret = 0; - BN_CTX *new_ctx = NULL; BIGNUM *curve_p, *curve_a, *curve_b; +#ifndef FIPS_MODE + BN_CTX *new_ctx = NULL; if (ctx == NULL) - if ((ctx = new_ctx = BN_CTX_new()) == NULL) - return 0; + ctx = new_ctx = BN_CTX_new(); +#endif + if (ctx == NULL) + return 0; + BN_CTX_start(ctx); - if (((curve_p = BN_CTX_get(ctx)) == NULL) || - ((curve_a = BN_CTX_get(ctx)) == NULL) || - ((curve_b = BN_CTX_get(ctx)) == NULL)) + curve_p = BN_CTX_get(ctx); + curve_a = BN_CTX_get(ctx); + curve_b = BN_CTX_get(ctx); + if (curve_b == NULL) goto err; BN_bin2bn(nistp224_curve_params[0], sizeof(felem_bytearray), curve_p); BN_bin2bn(nistp224_curve_params[1], sizeof(felem_bytearray), curve_a); @@ -1291,7 +1312,9 @@ int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p, ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); err: BN_CTX_end(ctx); +#ifndef FIPS_MODE BN_CTX_free(new_ctx); +#endif return ret; } @@ -1355,7 +1378,6 @@ static void make_points_affine(size_t num, felem points[ /* num */ ][3], sizeof(felem), tmp_felems, (void (*)(void *))felem_one, - (int (*)(const void *)) felem_is_zero_int, (void (*)(void *, const void *)) felem_assign, @@ -1386,11 +1408,10 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, int j; unsigned i; int mixed = 0; - BN_CTX *new_ctx = NULL; BIGNUM *x, *y, *z, *tmp_scalar; felem_bytearray g_secret; felem_bytearray *secrets = NULL; - felem(*pre_comp)[17][3] = NULL; + felem (*pre_comp)[17][3] = NULL; felem *tmp_felems = NULL; felem_bytearray tmp; unsigned num_bytes; @@ -1403,21 +1424,16 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, const EC_POINT *p = NULL; const BIGNUM *p_scalar = NULL; - if (ctx == NULL) - if ((ctx = new_ctx = BN_CTX_new()) == NULL) - return 0; BN_CTX_start(ctx); - if (((x = BN_CTX_get(ctx)) == NULL) || - ((y = BN_CTX_get(ctx)) == NULL) || - ((z = BN_CTX_get(ctx)) == NULL) || - ((tmp_scalar = BN_CTX_get(ctx)) == NULL)) + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + z = BN_CTX_get(ctx); + tmp_scalar = BN_CTX_get(ctx); + if (tmp_scalar == NULL) goto err; if (scalar != NULL) { - pre = EC_EX_DATA_get_data(group->extra_data, - nistp224_pre_comp_dup, - nistp224_pre_comp_free, - nistp224_pre_comp_clear_free); + pre = group->pre_comp.nistp224; if (pre) /* we have precomputation, try to use it */ g_pre_comp = (const felem(*)[16][3])pre->g_pre_comp; @@ -1457,11 +1473,11 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, */ mixed = 1; } - secrets = OPENSSL_malloc(num_points * sizeof(felem_bytearray)); - pre_comp = OPENSSL_malloc(num_points * 17 * 3 * sizeof(felem)); + secrets = OPENSSL_zalloc(sizeof(*secrets) * num_points); + pre_comp = OPENSSL_zalloc(sizeof(*pre_comp) * num_points); if (mixed) tmp_felems = - OPENSSL_malloc((num_points * 17 + 1) * sizeof(felem)); + OPENSSL_malloc(sizeof(felem) * (num_points * 17 + 1)); if ((secrets == NULL) || (pre_comp == NULL) || (mixed && (tmp_felems == NULL))) { ECerr(EC_F_EC_GFP_NISTP224_POINTS_MUL, ERR_R_MALLOC_FAILURE); @@ -1472,8 +1488,6 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, * we treat NULL scalars as 0, and NULL points as points at infinity, * i.e., they contribute nothing to the linear combination */ - memset(secrets, 0, num_points * sizeof(felem_bytearray)); - memset(pre_comp, 0, num_points * 17 * 3 * sizeof(felem)); for (i = 0; i < num_points; ++i) { if (i == num) /* the generator */ @@ -1533,7 +1547,7 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, /* the scalar for the generator */ if ((scalar != NULL) && (have_pre_comp)) { - memset(g_secret, 0, sizeof g_secret); + memset(g_secret, 0, sizeof(g_secret)); /* reduce scalar to 0 <= scalar < 2^224 */ if ((BN_num_bits(scalar) > 224) || (BN_is_negative(scalar))) { /* @@ -1572,13 +1586,9 @@ int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r, err: BN_CTX_end(ctx); EC_POINT_free(generator); - BN_CTX_free(new_ctx); - if (secrets != NULL) - OPENSSL_free(secrets); - if (pre_comp != NULL) - OPENSSL_free(pre_comp); - if (tmp_felems != NULL) - OPENSSL_free(tmp_felems); + OPENSSL_free(secrets); + OPENSSL_free(pre_comp); + OPENSSL_free(tmp_felems); return ret; } @@ -1587,20 +1597,27 @@ int ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx) int ret = 0; NISTP224_PRE_COMP *pre = NULL; int i, j; - BN_CTX *new_ctx = NULL; BIGNUM *x, *y; EC_POINT *generator = NULL; felem tmp_felems[32]; +#ifndef FIPS_MODE + BN_CTX *new_ctx = NULL; +#endif /* throw away old precomputation */ - EC_EX_DATA_free_data(&group->extra_data, nistp224_pre_comp_dup, - nistp224_pre_comp_free, - nistp224_pre_comp_clear_free); + EC_pre_comp_free(group); + +#ifndef FIPS_MODE if (ctx == NULL) - if ((ctx = new_ctx = BN_CTX_new()) == NULL) - return 0; + ctx = new_ctx = BN_CTX_new(); +#endif + if (ctx == NULL) + return 0; + BN_CTX_start(ctx); - if (((x = BN_CTX_get(ctx)) == NULL) || ((y = BN_CTX_get(ctx)) == NULL)) + x = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + if (y == NULL) goto err; /* get the generator */ if (group->generator == NULL) @@ -1610,7 +1627,7 @@ int ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx) goto err; BN_bin2bn(nistp224_curve_params[3], sizeof(felem_bytearray), x); BN_bin2bn(nistp224_curve_params[4], sizeof(felem_bytearray), y); - if (!EC_POINT_set_affine_coordinates_GFp(group, generator, x, y, ctx)) + if (!EC_POINT_set_affine_coordinates(group, generator, x, y, ctx)) goto err; if ((pre = nistp224_pre_comp_new()) == NULL) goto err; @@ -1619,8 +1636,7 @@ int ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx) */ if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) { memcpy(pre->g_pre_comp, gmul, sizeof(pre->g_pre_comp)); - ret = 1; - goto err; + goto done; } if ((!BN_to_felem(pre->g_pre_comp[0][1][0], group->generator->X)) || (!BN_to_felem(pre->g_pre_comp[0][1][1], group->generator->Y)) || @@ -1698,31 +1714,23 @@ int ec_GFp_nistp224_precompute_mult(EC_GROUP *group, BN_CTX *ctx) } make_points_affine(31, &(pre->g_pre_comp[0][1]), tmp_felems); - if (!EC_EX_DATA_set_data(&group->extra_data, pre, nistp224_pre_comp_dup, - nistp224_pre_comp_free, - nistp224_pre_comp_clear_free)) - goto err; - ret = 1; + done: + SETPRECOMP(group, nistp224, pre); pre = NULL; + ret = 1; err: BN_CTX_end(ctx); EC_POINT_free(generator); +#ifndef FIPS_MODE BN_CTX_free(new_ctx); - nistp224_pre_comp_free(pre); +#endif + EC_nistp224_pre_comp_free(pre); return ret; } int ec_GFp_nistp224_have_precompute_mult(const EC_GROUP *group) { - if (EC_EX_DATA_get_data(group->extra_data, nistp224_pre_comp_dup, - nistp224_pre_comp_free, - nistp224_pre_comp_clear_free) - != NULL) - return 1; - else - return 0; + return HAVEPRECOMP(group, nistp224); } -#else -static void *dummy = &dummy; #endif