gnutls/gnutls-FIPS-PCT-ECDH.patch
Pedro Monreal Gonzalez cf30493c2c Accepting request 1074130 from home:pmonrealgonzalez:branches:security:tls
- Update to 3.8.0: [bsc#1205763, bsc#1209627]
  * libgnutls: Fix a Bleichenbacher oracle in the TLS RSA key
    exchange. Reported by Hubert Kario (#1050). Fix developed by
    Alexander Sosedkin. [GNUTLS-SA-2020-07-14, CVSS: medium]
    [CVE-2023-0361]
  * libgnutls: C++ library is now header only. All definitions
    from gnutlsxx.c have been moved into gnutlsxx.h. Users of the
    C++ interface have two options:
    1. include gnutlsxx.h in their application and link against
       the C library. (default)
    2. include gnutlsxx.h in their application, compile with
       GNUTLS_GNUTLSXX_NO_HEADERONLY macro defined and link
       against the C++ library.
  * libgnutls: GNUTLS_NO_STATUS_REQUEST flag and %NO_STATUS_REQUEST
    priority modifier have been added to allow disabling of the
    status_request TLS extension in the client side.
  * libgnutls: TLS heartbeat is disabled by default.
    The heartbeat extension in TLS (RFC 6520) is not widely used
    given other implementations dropped support for it. To enable
    back support for it, supply --enable-heartbeat-support to
    configure script.
  * libgnutls: SRP authentication is now disabled by default.
    It is disabled because the SRP authentication in TLS is not
    up to date with the latest TLS standards and its ciphersuites
    are based on the CBC mode and SHA-1. To enable it back, supply
    --enable-srp-authentication option to configure script.
  * libgnutls: All code has been indented using "indent -ppi1 -linux".
    CI/CD has been adjusted to catch regressions. This is implemented
    through devel/indent-gnutls, devel/indent-maybe and .gitlab-ci.yml’s
    commit-check. You may run devel/indent-gnutls to fix any

OBS-URL: https://build.opensuse.org/request/show/1074130
OBS-URL: https://build.opensuse.org/package/show/security:tls/gnutls?expand=0&rev=88
2023-03-24 12:22:34 +00:00

194 lines
5.1 KiB
Diff

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
@@ -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
@@ -406,6 +409,10 @@ static int _wrap_nettle_pk_derive(gnutls_pk_algorithm_t algo,
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;
@@ -428,17 +435,28 @@ static int _wrap_nettle_pk_derive(gnutls_pk_algorithm_t algo,
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;
+ goto ecc_fail_cleanup;
}
ret = _ecc_params_to_privkey(priv, &ecc_priv, curve);
if (ret < 0) {
ecc_point_clear(&ecc_pub);
gnutls_assert();
- goto cleanup;
+ goto ecc_fail_cleanup;
}
out->size = gnutls_ecc_curve_get_size(priv->curve);
@@ -449,14 +467,118 @@ static int _wrap_nettle_pk_derive(gnutls_pk_algorithm_t algo,
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
+ * element (an infinity point). Note that this
+ * 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)) {
+ ret =
+ gnutls_assert_val
+ (GNUTLS_E_ILLEGAL_PARAMETER);
+ 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
+ */
+ order =
+ get_supported_nist_curve_order(priv->curve);
+ if (unlikely(order == NULL)) {
+ ret =
+ gnutls_assert_val
+ (GNUTLS_E_INTERNAL_ERROR);
+ goto ecc_cleanup;
+ }
+
+ ret = mpz_set_str(nn, order, 16);
+ if (unlikely(ret < 0)) {
+ ret =
+ gnutls_assert_val
+ (GNUTLS_E_MPI_SCAN_FAILED);
+ goto ecc_cleanup;
+ }
+
+ modulus =
+ get_supported_nist_curve_modulus
+ (priv->curve);
+ if (unlikely(modulus == NULL)) {
+ ret =
+ gnutls_assert_val
+ (GNUTLS_E_INTERNAL_ERROR);
+ goto ecc_cleanup;
+ }
+
+ ret = mpz_set_str(mm, modulus, 16);
+ if (unlikely(ret < 0)) {
+ ret =
+ gnutls_assert_val
+ (GNUTLS_E_MPI_SCAN_FAILED);
+ goto ecc_cleanup;
+ }
+
+ /* (n - 1) * Q = -Q */
+ mpz_sub_ui(nn, nn, 1);
+ ecc_scalar_set(&n, nn);
+ ecc_point_mul(&r, &n, &r);
+ ecc_point_get(&r, xx, yy);
+ mpz_sub(mm, mm, y);
+
+ if (mpz_cmp(xx, x) != 0 || mpz_cmp(yy, mm) != 0) {
+ ret =
+ gnutls_assert_val
+ (GNUTLS_E_ILLEGAL_PARAMETER);
+ goto ecc_cleanup;
+ }
+ } else {
+ not_approved = true;
+ }
+#endif
ecc_cleanup:
ecc_point_clear(&ecc_pub);
ecc_scalar_zclear(&ecc_priv);
+ ecc_fail_cleanup:
+ 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;
--
GitLab