X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fec%2Fec_lcl.h;h=a523ab64228d7fc61127c34fe4718dec4dd95833;hp=2cef3bced4ad86923cc48638a12d434cf599c886;hb=25f2138b0ab54a65ba713c093ca3734d88f7cb51;hpb=aa6bb1352b1026b20a23b49da4efdcf171926eb0 diff --git a/crypto/ec/ec_lcl.h b/crypto/ec/ec_lcl.h index 2cef3bced4..a523ab6422 100644 --- a/crypto/ec/ec_lcl.h +++ b/crypto/ec/ec_lcl.h @@ -1,33 +1,20 @@ /* - * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright (c) 2002, Oracle and/or its affiliates. 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 */ -/* ==================================================================== - * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. - * - * Portions of the attached software ("Contribution") are developed by - * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. - * - * The Contribution is licensed pursuant to the OpenSSL open source - * license provided above. - * - * The elliptic curve binary polynomial software is originally written by - * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories. - * - */ - #include #include #include #include - -#include "e_os.h" +#include "internal/refcount.h" +#include "crypto/ec.h" #if defined(__SUNPRO_C) # if __SUNPRO_C >= 0x520 @@ -62,8 +49,7 @@ struct ec_method_st { void (*group_finish) (EC_GROUP *); void (*group_clear_finish) (EC_GROUP *); int (*group_copy) (EC_GROUP *, const EC_GROUP *); - /* used by EC_GROUP_set_curve_GFp, EC_GROUP_get_curve_GFp, */ - /* EC_GROUP_set_curve_GF2m, and EC_GROUP_get_curve_GF2m: */ + /* used by EC_GROUP_set_curve, EC_GROUP_get_curve: */ int (*group_set_curve) (EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *); int (*group_get_curve) (const EC_GROUP *, BIGNUM *p, BIGNUM *a, BIGNUM *b, @@ -85,9 +71,9 @@ struct ec_method_st { * used by EC_POINT_set_to_infinity, * EC_POINT_set_Jprojective_coordinates_GFp, * EC_POINT_get_Jprojective_coordinates_GFp, - * EC_POINT_set_affine_coordinates_GFp, ..._GF2m, - * EC_POINT_get_affine_coordinates_GFp, ..._GF2m, - * EC_POINT_set_compressed_coordinates_GFp, ..._GF2m: + * EC_POINT_set_affine_coordinates, + * EC_POINT_get_affine_coordinates, + * EC_POINT_set_compressed_coordinates: */ int (*point_set_to_infinity) (const EC_GROUP *, EC_POINT *); int (*point_set_Jprojective_coordinates_GFp) (const EC_GROUP *, @@ -133,6 +119,23 @@ struct ec_method_st { * EC_POINT_have_precompute_mult (default implementations are used if the * 'mul' pointer is 0): */ + /*- + * mul() calculates the value + * + * r := generator * scalar + * + points[0] * scalars[0] + * + ... + * + points[num-1] * scalars[num-1]. + * + * For a fixed point multiplication (scalar != NULL, num == 0) + * or a variable point multiplication (scalar == NULL, num == 1), + * mul() must use a constant time algorithm: in both cases callers + * should provide an input scalar (either scalar or scalars[0]) + * in the range [0, ec_group_order); for robustness, implementers + * should handle the case when the scalar has not been reduced, but + * may treat it as an unusual input, without any constant-timeness + * guarantee. + */ int (*mul) (const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *); @@ -150,6 +153,13 @@ struct ec_method_st { int (*field_sqr) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); int (*field_div) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *); + /*- + * 'field_inv' computes the multiplicative inverse of a in the field, + * storing the result in r. + * + * If 'a' is zero (or equivalent), you'll get an EC_R_CANNOT_INVERT error. + */ + int (*field_inv) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); /* e.g. to Montgomery */ int (*field_encode) (const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); @@ -159,7 +169,7 @@ struct ec_method_st { int (*field_set_to_one) (const EC_GROUP *, BIGNUM *r, BN_CTX *); /* private key operations */ size_t (*priv2oct)(const EC_KEY *eckey, unsigned char *buf, size_t len); - int (*oct2priv)(EC_KEY *eckey, unsigned char *buf, size_t len); + int (*oct2priv)(EC_KEY *eckey, const unsigned char *buf, size_t len); int (*set_private)(EC_KEY *eckey, const BIGNUM *priv_key); int (*keygen)(EC_KEY *eckey); int (*keycheck)(const EC_KEY *eckey); @@ -169,7 +179,28 @@ struct ec_method_st { /* custom ECDH operation */ int (*ecdh_compute_key)(unsigned char **pout, size_t *poutlen, const EC_POINT *pub_key, const EC_KEY *ecdh); -} /* EC_METHOD */ ; + /* custom ECDSA */ + int (*ecdsa_sign_setup)(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinvp, + BIGNUM **rp); + ECDSA_SIG *(*ecdsa_sign_sig)(const unsigned char *dgst, int dgstlen, + const BIGNUM *kinv, const BIGNUM *r, + EC_KEY *eckey); + int (*ecdsa_verify_sig)(const unsigned char *dgst, int dgstlen, + const ECDSA_SIG *sig, EC_KEY *eckey); + /* Inverse modulo order */ + int (*field_inverse_mod_ord)(const EC_GROUP *, BIGNUM *r, + const BIGNUM *x, BN_CTX *); + int (*blind_coordinates)(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx); + int (*ladder_pre)(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx); + int (*ladder_step)(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx); + int (*ladder_post)(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx); +}; /* * Types and functions to manipulate pre-computed values. @@ -228,11 +259,16 @@ struct ec_group_st { /* data for ECDSA inverse */ BN_MONT_CTX *mont_data; - /* precomputed values for speed. */ + /* + * Precomputed values for speed. The PCT_xxx names match the + * pre_comp.xxx union names; see the SETPRECOMP and HAVEPRECOMP + * macros, below. + */ enum { - pct_none, - pct_nistp224, pct_nistp256, pct_nistp521, pct_nistz256, - pct_ec } pre_comp_type; + PCT_none, + PCT_nistp224, PCT_nistp256, PCT_nistp521, PCT_nistz256, + PCT_ec + } pre_comp_type; union { NISTP224_PRE_COMP *nistp224; NISTP256_PRE_COMP *nistp256; @@ -240,12 +276,14 @@ struct ec_group_st { NISTZ256_PRE_COMP *nistz256; EC_PRE_COMP *ec; } pre_comp; -} /* EC_GROUP */ ; + + OPENSSL_CTX *libctx; +}; #define SETPRECOMP(g, type, pre) \ - g->pre_comp_type = pct_##type, g->pre_comp.type = pre + g->pre_comp_type = PCT_##type, g->pre_comp.type = pre #define HAVEPRECOMP(g, type) \ - g->pre_comp_type == pct_##type && g->pre_comp.type != NULL + g->pre_comp_type == PCT_##type && g->pre_comp.type != NULL struct ec_key_st { const EC_KEY_METHOD *meth; @@ -254,22 +292,21 @@ struct ec_key_st { EC_GROUP *group; EC_POINT *pub_key; BIGNUM *priv_key; - /* - * Arbitrary extra data. - * For example in X25519 this contains the raw private key in a 32 byte - * buffer. - */ - void *custom_data; unsigned int enc_flag; point_conversion_form_t conv_form; - int references; + CRYPTO_REF_COUNT references; int flags; +#ifndef FIPS_MODE CRYPTO_EX_DATA ex_data; +#endif CRYPTO_RWLOCK *lock; -} /* EC_KEY */ ; + OPENSSL_CTX *libctx; +}; struct ec_point_st { const EC_METHOD *meth; + /* NID for the curve if known */ + int curve_name; /* * All members except 'meth' are handled by the method functions, even if * they appear generic @@ -280,12 +317,16 @@ struct ec_point_st { * Z) represents (X/Z^2, Y/Z^3) if Z != 0 */ int Z_is_one; /* enable optimized point arithmetics for * special case */ - /* - * Arbitrary extra data. - * For example in X25519 this contains the public key in a 32 byte buffer. - */ - void *custom_data; -} /* EC_POINT */ ; +}; + +static ossl_inline int ec_point_is_compat(const EC_POINT *point, + const EC_GROUP *group) +{ + return group->meth == point->meth + && (group->curve_name == 0 + || point->curve_name == 0 + || group->curve_name == point->curve_name); +} NISTP224_PRE_COMP *EC_nistp224_pre_comp_dup(NISTP224_PRE_COMP *); NISTP256_PRE_COMP *EC_nistp256_pre_comp_dup(NISTP256_PRE_COMP *); @@ -365,6 +406,19 @@ int ec_GFp_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *); int ec_GFp_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); +int ec_GFp_simple_field_inv(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); +int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p, + BN_CTX *ctx); +int ec_GFp_simple_ladder_pre(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx); +int ec_GFp_simple_ladder_step(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx); +int ec_GFp_simple_ladder_post(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx); /* method functions in ecp_mont.c */ int ec_GFp_mont_group_init(EC_GROUP *); @@ -377,6 +431,8 @@ int ec_GFp_mont_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *); int ec_GFp_mont_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); +int ec_GFp_mont_field_inv(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, + BN_CTX *); int ec_GFp_mont_field_encode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); int ec_GFp_mont_field_decode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, @@ -442,14 +498,6 @@ int ec_GF2m_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, int ec_GF2m_simple_field_div(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *); -/* method functions in ec2_mult.c */ -int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, - const BIGNUM *scalar, size_t num, - const EC_POINT *points[], const BIGNUM *scalars[], - BN_CTX *); -int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx); -int ec_GF2m_have_precompute_mult(const EC_GROUP *group); - #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 /* method functions in ecp_nistp224.c */ int ec_GFp_nistp224_group_init(EC_GROUP *group); @@ -540,7 +588,6 @@ void ec_GFp_nistp_points_make_affine_internal(size_t num, void *point_array, void ec_GFp_nistp_recode_scalar_bits(unsigned char *sign, unsigned char *digit, unsigned char in); #endif -int ec_precompute_mont_data(EC_GROUP *); int ec_group_simple_order_bits(const EC_GROUP *group); #ifdef ECP_NISTZ256_ASM @@ -550,14 +597,21 @@ int ec_group_simple_order_bits(const EC_GROUP *group); */ const EC_METHOD *EC_GFp_nistz256_method(void); #endif +#ifdef S390X_EC_ASM +const EC_METHOD *EC_GFp_s390x_nistp256_method(void); +const EC_METHOD *EC_GFp_s390x_nistp384_method(void); +const EC_METHOD *EC_GFp_s390x_nistp521_method(void); +#endif size_t ec_key_simple_priv2oct(const EC_KEY *eckey, unsigned char *buf, size_t len); -int ec_key_simple_oct2priv(EC_KEY *eckey, unsigned char *buf, size_t len); +int ec_key_simple_oct2priv(EC_KEY *eckey, const unsigned char *buf, size_t len); int ec_key_simple_generate_key(EC_KEY *eckey); int ec_key_simple_generate_public_key(EC_KEY *eckey); int ec_key_simple_check_key(const EC_KEY *eckey); +int ec_curve_nid_from_params(const EC_GROUP *group, BN_CTX *ctx); + /* EC_METHOD definitions */ struct ec_key_method_st { @@ -585,10 +639,12 @@ struct ec_key_method_st { const unsigned char *sigbuf, int sig_len, EC_KEY *eckey); int (*verify_sig)(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey); -} /* EC_KEY_METHOD */ ; +}; #define EC_KEY_METHOD_DYNAMIC 1 +EC_KEY *ec_key_new_method_int(OPENSSL_CTX *libctx, ENGINE *engine); + int ossl_ec_key_gen(EC_KEY *eckey); int ossl_ecdh_compute_key(unsigned char **pout, size_t *poutlen, const EC_POINT *pub_key, const EC_KEY *ecdh); @@ -612,10 +668,96 @@ int ossl_ecdsa_verify(int type, const unsigned char *dgst, int dgst_len, const unsigned char *sigbuf, int sig_len, EC_KEY *eckey); int ossl_ecdsa_verify_sig(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey); - -const EC_METHOD *ec_x25519_meth(void); +int ecdsa_simple_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, + BIGNUM **rp); +ECDSA_SIG *ecdsa_simple_sign_sig(const unsigned char *dgst, int dgst_len, + const BIGNUM *in_kinv, const BIGNUM *in_r, + EC_KEY *eckey); +int ecdsa_simple_verify_sig(const unsigned char *dgst, int dgst_len, + const ECDSA_SIG *sig, EC_KEY *eckey); + +int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len, + const uint8_t public_key[32], const uint8_t private_key[32]); +int ED25519_verify(const uint8_t *message, size_t message_len, + const uint8_t signature[64], const uint8_t public_key[32]); +void ED25519_public_from_private(uint8_t out_public_key[32], + const uint8_t private_key[32]); int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32], const uint8_t peer_public_value[32]); void X25519_public_from_private(uint8_t out_public_value[32], const uint8_t private_key[32]); + +/*- + * This functions computes a single point multiplication over the EC group, + * using, at a high level, a Montgomery ladder with conditional swaps, with + * various timing attack defenses. + * + * It performs either a fixed point multiplication + * (scalar * generator) + * when point is NULL, or a variable point multiplication + * (scalar * point) + * when point is not NULL. + * + * `scalar` cannot be NULL and should be in the range [0,n) otherwise all + * constant time bets are off (where n is the cardinality of the EC group). + * + * This function expects `group->order` and `group->cardinality` to be well + * defined and non-zero: it fails with an error code otherwise. + * + * NB: This says nothing about the constant-timeness of the ladder step + * implementation (i.e., the default implementation is based on EC_POINT_add and + * EC_POINT_dbl, which of course are not constant time themselves) or the + * underlying multiprecision arithmetic. + * + * The product is stored in `r`. + * + * This is an internal function: callers are in charge of ensuring that the + * input parameters `group`, `r`, `scalar` and `ctx` are not NULL. + * + * Returns 1 on success, 0 otherwise. + */ +int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r, + const BIGNUM *scalar, const EC_POINT *point, + BN_CTX *ctx); + +int ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx); + +static ossl_inline int ec_point_ladder_pre(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx) +{ + if (group->meth->ladder_pre != NULL) + return group->meth->ladder_pre(group, r, s, p, ctx); + + if (!EC_POINT_copy(s, p) + || !EC_POINT_dbl(group, r, s, ctx)) + return 0; + + return 1; +} + +static ossl_inline int ec_point_ladder_step(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx) +{ + if (group->meth->ladder_step != NULL) + return group->meth->ladder_step(group, r, s, p, ctx); + + if (!EC_POINT_add(group, s, r, s, ctx) + || !EC_POINT_dbl(group, r, r, ctx)) + return 0; + + return 1; + +} + +static ossl_inline int ec_point_ladder_post(const EC_GROUP *group, + EC_POINT *r, EC_POINT *s, + EC_POINT *p, BN_CTX *ctx) +{ + if (group->meth->ladder_post != NULL) + return group->meth->ladder_post(group, r, s, p, ctx); + + return 1; +}