diff --git a/tests/suites/test_suite_ssl_decrypt.function b/tests/suites/test_suite_ssl_decrypt.function index a7104bf20..39c92ce1e 100644 --- a/tests/suites/test_suite_ssl_decrypt.function +++ b/tests/suites/test_suite_ssl_decrypt.function @@ -2,6 +2,7 @@ /* Testing of mbedtls_ssl_decrypt_buf() specifically, focusing on negative * testing (using malformed inputs). */ +#include #include #include @@ -12,6 +13,128 @@ * END_DEPENDENCIES */ +/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_SOME_MODES_USE_MAC */ +void ssl_decrypt_stream(int cipher_type, int hash_id, int trunc_hmac) +{ + mbedtls_ssl_transform transform_in, transform_out; + mbedtls_ssl_transform_init(&transform_in); + mbedtls_ssl_transform_init(&transform_out); + mbedtls_record rec_good = { + .ctr = { 0 }, + .type = MBEDTLS_SSL_MSG_APPLICATION_DATA, + /* For simplicity, we only test one protocol version (TLS 1.2). + * For stream ciphers (unlike CBC), there are no changes in the + * data record format between SSL 3.0 and TLS 1.2 inclusive, so + * testing a single version should be good enough. */ + .ver = { MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3 }, + .buf = NULL, + .buf_len = 0, + .data_offset = 0, + .data_len = 0, +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + .cid_len = 0, + .cid = { 0 }, +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + }; + const char sample_plaintext[3] = "ABC"; + mbedtls_cipher_context_t cipher; + mbedtls_cipher_init(&cipher); + mbedtls_ssl_context ssl; + mbedtls_ssl_init(&ssl); + uint8_t *buf = NULL; + + USE_PSA_INIT(); + + TEST_EQUAL(mbedtls_test_ssl_build_transforms(&transform_in, &transform_out, + cipher_type, hash_id, + 0, trunc_hmac, + rec_good.ver[1], + 0, 0), 0); + + const size_t plaintext_length = sizeof(sample_plaintext); + rec_good.buf_len = plaintext_length + transform_in.maclen; + rec_good.data_len = plaintext_length; + TEST_CALLOC(rec_good.buf, rec_good.buf_len); + memcpy(rec_good.buf, sample_plaintext, plaintext_length); + TEST_EQUAL(mbedtls_test_ssl_prepare_record_mac(&rec_good, + &transform_out), 0); + + /* Encrypt in place */ + size_t len; + TEST_EQUAL(mbedtls_cipher_crypt(&transform_out.cipher_ctx_enc, + transform_out.iv_enc, transform_out.ivlen, + rec_good.buf + rec_good.data_offset, + rec_good.data_len, + rec_good.buf + rec_good.data_offset, + &len), 0); + /* This function only supports stream ciphers, which should preserve + * the length. */ + TEST_EQUAL(len, rec_good.data_len); + + /* Good case */ + mbedtls_record rec = rec_good; + TEST_EQUAL(mbedtls_ssl_decrypt_buf(&ssl, &transform_in, &rec), 0); + + /* Change any one byte of the plaintext or MAC. The MAC will be wrong. */ + TEST_CALLOC(buf, rec.buf_len); + for (size_t i = 0; i < rec.buf_len; i++) { + mbedtls_test_set_step(i); + rec = rec_good; + rec.buf = buf; + memcpy(buf, rec_good.buf, rec.buf_len); + buf[i] ^= 1; + TEST_EQUAL(mbedtls_ssl_decrypt_buf(&ssl, &transform_in, &rec), + MBEDTLS_ERR_SSL_INVALID_MAC); + } + mbedtls_free(buf); + buf = NULL; + + /* Shorter input buffer. Either the MAC will be wrong, or there isn't + * enough room for a MAC. */ + for (size_t n = 1; n < rec.buf_len; n++) { + mbedtls_test_set_step(n); + rec = rec_good; + TEST_CALLOC(buf, n); + rec.buf = buf; + rec.buf_len = n; + rec.data_len = n; + memcpy(buf, rec_good.buf, n); + TEST_EQUAL(mbedtls_ssl_decrypt_buf(&ssl, &transform_in, &rec), + MBEDTLS_ERR_SSL_INVALID_MAC); + mbedtls_free(buf); + buf = NULL; + } + + /* For robustness, check a 0-length buffer (non-null, then null). + * This should not reach mbedtls_ssl_decrypt_buf() as used in the library, + * so the exact error doesn't matter, but we don't want a crash. */ + { + const uint8_t buf1[1] = { 'a' }; + rec = rec_good; + /* We won't write to buf1[0] since it's out of range, so we can cast + * the const away. */ + rec.buf = (uint8_t *) buf1; + rec.buf_len = 0; + TEST_EQUAL(mbedtls_ssl_decrypt_buf(&ssl, &transform_in, &rec), + MBEDTLS_ERR_SSL_INTERNAL_ERROR); + } + rec = rec_good; + rec.buf = NULL; + rec.buf_len = 0; + TEST_EQUAL(mbedtls_ssl_decrypt_buf(&ssl, &transform_in, &rec), + MBEDTLS_ERR_SSL_INTERNAL_ERROR); + +exit: + USE_PSA_DONE(); + mbedtls_ssl_transform_free(&transform_in); + mbedtls_ssl_transform_free(&transform_out); + mbedtls_free(rec_good.buf); + mbedtls_ssl_free(&ssl); + mbedtls_cipher_free(&cipher); + mbedtls_free(buf); +} +/* END_CASE */ + /* BEGIN_CASE depends_on:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_AES_C:MBEDTLS_SSL_PROTO_TLS1_2 */ void ssl_decrypt_non_etm_cbc(int cipher_type, int hash_id, int trunc_hmac, int length_selector) diff --git a/tests/suites/test_suite_ssl_decrypt.misc.data b/tests/suites/test_suite_ssl_decrypt.misc.data index c2e543e57..770ca6f21 100644 --- a/tests/suites/test_suite_ssl_decrypt.misc.data +++ b/tests/suites/test_suite_ssl_decrypt.misc.data @@ -1,3 +1,67 @@ +Decrypt null cipher, MD5 +depends_on:MBEDTLS_CIPHER_NULL_CIPHER:MBEDTLS_MD5_C +ssl_decrypt_stream:MBEDTLS_CIPHER_NULL:MBEDTLS_MD_MD5:0 + +Decrypt null cipher, MD5 trunc +depends_on:MBEDTLS_CIPHER_NULL_CIPHER:MBEDTLS_MD5_C +ssl_decrypt_stream:MBEDTLS_CIPHER_NULL:MBEDTLS_MD_MD5:1 + +Decrypt null cipher, SHA-1 +depends_on:MBEDTLS_CIPHER_NULL_CIPHER:MBEDTLS_SHA1_C +ssl_decrypt_stream:MBEDTLS_CIPHER_NULL:MBEDTLS_MD_SHA1:0 + +Decrypt null cipher, SHA-1 trunc +depends_on:MBEDTLS_CIPHER_NULL_CIPHER:MBEDTLS_SHA1_C +ssl_decrypt_stream:MBEDTLS_CIPHER_NULL:MBEDTLS_MD_SHA1:1 + +Decrypt null cipher, SHA-256 +depends_on:MBEDTLS_CIPHER_NULL_CIPHER:MBEDTLS_SHA256_C +ssl_decrypt_stream:MBEDTLS_CIPHER_NULL:MBEDTLS_MD_SHA256:0 + +Decrypt null cipher, SHA-256 trunc +depends_on:MBEDTLS_CIPHER_NULL_CIPHER:MBEDTLS_SHA256_C +ssl_decrypt_stream:MBEDTLS_CIPHER_NULL:MBEDTLS_MD_SHA256:1 + +Decrypt null cipher, SHA-384 +depends_on:MBEDTLS_CIPHER_NULL_CIPHER:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384 +ssl_decrypt_stream:MBEDTLS_CIPHER_NULL:MBEDTLS_MD_SHA384:0 + +Decrypt null cipher, SHA-384 trunc +depends_on:MBEDTLS_CIPHER_NULL_CIPHER:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384 +ssl_decrypt_stream:MBEDTLS_CIPHER_NULL:MBEDTLS_MD_SHA384:1 + +Decrypt RC4, MD5 +depends_on:MBEDTLS_ARC4_C:MBEDTLS_MD5_C +ssl_decrypt_stream:MBEDTLS_CIPHER_ARC4_128:MBEDTLS_MD_MD5:0 + +Decrypt RC4, MD5 trunc +depends_on:MBEDTLS_ARC4_C:MBEDTLS_MD5_C +ssl_decrypt_stream:MBEDTLS_CIPHER_ARC4_128:MBEDTLS_MD_MD5:1 + +Decrypt RC4, SHA-1 +depends_on:MBEDTLS_ARC4_C:MBEDTLS_SHA1_C +ssl_decrypt_stream:MBEDTLS_CIPHER_ARC4_128:MBEDTLS_MD_SHA1:0 + +Decrypt RC4, SHA-1 trunc +depends_on:MBEDTLS_ARC4_C:MBEDTLS_SHA1_C +ssl_decrypt_stream:MBEDTLS_CIPHER_ARC4_128:MBEDTLS_MD_SHA1:1 + +Decrypt RC4, SHA-256 +depends_on:MBEDTLS_ARC4_C:MBEDTLS_SHA256_C +ssl_decrypt_stream:MBEDTLS_CIPHER_ARC4_128:MBEDTLS_MD_SHA256:0 + +Decrypt RC4, SHA-256 trunc +depends_on:MBEDTLS_ARC4_C:MBEDTLS_SHA256_C +ssl_decrypt_stream:MBEDTLS_CIPHER_ARC4_128:MBEDTLS_MD_SHA256:1 + +Decrypt RC4, SHA-384 +depends_on:MBEDTLS_ARC4_C:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384 +ssl_decrypt_stream:MBEDTLS_CIPHER_ARC4_128:MBEDTLS_MD_SHA384:0 + +Decrypt RC4, SHA-384 trunc +depends_on:MBEDTLS_ARC4_C:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384 +ssl_decrypt_stream:MBEDTLS_CIPHER_ARC4_128:MBEDTLS_MD_SHA384:1 + Decrypt CBC !EtM, AES MD5 !trunc, empty plaintext, minpad depends_on:MBEDTLS_AES_C:MBEDTLS_MD5_C ssl_decrypt_non_etm_cbc:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_MD_MD5:0:-1