diff options
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | devel/libgnutls-latest-x86_64.abi | 2 | ||||
-rw-r--r-- | devel/symbols.last | 3 | ||||
-rw-r--r-- | doc/Makefile.am | 4 | ||||
-rw-r--r-- | doc/manpages/Makefile.am | 2 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 5 | ||||
-rw-r--r-- | lib/libgnutls.map | 9 | ||||
-rw-r--r-- | lib/state.c | 67 | ||||
-rw-r--r-- | tests/tls13-early-data.c | 33 |
9 files changed, 128 insertions, 1 deletions
@@ -26,6 +26,10 @@ See the end for copying conditions. GNUTLS_NO_IMPLICIT_INIT to reflect the purpose (#1178). The former is now deprecated and will be removed in the future releases. +** API and ABI modifications: +gnutls_early_cipher_get: Added +gnutls_early_prf_hash_get: Added + * Version 3.7.1 (released 2021-03-10) ** libgnutls: Fixed potential use-after-free in sending "key_share" diff --git a/devel/libgnutls-latest-x86_64.abi b/devel/libgnutls-latest-x86_64.abi index ca32cbac7d..97a0184242 100644 --- a/devel/libgnutls-latest-x86_64.abi +++ b/devel/libgnutls-latest-x86_64.abi @@ -257,6 +257,8 @@ <elf-symbol name='gnutls_dtls_set_data_mtu' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='gnutls_dtls_set_mtu' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='gnutls_dtls_set_timeouts' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='gnutls_early_cipher_get' version='GNUTLS_3_7_2' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> + <elf-symbol name='gnutls_early_prf_hash_get' version='GNUTLS_3_7_2' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='gnutls_ecc_curve_get' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='gnutls_ecc_curve_get_id' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> <elf-symbol name='gnutls_ecc_curve_get_name' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/> diff --git a/devel/symbols.last b/devel/symbols.last index a3482d25a6..963287687b 100644 --- a/devel/symbols.last +++ b/devel/symbols.last @@ -12,6 +12,7 @@ GNUTLS_3_6_6@GNUTLS_3_6_6 GNUTLS_3_6_8@GNUTLS_3_6_8 GNUTLS_3_6_9@GNUTLS_3_6_9 GNUTLS_3_7_0@GNUTLS_3_7_0 +GNUTLS_3_7_2@GNUTLS_3_7_2 _gnutls_global_init_skip@GNUTLS_3_4 gnutls_aead_cipher_decrypt@GNUTLS_3_4 gnutls_aead_cipher_decryptv2@GNUTLS_3_6_10 @@ -203,6 +204,8 @@ gnutls_dtls_prestate_set@GNUTLS_3_4 gnutls_dtls_set_data_mtu@GNUTLS_3_4 gnutls_dtls_set_mtu@GNUTLS_3_4 gnutls_dtls_set_timeouts@GNUTLS_3_4 +gnutls_early_cipher_get@GNUTLS_3_7_2 +gnutls_early_prf_hash_get@GNUTLS_3_7_2 gnutls_ecc_curve_get@GNUTLS_3_4 gnutls_ecc_curve_get_id@GNUTLS_3_4 gnutls_ecc_curve_get_name@GNUTLS_3_4 diff --git a/doc/Makefile.am b/doc/Makefile.am index 5301db7d88..562a85fa87 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -992,6 +992,10 @@ FUNCS += functions/gnutls_dtls_set_mtu FUNCS += functions/gnutls_dtls_set_mtu.short FUNCS += functions/gnutls_dtls_set_timeouts FUNCS += functions/gnutls_dtls_set_timeouts.short +FUNCS += functions/gnutls_early_cipher_get +FUNCS += functions/gnutls_early_cipher_get.short +FUNCS += functions/gnutls_early_prf_hash_get +FUNCS += functions/gnutls_early_prf_hash_get.short FUNCS += functions/gnutls_ecc_curve_get FUNCS += functions/gnutls_ecc_curve_get.short FUNCS += functions/gnutls_ecc_curve_get_id diff --git a/doc/manpages/Makefile.am b/doc/manpages/Makefile.am index 0cfec06b7a..cee5a9644a 100644 --- a/doc/manpages/Makefile.am +++ b/doc/manpages/Makefile.am @@ -298,6 +298,8 @@ APIMANS += gnutls_dtls_prestate_set.3 APIMANS += gnutls_dtls_set_data_mtu.3 APIMANS += gnutls_dtls_set_mtu.3 APIMANS += gnutls_dtls_set_timeouts.3 +APIMANS += gnutls_early_cipher_get.3 +APIMANS += gnutls_early_prf_hash_get.3 APIMANS += gnutls_ecc_curve_get.3 APIMANS += gnutls_ecc_curve_get_id.3 APIMANS += gnutls_ecc_curve_get_name.3 diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index ca01fc9bdc..d69b29b443 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -1299,14 +1299,17 @@ gnutls_group_t gnutls_group_get(gnutls_session_t session); /* get information on the current session */ gnutls_cipher_algorithm_t gnutls_cipher_get(gnutls_session_t session); +gnutls_cipher_algorithm_t gnutls_early_cipher_get(gnutls_session_t session); gnutls_kx_algorithm_t gnutls_kx_get(gnutls_session_t session); gnutls_mac_algorithm_t gnutls_mac_get(gnutls_session_t session); gnutls_digest_algorithm_t gnutls_prf_hash_get(const gnutls_session_t session); +gnutls_digest_algorithm_t +gnutls_early_prf_hash_get(const gnutls_session_t session); gnutls_certificate_type_t gnutls_certificate_type_get(gnutls_session_t session); gnutls_certificate_type_t gnutls_certificate_type_get2(gnutls_session_t session, - gnutls_ctype_target_t target); + gnutls_ctype_target_t target); int gnutls_sign_algorithm_get(gnutls_session_t session); int gnutls_sign_algorithm_get_client(gnutls_session_t session); diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 0a4575f3fc..e6a19865b8 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -1346,6 +1346,15 @@ GNUTLS_3_7_0 *; } GNUTLS_3_4; +GNUTLS_3_7_2 +{ + global: + gnutls_early_cipher_get; + gnutls_early_prf_hash_get; + local: + *; +} GNUTLS_3_6_13; + GNUTLS_FIPS140_3_4 { global: gnutls_cipher_self_test; diff --git a/lib/state.c b/lib/state.c index 5836f81f21..f42c6ae6db 100644 --- a/lib/state.c +++ b/lib/state.c @@ -92,6 +92,40 @@ gnutls_cipher_algorithm_t gnutls_cipher_get(gnutls_session_t session) } /** + * gnutls_early_cipher_get: + * @session: is a #gnutls_session_t type. + * + * Get the cipher algorithm used for encrypting early data. + * + * Returns: the cipher used for early data, a + * #gnutls_cipher_algorithm_t type. + * + * Since: 3.7.2 + **/ +gnutls_cipher_algorithm_t gnutls_early_cipher_get(gnutls_session_t session) +{ + const cipher_entry_st *ce; + + if (!(session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT)) { + return gnutls_assert_val(GNUTLS_CIPHER_UNKNOWN); + } + + if (unlikely(session->internals. + resumed_security_parameters.cs == NULL)) { + return gnutls_assert_val(GNUTLS_CIPHER_UNKNOWN); + } + + ce = cipher_to_entry(session->internals. + resumed_security_parameters. + cs->block_algorithm); + if (unlikely(ce == NULL)) { + return gnutls_assert_val(GNUTLS_CIPHER_UNKNOWN); + } + + return ce->id; +} + +/** * gnutls_certificate_type_get: * @session: is a #gnutls_session_t type. * @@ -259,6 +293,39 @@ gnutls_prf_hash_get(const gnutls_session_t session) return (gnutls_digest_algorithm_t)session->security_parameters.prf->id; } +/** + * gnutls_early_prf_hash_get: + * @session: is a #gnutls_session_t type. + * + * Get the hash algorithm used as a PRF to derive keys for encrypting + * early data in TLS 1.3. + * + * Returns: the hash algorithm used for early data, a + * #gnutls_digest_algorithm_t value. + * + * Since: 3.7.2 + **/ +gnutls_digest_algorithm_t +gnutls_early_prf_hash_get(const gnutls_session_t session) +{ + if (!(session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT)) { + return gnutls_assert_val(GNUTLS_DIG_UNKNOWN); + } + + if (unlikely(session->internals. + resumed_security_parameters.prf == NULL)) { + return gnutls_assert_val(GNUTLS_DIG_UNKNOWN); + } + + if (unlikely(session->internals. + resumed_security_parameters.prf->id >= GNUTLS_MAC_AEAD)) { + return gnutls_assert_val(GNUTLS_DIG_UNKNOWN); + } + + return (gnutls_digest_algorithm_t)session->internals. + resumed_security_parameters.prf->id; +} + void reset_binders(gnutls_session_t session) { _gnutls_free_temp_key_datum(&session->key.binders[0].psk); diff --git a/tests/tls13-early-data.c b/tests/tls13-early-data.c index d26973e498..381ecbdb97 100644 --- a/tests/tls13-early-data.c +++ b/tests/tls13-early-data.c @@ -368,6 +368,25 @@ secret_callback(gnutls_session_t session, if (level == GNUTLS_ENCRYPTION_LEVEL_EARLY) { fail("early secret is set on initial connection\n"); } + } else { + if (level == GNUTLS_ENCRYPTION_LEVEL_EARLY) { + gnutls_cipher_algorithm_t cipher_algo; + gnutls_digest_algorithm_t digest_algo; + + cipher_algo = gnutls_early_cipher_get(session); + if (cipher_algo != GNUTLS_CIPHER_AES_128_GCM) { + fail("unexpected cipher used for early data: %s != %s\n", + gnutls_cipher_get_name(cipher_algo), + gnutls_cipher_get_name(GNUTLS_CIPHER_AES_128_GCM)); + } + + digest_algo = gnutls_early_prf_hash_get(session); + if (digest_algo != GNUTLS_DIG_SHA256) { + fail("unexpected PRF hash used for early data: %s != %s\n", + gnutls_digest_get_name(digest_algo), + gnutls_digest_get_name(GNUTLS_DIG_SHA256)); + } + } } if (secret_size > MAX_SECRET_SIZE) { @@ -475,6 +494,13 @@ client(int sds[], const struct fixture *fixture) &fixture->client_secrets[t]); } + ret = gnutls_cipher_get(session); + if ((t == 0 && ret != GNUTLS_CIPHER_AES_128_GCM) || + (t > 0 && ret != GNUTLS_CIPHER_CHACHA20_POLY1305)) { + fail("negotiated unexpected cipher: %s\n", + gnutls_cipher_get_name(ret)); + } + if (t == 0) { /* get the session data size */ ret = @@ -664,6 +690,13 @@ server(int sds[], const struct fixture *fixture) goto skip_early_data; } + ret = gnutls_cipher_get(session); + if ((t == 0 && ret != GNUTLS_CIPHER_AES_128_GCM) || + (t > 0 && ret != GNUTLS_CIPHER_CHACHA20_POLY1305)) { + fail("negotiated unexpected cipher: %s\n", + gnutls_cipher_get_name(ret)); + } + #if TRACE == TRACE_SERVER print_secrets(stderr, "server", fixture->name, t, callback_data.secrets, |