2023-03-24 12:22:34 +00:00
|
|
|
From 5030f40332ada4f90e80838a2232da36ce03757a Mon Sep 17 00:00:00 2001
|
|
|
|
From: Pedro Monreal <pmgdeb@gmail.com>
|
|
|
|
Date: Fri, 24 Feb 2023 22:02:48 +0000
|
|
|
|
Subject: [PATCH] ecdh: perform SP800-56A rev3 full pubkey validation on key
|
|
|
|
derivation
|
|
|
|
|
|
|
|
This implements full public key validation required in
|
|
|
|
SP800-56A rev3, section 5.6.2.3.3.
|
|
|
|
|
|
|
|
Co-authored-by: Daiki Ueno <ueno@gnu.org>
|
|
|
|
Signed-off-by: Pedro Monreal <pmgdeb@gmail.com>
|
|
|
|
---
|
|
|
|
lib/nettle/pk.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++--
|
|
|
|
1 file changed, 125 insertions(+), 3 deletions(-)
|
|
|
|
|
|
|
|
diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
|
|
|
|
index 6adf958a61..d30bca594f 100644
|
|
|
|
--- a/lib/nettle/pk.c
|
|
|
|
+++ b/lib/nettle/pk.c
|
2023-01-20 20:17:13 +00:00
|
|
|
@@ -71,6 +71,9 @@
|
|
|
|
static inline const struct ecc_curve *get_supported_nist_curve(int curve);
|
|
|
|
static inline const struct ecc_curve *get_supported_gost_curve(int curve);
|
|
|
|
|
|
|
|
+static inline const char *get_supported_nist_curve_order(int curve);
|
|
|
|
+static inline const char *get_supported_nist_curve_modulus(int curve);
|
|
|
|
+
|
|
|
|
/* When these callbacks are used for a nettle operation, the
|
|
|
|
* caller must check the macro HAVE_LIB_ERROR() after the operation
|
|
|
|
* is complete. If the macro is true, the operation is to be considered
|
2023-03-24 12:22:34 +00:00
|
|
|
@@ -406,6 +409,10 @@ static int _wrap_nettle_pk_derive(gnutls_pk_algorithm_t algo,
|
2023-01-20 20:17:13 +00:00
|
|
|
struct ecc_scalar ecc_priv;
|
|
|
|
struct ecc_point ecc_pub;
|
|
|
|
const struct ecc_curve *curve;
|
|
|
|
+ struct ecc_scalar n;
|
|
|
|
+ struct ecc_scalar m;
|
|
|
|
+ struct ecc_point r;
|
|
|
|
+ mpz_t x, y, xx, yy, nn, mm;
|
|
|
|
|
|
|
|
out->data = NULL;
|
|
|
|
|
2023-03-24 12:22:34 +00:00
|
|
|
@@ -428,17 +435,28 @@ static int _wrap_nettle_pk_derive(gnutls_pk_algorithm_t algo,
|
2023-01-20 20:17:13 +00:00
|
|
|
not_approved = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ mpz_init(x);
|
|
|
|
+ mpz_init(y);
|
|
|
|
+ mpz_init(xx);
|
|
|
|
+ mpz_init(yy);
|
|
|
|
+ mpz_init(nn);
|
|
|
|
+ mpz_init(mm);
|
|
|
|
+
|
|
|
|
+ ecc_scalar_init(&n, curve);
|
|
|
|
+ ecc_scalar_init(&m, curve);
|
|
|
|
+ ecc_point_init(&r, curve);
|
|
|
|
+
|
|
|
|
ret = _ecc_params_to_pubkey(pub, &ecc_pub, curve);
|
|
|
|
if (ret < 0) {
|
|
|
|
gnutls_assert();
|
|
|
|
- goto cleanup;
|
2023-03-24 12:22:34 +00:00
|
|
|
+ goto ecc_fail_cleanup;
|
2023-01-20 20:17:13 +00:00
|
|
|
}
|
|
|
|
|
2023-03-24 12:22:34 +00:00
|
|
|
ret = _ecc_params_to_privkey(priv, &ecc_priv, curve);
|
2023-01-20 20:17:13 +00:00
|
|
|
if (ret < 0) {
|
|
|
|
ecc_point_clear(&ecc_pub);
|
|
|
|
gnutls_assert();
|
|
|
|
- goto cleanup;
|
2023-03-24 12:22:34 +00:00
|
|
|
+ goto ecc_fail_cleanup;
|
2023-01-20 20:17:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
out->size = gnutls_ecc_curve_get_size(priv->curve);
|
2023-03-24 12:22:34 +00:00
|
|
|
@@ -449,14 +467,118 @@ static int _wrap_nettle_pk_derive(gnutls_pk_algorithm_t algo,
|
2023-01-20 20:17:13 +00:00
|
|
|
goto ecc_cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
+ /* Perform ECC Full Public-Key Validation Routine
|
|
|
|
+ * according to SP800-56A (revision 3), 5.6.2.3.3.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ /* Step 1: verify that Q is not an identity
|
2023-03-24 12:22:34 +00:00
|
|
|
+ * element (an infinity point). Note that this
|
2023-01-20 20:17:13 +00:00
|
|
|
+ * cannot happen in the nettle implementation,
|
|
|
|
+ * because it cannot represent an infinity point
|
|
|
|
+ * on curves. */
|
|
|
|
ret = ecc_shared_secret(&ecc_priv, &ecc_pub, out->data,
|
|
|
|
out->size);
|
|
|
|
- if (ret < 0)
|
|
|
|
+ if (ret < 0) {
|
|
|
|
gnutls_free(out->data);
|
|
|
|
+ goto ecc_cleanup;
|
|
|
|
+ }
|
|
|
|
+#ifdef ENABLE_FIPS140
|
|
|
|
+ if (_gnutls_fips_mode_enabled()) {
|
|
|
|
+ const char *order, *modulus;
|
|
|
|
+
|
|
|
|
+ ecc_point_mul(&r, &ecc_priv, &ecc_pub);
|
|
|
|
+ ecc_point_get(&r, x, y);
|
|
|
|
+
|
|
|
|
+ /* Step 2: verify that both coordinates of Q are
|
|
|
|
+ * in the range [0, p - 1].
|
|
|
|
+ *
|
|
|
|
+ * Step 3: verify that Q lie on the curve
|
|
|
|
+ *
|
|
|
|
+ * Both checks are performed in nettle. */
|
|
|
|
+ if (!ecc_point_set(&r, x, y)) {
|
2023-03-24 12:22:34 +00:00
|
|
|
+ ret =
|
|
|
|
+ gnutls_assert_val
|
|
|
|
+ (GNUTLS_E_ILLEGAL_PARAMETER);
|
2023-01-20 20:17:13 +00:00
|
|
|
+ goto ecc_cleanup;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Step 4: verify that n * Q, where n is the
|
|
|
|
+ * curve order, result in an identity element
|
|
|
|
+ *
|
|
|
|
+ * Since nettle internally cannot represent an
|
|
|
|
+ * identity element on curves, we validate this
|
|
|
|
+ * instead:
|
|
|
|
+ *
|
|
|
|
+ * (n - 1) * Q = -Q
|
|
|
|
+ *
|
|
|
|
+ * That effectively means: n * Q = -Q + Q = O
|
|
|
|
+ */
|
2023-03-24 12:22:34 +00:00
|
|
|
+ order =
|
|
|
|
+ get_supported_nist_curve_order(priv->curve);
|
2023-01-20 20:17:13 +00:00
|
|
|
+ if (unlikely(order == NULL)) {
|
2023-03-24 12:22:34 +00:00
|
|
|
+ ret =
|
|
|
|
+ gnutls_assert_val
|
|
|
|
+ (GNUTLS_E_INTERNAL_ERROR);
|
2023-01-20 20:17:13 +00:00
|
|
|
+ goto ecc_cleanup;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ret = mpz_set_str(nn, order, 16);
|
|
|
|
+ if (unlikely(ret < 0)) {
|
2023-03-24 12:22:34 +00:00
|
|
|
+ ret =
|
|
|
|
+ gnutls_assert_val
|
|
|
|
+ (GNUTLS_E_MPI_SCAN_FAILED);
|
2023-01-20 20:17:13 +00:00
|
|
|
+ goto ecc_cleanup;
|
|
|
|
+ }
|
|
|
|
+
|
2023-03-24 12:22:34 +00:00
|
|
|
+ modulus =
|
|
|
|
+ get_supported_nist_curve_modulus
|
|
|
|
+ (priv->curve);
|
2023-01-20 20:17:13 +00:00
|
|
|
+ if (unlikely(modulus == NULL)) {
|
2023-03-24 12:22:34 +00:00
|
|
|
+ ret =
|
|
|
|
+ gnutls_assert_val
|
|
|
|
+ (GNUTLS_E_INTERNAL_ERROR);
|
2023-01-20 20:17:13 +00:00
|
|
|
+ goto ecc_cleanup;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ret = mpz_set_str(mm, modulus, 16);
|
|
|
|
+ if (unlikely(ret < 0)) {
|
2023-03-24 12:22:34 +00:00
|
|
|
+ ret =
|
|
|
|
+ gnutls_assert_val
|
|
|
|
+ (GNUTLS_E_MPI_SCAN_FAILED);
|
2023-01-20 20:17:13 +00:00
|
|
|
+ goto ecc_cleanup;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* (n - 1) * Q = -Q */
|
2023-03-24 12:22:34 +00:00
|
|
|
+ mpz_sub_ui(nn, nn, 1);
|
2023-01-20 20:17:13 +00:00
|
|
|
+ ecc_scalar_set(&n, nn);
|
|
|
|
+ ecc_point_mul(&r, &n, &r);
|
|
|
|
+ ecc_point_get(&r, xx, yy);
|
2023-03-24 12:22:34 +00:00
|
|
|
+ mpz_sub(mm, mm, y);
|
2023-01-20 20:17:13 +00:00
|
|
|
+
|
|
|
|
+ if (mpz_cmp(xx, x) != 0 || mpz_cmp(yy, mm) != 0) {
|
2023-03-24 12:22:34 +00:00
|
|
|
+ ret =
|
|
|
|
+ gnutls_assert_val
|
|
|
|
+ (GNUTLS_E_ILLEGAL_PARAMETER);
|
2023-01-20 20:17:13 +00:00
|
|
|
+ goto ecc_cleanup;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ not_approved = true;
|
|
|
|
+ }
|
|
|
|
+#endif
|
|
|
|
|
2023-03-24 12:22:34 +00:00
|
|
|
ecc_cleanup:
|
|
|
|
ecc_point_clear(&ecc_pub);
|
2023-01-20 20:17:13 +00:00
|
|
|
ecc_scalar_zclear(&ecc_priv);
|
2023-03-24 12:22:34 +00:00
|
|
|
+ ecc_fail_cleanup:
|
2023-01-20 20:17:13 +00:00
|
|
|
+ mpz_clear(x);
|
|
|
|
+ mpz_clear(y);
|
|
|
|
+ mpz_clear(xx);
|
|
|
|
+ mpz_clear(yy);
|
|
|
|
+ mpz_clear(nn);
|
|
|
|
+ mpz_clear(mm);
|
|
|
|
+ ecc_point_clear(&r);
|
|
|
|
+ ecc_scalar_clear(&n);
|
|
|
|
+ ecc_scalar_clear(&m);
|
|
|
|
if (ret < 0)
|
|
|
|
goto cleanup;
|
|
|
|
break;
|
2023-03-24 12:22:34 +00:00
|
|
|
--
|
|
|
|
GitLab
|