TLS: Add negative tests for non-EtM CBC decryption
Signed-off-by: Manuel Pégourié-Gonnard <manuel.pegourie-gonnard@arm.com>
diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function
index 5cf6e8b..7f64f29 100644
--- a/tests/suites/test_suite_ssl.function
+++ b/tests/suites/test_suite_ssl.function
@@ -3452,6 +3452,116 @@
}
/* END_CASE */
+/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_2 */
+void ssl_decrypt_non_etm_cbc( int cipher_type, int hash_id, int trunc_hmac,
+ int plaintext_len, int badmac, data_t *padding,
+ int exp_ret )
+{
+ /*
+ * Test record decryption for CBC without EtM with possibly incorrect
+ * padding (provided as input) or MAC (generated by this function).
+ *
+ * Actually depends on TLS >= 1.0 (SSL 3.0 computes the MAC differently),
+ * but since the test framework doesn't support alternation in dependency
+ * statements, just depend on TLS 1.2.
+ */
+ mbedtls_ssl_context ssl; /* ONLY for debugging */
+ mbedtls_ssl_transform t0, t1;
+ mbedtls_record rec;
+ unsigned char *buf = NULL;
+ size_t buflen, olen = 0;
+ const size_t rec_data_offset = 16; /* IV size */
+ unsigned char add_data[13];
+ unsigned char mac[MBEDTLS_MD_MAX_SIZE];
+
+ mbedtls_ssl_init( &ssl );
+ mbedtls_ssl_transform_init( &t0 );
+ mbedtls_ssl_transform_init( &t1 );
+
+ /* Set up transforms with dummy keys */
+ TEST_ASSERT( build_transforms( &t0, &t1, cipher_type, hash_id,
+ 0, trunc_hmac,
+ MBEDTLS_SSL_MINOR_VERSION_3,
+ 0 , 0 ) == 0 );
+
+ /* Prepare a buffer for record data */
+ buflen = rec_data_offset
+ + plaintext_len
+ + t0.maclen
+ + padding->len;
+ ASSERT_ALLOC( buf, buflen );
+
+ /* Prepare a dummy record header */
+ memset( rec.ctr, 0, sizeof( rec.ctr ) );
+ rec.type = MBEDTLS_SSL_MSG_APPLICATION_DATA;
+ rec.ver[0] = MBEDTLS_SSL_MAJOR_VERSION_3;
+ rec.ver[1] = MBEDTLS_SSL_MINOR_VERSION_3;
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ rec.cid_len = 0;
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+ /* Prepare dummy record content */
+ rec.buf = buf;
+ rec.buf_len = buflen;
+ rec.data_offset = rec_data_offset;
+ rec.data_len = plaintext_len;
+ memset( rec.buf + rec.data_offset, 42, rec.data_len );
+
+ /*
+ * MAC, "pad" and encrypt - this near-duplicates the TLS 1.x non-EtM CBC
+ * code path of mbedtls_ssl_encrypt_buf(), but with user-provided padding,
+ * and possibly wrong HMAC. Also, without safety checks or CID support.
+ */
+
+ /* MAC with additional data */
+ memcpy( add_data, rec.ctr, 8 );
+ add_data[8] = rec.type;
+ add_data[9] = rec.ver[0];
+ add_data[10] = rec.ver[1];
+ add_data[11] = ( rec.data_len >> 8 ) & 0xff;
+ add_data[12] = ( rec.data_len >> 0 ) & 0xff;
+
+ TEST_EQUAL( 0, mbedtls_md_hmac_update( &t0.md_ctx_enc, add_data, 13 ) );
+ TEST_EQUAL( 0, mbedtls_md_hmac_update( &t0.md_ctx_enc,
+ rec.buf + rec.data_offset,
+ rec.data_len ) );
+ TEST_EQUAL( 0, mbedtls_md_hmac_finish( &t0.md_ctx_enc, mac ) );
+
+ memcpy( rec.buf + rec.data_offset + rec.data_len, mac, t0.maclen );
+ rec.data_len += t0.maclen;
+
+ /* Possibly falsify the MAC */
+ rec.buf[rec.data_offset + rec.data_len - 1] ^= badmac;
+
+ /* Append the user-provided padding */
+ memcpy( rec.buf + rec.data_offset + rec.data_len, padding->x, padding->len );
+ rec.data_len += padding->len;
+
+ /* Set dummy IV and encrypt */
+ memset( t0.iv_enc, 0x55, t0.ivlen );
+ TEST_ASSERT( t0.ivlen == rec_data_offset );
+ memcpy( rec.buf, t0.iv_enc, rec_data_offset );
+
+ TEST_EQUAL( 0, mbedtls_cipher_crypt( &t0.cipher_ctx_enc,
+ t0.iv_enc, t0.ivlen,
+ rec.buf + rec.data_offset, rec.data_len,
+ rec.buf + rec.data_offset, &olen ) );
+ rec.data_offset -= t0.ivlen;
+ rec.data_len += t0.ivlen;
+
+ /*
+ * Try to decrypt and check that we get the expected result
+ */
+ TEST_EQUAL( exp_ret, mbedtls_ssl_decrypt_buf( &ssl, &t1, &rec ) );
+
+exit:
+ mbedtls_ssl_free( &ssl );
+ mbedtls_ssl_transform_free( &t0 );
+ mbedtls_ssl_transform_free( &t1 );
+ mbedtls_free( buf );
+}
+/* END_CASE */
+
/* BEGIN_CASE */
void ssl_tls_prf( int type, data_t * secret, data_t * random,
char *label, data_t *result_hex_str, int exp_ret )