Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
Please login to access the resource
openSUSE:Leap:15.5:Update
gnutls.31677
gnutls-FIPS-PCT-ECDH.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File gnutls-FIPS-PCT-ECDH.patch of Package gnutls.31677
From a65dec4dc859fddad98d1ae9b23766a4f75ede38 Mon Sep 17 00:00:00 2001 From: Pedro Monreal <pmgdeb@gmail.com> Date: Thu, 16 Feb 2023 12:37:46 +0100 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> Index: gnutls-3.7.3/lib/nettle/pk.c =================================================================== --- gnutls-3.7.3.orig/lib/nettle/pk.c +++ gnutls-3.7.3/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 @@ dh_cleanup: 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; @@ -425,10 +432,21 @@ dh_cleanup: 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 = @@ -436,7 +454,7 @@ dh_cleanup: 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,104 @@ dh_cleanup: 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;
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor