]> www.infradead.org Git - users/hch/block.git/commitdiff
crypto: ecc - Implement vli_mmod_fast_521 for NIST p521
authorStefan Berger <stefanb@linux.ibm.com>
Thu, 4 Apr 2024 14:18:49 +0000 (10:18 -0400)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 12 Apr 2024 07:07:52 +0000 (15:07 +0800)
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
the vli digit array provides enough elements to fit the larger integers
required by this curve.

Tested-by: Lukas Wunner <lukas@wunner.de>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
crypto/ecc.c
include/crypto/internal/ecc.h

index e94183f6c41867299820af4816db658507f84836..8914e437f94b8bc136b93206b32b89172514a24f 100644 (file)
@@ -902,6 +902,28 @@ 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" section G.1.4
+ */
+static void vli_mmod_fast_521(u64 *result, const u64 *product,
+                             const u64 *curve_prime, u64 *tmp)
+{
+       const unsigned int ndigits = ECC_CURVE_NIST_P521_DIGITS;
+       size_t i;
+
+       /* Initialize result with lowest 521 bits from product */
+       vli_set(result, product, ndigits);
+       result[8] &= 0x1ff;
+
+       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 +963,9 @@ static bool vli_mmod_fast(u64 *result, u64 *product,
        case ECC_CURVE_NIST_P384_DIGITS:
                vli_mmod_fast_384(result, product, curve_prime, tmp);
                break;
+       case ECC_CURVE_NIST_P521_DIGITS:
+               vli_mmod_fast_521(result, product, curve_prime, tmp);
+               break;
        default:
                pr_err_ratelimited("ecc: unsupported digits size!\n");
                return false;
index ab722a8986b7644d9198bd0eeb2927045b27613f..4e2f5f938e91a82a2afd49c3326b502eaeb2f859 100644 (file)
@@ -33,7 +33,8 @@
 #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_CURVE_NIST_P521_DIGITS  9
+#define ECC_MAX_DIGITS              DIV_ROUND_UP(521, 64) /* NIST P521 */
 
 #define ECC_DIGITS_TO_BYTES_SHIFT 3