summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <ueno@gnu.org>2020-07-10 09:42:30 +0200
committerDaiki Ueno <ueno@gnu.org>2020-08-31 08:13:45 +0200
commit2f6cd079cb6b613bf7906af9e7bdff0e5ec80406 (patch)
treec8f5da989a063328717f5f9ed7c069fb5e84aaa4
parent4eca726fe64c4702748aef964c83d0d4a470b338 (diff)
downloadgnutls-2f6cd079cb6b613bf7906af9e7bdff0e5ec80406.tar.gz
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>
-rw-r--r--lib/nettle/pk.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
index 08c7d4860b..7f0fa8e032 100644
--- a/lib/nettle/pk.c
+++ b/lib/nettle/pk.c
@@ -229,25 +229,38 @@ _gost_params_to_pubkey(const gnutls_pk_params_st * pk_params,
}
#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
@@ -423,8 +436,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);