diff mbox series

[RFC,2/3] crypto: ecc - Implement and use ecc_curve_get_nbytes to get curve's nbytes

Message ID 20240612151900.895156-3-stefanb@linux.ibm.com (mailing list archive)
State New
Headers show
Series Introduce ecc_digits_to_bytes and clean up ecdh.c | expand

Commit Message

Stefan Berger June 12, 2024, 3:18 p.m. UTC
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(-)
diff mbox series

Patch

diff --git a/crypto/ecc.c b/crypto/ecc.c
index 1cdb5df3aa5d..7cc82c9eacc8 100644
--- a/crypto/ecc.c
+++ b/crypto/ecc.c
@@ -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;
diff --git a/crypto/ecdh.c b/crypto/ecdh.c
index 72cfd1590156..55d140772da0 100644
--- a/crypto/ecdh.c
+++ b/crypto/ecdh.c
@@ -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, &params) < 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)
diff --git a/include/crypto/internal/ecc.h b/include/crypto/internal/ecc.h
index b18297aaff08..d6e51e45fb3d 100644
--- a/include/crypto/internal/ecc.h
+++ b/include/crypto/internal/ecc.h
@@ -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
  *