* [PATCH v2 01/14] crypto: ecdsa - Convert byte arrays with key coordinates to digits
2024-02-15 23:13 [PATCH v2 00/14] Add support for NIST P521 to ecdsa and ecdh Stefan Berger
@ 2024-02-15 23:14 ` Stefan Berger
2024-02-15 23:14 ` [PATCH v2 02/14] crypto: ecdsa - Adjust tests on length of key parameters Stefan Berger
` (13 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Stefan Berger @ 2024-02-15 23:14 UTC (permalink / raw)
To: keyrings, linux-crypto, herbert, davem
Cc: linux-kernel, saulo.alessandre, Stefan Berger
For NIST P192/256/384 the public key's x and y parameters could be copied
directly from a given array since both parameters filled 'ndigits' of
digits (a 'digit' is a u64). For support of NIST P521 the key parameters
first have to be copied into a temporary byte array with leading zeros
and can then be copied into the final digit array using ecc_swap_digits.
Implement ecc_digits_from_bytes to convert a byte array into an array of
digits and use this function in ecdsa_set_pub_key where an input byte array
needs to be converted into digits.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
crypto/ecdsa.c | 14 +++++++++-----
include/crypto/internal/ecc.h | 19 +++++++++++++++++++
2 files changed, 28 insertions(+), 5 deletions(-)
diff --git a/crypto/ecdsa.c b/crypto/ecdsa.c
index fbd76498aba8..ba8fb76fd165 100644
--- a/crypto/ecdsa.c
+++ b/crypto/ecdsa.c
@@ -222,9 +222,8 @@ static int ecdsa_ecc_ctx_reset(struct ecc_ctx *ctx)
static int ecdsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, unsigned int keylen)
{
struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);
+ unsigned int digitlen, ndigits;
const unsigned char *d = key;
- const u64 *digits = (const u64 *)&d[1];
- unsigned int ndigits;
int ret;
ret = ecdsa_ecc_ctx_reset(ctx);
@@ -238,12 +237,17 @@ static int ecdsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, unsig
return -EINVAL;
keylen--;
- ndigits = (keylen >> 1) / sizeof(u64);
+ digitlen = keylen >> 1;
+
+ ndigits = digitlen / sizeof(u64);
if (ndigits != ctx->curve->g.ndigits)
return -EINVAL;
- ecc_swap_digits(digits, ctx->pub_key.x, ndigits);
- ecc_swap_digits(&digits[ndigits], ctx->pub_key.y, ndigits);
+ d++;
+
+ ecc_digits_from_bytes(d, digitlen, ctx->pub_key.x, ndigits);
+ ecc_digits_from_bytes(&d[digitlen], digitlen, ctx->pub_key.y, ndigits);
+
ret = ecc_is_pubkey_valid_full(ctx->curve, &ctx->pub_key);
ctx->pub_key_set = ret == 0;
diff --git a/include/crypto/internal/ecc.h b/include/crypto/internal/ecc.h
index 4f6c1a68882f..bee3329af7de 100644
--- a/include/crypto/internal/ecc.h
+++ b/include/crypto/internal/ecc.h
@@ -56,6 +56,25 @@ static inline void ecc_swap_digits(const void *in, u64 *out, unsigned int ndigit
out[i] = get_unaligned_be64(&src[ndigits - 1 - i]);
}
+/**
+ * ecc_digits_from_bytes() - Create ndigits-sized digits array from byte array
+ * @in: Input byte array
+ * @nbytes Size of input byte array
+ * @out Output digits array
+ * @ndigits: Number of digits to create from byte array
+ */
+static inline void ecc_digits_from_bytes(const u8 *in, unsigned int nbytes,
+ u64 *out, unsigned int ndigits)
+{
+ unsigned int sz = ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
+ u8 tmp[ECC_MAX_DIGITS << ECC_DIGITS_TO_BYTES_SHIFT];
+ unsigned int o = sz - nbytes;
+
+ memset(tmp, 0, o);
+ memcpy(&tmp[o], in, nbytes);
+ ecc_swap_digits(tmp, out, ndigits);
+}
+
/**
* ecc_is_key_valid() - Validate a given ECDH private key
*
--
2.43.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH v2 02/14] crypto: ecdsa - Adjust tests on length of key parameters
2024-02-15 23:13 [PATCH v2 00/14] Add support for NIST P521 to ecdsa and ecdh Stefan Berger
2024-02-15 23:14 ` [PATCH v2 01/14] crypto: ecdsa - Convert byte arrays with key coordinates to digits Stefan Berger
@ 2024-02-15 23:14 ` Stefan Berger
2024-02-15 23:14 ` [PATCH v2 03/14] crypto: ecdsa - Extend res.x mod n calculation for NIST P521 Stefan Berger
` (12 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Stefan Berger @ 2024-02-15 23:14 UTC (permalink / raw)
To: keyrings, linux-crypto, herbert, davem
Cc: linux-kernel, saulo.alessandre, Stefan Berger
In preparation for support of NIST P521, adjust the basic tests on the
length of the provided key parameters to only ensure that the length of the
x plus y coordinates parameter array is not an odd number and that each
coordinate fits into an array of 'ndigits' digits. Mathematical tests on
the key's parameters are then done in ecc_is_pubkey_valid_full rejecting
invalid keys.
The change is necessary since NIST P521 keys do not have keys with
coordinates that each fully require 'full' digits (= u64), unlike
NIST P192/256/384 that all require multiple 'full' digits.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
crypto/ecdsa.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/crypto/ecdsa.c b/crypto/ecdsa.c
index ba8fb76fd165..64e1e69d53ba 100644
--- a/crypto/ecdsa.c
+++ b/crypto/ecdsa.c
@@ -230,7 +230,7 @@ static int ecdsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, unsig
if (ret < 0)
return ret;
- if (keylen < 1 || (((keylen - 1) >> 1) % sizeof(u64)) != 0)
+ if (keylen < 1 || ((keylen - 1) & 1) != 0)
return -EINVAL;
/* we only accept uncompressed format indicated by '4' */
if (d[0] != 4)
@@ -239,7 +239,7 @@ static int ecdsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, unsig
keylen--;
digitlen = keylen >> 1;
- ndigits = digitlen / sizeof(u64);
+ ndigits = DIV_ROUND_UP(digitlen, sizeof(u64));
if (ndigits != ctx->curve->g.ndigits)
return -EINVAL;
--
2.43.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH v2 03/14] crypto: ecdsa - Extend res.x mod n calculation for NIST P521
2024-02-15 23:13 [PATCH v2 00/14] Add support for NIST P521 to ecdsa and ecdh Stefan Berger
2024-02-15 23:14 ` [PATCH v2 01/14] crypto: ecdsa - Convert byte arrays with key coordinates to digits Stefan Berger
2024-02-15 23:14 ` [PATCH v2 02/14] crypto: ecdsa - Adjust tests on length of key parameters Stefan Berger
@ 2024-02-15 23:14 ` Stefan Berger
2024-02-15 23:14 ` [PATCH v2 04/14] crypto: ecc - Implement vli_mmod_fast_521 for NIST p521 Stefan Berger
` (11 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Stefan Berger @ 2024-02-15 23:14 UTC (permalink / raw)
To: keyrings, linux-crypto, herbert, davem
Cc: linux-kernel, saulo.alessandre, Stefan Berger
res.x has been calculated by ecc_point_mult_shamir, which uses
'mod curve_prime'. The curve_prime 'p' is typically larger than the
curve_order 'n' and therefore it is possible that p > res.x >= n.
If res.x >= n then res.x mod n can be calculated by iteratively sub-
tracting n from res.x until n > res.x. For NIST P192/256/384 this can be
done in a single subtraction. This can also be done in a single
subtraction for NIST P521.
The mathematical reason why a single subtraction is sufficient is
due to the values of 'p' and 'n' of the NIST curves where the following
holds true:
note: max(res.x) = p - 1
max(res.x) - n < n
p - 1 - n < n
p - 1 < 2n => true for the NIST curves
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
crypto/ecdsa.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/crypto/ecdsa.c b/crypto/ecdsa.c
index 64e1e69d53ba..1814f009f971 100644
--- a/crypto/ecdsa.c
+++ b/crypto/ecdsa.c
@@ -122,7 +122,7 @@ static int _ecdsa_verify(struct ecc_ctx *ctx, const u64 *hash, const u64 *r, con
/* res.x = res.x mod n (if res.x > order) */
if (unlikely(vli_cmp(res.x, curve->n, ndigits) == 1))
- /* faster alternative for NIST p384, p256 & p192 */
+ /* faster alternative for NIST p521, p384, p256 & p192 */
vli_sub(res.x, res.x, curve->n, ndigits);
if (!vli_cmp(res.x, r, ndigits))
--
2.43.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH v2 04/14] crypto: ecc - Implement vli_mmod_fast_521 for NIST p521
2024-02-15 23:13 [PATCH v2 00/14] Add support for NIST P521 to ecdsa and ecdh Stefan Berger
` (2 preceding siblings ...)
2024-02-15 23:14 ` [PATCH v2 03/14] crypto: ecdsa - Extend res.x mod n calculation for NIST P521 Stefan Berger
@ 2024-02-15 23:14 ` Stefan Berger
2024-02-15 23:14 ` [PATCH v2 05/14] crypto: ecc - For NIST P521 use vli_num_bits to get number of bits Stefan Berger
` (10 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Stefan Berger @ 2024-02-15 23:14 UTC (permalink / raw)
To: keyrings, linux-crypto, herbert, davem
Cc: linux-kernel, saulo.alessandre, Stefan Berger
Implement vli_mmod_fast_521 following the description for how to calculate
the modulus for NIST P521 in the NIST publication "Recommendations for
Discrete Logarithm-Based Cryptography: Elliptic Curve Domain Parameters"
section G.1.4.
NIST p521 requires 9 64bit digits, so increase the ECC_MAX_DIGITS so that
arrays fit the larger numbers.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
crypto/ecc.c | 31 +++++++++++++++++++++++++++++++
include/crypto/internal/ecc.h | 2 +-
2 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/crypto/ecc.c b/crypto/ecc.c
index f53fb4d6af99..ea7b28b5e00e 100644
--- a/crypto/ecc.c
+++ b/crypto/ecc.c
@@ -902,6 +902,31 @@ static void vli_mmod_fast_384(u64 *result, const u64 *product,
#undef AND64H
#undef AND64L
+/* Computes result = product % curve_prime
+ * from "Recommendations for Discrete Logarithm-Based Cryptography:
+ * Elliptic Curve Domain Parameters" G.1.4
+ */
+static void vli_mmod_fast_521(u64 *result, const u64 *product,
+ const u64 *curve_prime, u64 *tmp)
+{
+ const unsigned int ndigits = 9;
+ size_t i;
+
+ for (i = 0; i < ndigits; i++)
+ tmp[i] = product[i];
+ tmp[8] &= 0x1ff;
+
+ vli_set(result, tmp, ndigits);
+
+
+ for (i = 0; i < ndigits; i++)
+ tmp[i] = (product[8 + i] >> 9) | (product[9 + i] << 55);
+ tmp[8] &= 0x1ff;
+
+ vli_mod_add(result, result, tmp, curve_prime, ndigits);
+}
+
+
/* Computes result = product % curve_prime for different curve_primes.
*
* Note that curve_primes are distinguished just by heuristic check and
@@ -941,6 +966,12 @@ static bool vli_mmod_fast(u64 *result, u64 *product,
case 6:
vli_mmod_fast_384(result, product, curve_prime, tmp);
break;
+ case 9:
+ if (!strcmp(curve->name, "nist_521")) {
+ vli_mmod_fast_521(result, product, curve_prime, tmp);
+ break;
+ }
+ fallthrough;
default:
pr_err_ratelimited("ecc: unsupported digits size!\n");
return false;
diff --git a/include/crypto/internal/ecc.h b/include/crypto/internal/ecc.h
index bee3329af7de..b8ca5023b3b5 100644
--- a/include/crypto/internal/ecc.h
+++ b/include/crypto/internal/ecc.h
@@ -33,7 +33,7 @@
#define ECC_CURVE_NIST_P192_DIGITS 3
#define ECC_CURVE_NIST_P256_DIGITS 4
#define ECC_CURVE_NIST_P384_DIGITS 6
-#define ECC_MAX_DIGITS (512 / 64) /* due to ecrdsa */
+#define ECC_MAX_DIGITS (576 / 64) /* due to NIST P521 */
#define ECC_DIGITS_TO_BYTES_SHIFT 3
--
2.43.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH v2 05/14] crypto: ecc - For NIST P521 use vli_num_bits to get number of bits
2024-02-15 23:13 [PATCH v2 00/14] Add support for NIST P521 to ecdsa and ecdh Stefan Berger
` (3 preceding siblings ...)
2024-02-15 23:14 ` [PATCH v2 04/14] crypto: ecc - Implement vli_mmod_fast_521 for NIST p521 Stefan Berger
@ 2024-02-15 23:14 ` Stefan Berger
2024-02-15 23:14 ` [PATCH v2 06/14] crypto: ecc - Add NIST P521 curve parameters Stefan Berger
` (9 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Stefan Berger @ 2024-02-15 23:14 UTC (permalink / raw)
To: keyrings, linux-crypto, herbert, davem
Cc: linux-kernel, saulo.alessandre, Stefan Berger
In ecc_point_mult use vli_num_bits to determine the number of bits when
using NIST P521. The change is required specifically for NIST P521 to
pass mathematical tests on the public key.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
crypto/ecc.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/crypto/ecc.c b/crypto/ecc.c
index ea7b28b5e00e..0734cea284a4 100644
--- a/crypto/ecc.c
+++ b/crypto/ecc.c
@@ -1326,7 +1326,10 @@ static void ecc_point_mult(struct ecc_point *result,
carry = vli_add(sk[0], scalar, curve->n, ndigits);
vli_add(sk[1], sk[0], curve->n, ndigits);
scalar = sk[!carry];
- num_bits = sizeof(u64) * ndigits * 8 + 1;
+ if (ndigits == 9 && !strcmp(curve->name, "nist_521"))
+ num_bits = vli_num_bits(scalar, ndigits);
+ else
+ num_bits = sizeof(u64) * ndigits * 8 + 1;
vli_set(rx[1], point->x, ndigits);
vli_set(ry[1], point->y, ndigits);
--
2.43.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH v2 06/14] crypto: ecc - Add NIST P521 curve parameters
2024-02-15 23:13 [PATCH v2 00/14] Add support for NIST P521 to ecdsa and ecdh Stefan Berger
` (4 preceding siblings ...)
2024-02-15 23:14 ` [PATCH v2 05/14] crypto: ecc - For NIST P521 use vli_num_bits to get number of bits Stefan Berger
@ 2024-02-15 23:14 ` Stefan Berger
2024-02-16 18:48 ` Elliott, Robert (Servers)
2024-02-15 23:14 ` [PATCH v2 07/14] crypto: ecdsa - Register NIST P521 and extend test suite Stefan Berger
` (8 subsequent siblings)
14 siblings, 1 reply; 21+ messages in thread
From: Stefan Berger @ 2024-02-15 23:14 UTC (permalink / raw)
To: keyrings, linux-crypto, herbert, davem
Cc: linux-kernel, saulo.alessandre, Stefan Berger
Add the parameters for the NIST P521 curve and define a new curve ID
for it. Make the curve available in ecc_get_curve.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
crypto/ecc.c | 2 ++
crypto/ecc_curve_defs.h | 44 +++++++++++++++++++++++++++++++++++++++++
include/crypto/ecdh.h | 1 +
3 files changed, 47 insertions(+)
diff --git a/crypto/ecc.c b/crypto/ecc.c
index 0734cea284a4..73fbbfc8d69c 100644
--- a/crypto/ecc.c
+++ b/crypto/ecc.c
@@ -60,6 +60,8 @@ const struct ecc_curve *ecc_get_curve(unsigned int curve_id)
return &nist_p256;
case ECC_CURVE_NIST_P384:
return &nist_p384;
+ case ECC_CURVE_NIST_P521:
+ return &nist_p521;
default:
return NULL;
}
diff --git a/crypto/ecc_curve_defs.h b/crypto/ecc_curve_defs.h
index 9719934c9428..93a47a5d460a 100644
--- a/crypto/ecc_curve_defs.h
+++ b/crypto/ecc_curve_defs.h
@@ -86,6 +86,50 @@ static struct ecc_curve nist_p384 = {
.b = nist_p384_b
};
+/* NIST P-521 */
+static u64 nist_p521_g_x[] = { 0xf97e7e31c2e5bd66ull, 0x3348b3c1856a429bull,
+ 0xfe1dc127a2ffa8deull, 0xa14b5e77efe75928ull,
+ 0xf828af606b4d3dbaull, 0x9c648139053fb521ull,
+ 0x9e3ecb662395b442ull, 0x858e06b70404e9cdull,
+ 0xc6ull };
+static u64 nist_p521_g_y[] = { 0x88be94769fd16650ull, 0x353c7086a272c240ull,
+ 0xc550b9013fad0761ull, 0x97ee72995ef42640ull,
+ 0x17afbd17273e662cull, 0x98f54449579b4468ull,
+ 0x5c8a5fb42c7d1bd9ull, 0x39296a789a3bc004ull,
+ 0x118ull };
+static u64 nist_p521_p[] = { 0xffffffffffffffffull, 0xffffffffffffffffull,
+ 0xffffffffffffffffull, 0xffffffffffffffffull,
+ 0xffffffffffffffffull, 0xffffffffffffffffull,
+ 0xffffffffffffffffull, 0xffffffffffffffffull,
+ 0x1ffull };
+static u64 nist_p521_n[] = { 0xbb6fb71e91386409ull, 0x3bb5c9b8899c47aeull,
+ 0x7fcc0148f709a5d0ull, 0x51868783bf2f966bull,
+ 0xfffffffffffffffaull, 0xffffffffffffffffull,
+ 0xffffffffffffffffull, 0xffffffffffffffffull,
+ 0x1ffull };
+static u64 nist_p521_a[] = { 0xfffffffffffffffcull, 0xffffffffffffffffull,
+ 0xffffffffffffffffull, 0xffffffffffffffffull,
+ 0xffffffffffffffffull, 0xffffffffffffffffull,
+ 0xffffffffffffffffull, 0xffffffffffffffffull,
+ 0x1ffull };
+static u64 nist_p521_b[] = { 0xef451fd46b503f00ull, 0x3573df883d2c34f1ull,
+ 0x1652c0bd3bb1bf07ull, 0x56193951ec7e937bull,
+ 0xb8b489918ef109e1ull, 0xa2da725b99b315f3ull,
+ 0x929a21a0b68540eeull, 0x953eb9618e1c9a1full,
+ 0x051ull };
+static struct ecc_curve nist_p521 = {
+ .name = "nist_521",
+ .g = {
+ .x = nist_p521_g_x,
+ .y = nist_p521_g_y,
+ .ndigits = 9,
+ },
+ .p = nist_p521_p,
+ .n = nist_p521_n,
+ .a = nist_p521_a,
+ .b = nist_p521_b
+};
+
/* curve25519 */
static u64 curve25519_g_x[] = { 0x0000000000000009, 0x0000000000000000,
0x0000000000000000, 0x0000000000000000 };
diff --git a/include/crypto/ecdh.h b/include/crypto/ecdh.h
index a9f98078d29c..9784ecdd2fb4 100644
--- a/include/crypto/ecdh.h
+++ b/include/crypto/ecdh.h
@@ -26,6 +26,7 @@
#define ECC_CURVE_NIST_P192 0x0001
#define ECC_CURVE_NIST_P256 0x0002
#define ECC_CURVE_NIST_P384 0x0003
+#define ECC_CURVE_NIST_P521 0x0004
/**
* struct ecdh - define an ECDH private key
--
2.43.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* RE: [PATCH v2 06/14] crypto: ecc - Add NIST P521 curve parameters
2024-02-15 23:14 ` [PATCH v2 06/14] crypto: ecc - Add NIST P521 curve parameters Stefan Berger
@ 2024-02-16 18:48 ` Elliott, Robert (Servers)
2024-02-16 19:03 ` Stefan Berger
0 siblings, 1 reply; 21+ messages in thread
From: Elliott, Robert (Servers) @ 2024-02-16 18:48 UTC (permalink / raw)
To: Stefan Berger, keyrings@vger.kernel.org,
linux-crypto@vger.kernel.org, herbert@gondor.apana.org.au,
davem@davemloft.net
Cc: linux-kernel@vger.kernel.org, saulo.alessandre@tse.jus.br
> -----Original Message-----
> From: Stefan Berger <stefanb@linux.ibm.com>
> Sent: Thursday, February 15, 2024 5:14 PM
> Subject: [PATCH v2 06/14] crypto: ecc - Add NIST P521 curve parameters
>
> Add the parameters for the NIST P521 curve and define a new curve ID
> for it. Make the curve available in ecc_get_curve.
>
...
> diff --git a/crypto/ecc_curve_defs.h b/crypto/ecc_curve_defs.h
...
> +static struct ecc_curve nist_p521 = {
> + .name = "nist_521",
Are the name fields in the ecc_curve structures used anywhere or
exposed to userspace?
It'd be nice if the strings for the nist_p192, nist_p256, and nist_p384
structures and this new nist_p521 structure included "p" before
the number, better matching all the code and the NIST FIPS 186-4 names:
.name = "nist_p192"
.name = "nist_p256"
.name = "nist_p384"
.name = "nist_p521"
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH v2 06/14] crypto: ecc - Add NIST P521 curve parameters
2024-02-16 18:48 ` Elliott, Robert (Servers)
@ 2024-02-16 19:03 ` Stefan Berger
0 siblings, 0 replies; 21+ messages in thread
From: Stefan Berger @ 2024-02-16 19:03 UTC (permalink / raw)
To: Elliott, Robert (Servers), keyrings@vger.kernel.org,
linux-crypto@vger.kernel.org, herbert@gondor.apana.org.au,
davem@davemloft.net
Cc: linux-kernel@vger.kernel.org, saulo.alessandre@tse.jus.br
On 2/16/24 13:48, Elliott, Robert (Servers) wrote:
>> -----Original Message-----
>> From: Stefan Berger <stefanb@linux.ibm.com>
>> Sent: Thursday, February 15, 2024 5:14 PM
>> Subject: [PATCH v2 06/14] crypto: ecc - Add NIST P521 curve parameters
>>
>> Add the parameters for the NIST P521 curve and define a new curve ID
>> for it. Make the curve available in ecc_get_curve.
>>
> ...
>> diff --git a/crypto/ecc_curve_defs.h b/crypto/ecc_curve_defs.h
> ...
>> +static struct ecc_curve nist_p521 = {
>> + .name = "nist_521",
>
> Are the name fields in the ecc_curve structures used anywhere or
> exposed to userspace?
>
> It'd be nice if the strings for the nist_p192, nist_p256, and nist_p384
> structures and this new nist_p521 structure included "p" before
> the number, better matching all the code and the NIST FIPS 186-4 names:
> .name = "nist_p192"
> .name = "nist_p256"
> .name = "nist_p384"
> .name = "nist_p521"
>
>
This is what is exposed:
$ cat /proc/crypto | grep nist
name : ecdh-nist-p384
driver : ecdh-nist-p384-generic
name : ecdh-nist-p256
driver : ecdh-nist-p256-generic
name : ecdh-nist-p192
driver : ecdh-nist-p192-generic
name : ecdsa-nist-p384
driver : ecdsa-nist-p384-generic
name : ecdsa-nist-p256
driver : ecdsa-nist-p256-generic
name : ecdsa-nist-p192
driver : ecdsa-nist-p192-generic
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v2 07/14] crypto: ecdsa - Register NIST P521 and extend test suite
2024-02-15 23:13 [PATCH v2 00/14] Add support for NIST P521 to ecdsa and ecdh Stefan Berger
` (5 preceding siblings ...)
2024-02-15 23:14 ` [PATCH v2 06/14] crypto: ecc - Add NIST P521 curve parameters Stefan Berger
@ 2024-02-15 23:14 ` Stefan Berger
2024-02-15 23:14 ` [PATCH v2 08/14] x509: Add OID for NIST P521 and extend parser for it Stefan Berger
` (7 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Stefan Berger @ 2024-02-15 23:14 UTC (permalink / raw)
To: keyrings, linux-crypto, herbert, davem
Cc: linux-kernel, saulo.alessandre, Stefan Berger
Register NIST P521 as an akcipher and extend the testmgr with
NIST P521-specific test vectors.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
crypto/ecdsa.c | 30 ++++++++++
crypto/testmgr.c | 7 +++
crypto/testmgr.h | 146 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 183 insertions(+)
diff --git a/crypto/ecdsa.c b/crypto/ecdsa.c
index 1814f009f971..faa55c692d2a 100644
--- a/crypto/ecdsa.c
+++ b/crypto/ecdsa.c
@@ -269,6 +269,28 @@ static unsigned int ecdsa_max_size(struct crypto_akcipher *tfm)
return ctx->pub_key.ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
}
+static int ecdsa_nist_p521_init_tfm(struct crypto_akcipher *tfm)
+{
+ struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);
+
+ return ecdsa_ecc_ctx_init(ctx, ECC_CURVE_NIST_P521);
+}
+
+static struct akcipher_alg ecdsa_nist_p521 = {
+ .verify = ecdsa_verify,
+ .set_pub_key = ecdsa_set_pub_key,
+ .max_size = ecdsa_max_size,
+ .init = ecdsa_nist_p521_init_tfm,
+ .exit = ecdsa_exit_tfm,
+ .base = {
+ .cra_name = "ecdsa-nist-p521",
+ .cra_driver_name = "ecdsa-nist-p521-generic",
+ .cra_priority = 100,
+ .cra_module = THIS_MODULE,
+ .cra_ctxsize = sizeof(struct ecc_ctx),
+ },
+};
+
static int ecdsa_nist_p384_init_tfm(struct crypto_akcipher *tfm)
{
struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);
@@ -352,8 +374,15 @@ static int __init ecdsa_init(void)
if (ret)
goto nist_p384_error;
+ ret = crypto_register_akcipher(&ecdsa_nist_p521);
+ if (ret)
+ goto nist_p521_error;
+
return 0;
+nist_p521_error:
+ crypto_unregister_akcipher(&ecdsa_nist_p384);
+
nist_p384_error:
crypto_unregister_akcipher(&ecdsa_nist_p256);
@@ -369,6 +398,7 @@ static void __exit ecdsa_exit(void)
crypto_unregister_akcipher(&ecdsa_nist_p192);
crypto_unregister_akcipher(&ecdsa_nist_p256);
crypto_unregister_akcipher(&ecdsa_nist_p384);
+ crypto_unregister_akcipher(&ecdsa_nist_p521);
}
subsys_initcall(ecdsa_init);
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 3dddd288ca02..00f5a6cf341a 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -5097,6 +5097,13 @@ static const struct alg_test_desc alg_test_descs[] = {
.suite = {
.akcipher = __VECS(ecdsa_nist_p384_tv_template)
}
+ }, {
+ .alg = "ecdsa-nist-p521",
+ .test = alg_test_akcipher,
+ .fips_allowed = 1,
+ .suite = {
+ .akcipher = __VECS(ecdsa_nist_p521_tv_template)
+ }
}, {
.alg = "ecrdsa",
.test = alg_test_akcipher,
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 986f331a5fc2..9bde04be8df9 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -991,6 +991,152 @@ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
},
};
+static const struct akcipher_testvec ecdsa_nist_p521_tv_template[] = {
+ {
+ .key = /* secp521r1(sha224) */
+ "\x04\x01\x4f\x43\x18\xb6\xa9\xc9\x5d\x68\xd3\xa9\x42\xf8\x98\xc0"
+ "\xd2\xd1\xa9\x50\x3b\xe8\xc4\x40\xe6\x11\x78\x88\x4b\xbd\x76\xa7"
+ "\x9a\xe0\xdd\x31\xa4\x67\x78\x45\x33\x9e\x8c\xd1\xc7\x44\xac\x61"
+ "\x68\xc8\x04\xe7\x5c\x79\xb1\xf1\x41\x0c\x71\xc0\x53\xa8\xbc\xfb"
+ "\xf5\xca\xd4\x01\x40\xfd\xa3\x45\xda\x08\xe0\xb4\xcb\x28\x3b\x0a"
+ "\x02\x35\x5f\x02\x9f\x3f\xcd\xef\x08\x22\x40\x97\x74\x65\xb7\x76"
+ "\x85\xc7\xc0\x5c\xfb\x81\xe1\xa5\xde\x0c\x4e\x8b\x12\x31\xb6\x47"
+ "\xed\x37\x0f\x99\x3f\x26\xba\xa3\x8e\xff\x79\x34\x7c\x3a\xfe\x1f"
+ "\x3b\x83\x82\x2f\x14",
+ .key_len = 133,
+ .params =
+ "\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
+ "\x00\x23",
+ .param_len = 18,
+ .m =
+ "\xa2\x3a\x6a\x8c\x7b\x3c\xf2\x51\xf8\xbe\x5f\x4f\x3b\x15\x05\xc4"
+ "\xb5\xbc\x19\xe7\x21\x85\xe9\x23\x06\x33\x62\xfb",
+ .m_size = 28,
+ .algo = OID_id_ecdsa_with_sha224,
+ .c =
+ "\x30\x81\x86\x02\x41\x01\xd6\x43\xe7\xff\x42\xb2\xba\x74\x35\xf6"
+ "\xdc\x6d\x02\x7b\x22\xac\xe2\xef\x07\x92\xee\x60\x94\x06\xf8\x3f"
+ "\x59\x0f\x74\xf0\x3f\xd8\x18\xc6\x37\x8a\xcb\xa7\xd8\x7d\x98\x85"
+ "\x29\x88\xff\x0b\x94\x94\x6c\xa6\x9b\x89\x8b\x1e\xfd\x09\x46\x6b"
+ "\xc7\xaf\x7a\xb9\x19\x0a\x02\x41\x3a\x26\x0d\x55\xcd\x23\x1e\x7d"
+ "\xa0\x5e\xf9\x88\xf3\xd2\x32\x90\x57\x0f\xf8\x65\x97\x6b\x09\x4d"
+ "\x22\x26\x0b\x5f\x49\x32\x6b\x91\x99\x30\x90\x0f\x1c\x8f\x78\xd3"
+ "\x9f\x0e\x64\xcc\xc4\xe8\x43\xd9\x0e\x1c\xad\x22\xda\x82\x00\x35"
+ "\xa3\x50\xb1\xa5\x98\x92\x2a\xa5\x52",
+ .c_size = 137,
+ .public_key_vec = true,
+ .siggen_sigver_test = true,
+ },
+ {
+ .key = /* secp521r1(sha256) */
+ "\x04\x01\x05\x3a\x6b\x3b\x5a\x0f\xa7\xb9\xb7\x32\x53\x4e\xe2\xae"
+ "\x0a\x52\xc5\xda\xdd\x5a\x79\x1c\x30\x2d\x33\x07\x79\xd5\x70\x14"
+ "\x61\x0c\xec\x26\x4d\xd8\x35\x57\x04\x1d\x88\x33\x4d\xce\x05\x36"
+ "\xa5\xaf\x56\x84\xfa\x0b\x9e\xff\x7b\x30\x4b\x92\x1d\x06\xf8\x81"
+ "\x24\x1e\x51\x00\x09\x21\x51\xf7\x46\x0a\x77\xdb\xb5\x0c\xe7\x9c"
+ "\xff\x27\x3c\x02\x71\xd7\x85\x36\xf1\xaa\x11\x59\xd8\xb8\xdc\x09"
+ "\xdc\x6d\x5a\x6f\x63\x07\x6c\xe1\xe5\x4d\x6e\x0f\x6e\xfb\x7c\x05"
+ "\x8a\xe9\x53\xa8\xcf\xce\x43\x0e\x82\x20\x86\xbc\x88\x9c\xb7\xe3"
+ "\xe6\x77\x1e\x1f\x8a",
+ .key_len = 133,
+ .params =
+ "\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
+ "\x00\x23",
+ .param_len = 18,
+ .m =
+ "\xcc\x97\x73\x0c\x73\xa2\x53\x2b\xfa\xd7\x83\x1d\x0c\x72\x1b\x39"
+ "\x80\x71\x8d\xdd\xc5\x9b\xff\x55\x32\x98\x25\xa2\x58\x2e\xb7\x73",
+ .m_size = 32,
+ .algo = OID_id_ecdsa_with_sha256,
+ .c =
+ "\x30\x81\x88\x02\x42\x00\xcd\xa5\x5f\x57\x52\x27\x78\x3a\xb5\x06"
+ "\x0f\xfd\x83\xfc\x0e\xd9\xce\x50\x9f\x7d\x1f\xca\x8b\xa8\x2d\x56"
+ "\x3c\xf6\xf0\xd8\xe1\xb7\x5d\x95\x35\x6f\x02\x0e\xaf\xe1\x4c\xae"
+ "\xce\x54\x76\x9a\xc2\x8f\xb8\x38\x1f\x46\x0b\x04\x64\x34\x79\xde"
+ "\x7e\xd7\x59\x10\xe9\xd9\xd5\x02\x42\x01\xcf\x50\x85\x38\xf9\x15"
+ "\x83\x18\x04\x6b\x35\xae\x65\xb5\x99\x12\x0a\xa9\x79\x24\xb9\x37"
+ "\x35\xdd\xa0\xe0\x87\x2c\x44\x4b\x5a\xee\xaf\xfa\x10\xdd\x9b\xfb"
+ "\x36\x1a\x31\x03\x42\x02\x5f\x50\xf0\xa2\x0d\x1c\x57\x56\x8f\x12"
+ "\xb7\x1d\x91\x55\x38\xb6\xf6\x34\x65\xc7\xbd",
+ .c_size = 139,
+ .public_key_vec = true,
+ .siggen_sigver_test = true,
+ },
+ {
+ .key = /* secp521r1(sha384) */
+ "\x04\x00\x2e\xd6\x21\x04\x75\xc3\xdc\x7d\xff\x0e\xf3\x70\x25\x2b"
+ "\xad\x72\xfc\x5a\x91\xf1\xd5\x9c\x64\xf3\x1f\x47\x11\x10\x62\x33"
+ "\xfd\x2e\xe8\x32\xca\x9e\x6f\x0a\x4c\x5b\x35\x9a\x46\xc5\xe7\xd4"
+ "\x38\xda\xb2\xf0\xf4\x87\xf3\x86\xf4\xea\x70\xad\x1e\xd4\x78\x8c"
+ "\x36\x18\x17\x00\xa2\xa0\x34\x1b\x2e\x6a\xdf\x06\xd6\x99\x2d\x47"
+ "\x50\x92\x1a\x8a\x72\x9c\x23\x44\xfa\xa7\xa9\xed\xa6\xef\x26\x14"
+ "\xb3\x9d\xfe\x5e\xa3\x8c\xd8\x29\xf8\xdf\xad\xa6\xab\xfc\xdd\x46"
+ "\x22\x6e\xd7\x35\xc7\x23\xb7\x13\xae\xb6\x34\xff\xd7\x80\xe5\x39"
+ "\xb3\x3b\x5b\x1b\x94",
+ .key_len = 133,
+ .params =
+ "\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
+ "\x00\x23",
+ .param_len = 18,
+ .m =
+ "\x36\x98\xd6\x82\xfa\xad\xed\x3c\xb9\x40\xb6\x4d\x9e\xb7\x04\x26"
+ "\xad\x72\x34\x44\xd2\x81\xb4\x9b\xbe\x01\x04\x7a\xd8\x50\xf8\x59"
+ "\xba\xad\x23\x85\x6b\x59\xbe\xfb\xf6\x86\xd4\x67\xa8\x43\x28\x76",
+ .m_size = 48,
+ .algo = OID_id_ecdsa_with_sha384,
+ .c =
+ "\x30\x81\x88\x02\x42\x00\x93\x96\x76\x3c\x27\xea\xaa\x9c\x26\xec"
+ "\x51\xdc\xe8\x35\x5e\xae\x16\xf2\x4b\x64\x98\xf7\xec\xda\xc7\x7e"
+ "\x42\x71\x86\x57\x2d\xf1\x7d\xe4\xdf\x9b\x7d\x9e\x47\xca\x33\x32"
+ "\x76\x06\xd0\xf9\xc0\xe4\xe6\x84\x59\xfd\x1a\xc4\x40\xdd\x43\xb8"
+ "\x6a\xdd\xfb\xe6\x63\x4e\x28\x02\x42\x00\xff\xc3\x6a\x87\x6e\xb5"
+ "\x13\x1f\x20\x55\xce\x37\x97\xc9\x05\x51\xe5\xe4\x3c\xbc\x93\x65"
+ "\x57\x1c\x30\xda\xa7\xcd\x26\x28\x76\x3b\x52\xdf\xc4\xc0\xdb\x54"
+ "\xdb\x8a\x0d\x6a\xc3\xf3\x7a\xd1\xfa\xe7\xa7\xe5\x5a\x94\x56\xcf"
+ "\x8f\xb4\x22\xc6\x4f\xab\x2b\x62\xc1\x42\xb1",
+ .c_size = 139,
+ .public_key_vec = true,
+ .siggen_sigver_test = true,
+ },
+ {
+ .key = /* secp521r1(sha512) */
+ "\x04\x00\xc7\x65\xee\x0b\x86\x7d\x8f\x02\xf1\x74\x5b\xb0\x4c\x3f"
+ "\xa6\x35\x60\x9f\x55\x23\x11\xcc\xdf\xb8\x42\x99\xee\x6c\x96\x6a"
+ "\x27\xa2\x56\xb2\x2b\x03\xad\x0f\xe7\x97\xde\x09\x5d\xb4\xc5\x5f"
+ "\xbd\x87\x37\xbf\x5a\x16\x35\x56\x08\xfd\x6f\x06\x1a\x1c\x84\xee"
+ "\xc3\x64\xb3\x00\x9e\xbd\x6e\x60\x76\xee\x69\xfd\x3a\xb8\xcd\x7e"
+ "\x91\x68\x53\x57\x44\x13\x2e\x77\x09\x2a\xbe\x48\xbd\x91\xd8\xf6"
+ "\x21\x16\x53\x99\xd5\xf0\x40\xad\xa6\xf8\x58\x26\xb6\x9a\xf8\x77"
+ "\xfe\x3a\x05\x1a\xdb\xa9\x0f\xc0\x6c\x76\x30\x8c\xd8\xde\x44\xae"
+ "\xd0\x17\xdf\x49\x6a",
+ .key_len = 133,
+ .params =
+ "\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
+ "\x00\x23",
+ .param_len = 18,
+ .m =
+ "\x5c\xa6\xbc\x79\xb8\xa0\x1e\x11\x83\xf7\xe9\x05\xdf\xba\xf7\x69"
+ "\x97\x22\x32\xe4\x94\x7c\x65\xbd\x74\xc6\x9a\x8b\xbd\x0d\xdc\xed"
+ "\xf5\x9c\xeb\xe1\xc5\x68\x40\xf2\xc7\x04\xde\x9e\x0d\x76\xc5\xa3"
+ "\xf9\x3c\x6c\x98\x08\x31\xbd\x39\xe8\x42\x7f\x80\x39\x6f\xfe\x68",
+ .m_size = 64,
+ .algo = OID_id_ecdsa_with_sha512,
+ .c =
+ "\x30\x81\x88\x02\x42\x01\x5c\x71\x86\x96\xac\x21\x33\x7e\x4e\xaa"
+ "\x86\xec\xa8\x05\x03\x52\x56\x63\x0e\x02\xcc\x94\xa9\x05\xb9\xfb"
+ "\x62\x1e\x42\x03\x6c\x74\x8a\x1f\x12\x3e\xb7\x7e\x51\xff\x7f\x27"
+ "\x93\xe8\x6c\x49\x7d\x28\xfc\x80\xa6\x13\xfc\xb6\x90\xf7\xbb\x28"
+ "\xb5\x04\xb0\xb6\x33\x1c\x7e\x02\x42\x01\x70\x43\x52\x1d\xe3\xc6"
+ "\xbd\x5a\x40\x95\x35\x89\x4f\x41\x5f\x9e\x19\x88\x05\x3e\x43\x39"
+ "\x01\xbd\xb7\x7a\x76\x37\x51\x47\x49\x98\x12\x71\xd0\xe9\xca\xa7"
+ "\xc0\xcb\xaa\x00\x55\xbb\x6a\xb4\x73\x00\xd2\x72\x74\x13\x63\x39"
+ "\xa6\xe5\x25\x46\x1e\x77\x44\x78\xe0\xd1\x04",
+ .c_size = 139,
+ .public_key_vec = true,
+ .siggen_sigver_test = true,
+ },
+};
+
/*
* EC-RDSA test vectors are generated by gost-engine.
*/
--
2.43.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH v2 08/14] x509: Add OID for NIST P521 and extend parser for it
2024-02-15 23:13 [PATCH v2 00/14] Add support for NIST P521 to ecdsa and ecdh Stefan Berger
` (6 preceding siblings ...)
2024-02-15 23:14 ` [PATCH v2 07/14] crypto: ecdsa - Register NIST P521 and extend test suite Stefan Berger
@ 2024-02-15 23:14 ` Stefan Berger
2024-02-15 23:14 ` [PATCH v2 09/14] crypto: ecdh - Use properly formatted digits to check for valid key Stefan Berger
` (6 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Stefan Berger @ 2024-02-15 23:14 UTC (permalink / raw)
To: keyrings, linux-crypto, herbert, davem
Cc: linux-kernel, saulo.alessandre, Stefan Berger, David Howells
Prepare the x509 parser to accept NIST P521 certificates and add the
OID for ansip521r1, which is the identifier for NIST P521.
Cc: David Howells <dhowells@redhat.com>
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
crypto/asymmetric_keys/x509_cert_parser.c | 3 +++
include/linux/oid_registry.h | 1 +
2 files changed, 4 insertions(+)
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
index 487204d39426..99f809b7910b 100644
--- a/crypto/asymmetric_keys/x509_cert_parser.c
+++ b/crypto/asymmetric_keys/x509_cert_parser.c
@@ -538,6 +538,9 @@ int x509_extract_key_data(void *context, size_t hdrlen,
case OID_id_ansip384r1:
ctx->cert->pub->pkey_algo = "ecdsa-nist-p384";
break;
+ case OID_id_ansip521r1:
+ ctx->cert->pub->pkey_algo = "ecdsa-nist-p521";
+ break;
default:
return -ENOPKG;
}
diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h
index 3921fbed0b28..af16d96fbbf2 100644
--- a/include/linux/oid_registry.h
+++ b/include/linux/oid_registry.h
@@ -65,6 +65,7 @@ enum OID {
OID_Scram, /* 1.3.6.1.5.5.14 */
OID_certAuthInfoAccess, /* 1.3.6.1.5.5.7.1.1 */
OID_id_ansip384r1, /* 1.3.132.0.34 */
+ OID_id_ansip521r1, /* 1.3.132.0.35 */
OID_sha256, /* 2.16.840.1.101.3.4.2.1 */
OID_sha384, /* 2.16.840.1.101.3.4.2.2 */
OID_sha512, /* 2.16.840.1.101.3.4.2.3 */
--
2.43.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH v2 09/14] crypto: ecdh - Use properly formatted digits to check for valid key
2024-02-15 23:13 [PATCH v2 00/14] Add support for NIST P521 to ecdsa and ecdh Stefan Berger
` (7 preceding siblings ...)
2024-02-15 23:14 ` [PATCH v2 08/14] x509: Add OID for NIST P521 and extend parser for it Stefan Berger
@ 2024-02-15 23:14 ` Stefan Berger
2024-02-15 23:14 ` [PATCH v2 10/14] crypto: ecc - Implement ecc_digits_to_bytes to convert digits to byte array Stefan Berger
` (5 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Stefan Berger @ 2024-02-15 23:14 UTC (permalink / raw)
To: keyrings, linux-crypto, herbert, davem
Cc: linux-kernel, saulo.alessandre, Stefan Berger
ecc_is_key_valid expects a key with the most significant digit in the last
entry of the digit array. Currently a reverse key is passed to
ecc_is_key_valid that then passes the rather simple test checking whether
the private key is in range [2, n-3]. For all current ecdh-supported
curves (NIST P192/256/384) the 'n' parameter is a rather large number,
therefore easily passing this test. Fix the format of the digit by using
ecc_digits_from_bytes to create a temporary private key and pass it to
the test function. Keep the swapped key in ctx->private_key.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
crypto/ecdh.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/crypto/ecdh.c b/crypto/ecdh.c
index 80afee3234fb..f187365db7b6 100644
--- a/crypto/ecdh.c
+++ b/crypto/ecdh.c
@@ -27,6 +27,8 @@ static int ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
unsigned int len)
{
struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
+ u64 priv[ECC_MAX_DIGITS];
+ unsigned int nbytes;
struct ecdh params;
if (crypto_ecdh_decode_key(buf, len, ¶ms) < 0 ||
@@ -37,10 +39,13 @@ static int ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
return ecc_gen_privkey(ctx->curve_id, ctx->ndigits,
ctx->private_key);
- memcpy(ctx->private_key, params.key, params.key_size);
+ nbytes = ctx->ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
+
+ memcpy(ctx->private_key, params.key, nbytes);
+ ecc_swap_digits(ctx->private_key, priv, ctx->ndigits);
if (ecc_is_key_valid(ctx->curve_id, ctx->ndigits,
- ctx->private_key, params.key_size) < 0) {
+ priv, params.key_size) < 0) {
memzero_explicit(ctx->private_key, params.key_size);
return -EINVAL;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH v2 10/14] crypto: ecc - Implement ecc_digits_to_bytes to convert digits to byte array
2024-02-15 23:13 [PATCH v2 00/14] Add support for NIST P521 to ecdsa and ecdh Stefan Berger
` (8 preceding siblings ...)
2024-02-15 23:14 ` [PATCH v2 09/14] crypto: ecdh - Use properly formatted digits to check for valid key Stefan Berger
@ 2024-02-15 23:14 ` Stefan Berger
2024-02-15 23:14 ` [PATCH v2 11/14] crypto: Add nbits field to ecc_curve structure Stefan Berger
` (4 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Stefan Berger @ 2024-02-15 23:14 UTC (permalink / raw)
To: keyrings, linux-crypto, herbert, davem
Cc: linux-kernel, saulo.alessandre, Stefan Berger
Implement ecc_digits_to_bytes to convert an array of digits into an
nbytes-sized byte array.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
include/crypto/internal/ecc.h | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/include/crypto/internal/ecc.h b/include/crypto/internal/ecc.h
index b8ca5023b3b5..6229aa3f3218 100644
--- a/include/crypto/internal/ecc.h
+++ b/include/crypto/internal/ecc.h
@@ -75,6 +75,24 @@ static inline void ecc_digits_from_bytes(const u8 *in, unsigned int nbytes,
ecc_swap_digits(tmp, out, 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
+ */
+static inline void ecc_digits_to_bytes(const u64 *in, unsigned int ndigits,
+ u8 *out, unsigned int nbytes)
+{
+ unsigned int sz = ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
+ u8 tmp[ECC_MAX_DIGITS << ECC_DIGITS_TO_BYTES_SHIFT];
+ unsigned int o = sz - nbytes;
+
+ ecc_swap_digits(in, (u64 *)tmp, ndigits);
+ memcpy(out, &tmp[o], nbytes);
+}
+
/**
* ecc_is_key_valid() - Validate a given ECDH private key
*
--
2.43.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH v2 11/14] crypto: Add nbits field to ecc_curve structure
2024-02-15 23:13 [PATCH v2 00/14] Add support for NIST P521 to ecdsa and ecdh Stefan Berger
` (9 preceding siblings ...)
2024-02-15 23:14 ` [PATCH v2 10/14] crypto: ecc - Implement ecc_digits_to_bytes to convert digits to byte array Stefan Berger
@ 2024-02-15 23:14 ` Stefan Berger
2024-02-15 23:14 ` [PATCH v2 12/14] crypto: ecc - Implement and use ecc_curve_get_nbytes to get curve's nbytes Stefan Berger
` (3 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Stefan Berger @ 2024-02-15 23:14 UTC (permalink / raw)
To: keyrings, linux-crypto, herbert, davem
Cc: linux-kernel, saulo.alessandre, Stefan Berger
Add the number of bits a curve has to the ecc_curve definition. This field
only needs to be set for curves that don't fill up all bytes in their
digits, such as NIST P521 which has only 9 bits in the most significant
digit. This field will be used to determine the number of bytes a curve
requires for its key coordinates for example.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
crypto/ecc_curve_defs.h | 1 +
include/crypto/ecc_curve.h | 3 +++
2 files changed, 4 insertions(+)
diff --git a/crypto/ecc_curve_defs.h b/crypto/ecc_curve_defs.h
index 93a47a5d460a..09a221657c31 100644
--- a/crypto/ecc_curve_defs.h
+++ b/crypto/ecc_curve_defs.h
@@ -119,6 +119,7 @@ static u64 nist_p521_b[] = { 0xef451fd46b503f00ull, 0x3573df883d2c34f1ull,
0x051ull };
static struct ecc_curve nist_p521 = {
.name = "nist_521",
+ .nbits = 521,
.g = {
.x = nist_p521_g_x,
.y = nist_p521_g_y,
diff --git a/include/crypto/ecc_curve.h b/include/crypto/ecc_curve.h
index 70964781eb68..337a44956926 100644
--- a/include/crypto/ecc_curve.h
+++ b/include/crypto/ecc_curve.h
@@ -23,6 +23,8 @@ struct ecc_point {
* struct ecc_curve - definition of elliptic curve
*
* @name: Short name of the curve.
+ * @nbits: Curves that do not use all bits in their ndigits must specify
+ * their number of bits here, otherwise can leave at 0.
* @g: Generator point of the curve.
* @p: Prime number, if Barrett's reduction is used for this curve
* pre-calculated value 'mu' is appended to the @p after ndigits.
@@ -34,6 +36,7 @@ struct ecc_point {
*/
struct ecc_curve {
char *name;
+ unsigned int nbits;
struct ecc_point g;
u64 *p;
u64 *n;
--
2.43.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH v2 12/14] crypto: ecc - Implement and use ecc_curve_get_nbytes to get curve's nbytes
2024-02-15 23:13 [PATCH v2 00/14] Add support for NIST P521 to ecdsa and ecdh Stefan Berger
` (10 preceding siblings ...)
2024-02-15 23:14 ` [PATCH v2 11/14] crypto: Add nbits field to ecc_curve structure Stefan Berger
@ 2024-02-15 23:14 ` Stefan Berger
2024-02-15 23:14 ` [PATCH v2 13/14] crypto: ecdh - Use functions to copy digits from and to byte array Stefan Berger
` (2 subsequent siblings)
14 siblings, 0 replies; 21+ messages in thread
From: Stefan Berger @ 2024-02-15 23:14 UTC (permalink / raw)
To: keyrings, linux-crypto, herbert, davem
Cc: linux-kernel, saulo.alessandre, Stefan Berger
Implement ecc_curve_get_nbytes to get a curve's number of bytes (nbytes).
The number of bytes can be derived from the nbits field of a curve, if
set, otherwise from the ndigits field.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
crypto/ecc.c | 6 ++----
include/crypto/internal/ecc.h | 11 +++++++++++
2 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/crypto/ecc.c b/crypto/ecc.c
index 73fbbfc8d69c..f643719450b8 100644
--- a/crypto/ecc.c
+++ b/crypto/ecc.c
@@ -1478,10 +1478,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;
+ int nbytes = ecc_curve_get_nbytes(curve);
if (private_key_len != nbytes)
return -EINVAL;
@@ -1506,7 +1504,7 @@ int ecc_gen_privkey(unsigned int curve_id, unsigned int ndigits, u64 *privkey)
{
const struct ecc_curve *curve = ecc_get_curve(curve_id);
u64 priv[ECC_MAX_DIGITS];
- unsigned int nbytes = ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
+ unsigned int nbytes = ecc_curve_get_nbytes(curve);
unsigned int nbits = vli_num_bits(curve->n, ndigits);
int err;
diff --git a/include/crypto/internal/ecc.h b/include/crypto/internal/ecc.h
index 6229aa3f3218..5d485d3221d3 100644
--- a/include/crypto/internal/ecc.h
+++ b/include/crypto/internal/ecc.h
@@ -93,6 +93,17 @@ static inline void ecc_digits_to_bytes(const u64 *in, unsigned int ndigits,
memcpy(out, &tmp[o], 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)
+{
+ if (curve->nbits)
+ return DIV_ROUND_UP(curve->nbits, 8);
+ return curve->g.ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
+}
+
/**
* ecc_is_key_valid() - Validate a given ECDH private key
*
--
2.43.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH v2 13/14] crypto: ecdh - Use functions to copy digits from and to byte array
2024-02-15 23:13 [PATCH v2 00/14] Add support for NIST P521 to ecdsa and ecdh Stefan Berger
` (11 preceding siblings ...)
2024-02-15 23:14 ` [PATCH v2 12/14] crypto: ecc - Implement and use ecc_curve_get_nbytes to get curve's nbytes Stefan Berger
@ 2024-02-15 23:14 ` Stefan Berger
2024-02-15 23:14 ` [PATCH v2 14/14] crypto: ecdh - Add support for NIST P521 and add test case Stefan Berger
2024-02-16 19:27 ` [PATCH v2 00/14] Add support for NIST P521 to ecdsa and ecdh Simo Sorce
14 siblings, 0 replies; 21+ messages in thread
From: Stefan Berger @ 2024-02-15 23:14 UTC (permalink / raw)
To: keyrings, linux-crypto, herbert, davem
Cc: linux-kernel, saulo.alessandre, Stefan Berger
All curves supported so far provide full 64bit digit arrays to convert
coordinates from and to. For NIST P521 only 8 digits and 2 bytes will be
given per coordinate so that conversion from 9 digits does not work since
some bytes are missing. Therefore, regard the input (output)
arrays as byte arrays that need to be converted to digits (from digits).
Use ecc_digits_from_bytes to convert a byte array to digits and
ecc_digits_to_bytes to convert digits to a byte array.
crypt_ecdh_shared_secret creates 'rand_z' from 'nbytes' of random bytes.
Also convert this array to fill a byte array with 'nbytes' of random bytes
and create the rand_z digits from the byte array. The most significant
digit of rand_z needs to be adjusted to mask out unnecessary bits beyond
the 521 bits of NIST P521. Therefore, apply the appropriate mask to the
most significant digit keeping only the 9 most significant bits.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
crypto/ecc.c | 27 +++++++++++++++------------
crypto/ecdh.c | 26 +++++++++++++++-----------
include/crypto/internal/ecc.h | 10 +++++++---
3 files changed, 37 insertions(+), 26 deletions(-)
diff --git a/crypto/ecc.c b/crypto/ecc.c
index f643719450b8..ced77eb6e533 100644
--- a/crypto/ecc.c
+++ b/crypto/ecc.c
@@ -1542,7 +1542,8 @@ int ecc_gen_privkey(unsigned int curve_id, unsigned int ndigits, u64 *privkey)
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;
@@ -1570,8 +1571,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);
@@ -1641,14 +1642,14 @@ 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, u64 msd_mask)
{
int ret = 0;
struct ecc_point *product, *pk;
u64 priv[ECC_MAX_DIGITS];
u64 rand_z[ECC_MAX_DIGITS];
- unsigned int nbytes;
+ u8 tmp[ECC_MAX_DIGITS << ECC_DIGITS_TO_BYTES_SHIFT];
const struct ecc_curve *curve = ecc_get_curve(curve_id);
if (!private_key || !public_key || !curve ||
@@ -1657,9 +1658,10 @@ 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);
+ get_random_bytes(tmp, nbytes);
+ ecc_digits_from_bytes(tmp, nbytes, rand_z, ndigits);
+ if (msd_mask)
+ rand_z[ndigits - 1] &= msd_mask;
pk = ecc_alloc_point(ndigits);
if (!pk) {
@@ -1667,8 +1669,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;
@@ -1688,7 +1691,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(priv, sizeof(priv));
diff --git a/crypto/ecdh.c b/crypto/ecdh.c
index f187365db7b6..e64133428552 100644
--- a/crypto/ecdh.c
+++ b/crypto/ecdh.c
@@ -15,6 +15,8 @@
struct ecdh_ctx {
unsigned int curve_id;
unsigned int ndigits;
+ unsigned int nbytes;
+ u64 msd_mask;
u64 private_key[ECC_MAX_DIGITS];
};
@@ -28,7 +30,6 @@ static int ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
{
struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
u64 priv[ECC_MAX_DIGITS];
- unsigned int nbytes;
struct ecdh params;
if (crypto_ecdh_decode_key(buf, len, ¶ms) < 0 ||
@@ -39,10 +40,8 @@ static int ecdh_set_secret(struct crypto_kpp *tfm, const void *buf,
return ecc_gen_privkey(ctx->curve_id, ctx->ndigits,
ctx->private_key);
- nbytes = ctx->ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
-
- memcpy(ctx->private_key, params.key, nbytes);
- ecc_swap_digits(ctx->private_key, priv, ctx->ndigits);
+ ecc_digits_from_bytes(params.key, ctx->nbytes, priv, ctx->ndigits);
+ ecc_swap_digits(priv, ctx->private_key, ctx->ndigits);
if (ecc_is_key_valid(ctx->curve_id, ctx->ndigits,
priv, params.key_size) < 0) {
@@ -56,13 +55,13 @@ 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);
- u64 *public_key;
- u64 *shared_secret = NULL;
+ unsigned int nbytes = ctx->nbytes;
+ u8 *public_key;
+ u8 *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;
@@ -91,12 +90,14 @@ 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,
+ ctx->msd_mask);
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;
}
@@ -134,6 +135,7 @@ static int ecdh_nist_p192_init_tfm(struct crypto_kpp *tfm)
ctx->curve_id = ECC_CURVE_NIST_P192;
ctx->ndigits = ECC_CURVE_NIST_P192_DIGITS;
+ ctx->nbytes = ctx->ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
return 0;
}
@@ -159,6 +161,7 @@ static int ecdh_nist_p256_init_tfm(struct crypto_kpp *tfm)
ctx->curve_id = ECC_CURVE_NIST_P256;
ctx->ndigits = ECC_CURVE_NIST_P256_DIGITS;
+ ctx->nbytes = ctx->ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
return 0;
}
@@ -184,6 +187,7 @@ static int ecdh_nist_p384_init_tfm(struct crypto_kpp *tfm)
ctx->curve_id = ECC_CURVE_NIST_P384;
ctx->ndigits = ECC_CURVE_NIST_P384_DIGITS;
+ ctx->nbytes = ctx->ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
return 0;
}
diff --git a/include/crypto/internal/ecc.h b/include/crypto/internal/ecc.h
index 5d485d3221d3..328a82bd35c8 100644
--- a/include/crypto/internal/ecc.h
+++ b/include/crypto/internal/ecc.h
@@ -138,12 +138,14 @@ int ecc_gen_privkey(unsigned int curve_id, unsigned int ndigits, u64 *privkey);
* @ndigits: curve's number of digits
* @private_key: pregenerated private key for the given curve
* @public_key: buffer for storing the generated public key
+ * @nbytes: number of bytes per coordinate of 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
@@ -152,7 +154,9 @@ int ecc_make_pub_key(const unsigned int curve_id, unsigned int ndigits,
* @ndigits: curve's number of digits
* @private_key: private key of part A
* @public_key: public key of counterpart B
+ * @nbytes: number of bytes per coordinate of public key
* @secret: buffer for storing the calculated shared secret
+ * @msd_mask: optional mask to apply to the most significant digit
*
* Note: It is recommended that you hash the result of crypto_ecdh_shared_secret
* before using it for symmetric encryption or HMAC.
@@ -161,8 +165,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, u64 msd_mask);
/**
* ecc_is_pubkey_valid_partial() - Partial public key validation
--
2.43.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* [PATCH v2 14/14] crypto: ecdh - Add support for NIST P521 and add test case
2024-02-15 23:13 [PATCH v2 00/14] Add support for NIST P521 to ecdsa and ecdh Stefan Berger
` (12 preceding siblings ...)
2024-02-15 23:14 ` [PATCH v2 13/14] crypto: ecdh - Use functions to copy digits from and to byte array Stefan Berger
@ 2024-02-15 23:14 ` Stefan Berger
2024-02-16 19:27 ` [PATCH v2 00/14] Add support for NIST P521 to ecdsa and ecdh Simo Sorce
14 siblings, 0 replies; 21+ messages in thread
From: Stefan Berger @ 2024-02-15 23:14 UTC (permalink / raw)
To: keyrings, linux-crypto, herbert, davem
Cc: linux-kernel, saulo.alessandre, Stefan Berger
Implement ecdh support with NIST P521 and add a test case from RFC5903.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
crypto/ecdh.c | 34 +++++++++++++++
crypto/testmgr.c | 7 ++++
crypto/testmgr.h | 79 +++++++++++++++++++++++++++++++++++
include/crypto/internal/ecc.h | 1 +
4 files changed, 121 insertions(+)
diff --git a/crypto/ecdh.c b/crypto/ecdh.c
index e64133428552..be87832e172e 100644
--- a/crypto/ecdh.c
+++ b/crypto/ecdh.c
@@ -207,6 +207,32 @@ static struct kpp_alg ecdh_nist_p384 = {
},
};
+static int ecdh_nist_p521_init_tfm(struct crypto_kpp *tfm)
+{
+ struct ecdh_ctx *ctx = ecdh_get_ctx(tfm);
+
+ ctx->curve_id = ECC_CURVE_NIST_P521;
+ ctx->ndigits = ECC_CURVE_NIST_P521_DIGITS;
+ ctx->nbytes = DIV_ROUND_UP(521, 8);
+ ctx->msd_mask = 0x1ff;
+
+ return 0;
+}
+static struct kpp_alg ecdh_nist_p521 = {
+ .set_secret = ecdh_set_secret,
+ .generate_public_key = ecdh_compute_value,
+ .compute_shared_secret = ecdh_compute_value,
+ .max_size = ecdh_max_size,
+ .init = ecdh_nist_p521_init_tfm,
+ .base = {
+ .cra_name = "ecdh-nist-p521",
+ .cra_driver_name = "ecdh-nist-p521-generic",
+ .cra_priority = 100,
+ .cra_module = THIS_MODULE,
+ .cra_ctxsize = sizeof(struct ecdh_ctx),
+ },
+};
+
static bool ecdh_nist_p192_registered;
static int __init ecdh_init(void)
@@ -225,8 +251,15 @@ static int __init ecdh_init(void)
if (ret)
goto nist_p384_error;
+ ret = crypto_register_kpp(&ecdh_nist_p521);
+ if (ret)
+ goto nist_p521_error;
+
return 0;
+nist_p521_error:
+ crypto_unregister_kpp(&ecdh_nist_p384);
+
nist_p384_error:
crypto_unregister_kpp(&ecdh_nist_p256);
@@ -242,6 +275,7 @@ static void __exit ecdh_exit(void)
crypto_unregister_kpp(&ecdh_nist_p192);
crypto_unregister_kpp(&ecdh_nist_p256);
crypto_unregister_kpp(&ecdh_nist_p384);
+ crypto_unregister_kpp(&ecdh_nist_p521);
}
subsys_initcall(ecdh_init);
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 00f5a6cf341a..91f39f5a438b 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -5077,6 +5077,13 @@ static const struct alg_test_desc alg_test_descs[] = {
.suite = {
.kpp = __VECS(ecdh_p384_tv_template)
}
+ }, {
+ .alg = "ecdh-nist-p521",
+ .test = alg_test_kpp,
+ .fips_allowed = 1,
+ .suite = {
+ .kpp = __VECS(ecdh_p521_tv_template)
+ }
}, {
.alg = "ecdsa-nist-p192",
.test = alg_test_akcipher,
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 9bde04be8df9..dc9a2b30b5fd 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -4468,6 +4468,85 @@ static const struct kpp_testvec ecdh_p384_tv_template[] = {
}
};
+/*
+ * NIST P521 test vectors from RFC5903
+ */
+static const struct kpp_testvec ecdh_p521_tv_template[] = {
+ {
+ .secret =
+#ifdef __LITTLE_ENDIAN
+ "\x02\x00" /* type */
+ "\x48\x00" /* len */
+ "\x42\x00" /* key_size */
+#else
+ "\x00\x02" /* type */
+ "\x00\x48" /* len */
+ "\x00\x42" /* key_size */
+#endif
+ "\x00\x37\xAD\xE9\x31\x9A\x89\xF4"
+ "\xDA\xBD\xB3\xEF\x41\x1A\xAC\xCC"
+ "\xA5\x12\x3C\x61\xAC\xAB\x57\xB5"
+ "\x39\x3D\xCE\x47\x60\x81\x72\xA0"
+ "\x95\xAA\x85\xA3\x0F\xE1\xC2\x95"
+ "\x2C\x67\x71\xD9\x37\xBA\x97\x77"
+ "\xF5\x95\x7B\x26\x39\xBA\xB0\x72"
+ "\x46\x2F\x68\xC2\x7A\x57\x38\x2D"
+ "\x4A\x52",
+ .b_public =
+ "\x00\xD0\xB3\x97\x5A\xC4\xB7\x99"
+ "\xF5\xBE\xA1\x6D\x5E\x13\xE9\xAF"
+ "\x97\x1D\x5E\x9B\x98\x4C\x9F\x39"
+ "\x72\x8B\x5E\x57\x39\x73\x5A\x21"
+ "\x9B\x97\xC3\x56\x43\x6A\xDC\x6E"
+ "\x95\xBB\x03\x52\xF6\xBE\x64\xA6"
+ "\xC2\x91\x2D\x4E\xF2\xD0\x43\x3C"
+ "\xED\x2B\x61\x71\x64\x00\x12\xD9"
+ "\x46\x0F"
+ "\x01\x5C\x68\x22\x63\x83\x95\x6E"
+ "\x3B\xD0\x66\xE7\x97\xB6\x23\xC2"
+ "\x7C\xE0\xEA\xC2\xF5\x51\xA1\x0C"
+ "\x2C\x72\x4D\x98\x52\x07\x7B\x87"
+ "\x22\x0B\x65\x36\xC5\xC4\x08\xA1"
+ "\xD2\xAE\xBB\x8E\x86\xD6\x78\xAE"
+ "\x49\xCB\x57\x09\x1F\x47\x32\x29"
+ "\x65\x79\xAB\x44\xFC\xD1\x7F\x0F"
+ "\xC5\x6A",
+ .expected_a_public =
+ "\x00\x15\x41\x7E\x84\xDB\xF2\x8C"
+ "\x0A\xD3\xC2\x78\x71\x33\x49\xDC"
+ "\x7D\xF1\x53\xC8\x97\xA1\x89\x1B"
+ "\xD9\x8B\xAB\x43\x57\xC9\xEC\xBE"
+ "\xE1\xE3\xBF\x42\xE0\x0B\x8E\x38"
+ "\x0A\xEA\xE5\x7C\x2D\x10\x75\x64"
+ "\x94\x18\x85\x94\x2A\xF5\xA7\xF4"
+ "\x60\x17\x23\xC4\x19\x5D\x17\x6C"
+ "\xED\x3E"
+ "\x01\x7C\xAE\x20\xB6\x64\x1D\x2E"
+ "\xEB\x69\x57\x86\xD8\xC9\x46\x14"
+ "\x62\x39\xD0\x99\xE1\x8E\x1D\x5A"
+ "\x51\x4C\x73\x9D\x7C\xB4\xA1\x0A"
+ "\xD8\xA7\x88\x01\x5A\xC4\x05\xD7"
+ "\x79\x9D\xC7\x5E\x7B\x7D\x5B\x6C"
+ "\xF2\x26\x1A\x6A\x7F\x15\x07\x43"
+ "\x8B\xF0\x1B\xEB\x6C\xA3\x92\x6F"
+ "\x95\x82",
+ .expected_ss =
+ "\x01\x14\x4C\x7D\x79\xAE\x69\x56"
+ "\xBC\x8E\xDB\x8E\x7C\x78\x7C\x45"
+ "\x21\xCB\x08\x6F\xA6\x44\x07\xF9"
+ "\x78\x94\xE5\xE6\xB2\xD7\x9B\x04"
+ "\xD1\x42\x7E\x73\xCA\x4B\xAA\x24"
+ "\x0A\x34\x78\x68\x59\x81\x0C\x06"
+ "\xB3\xC7\x15\xA3\xA8\xCC\x31\x51"
+ "\xF2\xBE\xE4\x17\x99\x6D\x19\xF3"
+ "\xDD\xEA",
+ .secret_size = 72,
+ .b_public_size = 132,
+ .expected_a_public_size = 132,
+ .expected_ss_size = 66
+ }
+};
+
/*
* MD4 test vectors from RFC1320
*/
diff --git a/include/crypto/internal/ecc.h b/include/crypto/internal/ecc.h
index 328a82bd35c8..a04b313f2871 100644
--- a/include/crypto/internal/ecc.h
+++ b/include/crypto/internal/ecc.h
@@ -33,6 +33,7 @@
#define ECC_CURVE_NIST_P192_DIGITS 3
#define ECC_CURVE_NIST_P256_DIGITS 4
#define ECC_CURVE_NIST_P384_DIGITS 6
+#define ECC_CURVE_NIST_P521_DIGITS 9
#define ECC_MAX_DIGITS (576 / 64) /* due to NIST P521 */
#define ECC_DIGITS_TO_BYTES_SHIFT 3
--
2.43.0
^ permalink raw reply related [flat|nested] 21+ messages in thread* Re: [PATCH v2 00/14] Add support for NIST P521 to ecdsa and ecdh
2024-02-15 23:13 [PATCH v2 00/14] Add support for NIST P521 to ecdsa and ecdh Stefan Berger
` (13 preceding siblings ...)
2024-02-15 23:14 ` [PATCH v2 14/14] crypto: ecdh - Add support for NIST P521 and add test case Stefan Berger
@ 2024-02-16 19:27 ` Simo Sorce
2024-02-16 19:32 ` Stefan Berger
14 siblings, 1 reply; 21+ messages in thread
From: Simo Sorce @ 2024-02-16 19:27 UTC (permalink / raw)
To: Stefan Berger, keyrings, linux-crypto, herbert, davem
Cc: linux-kernel, saulo.alessandre
On Thu, 2024-02-15 at 18:13 -0500, Stefan Berger wrote:
> This series of patches adds support for the NIST P521 curve to ecdsa and
> ecdh. Test cases for NIST P521 are added to both modules.
>
> An issue with the current code in ecdsa and ecdh is that it assumes that
> input arrays providing key coordinates for example, are arrays of digits
> (a 'digit' is a 'u64'). This works well for all currently supported
> curves, such as NIST P192/256/384, but does not work for NIST P521 where
> coordinates are 8 digits + 2 bytes long. So some of the changes deal with
> converting byte arrays to digits and digits to byte arrays.
>
>
> Regards,
> Stefan
>
> v2:
> - Reformulated some patch descriptions
> - Fixed issue detected by krobot
> - Some other small changes to the code
>
> Stefan Berger (14):
> crypto: ecdsa - Convert byte arrays with key coordinates to digits
> crypto: ecdsa - Adjust tests on length of key parameters
> crypto: ecdsa - Extend res.x mod n calculation for NIST P521
> crypto: ecc - Implement vli_mmod_fast_521 for NIST p521
> crypto: ecc - For NIST P521 use vli_num_bits to get number of bits
> crypto: ecc - Add NIST P521 curve parameters
> crypto: ecdsa - Register NIST P521 and extend test suite
> x509: Add OID for NIST P521 and extend parser for it
> crypto: ecdh - Use properly formatted digits to check for valid key
> crypto: ecc - Implement ecc_digits_to_bytes to convert digits to byte
> array
> crypto: Add nbits field to ecc_curve structure
> 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 array
> crypto: ecdh - Add support for NIST P521 and add test case
>
> crypto/asymmetric_keys/x509_cert_parser.c | 3 +
> crypto/ecc.c | 71 +++++--
> crypto/ecc_curve_defs.h | 45 +++++
> crypto/ecdh.c | 59 +++++-
> crypto/ecdsa.c | 48 ++++-
> crypto/testmgr.c | 14 ++
> crypto/testmgr.h | 225 ++++++++++++++++++++++
> include/crypto/ecc_curve.h | 3 +
> include/crypto/ecdh.h | 1 +
> include/crypto/internal/ecc.h | 61 +++++-
> include/linux/oid_registry.h | 1 +
> 11 files changed, 495 insertions(+), 36 deletions(-)
Hi Stefan,
what kind of side-channel testing was performed on this code?
And what is the use case you are adding it for?
Thanks,
Simo.
--
Simo Sorce
Distinguished Engineer
RHEL Crypto Team
Red Hat, Inc
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH v2 00/14] Add support for NIST P521 to ecdsa and ecdh
2024-02-16 19:27 ` [PATCH v2 00/14] Add support for NIST P521 to ecdsa and ecdh Simo Sorce
@ 2024-02-16 19:32 ` Stefan Berger
2024-02-16 19:40 ` Simo Sorce
0 siblings, 1 reply; 21+ messages in thread
From: Stefan Berger @ 2024-02-16 19:32 UTC (permalink / raw)
To: Simo Sorce, keyrings, linux-crypto, herbert, davem
Cc: linux-kernel, saulo.alessandre
On 2/16/24 14:27, Simo Sorce wrote:
> On Thu, 2024-02-15 at 18:13 -0500, Stefan Berger wrote:
>> This series of patches adds support for the NIST P521 curve to ecdsa and
>> ecdh. Test cases for NIST P521 are added to both modules.
>>
>> An issue with the current code in ecdsa and ecdh is that it assumes that
>> input arrays providing key coordinates for example, are arrays of digits
>> (a 'digit' is a 'u64'). This works well for all currently supported
>> curves, such as NIST P192/256/384, but does not work for NIST P521 where
>> coordinates are 8 digits + 2 bytes long. So some of the changes deal with
>> converting byte arrays to digits and digits to byte arrays.
>>
>>
>> Regards,
>> Stefan
>>
>> v2:
>> - Reformulated some patch descriptions
>> - Fixed issue detected by krobot
>> - Some other small changes to the code
>>
>> Stefan Berger (14):
>> crypto: ecdsa - Convert byte arrays with key coordinates to digits
>> crypto: ecdsa - Adjust tests on length of key parameters
>> crypto: ecdsa - Extend res.x mod n calculation for NIST P521
>> crypto: ecc - Implement vli_mmod_fast_521 for NIST p521
>> crypto: ecc - For NIST P521 use vli_num_bits to get number of bits
>> crypto: ecc - Add NIST P521 curve parameters
>> crypto: ecdsa - Register NIST P521 and extend test suite
>> x509: Add OID for NIST P521 and extend parser for it
>> crypto: ecdh - Use properly formatted digits to check for valid key
>> crypto: ecc - Implement ecc_digits_to_bytes to convert digits to byte
>> array
>> crypto: Add nbits field to ecc_curve structure
>> 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 array
>> crypto: ecdh - Add support for NIST P521 and add test case
>>
>> crypto/asymmetric_keys/x509_cert_parser.c | 3 +
>> crypto/ecc.c | 71 +++++--
>> crypto/ecc_curve_defs.h | 45 +++++
>> crypto/ecdh.c | 59 +++++-
>> crypto/ecdsa.c | 48 ++++-
>> crypto/testmgr.c | 14 ++
>> crypto/testmgr.h | 225 ++++++++++++++++++++++
>> include/crypto/ecc_curve.h | 3 +
>> include/crypto/ecdh.h | 1 +
>> include/crypto/internal/ecc.h | 61 +++++-
>> include/linux/oid_registry.h | 1 +
>> 11 files changed, 495 insertions(+), 36 deletions(-)
>
> Hi Stefan,
> what kind of side-channel testing was performed on this code?
> And what is the use case you are adding it for?
We're using public keys for signature verification. I am not aware that
public key usage is critical to side channels.
The use case for adding it is primarily driven by closing a gap to
complete the support for the common ECDSA NIST curves.
Stefan
>
> Thanks,
> Simo.
>
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH v2 00/14] Add support for NIST P521 to ecdsa and ecdh
2024-02-16 19:32 ` Stefan Berger
@ 2024-02-16 19:40 ` Simo Sorce
2024-02-19 14:40 ` Stefan Berger
0 siblings, 1 reply; 21+ messages in thread
From: Simo Sorce @ 2024-02-16 19:40 UTC (permalink / raw)
To: Stefan Berger, keyrings, linux-crypto, herbert, davem
Cc: linux-kernel, saulo.alessandre
On Fri, 2024-02-16 at 14:32 -0500, Stefan Berger wrote:
>
> On 2/16/24 14:27, Simo Sorce wrote:
> > On Thu, 2024-02-15 at 18:13 -0500, Stefan Berger wrote:
> > > This series of patches adds support for the NIST P521 curve to ecdsa and
> > > ecdh. Test cases for NIST P521 are added to both modules.
> > >
> > > An issue with the current code in ecdsa and ecdh is that it assumes that
> > > input arrays providing key coordinates for example, are arrays of digits
> > > (a 'digit' is a 'u64'). This works well for all currently supported
> > > curves, such as NIST P192/256/384, but does not work for NIST P521 where
> > > coordinates are 8 digits + 2 bytes long. So some of the changes deal with
> > > converting byte arrays to digits and digits to byte arrays.
> > >
> > >
> > > Regards,
> > > Stefan
> > >
> > > v2:
> > > - Reformulated some patch descriptions
> > > - Fixed issue detected by krobot
> > > - Some other small changes to the code
> > >
> > > Stefan Berger (14):
> > > crypto: ecdsa - Convert byte arrays with key coordinates to digits
> > > crypto: ecdsa - Adjust tests on length of key parameters
> > > crypto: ecdsa - Extend res.x mod n calculation for NIST P521
> > > crypto: ecc - Implement vli_mmod_fast_521 for NIST p521
> > > crypto: ecc - For NIST P521 use vli_num_bits to get number of bits
> > > crypto: ecc - Add NIST P521 curve parameters
> > > crypto: ecdsa - Register NIST P521 and extend test suite
> > > x509: Add OID for NIST P521 and extend parser for it
> > > crypto: ecdh - Use properly formatted digits to check for valid key
> > > crypto: ecc - Implement ecc_digits_to_bytes to convert digits to byte
> > > array
> > > crypto: Add nbits field to ecc_curve structure
> > > 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 array
> > > crypto: ecdh - Add support for NIST P521 and add test case
> > >
> > > crypto/asymmetric_keys/x509_cert_parser.c | 3 +
> > > crypto/ecc.c | 71 +++++--
> > > crypto/ecc_curve_defs.h | 45 +++++
> > > crypto/ecdh.c | 59 +++++-
> > > crypto/ecdsa.c | 48 ++++-
> > > crypto/testmgr.c | 14 ++
> > > crypto/testmgr.h | 225 ++++++++++++++++++++++
> > > include/crypto/ecc_curve.h | 3 +
> > > include/crypto/ecdh.h | 1 +
> > > include/crypto/internal/ecc.h | 61 +++++-
> > > include/linux/oid_registry.h | 1 +
> > > 11 files changed, 495 insertions(+), 36 deletions(-)
> >
> > Hi Stefan,
> > what kind of side-channel testing was performed on this code?
> > And what is the use case you are adding it for?
>
> We're using public keys for signature verification. I am not aware that
> public key usage is critical to side channels.
>
> The use case for adding it is primarily driven by closing a gap to
> complete the support for the common ECDSA NIST curves.
Is there an assumption the ECDH code uses exclusively ephemeral keys?
Simo.
--
Simo Sorce
Distinguished Engineer
RHEL Crypto Team
Red Hat, Inc
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v2 00/14] Add support for NIST P521 to ecdsa and ecdh
2024-02-16 19:40 ` Simo Sorce
@ 2024-02-19 14:40 ` Stefan Berger
0 siblings, 0 replies; 21+ messages in thread
From: Stefan Berger @ 2024-02-19 14:40 UTC (permalink / raw)
To: Simo Sorce, keyrings, linux-crypto, herbert, davem
Cc: linux-kernel, saulo.alessandre
On 2/16/24 14:40, Simo Sorce wrote:
> On Fri, 2024-02-16 at 14:32 -0500, Stefan Berger wrote:
>>
>> On 2/16/24 14:27, Simo Sorce wrote:
>>> On Thu, 2024-02-15 at 18:13 -0500, Stefan Berger wrote:
>>>> This series of patches adds support for the NIST P521 curve to ecdsa and
>>>> ecdh. Test cases for NIST P521 are added to both modules.
>>>>
>>>> An issue with the current code in ecdsa and ecdh is that it assumes that
>>>> input arrays providing key coordinates for example, are arrays of digits
>>>> (a 'digit' is a 'u64'). This works well for all currently supported
>>>> curves, such as NIST P192/256/384, but does not work for NIST P521 where
>>>> coordinates are 8 digits + 2 bytes long. So some of the changes deal with
>>>> converting byte arrays to digits and digits to byte arrays.
>>>>
>>>>
>>>> Regards,
>>>> Stefan
>>>>
>>>> v2:
>>>> - Reformulated some patch descriptions
>>>> - Fixed issue detected by krobot
>>>> - Some other small changes to the code
>>>>
>>>> Stefan Berger (14):
>>>> crypto: ecdsa - Convert byte arrays with key coordinates to digits
>>>> crypto: ecdsa - Adjust tests on length of key parameters
>>>> crypto: ecdsa - Extend res.x mod n calculation for NIST P521
>>>> crypto: ecc - Implement vli_mmod_fast_521 for NIST p521
>>>> crypto: ecc - For NIST P521 use vli_num_bits to get number of bits
>>>> crypto: ecc - Add NIST P521 curve parameters
>>>> crypto: ecdsa - Register NIST P521 and extend test suite
>>>> x509: Add OID for NIST P521 and extend parser for it
>>>> crypto: ecdh - Use properly formatted digits to check for valid key
>>>> crypto: ecc - Implement ecc_digits_to_bytes to convert digits to byte
>>>> array
>>>> crypto: Add nbits field to ecc_curve structure
>>>> 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 array
>>>> crypto: ecdh - Add support for NIST P521 and add test case
>>>>
>>>> crypto/asymmetric_keys/x509_cert_parser.c | 3 +
>>>> crypto/ecc.c | 71 +++++--
>>>> crypto/ecc_curve_defs.h | 45 +++++
>>>> crypto/ecdh.c | 59 +++++-
>>>> crypto/ecdsa.c | 48 ++++-
>>>> crypto/testmgr.c | 14 ++
>>>> crypto/testmgr.h | 225 ++++++++++++++++++++++
>>>> include/crypto/ecc_curve.h | 3 +
>>>> include/crypto/ecdh.h | 1 +
>>>> include/crypto/internal/ecc.h | 61 +++++-
>>>> include/linux/oid_registry.h | 1 +
>>>> 11 files changed, 495 insertions(+), 36 deletions(-)
>>>
>>> Hi Stefan,
>>> what kind of side-channel testing was performed on this code?
>>> And what is the use case you are adding it for?
>>
>> We're using public keys for signature verification. I am not aware that
>> public key usage is critical to side channels.
>>
>> The use case for adding it is primarily driven by closing a gap to
>> complete the support for the common ECDSA NIST curves.
>
> Is there an assumption the ECDH code uses exclusively ephemeral keys?
>
It can use both, provided keys and ephemeral keys. I think at this point
it's best to drop ecdh support from this series.
Stefan
> Simo.
>
^ permalink raw reply [flat|nested] 21+ messages in thread