summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <dueno@redhat.com>2019-04-25 17:08:43 +0200
committerDaiki Ueno <dueno@redhat.com>2019-05-14 06:44:38 +0200
commit2dc96e3b8d0e043bebf0815edaaa945f66ac0531 (patch)
treedf3932ecaf592291b53cb8936d23ba19f9226f50
parent9509af0e791b74538de8ffa8dd0d47c05cb08eed (diff)
downloadgnutls-tmp-record-sizes.tar.gz
ext/record_size_limit: distinguish sending and receiving limitstmp-record-sizes
The previous behavior was that both sending and receiving limits are negotiated to be the same value. It was problematic when: - client sends a record_size_limit with a large value in CH - server sends a record_size_limit with a smaller value in EE - client updates the limit for both sending and receiving, upon receiving EE - server sends a Certificate message larger than the limit With this patch, each peer maintains the sending / receiving limits separately so not to confuse with the contradicting settings. Signed-off-by: Daiki Ueno <dueno@redhat.com>
-rw-r--r--.gitignore1
-rw-r--r--NEWS1
-rw-r--r--devel/libgnutls-latest-x86_64.abi8
-rw-r--r--devel/symbols.last4
-rw-r--r--doc/Makefile.am2
-rw-r--r--doc/manpages/Makefile.am1
-rw-r--r--lib/constate.c10
-rw-r--r--lib/dtls.c4
-rw-r--r--lib/ext/max_record.c79
-rw-r--r--lib/ext/record_size_limit.c19
-rw-r--r--lib/gnutls_int.h20
-rw-r--r--lib/includes/gnutls/gnutls.h.in1
-rw-r--r--lib/libgnutls.map8
-rw-r--r--lib/range.c4
-rw-r--r--lib/record.c2
-rw-r--r--lib/session_pack.c12
-rw-r--r--lib/state.c4
-rw-r--r--tests/Makefile.am3
-rw-r--r--tests/tls-record-size-limit-asym.c277
19 files changed, 410 insertions, 50 deletions
diff --git a/.gitignore b/.gitignore
index f7983c159b..4c0a25a3bf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -765,6 +765,7 @@ tests/tls-max-record
tests/tls-neg-ext-key
tests/tls-neg-ext4-key
tests/tls-record-size-limit
+tests/tls-record-size-limit-asym
tests/tls-rehandshake-anon
tests/tls-rehandshake-cert
tests/tls-rehandshake-cert-2
diff --git a/NEWS b/NEWS
index 0ada7c1a31..c8241ee151 100644
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,7 @@ See the end for copying conditions.
** API and ABI modifications:
gnutls_prf_early: Added
+gnutls_record_set_max_recv_size: Added
* Version 3.6.7 (released 2019-03-27)
diff --git a/devel/libgnutls-latest-x86_64.abi b/devel/libgnutls-latest-x86_64.abi
index c4659d954b..511f61d47b 100644
--- a/devel/libgnutls-latest-x86_64.abi
+++ b/devel/libgnutls-latest-x86_64.abi
@@ -587,7 +587,7 @@
<elf-symbol name='gnutls_pkcs_schema_get_name' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='gnutls_pkcs_schema_get_oid' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='gnutls_prf' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
- <elf-symbol name='gnutls_prf_early' version='GNUTLS_3_6_6' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='gnutls_prf_early' version='GNUTLS_3_6_8' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='gnutls_prf_raw' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='gnutls_prf_rfc5705' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='gnutls_priority_certificate_type_list2' version='GNUTLS_3_6_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -738,6 +738,7 @@
<elf-symbol name='gnutls_record_send_early_data' version='GNUTLS_3_6_5' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='gnutls_record_send_range' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='gnutls_record_set_max_early_data_size' version='GNUTLS_3_6_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='gnutls_record_set_max_recv_size' version='GNUTLS_3_6_8' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='gnutls_record_set_max_size' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='gnutls_record_set_state' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='gnutls_record_set_timeout' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -17228,6 +17229,11 @@
<typedef-decl name='hello_ext_entry_st' type-id='type-id-296' id='type-id-1075'/>
<qualified-type-def type-id='type-id-1075' const='yes' id='type-id-1076'/>
<var-decl name='ext_mod_max_record_size' type-id='type-id-1076' visibility='default'/>
+ <function-decl name='gnutls_record_set_max_recv_size' mangled-name='gnutls_record_set_max_recv_size' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='gnutls_record_set_max_recv_size@@GNUTLS_3_6_6'>
+ <parameter type-id='type-id-236' name='session'/>
+ <parameter type-id='type-id-100' name='size'/>
+ <return type-id='type-id-3'/>
+ </function-decl>
<function-decl name='gnutls_record_set_max_size' mangled-name='gnutls_record_set_max_size' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='gnutls_record_set_max_size@@GNUTLS_3_4'>
<parameter type-id='type-id-236' name='session'/>
<parameter type-id='type-id-100' name='size'/>
diff --git a/devel/symbols.last b/devel/symbols.last
index d9dedea09c..7449e9acc7 100644
--- a/devel/symbols.last
+++ b/devel/symbols.last
@@ -5,6 +5,7 @@ GNUTLS_3_6_3@GNUTLS_3_6_3
GNUTLS_3_6_4@GNUTLS_3_6_4
GNUTLS_3_6_5@GNUTLS_3_6_5
GNUTLS_3_6_6@GNUTLS_3_6_6
+GNUTLS_3_6_8@GNUTLS_3_6_8
_gnutls_global_init_skip@GNUTLS_3_4
gnutls_aead_cipher_decrypt@GNUTLS_3_4
gnutls_aead_cipher_deinit@GNUTLS_3_4
@@ -553,7 +554,7 @@ gnutls_pkcs8_info@GNUTLS_3_4
gnutls_pkcs_schema_get_name@GNUTLS_3_4
gnutls_pkcs_schema_get_oid@GNUTLS_3_4
gnutls_prf@GNUTLS_3_4
-gnutls_prf_early@GNUTLS_3_6_6
+gnutls_prf_early@GNUTLS_3_6_8
gnutls_prf_raw@GNUTLS_3_4
gnutls_prf_rfc5705@GNUTLS_3_4
gnutls_priority_certificate_type_list2@GNUTLS_3_6_4
@@ -705,6 +706,7 @@ gnutls_record_send@GNUTLS_3_4
gnutls_record_send_early_data@GNUTLS_3_6_5
gnutls_record_send_range@GNUTLS_3_4
gnutls_record_set_max_early_data_size@GNUTLS_3_6_4
+gnutls_record_set_max_recv_size@GNUTLS_3_6_8
gnutls_record_set_max_size@GNUTLS_3_4
gnutls_record_set_state@GNUTLS_3_4
gnutls_record_set_timeout@GNUTLS_3_4
diff --git a/doc/Makefile.am b/doc/Makefile.am
index c60d0e46dd..bba2c52c97 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -1851,6 +1851,8 @@ FUNCS += functions/gnutls_record_send_range
FUNCS += functions/gnutls_record_send_range.short
FUNCS += functions/gnutls_record_set_max_early_data_size
FUNCS += functions/gnutls_record_set_max_early_data_size.short
+FUNCS += functions/gnutls_record_set_max_recv_size
+FUNCS += functions/gnutls_record_set_max_recv_size.short
FUNCS += functions/gnutls_record_set_max_size
FUNCS += functions/gnutls_record_set_max_size.short
FUNCS += functions/gnutls_record_set_state
diff --git a/doc/manpages/Makefile.am b/doc/manpages/Makefile.am
index bbf4220c09..503b2c14bc 100644
--- a/doc/manpages/Makefile.am
+++ b/doc/manpages/Makefile.am
@@ -727,6 +727,7 @@ APIMANS += gnutls_record_send2.3
APIMANS += gnutls_record_send_early_data.3
APIMANS += gnutls_record_send_range.3
APIMANS += gnutls_record_set_max_early_data_size.3
+APIMANS += gnutls_record_set_max_recv_size.3
APIMANS += gnutls_record_set_max_size.3
APIMANS += gnutls_record_set_state.3
APIMANS += gnutls_record_set_timeout.3
diff --git a/lib/constate.c b/lib/constate.c
index be784bce64..51a4eca30a 100644
--- a/lib/constate.c
+++ b/lib/constate.c
@@ -821,14 +821,12 @@ int _gnutls_write_connection_state_init(gnutls_session_t session)
session->security_parameters.epoch_next;
int ret;
- /* reset max_record_recv_size if it was negotiated in the
+ /* reset max_record_send_size if it was negotiated in the
* previous handshake using the record_size_limit extension */
- if (session->security_parameters.max_record_recv_size !=
- session->security_parameters.max_record_send_size &&
- !(session->internals.hsk_flags & HSK_RECORD_SIZE_LIMIT_NEGOTIATED) &&
+ if (!(session->internals.hsk_flags & HSK_RECORD_SIZE_LIMIT_NEGOTIATED) &&
session->security_parameters.entity == GNUTLS_SERVER)
- session->security_parameters.max_record_recv_size =
- session->security_parameters.max_record_send_size;
+ session->security_parameters.max_record_send_size =
+ session->security_parameters.max_user_record_send_size;
/* Update internals from CipherSuite selected.
* If we are resuming just copy the connection session
diff --git a/lib/dtls.c b/lib/dtls.c
index d5ff906b18..b5f6cf2cb5 100644
--- a/lib/dtls.c
+++ b/lib/dtls.c
@@ -65,8 +65,8 @@ transmit_message(gnutls_session_t session,
unsigned int mtu =
gnutls_dtls_get_data_mtu(session);
- if (session->security_parameters.max_record_recv_size < mtu)
- mtu = session->security_parameters.max_record_recv_size;
+ if (session->security_parameters.max_record_send_size < mtu)
+ mtu = session->security_parameters.max_record_send_size;
mtu -= DTLS_HANDSHAKE_HEADER_SIZE;
diff --git a/lib/ext/max_record.c b/lib/ext/max_record.c
index 681c943863..0fb97b9789 100644
--- a/lib/ext/max_record.c
+++ b/lib/ext/max_record.c
@@ -105,11 +105,13 @@ _gnutls_max_record_recv_params(gnutls_session_t session,
}
if (new_size != session->security_parameters.
- max_record_send_size) {
+ max_user_record_send_size) {
gnutls_assert();
return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
} else {
session->security_parameters.
+ max_record_send_size = new_size;
+ session->security_parameters.
max_record_recv_size = new_size;
}
@@ -132,11 +134,18 @@ _gnutls_max_record_send_params(gnutls_session_t session,
/* this function sends the client extension data (dnsname) */
if (session->security_parameters.entity == GNUTLS_CLIENT) {
- if (session->security_parameters.max_record_send_size !=
+ /* if the user limits for sending and receiving are
+ * different, that means the programmer had chosen to
+ * use record_size_limit instead */
+ if (session->security_parameters.max_user_record_send_size !=
+ session->security_parameters.max_user_record_recv_size)
+ return 0;
+
+ if (session->security_parameters.max_user_record_send_size !=
DEFAULT_MAX_RECORD_SIZE) {
ret = _gnutls_mre_record2num
(session->security_parameters.
- max_record_send_size);
+ max_user_record_send_size);
/* it's not an error, as long as we send the
* record_size_limit extension with that value */
@@ -239,23 +248,22 @@ size_t gnutls_record_get_max_size(gnutls_session_t session)
* @session: is a #gnutls_session_t type.
* @size: is the new size
*
- * This function sets the maximum record packet size in this
- * connection.
- *
- * The requested record size does get in effect immediately only while
- * sending data. The receive part will take effect after a successful
- * handshake.
+ * This function sets the maximum amount of plaintext sent and
+ * received in a record in this connection.
*
* Prior to 3.6.4, this function was implemented using a TLS extension
- * called 'max record size', which limits the acceptable values to
- * 512(=2^9), 1024(=2^10), 2048(=2^11) and 4096(=2^12). Since 3.6.4,
- * it uses another TLS extension called 'record size limit', which
- * doesn't have the limitation, as long as the value ranges between
- * 512 and 16384. Note that not all TLS implementations use or even
- * understand those extension.
+ * called 'max fragment length', which limits the acceptable values to
+ * 512(=2^9), 1024(=2^10), 2048(=2^11) and 4096(=2^12).
*
- * In TLS 1.3, the value is the length of plaintext content plus its
- * padding, excluding content type octet.
+ * Since 3.6.4, the limit is also negotiated through a new TLS
+ * extension called 'record size limit', which doesn't have the
+ * limitation, as long as the value ranges between 512 and 16384.
+ * Note that while the 'record size limit' extension is preferred, not
+ * all TLS implementations use or even understand the extension.
+ *
+ * Deprecated: if the client can assume that the 'record size limit'
+ * extension is supported by the server, we recommend using
+ * gnutls_record_set_max_recv_size() instead.
*
* Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
* otherwise a negative error code is returned.
@@ -265,7 +273,42 @@ ssize_t gnutls_record_set_max_size(gnutls_session_t session, size_t size)
if (size < MIN_RECORD_SIZE || size > DEFAULT_MAX_RECORD_SIZE)
return GNUTLS_E_INVALID_REQUEST;
- session->security_parameters.max_record_send_size = size;
+ if (session->internals.handshake_in_progress)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+ session->security_parameters.max_user_record_send_size = size;
+ session->security_parameters.max_user_record_recv_size = size;
+
+ return 0;
+}
+
+/**
+ * gnutls_record_set_max_recv_size:
+ * @session: is a #gnutls_session_t type.
+ * @size: is the new size
+ *
+ * This function sets the maximum amount of plaintext received in a
+ * record in this connection.
+ *
+ * The limit is also negotiated through a TLS extension called 'record
+ * size limit'. Note that while the 'record size limit' extension is
+ * preferred, not all TLS implementations use or even understand the
+ * extension.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
+ * otherwise a negative error code is returned.
+ *
+ * Since: 3.6.8
+ **/
+ssize_t gnutls_record_set_max_recv_size(gnutls_session_t session, size_t size)
+{
+ if (size < MIN_RECORD_SIZE || size > DEFAULT_MAX_RECORD_SIZE)
+ return GNUTLS_E_INVALID_REQUEST;
+
+ if (session->internals.handshake_in_progress)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+ session->security_parameters.max_user_record_recv_size = size;
return 0;
}
diff --git a/lib/ext/record_size_limit.c b/lib/ext/record_size_limit.c
index 8c495939d8..8b491da72c 100644
--- a/lib/ext/record_size_limit.c
+++ b/lib/ext/record_size_limit.c
@@ -81,6 +81,12 @@ _gnutls_record_size_limit_recv_params(gnutls_session_t session,
session->internals.hsk_flags |= HSK_RECORD_SIZE_LIMIT_NEGOTIATED;
+ /* client uses the reception of this extension as an
+ * indication of the request was accepted by the server */
+ if (session->security_parameters.entity == GNUTLS_CLIENT)
+ session->security_parameters.max_record_recv_size =
+ session->security_parameters.max_user_record_recv_size;
+
_gnutls_handshake_log("EXT[%p]: record_size_limit %u negotiated\n",
session, (unsigned)new_size);
@@ -89,9 +95,9 @@ _gnutls_record_size_limit_recv_params(gnutls_session_t session,
if (unlikely(vers == NULL))
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
- session->security_parameters.max_record_recv_size =
+ session->security_parameters.max_record_send_size =
MIN(new_size - vers->tls13_sem,
- session->security_parameters.max_record_send_size);
+ session->security_parameters.max_user_record_send_size);
return 0;
}
@@ -105,11 +111,11 @@ _gnutls_record_size_limit_send_params(gnutls_session_t session,
int ret;
uint16_t send_size;
- assert(session->security_parameters.max_record_send_size >= 64 &&
- session->security_parameters.max_record_send_size <=
+ assert(session->security_parameters.max_user_record_recv_size >= 64 &&
+ session->security_parameters.max_user_record_recv_size <=
DEFAULT_MAX_RECORD_SIZE);
- send_size = session->security_parameters.max_record_send_size;
+ send_size = session->security_parameters.max_user_record_recv_size;
if (session->security_parameters.entity == GNUTLS_SERVER) {
const version_entry_st *vers;
@@ -124,6 +130,9 @@ _gnutls_record_size_limit_send_params(gnutls_session_t session,
if (unlikely(vers == NULL))
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+ session->security_parameters.max_record_recv_size =
+ send_size;
+
send_size += vers->tls13_sem;
} else {
const version_entry_st *vers;
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 2c8d259086..50251a356a 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -779,12 +779,18 @@ typedef struct {
/* whether client has agreed in post handshake auth - only set on server side */
uint8_t post_handshake_auth;
- /* The send size is the one requested by the programmer.
- * The recv size is the one negotiated with the peer.
+ /* The maximum amount of plaintext sent in a record,
+ * negotiated with the peer.
*/
uint16_t max_record_send_size;
uint16_t max_record_recv_size;
+ /* The maximum amount of plaintext sent in a record, set by
+ * the programmer.
+ */
+ uint16_t max_user_record_send_size;
+ uint16_t max_user_record_recv_size;
+
/* The maximum amount of early data */
uint32_t max_early_data_size;
@@ -1551,17 +1557,17 @@ inline static int _gnutls_set_current_version(gnutls_session_t s, unsigned v)
return 0;
}
-/* Returns the maximum size of the plaintext to be sent, considering
+/* Returns the maximum amount of the plaintext to be sent, considering
* both user-specified/negotiated maximum values.
*/
-inline static size_t max_user_send_size(gnutls_session_t session,
- record_parameters_st *
- record_params)
+inline static size_t max_record_send_size(gnutls_session_t session,
+ record_parameters_st *
+ record_params)
{
size_t max;
max = MIN(session->security_parameters.max_record_send_size,
- session->security_parameters.max_record_recv_size);
+ session->security_parameters.max_user_record_send_size);
if (IS_DTLS(session))
max = MIN(gnutls_dtls_get_data_mtu(session), max);
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index 0801203128..87ce08823b 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -1447,6 +1447,7 @@ int gnutls_record_get_direction(gnutls_session_t session);
size_t gnutls_record_get_max_size(gnutls_session_t session);
ssize_t gnutls_record_set_max_size(gnutls_session_t session, size_t size);
+ssize_t gnutls_record_set_max_recv_size(gnutls_session_t session, size_t size);
size_t gnutls_record_check_pending(gnutls_session_t session);
size_t gnutls_record_check_corked(gnutls_session_t session);
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 2bc33ee732..ec8aadf558 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -1271,9 +1271,15 @@ GNUTLS_3_6_6
gnutls_certificate_set_rawpk_key_file;
gnutls_pcert_import_rawpk;
gnutls_pcert_import_rawpk_raw;
- gnutls_prf_early;
} GNUTLS_3_6_5;
+GNUTLS_3_6_8
+{
+ global:
+ gnutls_prf_early;
+ gnutls_record_set_max_recv_size;
+} GNUTLS_3_6_6;
+
GNUTLS_FIPS140_3_4 {
global:
gnutls_cipher_self_test;
diff --git a/lib/range.c b/lib/range.c
index 788c56e92d..041578c48b 100644
--- a/lib/range.c
+++ b/lib/range.c
@@ -66,7 +66,7 @@ _gnutls_range_max_lh_pad(gnutls_session_t session, ssize_t data_length,
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
if (vers->tls13_sem) {
- max_pad = max_user_send_size(session, record_params);
+ max_pad = max_record_send_size(session, record_params);
fixed_pad = 2;
} else {
max_pad = MAX_PAD_SIZE;
@@ -182,7 +182,7 @@ gnutls_range_split(gnutls_session_t session,
if (ret < 0)
return gnutls_assert_val(ret);
- max_frag = max_user_send_size(session, record_params);
+ max_frag = max_record_send_size(session, record_params);
if (orig_high == orig_low) {
int length = MIN(orig_high, max_frag);
diff --git a/lib/record.c b/lib/record.c
index ba269037d7..7d661e2309 100644
--- a/lib/record.c
+++ b/lib/record.c
@@ -467,7 +467,7 @@ _gnutls_send_tlen_int(gnutls_session_t session, content_type_t type,
return GNUTLS_E_INVALID_SESSION;
}
- max_send_size = max_user_send_size(session, record_params);
+ max_send_size = max_record_send_size(session, record_params);
if (data_size > max_send_size) {
if (IS_DTLS(session))
diff --git a/lib/session_pack.c b/lib/session_pack.c
index 4b485ba9d6..b655b71289 100644
--- a/lib/session_pack.c
+++ b/lib/session_pack.c
@@ -918,20 +918,22 @@ pack_security_parameters(gnutls_session_t session, gnutls_buffer_st * ps)
BUFFER_APPEND_PFX1(ps, session->security_parameters.server_random,
GNUTLS_RANDOM_SIZE);
- BUFFER_APPEND_NUM(ps,
- session->security_parameters.
- max_record_send_size);
-
/* reset max_record_recv_size if it was negotiated
* using the record_size_limit extension */
if (session->internals.hsk_flags & HSK_RECORD_SIZE_LIMIT_NEGOTIATED) {
BUFFER_APPEND_NUM(ps,
session->security_parameters.
- max_record_send_size);
+ max_user_record_send_size);
+ BUFFER_APPEND_NUM(ps,
+ session->security_parameters.
+ max_user_record_recv_size);
} else {
BUFFER_APPEND_NUM(ps,
session->security_parameters.
max_record_recv_size);
+ BUFFER_APPEND_NUM(ps,
+ session->security_parameters.
+ max_record_send_size);
}
if (session->security_parameters.grp) {
diff --git a/lib/state.c b/lib/state.c
index 97461e6722..0aec397241 100644
--- a/lib/state.c
+++ b/lib/state.c
@@ -522,6 +522,10 @@ int gnutls_init(gnutls_session_t * session, unsigned int flags)
DEFAULT_MAX_RECORD_SIZE;
(*session)->security_parameters.max_record_send_size =
DEFAULT_MAX_RECORD_SIZE;
+ (*session)->security_parameters.max_user_record_recv_size =
+ DEFAULT_MAX_RECORD_SIZE;
+ (*session)->security_parameters.max_user_record_send_size =
+ DEFAULT_MAX_RECORD_SIZE;
/* set the default early data size for TLS
*/
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 940e1ba605..eb65e94858 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -208,7 +208,8 @@ ctests += mini-record-2 simple gnutls_hmac_fast set_pkcs12_cred cert certuniquei
dss-sig-val sign-pk-api tls-session-ext-override record-pad \
tls13-server-kx-neg gnutls_ext_raw_parse_dtls key-export-pkcs8 \
null_retrieve_function tls-record-size-limit tls-crt_type-neg \
- resume-with-stek-expiration resume-with-previous-stek rawpk-api
+ resume-with-stek-expiration resume-with-previous-stek rawpk-api \
+ tls-record-size-limit-asym
if HAVE_SECCOMP_TESTS
ctests += dtls-with-seccomp tls-with-seccomp dtls-client-with-seccomp tls-client-with-seccomp
diff --git a/tests/tls-record-size-limit-asym.c b/tests/tls-record-size-limit-asym.c
new file mode 100644
index 0000000000..1fd8289883
--- /dev/null
+++ b/tests/tls-record-size-limit-asym.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2015, 2019 Red Hat, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos, Daiki Ueno
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GnuTLS; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <gnutls/gnutls.h>
+#include "utils.h"
+
+#include "eagain-common.h"
+
+#include "cert-common.h"
+
+/* This tests whether the max-record extension is respected on TLS.
+ */
+
+const char *side;
+
+static void tls_log_func(int level, const char *str)
+{
+ fprintf(stderr, "%s|<%d>| %s", side, level, str);
+}
+
+#define MAX_BUF 16384
+static char buffer[MAX_BUF];
+
+struct test_exp_st {
+ int error;
+ size_t size;
+};
+
+struct test_st {
+ const char *prio;
+ size_t server_max_size;
+ size_t client_max_size;
+
+ struct test_exp_st server_exp;
+ struct test_exp_st client_exp;
+};
+
+static void start(const struct test_st *test)
+{
+ int ret;
+ /* Server stuff. */
+ gnutls_certificate_credentials_t serverx509cred;
+ gnutls_session_t server;
+ int sret = GNUTLS_E_AGAIN;
+ /* Client stuff. */
+ gnutls_certificate_credentials_t clientx509cred;
+ gnutls_session_t client;
+ int cret = GNUTLS_E_AGAIN;
+
+ printf("testing server limit %d and client limit %d in %s\n",
+ (int)test->server_max_size, (int)test->client_max_size,
+ test->prio);
+
+ global_init();
+
+ /* General init. */
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(6);
+
+ /* Init server */
+ assert(gnutls_certificate_allocate_credentials(&serverx509cred) >= 0);
+ assert(gnutls_certificate_set_x509_key_mem(serverx509cred,
+ &server2_cert, &server2_key,
+ GNUTLS_X509_FMT_PEM) >= 0);
+
+ assert(gnutls_init(&server, GNUTLS_SERVER) >= 0);
+ assert(gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE,
+ serverx509cred) >= 0);
+
+ assert(gnutls_priority_set_direct(server, test->prio, NULL) >= 0);
+
+ ret = gnutls_record_set_max_recv_size(server, test->server_max_size);
+ if (ret != test->server_exp.error)
+ fail("server: unexpected error from gnutls_record_set_max_recv_size()");
+
+ gnutls_transport_set_push_function(server, server_push);
+ gnutls_transport_set_pull_function(server, server_pull);
+ gnutls_transport_set_pull_timeout_function(server,
+ server_pull_timeout_func);
+ gnutls_transport_set_ptr(server, server);
+
+
+ /* Init client */
+ assert(gnutls_certificate_allocate_credentials(&clientx509cred) >= 0);
+
+ assert(gnutls_certificate_set_x509_trust_mem(clientx509cred, &ca2_cert, GNUTLS_X509_FMT_PEM) >= 0);
+
+ assert(gnutls_init(&client, GNUTLS_CLIENT) >= 0);
+
+ assert(gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE,
+ clientx509cred) >= 0);
+
+ assert(gnutls_priority_set_direct(client, test->prio, NULL) >= 0);
+
+ ret = gnutls_record_set_max_recv_size(client, test->client_max_size);
+ if (ret != test->client_exp.error)
+ fail("client: unexpected error from gnutls_record_set_max_recv_size()");
+
+ gnutls_transport_set_push_function(client, client_push);
+ gnutls_transport_set_pull_function(client, client_pull);
+ gnutls_transport_set_pull_timeout_function(client,
+ client_pull_timeout_func);
+ gnutls_transport_set_ptr(client, client);
+
+ HANDSHAKE(client, server);
+
+ memset(buffer, 1, sizeof(buffer));
+ ret = gnutls_record_send(server, buffer, test->client_max_size + 1);
+ if (ret < 0) {
+ gnutls_perror(ret);
+ exit(1);
+ }
+ if (ret != (int)test->server_exp.size)
+ fail("server: unexpected record size sent: %d (%d)\n",
+ ret, (int)test->server_exp.size);
+ success("server: did not send a %d-byte packet\n",
+ (int)test->server_exp.size);
+
+ ret = gnutls_record_send(server, buffer, test->client_max_size);
+ if (ret < 0) {
+ gnutls_perror(ret);
+ exit(1);
+ }
+ success("server: did send a %d-byte packet\n",
+ (int)test->client_max_size);
+
+ ret = gnutls_record_send(client, buffer, test->server_max_size + 1);
+ if (ret < 0) {
+ gnutls_perror(ret);
+ exit(1);
+ }
+ if (ret != (int)test->client_exp.size)
+ fail("client: unexpected record size sent: %d (%d)\n",
+ ret, (int)test->client_exp.size);
+ success("client: did not send a %d-byte packet\n",
+ (int)test->server_max_size + 1);
+
+ ret = gnutls_record_send(client, buffer, test->server_max_size);
+ if (ret < 0) {
+ gnutls_perror(ret);
+ exit(1);
+ }
+ success("client: did send a %d-byte packet\n",
+ (int)test->server_max_size);
+
+ gnutls_bye(client, GNUTLS_SHUT_RDWR);
+ gnutls_bye(server, GNUTLS_SHUT_RDWR);
+
+ gnutls_deinit(client);
+ gnutls_deinit(server);
+
+ gnutls_certificate_free_credentials(serverx509cred);
+ gnutls_certificate_free_credentials(clientx509cred);
+
+ gnutls_global_deinit();
+
+ reset_buffers();
+}
+
+static const struct test_st tests[] = {
+ {
+ .prio = "NORMAL:-VERS-ALL:+VERS-TLS1.2",
+ .server_max_size = 512,
+ .client_max_size = 16384,
+ .server_exp = {
+ .error = 0,
+ .size = 16384,
+ },
+ .client_exp = {
+ .error = 0,
+ .size = 512,
+ }
+ },
+ {
+ .prio = "NORMAL:-VERS-ALL:+VERS-TLS1.2",
+ .server_max_size = 16384,
+ .client_max_size = 512,
+ .server_exp = {
+ .error = 0,
+ .size = 512,
+ },
+ .client_exp = {
+ .error = 0,
+ .size = 16384,
+ }
+ },
+ {
+ .prio = "NORMAL:-VERS-ALL:+VERS-TLS1.3",
+ .server_max_size = 512,
+ .client_max_size = 16384,
+ .server_exp = {
+ .error = 0,
+ .size = 16384,
+ },
+ .client_exp = {
+ .error = 0,
+ .size = 512,
+ }
+ },
+ {
+ .prio = "NORMAL:-VERS-ALL:+VERS-TLS1.3",
+ .server_max_size = 16384,
+ .client_max_size = 512,
+ .server_exp = {
+ .error = 0,
+ .size = 512,
+ },
+ .client_exp = {
+ .error = 0,
+ .size = 16384,
+ }
+ },
+ {
+ .prio = "NORMAL",
+ .server_max_size = 512,
+ .client_max_size = 16384,
+ .server_exp = {
+ .error = 0,
+ .size = 16384,
+ },
+ .client_exp = {
+ .error = 0,
+ .size = 512,
+ }
+ },
+ {
+ .prio = "NORMAL",
+ .server_max_size = 16384,
+ .client_max_size = 512,
+ .server_exp = {
+ .error = 0,
+ .size = 512,
+ },
+ .client_exp = {
+ .error = 0,
+ .size = 16384,
+ }
+ }
+};
+
+void doit(void)
+{
+ size_t i;
+ for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ start(&tests[i]);
+}