Torsten Duwe 89425d
Git-commit: ea169a30a6bf6782a05a51d2b9cf73db151eab8b
Torsten Duwe 89425d
From: Stephan Mueller <smueller@chronox.de>
Torsten Duwe 89425d
Date: Mon, 25 Jun 2018 12:00:18 +0200
Torsten Duwe 89425d
Subject: [PATCH] crypto: ecdh - add public key verification test
Torsten Duwe 89425d
Patch-mainline: v4.19-rc1
Torsten Duwe 89425d
References: bsc#1155331
Torsten Duwe 89425d
Torsten Duwe 89425d
According to SP800-56A section 5.6.2.1, the public key to be processed
Torsten Duwe 89425d
for the ECDH operation shall be checked for appropriateness. When the
Torsten Duwe 89425d
public key is considered to be an ephemeral key, the partial validation
Torsten Duwe 89425d
test as defined in SP800-56A section 5.6.2.3.4 can be applied.
Torsten Duwe 89425d
Torsten Duwe 89425d
The partial verification test requires the presence of the field
Torsten Duwe 89425d
elements of a and b. For the implemented NIST curves, b is defined in
Torsten Duwe 89425d
FIPS 186-4 appendix D.1.2. The element a is implicitly given with the
Torsten Duwe 89425d
Weierstrass equation given in D.1.2 where a = p - 3.
Torsten Duwe 89425d
Torsten Duwe 89425d
Without the test, the NIST ACVP testing fails. After adding this check,
Torsten Duwe 89425d
the NIST ACVP testing passes.
Torsten Duwe 89425d
Torsten Duwe 89425d
Signed-off-by: Stephan Mueller <smueller@chronox.de>
Torsten Duwe 89425d
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Torsten Duwe 89425d
Signed-off-by: Torsten Duwe <duwe@suse.de>
Torsten Duwe 89425d
---
Torsten Duwe 89425d
 crypto/ecc.c            | 42 ++++++++++++++++++++++++++++++++++++++----
Torsten Duwe 89425d
 crypto/ecc_curve_defs.h | 22 ++++++++++++++++++----
Torsten Duwe 89425d
 2 files changed, 56 insertions(+), 8 deletions(-)
Torsten Duwe 89425d
Torsten Duwe 89425d
--- a/crypto/ecc.c
Torsten Duwe 89425d
+++ b/crypto/ecc.c
Torsten Duwe 89425d
@@ -966,6 +966,36 @@ out:
Torsten Duwe 89425d
 	return ret;
Torsten Duwe 89425d
 }
Torsten Duwe 89425d
 
