diff options
Diffstat (limited to 'lib')
-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 |
11 files changed, 116 insertions, 47 deletions
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 */ |