Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Step:15-SP4
gnutls.27840
0005-ecdh-perform-SP800-56A-rev3-full-pubkey-va...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0005-ecdh-perform-SP800-56A-rev3-full-pubkey-validation-o.patch of Package gnutls.27840
From 23756c8580dff99d0856adca49dd22a55352ad62 Mon Sep 17 00:00:00 2001 From: Daiki Ueno <ueno@gnu.org> Date: Sat, 18 Jul 2020 08:26:48 +0200 Subject: [PATCH 5/5] ecdh: perform SP800-56A rev3 full pubkey validation on keygen This implements full public key validation required in SP800-56A rev3, section 5.6.2.3.3. Signed-off-by: Daiki Ueno <ueno@gnu.org> --- lib/nettle/pk.c | 182 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 180 insertions(+), 2 deletions(-) Index: gnutls-3.6.7/lib/nettle/pk.c =================================================================== --- gnutls-3.6.7.orig/lib/nettle/pk.c 2020-09-03 14:20:20.265198684 +0200 +++ gnutls-3.6.7/lib/nettle/pk.c 2020-09-03 14:20:20.301198910 +0200 @@ -1316,6 +1316,80 @@ static inline const struct ecc_curve *ge } } +static inline const char *get_supported_nist_curve_order(int curve) +{ + static const struct { + int curve; + const char *order; + } orders[] = { +#ifdef ENABLE_NON_SUITEB_CURVES + { GNUTLS_ECC_CURVE_SECP192R1, + "ffffffffffffffffffffffff99def836" + "146bc9b1b4d22831" }, + { GNUTLS_ECC_CURVE_SECP224R1, + "ffffffffffffffffffffffffffff16a2" + "e0b8f03e13dd29455c5c2a3d" }, +#endif + { GNUTLS_ECC_CURVE_SECP256R1, + "ffffffff00000000ffffffffffffffff" + "bce6faada7179e84f3b9cac2fc632551" }, + { GNUTLS_ECC_CURVE_SECP384R1, + "ffffffffffffffffffffffffffffffff" + "ffffffffffffffffc7634d81f4372ddf" + "581a0db248b0a77aecec196accc52973" }, + { GNUTLS_ECC_CURVE_SECP521R1, + "1fffffffffffffffffffffffffffffff" + "ffffffffffffffffffffffffffffffff" + "ffa51868783bf2f966b7fcc0148f709a" + "5d03bb5c9b8899c47aebb6fb71e91386" + "409" }, + }; + size_t i; + + for (i = 0; i < sizeof(orders)/sizeof(orders[0]); i++) { + if (orders[i].curve == curve) + return orders[i].order; + } + return NULL; +} + +static inline const char *get_supported_nist_curve_modulus(int curve) +{ + static const struct { + int curve; + const char *order; + } orders[] = { +#ifdef ENABLE_NON_SUITEB_CURVES + { GNUTLS_ECC_CURVE_SECP192R1, + "fffffffffffffffffffffffffffffffe" + "ffffffffffffffff" }, + { GNUTLS_ECC_CURVE_SECP224R1, + "ffffffffffffffffffffffffffffffff" + "000000000000000000000001" }, +#endif + { GNUTLS_ECC_CURVE_SECP256R1, + "ffffffff000000010000000000000000" + "00000000ffffffffffffffffffffffff" }, + { GNUTLS_ECC_CURVE_SECP384R1, + "ffffffffffffffffffffffffffffffff" + "fffffffffffffffffffffffffffffffe" + "ffffffff0000000000000000ffffffff" }, + { GNUTLS_ECC_CURVE_SECP521R1, + "1ff" + "ffffffffffffffffffffffffffffffff" + "ffffffffffffffffffffffffffffffff" + "ffffffffffffffffffffffffffffffff" + "ffffffffffffffffffffffffffffffff" }, + }; + size_t i; + + for (i = 0; i < sizeof(orders)/sizeof(orders[0]); i++) { + if (orders[i].curve == curve) + return orders[i].order; + } + return NULL; +} + static inline const struct ecc_curve *get_supported_gost_curve(int curve) { switch (curve) { @@ -2228,6 +2302,10 @@ wrap_nettle_pk_generate_keys(gnutls_pk_a struct ecc_scalar key; struct ecc_point 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; curve = get_supported_nist_curve(level); if (curve == NULL) @@ -2235,8 +2313,18 @@ wrap_nettle_pk_generate_keys(gnutls_pk_a gnutls_assert_val (GNUTLS_E_ECC_UNSUPPORTED_CURVE); + mpz_init(x); + mpz_init(y); + mpz_init(xx); + mpz_init(yy); + mpz_init(nn); + mpz_init(mm); + ecc_scalar_init(&key, curve); ecc_point_init(&pub, curve); + ecc_scalar_init(&n, curve); + ecc_scalar_init(&m, curve); + ecc_point_init(&r, curve); ecdsa_generate_keypair(&pub, &key, NULL, rnd_func); if (HAVE_LIB_ERROR()) { @@ -2254,15 +2342,105 @@ wrap_nettle_pk_generate_keys(gnutls_pk_a params->curve = level; params->params_nr = ECC_PRIVATE_PARAMS; - ecc_point_get(&pub, TOMPZ(params->params[ECC_X]), - TOMPZ(params->params[ECC_Y])); + ecc_point_get(&pub, x, y); + +#ifdef ENABLE_FIPS140 + if (_gnutls_fips_mode_enabled()) { + /* Perform ECC full public key validation checks + * according to SP800-56A (revision 3), 5.6.2.3.3. + */ + + const char *order, *modulus; + + /* 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. */ + if (mpz_cmp_ui(x, 0) == 0 && mpz_cmp_ui(y, 0) == 0) { + ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); + goto ecc_fail; + } + + /* 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_fail; + } + + /* 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(level); + if (unlikely(order == NULL)) { + ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + goto ecc_fail; + } + + ret = mpz_set_str(nn, order, 16); + if (unlikely(ret < 0)) { + ret = gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED); + goto ecc_fail; + } + + modulus = get_supported_nist_curve_modulus(level); + if (unlikely(modulus == NULL)) { + ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + goto ecc_fail; + } + + ret = mpz_set_str(mm, modulus, 16); + if (unlikely(ret < 0)) { + ret = gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED); + goto ecc_fail; + } + + /* (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_fail; + } + } +#endif + + mpz_set(TOMPZ(params->params[ECC_X]), x); + mpz_set(TOMPZ(params->params[ECC_Y]), y); + ecc_scalar_get(&key, TOMPZ(params->params[ECC_K])); ret = 0; ecc_fail: + mpz_clear(x); + mpz_clear(y); + mpz_clear(xx); + mpz_clear(yy); + mpz_clear(nn); + mpz_clear(mm); ecc_point_clear(&pub); ecc_scalar_clear(&key); + ecc_point_clear(&r); + ecc_scalar_clear(&n); + ecc_scalar_clear(&m); if (ret < 0) goto fail;
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