summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZoltán Fridrich <zfridric@redhat.com>2023-01-10 17:11:30 +0000
committerZoltán Fridrich <zfridric@redhat.com>2023-01-10 17:11:30 +0000
commit74bdd762e569861568ccffacd0d6a46676fa79b9 (patch)
tree5fe427910a479a9896402bfd17be98bff9150b9b
parent4e5afffcba3e5f898eca7c450408605969135d48 (diff)
parent9fa9891e01896811a9c44c54844d44c48534d75e (diff)
downloadgnutls-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.texi4
-rw-r--r--lib/ext/compress_certificate.c35
-rw-r--r--lib/ext/compress_certificate.h12
-rw-r--r--lib/gnutls_int.h1
-rw-r--r--lib/tls13/certificate.c13
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);