Merge remote-tracking branch 'restricted/pr/516' into development

This commit is contained in:
Simon Butcher 2018-11-29 16:53:51 +00:00
commit 658618b6b2
4 changed files with 444 additions and 44 deletions

View file

@ -1,5 +1,14 @@
mbed TLS ChangeLog (Sorted per branch, date) mbed TLS ChangeLog (Sorted per branch, date)
= mbed TLS 2.xx.x branch released xxxx-xx-xx
Security
* Fix timing variations and memory access variations in RSA PKCS#1 v1.5
decryption that could lead to a Bleichenbacher-style padding oracle
attack. In TLS, this affects RSA-based ciphersuites without DHE or
ECDHE. Reported by Yuval Yarom, Eyal Ronen, Adi Shamir, David Wong and
Daniel Genkin.
= mbed TLS 2.14.0 branch released 2018-11-19 = mbed TLS 2.14.0 branch released 2018-11-19
Security Security

View file

@ -1387,6 +1387,97 @@ cleanup:
#endif /* MBEDTLS_PKCS1_V21 */ #endif /* MBEDTLS_PKCS1_V21 */
#if defined(MBEDTLS_PKCS1_V15) #if defined(MBEDTLS_PKCS1_V15)
/** Turn zero-or-nonzero into zero-or-all-bits-one, without branches.
*
* \param value The value to analyze.
* \return Zero if \p value is zero, otherwise all-bits-one.
*/
static unsigned all_or_nothing_int( unsigned value )
{
/* MSVC has a warning about unary minus on unsigned, but this is
* well-defined and precisely what we want to do here */
#if defined(_MSC_VER)
#pragma warning( push )
#pragma warning( disable : 4146 )
#endif
return( - ( ( value | - value ) >> ( sizeof( value ) * 8 - 1 ) ) );
#if defined(_MSC_VER)
#pragma warning( pop )
#endif
}
/** Check whether a size is out of bounds, without branches.
*
* This is equivalent to `size > max`, but is likely to be compiled to
* to code using bitwise operation rather than a branch.
*
* \param size Size to check.
* \param max Maximum desired value for \p size.
* \return \c 0 if `size <= max`.
* \return \c 1 if `size > max`.
*/
static unsigned size_greater_than( size_t size, size_t max )
{
/* Return the sign bit (1 for negative) of (max - size). */
return( ( max - size ) >> ( sizeof( size_t ) * 8 - 1 ) );
}
/** Choose between two integer values, without branches.
*
* This is equivalent to `cond ? if1 : if0`, but is likely to be compiled
* to code using bitwise operation rather than a branch.
*
* \param cond Condition to test.
* \param if1 Value to use if \p cond is nonzero.
* \param if0 Value to use if \p cond is zero.
* \return \c if1 if \p cond is nonzero, otherwise \c if0.
*/
static unsigned if_int( unsigned cond, unsigned if1, unsigned if0 )
{
unsigned mask = all_or_nothing_int( cond );
return( ( mask & if1 ) | (~mask & if0 ) );
}
/** Shift some data towards the left inside a buffer without leaking
* the length of the data through side channels.
*
* `mem_move_to_left(start, total, offset)` is functionally equivalent to
* ```
* memmove(start, start + offset, total - offset);
* memset(start + offset, 0, total - offset);
* ```
* but it strives to use a memory access pattern (and thus total timing)
* that does not depend on \p offset. This timing independence comes at
* the expense of performance.
*
* \param start Pointer to the start of the buffer.
* \param total Total size of the buffer.
* \param offset Offset from which to copy \p total - \p offset bytes.
*/
static void mem_move_to_left( void *start,
size_t total,
size_t offset )
{
volatile unsigned char *buf = start;
size_t i, n;
if( total == 0 )
return;
for( i = 0; i < total; i++ )
{
unsigned no_op = size_greater_than( total - offset, i );
/* The first `total - offset` passes are a no-op. The last
* `offset` passes shift the data one byte to the left and
* zero out the last byte. */
for( n = 0; n < total - 1; n++ )
{
unsigned char current = buf[n];
unsigned char next = buf[n+1];
buf[n] = if_int( no_op, current, next );
}
buf[total-1] = if_int( no_op, buf[total-1], 0 );
}
}
/* /*
* Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function
*/ */
@ -1396,18 +1487,34 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx,
int mode, size_t *olen, int mode, size_t *olen,
const unsigned char *input, const unsigned char *input,
unsigned char *output, unsigned char *output,
size_t output_max_len) size_t output_max_len )
{ {
int ret; int ret;
size_t ilen, pad_count = 0, i; size_t ilen = ctx->len;
unsigned char *p, bad, pad_done = 0; size_t i;
size_t plaintext_max_size = ( output_max_len > ilen - 11 ?
ilen - 11 :
output_max_len );
unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
/* The following variables take sensitive values: their value must
* not leak into the observable behavior of the function other than
* the designated outputs (output, olen, return value). Otherwise
* this would open the execution of the function to
* side-channel-based variants of the Bleichenbacher padding oracle
* attack. Potential side channels include overall timing, memory
* access patterns (especially visible to an adversary who has access
* to a shared memory cache), and branches (especially visible to
* an adversary who has access to a shared code cache or to a shared
* branch predictor). */
size_t pad_count = 0;
unsigned bad = 0;
unsigned char pad_done = 0;
size_t plaintext_size = 0;
unsigned output_too_large;
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
ilen = ctx->len;
if( ilen < 16 || ilen > sizeof( buf ) ) if( ilen < 16 || ilen > sizeof( buf ) )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
@ -1418,63 +1525,109 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx,
if( ret != 0 ) if( ret != 0 )
goto cleanup; goto cleanup;
p = buf; /* Check and get padding length in constant time and constant
bad = 0; * memory trace. The first byte must be 0. */
bad |= buf[0];
/*
* Check and get padding len in "constant-time"
*/
bad |= *p++; /* First byte must be 0 */
/* This test does not depend on secret data */
if( mode == MBEDTLS_RSA_PRIVATE ) if( mode == MBEDTLS_RSA_PRIVATE )
{ {
bad |= *p++ ^ MBEDTLS_RSA_CRYPT; /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00
* where PS must be at least 8 nonzero bytes. */
bad |= buf[1] ^ MBEDTLS_RSA_CRYPT;
/* Get padding len, but always read till end of buffer /* Read the whole buffer. Set pad_done to nonzero if we find
* (minus one, for the 00 byte) */ * the 0x00 byte and remember the padding length in pad_count. */
for( i = 0; i < ilen - 3; i++ ) for( i = 2; i < ilen; i++ )
{ {
pad_done |= ((p[i] | (unsigned char)-p[i]) >> 7) ^ 1; pad_done |= ((buf[i] | (unsigned char)-buf[i]) >> 7) ^ 1;
pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1;
} }
p += pad_count;
bad |= *p++; /* Must be zero */
} }
else else
{ {
bad |= *p++ ^ MBEDTLS_RSA_SIGN; /* Decode EMSA-PKCS1-v1_5 padding: 0x00 || 0x01 || PS || 0x00
* where PS must be at least 8 bytes with the value 0xFF. */
bad |= buf[1] ^ MBEDTLS_RSA_SIGN;
/* Get padding len, but always read till end of buffer /* Read the whole buffer. Set pad_done to nonzero if we find
* (minus one, for the 00 byte) */ * the 0x00 byte and remember the padding length in pad_count.
for( i = 0; i < ilen - 3; i++ ) * If there's a non-0xff byte in the padding, the padding is bad. */
for( i = 2; i < ilen; i++ )
{ {
pad_done |= ( p[i] != 0xFF ); pad_done |= if_int( buf[i], 0, 1 );
pad_count += ( pad_done == 0 ); pad_count += if_int( pad_done, 0, 1 );
bad |= if_int( pad_done, 0, buf[i] ^ 0xFF );
} }
p += pad_count;
bad |= *p++; /* Must be zero */
} }
bad |= ( pad_count < 8 ); /* If pad_done is still zero, there's no data, only unfinished padding. */
bad |= if_int( pad_done, 0, 1 );
if( bad ) /* There must be at least 8 bytes of padding. */
{ bad |= size_greater_than( 8, pad_count );
ret = MBEDTLS_ERR_RSA_INVALID_PADDING;
goto cleanup;
}
if( ilen - ( p - buf ) > output_max_len ) /* If the padding is valid, set plaintext_size to the number of
{ * remaining bytes after stripping the padding. If the padding
ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; * is invalid, avoid leaking this fact through the size of the
goto cleanup; * output: use the maximum message size that fits in the output
} * buffer. Do it without branches to avoid leaking the padding
* validity through timing. RSA keys are small enough that all the
* size_t values involved fit in unsigned int. */
plaintext_size = if_int( bad,
(unsigned) plaintext_max_size,
(unsigned) ( ilen - pad_count - 3 ) );
*olen = ilen - (p - buf); /* Set output_too_large to 0 if the plaintext fits in the output
memcpy( output, p, *olen ); * buffer and to 1 otherwise. */
ret = 0; output_too_large = size_greater_than( plaintext_size,
plaintext_max_size );
/* Set ret without branches to avoid timing attacks. Return:
* - INVALID_PADDING if the padding is bad (bad != 0).
* - OUTPUT_TOO_LARGE if the padding is good but the decrypted
* plaintext does not fit in the output buffer.
* - 0 if the padding is correct. */
ret = - (int) if_int( bad, - MBEDTLS_ERR_RSA_INVALID_PADDING,
if_int( output_too_large, - MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE,
0 ) );
/* If the padding is bad or the plaintext is too large, zero the
* data that we're about to copy to the output buffer.
* We need to copy the same amount of data
* from the same buffer whether the padding is good or not to
* avoid leaking the padding validity through overall timing or
* through memory or cache access patterns. */
bad = all_or_nothing_int( bad | output_too_large );
for( i = 11; i < ilen; i++ )
buf[i] &= ~bad;
/* If the plaintext is too large, truncate it to the buffer size.
* Copy anyway to avoid revealing the length through timing, because
* revealing the length is as bad as revealing the padding validity
* for a Bleichenbacher attack. */
plaintext_size = if_int( output_too_large,
(unsigned) plaintext_max_size,
(unsigned) plaintext_size );
/* Move the plaintext to the leftmost position where it can start in
* the working buffer, i.e. make it start plaintext_max_size from
* the end of the buffer. Do this with a memory access trace that
* does not depend on the plaintext size. After this move, the
* starting location of the plaintext is no longer sensitive
* information. */
mem_move_to_left( buf + ilen - plaintext_max_size,
plaintext_max_size,
plaintext_max_size - plaintext_size );
/* Finally copy the decrypted plaintext plus trailing zeros
* into the output buffer. */
memcpy( output, buf + ilen - plaintext_max_size, plaintext_max_size );
/* Report the amount of data we copied to the output buffer. In case
* of errors (bad padding or output too large), the value of *olen
* when this function returns is not specified. Making it equivalent
* to the good case limits the risks of leaking the padding validity. */
*olen = plaintext_size;
cleanup: cleanup:
mbedtls_platform_zeroize( buf, sizeof( buf ) ); mbedtls_platform_zeroize( buf, sizeof( buf ) );

View file

@ -33,3 +33,93 @@ pkcs1_rsassa_v15_sign:1024:16:"d17f655bf27c8b16d35462c905cc04a26f37e2a67fa9c0ce0
RSASSA-V15 Verification Test Vector Int RSASSA-V15 Verification Test Vector Int
pkcs1_rsassa_v15_verify:1024:16:"a2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e577c2eeaffa20d883a76e65e394c69d4b3c05a1e8fadda27edb2a42bc000fe888b9b32c22d15add0cd76b3e7936e19955b220dd17d4ea904b1ec102b2e4de7751222aa99151024c7cb41cc5ea21d00eeb41f7c800834d2c6e06bce3bce7ea9a5":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"859eef2fd78aca00308bdc471193bf55bf9d78db8f8a672b484634f3c9c26e6478ae10260fe0dd8c082e53a5293af2173cd50c6d5d354febf78b26021c25c02712e78cd4694c9f469777e451e7f8e9e04cd3739c6bbfedae487fb55644e9ca74ff77a53cb729802f6ed4a5ffa8ba159890fc":"e3b5d5d002c1bce50c2b65ef88a188d83bce7e61":"2154f928615e5101fcdeb57bc08fc2f35c3d5996403861ae3efb1d0712f8bb05cc21f7f5f11f62e5b6ea9f0f2b62180e5cbe7ba535032d6ac8068fff7f362f73d2c3bf5eca6062a1723d7cfd5abb6dcf7e405f2dc560ffe6fc37d38bee4dc9e24fe2bece3e3b4a3f032701d3f0947b42930083dd4ad241b3309b514595482d42":0 pkcs1_rsassa_v15_verify:1024:16:"a2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e577c2eeaffa20d883a76e65e394c69d4b3c05a1e8fadda27edb2a42bc000fe888b9b32c22d15add0cd76b3e7936e19955b220dd17d4ea904b1ec102b2e4de7751222aa99151024c7cb41cc5ea21d00eeb41f7c800834d2c6e06bce3bce7ea9a5":16:"010001":MBEDTLS_MD_SHA1:MBEDTLS_MD_SHA1:"859eef2fd78aca00308bdc471193bf55bf9d78db8f8a672b484634f3c9c26e6478ae10260fe0dd8c082e53a5293af2173cd50c6d5d354febf78b26021c25c02712e78cd4694c9f469777e451e7f8e9e04cd3739c6bbfedae487fb55644e9ca74ff77a53cb729802f6ed4a5ffa8ba159890fc":"e3b5d5d002c1bce50c2b65ef88a188d83bce7e61":"2154f928615e5101fcdeb57bc08fc2f35c3d5996403861ae3efb1d0712f8bb05cc21f7f5f11f62e5b6ea9f0f2b62180e5cbe7ba535032d6ac8068fff7f362f73d2c3bf5eca6062a1723d7cfd5abb6dcf7e405f2dc560ffe6fc37d38bee4dc9e24fe2bece3e3b4a3f032701d3f0947b42930083dd4ad241b3309b514595482d42":0
RSAES-V15 decoding: good, payload=max, tight output buffer
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0002505152535455565700":117:117:0
RSAES-V15 decoding: good, payload=max, larger output buffer
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0002505152535455565700":117:128:0
RSAES-V15 decoding: good, payload=max-1, tight output buffer
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"000250515253545556575800":116:116:0
RSAES-V15 decoding: good, payload=max-1, larger output buffer
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"000250515253545556575800":116:117:0
RSAES-V15 decoding: good, payload=1
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"00025050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505000":1:1:0
RSAES-V15 decoding: good, empty payload
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0002505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505000":0:0:0
RSAES-V15 decoding: payload=max, output too large
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0002505152535455565700":117:116:MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE
RSAES-V15 decoding: payload=max-1, output too large
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"000250515253545556575800":116:115:MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE
RSAES-V15 decoding: bad first byte
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0102505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
RSAES-V15 decoding: bad second byte (0 instead of 2)
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0000505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
RSAES-V15 decoding: bad second byte (1 instead of 2)
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0001505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
RSAES-V15 decoding: padding too short (0)
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"000200":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
RSAES-V15 decoding: padding too short (7)
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0002505050505050500000ffffffffffffffffff00":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
RSAES-V15 decoding: unfinished padding
pkcs1_v15_decode:MBEDTLS_RSA_PRIVATE:"0002505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: good, payload=max, tight output buffer
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001ffffffffffffffff00":117:117:0
EMSA-V15 decoding: good, payload=max, larger output buffer
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001ffffffffffffffff00":117:128:0
EMSA-V15 decoding: good, payload=max-1, tight output buffer
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001ffffffffffffffffff00":116:116:0
EMSA-V15 decoding: good, payload=max-1, larger output buffer
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001ffffffffffffffffff00":116:117:0
EMSA-V15 decoding: good, payload=1
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00":1:1:0
EMSA-V15 decoding: good, empty payload
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00":0:0:0
EMSA-V15 decoding: bad first byte
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0101ffffffffffffffff00":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: bad second byte (0 instead of 1)
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0000ffffffffffffffff00":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: bad second byte (2 instead of 1)
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0002ffffffffffffffff00":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: padding too short (0)
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"000100":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: padding too short (7)
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001ffffffffffffff0000ffffffffffffffff00":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: invalid padding at first byte
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001fffffffffffffffe00":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: invalid padding at last byte
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001feffffffffffffff00":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: unfinished padding
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: unfinished padding with invalid first byte
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING
EMSA-V15 decoding: unfinished padding with invalid last byte
pkcs1_v15_decode:MBEDTLS_RSA_PUBLIC:"0001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe":0:42:MBEDTLS_ERR_RSA_INVALID_PADDING

View file

@ -93,6 +93,154 @@ exit:
} }
/* END_CASE */ /* END_CASE */
/* BEGIN_CASE */
void pkcs1_v15_decode( int mode,
data_t *input,
int expected_plaintext_length_arg,
int output_size_arg,
int expected_result )
{
size_t expected_plaintext_length = expected_plaintext_length_arg;
size_t output_size = output_size_arg;
rnd_pseudo_info rnd_info;
mbedtls_mpi Nmpi, Empi, Pmpi, Qmpi;
mbedtls_rsa_context ctx;
static unsigned char N[128] = {
0xc4, 0x79, 0x4c, 0x6d, 0xb2, 0xe9, 0xdf, 0xc5,
0xe5, 0xd7, 0x55, 0x4b, 0xfb, 0x6c, 0x2e, 0xec,
0x84, 0xd0, 0x88, 0x12, 0xaf, 0xbf, 0xb4, 0xf5,
0x47, 0x3c, 0x7e, 0x92, 0x4c, 0x58, 0xc8, 0x73,
0xfe, 0x8f, 0x2b, 0x8f, 0x8e, 0xc8, 0x5c, 0xf5,
0x05, 0xeb, 0xfb, 0x0d, 0x7b, 0x2a, 0x93, 0xde,
0x15, 0x0d, 0xc8, 0x13, 0xcf, 0xd2, 0x6f, 0x0d,
0x9d, 0xad, 0x30, 0xe5, 0x70, 0x20, 0x92, 0x9e,
0xb3, 0x6b, 0xba, 0x5c, 0x50, 0x0f, 0xc3, 0xb2,
0x7e, 0x64, 0x07, 0x94, 0x7e, 0xc9, 0x4e, 0xc1,
0x65, 0x04, 0xaf, 0xb3, 0x9f, 0xde, 0xa8, 0x46,
0xfa, 0x6c, 0xf3, 0x03, 0xaf, 0x1c, 0x1b, 0xec,
0x75, 0x44, 0x66, 0x77, 0xc9, 0xde, 0x51, 0x33,
0x64, 0x27, 0xb0, 0xd4, 0x8d, 0x31, 0x6a, 0x11,
0x27, 0x3c, 0x99, 0xd4, 0x22, 0xc0, 0x9d, 0x12,
0x01, 0xc7, 0x4a, 0x73, 0xac, 0xbf, 0xc2, 0xbb
};
static unsigned char E[1] = { 0x03 };
static unsigned char P[64] = {
0xe5, 0x53, 0x1f, 0x88, 0x51, 0xee, 0x59, 0xf8,
0xc1, 0xe4, 0xcc, 0x5b, 0xb3, 0x75, 0x8d, 0xc8,
0xe8, 0x95, 0x2f, 0xd0, 0xef, 0x37, 0xb4, 0xcd,
0xd3, 0x9e, 0x48, 0x8b, 0x81, 0x58, 0x60, 0xb9,
0x27, 0x1d, 0xb6, 0x28, 0x92, 0x64, 0xa3, 0xa5,
0x64, 0xbd, 0xcc, 0x53, 0x68, 0xdd, 0x3e, 0x55,
0xea, 0x9d, 0x5e, 0xcd, 0x1f, 0x96, 0x87, 0xf1,
0x29, 0x75, 0x92, 0x70, 0x8f, 0x28, 0xfb, 0x2b
};
static unsigned char Q[64] = {
0xdb, 0x53, 0xef, 0x74, 0x61, 0xb4, 0x20, 0x3b,
0x3b, 0x87, 0x76, 0x75, 0x81, 0x56, 0x11, 0x03,
0x59, 0x31, 0xe3, 0x38, 0x4b, 0x8c, 0x7a, 0x9c,
0x05, 0xd6, 0x7f, 0x1e, 0x5e, 0x60, 0xf0, 0x4e,
0x0b, 0xdc, 0x34, 0x54, 0x1c, 0x2e, 0x90, 0x83,
0x14, 0xef, 0xc0, 0x96, 0x5c, 0x30, 0x10, 0xcc,
0xc1, 0xba, 0xa0, 0x54, 0x3f, 0x96, 0x24, 0xca,
0xa3, 0xfb, 0x55, 0xbc, 0x71, 0x29, 0x4e, 0xb1
};
unsigned char original[128];
unsigned char intermediate[128];
static unsigned char default_content[128] = {
/* A randomly generated pattern. */
0x4c, 0x27, 0x54, 0xa0, 0xce, 0x0d, 0x09, 0x4a,
0x1c, 0x38, 0x8e, 0x2d, 0xa3, 0xc4, 0xe0, 0x19,
0x4c, 0x99, 0xb2, 0xbf, 0xe6, 0x65, 0x7e, 0x58,
0xd7, 0xb6, 0x8a, 0x05, 0x2f, 0xa5, 0xec, 0xa4,
0x35, 0xad, 0x10, 0x36, 0xff, 0x0d, 0x08, 0x50,
0x74, 0x47, 0xc9, 0x9c, 0x4a, 0xe7, 0xfd, 0xfa,
0x83, 0x5f, 0x14, 0x5a, 0x1e, 0xe7, 0x35, 0x08,
0xad, 0xf7, 0x0d, 0x86, 0xdf, 0xb8, 0xd4, 0xcf,
0x32, 0xb9, 0x5c, 0xbe, 0xa3, 0xd2, 0x89, 0x70,
0x7b, 0xc6, 0x48, 0x7e, 0x58, 0x4d, 0xf3, 0xef,
0x34, 0xb7, 0x57, 0x54, 0x79, 0xc5, 0x8e, 0x0a,
0xa3, 0xbf, 0x6d, 0x42, 0x83, 0x25, 0x13, 0xa2,
0x95, 0xc0, 0x0d, 0x32, 0xec, 0x77, 0x91, 0x2b,
0x68, 0xb6, 0x8c, 0x79, 0x15, 0xfb, 0x94, 0xde,
0xb9, 0x2b, 0x94, 0xb3, 0x28, 0x23, 0x86, 0x3d,
0x37, 0x00, 0xe6, 0xf1, 0x1f, 0x4e, 0xd4, 0x42
};
unsigned char final[128];
size_t output_length = 0x7EA0;
memset( &rnd_info, 0, sizeof( rnd_pseudo_info ) );
mbedtls_mpi_init( &Nmpi ); mbedtls_mpi_init( &Empi );
mbedtls_mpi_init( &Pmpi ); mbedtls_mpi_init( &Qmpi );
mbedtls_rsa_init( &ctx, MBEDTLS_RSA_PKCS_V15, 0 );
TEST_ASSERT( mbedtls_mpi_read_binary( &Nmpi, N, sizeof( N ) ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_binary( &Empi, E, sizeof( E ) ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_binary( &Pmpi, P, sizeof( P ) ) == 0 );
TEST_ASSERT( mbedtls_mpi_read_binary( &Qmpi, Q, sizeof( Q ) ) == 0 );
TEST_ASSERT( mbedtls_rsa_import( &ctx, &Nmpi, &Pmpi, &Qmpi,
NULL, &Empi ) == 0 );
TEST_ASSERT( mbedtls_rsa_complete( &ctx ) == 0 );
TEST_ASSERT( input->len <= sizeof( N ) );
memcpy( original, input->x, input->len );
memset( original + input->len, 'd', sizeof( original ) - input->len );
if( mode == MBEDTLS_RSA_PRIVATE )
TEST_ASSERT( mbedtls_rsa_public( &ctx, original, intermediate ) == 0 );
else
TEST_ASSERT( mbedtls_rsa_private( &ctx, &rnd_pseudo_rand, &rnd_info,
original, intermediate ) == 0 );
memcpy( final, default_content, sizeof( final ) );
TEST_ASSERT( mbedtls_rsa_pkcs1_decrypt( &ctx,
&rnd_pseudo_rand, &rnd_info,
mode,
&output_length,
intermediate,
final,
output_size ) == expected_result );
if( expected_result == 0 )
{
TEST_ASSERT( output_length == expected_plaintext_length );
TEST_ASSERT( memcmp( original + sizeof( N ) - output_length,
final,
output_length ) == 0 );
}
else if( expected_result == MBEDTLS_ERR_RSA_INVALID_PADDING ||
expected_result == MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE )
{
size_t max_payload_length =
output_size > sizeof( N ) - 11 ? sizeof( N ) - 11 : output_size;
size_t i;
size_t count = 0;
#if !defined(MBEDTLS_RSA_ALT)
/* Check that the output in invalid cases is what the default
* implementation currently does. Alternative implementations
* may produce different output, so we only perform these precise
* checks when using the default implementation. */
TEST_ASSERT( output_length == max_payload_length );
for( i = 0; i < max_payload_length; i++ )
TEST_ASSERT( final[i] == 0 );
#endif
/* Even in alternative implementations, the outputs must have
* changed, otherwise it indicates at least a timing vulnerability
* because no write to the outputs is performed in the bad case. */
TEST_ASSERT( output_length != 0x7EA0 );
for( i = 0; i < max_payload_length; i++ )
count += ( final[i] == default_content[i] );
/* If more than 16 bytes are unchanged in final, that's evidence
* that final wasn't overwritten. */
TEST_ASSERT( count < 16 );
}
exit:
mbedtls_mpi_free( &Nmpi ); mbedtls_mpi_free( &Empi );
mbedtls_mpi_free( &Pmpi ); mbedtls_mpi_free( &Qmpi );
mbedtls_rsa_free( &ctx );
}
/* END_CASE */
/* BEGIN_CASE */ /* BEGIN_CASE */
void pkcs1_rsassa_v15_sign( int mod, int radix_P, char * input_P, int radix_Q, void pkcs1_rsassa_v15_sign( int mod, int radix_P, char * input_P, int radix_Q,
char * input_Q, int radix_N, char * input_N, char * input_Q, int radix_N, char * input_N,