From 1d35f33fc77f569f798f66a83a11c9648d35f517 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Apr 28 2020 09:41:03 +0000 Subject: import gnutls-3.6.8-9.el8 --- diff --git a/SOURCES/gnutls-3.6.8-decr-len.patch b/SOURCES/gnutls-3.6.8-decr-len.patch new file mode 100644 index 0000000..30272a1 --- /dev/null +++ b/SOURCES/gnutls-3.6.8-decr-len.patch @@ -0,0 +1,687 @@ +From e0fe31f1fc2ba13ada1d6bc35231847b75be4ee9 Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Thu, 8 Aug 2019 18:02:08 +0200 +Subject: [PATCH 1/2] gnutls_int.h: make DECR_LEN neutral to signedness + +DECR_LEN was previously implemented in a way that it first decrements +the given length and then checks whether the result is negative. This +requires the caller to properly coerce the length argument to a signed +integer, before invoking the macro. + +Signed-off-by: Daiki Ueno +--- + lib/gnutls_int.h | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h +index 179d71b4a..7f7b6a7c9 100644 +--- a/lib/gnutls_int.h ++++ b/lib/gnutls_int.h +@@ -256,14 +256,15 @@ typedef enum record_send_state_t { + + #define MEMSUB(x,y) ((ssize_t)((ptrdiff_t)x-(ptrdiff_t)y)) + +-#define DECR_LEN(len, x) do { len-=x; if (len<0) {gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;} } while (0) ++#define DECR_LEN(len, x) DECR_LENGTH_RET(len, x, GNUTLS_E_UNEXPECTED_PACKET_LENGTH) + #define DECR_LEN_FINAL(len, x) do { \ +- len-=x; \ +- if (len != 0) \ ++ if (len != x) \ + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); \ ++ else \ ++ len = 0; \ + } while (0) +-#define DECR_LENGTH_RET(len, x, RET) do { len-=x; if (len<0) {gnutls_assert(); return RET;} } while (0) +-#define DECR_LENGTH_COM(len, x, COM) do { len-=x; if (len<0) {gnutls_assert(); COM;} } while (0) ++#define DECR_LENGTH_RET(len, x, RET) DECR_LENGTH_COM(len, x, return RET) ++#define DECR_LENGTH_COM(len, x, COM) do { if (len +Date: Thu, 8 Aug 2019 18:04:18 +0200 +Subject: [PATCH 2/2] lib/*: remove unnecessary cast to ssize_t + +Signed-off-by: Daiki Ueno +--- + lib/crypto-api.c | 10 +++++----- + lib/ext/alpn.c | 3 +-- + lib/ext/client_cert_type.c | 9 ++++----- + lib/ext/cookie.c | 5 ++--- + lib/ext/ec_point_formats.c | 7 +++---- + lib/ext/key_share.c | 5 ++--- + lib/ext/max_record.c | 3 +-- + lib/ext/psk_ke_modes.c | 3 +-- + lib/ext/record_size_limit.c | 3 +-- + lib/ext/safe_renegotiation.c | 3 +-- + lib/ext/server_cert_type.c | 9 ++++----- + lib/ext/server_name.c | 3 +-- + lib/ext/session_ticket.c | 5 ++--- + lib/ext/signature.c | 3 +-- + lib/ext/srp.c | 3 +-- + lib/ext/srtp.c | 5 ++--- + lib/ext/status_request.c | 3 +-- + lib/ext/supported_groups.c | 3 +-- + lib/ext/supported_versions.c | 5 ++--- + lib/extv.c | 8 ++++---- + lib/sslv2_compat.c | 3 +-- + lib/supplemental.c | 4 ++-- + lib/tls13/certificate.c | 21 +++++++++++---------- + lib/tls13/psk_ext_parser.c | 4 +--- + lib/tls13/psk_ext_parser.h | 4 ++-- + lib/tls13/session_ticket.c | 2 +- + 26 files changed, 58 insertions(+), 78 deletions(-) + +diff --git a/lib/crypto-api.c b/lib/crypto-api.c +index 2834c0199..09b3d7bfc 100644 +--- a/lib/crypto-api.c ++++ b/lib/crypto-api.c +@@ -990,9 +990,9 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle, + api_aead_cipher_hd_st *h = handle; + ssize_t ret; + uint8_t *dst; +- ssize_t dst_size, total = 0; ++ size_t dst_size, total = 0; + uint8_t *p; +- ssize_t blocksize = handle->ctx_enc.e->blocksize; ++ size_t blocksize = handle->ctx_enc.e->blocksize; + struct iov_iter_st iter; + size_t blocks; + +@@ -1071,7 +1071,7 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle, + if (ret == 0) + break; + blocks = ret; +- if (unlikely((size_t) dst_size < blocksize * blocks)) ++ if (unlikely(dst_size < blocksize * blocks)) + return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); + ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, p, + blocksize * blocks, +@@ -1083,7 +1083,7 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle, + total += blocksize * blocks; + } + if (iter.block_offset > 0) { +- if (unlikely((size_t) dst_size < iter.block_offset)) ++ if (unlikely(dst_size < iter.block_offset)) + return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); + ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, + iter.block, iter.block_offset, +@@ -1095,7 +1095,7 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle, + total += iter.block_offset; + } + +- if ((size_t)dst_size < tag_size) ++ if (dst_size < tag_size) + return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); + + _gnutls_cipher_tag(&handle->ctx_enc, dst, tag_size); +diff --git a/lib/ext/alpn.c b/lib/ext/alpn.c +index 34f6ce09d..b9991f0a1 100644 +--- a/lib/ext/alpn.c ++++ b/lib/ext/alpn.c +@@ -51,13 +51,12 @@ const hello_ext_entry_st ext_mod_alpn = { + + static int + _gnutls_alpn_recv_params(gnutls_session_t session, +- const uint8_t * data, size_t _data_size) ++ const uint8_t * data, size_t data_size) + { + unsigned int i; + int ret; + const uint8_t *p = data; + unsigned len1, len; +- ssize_t data_size = _data_size; + alpn_ext_st *priv; + gnutls_ext_priv_data_t epriv; + int selected_protocol_index; +diff --git a/lib/ext/client_cert_type.c b/lib/ext/client_cert_type.c +index 471d42c5f..b627b71f9 100644 +--- a/lib/ext/client_cert_type.c ++++ b/lib/ext/client_cert_type.c +@@ -73,7 +73,6 @@ static int _gnutls_client_cert_type_recv_params(gnutls_session_t session, + gnutls_certificate_type_t cert_type; + + uint8_t i, found = 0; +- ssize_t len = data_size; + const uint8_t* pdata = data; + + /* Only activate this extension if we have cert credentials set +@@ -86,7 +85,7 @@ static int _gnutls_client_cert_type_recv_params(gnutls_session_t session, + + /* Compare packet length with expected packet length. For the + * client this is a single byte. */ +- if (len != 1) { ++ if (data_size != 1) { + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + } +@@ -136,8 +135,8 @@ static int _gnutls_client_cert_type_recv_params(gnutls_session_t session, + + } else { // server mode + // Compare packet length with expected packet length. +- DECR_LEN(len, 1); +- if (data[0] != len) { ++ DECR_LEN(data_size, 1); ++ if (data[0] != data_size) { + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + } +@@ -145,7 +144,7 @@ static int _gnutls_client_cert_type_recv_params(gnutls_session_t session, + + // Assign the contents of our data buffer to a gnutls_datum_t + cert_types.data = (uint8_t*)pdata; // Need casting to get rid of 'discards const qualifier' warning +- cert_types.size = len; ++ cert_types.size = data_size; + + // Store the client certificate types in our session + _gnutls_hello_ext_set_datum(session, +diff --git a/lib/ext/cookie.c b/lib/ext/cookie.c +index 1e66c3d49..0feb2f0e5 100644 +--- a/lib/ext/cookie.c ++++ b/lib/ext/cookie.c +@@ -53,10 +53,9 @@ const hello_ext_entry_st ext_mod_cookie = { + /* Only client sends this extension. */ + static int + cookie_recv_params(gnutls_session_t session, +- const uint8_t * data, size_t _data_size) ++ const uint8_t * data, size_t data_size) + { +- ssize_t data_size = _data_size; +- ssize_t csize; ++ size_t csize; + int ret; + gnutls_datum_t tmp; + +diff --git a/lib/ext/ec_point_formats.c b/lib/ext/ec_point_formats.c +index eb59ec139..c702d434c 100644 +--- a/lib/ext/ec_point_formats.c ++++ b/lib/ext/ec_point_formats.c +@@ -57,11 +57,10 @@ const hello_ext_entry_st ext_mod_supported_ec_point_formats = { + static int + _gnutls_supported_ec_point_formats_recv_params(gnutls_session_t session, + const uint8_t * data, +- size_t _data_size) ++ size_t data_size) + { +- int len, i; ++ size_t len, i; + int uncompressed = 0; +- int data_size = _data_size; + + if (session->security_parameters.entity == GNUTLS_CLIENT) { + if (data_size < 1) +@@ -91,7 +90,7 @@ _gnutls_supported_ec_point_formats_recv_params(gnutls_session_t session, + /* only sanity check here. We only support uncompressed points + * and a client must support it thus nothing to check. + */ +- if (_data_size < 1) ++ if (data_size < 1) + return + gnutls_assert_val + (GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION); +diff --git a/lib/ext/key_share.c b/lib/ext/key_share.c +index 599eff8fb..8f0912e69 100644 +--- a/lib/ext/key_share.c ++++ b/lib/ext/key_share.c +@@ -504,11 +504,10 @@ client_use_key_share(gnutls_session_t session, const gnutls_group_entry_st *grou + + static int + key_share_recv_params(gnutls_session_t session, +- const uint8_t * data, size_t _data_size) ++ const uint8_t * data, size_t data_size) + { + int ret; +- ssize_t data_size = _data_size; +- ssize_t size; ++ size_t size; + unsigned gid; + const version_entry_st *ver; + const gnutls_group_entry_st *group; +diff --git a/lib/ext/max_record.c b/lib/ext/max_record.c +index dbb98cf62..3cada69be 100644 +--- a/lib/ext/max_record.c ++++ b/lib/ext/max_record.c +@@ -65,10 +65,9 @@ const hello_ext_entry_st ext_mod_max_record_size = { + + static int + _gnutls_max_record_recv_params(gnutls_session_t session, +- const uint8_t * data, size_t _data_size) ++ const uint8_t * data, size_t data_size) + { + ssize_t new_size; +- ssize_t data_size = _data_size; + + if (session->internals.hsk_flags & HSK_RECORD_SIZE_LIMIT_NEGOTIATED) + return 0; +diff --git a/lib/ext/psk_ke_modes.c b/lib/ext/psk_ke_modes.c +index da7a55098..8d8effb43 100644 +--- a/lib/ext/psk_ke_modes.c ++++ b/lib/ext/psk_ke_modes.c +@@ -106,10 +106,9 @@ psk_ke_modes_send_params(gnutls_session_t session, + */ + static int + psk_ke_modes_recv_params(gnutls_session_t session, +- const unsigned char *data, size_t _len) ++ const unsigned char *data, size_t len) + { + uint8_t ke_modes_len; +- ssize_t len = _len; + const version_entry_st *vers = get_version(session); + gnutls_psk_server_credentials_t cred; + int dhpsk_pos = MAX_POS; +diff --git a/lib/ext/record_size_limit.c b/lib/ext/record_size_limit.c +index e9fe6a1d8..0e94fece3 100644 +--- a/lib/ext/record_size_limit.c ++++ b/lib/ext/record_size_limit.c +@@ -48,10 +48,9 @@ const hello_ext_entry_st ext_mod_record_size_limit = { + + static int + _gnutls_record_size_limit_recv_params(gnutls_session_t session, +- const uint8_t * data, size_t _data_size) ++ const uint8_t * data, size_t data_size) + { + ssize_t new_size; +- ssize_t data_size = _data_size; + const version_entry_st *vers; + + DECR_LEN(data_size, 2); +diff --git a/lib/ext/safe_renegotiation.c b/lib/ext/safe_renegotiation.c +index 6424f45b5..bb4a57e45 100644 +--- a/lib/ext/safe_renegotiation.c ++++ b/lib/ext/safe_renegotiation.c +@@ -265,10 +265,9 @@ int _gnutls_ext_sr_send_cs(gnutls_session_t session) + + static int + _gnutls_sr_recv_params(gnutls_session_t session, +- const uint8_t * data, size_t _data_size) ++ const uint8_t * data, size_t data_size) + { + unsigned int len; +- ssize_t data_size = _data_size; + sr_ext_st *priv; + gnutls_ext_priv_data_t epriv; + int set = 0, ret; +diff --git a/lib/ext/server_cert_type.c b/lib/ext/server_cert_type.c +index dbcb3971b..864a44bbc 100644 +--- a/lib/ext/server_cert_type.c ++++ b/lib/ext/server_cert_type.c +@@ -73,7 +73,6 @@ static int _gnutls_server_cert_type_recv_params(gnutls_session_t session, + gnutls_certificate_type_t cert_type; + + uint8_t i, found = 0; +- ssize_t len = data_size; + const uint8_t* pdata = data; + + /* Only activate this extension if we have cert credentials set +@@ -86,7 +85,7 @@ static int _gnutls_server_cert_type_recv_params(gnutls_session_t session, + + /* Compare packet length with expected packet length. For the + * client this is a single byte. */ +- if (len != 1) { ++ if (data_size != 1) { + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + } +@@ -135,8 +134,8 @@ static int _gnutls_server_cert_type_recv_params(gnutls_session_t session, + + } else { // server mode + // Compare packet length with expected packet length. +- DECR_LEN(len, 1); +- if (data[0] != len) { ++ DECR_LEN(data_size, 1); ++ if (data[0] != data_size) { + return + gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + } +@@ -144,7 +143,7 @@ static int _gnutls_server_cert_type_recv_params(gnutls_session_t session, + + // Assign the contents of our data buffer to a gnutls_datum_t + cert_types.data = (uint8_t*)pdata; // Need casting to get rid of 'discards const qualifier' warning +- cert_types.size = len; ++ cert_types.size = data_size; + + // Store the server certificate types in our session + _gnutls_hello_ext_set_datum(session, +diff --git a/lib/ext/server_name.c b/lib/ext/server_name.c +index 259dc998e..0c6331569 100644 +--- a/lib/ext/server_name.c ++++ b/lib/ext/server_name.c +@@ -66,11 +66,10 @@ const hello_ext_entry_st ext_mod_server_name = { + */ + static int + _gnutls_server_name_recv_params(gnutls_session_t session, +- const uint8_t * data, size_t _data_size) ++ const uint8_t * data, size_t data_size) + { + const unsigned char *p; + uint16_t len, type; +- ssize_t data_size = _data_size; + gnutls_datum_t name; + + if (session->security_parameters.entity == GNUTLS_SERVER) { +diff --git a/lib/ext/session_ticket.c b/lib/ext/session_ticket.c +index 98db39ff8..263273fa2 100644 +--- a/lib/ext/session_ticket.c ++++ b/lib/ext/session_ticket.c +@@ -78,7 +78,7 @@ static int + unpack_ticket(const gnutls_datum_t *ticket_data, struct ticket_st *ticket) + { + const uint8_t * data = ticket_data->data; +- ssize_t data_size = ticket_data->size; ++ size_t data_size = ticket_data->size; + const uint8_t *encrypted_state; + + /* Format: +@@ -371,11 +371,10 @@ unpack_session(gnutls_session_t session, const gnutls_datum_t *state) + + static int + session_ticket_recv_params(gnutls_session_t session, +- const uint8_t * data, size_t _data_size) ++ const uint8_t * data, size_t data_size) + { + gnutls_datum_t ticket_data; + gnutls_datum_t state; +- ssize_t data_size = _data_size; + int ret; + + if (session->internals.flags & GNUTLS_NO_TICKETS) +diff --git a/lib/ext/signature.c b/lib/ext/signature.c +index e734d2c7d..a90f58d53 100644 +--- a/lib/ext/signature.c ++++ b/lib/ext/signature.c +@@ -187,9 +187,8 @@ _gnutls_sign_algorithm_parse_data(gnutls_session_t session, + static int + _gnutls_signature_algorithm_recv_params(gnutls_session_t session, + const uint8_t * data, +- size_t _data_size) ++ size_t data_size) + { +- ssize_t data_size = _data_size; + int ret; + + if (session->security_parameters.entity == GNUTLS_CLIENT) { +diff --git a/lib/ext/srp.c b/lib/ext/srp.c +index 8b58222e0..07f6e6883 100644 +--- a/lib/ext/srp.c ++++ b/lib/ext/srp.c +@@ -59,10 +59,9 @@ const hello_ext_entry_st ext_mod_srp = { + + static int + _gnutls_srp_recv_params(gnutls_session_t session, const uint8_t * data, +- size_t _data_size) ++ size_t data_size) + { + uint8_t len; +- ssize_t data_size = _data_size; + gnutls_ext_priv_data_t epriv; + srp_ext_st *priv; + +diff --git a/lib/ext/srtp.c b/lib/ext/srtp.c +index 3fc7ed35a..412e26d45 100644 +--- a/lib/ext/srtp.c ++++ b/lib/ext/srtp.c +@@ -162,13 +162,12 @@ const char *gnutls_srtp_get_profile_name(gnutls_srtp_profile_t profile) + + static int + _gnutls_srtp_recv_params(gnutls_session_t session, +- const uint8_t * data, size_t _data_size) ++ const uint8_t * data, size_t data_size) + { + unsigned int i; + int ret; + const uint8_t *p = data; +- int len; +- ssize_t data_size = _data_size; ++ size_t len; + srtp_ext_st *priv; + gnutls_ext_priv_data_t epriv; + uint16_t profile; +diff --git a/lib/ext/status_request.c b/lib/ext/status_request.c +index d8779e8cf..cf9d5bd03 100644 +--- a/lib/ext/status_request.c ++++ b/lib/ext/status_request.c +@@ -86,9 +86,8 @@ client_send(gnutls_session_t session, + static int + server_recv(gnutls_session_t session, + status_request_ext_st * priv, +- const uint8_t * data, size_t size) ++ const uint8_t * data, size_t data_size) + { +- ssize_t data_size = size; + unsigned rid_bytes = 0; + + /* minimum message is type (1) + responder_id_list (2) + +diff --git a/lib/ext/supported_groups.c b/lib/ext/supported_groups.c +index 952d3bb0c..ef7859f73 100644 +--- a/lib/ext/supported_groups.c ++++ b/lib/ext/supported_groups.c +@@ -93,10 +93,9 @@ static unsigned get_min_dh(gnutls_session_t session) + */ + static int + _gnutls_supported_groups_recv_params(gnutls_session_t session, +- const uint8_t * data, size_t _data_size) ++ const uint8_t * data, size_t data_size) + { + int i; +- ssize_t data_size = _data_size; + uint16_t len; + const uint8_t *p = data; + const gnutls_group_entry_st *group = NULL; +diff --git a/lib/ext/supported_versions.c b/lib/ext/supported_versions.c +index 52828ee37..8d52fad5c 100644 +--- a/lib/ext/supported_versions.c ++++ b/lib/ext/supported_versions.c +@@ -54,12 +54,11 @@ const hello_ext_entry_st ext_mod_supported_versions = { + + static int + supported_versions_recv_params(gnutls_session_t session, +- const uint8_t * data, size_t _data_size) ++ const uint8_t * data, size_t data_size) + { + const version_entry_st *vers; +- ssize_t data_size = _data_size; + uint8_t major, minor; +- ssize_t bytes; ++ size_t bytes; + int ret; + + if (session->security_parameters.entity == GNUTLS_SERVER) { +diff --git a/lib/extv.c b/lib/extv.c +index bfdfdf974..0c0c46f32 100644 +--- a/lib/extv.c ++++ b/lib/extv.c +@@ -105,7 +105,7 @@ int gnutls_ext_raw_parse(void *ctx, gnutls_ext_raw_process_func cb, + const gnutls_datum_t *data, unsigned int flags) + { + if (flags & GNUTLS_EXT_RAW_FLAG_TLS_CLIENT_HELLO) { +- ssize_t size = data->size; ++ size_t size = data->size; + size_t len; + uint8_t *p = data->data; + +@@ -137,12 +137,12 @@ int gnutls_ext_raw_parse(void *ctx, gnutls_ext_raw_process_func cb, + DECR_LEN(size, len); + p += len; + +- if (size <= 0) ++ if (size == 0) + return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); + + return _gnutls_extv_parse(ctx, cb, p, size); + } else if (flags & GNUTLS_EXT_RAW_FLAG_DTLS_CLIENT_HELLO) { +- ssize_t size = data->size; ++ size_t size = data->size; + size_t len; + uint8_t *p = data->data; + +@@ -181,7 +181,7 @@ int gnutls_ext_raw_parse(void *ctx, gnutls_ext_raw_process_func cb, + DECR_LEN(size, len); + p += len; + +- if (size <= 0) ++ if (size == 0) + return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); + + return _gnutls_extv_parse(ctx, cb, p, size); +diff --git a/lib/sslv2_compat.c b/lib/sslv2_compat.c +index 6122d1098..9d247ba4c 100644 +--- a/lib/sslv2_compat.c ++++ b/lib/sslv2_compat.c +@@ -87,14 +87,13 @@ _gnutls_handshake_select_v2_suite(gnutls_session_t session, + */ + int + _gnutls_read_client_hello_v2(gnutls_session_t session, uint8_t * data, +- unsigned int datalen) ++ unsigned int len) + { + uint16_t session_id_len = 0; + int pos = 0; + int ret = 0, sret = 0; + uint16_t sizeOfSuites; + uint8_t rnd[GNUTLS_RANDOM_SIZE], major, minor; +- int len = datalen; + int neg_version; + const version_entry_st *vers; + uint16_t challenge; +diff --git a/lib/supplemental.c b/lib/supplemental.c +index cd90fa1fb..07b38cc93 100644 +--- a/lib/supplemental.c ++++ b/lib/supplemental.c +@@ -192,14 +192,14 @@ _gnutls_parse_supplemental(gnutls_session_t session, + const uint8_t * data, int datalen) + { + const uint8_t *p = data; +- ssize_t dsize = datalen; ++ size_t dsize = datalen; + size_t total_size; + + DECR_LEN(dsize, 3); + total_size = _gnutls_read_uint24(p); + p += 3; + +- if (dsize != (ssize_t) total_size) { ++ if (dsize != total_size) { + gnutls_assert(); + return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; + } +diff --git a/lib/tls13/certificate.c b/lib/tls13/certificate.c +index bd257237f..8a1a11872 100644 +--- a/lib/tls13/certificate.c ++++ b/lib/tls13/certificate.c +@@ -360,11 +360,12 @@ 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) + { +- int len, ret; ++ int ret; ++ size_t len; + uint8_t *p = data; + cert_auth_info_t info; + gnutls_certificate_credentials_t cred; +- ssize_t dsize = data_size, size; ++ size_t size; + int i; + unsigned npeer_certs, npeer_ocsp, j; + crt_cert_ctx_st ctx; +@@ -395,31 +396,31 @@ parse_cert_list(gnutls_session_t session, uint8_t * data, size_t data_size) + if (info == NULL) + return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS); + +- DECR_LEN(dsize, 3); ++ DECR_LEN(data_size, 3); + size = _gnutls_read_uint24(p); + p += 3; + +- if (size != dsize) ++ if (size != data_size) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + if (size == 0) + return gnutls_assert_val(GNUTLS_E_NO_CERTIFICATE_FOUND); + +- i = dsize; ++ i = data_size; + + while (i > 0) { +- DECR_LEN(dsize, 3); ++ DECR_LEN(data_size, 3); + len = _gnutls_read_uint24(p); + if (len == 0) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + +- DECR_LEN(dsize, len); ++ DECR_LEN(data_size, len); + p += len + 3; + i -= len + 3; + +- DECR_LEN(dsize, 2); ++ DECR_LEN(data_size, 2); + len = _gnutls_read_uint16(p); +- DECR_LEN(dsize, len); ++ DECR_LEN(data_size, len); + + i -= len + 2; + p += len + 2; +@@ -427,7 +428,7 @@ parse_cert_list(gnutls_session_t session, uint8_t * data, size_t data_size) + nentries++; + } + +- if (dsize != 0) ++ if (data_size != 0) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); + + /* this is unnecessary - keeping to avoid a regression due to a re-org +diff --git a/lib/tls13/psk_ext_parser.c b/lib/tls13/psk_ext_parser.c +index 6e3a12f90..33ebc0461 100644 +--- a/lib/tls13/psk_ext_parser.c ++++ b/lib/tls13/psk_ext_parser.c +@@ -28,10 +28,8 @@ + * are present, or 0, on success. + */ + int _gnutls13_psk_ext_parser_init(psk_ext_parser_st *p, +- const unsigned char *data, size_t _len) ++ const unsigned char *data, size_t len) + { +- ssize_t len = _len; +- + if (!p || !data || !len) + return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + +diff --git a/lib/tls13/psk_ext_parser.h b/lib/tls13/psk_ext_parser.h +index 30b47e904..f46b211e0 100644 +--- a/lib/tls13/psk_ext_parser.h ++++ b/lib/tls13/psk_ext_parser.h +@@ -25,10 +25,10 @@ + + struct psk_ext_parser_st { + const unsigned char *identities_data; +- ssize_t identities_len; ++ size_t identities_len; + + const unsigned char *binders_data; +- ssize_t binders_len; ++ size_t binders_len; + }; + + typedef struct psk_ext_parser_st psk_ext_parser_st; +diff --git a/lib/tls13/session_ticket.c b/lib/tls13/session_ticket.c +index 146aee9b1..072a56d9c 100644 +--- a/lib/tls13/session_ticket.c ++++ b/lib/tls13/session_ticket.c +@@ -105,7 +105,7 @@ unpack_ticket(gnutls_session_t session, gnutls_datum_t *packed, tls13_ticket_st + gnutls_mac_algorithm_t kdf; + const mac_entry_st *prf; + uint8_t *p; +- ssize_t len; ++ size_t len; + uint64_t v; + int ret; + +-- +2.21.0 + diff --git a/SOURCES/gnutls-3.6.8-fix-aead-cipher-encryptv2.patch b/SOURCES/gnutls-3.6.8-fix-aead-cipher-encryptv2.patch new file mode 100644 index 0000000..0194c6c --- /dev/null +++ b/SOURCES/gnutls-3.6.8-fix-aead-cipher-encryptv2.patch @@ -0,0 +1,767 @@ +From bbb312749780928cc10b45662c6d7eadcaa98f0b Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Thu, 3 Oct 2019 10:34:18 +0200 +Subject: [PATCH 1/3] iov: _gnutls_iov_iter_next: return bytes instead of + blocks + +This eliminates the need of special handling of final block. Also +adds more tests in exceptional cases. + +Signed-off-by: Daiki Ueno +--- + lib/crypto-api.c | 82 +++++------------------------- + lib/iov.c | 31 +++++++++--- + tests/iov.c | 126 ++++++++++++++++++++++++++++++++--------------- + 3 files changed, 121 insertions(+), 118 deletions(-) + +diff --git a/lib/crypto-api.c b/lib/crypto-api.c +index 09b3d7bfc..41e759b74 100644 +--- a/lib/crypto-api.c ++++ b/lib/crypto-api.c +@@ -992,9 +992,9 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle, + uint8_t *dst; + size_t dst_size, total = 0; + uint8_t *p; ++ size_t len; + size_t blocksize = handle->ctx_enc.e->blocksize; + struct iov_iter_st iter; +- size_t blocks; + + /* Limitation: this function provides an optimization under the internally registered + * AEAD ciphers. When an AEAD cipher is used registered with gnutls_crypto_register_aead_cipher(), +@@ -1045,15 +1045,7 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle, + return gnutls_assert_val(ret); + if (ret == 0) + break; +- blocks = ret; +- ret = _gnutls_cipher_auth(&handle->ctx_enc, p, +- blocksize * blocks); +- if (unlikely(ret < 0)) +- return gnutls_assert_val(ret); +- } +- if (iter.block_offset > 0) { +- ret = _gnutls_cipher_auth(&handle->ctx_enc, +- iter.block, iter.block_offset); ++ ret = _gnutls_cipher_auth(&handle->ctx_enc, p, ret); + if (unlikely(ret < 0)) + return gnutls_assert_val(ret); + } +@@ -1070,29 +1062,15 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle, + return gnutls_assert_val(ret); + if (ret == 0) + break; +- blocks = ret; +- if (unlikely(dst_size < blocksize * blocks)) +- return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); +- ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, p, +- blocksize * blocks, +- dst, dst_size); +- if (unlikely(ret < 0)) +- return gnutls_assert_val(ret); +- DECR_LEN(dst_size, blocksize * blocks); +- dst += blocksize * blocks; +- total += blocksize * blocks; +- } +- if (iter.block_offset > 0) { +- if (unlikely(dst_size < iter.block_offset)) +- return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER); ++ len = ret; + ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, +- iter.block, iter.block_offset, ++ p, len, + dst, dst_size); + if (unlikely(ret < 0)) + return gnutls_assert_val(ret); +- DECR_LEN(dst_size, iter.block_offset); +- dst += iter.block_offset; +- total += iter.block_offset; ++ DECR_LEN(dst_size, len); ++ dst += len; ++ total += len; + } + + if (dst_size < tag_size) +@@ -1137,7 +1115,6 @@ gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle, + uint8_t *p; + ssize_t blocksize = handle->ctx_enc.e->blocksize; + struct iov_iter_st iter; +- size_t blocks; + size_t _tag_size; + + if (tag_size == NULL || *tag_size == 0) +@@ -1220,15 +1197,7 @@ gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle, + return gnutls_assert_val(ret); + if (ret == 0) + break; +- blocks = ret; +- ret = _gnutls_cipher_auth(&handle->ctx_enc, p, +- blocksize * blocks); +- if (unlikely(ret < 0)) +- return gnutls_assert_val(ret); +- } +- if (iter.block_offset > 0) { +- ret = _gnutls_cipher_auth(&handle->ctx_enc, +- iter.block, iter.block_offset); ++ ret = _gnutls_cipher_auth(&handle->ctx_enc, p, ret); + if (unlikely(ret < 0)) + return gnutls_assert_val(ret); + } +@@ -1242,17 +1211,7 @@ gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle, + return gnutls_assert_val(ret); + if (ret == 0) + break; +- blocks = ret; +- ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, +- p, blocksize * blocks, +- p, blocksize * blocks); +- if (unlikely(ret < 0)) +- return gnutls_assert_val(ret); +- } +- if (iter.block_offset > 0) { +- ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, +- iter.block, iter.block_offset, +- iter.block, iter.block_offset); ++ ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, p, ret, p, ret); + if (unlikely(ret < 0)) + return gnutls_assert_val(ret); + } +@@ -1296,7 +1255,6 @@ gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle, + uint8_t *p; + ssize_t blocksize = handle->ctx_enc.e->blocksize; + struct iov_iter_st iter; +- size_t blocks; + uint8_t _tag[MAX_HASH_SIZE]; + + if (tag_size == 0) +@@ -1370,15 +1328,7 @@ gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle, + return gnutls_assert_val(ret); + if (ret == 0) + break; +- blocks = ret; +- ret = _gnutls_cipher_auth(&handle->ctx_enc, p, +- blocksize * blocks); +- if (unlikely(ret < 0)) +- return gnutls_assert_val(ret); +- } +- if (iter.block_offset > 0) { +- ret = _gnutls_cipher_auth(&handle->ctx_enc, +- iter.block, iter.block_offset); ++ ret = _gnutls_cipher_auth(&handle->ctx_enc, p, ret); + if (unlikely(ret < 0)) + return gnutls_assert_val(ret); + } +@@ -1392,17 +1342,7 @@ gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle, + return gnutls_assert_val(ret); + if (ret == 0) + break; +- blocks = ret; +- ret = _gnutls_cipher_decrypt2(&handle->ctx_enc, +- p, blocksize * blocks, +- p, blocksize * blocks); +- if (unlikely(ret < 0)) +- return gnutls_assert_val(ret); +- } +- if (iter.block_offset > 0) { +- ret = _gnutls_cipher_decrypt2(&handle->ctx_enc, +- iter.block, iter.block_offset, +- iter.block, iter.block_offset); ++ ret = _gnutls_cipher_decrypt2(&handle->ctx_enc, p, ret, p, ret); + if (unlikely(ret < 0)) + return gnutls_assert_val(ret); + } +diff --git a/lib/iov.c b/lib/iov.c +index 5dc29c54b..17272886c 100644 +--- a/lib/iov.c ++++ b/lib/iov.c +@@ -58,8 +58,8 @@ _gnutls_iov_iter_init(struct iov_iter_st *iter, + * @data: the return location of extracted data + * + * Retrieve block(s) pointed by @iter and advance it to the next +- * position. It returns the number of consecutive blocks in @data. +- * At the end of iteration, 0 is returned. ++ * position. It returns the number of bytes in @data. At the end of ++ * iteration, 0 is returned. + * + * If the data stored in @iter is not multiple of the block size, the + * remaining data is stored in the "block" field of @iter with the +@@ -88,25 +88,30 @@ _gnutls_iov_iter_next(struct iov_iter_st *iter, uint8_t **data) + if ((len % iter->block_size) == 0) { + iter->iov_index++; + iter->iov_offset = 0; +- } else +- iter->iov_offset += +- len - (len % iter->block_size); ++ } else { ++ len -= (len % iter->block_size); ++ iter->iov_offset += len; ++ } + + /* Return the blocks. */ + *data = p; +- return len / iter->block_size; ++ return len; + } + + /* We can complete one full block to return. */ + block_left = iter->block_size - iter->block_offset; + if (len >= block_left) { + memcpy(iter->block + iter->block_offset, p, block_left); +- iter->iov_offset += block_left; ++ if (len == block_left) { ++ iter->iov_index++; ++ iter->iov_offset = 0; ++ } else ++ iter->iov_offset += block_left; + iter->block_offset = 0; + + /* Return the filled block. */ + *data = iter->block; +- return 1; ++ return iter->block_size; + } + + /* Not enough data for a full block, store in temp +@@ -116,5 +121,15 @@ _gnutls_iov_iter_next(struct iov_iter_st *iter, uint8_t **data) + iter->iov_index++; + iter->iov_offset = 0; + } ++ ++ if (iter->block_offset > 0) { ++ size_t len = iter->block_offset; ++ ++ /* Return the incomplete block. */ ++ *data = iter->block; ++ iter->block_offset = 0; ++ return len; ++ } ++ + return 0; + } +diff --git a/tests/iov.c b/tests/iov.c +index eda5583a7..3d116b471 100644 +--- a/tests/iov.c ++++ b/tests/iov.c +@@ -32,7 +32,6 @@ struct exp_st { + ssize_t ret; + size_t iov_index; + size_t iov_offset; +- size_t block_offset; + }; + + struct test_st { +@@ -42,7 +41,6 @@ struct test_st { + size_t block_size; + const struct exp_st *exp; + size_t expcnt; +- size_t remaining; + }; + + static const giovec_t iov16[] = { +@@ -53,40 +51,41 @@ static const giovec_t iov16[] = { + }; + + static const struct exp_st exp16_64[] = { +- {1, 3, 16, 0}, +- {0, 0, 0, 0} ++ {64, 4, 0}, ++ {0, 0, 0} + }; + + static const struct exp_st exp16_32[] = { +- {1, 1, 16, 0}, +- {1, 3, 16, 0}, +- {0, 0, 0, 0} ++ {32, 2, 0}, ++ {32, 4, 0}, ++ {0, 0, 0} + }; + + static const struct exp_st exp16_16[] = { +- {1, 1, 0, 0}, +- {1, 2, 0, 0}, +- {1, 3, 0, 0}, +- {1, 4, 0, 0}, +- {0, 0, 0, 0} ++ {16, 1, 0}, ++ {16, 2, 0}, ++ {16, 3, 0}, ++ {16, 4, 0}, ++ {0, 0, 0} + }; + + static const struct exp_st exp16_4[] = { +- {4, 1, 0, 0}, +- {4, 2, 0, 0}, +- {4, 3, 0, 0}, +- {4, 4, 0, 0}, +- {0, 0, 0, 0} ++ {16, 1, 0}, ++ {16, 2, 0}, ++ {16, 3, 0}, ++ {16, 4, 0}, ++ {0, 0, 0} + }; + + static const struct exp_st exp16_3[] = { +- {5, 0, 15, 0}, +- {1, 1, 2, 0}, +- {4, 1, 14, 0}, +- {1, 2, 1, 0}, +- {5, 3, 0, 0}, +- {5, 3, 15, 0}, +- {0, 0, 0, 1} ++ {15, 0, 15}, ++ {3, 1, 2}, ++ {12, 1, 14}, ++ {3, 2, 1}, ++ {15, 3, 0}, ++ {15, 3, 15}, ++ {1, 4, 0}, ++ {0, 0, 0} + }; + + static const giovec_t iov8[] = { +@@ -97,22 +96,74 @@ static const giovec_t iov8[] = { + }; + + static const struct exp_st exp8_64[] = { +- {0, 0, 0, 32} ++ {32, 4, 0}, ++ {0, 0, 0} ++}; ++ ++static const giovec_t iov_odd[] = { ++ {(void *) "0", 1}, ++ {(void *) "012", 3}, ++ {(void *) "01234", 5}, ++ {(void *) "0123456", 7}, ++ {(void *) "012345678", 9}, ++ {(void *) "01234567890", 11}, ++ {(void *) "0123456789012", 13}, ++ {(void *) "012345678901234", 15} ++}; ++ ++static const struct exp_st exp_odd_16[] = { ++ {16, 4, 0}, ++ {16, 5, 7}, ++ {16, 6, 12}, ++ {16, 8, 0}, ++ {0, 0, 0} ++}; ++ ++static const giovec_t iov_skip[] = { ++ {(void *) "0123456789012345", 16}, ++ {(void *) "01234567", 8}, ++ {(void *) "", 0}, ++ {(void *) "", 0}, ++ {(void *) "0123456789012345", 16} ++}; ++ ++static const struct exp_st exp_skip_16[] = { ++ {16, 1, 0}, ++ {16, 4, 8}, ++ {8, 5, 0}, ++ {0, 0, 0} ++}; ++ ++static const giovec_t iov_empty[] = { ++ {(void *) "", 0}, ++ {(void *) "", 0}, ++ {(void *) "", 0}, ++ {(void *) "", 0} ++}; ++ ++static const struct exp_st exp_empty_16[] = { ++ {0, 0, 0} + }; + + static const struct test_st tests[] = { + { "16/64", iov16, sizeof(iov16)/sizeof(iov16[0]), 64, +- exp16_64, sizeof(exp16_64)/sizeof(exp16_64[0]), 0 }, ++ exp16_64, sizeof(exp16_64)/sizeof(exp16_64[0]) }, + { "16/32", iov16, sizeof(iov16)/sizeof(iov16[0]), 32, +- exp16_32, sizeof(exp16_32)/sizeof(exp16_32[0]), 0 }, ++ exp16_32, sizeof(exp16_32)/sizeof(exp16_32[0]) }, + { "16/16", iov16, sizeof(iov16)/sizeof(iov16[0]), 16, +- exp16_16, sizeof(exp16_16)/sizeof(exp16_16[0]), 0 }, ++ exp16_16, sizeof(exp16_16)/sizeof(exp16_16[0]) }, + { "16/4", iov16, sizeof(iov16)/sizeof(iov16[0]), 4, +- exp16_4, sizeof(exp16_4)/sizeof(exp16_4[0]), 0 }, ++ exp16_4, sizeof(exp16_4)/sizeof(exp16_4[0]) }, + { "16/3", iov16, sizeof(iov16)/sizeof(iov16[0]), 3, +- exp16_3, sizeof(exp16_3)/sizeof(exp16_3[0]), 1 }, ++ exp16_3, sizeof(exp16_3)/sizeof(exp16_3[0]) }, + { "8/64", iov8, sizeof(iov8)/sizeof(iov8[0]), 64, +- exp8_64, sizeof(exp8_64)/sizeof(exp8_64[0]), 32 } ++ exp8_64, sizeof(exp8_64)/sizeof(exp8_64[0]) }, ++ { "odd/16", iov_odd, sizeof(iov_odd)/sizeof(iov_odd[0]), 16, ++ exp_odd_16, sizeof(exp_odd_16)/sizeof(exp_odd_16[0]) }, ++ { "skip/16", iov_skip, sizeof(iov_skip)/sizeof(iov_skip[0]), 16, ++ exp_skip_16, sizeof(exp_skip_16)/sizeof(exp_skip_16[0]) }, ++ { "empty/16", iov_empty, sizeof(iov_empty)/sizeof(iov_empty[0]), 16, ++ exp_empty_16, sizeof(exp_empty_16)/sizeof(exp_empty_16[0]) }, + }; + + void +@@ -155,16 +206,13 @@ doit (void) + else if (debug) + success("iter.iov_offset: %u == %u\n", + (unsigned) iter.iov_offset, (unsigned) exp[j].iov_offset); +- if (iter.block_offset != exp[j].block_offset) +- fail("iter.block_offset: %u != %u\n", +- (unsigned) iter.block_offset, (unsigned) exp[j].block_offset); ++ if (iter.block_offset != 0) ++ fail("iter.block_offset: %u != 0\n", ++ (unsigned) iter.block_offset); + else if (debug) +- success("iter.block_offset: %u == %u\n", +- (unsigned) iter.block_offset, (unsigned) exp[j].block_offset); ++ success("iter.block_offset: %u == 0\n", ++ (unsigned) iter.block_offset); + } + } +- if (iter.block_offset != tests[i].remaining) +- fail("remaining: %u != %u\n", +- (unsigned) iter.block_offset, (unsigned) tests[i].remaining); + } + } +-- +2.21.0 + + +From c684814cc456a9792a9183ce77d32d435f29e6b7 Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Tue, 1 Oct 2019 18:14:48 +0200 +Subject: [PATCH 2/3] iov: add _gnutls_iov_iter_sync to write back cached data + to iov + +Signed-off-by: Daiki Ueno +--- + lib/iov.c | 59 +++++++++++++++++++++++++++++++++++++++++++++ + lib/iov.h | 4 +++- + lib/libgnutls.map | 1 + + tests/iov.c | 61 +++++++++++++++++++++++++++++++++++++++++++---- + 4 files changed, 119 insertions(+), 6 deletions(-) + +diff --git a/lib/iov.c b/lib/iov.c +index 17272886c..1cd8d46dd 100644 +--- a/lib/iov.c ++++ b/lib/iov.c +@@ -133,3 +133,62 @@ _gnutls_iov_iter_next(struct iov_iter_st *iter, uint8_t **data) + + return 0; + } ++ ++/** ++ * _gnutls_iov_iter_sync: ++ * @iter: the iterator ++ * @data: data returned by _gnutls_iov_iter_next ++ * @data_size: size of @data ++ * ++ * Flush the content of temp buffer (if any) to the data buffer. ++ */ ++int ++_gnutls_iov_iter_sync(struct iov_iter_st *iter, const uint8_t *data, ++ size_t data_size) ++{ ++ size_t iov_index; ++ size_t iov_offset; ++ ++ /* We didn't return the cached block. */ ++ if (data != iter->block) ++ return 0; ++ ++ iov_index = iter->iov_index; ++ iov_offset = iter->iov_offset; ++ ++ /* When syncing a cache block we walk backwards because we only have a ++ * pointer to were the block ends in the iovec, walking backwards is ++ * fine as we are always writing a full block, so the whole content ++ * is written in the right places: ++ * iovec: |--0--|---1---|--2--|-3-| ++ * block: |-----------------------| ++ * 1st write |---| ++ * 2nd write |----- ++ * 3rd write |------- ++ * last write |----- ++ */ ++ while (data_size > 0) { ++ const giovec_t *iov; ++ uint8_t *p; ++ size_t to_write; ++ ++ while (iov_offset == 0) { ++ if (unlikely(iov_index == 0)) ++ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); ++ ++ iov_index--; ++ iov_offset = iter->iov[iov_index].iov_len; ++ } ++ ++ iov = &iter->iov[iov_index]; ++ p = iov->iov_base; ++ to_write = MIN(data_size, iov_offset); ++ ++ iov_offset -= to_write; ++ data_size -= to_write; ++ ++ memcpy(p + iov_offset, &iter->block[data_size], to_write); ++ } ++ ++ return 0; ++} +diff --git a/lib/iov.h b/lib/iov.h +index 47fba559a..5b9903460 100644 +--- a/lib/iov.h ++++ b/lib/iov.h +@@ -34,7 +34,6 @@ struct iov_iter_st { + uint8_t block[MAX_CIPHER_BLOCK_SIZE]; /* incomplete block for reading */ + size_t block_size; /* actual block size of the cipher */ + size_t block_offset; /* offset in block */ +- + }; + + int _gnutls_iov_iter_init(struct iov_iter_st *iter, +@@ -43,4 +42,7 @@ int _gnutls_iov_iter_init(struct iov_iter_st *iter, + + ssize_t _gnutls_iov_iter_next(struct iov_iter_st *iter, uint8_t **data); + ++int _gnutls_iov_iter_sync(struct iov_iter_st *iter, const uint8_t *data, ++ size_t data_size); ++ + #endif /* GNUTLS_LIB_IOV_H */ +diff --git a/lib/libgnutls.map b/lib/libgnutls.map +index f83a21e9b..d6973f72e 100644 +--- a/lib/libgnutls.map ++++ b/lib/libgnutls.map +@@ -1394,4 +1394,5 @@ GNUTLS_PRIVATE_3_4 { + # needed by tests/iov: + _gnutls_iov_iter_init; + _gnutls_iov_iter_next; ++ _gnutls_iov_iter_sync; + } GNUTLS_3_4; +diff --git a/tests/iov.c b/tests/iov.c +index 3d116b471..2acd2b5f5 100644 +--- a/tests/iov.c ++++ b/tests/iov.c +@@ -44,10 +44,10 @@ struct test_st { + }; + + static const giovec_t iov16[] = { +- {(void *) "0123456789abcdef", 16}, +- {(void *) "0123456789abcdef", 16}, +- {(void *) "0123456789abcdef", 16}, +- {(void *) "0123456789abcdef", 16} ++ {(void *) "0123456789012345", 16}, ++ {(void *) "0123456789012345", 16}, ++ {(void *) "0123456789012345", 16}, ++ {(void *) "0123456789012345", 16} + }; + + static const struct exp_st exp16_64[] = { +@@ -166,20 +166,53 @@ static const struct test_st tests[] = { + exp_empty_16, sizeof(exp_empty_16)/sizeof(exp_empty_16[0]) }, + }; + ++static void ++copy(giovec_t *dst, uint8_t *buffer, const giovec_t *src, size_t iovcnt) ++{ ++ uint8_t *p = buffer; ++ size_t i; ++ ++ for (i = 0; i < iovcnt; i++) { ++ dst[i].iov_base = p; ++ dst[i].iov_len = src[i].iov_len; ++ memcpy(dst[i].iov_base, src[i].iov_base, src[i].iov_len); ++ p += src[i].iov_len; ++ } ++} ++ ++static void ++translate(uint8_t *data, size_t len) ++{ ++ for (; len > 0; len--) { ++ uint8_t *p = &data[len - 1]; ++ if (*p >= '0' && *p <= '9') ++ *p = 'A' + *p - '0'; ++ else if (*p >= 'A' && *p <= 'Z') ++ *p = '0' + *p - 'A'; ++ } ++} ++ ++#define MAX_BUF 1024 ++#define MAX_IOV 16 ++ + void + doit (void) + { ++ uint8_t buffer[MAX_BUF]; + size_t i; + + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { ++ giovec_t iov[MAX_IOV]; + struct iov_iter_st iter; + const struct exp_st *exp = tests[i].exp; + uint8_t *data; + size_t j; + ++ copy(iov, buffer, tests[i].iov, tests[i].iovcnt); ++ + success("%s\n", tests[i].name); + assert(_gnutls_iov_iter_init(&iter, +- tests[i].iov, tests[i].iovcnt, ++ iov, tests[i].iovcnt, + tests[i].block_size) == 0); + for (j = 0; j < tests[i].expcnt; j++) { + ssize_t ret; +@@ -212,7 +245,25 @@ doit (void) + else if (debug) + success("iter.block_offset: %u == 0\n", + (unsigned) iter.block_offset); ++ ++ translate(data, ret); ++ ++ ret = _gnutls_iov_iter_sync(&iter, data, ret); ++ if (ret < 0) ++ fail("sync failed\n"); + } + } ++ ++ for (j = 0; j < tests[i].iovcnt; j++) { ++ translate(iov[j].iov_base, iov[j].iov_len); ++ ++ if (memcmp(iov[j].iov_base, tests[i].iov[j].iov_base, ++ iov[j].iov_len) != 0) ++ fail("iov doesn't match: %*s != %*s\n", ++ (int)iov[j].iov_len, ++ (char *)iov[j].iov_base, ++ (int)tests[i].iov[j].iov_len, ++ (char *)tests[i].iov[j].iov_len); ++ } + } + } +-- +2.21.0 + + +From 6df0cf1c0ec727fc237a9b429684c8f2ef5d34b7 Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Tue, 1 Oct 2019 18:15:19 +0200 +Subject: [PATCH 3/3] gnutls_aead_cipher_{en,de}cryptv2: write back cached data + to buffers + +Previously, those functions failed to write the output to the buffers +if the buffer length is not multiple of cipher block size. This makes +sure that the cached data is always flushed. + +Signed-off-by: Daiki Ueno +--- + lib/crypto-api.c | 18 ++++++++++++++++-- + tests/aead-cipher-vec.c | 14 ++++++++------ + 2 files changed, 24 insertions(+), 8 deletions(-) + +diff --git a/lib/crypto-api.c b/lib/crypto-api.c +index 41e759b74..7308d7e7b 100644 +--- a/lib/crypto-api.c ++++ b/lib/crypto-api.c +@@ -1113,6 +1113,7 @@ gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle, + api_aead_cipher_hd_st *h = handle; + ssize_t ret; + uint8_t *p; ++ size_t len; + ssize_t blocksize = handle->ctx_enc.e->blocksize; + struct iov_iter_st iter; + size_t _tag_size; +@@ -1211,7 +1212,13 @@ gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle, + return gnutls_assert_val(ret); + if (ret == 0) + break; +- ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, p, ret, p, ret); ++ ++ len = ret; ++ ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, p, len, p, len); ++ if (unlikely(ret < 0)) ++ return gnutls_assert_val(ret); ++ ++ ret = _gnutls_iov_iter_sync(&iter, p, len); + if (unlikely(ret < 0)) + return gnutls_assert_val(ret); + } +@@ -1253,6 +1260,7 @@ gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle, + api_aead_cipher_hd_st *h = handle; + ssize_t ret; + uint8_t *p; ++ size_t len; + ssize_t blocksize = handle->ctx_enc.e->blocksize; + struct iov_iter_st iter; + uint8_t _tag[MAX_HASH_SIZE]; +@@ -1342,7 +1350,13 @@ gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle, + return gnutls_assert_val(ret); + if (ret == 0) + break; +- ret = _gnutls_cipher_decrypt2(&handle->ctx_enc, p, ret, p, ret); ++ ++ len = ret; ++ ret = _gnutls_cipher_decrypt2(&handle->ctx_enc, p, len, p, len); ++ if (unlikely(ret < 0)) ++ return gnutls_assert_val(ret); ++ ++ ret = _gnutls_iov_iter_sync(&iter, p, len); + if (unlikely(ret < 0)) + return gnutls_assert_val(ret); + } +diff --git a/tests/aead-cipher-vec.c b/tests/aead-cipher-vec.c +index 6c2542cf1..10e3db862 100644 +--- a/tests/aead-cipher-vec.c ++++ b/tests/aead-cipher-vec.c +@@ -43,9 +43,9 @@ static void start(const char *name, int algo) + uint8_t key16[64]; + uint8_t iv16[32]; + uint8_t auth[128]; +- uint8_t data[128+64]; ++ uint8_t data[64+56+36]; + gnutls_datum_t key, iv; +- giovec_t iov[2]; ++ giovec_t iov[3]; + giovec_t auth_iov[2]; + uint8_t tag[64]; + size_t tag_size = 0; +@@ -60,13 +60,15 @@ static void start(const char *name, int algo) + + memset(iv.data, 0xff, iv.size); + memset(key.data, 0xfe, key.size); +- memset(data, 0xfa, 128); ++ memset(data, 0xfa, sizeof(data)); + memset(auth, 0xaa, sizeof(auth)); + + iov[0].iov_base = data; + iov[0].iov_len = 64; + iov[1].iov_base = data + 64; +- iov[1].iov_len = 64; ++ iov[1].iov_len = 56; ++ iov[2].iov_base = data + 64 + 56; ++ iov[2].iov_len = 36; + + auth_iov[0].iov_base = auth; + auth_iov[0].iov_len = 64; +@@ -83,7 +85,7 @@ static void start(const char *name, int algo) + ret = gnutls_aead_cipher_encryptv2(ch, + iv.data, iv.size, + auth_iov, 2, +- iov, 2, ++ iov, 3, + tag, &tag_size); + if (ret < 0) + fail("could not encrypt data: %s\n", gnutls_strerror(ret)); +@@ -91,7 +93,7 @@ static void start(const char *name, int algo) + ret = gnutls_aead_cipher_decryptv2(ch, + iv.data, iv.size, + auth_iov, 2, +- iov, 2, ++ iov, 3, + tag, tag_size); + if (ret < 0) + fail("could not decrypt data: %s\n", gnutls_strerror(ret)); +-- +2.21.0 + diff --git a/SOURCES/gnutls-3.6.8-fix-cfb8-decrypt.patch b/SOURCES/gnutls-3.6.8-fix-cfb8-decrypt.patch new file mode 100644 index 0000000..738069b --- /dev/null +++ b/SOURCES/gnutls-3.6.8-fix-cfb8-decrypt.patch @@ -0,0 +1,204 @@ +From 1c2135506825ae80966fe2797613806916b7e3c0 Mon Sep 17 00:00:00 2001 +From: Daiki Ueno +Date: Wed, 6 Nov 2019 12:07:24 +0100 +Subject: [PATCH 1/2] nettle: backport fixes to cfb8_decrypt + +cfb8: don't truncate output IV if input is shorter than block size: +https://git.lysator.liu.se/nettle/nettle/commit/f4a9c842621baf5d71aa9cc3989851f44dc46861 + +Signed-off-by: Daiki Ueno +--- + lib/nettle/backport/cfb8.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/lib/nettle/backport/cfb8.c b/lib/nettle/backport/cfb8.c +index e9816feb7..1762192f4 100644 +--- a/lib/nettle/backport/cfb8.c ++++ b/lib/nettle/backport/cfb8.c +@@ -110,10 +110,12 @@ cfb8_decrypt(const void *ctx, nettle_cipher_func *f, + src += i; + dst += i; + +- memcpy(buffer, buffer + block_size, block_size); +- memcpy(buffer + block_size, src, +- length < block_size ? length : block_size); +- ++ if (i == block_size) ++ { ++ memcpy(buffer, buffer + block_size, block_size); ++ memcpy(buffer + block_size, src, ++ length < block_size ? length : block_size); ++ } + } + + memcpy(iv, buffer + i, block_size); +-- +2.21.0 + + +From cc01347302678719f0bcfb4f3383fe0f1e905ed8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?G=C3=BCnther=20Deschner?= +Date: Wed, 6 Nov 2019 13:17:57 +0100 +Subject: [PATCH 2/2] crypto-selftests: test CFB8 ciphers with different + chunksizes + +Signed-off-by: Guenther Deschner +Signed-off-by: Daiki Ueno +--- + lib/crypto-selftests.c | 124 +++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 118 insertions(+), 6 deletions(-) + +diff --git a/lib/crypto-selftests.c b/lib/crypto-selftests.c +index 6caf817e8..5f0a4ec8b 100644 +--- a/lib/crypto-selftests.c ++++ b/lib/crypto-selftests.c +@@ -710,6 +710,107 @@ static int test_cipher(gnutls_cipher_algorithm_t cipher, + return 0; + } + ++static int test_cipher_all_block_sizes(gnutls_cipher_algorithm_t cipher, ++ const struct cipher_vectors_st *vectors, ++ size_t vectors_size, unsigned flags) ++{ ++ gnutls_cipher_hd_t hd; ++ int ret; ++ unsigned int i; ++ uint8_t tmp[384]; ++ gnutls_datum_t key, iv = {NULL, 0}; ++ size_t block; ++ size_t offset; ++ ++ for (i = 0; i < vectors_size; i++) { ++ for (block = 1; block <= vectors[i].plaintext_size; block++) { ++ key.data = (void *) vectors[i].key; ++ key.size = vectors[i].key_size; ++ ++ iv.data = (void *) vectors[i].iv; ++ iv.size = gnutls_cipher_get_iv_size(cipher); ++ ++ if (iv.size != vectors[i].iv_size) ++ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); ++ ++ ret = gnutls_cipher_init(&hd, cipher, &key, &iv); ++ if (ret < 0) { ++ _gnutls_debug_log("error initializing: %s\n", ++ gnutls_cipher_get_name(cipher)); ++ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); ++ } ++ ++ for (offset = 0; ++ offset < vectors[i].plaintext_size; ++ offset += block) { ++ ret = ++ gnutls_cipher_encrypt2(hd, ++ vectors[i].plaintext + offset, ++ MIN(block, vectors[i].plaintext_size - offset), ++ tmp + offset, ++ sizeof(tmp) - offset); ++ if (ret < 0) ++ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); ++ } ++ ++ if (memcmp ++ (tmp, vectors[i].ciphertext, ++ vectors[i].plaintext_size) != 0) { ++ _gnutls_debug_log("%s encryption of test vector %d failed with block size %d/%d!\n", ++ gnutls_cipher_get_name(cipher), ++ i, (int)block, (int)vectors[i].plaintext_size); ++ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); ++ } ++ ++ gnutls_cipher_deinit(hd); ++ } ++ } ++ ++ for (i = 0; i < vectors_size; i++) { ++ for (block = 1; block <= vectors[i].plaintext_size; block++) { ++ key.data = (void *) vectors[i].key; ++ key.size = vectors[i].key_size; ++ ++ iv.data = (void *) vectors[i].iv; ++ iv.size = gnutls_cipher_get_iv_size(cipher); ++ ++ ret = gnutls_cipher_init(&hd, cipher, &key, &iv); ++ if (ret < 0) ++ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); ++ ++ for (offset = 0; ++ offset + block <= vectors[i].plaintext_size; ++ offset += block) { ++ ret = ++ gnutls_cipher_decrypt2(hd, ++ vectors[i].ciphertext + offset, ++ MIN(block, vectors[i].plaintext_size - offset), ++ tmp + offset, ++ sizeof(tmp) - offset); ++ if (ret < 0) ++ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); ++ } ++ ++ if (memcmp ++ (tmp, vectors[i].plaintext, ++ vectors[i].plaintext_size) != 0) { ++ _gnutls_debug_log("%s decryption of test vector %d failed with block size %d!\n", ++ gnutls_cipher_get_name(cipher), ++ i, (int)block); ++ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR); ++ } ++ ++ gnutls_cipher_deinit(hd); ++ } ++ } ++ ++ _gnutls_debug_log ++ ("%s self check succeeded\n", ++ gnutls_cipher_get_name(cipher)); ++ ++ return 0; ++} ++ + /* AEAD modes (compat APIs) */ + static int test_cipher_aead_compat(gnutls_cipher_algorithm_t cipher, + const struct cipher_aead_vectors_st *vectors, +@@ -1721,6 +1822,14 @@ static int test_mac(gnutls_mac_algorithm_t mac, + if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL) || ret < 0) \ + return ret + ++#define CASE2(x, func, func2, vectors) case x: \ ++ ret = func(x, V(vectors), flags); \ ++ if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL) || ret < 0) \ ++ return ret; \ ++ ret = func2(x, V(vectors), flags); \ ++ if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL) || ret < 0) \ ++ return ret ++ + #define NON_FIPS_CASE(x, func, vectors) case x: \ + if (_gnutls_fips_mode_enabled() == 0) { \ + ret = func(x, V(vectors), flags); \ +@@ -1786,14 +1895,17 @@ int gnutls_cipher_self_test(unsigned flags, gnutls_cipher_algorithm_t cipher) + NON_FIPS_CASE(GNUTLS_CIPHER_CHACHA20_POLY1305, test_cipher_aead, + chacha_poly1305_vectors); + FALLTHROUGH; +- CASE(GNUTLS_CIPHER_AES_128_CFB8, test_cipher, +- aes128_cfb8_vectors); ++ CASE2(GNUTLS_CIPHER_AES_128_CFB8, test_cipher, ++ test_cipher_all_block_sizes, ++ aes128_cfb8_vectors); + FALLTHROUGH; +- CASE(GNUTLS_CIPHER_AES_192_CFB8, test_cipher, +- aes192_cfb8_vectors); ++ CASE2(GNUTLS_CIPHER_AES_192_CFB8, test_cipher, ++ test_cipher_all_block_sizes, ++ aes192_cfb8_vectors); + FALLTHROUGH; +- CASE(GNUTLS_CIPHER_AES_256_CFB8, test_cipher, +- aes256_cfb8_vectors); ++ CASE2(GNUTLS_CIPHER_AES_256_CFB8, test_cipher, ++ test_cipher_all_block_sizes, ++ aes256_cfb8_vectors); + FALLTHROUGH; + CASE(GNUTLS_CIPHER_AES_128_XTS, test_cipher, + aes128_xts_vectors); +-- +2.21.0 + diff --git a/SPECS/gnutls.spec b/SPECS/gnutls.spec index f71519b..007d302 100644 --- a/SPECS/gnutls.spec +++ b/SPECS/gnutls.spec @@ -1,5 +1,5 @@ Version: 3.6.8 -Release: 8%{?dist} +Release: 9%{?dist} Patch1: gnutls-3.2.7-rpath.patch Patch2: gnutls-3.6.4-no-now-guile.patch Patch3: gnutls-3.6.5-fix-fips-signature-post.patch @@ -11,6 +11,9 @@ Patch8: gnutls-3.6.8-pkcs11-login-error.patch Patch9: gnutls-3.6.8-fips-deterministic-ecdsa.patch Patch10: gnutls-3.6.8-aead-cipher-encryptv2.patch Patch11: gnutls-3.6.8-fips-rsa-random-selftests.patch +Patch12: gnutls-3.6.8-decr-len.patch +Patch13: gnutls-3.6.8-fix-aead-cipher-encryptv2.patch +Patch14: gnutls-3.6.8-fix-cfb8-decrypt.patch %bcond_without dane %if 0%{?rhel} %bcond_with guile @@ -294,6 +297,10 @@ fi %endif %changelog +* Wed Nov 6 2019 Daiki Ueno - 3.6.8-9 +- Fix CFB8 decryption when repeatedly called (#1757848) +- Fix gnutls_aead_cipher_{en,de}cryptv2 with input not multiple of block size (#1757856) + * Fri Aug 16 2019 Daiki Ueno - 3.6.8-8 - Use fallback random function for RSA blinding in FIPS selftests