forked from pool/gnutls
Pedro Monreal Gonzalez
cf30493c2c
- 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
194 lines
5.1 KiB
Diff
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
|