Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:15.5:Update
gnutls
gnutls-CVE-2024-28834.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File gnutls-CVE-2024-28834.patch of Package gnutls
From 1c4701ffc342259fc5965d5a0de90d87f780e3e5 Mon Sep 17 00:00:00 2001 From: Daiki Ueno <ueno@gnu.org> Date: Fri, 12 Jan 2024 17:56:58 +0900 Subject: [PATCH] nettle: avoid normalization of mpz_t in deterministic ECDSA This removes function calls that potentially leak bit-length of a private key used to calculate a nonce in deterministic ECDSA. Namely: - _gnutls_dsa_compute_k has been rewritten to work on always zero-padded mp_limb_t arrays instead of mpz_t - rnd_mpz_func has been replaced with rnd_datum_func, which is backed by a byte array instead of an mpz_t value Signed-off-by: Daiki Ueno <ueno@gnu.org> --- lib/nettle/int/dsa-compute-k.c | 70 +++++++++++++++++++++---------- lib/nettle/int/dsa-compute-k.h | 23 +++++++++- lib/nettle/int/ecdsa-compute-k.c | 28 +++---------- lib/nettle/int/ecdsa-compute-k.h | 4 +- lib/nettle/pk.c | 65 +++++++++++++++++++++------- tests/sign-verify-deterministic.c | 2 +- 6 files changed, 127 insertions(+), 65 deletions(-) Index: gnutls-3.7.3/lib/nettle/int/dsa-compute-k.c =================================================================== --- gnutls-3.7.3.orig/lib/nettle/int/dsa-compute-k.c +++ gnutls-3.7.3/lib/nettle/int/dsa-compute-k.c @@ -31,33 +31,37 @@ #include "mpn-base256.h" #include <string.h> -#define BITS_TO_LIMBS(bits) (((bits) + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS) +/* For mini-gmp */ +#ifndef GMP_LIMB_BITS +#define GMP_LIMB_BITS GMP_NUMB_BITS +#endif + +static inline int is_zero_limb(mp_limb_t x) +{ + x |= (x << 1); + return ((x >> 1) - 1) >> (GMP_LIMB_BITS - 1); +} + +static int sec_zero_p(const mp_limb_t *ap, mp_size_t n) +{ + volatile mp_limb_t w; + mp_size_t i; + + for (i = 0, w = 0; i < n; i++) + w |= ap[i]; -/* The maximum size of q, choosen from the fact that we support - * 521-bit elliptic curve generator and 512-bit DSA subgroup at - * maximum. */ -#define MAX_Q_BITS 521 -#define MAX_Q_SIZE ((MAX_Q_BITS + 7) / 8) -#define MAX_Q_LIMBS BITS_TO_LIMBS(MAX_Q_BITS) - -#define MAX_HASH_BITS (MAX_HASH_SIZE * 8) -#define MAX_HASH_LIMBS BITS_TO_LIMBS(MAX_HASH_BITS) - -int -_gnutls_dsa_compute_k(mpz_t k, - const mpz_t q, - const mpz_t x, - gnutls_mac_algorithm_t mac, - const uint8_t *digest, - size_t length) + return is_zero_limb(w); +} + +int _gnutls_dsa_compute_k(mp_limb_t *h, const mp_limb_t *q, const mp_limb_t *x, + mp_size_t qn, mp_bitcnt_t q_bits, + gnutls_mac_algorithm_t mac, const uint8_t *digest, + size_t length) { uint8_t V[MAX_HASH_SIZE]; uint8_t K[MAX_HASH_SIZE]; uint8_t xp[MAX_Q_SIZE]; uint8_t tp[MAX_Q_SIZE]; - mp_limb_t h[MAX(MAX_Q_LIMBS, MAX_HASH_LIMBS)]; - mp_bitcnt_t q_bits = mpz_sizeinbase (q, 2); - mp_size_t qn = mpz_size(q); mp_bitcnt_t h_bits = length * 8; mp_size_t hn = BITS_TO_LIMBS(h_bits); size_t nbytes = (q_bits + 7) / 8; @@ -66,6 +70,7 @@ _gnutls_dsa_compute_k(mpz_t k, mp_limb_t cy; gnutls_hmac_hd_t hd; int ret = 0; + mp_limb_t scratch[MAX_Q_LIMBS]; if (unlikely(q_bits > MAX_Q_BITS)) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); @@ -73,7 +78,7 @@ _gnutls_dsa_compute_k(mpz_t k, return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); /* int2octets(x) */ - mpn_get_base256(xp, nbytes, mpz_limbs_read(x), qn); + mpn_get_base256(xp, nbytes, x, qn); /* bits2octets(h) */ mpn_set_base256(h, hn, digest, length); @@ -97,12 +102,12 @@ _gnutls_dsa_compute_k(mpz_t k, mpn_rshift(h, h, hn, shift % GMP_NUMB_BITS); } - cy = mpn_sub_n(h, h, mpz_limbs_read(q), qn); + cy = mpn_sub_n(h, h, q, qn); /* Fall back to addmul_1, if nettle is linked with mini-gmp. */ #ifdef mpn_cnd_add_n - mpn_cnd_add_n(cy, h, h, mpz_limbs_read(q), qn); + mpn_cnd_add_n(cy, h, h, q, qn); #else - mpn_addmul_1(h, mpz_limbs_read(q), qn, cy != 0); + mpn_addmul_1(h, q, qn, cy != 0); #endif mpn_get_base256(tp, nbytes, h, qn); @@ -178,12 +183,8 @@ _gnutls_dsa_compute_k(mpz_t k, if (tlen * 8 > q_bits) mpn_rshift (h, h, qn, tlen * 8 - q_bits); /* Check if k is in [1,q-1] */ - if (!mpn_zero_p (h, qn) && - mpn_cmp (h, mpz_limbs_read(q), qn) < 0) { - mpn_copyi(mpz_limbs_write(k, qn), h, qn); - mpz_limbs_finish(k, qn); + if (!sec_zero_p(h, qn) && mpn_sub_n(scratch, h, q, qn)) break; - } ret = gnutls_hmac_init(&hd, mac, K, length); if (ret < 0) @@ -207,3 +208,24 @@ _gnutls_dsa_compute_k(mpz_t k, return ret; } + +/* cancel-out dsa_sign's addition of 1 to random data */ +void _gnutls_dsa_compute_k_finish(uint8_t *k, size_t nbytes, mp_limb_t *h, + mp_size_t n) +{ + /* Fall back to sub_1, if nettle is linked with mini-gmp. */ +#ifdef mpn_sec_sub_1 + mp_limb_t t[MAX_Q_LIMBS]; + + mpn_sec_sub_1(h, h, n, 1, t); +#else + mpn_sub_1(h, h, n, 1); +#endif + mpn_get_base256(k, nbytes, h, n); +} + +void _gnutls_ecdsa_compute_k_finish(uint8_t *k, size_t nbytes, mp_limb_t *h, + mp_size_t n) +{ + mpn_get_base256(k, nbytes, h, n); +} Index: gnutls-3.7.3/lib/nettle/int/dsa-compute-k.h =================================================================== --- gnutls-3.7.3.orig/lib/nettle/int/dsa-compute-k.h +++ gnutls-3.7.3/lib/nettle/int/dsa-compute-k.h @@ -26,12 +26,29 @@ #include <gnutls/gnutls.h> #include <nettle/bignum.h> /* includes gmp.h */ -int -_gnutls_dsa_compute_k(mpz_t k, - const mpz_t q, - const mpz_t x, - gnutls_mac_algorithm_t mac, - const uint8_t *digest, - size_t length); +#define BITS_TO_LIMBS(bits) (((bits) + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS) + +/* The maximum size of q, chosen from the fact that we support + * 521-bit elliptic curve generator and 512-bit DSA subgroup at + * maximum. */ +#define MAX_Q_BITS 521 +#define MAX_Q_SIZE ((MAX_Q_BITS + 7) / 8) +#define MAX_Q_LIMBS BITS_TO_LIMBS(MAX_Q_BITS) + +#define MAX_HASH_BITS (MAX_HASH_SIZE * 8) +#define MAX_HASH_LIMBS BITS_TO_LIMBS(MAX_HASH_BITS) + +#define DSA_COMPUTE_K_ITCH MAX(MAX_Q_LIMBS, MAX_HASH_LIMBS) + +int _gnutls_dsa_compute_k(mp_limb_t *h, const mp_limb_t *q, const mp_limb_t *x, + mp_size_t qn, mp_bitcnt_t q_bits, + gnutls_mac_algorithm_t mac, const uint8_t *digest, + size_t length); + +void _gnutls_dsa_compute_k_finish(uint8_t *k, size_t nbytes, mp_limb_t *h, + mp_size_t n); + +void _gnutls_ecdsa_compute_k_finish(uint8_t *k, size_t nbytes, mp_limb_t *h, + mp_size_t n); #endif /* GNUTLS_LIB_NETTLE_INT_DSA_COMPUTE_K_H */ Index: gnutls-3.7.3/lib/nettle/int/ecdsa-compute-k.c =================================================================== --- gnutls-3.7.3.orig/lib/nettle/int/ecdsa-compute-k.c +++ gnutls-3.7.3/lib/nettle/int/ecdsa-compute-k.c @@ -29,39 +29,38 @@ #include "dsa-compute-k.h" #include "gnutls_int.h" -static inline int -_gnutls_ecc_curve_to_dsa_q(mpz_t *q, gnutls_ecc_curve_t curve) +int _gnutls_ecc_curve_to_dsa_q(mpz_t q, gnutls_ecc_curve_t curve) { switch (curve) { #ifdef ENABLE_NON_SUITEB_CURVES case GNUTLS_ECC_CURVE_SECP192R1: - mpz_init_set_str(*q, + mpz_init_set_str(q, "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836" "146BC9B1B4D22831", 16); return 0; case GNUTLS_ECC_CURVE_SECP224R1: - mpz_init_set_str(*q, + mpz_init_set_str(q, "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2" "E0B8F03E13DD29455C5C2A3D", 16); return 0; #endif case GNUTLS_ECC_CURVE_SECP256R1: - mpz_init_set_str(*q, + mpz_init_set_str(q, "FFFFFFFF00000000FFFFFFFFFFFFFFFF" "BCE6FAADA7179E84F3B9CAC2FC632551", 16); return 0; case GNUTLS_ECC_CURVE_SECP384R1: - mpz_init_set_str(*q, + mpz_init_set_str(q, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFC7634D81F4372DDF" "581A0DB248B0A77AECEC196ACCC52973", 16); return 0; case GNUTLS_ECC_CURVE_SECP521R1: - mpz_init_set_str(*q, + mpz_init_set_str(q, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFA51868783BF2F966B7FCC0148F709A" @@ -73,23 +72,3 @@ _gnutls_ecc_curve_to_dsa_q(mpz_t *q, gnu return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM); } } - -int -_gnutls_ecdsa_compute_k (mpz_t k, - gnutls_ecc_curve_t curve, - const mpz_t x, - gnutls_mac_algorithm_t mac, - const uint8_t *digest, - size_t length) -{ - mpz_t q; - int ret; - - ret = _gnutls_ecc_curve_to_dsa_q(&q, curve); - if (ret < 0) - return gnutls_assert_val(ret); - - ret = _gnutls_dsa_compute_k (k, q, x, mac, digest, length); - mpz_clear(q); - return ret; -} Index: gnutls-3.7.3/lib/nettle/int/ecdsa-compute-k.h =================================================================== --- gnutls-3.7.3.orig/lib/nettle/int/ecdsa-compute-k.h +++ gnutls-3.7.3/lib/nettle/int/ecdsa-compute-k.h @@ -26,12 +26,6 @@ #include <gnutls/gnutls.h> #include <nettle/bignum.h> /* includes gmp.h */ -int -_gnutls_ecdsa_compute_k (mpz_t k, - gnutls_ecc_curve_t curve, - const mpz_t x, - gnutls_mac_algorithm_t mac, - const uint8_t *digest, - size_t length); +int _gnutls_ecc_curve_to_dsa_q(mpz_t q, gnutls_ecc_curve_t curve); #endif /* GNUTLS_LIB_NETTLE_INT_ECDSA_COMPUTE_K_H */ 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 @@ -100,10 +100,16 @@ static void rnd_nonce_func(void *_ctx, s } } -static void rnd_mpz_func(void *_ctx, size_t length, uint8_t * data) +static void rnd_datum_func(void *ctx, size_t length, uint8_t * data) { - mpz_t *k = _ctx; - nettle_mpz_get_str_256 (length, data, *k); + gnutls_datum_t *d = ctx; + + if (length > d->size) { + memset(data, 0, length - d->size); + memcpy(data + (length - d->size), d->data, d->size); + } else { + memcpy(data, d->data, length); + } } static void rnd_nonce_func_fallback(void *_ctx, size_t length, uint8_t * data) @@ -1184,7 +1190,10 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm struct dsa_signature sig; int curve_id = pk_params->curve; const struct ecc_curve *curve; - mpz_t k; + mpz_t q; + /* 521-bit elliptic curve generator at maximum */ + uint8_t buf[(521 + 7) / 8]; + gnutls_datum_t k = { NULL, 0 }; void *random_ctx; nettle_random_func *random_func; @@ -1231,19 +1240,31 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm hash_len = vdata->size; } - mpz_init(k); + mpz_init(q); if (_gnutls_get_lib_state() == LIB_STATE_SELFTEST || (sign_params->flags & GNUTLS_PK_FLAG_REPRODUCIBLE)) { - ret = _gnutls_ecdsa_compute_k(k, - curve_id, - pk_params->params[ECC_K], - DIG_TO_MAC(sign_params->dsa_dig), - vdata->data, - vdata->size); + mp_limb_t h[DSA_COMPUTE_K_ITCH]; + + ret = _gnutls_ecc_curve_to_dsa_q(q, curve_id); + if (ret < 0) + goto ecdsa_cleanup; + + ret = _gnutls_dsa_compute_k( + h, mpz_limbs_read(q), priv.p, + ecc_size(priv.ecc), ecc_bit_size(priv.ecc), + DIG_TO_MAC(sign_params->dsa_dig), vdata->data, + vdata->size); if (ret < 0) goto ecdsa_cleanup; + + k.data = buf; + k.size = (ecc_bit_size(priv.ecc) + 7) / 8; + + _gnutls_ecdsa_compute_k_finish(k.data, k.size, h, + ecc_size(priv.ecc)); + random_ctx = &k; - random_func = rnd_mpz_func; + random_func = rnd_datum_func; } else { random_ctx = NULL; random_func = rnd_nonce_func; @@ -1264,7 +1285,7 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm ecdsa_cleanup: dsa_signature_clear(&sig); ecc_scalar_zclear(&priv); - mpz_clear(k); + mpz_clear(q); if (ret < 0) { gnutls_assert(); @@ -1277,7 +1298,9 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm struct dsa_params pub; bigint_t priv; struct dsa_signature sig; - mpz_t k; + /* 512-bit DSA subgroup at maximum */ + uint8_t buf[(512 + 7) / 8]; + gnutls_datum_t k = { NULL, 0 }; void *random_ctx; nettle_random_func *random_func; @@ -1304,21 +1327,27 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm hash_len = vdata->size; } - mpz_init(k); if (_gnutls_get_lib_state() == LIB_STATE_SELFTEST || (sign_params->flags & GNUTLS_PK_FLAG_REPRODUCIBLE)) { - ret = _gnutls_dsa_compute_k(k, - pub.q, - TOMPZ(priv), - DIG_TO_MAC(sign_params->dsa_dig), - vdata->data, + mp_limb_t h[DSA_COMPUTE_K_ITCH]; + + ret = _gnutls_dsa_compute_k( + h, mpz_limbs_read(pub.q), + mpz_limbs_read(TOMPZ(priv)), mpz_size(pub.q), + mpz_sizeinbase(pub.q, 2), + DIG_TO_MAC(sign_params->dsa_dig), vdata->data, vdata->size); if (ret < 0) goto dsa_fail; - /* cancel-out dsa_sign's addition of 1 to random data */ - mpz_sub_ui (k, k, 1); + + k.data = buf; + k.size = (mpz_sizeinbase(pub.q, 2) + 7) / 8; + + _gnutls_dsa_compute_k_finish(k.data, k.size, h, + mpz_size(pub.q)); + random_ctx = &k; - random_func = rnd_mpz_func; + random_func = rnd_datum_func; } else { random_ctx = NULL; random_func = rnd_nonce_func; @@ -1338,7 +1367,6 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm dsa_fail: dsa_signature_clear(&sig); - mpz_clear(k); if (ret < 0) { gnutls_assert(); Index: gnutls-3.7.3/tests/sign-verify-deterministic.c =================================================================== --- gnutls-3.7.3.orig/tests/sign-verify-deterministic.c +++ gnutls-3.7.3/tests/sign-verify-deterministic.c @@ -197,7 +197,7 @@ void doit(void) &signature); if (ret < 0) testfail("gnutls_pubkey_verify_data2\n"); - success(" - pass"); + success(" - pass\n"); next: gnutls_free(signature.data);
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