mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-07-29 11:41:15 +03:00
Merge development commit 8e76332
into development-psa
Additional changes to temporarily enable running tests: ssl_srv.c and test_suite_ecdh use mbedtls_ecp_group_load instead of mbedtls_ecdh_setup test_suite_ctr_drbg uses mbedtls_ctr_drbg_update instead of mbedtls_ctr_drbg_update_ret
This commit is contained in:
451
library/rsa.c
451
library/rsa.c
@ -71,6 +71,12 @@
|
||||
|
||||
#if !defined(MBEDTLS_RSA_ALT)
|
||||
|
||||
/* Parameter validation macros */
|
||||
#define RSA_VALIDATE_RET( cond ) \
|
||||
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_RSA_BAD_INPUT_DATA )
|
||||
#define RSA_VALIDATE( cond ) \
|
||||
MBEDTLS_INTERNAL_VALIDATE( cond )
|
||||
|
||||
#if defined(MBEDTLS_PKCS1_V15)
|
||||
/* constant-time buffer comparison */
|
||||
static inline int mbedtls_safer_memcmp( const void *a, const void *b, size_t n )
|
||||
@ -93,6 +99,7 @@ int mbedtls_rsa_import( mbedtls_rsa_context *ctx,
|
||||
const mbedtls_mpi *D, const mbedtls_mpi *E )
|
||||
{
|
||||
int ret;
|
||||
RSA_VALIDATE_RET( ctx != NULL );
|
||||
|
||||
if( ( N != NULL && ( ret = mbedtls_mpi_copy( &ctx->N, N ) ) != 0 ) ||
|
||||
( P != NULL && ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ) ||
|
||||
@ -117,6 +124,7 @@ int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx,
|
||||
unsigned char const *E, size_t E_len )
|
||||
{
|
||||
int ret = 0;
|
||||
RSA_VALIDATE_RET( ctx != NULL );
|
||||
|
||||
if( N != NULL )
|
||||
{
|
||||
@ -240,12 +248,16 @@ static int rsa_check_context( mbedtls_rsa_context const *ctx, int is_priv,
|
||||
int mbedtls_rsa_complete( mbedtls_rsa_context *ctx )
|
||||
{
|
||||
int ret = 0;
|
||||
int have_N, have_P, have_Q, have_D, have_E;
|
||||
int n_missing, pq_missing, d_missing, is_pub, is_priv;
|
||||
|
||||
const int have_N = ( mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 );
|
||||
const int have_P = ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 );
|
||||
const int have_Q = ( mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 );
|
||||
const int have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 );
|
||||
const int have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 );
|
||||
RSA_VALIDATE_RET( ctx != NULL );
|
||||
|
||||
have_N = ( mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 );
|
||||
have_P = ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 );
|
||||
have_Q = ( mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 );
|
||||
have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 );
|
||||
have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 );
|
||||
|
||||
/*
|
||||
* Check whether provided parameters are enough
|
||||
@ -257,13 +269,13 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx )
|
||||
*
|
||||
*/
|
||||
|
||||
const int n_missing = have_P && have_Q && have_D && have_E;
|
||||
const int pq_missing = have_N && !have_P && !have_Q && have_D && have_E;
|
||||
const int d_missing = have_P && have_Q && !have_D && have_E;
|
||||
const int is_pub = have_N && !have_P && !have_Q && !have_D && have_E;
|
||||
n_missing = have_P && have_Q && have_D && have_E;
|
||||
pq_missing = have_N && !have_P && !have_Q && have_D && have_E;
|
||||
d_missing = have_P && have_Q && !have_D && have_E;
|
||||
is_pub = have_N && !have_P && !have_Q && !have_D && have_E;
|
||||
|
||||
/* These three alternatives are mutually exclusive */
|
||||
const int is_priv = n_missing || pq_missing || d_missing;
|
||||
is_priv = n_missing || pq_missing || d_missing;
|
||||
|
||||
if( !is_priv && !is_pub )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
@ -336,9 +348,11 @@ int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx,
|
||||
unsigned char *E, size_t E_len )
|
||||
{
|
||||
int ret = 0;
|
||||
int is_priv;
|
||||
RSA_VALIDATE_RET( ctx != NULL );
|
||||
|
||||
/* Check if key is private or public */
|
||||
const int is_priv =
|
||||
is_priv =
|
||||
mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 &&
|
||||
mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 &&
|
||||
mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 &&
|
||||
@ -379,9 +393,11 @@ int mbedtls_rsa_export( const mbedtls_rsa_context *ctx,
|
||||
mbedtls_mpi *D, mbedtls_mpi *E )
|
||||
{
|
||||
int ret;
|
||||
int is_priv;
|
||||
RSA_VALIDATE_RET( ctx != NULL );
|
||||
|
||||
/* Check if key is private or public */
|
||||
int is_priv =
|
||||
is_priv =
|
||||
mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 &&
|
||||
mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 &&
|
||||
mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 &&
|
||||
@ -421,9 +437,11 @@ int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx,
|
||||
mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP )
|
||||
{
|
||||
int ret;
|
||||
int is_priv;
|
||||
RSA_VALIDATE_RET( ctx != NULL );
|
||||
|
||||
/* Check if key is private or public */
|
||||
int is_priv =
|
||||
is_priv =
|
||||
mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 &&
|
||||
mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 &&
|
||||
mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 &&
|
||||
@ -459,6 +477,10 @@ void mbedtls_rsa_init( mbedtls_rsa_context *ctx,
|
||||
int padding,
|
||||
int hash_id )
|
||||
{
|
||||
RSA_VALIDATE( ctx != NULL );
|
||||
RSA_VALIDATE( padding == MBEDTLS_RSA_PKCS_V15 ||
|
||||
padding == MBEDTLS_RSA_PKCS_V21 );
|
||||
|
||||
memset( ctx, 0, sizeof( mbedtls_rsa_context ) );
|
||||
|
||||
mbedtls_rsa_set_padding( ctx, padding, hash_id );
|
||||
@ -471,8 +493,13 @@ void mbedtls_rsa_init( mbedtls_rsa_context *ctx,
|
||||
/*
|
||||
* Set padding for an existing RSA context
|
||||
*/
|
||||
void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, int hash_id )
|
||||
void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding,
|
||||
int hash_id )
|
||||
{
|
||||
RSA_VALIDATE( ctx != NULL );
|
||||
RSA_VALIDATE( padding == MBEDTLS_RSA_PKCS_V15 ||
|
||||
padding == MBEDTLS_RSA_PKCS_V21 );
|
||||
|
||||
ctx->padding = padding;
|
||||
ctx->hash_id = hash_id;
|
||||
}
|
||||
@ -503,11 +530,10 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
|
||||
int ret;
|
||||
mbedtls_mpi H, G, L;
|
||||
int prime_quality = 0;
|
||||
RSA_VALIDATE_RET( ctx != NULL );
|
||||
RSA_VALIDATE_RET( f_rng != NULL );
|
||||
|
||||
if( f_rng == NULL || nbits < 128 || exponent < 3 )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
|
||||
if( nbits % 2 )
|
||||
if( nbits < 128 || exponent < 3 || nbits % 2 != 0 )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
|
||||
/*
|
||||
@ -612,6 +638,8 @@ cleanup:
|
||||
*/
|
||||
int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx )
|
||||
{
|
||||
RSA_VALIDATE_RET( ctx != NULL );
|
||||
|
||||
if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) != 0 )
|
||||
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
|
||||
|
||||
@ -635,6 +663,8 @@ int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx )
|
||||
*/
|
||||
int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx )
|
||||
{
|
||||
RSA_VALIDATE_RET( ctx != NULL );
|
||||
|
||||
if( mbedtls_rsa_check_pubkey( ctx ) != 0 ||
|
||||
rsa_check_context( ctx, 1 /* private */, 1 /* blinding */ ) != 0 )
|
||||
{
|
||||
@ -664,6 +694,9 @@ int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx )
|
||||
int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub,
|
||||
const mbedtls_rsa_context *prv )
|
||||
{
|
||||
RSA_VALIDATE_RET( pub != NULL );
|
||||
RSA_VALIDATE_RET( prv != NULL );
|
||||
|
||||
if( mbedtls_rsa_check_pubkey( pub ) != 0 ||
|
||||
mbedtls_rsa_check_privkey( prv ) != 0 )
|
||||
{
|
||||
@ -689,6 +722,9 @@ int mbedtls_rsa_public( mbedtls_rsa_context *ctx,
|
||||
int ret;
|
||||
size_t olen;
|
||||
mbedtls_mpi T;
|
||||
RSA_VALIDATE_RET( ctx != NULL );
|
||||
RSA_VALIDATE_RET( input != NULL );
|
||||
RSA_VALIDATE_RET( output != NULL );
|
||||
|
||||
if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
@ -831,6 +867,10 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx,
|
||||
* checked result; should be the same in the end. */
|
||||
mbedtls_mpi I, C;
|
||||
|
||||
RSA_VALIDATE_RET( ctx != NULL );
|
||||
RSA_VALIDATE_RET( input != NULL );
|
||||
RSA_VALIDATE_RET( output != NULL );
|
||||
|
||||
if( rsa_check_context( ctx, 1 /* private key checks */,
|
||||
f_rng != NULL /* blinding y/n */ ) != 0 )
|
||||
{
|
||||
@ -1091,6 +1131,13 @@ int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx,
|
||||
const mbedtls_md_info_t *md_info;
|
||||
mbedtls_md_context_t md_ctx;
|
||||
|
||||
RSA_VALIDATE_RET( ctx != NULL );
|
||||
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
|
||||
mode == MBEDTLS_RSA_PUBLIC );
|
||||
RSA_VALIDATE_RET( output != NULL );
|
||||
RSA_VALIDATE_RET( input != NULL );
|
||||
RSA_VALIDATE_RET( label_len == 0 || label != NULL );
|
||||
|
||||
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
|
||||
@ -1167,11 +1214,13 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx,
|
||||
int ret;
|
||||
unsigned char *p = output;
|
||||
|
||||
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
RSA_VALIDATE_RET( ctx != NULL );
|
||||
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
|
||||
mode == MBEDTLS_RSA_PUBLIC );
|
||||
RSA_VALIDATE_RET( output != NULL );
|
||||
RSA_VALIDATE_RET( input != NULL );
|
||||
|
||||
// We don't check p_rng because it won't be dereferenced here
|
||||
if( f_rng == NULL || input == NULL || output == NULL )
|
||||
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
|
||||
olen = ctx->len;
|
||||
@ -1185,6 +1234,9 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx,
|
||||
*p++ = 0;
|
||||
if( mode == MBEDTLS_RSA_PUBLIC )
|
||||
{
|
||||
if( f_rng == NULL )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
|
||||
*p++ = MBEDTLS_RSA_CRYPT;
|
||||
|
||||
while( nb_pad-- > 0 )
|
||||
@ -1229,6 +1281,12 @@ int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx,
|
||||
const unsigned char *input,
|
||||
unsigned char *output )
|
||||
{
|
||||
RSA_VALIDATE_RET( ctx != NULL );
|
||||
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
|
||||
mode == MBEDTLS_RSA_PUBLIC );
|
||||
RSA_VALIDATE_RET( output != NULL );
|
||||
RSA_VALIDATE_RET( input != NULL );
|
||||
|
||||
switch( ctx->padding )
|
||||
{
|
||||
#if defined(MBEDTLS_PKCS1_V15)
|
||||
@ -1271,6 +1329,14 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx,
|
||||
const mbedtls_md_info_t *md_info;
|
||||
mbedtls_md_context_t md_ctx;
|
||||
|
||||
RSA_VALIDATE_RET( ctx != NULL );
|
||||
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
|
||||
mode == MBEDTLS_RSA_PUBLIC );
|
||||
RSA_VALIDATE_RET( output_max_len == 0 || output != NULL );
|
||||
RSA_VALIDATE_RET( label_len == 0 || label != NULL );
|
||||
RSA_VALIDATE_RET( input != NULL );
|
||||
RSA_VALIDATE_RET( olen != NULL );
|
||||
|
||||
/*
|
||||
* Parameters sanity checks
|
||||
*/
|
||||
@ -1387,6 +1453,97 @@ cleanup:
|
||||
#endif /* MBEDTLS_PKCS1_V21 */
|
||||
|
||||
#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
|
||||
*/
|
||||
@ -1396,18 +1553,42 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx,
|
||||
int mode, size_t *olen,
|
||||
const unsigned char *input,
|
||||
unsigned char *output,
|
||||
size_t output_max_len)
|
||||
size_t output_max_len )
|
||||
{
|
||||
int ret;
|
||||
size_t ilen, pad_count = 0, i;
|
||||
unsigned char *p, bad, pad_done = 0;
|
||||
size_t ilen, i, plaintext_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;
|
||||
|
||||
RSA_VALIDATE_RET( ctx != NULL );
|
||||
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
|
||||
mode == MBEDTLS_RSA_PUBLIC );
|
||||
RSA_VALIDATE_RET( output_max_len == 0 || output != NULL );
|
||||
RSA_VALIDATE_RET( input != NULL );
|
||||
RSA_VALIDATE_RET( olen != NULL );
|
||||
|
||||
ilen = ctx->len;
|
||||
plaintext_max_size = ( output_max_len > ilen - 11 ?
|
||||
ilen - 11 :
|
||||
output_max_len );
|
||||
|
||||
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
|
||||
ilen = ctx->len;
|
||||
|
||||
if( ilen < 16 || ilen > sizeof( buf ) )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
|
||||
@ -1418,63 +1599,109 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx,
|
||||
if( ret != 0 )
|
||||
goto cleanup;
|
||||
|
||||
p = buf;
|
||||
bad = 0;
|
||||
/* Check and get padding length in constant time and constant
|
||||
* 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 )
|
||||
{
|
||||
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
|
||||
* (minus one, for the 00 byte) */
|
||||
for( i = 0; i < ilen - 3; i++ )
|
||||
/* Read the whole buffer. Set pad_done to nonzero if we find
|
||||
* the 0x00 byte and remember the padding length in pad_count. */
|
||||
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;
|
||||
}
|
||||
|
||||
p += pad_count;
|
||||
bad |= *p++; /* Must be zero */
|
||||
}
|
||||
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
|
||||
* (minus one, for the 00 byte) */
|
||||
for( i = 0; i < ilen - 3; i++ )
|
||||
/* Read the whole buffer. Set pad_done to nonzero if we find
|
||||
* the 0x00 byte and remember the padding length in pad_count.
|
||||
* 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_count += ( pad_done == 0 );
|
||||
pad_done |= if_int( buf[i], 0, 1 );
|
||||
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 )
|
||||
{
|
||||
ret = MBEDTLS_ERR_RSA_INVALID_PADDING;
|
||||
goto cleanup;
|
||||
}
|
||||
/* There must be at least 8 bytes of padding. */
|
||||
bad |= size_greater_than( 8, pad_count );
|
||||
|
||||
if( ilen - ( p - buf ) > output_max_len )
|
||||
{
|
||||
ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;
|
||||
goto cleanup;
|
||||
}
|
||||
/* If the padding is valid, set plaintext_size to the number of
|
||||
* remaining bytes after stripping the padding. If the padding
|
||||
* is invalid, avoid leaking this fact through the size of the
|
||||
* 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);
|
||||
memcpy( output, p, *olen );
|
||||
ret = 0;
|
||||
/* Set output_too_large to 0 if the plaintext fits in the output
|
||||
* buffer and to 1 otherwise. */
|
||||
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:
|
||||
mbedtls_platform_zeroize( buf, sizeof( buf ) );
|
||||
@ -1494,6 +1721,13 @@ int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx,
|
||||
unsigned char *output,
|
||||
size_t output_max_len)
|
||||
{
|
||||
RSA_VALIDATE_RET( ctx != NULL );
|
||||
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
|
||||
mode == MBEDTLS_RSA_PUBLIC );
|
||||
RSA_VALIDATE_RET( output_max_len == 0 || output != NULL );
|
||||
RSA_VALIDATE_RET( input != NULL );
|
||||
RSA_VALIDATE_RET( olen != NULL );
|
||||
|
||||
switch( ctx->padding )
|
||||
{
|
||||
#if defined(MBEDTLS_PKCS1_V15)
|
||||
@ -1535,6 +1769,13 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
|
||||
size_t msb;
|
||||
const mbedtls_md_info_t *md_info;
|
||||
mbedtls_md_context_t md_ctx;
|
||||
RSA_VALIDATE_RET( ctx != NULL );
|
||||
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
|
||||
mode == MBEDTLS_RSA_PUBLIC );
|
||||
RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE &&
|
||||
hashlen == 0 ) ||
|
||||
hash != NULL );
|
||||
RSA_VALIDATE_RET( sig != NULL );
|
||||
|
||||
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
@ -1782,6 +2023,14 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx,
|
||||
int ret;
|
||||
unsigned char *sig_try = NULL, *verif = NULL;
|
||||
|
||||
RSA_VALIDATE_RET( ctx != NULL );
|
||||
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
|
||||
mode == MBEDTLS_RSA_PUBLIC );
|
||||
RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE &&
|
||||
hashlen == 0 ) ||
|
||||
hash != NULL );
|
||||
RSA_VALIDATE_RET( sig != NULL );
|
||||
|
||||
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
|
||||
@ -1851,6 +2100,14 @@ int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx,
|
||||
const unsigned char *hash,
|
||||
unsigned char *sig )
|
||||
{
|
||||
RSA_VALIDATE_RET( ctx != NULL );
|
||||
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
|
||||
mode == MBEDTLS_RSA_PUBLIC );
|
||||
RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE &&
|
||||
hashlen == 0 ) ||
|
||||
hash != NULL );
|
||||
RSA_VALIDATE_RET( sig != NULL );
|
||||
|
||||
switch( ctx->padding )
|
||||
{
|
||||
#if defined(MBEDTLS_PKCS1_V15)
|
||||
@ -1897,6 +2154,14 @@ int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx,
|
||||
mbedtls_md_context_t md_ctx;
|
||||
unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
|
||||
|
||||
RSA_VALIDATE_RET( ctx != NULL );
|
||||
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
|
||||
mode == MBEDTLS_RSA_PUBLIC );
|
||||
RSA_VALIDATE_RET( sig != NULL );
|
||||
RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE &&
|
||||
hashlen == 0 ) ||
|
||||
hash != NULL );
|
||||
|
||||
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
|
||||
@ -2025,7 +2290,16 @@ int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx,
|
||||
const unsigned char *hash,
|
||||
const unsigned char *sig )
|
||||
{
|
||||
mbedtls_md_type_t mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE )
|
||||
mbedtls_md_type_t mgf1_hash_id;
|
||||
RSA_VALIDATE_RET( ctx != NULL );
|
||||
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
|
||||
mode == MBEDTLS_RSA_PUBLIC );
|
||||
RSA_VALIDATE_RET( sig != NULL );
|
||||
RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE &&
|
||||
hashlen == 0 ) ||
|
||||
hash != NULL );
|
||||
|
||||
mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE )
|
||||
? (mbedtls_md_type_t) ctx->hash_id
|
||||
: md_alg;
|
||||
|
||||
@ -2051,9 +2325,19 @@ int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx,
|
||||
const unsigned char *sig )
|
||||
{
|
||||
int ret = 0;
|
||||
const size_t sig_len = ctx->len;
|
||||
size_t sig_len;
|
||||
unsigned char *encoded = NULL, *encoded_expected = NULL;
|
||||
|
||||
RSA_VALIDATE_RET( ctx != NULL );
|
||||
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
|
||||
mode == MBEDTLS_RSA_PUBLIC );
|
||||
RSA_VALIDATE_RET( sig != NULL );
|
||||
RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE &&
|
||||
hashlen == 0 ) ||
|
||||
hash != NULL );
|
||||
|
||||
sig_len = ctx->len;
|
||||
|
||||
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
|
||||
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
|
||||
|
||||
@ -2123,6 +2407,14 @@ int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx,
|
||||
const unsigned char *hash,
|
||||
const unsigned char *sig )
|
||||
{
|
||||
RSA_VALIDATE_RET( ctx != NULL );
|
||||
RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE ||
|
||||
mode == MBEDTLS_RSA_PUBLIC );
|
||||
RSA_VALIDATE_RET( sig != NULL );
|
||||
RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE &&
|
||||
hashlen == 0 ) ||
|
||||
hash != NULL );
|
||||
|
||||
switch( ctx->padding )
|
||||
{
|
||||
#if defined(MBEDTLS_PKCS1_V15)
|
||||
@ -2148,6 +2440,8 @@ int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx,
|
||||
int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src )
|
||||
{
|
||||
int ret;
|
||||
RSA_VALIDATE_RET( dst != NULL );
|
||||
RSA_VALIDATE_RET( src != NULL );
|
||||
|
||||
dst->ver = src->ver;
|
||||
dst->len = src->len;
|
||||
@ -2187,14 +2481,23 @@ cleanup:
|
||||
*/
|
||||
void mbedtls_rsa_free( mbedtls_rsa_context *ctx )
|
||||
{
|
||||
mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->Vf );
|
||||
mbedtls_mpi_free( &ctx->RN ); mbedtls_mpi_free( &ctx->D );
|
||||
mbedtls_mpi_free( &ctx->Q ); mbedtls_mpi_free( &ctx->P );
|
||||
mbedtls_mpi_free( &ctx->E ); mbedtls_mpi_free( &ctx->N );
|
||||
if( ctx == NULL )
|
||||
return;
|
||||
|
||||
mbedtls_mpi_free( &ctx->Vi );
|
||||
mbedtls_mpi_free( &ctx->Vf );
|
||||
mbedtls_mpi_free( &ctx->RN );
|
||||
mbedtls_mpi_free( &ctx->D );
|
||||
mbedtls_mpi_free( &ctx->Q );
|
||||
mbedtls_mpi_free( &ctx->P );
|
||||
mbedtls_mpi_free( &ctx->E );
|
||||
mbedtls_mpi_free( &ctx->N );
|
||||
|
||||
#if !defined(MBEDTLS_RSA_NO_CRT)
|
||||
mbedtls_mpi_free( &ctx->RQ ); mbedtls_mpi_free( &ctx->RP );
|
||||
mbedtls_mpi_free( &ctx->QP ); mbedtls_mpi_free( &ctx->DQ );
|
||||
mbedtls_mpi_free( &ctx->RQ );
|
||||
mbedtls_mpi_free( &ctx->RP );
|
||||
mbedtls_mpi_free( &ctx->QP );
|
||||
mbedtls_mpi_free( &ctx->DQ );
|
||||
mbedtls_mpi_free( &ctx->DP );
|
||||
#endif /* MBEDTLS_RSA_NO_CRT */
|
||||
|
||||
|
Reference in New Issue
Block a user