2024-06-12 15:19:45

by Stefan Berger

[permalink] [raw]
Subject: [RFC PATCH 0/3] Introduce ecc_digits_to_bytes and clean up ecdh.c

This series introduces ecc_digits_to_bytes to convert an array of digits
to bytes and uses this function and ecc_digits_from_bytes in ecdh-related
code to convert between byte arrays and digits. Using these functions is
generally better than using ecc_swap_digits. The latter cannot be used with
curves like NIST P521 since it does not properly handle curves that do not
use all bytes in the most significant digit.

It also introduces ecc_curve_get_nbytes to get the number of bytes (nbytes)
a curve needs for its coordinates. It derives this number from the nbits
parameter of a curve. Using this function is also generally better than
deriving nbytes from ndigits, which does not work correctly vor NIST P521.

None of the converted functions have been used with NIST P521 but only
with NIST P192/256/384 so far, so they work fine as they are.

Due to concerns related to constant time operations when signing with EC
private keys I am not planning to add NIST P521 support to ecdh, so the
changes in this series are primarly 'code improvements' (-> RFC).

Stefan

Stefan Berger (3):
crypto: ecc - Implement ecc_digits_to_bytes to convert digits to byte
array
crypto: ecc - Implement and use ecc_curve_get_nbytes to get curve's
nbytes
crypto: ecdh - Use functions to copy digits from and to byte arrays

crypto/ecc.c | 47 ++++++++++++++++++++++++-----------
crypto/ecdh.c | 24 +++++++++++-------
include/crypto/internal/ecc.h | 37 ++++++++++++++++++++++-----
3 files changed, 79 insertions(+), 29 deletions(-)

--
2.43.0



2024-06-12 15:19:55

by Stefan Berger

[permalink] [raw]
Subject: [RFC PATCH 1/3] crypto: ecc - Implement ecc_digits_to_bytes to convert digits to byte array

Implement ecc_digits_to_bytes to convert an array of digits into an
nbytes-sized byte array. The first byte in the byte array holds the most
significant bits of the large integer.

Signed-off-by: Stefan Berger <[email protected]>
---
crypto/ecc.c | 22 ++++++++++++++++++++++
include/crypto/internal/ecc.h | 13 +++++++++++++
2 files changed, 35 insertions(+)

diff --git a/crypto/ecc.c b/crypto/ecc.c
index af698f8852fb..1cdb5df3aa5d 100644
--- a/crypto/ecc.c
+++ b/crypto/ecc.c
@@ -90,6 +90,28 @@ void ecc_digits_from_bytes(const u8 *in, unsigned int nbytes,
}
EXPORT_SYMBOL(ecc_digits_from_bytes);

+void ecc_digits_to_bytes(const u64 *in, unsigned int ndigits,
+ u8 *out, unsigned int nbytes)
+{
+ unsigned int o = nbytes & 7;
+ __be64 msd;
+ int i;
+
+ if (o) {
+ msd = cpu_to_be64(in[--ndigits]);
+ memcpy(out, (u8 *)&msd + sizeof(msd) - o, o);
+ out += o;
+ nbytes -= o;
+ }
+
+ for (i = ndigits - 1; i >= 0 && nbytes > 0; i--) {
+ put_unaligned_be64(in[i], out);
+ out += sizeof(u64);
+ nbytes -= sizeof(u64);
+ }
+}
+EXPORT_SYMBOL(ecc_digits_to_bytes);
+
static u64 *ecc_alloc_digits_space(unsigned int ndigits)
{
size_t len = ndigits * sizeof(u64);
diff --git a/include/crypto/internal/ecc.h b/include/crypto/internal/ecc.h
index 0717a53ae732..b18297aaff08 100644
--- a/include/crypto/internal/ecc.h
+++ b/include/crypto/internal/ecc.h
@@ -70,6 +70,19 @@ static inline void ecc_swap_digits(const void *in, u64 *out, unsigned int ndigit
void ecc_digits_from_bytes(const u8 *in, unsigned int nbytes,
u64 *out, unsigned int ndigits);

+/**
+ * ecc_digits_to_bytes() - Copy digits into a byte array of size nbytes
+ * @in: Input digits array
+ * @ndigits: Number of digits in input digits array
+ * @out: Output byte array
+ * @nbytes: Number of bytes to copy into byte array
+ *
+ * The first byte in the byte array will have the most significant bits of the
+ * large integer.
+ */
+void ecc_digits_to_bytes(const u64 *in, unsigned int ndigits,
+ u8 *out, unsigned int nbytes);
+
/**
* ecc_is_key_valid() - Validate a given ECDH private key
*
--
2.43.0