Test mbedtls_ssl_decrypt_buf(): stream cipher, negative cases

Test mbedtls_ssl_decrypt_buf() with a null cipher (the only type of stream
cipher we support). Test the good case (to make sure the test code
constructs the input correctly), test with an invalid MAC, and test with a
shortened input.

Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
This commit is contained in:
Gilles Peskine 2023-09-18 14:05:55 +02:00
parent 9099d3fd76
commit d2e004e401
2 changed files with 123 additions and 0 deletions

View file

@ -13,6 +13,113 @@
* END_DEPENDENCIES
*/
/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_CIPHER_NULL_CIPHER */
void ssl_decrypt_null(int hash_id)
{
mbedtls_ssl_transform transform_in, transform_out;
mbedtls_ssl_transform_init(&transform_in);
mbedtls_ssl_transform_init(&transform_out);
const mbedtls_ssl_protocol_version version = MBEDTLS_SSL_VERSION_TLS1_2;
const mbedtls_cipher_type_t cipher_type = MBEDTLS_CIPHER_NULL;
mbedtls_record rec_good = {
.ctr = { 0 },
.type = MBEDTLS_SSL_MSG_APPLICATION_DATA,
.ver = { 0, 0 }, /* Will be set by a function call below */
.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 */
};
mbedtls_ssl_write_version(rec_good.ver,
MBEDTLS_SSL_TRANSPORT_STREAM,
version);
const char sample_plaintext[3] = "ABC";
mbedtls_ssl_context ssl;
mbedtls_ssl_init(&ssl);
uint8_t *buf = NULL;
MD_OR_USE_PSA_INIT();
TEST_EQUAL(mbedtls_test_ssl_build_transforms(&transform_in, &transform_out,
cipher_type, hash_id, 0, 0,
version,
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);
/* 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:
mbedtls_ssl_transform_free(&transform_in);
mbedtls_ssl_transform_free(&transform_out);
mbedtls_free(rec_good.buf);
mbedtls_ssl_free(&ssl);
mbedtls_free(buf);
MD_OR_USE_PSA_DONE();
}
/* 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)

View file

@ -1,3 +1,19 @@
Decrypt null cipher, MD5
depends_on:MBEDTLS_MD_CAN_MD5
ssl_decrypt_null:MBEDTLS_MD_MD5
Decrypt null cipher, SHA-1
depends_on:MBEDTLS_MD_CAN_SHA1
ssl_decrypt_null:MBEDTLS_MD_SHA1
Decrypt null cipher, SHA-256
depends_on:MBEDTLS_MD_CAN_SHA256
ssl_decrypt_null:MBEDTLS_MD_SHA256
Decrypt null cipher, SHA-384
depends_on:MBEDTLS_MD_CAN_SHA384
ssl_decrypt_null:MBEDTLS_MD_SHA384
Decrypt CBC !EtM, AES MD5 !trunc, empty plaintext, minpad
depends_on:MBEDTLS_AES_C:MBEDTLS_MD_CAN_MD5
ssl_decrypt_non_etm_cbc:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_MD_MD5:0:-1