diff options
Diffstat (limited to 'crypto/ec/ecp_nistp521.c')
-rw-r--r-- | crypto/ec/ecp_nistp521.c | 319 |
1 files changed, 191 insertions, 128 deletions
diff --git a/crypto/ec/ecp_nistp521.c b/crypto/ec/ecp_nistp521.c index 08b32787293b..31a97d793742 100644 --- a/crypto/ec/ecp_nistp521.c +++ b/crypto/ec/ecp_nistp521.c @@ -1,7 +1,7 @@ /* - * Copyright 2011-2020 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2011-2021 The OpenSSL Project Authors. All Rights Reserved. * - * Licensed under the OpenSSL license (the "License"). You may not use + * 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 @@ -24,6 +24,12 @@ */ /* + * ECDSA low level APIs are deprecated for public use, but still ok for + * internal use. + */ +#include "internal/deprecated.h" + +/* * A 64-bit implementation of the NIST P-521 elliptic curve point multiplication * * OpenSSL integration was taken from Emilia Kasper's work in ecp_nistp224.c. @@ -32,27 +38,22 @@ */ #include <openssl/e_os2.h> -#ifdef OPENSSL_NO_EC_NISTP_64_GCC_128 -NON_EMPTY_TRANSLATION_UNIT -#else -# include <string.h> -# include <openssl/err.h> -# include "ec_local.h" +#include <string.h> +#include <openssl/err.h> +#include "ec_local.h" -# 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 "Your compiler doesn't appear to support 128-bit integer types" -# endif +#include "internal/numbers.h" + +#ifndef INT128_MAX +# error "Your compiler doesn't appear to support 128-bit integer types" +#endif typedef uint8_t u8; typedef uint64_t u64; /* - * The underlying field. P521 operates over GF(2^521-1). We can serialise an + * The underlying field. P521 operates over GF(2^521-1). We can serialize an * element of this field into 66 bytes where the most significant byte * contains only a single bit. We call this an felem_bytearray. */ @@ -125,7 +126,7 @@ static const felem_bytearray nistp521_curve_params[5] = { * A field element with 64-bit limbs is an 'felem'. One with 128-bit limbs is a * 'largefelem' */ -# define NLIMBS 9 +#define NLIMBS 9 typedef uint64_t limb; typedef limb limb_aX __attribute((__aligned__(1))); @@ -153,7 +154,7 @@ static void bin66_to_felem(felem out, const u8 in[66]) } /* - * felem_to_bin66 takes an felem and serialises into a little endian, 66 byte + * felem_to_bin66 takes an felem and serializes into a little endian, 66 byte * array. This assumes that the CPU is little-endian. */ static void felem_to_bin66(u8 out[66], const felem in) @@ -177,12 +178,12 @@ static int BN_to_felem(felem out, const BIGNUM *bn) int num_bytes; if (BN_is_negative(bn)) { - ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); + ERR_raise(ERR_LIB_EC, EC_R_BIGNUM_OUT_OF_RANGE); return 0; } num_bytes = BN_bn2lebinpad(bn, b_out, sizeof(b_out)); if (num_bytes < 0) { - ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE); + ERR_raise(ERR_LIB_EC, EC_R_BIGNUM_OUT_OF_RANGE); return 0; } bin66_to_felem(out, b_out); @@ -400,7 +401,7 @@ static void felem_diff128(largefelem out, const largefelem in) * On exit: * out[i] < 17 * max(in[i]) * max(in[i]) */ -static void felem_square(largefelem out, const felem in) +static void felem_square_ref(largefelem out, const felem in) { felem inx2, inx4; felem_scalar(inx2, in, 2); @@ -484,7 +485,7 @@ static void felem_square(largefelem out, const felem in) * On exit: * out[i] < 17 * max(in1[i]) * max(in2[i]) */ -static void felem_mul(largefelem out, const felem in1, const felem in2) +static void felem_mul_ref(largefelem out, const felem in1, const felem in2) { felem in2x2; felem_scalar(in2x2, in2, 2); @@ -674,6 +675,57 @@ static void felem_reduce(felem out, const largefelem in) */ } +#if defined(ECP_NISTP521_ASM) +void felem_square_wrapper(largefelem out, const felem in); +void felem_mul_wrapper(largefelem out, const felem in1, const felem in2); + +static void (*felem_square_p)(largefelem out, const felem in) = + felem_square_wrapper; +static void (*felem_mul_p)(largefelem out, const felem in1, const felem in2) = + felem_mul_wrapper; + +void p521_felem_square(largefelem out, const felem in); +void p521_felem_mul(largefelem out, const felem in1, const felem in2); + +# if defined(_ARCH_PPC64) +# include "crypto/ppc_arch.h" +# endif + +void felem_select(void) +{ +# if defined(_ARCH_PPC64) + if ((OPENSSL_ppccap_P & PPC_MADD300) && (OPENSSL_ppccap_P & PPC_ALTIVEC)) { + felem_square_p = p521_felem_square; + felem_mul_p = p521_felem_mul; + + return; + } +# endif + + /* Default */ + felem_square_p = felem_square_ref; + felem_mul_p = felem_mul_ref; +} + +void felem_square_wrapper(largefelem out, const felem in) +{ + felem_select(); + felem_square_p(out, in); +} + +void felem_mul_wrapper(largefelem out, const felem in1, const felem in2) +{ + felem_select(); + felem_mul_p(out, in1, in2); +} + +# define felem_square felem_square_p +# define felem_mul felem_mul_p +#else +# define felem_square felem_square_ref +# define felem_mul felem_mul_ref +#endif + static void felem_square_reduce(felem out, const felem in) { largefelem tmp; @@ -1266,8 +1318,8 @@ static void point_add(felem x3, felem y3, felem z3, * This is obviously not constant-time but it will almost-never happen * for ECDH / ECDSA. The case where it can happen is during scalar-mult * where the intermediate value gets very close to the group order. - * Since |ec_GFp_nistp_recode_scalar_bits| produces signed digits for - * the scalar, it's possible for the intermediate value to be a small + * Since |ossl_ec_GFp_nistp_recode_scalar_bits| produces signed digits + * for the scalar, it's possible for the intermediate value to be a small * negative multiple of the base point, and for the final signed digit * to be the same value. We believe that this only occurs for the scalar * 1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff @@ -1584,7 +1636,7 @@ static void batch_mul(felem x_out, felem y_out, felem z_out, bits |= get_bit(scalars[num], i + 1) << 2; bits |= get_bit(scalars[num], i) << 1; bits |= get_bit(scalars[num], i - 1); - ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits); + ossl_ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits); /* * select the point to add or subtract, in constant time @@ -1622,54 +1674,55 @@ const EC_METHOD *EC_GFp_nistp521_method(void) static const EC_METHOD ret = { EC_FLAGS_DEFAULT_OCT, NID_X9_62_prime_field, - ec_GFp_nistp521_group_init, - ec_GFp_simple_group_finish, - ec_GFp_simple_group_clear_finish, - ec_GFp_nist_group_copy, - ec_GFp_nistp521_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, - ec_GFp_simple_point_clear_finish, - ec_GFp_simple_point_copy, - ec_GFp_simple_point_set_to_infinity, - ec_GFp_simple_set_Jprojective_coordinates_GFp, - ec_GFp_simple_get_Jprojective_coordinates_GFp, - ec_GFp_simple_point_set_affine_coordinates, - ec_GFp_nistp521_point_get_affine_coordinates, + ossl_ec_GFp_nistp521_group_init, + ossl_ec_GFp_simple_group_finish, + ossl_ec_GFp_simple_group_clear_finish, + ossl_ec_GFp_nist_group_copy, + ossl_ec_GFp_nistp521_group_set_curve, + ossl_ec_GFp_simple_group_get_curve, + ossl_ec_GFp_simple_group_get_degree, + ossl_ec_group_simple_order_bits, + ossl_ec_GFp_simple_group_check_discriminant, + ossl_ec_GFp_simple_point_init, + ossl_ec_GFp_simple_point_finish, + ossl_ec_GFp_simple_point_clear_finish, + ossl_ec_GFp_simple_point_copy, + ossl_ec_GFp_simple_point_set_to_infinity, + ossl_ec_GFp_simple_point_set_affine_coordinates, + ossl_ec_GFp_nistp521_point_get_affine_coordinates, 0 /* point_set_compressed_coordinates */ , 0 /* point2oct */ , 0 /* oct2point */ , - ec_GFp_simple_add, - ec_GFp_simple_dbl, - ec_GFp_simple_invert, - ec_GFp_simple_is_at_infinity, - ec_GFp_simple_is_on_curve, - ec_GFp_simple_cmp, - ec_GFp_simple_make_affine, - ec_GFp_simple_points_make_affine, - ec_GFp_nistp521_points_mul, - ec_GFp_nistp521_precompute_mult, - ec_GFp_nistp521_have_precompute_mult, - ec_GFp_nist_field_mul, - ec_GFp_nist_field_sqr, + ossl_ec_GFp_simple_add, + ossl_ec_GFp_simple_dbl, + ossl_ec_GFp_simple_invert, + ossl_ec_GFp_simple_is_at_infinity, + ossl_ec_GFp_simple_is_on_curve, + ossl_ec_GFp_simple_cmp, + ossl_ec_GFp_simple_make_affine, + ossl_ec_GFp_simple_points_make_affine, + ossl_ec_GFp_nistp521_points_mul, + ossl_ec_GFp_nistp521_precompute_mult, + ossl_ec_GFp_nistp521_have_precompute_mult, + ossl_ec_GFp_nist_field_mul, + ossl_ec_GFp_nist_field_sqr, 0 /* field_div */ , - ec_GFp_simple_field_inv, + ossl_ec_GFp_simple_field_inv, 0 /* field_encode */ , 0 /* field_decode */ , 0, /* field_set_to_one */ - ec_key_simple_priv2oct, - ec_key_simple_oct2priv, + ossl_ec_key_simple_priv2oct, + ossl_ec_key_simple_oct2priv, 0, /* set private */ - ec_key_simple_generate_key, - ec_key_simple_check_key, - ec_key_simple_generate_public_key, + ossl_ec_key_simple_generate_key, + ossl_ec_key_simple_check_key, + ossl_ec_key_simple_generate_public_key, 0, /* keycopy */ 0, /* keyfinish */ - ecdh_simple_compute_key, + ossl_ecdh_simple_compute_key, + ossl_ecdsa_simple_sign_setup, + ossl_ecdsa_simple_sign_sig, + ossl_ecdsa_simple_verify_sig, 0, /* field_inverse_mod_ord */ 0, /* blind_coordinates */ 0, /* ladder_pre */ @@ -1690,7 +1743,7 @@ static NISTP521_PRE_COMP *nistp521_pre_comp_new(void) NISTP521_PRE_COMP *ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) { - ECerr(EC_F_NISTP521_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); return ret; } @@ -1698,7 +1751,7 @@ static NISTP521_PRE_COMP *nistp521_pre_comp_new(void) ret->lock = CRYPTO_THREAD_lock_new(); if (ret->lock == NULL) { - ECerr(EC_F_NISTP521_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); OPENSSL_free(ret); return NULL; } @@ -1721,7 +1774,7 @@ void EC_nistp521_pre_comp_free(NISTP521_PRE_COMP *p) return; CRYPTO_DOWN_REF(&p->references, &i, p->lock); - REF_PRINT_COUNT("EC_nistp521", x); + REF_PRINT_COUNT("EC_nistp521", p); if (i > 0) return; REF_ASSERT_ISNT(i < 0); @@ -1735,25 +1788,29 @@ void EC_nistp521_pre_comp_free(NISTP521_PRE_COMP *p) * OPENSSL EC_METHOD FUNCTIONS */ -int ec_GFp_nistp521_group_init(EC_GROUP *group) +int ossl_ec_GFp_nistp521_group_init(EC_GROUP *group) { int ret; - ret = ec_GFp_simple_group_init(group); + ret = ossl_ec_GFp_simple_group_init(group); group->a_is_minus3 = 1; return ret; } -int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p, - const BIGNUM *a, const BIGNUM *b, - BN_CTX *ctx) +int ossl_ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p, + const BIGNUM *a, const BIGNUM *b, + BN_CTX *ctx) { int ret = 0; - BN_CTX *new_ctx = NULL; BIGNUM *curve_p, *curve_a, *curve_b; +#ifndef FIPS_MODULE + 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); curve_p = BN_CTX_get(ctx); curve_a = BN_CTX_get(ctx); @@ -1764,15 +1821,16 @@ int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p, BN_bin2bn(nistp521_curve_params[1], sizeof(felem_bytearray), curve_a); BN_bin2bn(nistp521_curve_params[2], sizeof(felem_bytearray), curve_b); if ((BN_cmp(curve_p, p)) || (BN_cmp(curve_a, a)) || (BN_cmp(curve_b, b))) { - ECerr(EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE, - EC_R_WRONG_CURVE_PARAMETERS); + ERR_raise(ERR_LIB_EC, EC_R_WRONG_CURVE_PARAMETERS); goto err; } group->field_mod_func = BN_nist_mod_521; - ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); + ret = ossl_ec_GFp_simple_group_set_curve(group, p, a, b, ctx); err: BN_CTX_end(ctx); +#ifndef FIPS_MODULE BN_CTX_free(new_ctx); +#endif return ret; } @@ -1780,17 +1838,16 @@ int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p, * Takes the Jacobian coordinates (X, Y, Z) of a point and returns (X', Y') = * (X/Z^2, Y/Z^3) */ -int ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group, - const EC_POINT *point, - BIGNUM *x, BIGNUM *y, - BN_CTX *ctx) +int ossl_ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group, + const EC_POINT *point, + BIGNUM *x, BIGNUM *y, + BN_CTX *ctx) { felem z1, z2, x_in, y_in, x_out, y_out; largefelem tmp; if (EC_POINT_is_at_infinity(group, point)) { - ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES, - EC_R_POINT_AT_INFINITY); + ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY); return 0; } if ((!BN_to_felem(x_in, point->X)) || (!BN_to_felem(y_in, point->Y)) || @@ -1804,8 +1861,7 @@ int ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group, felem_contract(x_out, x_in); if (x != NULL) { if (!felem_to_BN(x, x_out)) { - ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES, - ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); return 0; } } @@ -1816,8 +1872,7 @@ int ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group, felem_contract(y_out, y_in); if (y != NULL) { if (!felem_to_BN(y, y_out)) { - ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES, - ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); return 0; } } @@ -1832,36 +1887,36 @@ static void make_points_affine(size_t num, felem points[][3], * Runs in constant time, unless an input is the point at infinity (which * normally shouldn't happen). */ - ec_GFp_nistp_points_make_affine_internal(num, - points, - sizeof(felem), - tmp_felems, - (void (*)(void *))felem_one, - felem_is_zero_int, - (void (*)(void *, const void *)) - felem_assign, - (void (*)(void *, const void *)) - felem_square_reduce, (void (*) - (void *, - const void - *, - const void - *)) - felem_mul_reduce, - (void (*)(void *, const void *)) - felem_inv, - (void (*)(void *, const void *)) - felem_contract); + ossl_ec_GFp_nistp_points_make_affine_internal(num, + points, + sizeof(felem), + tmp_felems, + (void (*)(void *))felem_one, + felem_is_zero_int, + (void (*)(void *, const void *)) + felem_assign, + (void (*)(void *, const void *)) + felem_square_reduce, (void (*) + (void *, + const void + *, + const void + *)) + felem_mul_reduce, + (void (*)(void *, const void *)) + felem_inv, + (void (*)(void *, const void *)) + felem_contract); } /* * Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL * values Result is stored in r (r can equal one of the inputs). */ -int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, - const BIGNUM *scalar, size_t num, - const EC_POINT *points[], - const BIGNUM *scalars[], BN_CTX *ctx) +int ossl_ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, size_t num, + const EC_POINT *points[], + const BIGNUM *scalars[], BN_CTX *ctx) { int ret = 0; int j; @@ -1905,12 +1960,12 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, if (!felem_to_BN(x, g_pre_comp[1][0]) || !felem_to_BN(y, g_pre_comp[1][1]) || !felem_to_BN(z, g_pre_comp[1][2])) { - ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } - if (!EC_POINT_set_Jprojective_coordinates_GFp(group, - generator, x, y, z, - ctx)) + if (!ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(group, + generator, + x, y, z, ctx)) goto err; if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) /* precomputation matches generator */ @@ -1938,7 +1993,7 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, OPENSSL_malloc(sizeof(*tmp_felems) * (num_points * 17 + 1)); if ((secrets == NULL) || (pre_comp == NULL) || (mixed && (tmp_felems == NULL))) { - ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_MALLOC_FAILURE); + ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); goto err; } @@ -1968,7 +2023,7 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, * constant-timeness */ if (!BN_nnmod(tmp_scalar, p_scalar, group->order, ctx)) { - ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } num_bytes = BN_bn2lebinpad(tmp_scalar, @@ -1978,7 +2033,7 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, secrets[i], sizeof(secrets[i])); } if (num_bytes < 0) { - ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } /* precompute multiples */ @@ -2020,7 +2075,7 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, * constant-timeness */ if (!BN_nnmod(tmp_scalar, scalar, group->order, ctx)) { - ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } num_bytes = BN_bn2lebinpad(tmp_scalar, g_secret, sizeof(g_secret)); @@ -2045,10 +2100,11 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, felem_contract(z_in, z_out); if ((!felem_to_BN(x, x_in)) || (!felem_to_BN(y, y_in)) || (!felem_to_BN(z, z_in))) { - ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB); + ERR_raise(ERR_LIB_EC, ERR_R_BN_LIB); goto err; } - ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx); + ret = ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(group, r, x, y, z, + ctx); err: BN_CTX_end(ctx); @@ -2059,21 +2115,28 @@ int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r, return ret; } -int ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx) +int ossl_ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx) { int ret = 0; NISTP521_PRE_COMP *pre = NULL; int i, j; - BN_CTX *new_ctx = NULL; BIGNUM *x, *y; EC_POINT *generator = NULL; felem tmp_felems[16]; +#ifndef FIPS_MODULE + BN_CTX *new_ctx = NULL; +#endif /* throw away old precomputation */ EC_pre_comp_free(group); + +#ifndef FIPS_MODULE 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); x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); @@ -2161,14 +2224,14 @@ int ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx) err: BN_CTX_end(ctx); EC_POINT_free(generator); +#ifndef FIPS_MODULE BN_CTX_free(new_ctx); +#endif EC_nistp521_pre_comp_free(pre); return ret; } -int ec_GFp_nistp521_have_precompute_mult(const EC_GROUP *group) +int ossl_ec_GFp_nistp521_have_precompute_mult(const EC_GROUP *group) { return HAVEPRECOMP(group, nistp521); } - -#endif |