File 0002-ecdh-check-validity-of-P-before-export.patch of Package gnutls.31638

From 13202600d3e42258d8758b05ff45a3e3d0f07e4e Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@gnu.org>
Date: Fri, 10 Jul 2020 09:42:30 +0200
Subject: [PATCH 2/5] ecdh: check validity of P before export

SP800-56A rev3 section 5.7.1.2 step 2 mandates that the validity of
the calculated shared secret is verified before the data is returned
to the caller.  This patch adds the validation check.

Suggested by Stephan Mueller.

Signed-off-by: Daiki Ueno <ueno@gnu.org>
---
 lib/nettle/pk.c | 27 +++++++++++++++++++++------
 1 file changed, 21 insertions(+), 6 deletions(-)

Index: gnutls-3.6.7/lib/nettle/pk.c
===================================================================
--- gnutls-3.6.7.orig/lib/nettle/pk.c	2020-09-03 14:20:20.153197979 +0200
+++ gnutls-3.6.7/lib/nettle/pk.c	2020-09-03 14:20:25.165229513 +0200
@@ -199,25 +199,38 @@ _gost_params_to_pubkey(const gnutls_pk_p
 }
 #endif
 
-static void
+static int
 ecc_shared_secret(struct ecc_scalar *private_key,
 		  struct ecc_point *public_key, void *out, unsigned size)
 {
 	struct ecc_point r;
-	mpz_t x;
+	mpz_t x, y;
+	int ret = 0;
 
 	mpz_init(x);
+	mpz_init(y);
 	ecc_point_init(&r, public_key->ecc);
 
 	ecc_point_mul(&r, private_key, public_key);
 
-	ecc_point_get(&r, x, NULL);
+	ecc_point_get(&r, x, y);
+
+	/* Check if the point is not an identity element.  Note that this cannot
+	 * happen in nettle implementation, because it cannot represent an
+	 * infinity point. */
+	if (mpz_cmp_ui(x, 0) == 0 && mpz_cmp_ui(y, 0) == 0) {
+		ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
+		goto cleanup;
+	}
+
 	nettle_mpz_get_str_256(size, out, x);
 
+ cleanup:
 	mpz_clear(x);
+	mpz_clear(y);
 	ecc_point_clear(&r);
 
-	return;
+	return ret;
 }
 
 #define MAX_DH_BITS DEFAULT_MAX_VERIFY_BITS
@@ -365,8 +378,10 @@ dh_cleanup:
 				goto ecc_cleanup;
 			}
 
-			ecc_shared_secret(&ecc_priv, &ecc_pub, out->data,
-					  out->size);
+			ret = ecc_shared_secret(&ecc_priv, &ecc_pub, out->data,
+						out->size);
+			if (ret < 0)
+				gnutls_free(out->data);
 
 		      ecc_cleanup:
 			ecc_point_clear(&ecc_pub);
openSUSE Build Service is sponsored by