diff --git a/ChangeLog.d/ssl_decrypt_buf-short_record.txt b/ChangeLog.d/ssl_decrypt_buf-short_record.txt new file mode 100644 index 0000000000000000000000000000000000000000..88dc219acb506c4ad494eaf6f2e43f04868e1cf2 --- /dev/null +++ b/ChangeLog.d/ssl_decrypt_buf-short_record.txt @@ -0,0 +1,3 @@ +Security + * Fix a buffer overread when parsing short TLS application data records in + null-cipher cipher suites. Credit to OSS-Fuzz. \ No newline at end of file diff --git a/library/ssl_msg.c b/library/ssl_msg.c index 51eb4619c68c2d0bd4249c43a2fff83bc151ba25..be4e333db035bf513de6ef04c3936686f25a2747 100644 --- a/library/ssl_msg.c +++ b/library/ssl_msg.c @@ -1038,6 +1038,13 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl, #if defined(MBEDTLS_SSL_SOME_SUITES_USE_STREAM) if( mode == MBEDTLS_MODE_STREAM ) { + if (rec->data_len < transform->maclen) { + MBEDTLS_SSL_DEBUG_MSG(1, + ("Record too short for MAC:" + " %" MBEDTLS_PRINTF_SIZET " < %" MBEDTLS_PRINTF_SIZET, + rec->data_len, transform->maclen)); + return MBEDTLS_ERR_SSL_INVALID_MAC; + } padlen = 0; if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_dec, transform->iv_dec, @@ -1430,7 +1437,7 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl, unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD]; unsigned char mac_peer[MBEDTLS_SSL_MAC_ADD]; - /* If the initial value of padlen was such that + /* For CBC+MAC, If the initial value of padlen was such that * data_len < maclen + padlen + 1, then padlen * got reset to 1, and the initial check * data_len >= minlen + maclen + 1 @@ -1442,6 +1449,9 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl, * subtracted either padlen + 1 (if the padding was correct) * or 0 (if the padding was incorrect) since then, * hence data_len >= maclen in any case. + * + * For stream ciphers, we checked above that + * data_len >= maclen. */ rec->data_len -= transform->maclen; ssl_extract_add_data_from_record( add_data, &add_data_len, rec,