diff options
author | Daiki Ueno <dueno@redhat.com> | 2019-04-25 17:08:43 +0200 |
---|---|---|
committer | Daiki Ueno <dueno@redhat.com> | 2019-05-14 06:44:38 +0200 |
commit | 2dc96e3b8d0e043bebf0815edaaa945f66ac0531 (patch) | |
tree | df3932ecaf592291b53cb8936d23ba19f9226f50 | |
parent | 9509af0e791b74538de8ffa8dd0d47c05cb08eed (diff) | |
download | gnutls-2dc96e3b8d0e043bebf0815edaaa945f66ac0531.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-- | .gitignore | 1 | ||||
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | devel/libgnutls-latest-x86_64.abi | 8 | ||||
-rw-r--r-- | devel/symbols.last | 4 | ||||
-rw-r--r-- | doc/Makefile.am | 2 | ||||
-rw-r--r-- | doc/manpages/Makefile.am | 1 | ||||
-rw-r--r-- | lib/constate.c | 10 | ||||
-rw-r--r-- | lib/dtls.c | 4 | ||||
-rw-r--r-- | lib/ext/max_record.c | 79 | ||||
-rw-r--r-- | lib/ext/record_size_limit.c | 19 | ||||
-rw-r--r-- | lib/gnutls_int.h | 20 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 1 | ||||
-rw-r--r-- | lib/libgnutls.map | 8 | ||||
-rw-r--r-- | lib/range.c | 4 | ||||
-rw-r--r-- | lib/record.c | 2 | ||||
-rw-r--r-- | lib/session_pack.c | 12 | ||||
-rw-r--r-- | lib/state.c | 4 | ||||
-rw-r--r-- | tests/Makefile.am | 3 | ||||
-rw-r--r-- | tests/tls-record-size-limit-asym.c | 277 |
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 @@ -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]); +} |