mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2024-12-23 09:35:39 +00:00
Merge pull request #717 from mpg/non-etm-cbc-negative-testing
Add negative tests for non-EtM CBC decryption
This commit is contained in:
commit
ea6a740923
File diff suppressed because it is too large
Load diff
|
@ -3452,6 +3452,219 @@ exit:
|
|||
}
|
||||
/* 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 )
|
||||
{
|
||||
/*
|
||||
* Test record decryption for CBC without EtM, focused on the verification
|
||||
* of padding and MAC.
|
||||
*
|
||||
* Actually depends on TLS >= 1.0 (SSL 3.0 computes the MAC differently),
|
||||
* and either AES, ARIA, Camellia or DES, but since the test framework
|
||||
* doesn't support alternation in dependency statements, just depend on
|
||||
* TLS 1.2 and AES.
|
||||
*
|
||||
* The length_selector argument is interpreted as follows:
|
||||
* - if it's -1, the plaintext length is 0 and minimal padding is applied
|
||||
* - if it's -2, the plaintext length is 0 and maximal padding is applied
|
||||
* - otherwise it must be in [0, 255] and is padding_length from RFC 5246:
|
||||
* it's the length of the rest of the padding, that is, excluding the
|
||||
* byte that encodes the length. The minimal non-zero plaintext length
|
||||
* that gives this padding_length is automatically selected.
|
||||
*/
|
||||
mbedtls_ssl_context ssl; /* ONLY for debugging */
|
||||
mbedtls_ssl_transform t0, t1;
|
||||
mbedtls_record rec, rec_save;
|
||||
unsigned char *buf = NULL, *buf_save = NULL;
|
||||
size_t buflen, olen = 0;
|
||||
size_t plaintext_len, block_size, i;
|
||||
unsigned char padlen; /* excluding the padding_length byte */
|
||||
unsigned char add_data[13];
|
||||
unsigned char mac[MBEDTLS_MD_MAX_SIZE];
|
||||
int exp_ret;
|
||||
const unsigned char pad_max_len = 255; /* Per the standard */
|
||||
|
||||
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 );
|
||||
|
||||
/* Determine padding/plaintext length */
|
||||
TEST_ASSERT( length_selector >= -2 && length_selector <= 255 );
|
||||
block_size = t0.ivlen;
|
||||
if( length_selector < 0 )
|
||||
{
|
||||
plaintext_len = 0;
|
||||
|
||||
/* Minimal padding
|
||||
* The +1 is for the padding_length byte, not counted in padlen. */
|
||||
padlen = block_size - ( t0.maclen + 1 ) % block_size;
|
||||
|
||||
/* Maximal padding? */
|
||||
if( length_selector == -2 )
|
||||
padlen += block_size * ( ( pad_max_len - padlen ) / block_size );
|
||||
}
|
||||
else
|
||||
{
|
||||
padlen = length_selector;
|
||||
|
||||
/* Minimal non-zero plaintext_length giving desired padding.
|
||||
* The +1 is for the padding_length byte, not counted in padlen. */
|
||||
plaintext_len = block_size - ( padlen + t0.maclen + 1 ) % block_size;
|
||||
}
|
||||
|
||||
/* Prepare a buffer for record data */
|
||||
buflen = block_size
|
||||
+ plaintext_len
|
||||
+ t0.maclen
|
||||
+ padlen + 1;
|
||||
ASSERT_ALLOC( buf, buflen );
|
||||
ASSERT_ALLOC( buf_save, 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 = block_size;
|
||||
rec.data_len = plaintext_len;
|
||||
memset( rec.buf + rec.data_offset, 42, rec.data_len );
|
||||
|
||||
/* Serialized version of record header for MAC purposes */
|
||||
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;
|
||||
|
||||
/* Set dummy IV */
|
||||
memset( t0.iv_enc, 0x55, t0.ivlen );
|
||||
memcpy( rec.buf, t0.iv_enc, t0.ivlen );
|
||||
|
||||
/*
|
||||
* Prepare a pre-encryption record (with MAC and padding), and save it.
|
||||
*/
|
||||
|
||||
/* MAC with additional data */
|
||||
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;
|
||||
|
||||
/* Pad */
|
||||
memset( rec.buf + rec.data_offset + rec.data_len, padlen, padlen + 1 );
|
||||
rec.data_len += padlen + 1;
|
||||
|
||||
/* Save correct pre-encryption record */
|
||||
rec_save = rec;
|
||||
rec_save.buf = buf_save;
|
||||
memcpy( buf_save, buf, buflen );
|
||||
|
||||
/*
|
||||
* Encrypt and decrypt the correct record, expecting success
|
||||
*/
|
||||
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;
|
||||
|
||||
TEST_EQUAL( 0, mbedtls_ssl_decrypt_buf( &ssl, &t1, &rec ) );
|
||||
|
||||
/*
|
||||
* Modify each byte of the pre-encryption record before encrypting and
|
||||
* decrypting it, expecting failure every time.
|
||||
*/
|
||||
for( i = block_size; i < buflen; i++ )
|
||||
{
|
||||
test_set_step( i );
|
||||
|
||||
/* Restore correct pre-encryption record */
|
||||
rec = rec_save;
|
||||
rec.buf = buf;
|
||||
memcpy( buf, buf_save, buflen );
|
||||
|
||||
/* Corrupt one byte of the data (could be plaintext, MAC or padding) */
|
||||
rec.buf[i] ^= 0x01;
|
||||
|
||||
/* Encrypt */
|
||||
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;
|
||||
|
||||
/* Decrypt and expect failure */
|
||||
TEST_EQUAL( MBEDTLS_ERR_SSL_INVALID_MAC,
|
||||
mbedtls_ssl_decrypt_buf( &ssl, &t1, &rec ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Use larger values of the padding bytes - with small buffers, this tests
|
||||
* the case where the announced padlen would be larger than the buffer
|
||||
* (and before that, than the buffer minus the size of the MAC), to make
|
||||
* sure our padding checking code does not perform any out-of-bounds reads
|
||||
* in this case. (With larger buffers, ie when the plaintext is long or
|
||||
* maximal length padding is used, this is less relevant but still doesn't
|
||||
* hurt to test.)
|
||||
*
|
||||
* (Start the loop with correct padding, just to double-check that record
|
||||
* saving did work, and that we're overwriting the correct bytes.)
|
||||
*/
|
||||
for( i = padlen; i <= pad_max_len; i++ )
|
||||
{
|
||||
test_set_step( i );
|
||||
|
||||
/* Restore correct pre-encryption record */
|
||||
rec = rec_save;
|
||||
rec.buf = buf;
|
||||
memcpy( buf, buf_save, buflen );
|
||||
|
||||
/* Set padding bytes to new value */
|
||||
memset( buf + buflen - padlen - 1, i, padlen + 1 );
|
||||
|
||||
/* Encrypt */
|
||||
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;
|
||||
|
||||
/* Decrypt and expect failure except the first time */
|
||||
exp_ret = ( i == padlen ) ? 0 : MBEDTLS_ERR_SSL_INVALID_MAC;
|
||||
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 );
|
||||
mbedtls_free( buf_save );
|
||||
}
|
||||
/* 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 )
|
||||
|
|
Loading…
Reference in a new issue