Torsten Duwe 89425d
+/* SP800-56A section 5.6.2.3.4 partial verification: ephemeral keys only */
Torsten Duwe 89425d
+static int ecc_is_pubkey_valid_partial(const struct ecc_curve *curve,
Torsten Duwe 89425d
+				       struct ecc_point *pk)
Torsten Duwe 89425d
+{
Torsten Duwe 89425d
+	u64 yy[ECC_MAX_DIGITS], xxx[ECC_MAX_DIGITS], w[ECC_MAX_DIGITS];
Torsten Duwe 89425d
+
Torsten Duwe 89425d
+	/* Check 1: Verify key is not the zero point. */
Torsten Duwe 89425d
+	if (ecc_point_is_zero(pk))
Torsten Duwe 89425d
+		return -EINVAL;
Torsten Duwe 89425d
+
Torsten Duwe 89425d
+	/* Check 2: Verify key is in the range [1, p-1]. */
Torsten Duwe 89425d
+	if (vli_cmp(curve->p, pk->x, pk->ndigits) != 1)
Torsten Duwe 89425d
+		return -EINVAL;
Torsten Duwe 89425d
+	if (vli_cmp(curve->p, pk->y, pk->ndigits) != 1)
Torsten Duwe 89425d
+		return -EINVAL;
Torsten Duwe 89425d
+
Torsten Duwe 89425d
+	/* Check 3: Verify that y^2 == (x^3 + a路x + b) mod p */
Torsten Duwe 89425d
+	vli_mod_square_fast(yy, pk->y, curve->p, pk->ndigits); /* y^2 */
Torsten Duwe 89425d
+	vli_mod_square_fast(xxx, pk->x, curve->p, pk->ndigits); /* x^2 */
Torsten Duwe 89425d
+	vli_mod_mult_fast(xxx, xxx, pk->x, curve->p, pk->ndigits); /* x^3 */
Torsten Duwe 89425d
+	vli_mod_mult_fast(w, curve->a, pk->x, curve->p, pk->ndigits); /* a路x */
Torsten Duwe 89425d
+	vli_mod_add(w, w, curve->b, curve->p, pk->ndigits); /* a路x + b */
Torsten Duwe 89425d
+	vli_mod_add(w, w, xxx, curve->p, pk->ndigits); /* x^3 + a路x + b */
Torsten Duwe 89425d
+	if (vli_cmp(yy, w, pk->ndigits) != 0) /* Equation */
Torsten Duwe 89425d
+		return -EINVAL;
Torsten Duwe 89425d
+
Torsten Duwe 89425d
+	return 0;
Torsten Duwe 89425d
+
Torsten Duwe 89425d
+}
Torsten Duwe 89425d
+
Torsten Duwe 89425d
 int crypto_ecdh_shared_secret(unsigned int curve_id, unsigned int ndigits,
Torsten Duwe 89425d
 		       const u8 *private_key, unsigned int private_key_len,
Torsten Duwe 89425d
 		       const u8 *public_key, unsigned int public_key_len,
Torsten Duwe 89425d
@@ -993,16 +1023,20 @@ int crypto_ecdh_shared_secret(unsigned i
Torsten Duwe 89425d
 		goto out;
Torsten Duwe 89425d
 	}
Torsten Duwe 89425d
 
Torsten Duwe 89425d
+	ecc_swap_digits((const u64 *)public_key, pk->x, ndigits);
Torsten Duwe 89425d
+	ecc_swap_digits((const u64 *)&public_key[nbytes], pk->y, ndigits);
Torsten Duwe 89425d
+	ret = ecc_is_pubkey_valid_partial(curve, pk);
Torsten Duwe 89425d
+	if (ret)
Torsten Duwe 89425d
+		goto err_alloc_product;
Torsten Duwe 89425d
+
Torsten Duwe 89425d
+	ecc_swap_digits((const u64 *)private_key, priv, ndigits);
Torsten Duwe 89425d
+
Torsten Duwe 89425d
 	product = ecc_alloc_point(ndigits);
Torsten Duwe 89425d
 	if (!product) {
Torsten Duwe 89425d
 		ret = -ENOMEM;
Torsten Duwe 89425d
 		goto err_alloc_product;
Torsten Duwe 89425d
 	}
Torsten Duwe 89425d
 
Torsten Duwe 89425d
-	ecc_swap_digits((const u64 *)public_key, pk->x, ndigits);
Torsten Duwe 89425d
-	ecc_swap_digits((const u64 *)&public_key[nbytes], pk->y, ndigits);
Torsten Duwe 89425d
-	ecc_swap_digits((const u64 *)private_key, priv, ndigits);
Torsten Duwe 89425d
-
Torsten Duwe 89425d
 	ecc_point_mult(product, pk, priv, rand_z, curve->p, ndigits);
Torsten Duwe 89425d
 
Torsten Duwe 89425d
 	ecc_swap_digits(product->x, (u64 *)secret, ndigits);
Torsten Duwe 89425d
--- a/crypto/ecc_curve_defs.h
Torsten Duwe 89425d
+++ b/crypto/ecc_curve_defs.h
Torsten Duwe 89425d
@@ -12,9 +12,11 @@ struct ecc_curve {
Torsten Duwe 89425d
 	struct ecc_point g;
Torsten Duwe 89425d
 	u64 *p;
Torsten Duwe 89425d
 	u64 *n;
Torsten Duwe 89425d
+	u64 *a;
Torsten Duwe 89425d
+	u64 *b;
Torsten Duwe 89425d
 };
Torsten Duwe 89425d
 
Torsten Duwe 89425d
-/* NIST P-192 */
Torsten Duwe 89425d
+/* NIST P-192: a = p - 3 */
Torsten Duwe 89425d
 static u64 nist_p192_g_x[] = { 0xF4FF0AFD82FF1012ull, 0x7CBF20EB43A18800ull,
Torsten Duwe 89425d
 				0x188DA80EB03090F6ull };
Torsten Duwe 89425d
 static u64 nist_p192_g_y[] = { 0x73F977A11E794811ull, 0x631011ED6B24CDD5ull,
Torsten Duwe 89425d
@@ -23,6 +25,10 @@ static u64 nist_p192_p[] = { 0xFFFFFFFFF
Torsten Duwe 89425d
 				0xFFFFFFFFFFFFFFFFull };
Torsten Duwe 89425d
 static u64 nist_p192_n[] = { 0x146BC9B1B4D22831ull, 0xFFFFFFFF99DEF836ull,
Torsten Duwe 89425d
 				0xFFFFFFFFFFFFFFFFull };
Torsten Duwe 89425d
+static u64 nist_p192_a[] = { 0xFFFFFFFFFFFFFFFCull, 0xFFFFFFFFFFFFFFFEull,
Torsten Duwe 89425d
+				0xFFFFFFFFFFFFFFFEull };
Torsten Duwe 89425d
+static u64 nist_p192_b[] = { 0xFEB8DEECC146B9B1ull, 0x0FA7E9AB72243049ull,
Torsten Duwe 89425d
+				0x64210519E59C80E7ull };
Torsten Duwe 89425d
 static struct ecc_curve nist_p192 = {
Torsten Duwe 89425d
 	.name = "nist_192",
Torsten Duwe 89425d
 	.g = {
Torsten Duwe 89425d
@@ -31,10 +37,12 @@ static struct ecc_curve nist_p192 = {
Torsten Duwe 89425d
 		.ndigits = 3,
Torsten Duwe 89425d
 	},
Torsten Duwe 89425d
 	.p = nist_p192_p,
Torsten Duwe 89425d
-	.n = nist_p192_n
Torsten Duwe 89425d
+	.n = nist_p192_n,
Torsten Duwe 89425d
+	.a = nist_p192_a,
Torsten Duwe 89425d
+	.b = nist_p192_b
Torsten Duwe 89425d
 };
Torsten Duwe 89425d
 
Torsten Duwe 89425d
-/* NIST P-256 */
Torsten Duwe 89425d
+/* NIST P-256: a = p - 3 */
Torsten Duwe 89425d
 static u64 nist_p256_g_x[] = { 0xF4A13945D898C296ull, 0x77037D812DEB33A0ull,
Torsten Duwe 89425d
 				0xF8BCE6E563A440F2ull, 0x6B17D1F2E12C4247ull };
Torsten Duwe 89425d
 static u64 nist_p256_g_y[] = { 0xCBB6406837BF51F5ull, 0x2BCE33576B315ECEull,
Torsten Duwe 89425d
@@ -43,6 +51,10 @@ static u64 nist_p256_p[] = { 0xFFFFFFFFF
Torsten Duwe 89425d
 				0x0000000000000000ull, 0xFFFFFFFF00000001ull };
Torsten Duwe 89425d
 static u64 nist_p256_n[] = { 0xF3B9CAC2FC632551ull, 0xBCE6FAADA7179E84ull,
Torsten Duwe 89425d
 				0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFF00000000ull };
Torsten Duwe 89425d
+static u64 nist_p256_a[] = { 0xFFFFFFFFFFFFFFFCull, 0x00000000FFFFFFFFull,
Torsten Duwe 89425d
+				0x0000000000000000ull, 0xFFFFFFFF00000001ull };
Torsten Duwe 89425d
+static u64 nist_p256_b[] = { 0x3BCE3C3E27D2604Bull, 0x651D06B0CC53B0F6ull,
Torsten Duwe 89425d
+				0xB3EBBD55769886BCull, 0x5AC635D8AA3A93E7ull };
Torsten Duwe 89425d
 static struct ecc_curve nist_p256 = {
Torsten Duwe 89425d
 	.name = "nist_256",
Torsten Duwe 89425d
 	.g = {
Torsten Duwe 89425d
@@ -51,7 +63,9 @@ static struct ecc_curve nist_p256 = {
Torsten Duwe 89425d
 		.ndigits = 4,
Torsten Duwe 89425d
 	},
Torsten Duwe 89425d
 	.p = nist_p256_p,
Torsten Duwe 89425d
-	.n = nist_p256_n
Torsten Duwe 89425d
+	.n = nist_p256_n,
Torsten Duwe 89425d
+	.a = nist_p256_a,
Torsten Duwe 89425d
+	.b = nist_p256_b
Torsten Duwe 89425d
 };
Torsten Duwe 89425d
 
Torsten Duwe 89425d
 #endif