Petr Tesarik 1b908a
From: =?UTF-8?q?Stephan=20M=C3=BCller?= <smueller@chronox.de>
Petr Tesarik 1b908a
Date: Mon, 20 Jul 2020 19:09:23 +0200
Petr Tesarik 1b908a
Subject: crypto: ecc - SP800-56A rev 3 local public key validation
Petr Tesarik 1b908a
Git-commit: 6914dd53eb7af7cbc66edf7992d600b1e952c40d
Petr Tesarik 1b908a
Patch-mainline: v5.9-rc1
Petr Tesarik 1b908a
References: bsc#1175718
Petr Tesarik 1b908a
Petr Tesarik 1b908a
After the generation of a local public key, SP800-56A rev 3 section
Petr Tesarik 1b908a
5.6.2.1.3 mandates a validation of that key with a full validation
Petr Tesarik 1b908a
compliant to section 5.6.2.3.3.
Petr Tesarik 1b908a
Petr Tesarik 1b908a
Only if the full validation passes, the key is allowed to be used.
Petr Tesarik 1b908a
Petr Tesarik 1b908a
The patch adds the full key validation compliant to 5.6.2.3.3 and
Petr Tesarik 1b908a
performs the required check on the generated public key.
Petr Tesarik 1b908a
Petr Tesarik 1b908a
Signed-off-by: Stephan Mueller <smueller@chronox.de>
Petr Tesarik 1b908a
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Petr Tesarik 1b908a
[ ptesarik: The export is needed only to share the routines with ecrdsa.
Petr Tesarik 1b908a
  SLE15 does not have the ecrdsa module, so the added function should be
Petr Tesarik 1b908a
  local to crypto/ecc.c. ]
Petr Tesarik 1b908a
Signed-off-by: Petr Tesarik <ptesarik@suse.com>
Petr Tesarik 1b908a
---
Petr Tesarik 1b908a
 crypto/ecc.c |   34 +++++++++++++++++++++++++++++++++-
Petr Tesarik 1b908a
 1 file changed, 33 insertions(+), 1 deletion(-)
Petr Tesarik 1b908a
Petr Tesarik 1b908a
--- a/crypto/ecc.c
Petr Tesarik 1b908a
+++ b/crypto/ecc.c
Petr Tesarik 1b908a
@@ -42,6 +42,9 @@ typedef struct {
Petr Tesarik 1b908a
 	u64 m_high;
Petr Tesarik 1b908a
 } uint128_t;
Petr Tesarik 1b908a
 
Petr Tesarik 1b908a
+static int ecc_is_pubkey_valid_full(const struct ecc_curve *curve,
Petr Tesarik 1b908a
+				    struct ecc_point *pk);
Petr Tesarik 1b908a
+
Petr Tesarik 1b908a
 static inline const struct ecc_curve *ecc_get_curve(unsigned int curve_id)
Petr Tesarik 1b908a
 {
Petr Tesarik 1b908a
 	switch (curve_id) {
Petr Tesarik 1b908a
@@ -1404,7 +1407,9 @@ int ecc_make_pub_key(unsigned int curve_
Petr Tesarik 1b908a
 	}
Petr Tesarik 1b908a
 
Petr Tesarik 1b908a
 	ecc_point_mult(pk, &curve->g, priv, NULL, curve, ndigits);
Petr Tesarik 1b908a
-	if (ecc_point_is_zero(pk)) {
Petr Tesarik 1b908a
+
Petr Tesarik 1b908a
+	/* SP800-56A rev 3 5.6.2.1.3 key check */
Petr Tesarik 1b908a
+	if (ecc_is_pubkey_valid_full(curve, pk)) {
Petr Tesarik 1b908a
 		ret = -EAGAIN;
Petr Tesarik 1b908a
 		goto err_free_point;
Petr Tesarik 1b908a
 	}
Petr Tesarik 1b908a
@@ -1452,6 +1457,33 @@ int ecc_is_pubkey_valid_partial(const st
Petr Tesarik 1b908a
 }
Petr Tesarik 1b908a
 EXPORT_SYMBOL(ecc_is_pubkey_valid_partial);
Petr Tesarik 1b908a
 
Petr Tesarik 1b908a
+/* SP800-56A section 5.6.2.3.3 full verification */
Petr Tesarik 1b908a
+static int ecc_is_pubkey_valid_full(const struct ecc_curve *curve,
Petr Tesarik 1b908a
+				    struct ecc_point *pk)
Petr Tesarik 1b908a
+{
Petr Tesarik 1b908a
+	struct ecc_point *nQ;
Petr Tesarik 1b908a
+
Petr Tesarik 1b908a
+	/* Checks 1 through 3 */
Petr Tesarik 1b908a
+	int ret = ecc_is_pubkey_valid_partial(curve, pk);
Petr Tesarik 1b908a
+
Petr Tesarik 1b908a
+	if (ret)
Petr Tesarik 1b908a
+		return ret;
Petr Tesarik 1b908a
+
Petr Tesarik 1b908a
+	/* Check 4: Verify that nQ is the zero point. */
Petr Tesarik 1b908a
+	nQ = ecc_alloc_point(pk->ndigits);
Petr Tesarik 1b908a
+	if (!nQ)
Petr Tesarik 1b908a
+		return -ENOMEM;
Petr Tesarik 1b908a
+
Petr Tesarik 1b908a
+	ecc_point_mult(nQ, pk, curve->n, NULL, curve, pk->ndigits);
Petr Tesarik 1b908a
+	if (!ecc_point_is_zero(nQ))
Petr Tesarik 1b908a
+		ret = -EINVAL;
Petr Tesarik 1b908a
+
Petr Tesarik 1b908a
+	ecc_free_point(nQ);
Petr Tesarik 1b908a
+
Petr Tesarik 1b908a
+	return ret;
Petr Tesarik 1b908a
+}
Petr Tesarik 1b908a
+EXPORT_SYMBOL(ecc_is_pubkey_valid_full);
Petr Tesarik 1b908a
+
Petr Tesarik 1b908a
 int crypto_ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits,
Petr Tesarik 1b908a
 			      const u64 *private_key, const u64 *public_key,
Petr Tesarik 1b908a
 			      u64 *secret)