2024-06-12 15:20:08

by Stefan Berger

[permalink] [raw]
Subject: [RFC PATCH 3/3] crypto: ecdh - Use functions to copy digits from and to byte arrays

In ecdh_compute_value the public_key and shared_secret variables are not
arrays of digits (u64 *) but byte buffers that are either copied into from
the scatterlist req->src or copied out of to the scatterlist req->dst.
Therefore, convert these variables to 'u8 *' and modify ecc_make_pub_key
and crypto_ecdh_shared_secret to use ecc_digits_from_bytes to convert byte
arrays to digits and ecc_digits_to_bytes to convert digits to byte arrays.
This also prepares the code for usage with curves that do not use all
bytes in the most significant digit, such as NIST P521, since these two
functions can handle conversions between digits and byte arrays related to
such curves.

Signed-off-by: Stefan Berger <[email protected]>
---
crypto/ecc.c | 21 ++++++++++-----------
crypto/ecdh.c | 9 +++++----
include/crypto/internal/ecc.h | 15 +++++++++------
3 files changed, 24 insertions(+), 21 deletions(-)

diff --git a/crypto/ecc.c b/crypto/ecc.c
index 7cc82c9eacc8..3ad2d8ae41b9 100644
--- a/crypto/ecc.c
+++ b/crypto/ecc.c
@@ -1584,7 +1584,8 @@ int ecc_gen_privkey(unsigned int curve_id, unsigned int ndigits,
EXPORT_SYMBOL(ecc_gen_privkey);

int ecc_make_pub_key(unsigned int curve_id, unsigned int ndigits,
- const u64 *private_key, u64 *public_key)
+ const u64 *private_key, u8 *public_key,
+ unsigned int nbytes)
{
int ret = 0;
struct ecc_point *pk;
@@ -1609,8 +1610,8 @@ int ecc_make_pub_key(unsigned int curve_id, unsigned int ndigits,
goto err_free_point;
}

- ecc_swap_digits(pk->x, public_key, ndigits);
- ecc_swap_digits(pk->y, &public_key[ndigits], ndigits);
+ ecc_digits_to_bytes(pk->x, ndigits, public_key, nbytes);
+ ecc_digits_to_bytes(pk->y, ndigits, &public_key[nbytes], nbytes);

err_free_point:
ecc_free_point(pk);
@@ -1680,13 +1681,12 @@ int ecc_is_pubkey_valid_full(const struct ecc_curve *curve,
EXPORT_SYMBOL(ecc_is_pubkey_valid_full);

int crypto_ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits,
- const u64 *private_key, const u64 *public_key,
- u64 *secret)
+ const u64 *private_key, const u8 *public_key,
+ unsigned int nbytes, u8 *secret)
{
int ret = 0;
struct ecc_point *product, *pk;
u64 rand_z[ECC_MAX_DIGITS];
- unsigned int nbytes;
const struct ecc_curve *curve = ecc_get_curve(curve_id);

if (!private_key || !public_key || ndigits > ARRAY_SIZE(rand_z)) {
@@ -1694,8 +1694,6 @@ int crypto_ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits,
goto out;
}

- nbytes = ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
-
get_random_bytes(rand_z, nbytes);

pk = ecc_alloc_point(ndigits);
@@ -1704,8 +1702,9 @@ int crypto_ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits,
goto out;
}

- ecc_swap_digits(public_key, pk->x, ndigits);
- ecc_swap_digits(&public_key[ndigits], pk->y, ndigits);
+ ecc_digits_from_bytes(public_key, nbytes, pk->x, ndigits);
+ ecc_digits_from_bytes(&public_key[nbytes], nbytes, pk->y, ndigits);
+
ret = ecc_is_pubkey_valid_partial(curve, pk);
if (ret)
goto err_alloc_product;
@@ -1723,7 +1722,7 @@ int crypto_ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits,
goto err_validity;
}

- ecc_swap_digits(product->x, secret, ndigits);
+ ecc_digits_to_bytes(product->x, ndigits, secret, nbytes);

err_validity:
memzero_explicit(rand_z, sizeof(rand_z));
diff --git a/crypto/ecdh.c b/crypto/ecdh.c
index 55d140772da0..dfb5fa1a50d2 100644
--- a/crypto/ecdh.c
+++ b/crypto/ecdh.c
@@ -60,8 +60,8 @@ static int ecdh_compute_value(struct kpp_request *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;
+ u8 *public_key;
+ u8 *shared_secret = NULL;
void *buf;
size_t copied, public_key_sz;
int ret = -ENOMEM;
@@ -94,12 +94,13 @@ static int ecdh_compute_value(struct kpp_request *req)

ret = crypto_ecdh_shared_secret(ctx->curve_id, ctx->ndigits,
ctx->private_key, public_key,
- shared_secret);
+ nbytes, shared_secret);

buf = shared_secret;
} else {
ret = ecc_make_pub_key(ctx->curve_id, ctx->ndigits,
- ctx->private_key, public_key);
+ ctx->private_key, public_key,
+ nbytes);
buf = public_key;
nbytes = public_key_sz;
}
diff --git a/include/crypto/internal/ecc.h b/include/crypto/internal/ecc.h
index d6e51e45fb3d..19265394be48 100644
--- a/include/crypto/internal/ecc.h
+++ b/include/crypto/internal/ecc.h
@@ -126,13 +126,15 @@ int ecc_gen_privkey(unsigned int curve_id, unsigned int ndigits,
* @curve_id: id representing the curve to use
* @ndigits: curve's number of digits
* @private_key: pregenerated private key for the given curve
- * @public_key: buffer for storing the generated public key
+ * @public_key: 2 * nbytes buffer for storing the generated public key
+ * @nbytes: size of one coordinate of the public key
*
* Returns 0 if the public key was generated successfully, a negative value
* if an error occurred.
*/
int ecc_make_pub_key(const unsigned int curve_id, unsigned int ndigits,
- const u64 *private_key, u64 *public_key);
+ const u64 *private_key, u8 *public_key,
+ unsigned int nbytes);

/**
* crypto_ecdh_shared_secret() - Compute a shared secret
@@ -140,8 +142,9 @@ int ecc_make_pub_key(const unsigned int curve_id, unsigned int ndigits,
* @curve_id: id representing the curve to use
* @ndigits: curve's number of digits
* @private_key: private key of part A
- * @public_key: public key of counterpart B
- * @secret: buffer for storing the calculated shared secret
+ * @public_key: 2 * nbytes buffer with public key of counterpart B
+ * @nbytes: size of one coordinate of the public key
+ * @secret: nbytes buffer for storing the calculated shared secret
*
* Note: It is recommended that you hash the result of crypto_ecdh_shared_secret
* before using it for symmetric encryption or HMAC.
@@ -150,8 +153,8 @@ int ecc_make_pub_key(const unsigned int curve_id, unsigned int ndigits,
* if an error occurred.
*/
int crypto_ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits,
- const u64 *private_key, const u64 *public_key,
- u64 *secret);
+ const u64 *private_key, const u8 *public_key,
+ unsigned int nbytes, u8 *secret);

/**
* ecc_is_pubkey_valid_partial() - Partial public key validation
--
2.43.0