diff options
author | Zoltán Fridrich <zfridric@redhat.com> | 2023-01-10 17:11:30 +0000 |
---|---|---|
committer | Zoltán Fridrich <zfridric@redhat.com> | 2023-01-10 17:11:30 +0000 |
commit | 74bdd762e569861568ccffacd0d6a46676fa79b9 (patch) | |
tree | 5fe427910a479a9896402bfd17be98bff9150b9b | |
parent | 4e5afffcba3e5f898eca7c450408605969135d48 (diff) | |
parent | 9fa9891e01896811a9c44c54844d44c48534d75e (diff) | |
download | gnutls-74bdd762e569861568ccffacd0d6a46676fa79b9.tar.gz |
Merge branch 'zfridric_devel2' into 'master'
Forbid uncolicited CompressedCertificate messages
Closes #1440
See merge request gnutls/gnutls!1678
-rw-r--r-- | doc/gnutls.texi | 4 | ||||
-rw-r--r-- | lib/ext/compress_certificate.c | 35 | ||||
-rw-r--r-- | lib/ext/compress_certificate.h | 12 | ||||
-rw-r--r-- | lib/gnutls_int.h | 1 | ||||
-rw-r--r-- | lib/tls13/certificate.c | 13 |
5 files changed, 55 insertions, 10 deletions
diff --git a/doc/gnutls.texi b/doc/gnutls.texi index ece0a7c6b1..a07647fb37 100644 --- a/doc/gnutls.texi +++ b/doc/gnutls.texi @@ -16,8 +16,8 @@ This manual is last updated @value{UPDATED} for version @value{VERSION} of GnuTLS. -Copyright @copyright{} 2001-2022 Free Software Foundation, Inc.\\ -Copyright @copyright{} 2001-2022 Nikos Mavrogiannopoulos +Copyright @copyright{} 2001-2023 Free Software Foundation, Inc.\\ +Copyright @copyright{} 2001-2023 Nikos Mavrogiannopoulos @quotation Permission is granted to copy, distribute and/or modify this document diff --git a/lib/ext/compress_certificate.c b/lib/ext/compress_certificate.c index 7d94e47aea..66dd9e9275 100644 --- a/lib/ext/compress_certificate.c +++ b/lib/ext/compress_certificate.c @@ -26,7 +26,8 @@ #include "num.h" #include <ext/compress_certificate.h> -/* Check whether certificate compression method is valid, ie. supported by gnutls */ +/* Check whether certificate compression method is valid, ie. supported by gnutls + */ static inline int is_valid_method(gnutls_compression_method_t method) { @@ -48,7 +49,8 @@ is_valid_method(gnutls_compression_method_t method) } } -/* Converts compression algorithm number established in RFC8879 to internal compression method type */ +/* Converts compression algorithm number established in RFC8879 to internal compression method type + */ gnutls_compression_method_t _gnutls_compress_certificate_num2method(uint16_t num) { @@ -64,7 +66,8 @@ _gnutls_compress_certificate_num2method(uint16_t num) } } -/* Converts compression method type to compression algorithm number established in RFC8879 */ +/* Converts compression method type to compression algorithm number established in RFC8879 + */ int _gnutls_compress_certificate_method2num(gnutls_compression_method_t method) { @@ -80,6 +83,30 @@ _gnutls_compress_certificate_method2num(gnutls_compression_method_t method) } } +/* Returns 1 if the method is set as supported compression method for the session, + * returns 0 otherwise + */ +bool +_gnutls_compress_certificate_is_method_enabled(gnutls_session_t session, + gnutls_compression_method_t method) +{ + int ret; + unsigned i; + compress_certificate_ext_st *priv; + gnutls_ext_priv_data_t epriv; + + ret = _gnutls_hello_ext_get_priv(session, GNUTLS_EXTENSION_COMPRESS_CERTIFICATE, &epriv); + if (ret < 0) + return false; + priv = epriv; + + for (i = 0; i < priv->methods_len; ++i) + if (priv->methods[i] == method) + return true; + + return false; +} + /** * gnutls_compress_certificate_get_selected_method: * @session: is a #gnutls_session_t type. @@ -236,6 +263,8 @@ _gnutls_compress_certificate_send_params(gnutls_session_t session, if (ret < 0) return gnutls_assert_val(ret); + session->internals.hsk_flags |= HSK_COMP_CRT_REQ_SENT; + return bytes_len + 1; } diff --git a/lib/ext/compress_certificate.h b/lib/ext/compress_certificate.h index b7083742ef..e0f445f620 100644 --- a/lib/ext/compress_certificate.h +++ b/lib/ext/compress_certificate.h @@ -35,13 +35,21 @@ typedef struct { extern const hello_ext_entry_st ext_mod_compress_certificate; -gnutls_compression_method_t _gnutls_compress_certificate_num2method(uint16_t num); -int _gnutls_compress_certificate_method2num(gnutls_compression_method_t method); +gnutls_compression_method_t +_gnutls_compress_certificate_num2method(uint16_t num); + +int +_gnutls_compress_certificate_method2num(gnutls_compression_method_t method); + +bool +_gnutls_compress_certificate_is_method_enabled(gnutls_session_t session, + gnutls_compression_method_t method); int _gnutls_compress_certificate_recv_params(gnutls_session_t session, const uint8_t * data, size_t data_size); + int _gnutls_compress_certificate_send_params(gnutls_session_t session, gnutls_buffer_st * data); diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 8ebf6b8e35..9b2afcf80c 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -1354,6 +1354,7 @@ typedef struct { #define HSK_HRR_SENT (1<<3) #define HSK_HRR_RECEIVED (1<<4) #define HSK_CRT_REQ_SENT (1<<5) +#define HSK_COMP_CRT_REQ_SENT (1<<6) /* whether certificate compression has been requested */ #define HSK_KEY_UPDATE_ASKED (1<<7) /* flag is not used during handshake */ #define HSK_FALSE_START_USED (1<<8) /* TLS1.2 only */ #define HSK_HAVE_FFDHE (1<<9) /* whether the peer has advertized at least an FFDHE group */ diff --git a/lib/tls13/certificate.c b/lib/tls13/certificate.c index 979262930e..a9e7c312b5 100644 --- a/lib/tls13/certificate.c +++ b/lib/tls13/certificate.c @@ -35,7 +35,7 @@ static int parse_cert_extension(void *ctx, unsigned tls_id, const uint8_t *data, static int parse_cert_list(gnutls_session_t session, uint8_t * data, size_t data_size); static int compress_certificate(gnutls_buffer_st * buf, unsigned cert_pos_mark, gnutls_compression_method_t comp_method); -static int decompress_certificate(gnutls_buffer_st * buf); +static int decompress_certificate(gnutls_session_t session, gnutls_buffer_st * buf); int _gnutls13_recv_certificate(gnutls_session_t session) { @@ -61,6 +61,10 @@ int _gnutls13_recv_certificate(gnutls_session_t session) /* check if we received compressed certificate */ err = _gnutls_recv_handshake(session, GNUTLS_HANDSHAKE_COMPRESSED_CERTIFICATE_PKT, 0, &buf); if (err >= 0) { + /* fail if we receive unsolicited compressed certificate */ + if (!(session->internals.hsk_flags & HSK_COMP_CRT_REQ_SENT)) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET); + decompress_cert = 1; ret = err; } @@ -79,7 +83,7 @@ int _gnutls13_recv_certificate(gnutls_session_t session) } if (decompress_cert) { - ret = decompress_certificate(&buf); + ret = decompress_certificate(session, &buf); if (ret < 0) { gnutls_assert(); gnutls_alert_send(session, GNUTLS_AL_FATAL, GNUTLS_A_BAD_CERTIFICATE); @@ -613,7 +617,7 @@ cleanup: } static int -decompress_certificate(gnutls_buffer_st * buf) +decompress_certificate(gnutls_session_t session, gnutls_buffer_st * buf) { int ret; size_t method_num, plain_exp_len; @@ -625,6 +629,9 @@ decompress_certificate(gnutls_buffer_st * buf) return gnutls_assert_val(ret); comp_method = _gnutls_compress_certificate_num2method(method_num); + if (!_gnutls_compress_certificate_is_method_enabled(session, comp_method)) + return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); + ret = _gnutls_buffer_pop_prefix24(buf, &plain_exp_len, 0); if (ret < 0) return gnutls_assert_val(ret); |