@@ -1522,10 +1522,8 @@ static int __ecc_is_key_valid(const struct ecc_curve *curve,
int ecc_is_key_valid(unsigned int curve_id, unsigned int ndigits,
const u64 *private_key, unsigned int private_key_len)
{
- int nbytes;
const struct ecc_curve *curve = ecc_get_curve(curve_id);
-
- nbytes = ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
+ unsigned int nbytes = ecc_curve_get_nbytes(curve);
if (private_key_len != nbytes)
return -EINVAL;
@@ -27,11 +27,13 @@ static int ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
unsigned int len)
{
struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
+ const struct ecc_curve *curve = ecc_get_curve(ctx->curve_id);
+ unsigned int nbytes = ecc_curve_get_nbytes(curve);
struct ecdh params;
int ret = 0;
if (crypto_ecdh_decode_key(buf, len, ¶ms) < 0 ||
- params.key_size > sizeof(u64) * ctx->ndigits)
+ params.key_size > nbytes)
return -EINVAL;
memset(ctx->private_key, 0, sizeof(ctx->private_key));
@@ -56,13 +58,14 @@ static int ecdh_compute_value(struct kpp_request *req)
{
struct crypto_kpp *tfm = crypto_kpp_reqtfm(req);
struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
+ const struct ecc_curve *curve = ecc_get_curve(ctx->curve_id);
+ unsigned int nbytes = ecc_curve_get_nbytes(curve);
u64 *public_key;
u64 *shared_secret = NULL;
void *buf;
- size_t copied, nbytes, public_key_sz;
+ size_t copied, public_key_sz;
int ret = -ENOMEM;
- nbytes = ctx->ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
/* Public part is a point thus it has both coordinates */
public_key_sz = 2 * nbytes;
@@ -123,9 +126,11 @@ static int ecdh_compute_value(struct kpp_request *req)
static unsigned int ecdh_max_size(struct crypto_kpp *tfm)
{
struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
+ const struct ecc_curve *curve = ecc_get_curve(ctx->curve_id);
+ unsigned int nbytes = ecc_curve_get_nbytes(curve);
- /* Public key is made of two coordinates, add one to the left shift */
- return ctx->ndigits << (ECC_DIGITS_TO_BYTES_SHIFT + 1);
+ /* Public key is made of two coordinates */
+ return nbytes * 2;
}
static int ecdh_nist_p192_init_tfm(struct crypto_kpp *tfm)
@@ -83,6 +83,15 @@ void ecc_digits_from_bytes(const u8 *in, unsigned int nbytes,
void ecc_digits_to_bytes(const u64 *in, unsigned int ndigits,
u8 *out, unsigned int nbytes);
+/*
+ * ecc_curve_get_nbytes() - Get the number of bytes the curve requires
+ * @curve: The curve
+ */
+static inline unsigned int ecc_curve_get_nbytes(const struct ecc_curve *curve)
+{
+ return DIV_ROUND_UP(curve->nbits, 8);
+}
+
/**
* ecc_is_key_valid() - Validate a given ECDH private key
*
Implement ecc_curve_get_nbytes to get a curve's number of bytes (nbytes) derived from the nbits field of a curve. This function should be used where nbytes is currently derived from ndigits since it gives a precise number for all curves including those that do not use all bytes in the most significant digit, such as NIST P521. Neither of the modified functions have so far been used with the NIST P521 curve. Signed-off-by: Stefan Berger <stefanb@linux.ibm.com> --- crypto/ecc.c | 4 +--- crypto/ecdh.c | 15 ++++++++++----- include/crypto/internal/ecc.h | 9 +++++++++ 3 files changed, 20 insertions(+), 8 deletions(-)