Commit c7673b02 authored by Luiz Felipe Silva's avatar Luiz Felipe Silva
Browse files

Merge remote-tracking branch 'upstream/dev' into dev

parents ba9a938e 5c8af3c4
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
#include <string.h> #include <string.h>
#if !defined(MBEDTLS_ECJPAKE_ALT)
/* /*
* Convert a mbedtls_ecjpake_role to identifier string * Convert a mbedtls_ecjpake_role to identifier string
*/ */
...@@ -764,6 +766,7 @@ cleanup: ...@@ -764,6 +766,7 @@ cleanup:
#undef ID_MINE #undef ID_MINE
#undef ID_PEER #undef ID_PEER
#endif /* ! MBEDTLS_ECJPAKE_ALT */
#if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_SELF_TEST)
......
...@@ -1953,7 +1953,6 @@ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, ...@@ -1953,7 +1953,6 @@ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
{ {
/* SEC1 3.2.1: Generate d such that 1 <= n < N */ /* SEC1 3.2.1: Generate d such that 1 <= n < N */
int count = 0; int count = 0;
unsigned char rnd[MBEDTLS_ECP_MAX_BYTES];
/* /*
* Match the procedure given in RFC 6979 (deterministic ECDSA): * Match the procedure given in RFC 6979 (deterministic ECDSA):
...@@ -1964,8 +1963,7 @@ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, ...@@ -1964,8 +1963,7 @@ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp,
*/ */
do do
{ {
MBEDTLS_MPI_CHK( f_rng( p_rng, rnd, n_size ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( d, rnd, n_size ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) );
/* /*
......
...@@ -68,21 +68,26 @@ static void mbedtls_zeroize( void *v, size_t n ) { ...@@ -68,21 +68,26 @@ static void mbedtls_zeroize( void *v, size_t n ) {
void mbedtls_entropy_init( mbedtls_entropy_context *ctx ) void mbedtls_entropy_init( mbedtls_entropy_context *ctx )
{ {
memset( ctx, 0, sizeof(mbedtls_entropy_context) ); ctx->source_count = 0;
memset( ctx->source, 0, sizeof( ctx->source ) );
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_init( &ctx->mutex ); mbedtls_mutex_init( &ctx->mutex );
#endif #endif
ctx->accumulator_started = 0;
#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
mbedtls_sha512_starts( &ctx->accumulator, 0 ); mbedtls_sha512_init( &ctx->accumulator );
#else #else
mbedtls_sha256_starts( &ctx->accumulator, 0 ); mbedtls_sha256_init( &ctx->accumulator );
#endif #endif
#if defined(MBEDTLS_HAVEGE_C) #if defined(MBEDTLS_HAVEGE_C)
mbedtls_havege_init( &ctx->havege_data ); mbedtls_havege_init( &ctx->havege_data );
#endif #endif
/* Reminder: Update ENTROPY_HAVE_STRONG in the test files
* when adding more strong entropy sources here. */
#if defined(MBEDTLS_TEST_NULL_ENTROPY) #if defined(MBEDTLS_TEST_NULL_ENTROPY)
mbedtls_entropy_add_source( ctx, mbedtls_null_entropy_poll, NULL, mbedtls_entropy_add_source( ctx, mbedtls_null_entropy_poll, NULL,
1, MBEDTLS_ENTROPY_SOURCE_STRONG ); 1, MBEDTLS_ENTROPY_SOURCE_STRONG );
...@@ -113,6 +118,7 @@ void mbedtls_entropy_init( mbedtls_entropy_context *ctx ) ...@@ -113,6 +118,7 @@ void mbedtls_entropy_init( mbedtls_entropy_context *ctx )
mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL, mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL,
MBEDTLS_ENTROPY_BLOCK_SIZE, MBEDTLS_ENTROPY_BLOCK_SIZE,
MBEDTLS_ENTROPY_SOURCE_STRONG ); MBEDTLS_ENTROPY_SOURCE_STRONG );
ctx->initial_entropy_run = 0;
#endif #endif
#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ #endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */
} }
...@@ -125,7 +131,17 @@ void mbedtls_entropy_free( mbedtls_entropy_context *ctx ) ...@@ -125,7 +131,17 @@ void mbedtls_entropy_free( mbedtls_entropy_context *ctx )
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_free( &ctx->mutex ); mbedtls_mutex_free( &ctx->mutex );
#endif #endif
mbedtls_zeroize( ctx, sizeof( mbedtls_entropy_context ) ); #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
mbedtls_sha512_free( &ctx->accumulator );
#else
mbedtls_sha256_free( &ctx->accumulator );
#endif
#if defined(MBEDTLS_ENTROPY_NV_SEED)
ctx->initial_entropy_run = 0;
#endif
ctx->source_count = 0;
mbedtls_zeroize( ctx->source, sizeof( ctx->source ) );
ctx->accumulator_started = 0;
} }
int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx,
...@@ -172,13 +188,16 @@ static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id ...@@ -172,13 +188,16 @@ static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id
unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE]; unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE];
size_t use_len = len; size_t use_len = len;
const unsigned char *p = data; const unsigned char *p = data;
int ret = 0;
if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE ) if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE )
{ {
#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
mbedtls_sha512( data, len, tmp, 0 ); if( ( ret = mbedtls_sha512_ret( data, len, tmp, 0 ) ) != 0 )
goto cleanup;
#else #else
mbedtls_sha256( data, len, tmp, 0 ); if( ( ret = mbedtls_sha256_ret( data, len, tmp, 0 ) ) != 0 )
goto cleanup;
#endif #endif
p = tmp; p = tmp;
use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; use_len = MBEDTLS_ENTROPY_BLOCK_SIZE;
...@@ -187,15 +206,35 @@ static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id ...@@ -187,15 +206,35 @@ static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id
header[0] = source_id; header[0] = source_id;
header[1] = use_len & 0xFF; header[1] = use_len & 0xFF;
/*
* Start the accumulator if this has not already happened. Note that
* it is sufficient to start the accumulator here only because all calls to
* gather entropy eventually execute this code.
*/
#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
mbedtls_sha512_update( &ctx->accumulator, header, 2 ); if( ctx->accumulator_started == 0 &&
mbedtls_sha512_update( &ctx->accumulator, p, use_len ); ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
goto cleanup;
else
ctx->accumulator_started = 1;
if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, header, 2 ) ) != 0 )
goto cleanup;
ret = mbedtls_sha512_update_ret( &ctx->accumulator, p, use_len );
#else #else
mbedtls_sha256_update( &ctx->accumulator, header, 2 ); if( ctx->accumulator_started == 0 &&
mbedtls_sha256_update( &ctx->accumulator, p, use_len ); ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
goto cleanup;
else
ctx->accumulator_started = 1;
if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, header, 2 ) ) != 0 )
goto cleanup;
ret = mbedtls_sha256_update_ret( &ctx->accumulator, p, use_len );
#endif #endif
return( 0 ); cleanup:
mbedtls_zeroize( tmp, sizeof( tmp ) );
return( ret );
} }
int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx,
...@@ -242,7 +281,7 @@ static int entropy_gather_internal( mbedtls_entropy_context *ctx ) ...@@ -242,7 +281,7 @@ static int entropy_gather_internal( mbedtls_entropy_context *ctx )
if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source, if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen ) ) != 0 ) buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen ) ) != 0 )
{ {
return( ret ); goto cleanup;
} }
/* /*
...@@ -250,15 +289,20 @@ static int entropy_gather_internal( mbedtls_entropy_context *ctx ) ...@@ -250,15 +289,20 @@ static int entropy_gather_internal( mbedtls_entropy_context *ctx )
*/ */
if( olen > 0 ) if( olen > 0 )
{ {
entropy_update( ctx, (unsigned char) i, buf, olen ); if( ( ret = entropy_update( ctx, (unsigned char) i,
buf, olen ) ) != 0 )
return( ret );
ctx->source[i].size += olen; ctx->source[i].size += olen;
} }
} }
if( have_one_strong == 0 ) if( have_one_strong == 0 )
return( MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE ); ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE;
return( 0 ); cleanup:
mbedtls_zeroize( buf, sizeof( buf ) );
return( ret );
} }
/* /*
...@@ -333,33 +377,52 @@ int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ) ...@@ -333,33 +377,52 @@ int mbedtls_entropy_func( void *data, unsigned char *output, size_t len )
memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
mbedtls_sha512_finish( &ctx->accumulator, buf ); /*
* Note that at this stage it is assumed that the accumulator was started
* in a previous call to entropy_update(). If this is not guaranteed, the
* code below will fail.
*/
if( ( ret = mbedtls_sha512_finish_ret( &ctx->accumulator, buf ) ) != 0 )
goto exit;
/* /*
* Reset accumulator and counters and recycle existing entropy * Reset accumulator and counters and recycle existing entropy
*/ */
memset( &ctx->accumulator, 0, sizeof( mbedtls_sha512_context ) ); mbedtls_sha512_free( &ctx->accumulator );
mbedtls_sha512_starts( &ctx->accumulator, 0 ); mbedtls_sha512_init( &ctx->accumulator );
mbedtls_sha512_update( &ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); if( ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
goto exit;
if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, buf,
MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
goto exit;
/* /*
* Perform second SHA-512 on entropy * Perform second SHA-512 on entropy
*/ */
mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0 ); if( ( ret = mbedtls_sha512_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE,
buf, 0 ) ) != 0 )
goto exit;
#else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ #else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
mbedtls_sha256_finish( &ctx->accumulator, buf ); if( ( ret = mbedtls_sha256_finish_ret( &ctx->accumulator, buf ) ) != 0 )
goto exit;
/* /*
* Reset accumulator and counters and recycle existing entropy * Reset accumulator and counters and recycle existing entropy
*/ */
memset( &ctx->accumulator, 0, sizeof( mbedtls_sha256_context ) ); mbedtls_sha256_free( &ctx->accumulator );
mbedtls_sha256_starts( &ctx->accumulator, 0 ); mbedtls_sha256_init( &ctx->accumulator );
mbedtls_sha256_update( &ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); if( ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
goto exit;
if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, buf,
MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
goto exit;
/* /*
* Perform second SHA-256 on entropy * Perform second SHA-256 on entropy
*/ */
mbedtls_sha256( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0 ); if( ( ret = mbedtls_sha256_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE,
buf, 0 ) ) != 0 )
goto exit;
#endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ #endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
for( i = 0; i < ctx->source_count; i++ ) for( i = 0; i < ctx->source_count; i++ )
...@@ -370,6 +433,8 @@ int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ) ...@@ -370,6 +433,8 @@ int mbedtls_entropy_func( void *data, unsigned char *output, size_t len )
ret = 0; ret = 0;
exit: exit:
mbedtls_zeroize( buf, sizeof( buf ) );
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
...@@ -382,7 +447,7 @@ exit: ...@@ -382,7 +447,7 @@ exit:
int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ) int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx )
{ {
int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ]; unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
/* Read new seed and write it to NV */ /* Read new seed and write it to NV */
if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
...@@ -393,9 +458,9 @@ int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ) ...@@ -393,9 +458,9 @@ int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx )
/* Manually update the remaining stream with a separator value to diverge */ /* Manually update the remaining stream with a separator value to diverge */
memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); ret = mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE );
return( 0 ); return( ret );
} }
#endif /* MBEDTLS_ENTROPY_NV_SEED */ #endif /* MBEDTLS_ENTROPY_NV_SEED */
...@@ -421,12 +486,15 @@ int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *p ...@@ -421,12 +486,15 @@ int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *p
ret = 0; ret = 0;
exit: exit:
mbedtls_zeroize( buf, sizeof( buf ) );
fclose( f ); fclose( f );
return( ret ); return( ret );
} }
int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ) int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path )
{ {
int ret = 0;
FILE *f; FILE *f;
size_t n; size_t n;
unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ]; unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ];
...@@ -442,14 +510,16 @@ int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char * ...@@ -442,14 +510,16 @@ int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *
n = MBEDTLS_ENTROPY_MAX_SEED_SIZE; n = MBEDTLS_ENTROPY_MAX_SEED_SIZE;
if( fread( buf, 1, n, f ) != n ) if( fread( buf, 1, n, f ) != n )
{ ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
fclose( f ); else
return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); ret = mbedtls_entropy_update_manual( ctx, buf, n );
}
fclose( f ); fclose( f );
mbedtls_entropy_update_manual( ctx, buf, n ); mbedtls_zeroize( buf, sizeof( buf ) );
if( ret != 0 )
return( ret );
return( mbedtls_entropy_write_seed_file( ctx, path ) ); return( mbedtls_entropy_write_seed_file( ctx, path ) );
} }
......
...@@ -45,6 +45,10 @@ ...@@ -45,6 +45,10 @@
#include "mbedtls/aes.h" #include "mbedtls/aes.h"
#endif #endif
#if defined(MBEDTLS_ARC4_C)
#include "mbedtls/arc4.h"
#endif
#if defined(MBEDTLS_BASE64_C) #if defined(MBEDTLS_BASE64_C)
#include "mbedtls/base64.h" #include "mbedtls/base64.h"
#endif #endif
...@@ -69,6 +73,10 @@ ...@@ -69,6 +73,10 @@
#include "mbedtls/cipher.h" #include "mbedtls/cipher.h"
#endif #endif
#if defined(MBEDTLS_CMAC_C)
#include "mbedtls/cmac.h"
#endif
#if defined(MBEDTLS_CTR_DRBG_C) #if defined(MBEDTLS_CTR_DRBG_C)
#include "mbedtls/ctr_drbg.h" #include "mbedtls/ctr_drbg.h"
#endif #endif
...@@ -101,6 +109,18 @@ ...@@ -101,6 +109,18 @@
#include "mbedtls/md.h" #include "mbedtls/md.h"
#endif #endif
#if defined(MBEDTLS_MD2_C)
#include "mbedtls/md2.h"
#endif
#if defined(MBEDTLS_MD4_C)
#include "mbedtls/md4.h"
#endif
#if defined(MBEDTLS_MD5_C)
#include "mbedtls/md5.h"
#endif
#if defined(MBEDTLS_NET_C) #if defined(MBEDTLS_NET_C)
#include "mbedtls/net_sockets.h" #include "mbedtls/net_sockets.h"
#endif #endif
...@@ -129,10 +149,26 @@ ...@@ -129,10 +149,26 @@
#include "mbedtls/pkcs5.h" #include "mbedtls/pkcs5.h"
#endif #endif
#if defined(MBEDTLS_RIPEMD160_C)
#include "mbedtls/ripemd160.h"
#endif
#if defined(MBEDTLS_RSA_C) #if defined(MBEDTLS_RSA_C)
#include "mbedtls/rsa.h" #include "mbedtls/rsa.h"
#endif #endif
#if defined(MBEDTLS_SHA1_C)
#include "mbedtls/sha1.h"
#endif
#if defined(MBEDTLS_SHA256_C)
#include "mbedtls/sha256.h"
#endif
#if defined(MBEDTLS_SHA512_C)
#include "mbedtls/sha512.h"
#endif
#if defined(MBEDTLS_SSL_TLS_C) #if defined(MBEDTLS_SSL_TLS_C)
#include "mbedtls/ssl.h" #include "mbedtls/ssl.h"
#endif #endif
...@@ -174,7 +210,7 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) ...@@ -174,7 +210,7 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
if( use_ret == -(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) ) if( use_ret == -(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) )
mbedtls_snprintf( buf, buflen, "CIPHER - The selected feature is not available" ); mbedtls_snprintf( buf, buflen, "CIPHER - The selected feature is not available" );
if( use_ret == -(MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA) ) if( use_ret == -(MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA) )
mbedtls_snprintf( buf, buflen, "CIPHER - Bad input parameters to function" ); mbedtls_snprintf( buf, buflen, "CIPHER - Bad input parameters" );
if( use_ret == -(MBEDTLS_ERR_CIPHER_ALLOC_FAILED) ) if( use_ret == -(MBEDTLS_ERR_CIPHER_ALLOC_FAILED) )
mbedtls_snprintf( buf, buflen, "CIPHER - Failed to allocate memory" ); mbedtls_snprintf( buf, buflen, "CIPHER - Failed to allocate memory" );
if( use_ret == -(MBEDTLS_ERR_CIPHER_INVALID_PADDING) ) if( use_ret == -(MBEDTLS_ERR_CIPHER_INVALID_PADDING) )
...@@ -184,12 +220,14 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) ...@@ -184,12 +220,14 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
if( use_ret == -(MBEDTLS_ERR_CIPHER_AUTH_FAILED) ) if( use_ret == -(MBEDTLS_ERR_CIPHER_AUTH_FAILED) )
mbedtls_snprintf( buf, buflen, "CIPHER - Authentication failed (for AEAD modes)" ); mbedtls_snprintf( buf, buflen, "CIPHER - Authentication failed (for AEAD modes)" );
if( use_ret == -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT) ) if( use_ret == -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT) )
mbedtls_snprintf( buf, buflen, "CIPHER - The context is invalid, eg because it was free()ed" ); mbedtls_snprintf( buf, buflen, "CIPHER - The context is invalid. For example, because it was freed" );
if( use_ret == -(MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "CIPHER - Cipher hardware accelerator failed" );
#endif /* MBEDTLS_CIPHER_C */ #endif /* MBEDTLS_CIPHER_C */
#if defined(MBEDTLS_DHM_C) #if defined(MBEDTLS_DHM_C)
if( use_ret == -(MBEDTLS_ERR_DHM_BAD_INPUT_DATA) ) if( use_ret == -(MBEDTLS_ERR_DHM_BAD_INPUT_DATA) )
mbedtls_snprintf( buf, buflen, "DHM - Bad input parameters to function" ); mbedtls_snprintf( buf, buflen, "DHM - Bad input parameters" );
if( use_ret == -(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED) ) if( use_ret == -(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED) )
mbedtls_snprintf( buf, buflen, "DHM - Reading of the DHM parameters failed" ); mbedtls_snprintf( buf, buflen, "DHM - Reading of the DHM parameters failed" );
if( use_ret == -(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED) ) if( use_ret == -(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED) )
...@@ -205,7 +243,11 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) ...@@ -205,7 +243,11 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
if( use_ret == -(MBEDTLS_ERR_DHM_ALLOC_FAILED) ) if( use_ret == -(MBEDTLS_ERR_DHM_ALLOC_FAILED) )
mbedtls_snprintf( buf, buflen, "DHM - Allocation of memory failed" ); mbedtls_snprintf( buf, buflen, "DHM - Allocation of memory failed" );
if( use_ret == -(MBEDTLS_ERR_DHM_FILE_IO_ERROR) ) if( use_ret == -(MBEDTLS_ERR_DHM_FILE_IO_ERROR) )
mbedtls_snprintf( buf, buflen, "DHM - Read/write of file failed" ); mbedtls_snprintf( buf, buflen, "DHM - Read or write of file failed" );
if( use_ret == -(MBEDTLS_ERR_DHM_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "DHM - DHM hardware accelerator failed" );
if( use_ret == -(MBEDTLS_ERR_DHM_SET_GROUP_FAILED) )
mbedtls_snprintf( buf, buflen, "DHM - Setting the modulus and generator failed" );
#endif /* MBEDTLS_DHM_C */ #endif /* MBEDTLS_DHM_C */
#if defined(MBEDTLS_ECP_C) #if defined(MBEDTLS_ECP_C)
...@@ -225,6 +267,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) ...@@ -225,6 +267,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "ECP - Invalid private or public key" ); mbedtls_snprintf( buf, buflen, "ECP - Invalid private or public key" );
if( use_ret == -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) ) if( use_ret == -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) )
mbedtls_snprintf( buf, buflen, "ECP - Signature is valid but shorter than the user-supplied length" ); mbedtls_snprintf( buf, buflen, "ECP - Signature is valid but shorter than the user-supplied length" );
if( use_ret == -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "ECP - ECP hardware accelerator failed" );
#endif /* MBEDTLS_ECP_C */ #endif /* MBEDTLS_ECP_C */
#if defined(MBEDTLS_MD_C) #if defined(MBEDTLS_MD_C)
...@@ -236,6 +280,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) ...@@ -236,6 +280,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "MD - Failed to allocate memory" ); mbedtls_snprintf( buf, buflen, "MD - Failed to allocate memory" );
if( use_ret == -(MBEDTLS_ERR_MD_FILE_IO_ERROR) ) if( use_ret == -(MBEDTLS_ERR_MD_FILE_IO_ERROR) )
mbedtls_snprintf( buf, buflen, "MD - Opening or reading of file failed" ); mbedtls_snprintf( buf, buflen, "MD - Opening or reading of file failed" );
if( use_ret == -(MBEDTLS_ERR_MD_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "MD - MD hardware accelerator failed" );
#endif /* MBEDTLS_MD_C */ #endif /* MBEDTLS_MD_C */
#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) #if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C)
...@@ -288,6 +334,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) ...@@ -288,6 +334,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "PK - Unavailable feature, e.g. RSA disabled for RSA key" ); mbedtls_snprintf( buf, buflen, "PK - Unavailable feature, e.g. RSA disabled for RSA key" );
if( use_ret == -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH) ) if( use_ret == -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH) )
mbedtls_snprintf( buf, buflen, "PK - The signature is valid but its length is less than expected" ); mbedtls_snprintf( buf, buflen, "PK - The signature is valid but its length is less than expected" );
if( use_ret == -(MBEDTLS_ERR_PK_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "PK - PK hardware accelerator failed" );
#endif /* MBEDTLS_PK_C */ #endif /* MBEDTLS_PK_C */
#if defined(MBEDTLS_PKCS12_C) #if defined(MBEDTLS_PKCS12_C)
...@@ -320,7 +368,7 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) ...@@ -320,7 +368,7 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
if( use_ret == -(MBEDTLS_ERR_RSA_KEY_GEN_FAILED) ) if( use_ret == -(MBEDTLS_ERR_RSA_KEY_GEN_FAILED) )
mbedtls_snprintf( buf, buflen, "RSA - Something failed during generation of a key" ); mbedtls_snprintf( buf, buflen, "RSA - Something failed during generation of a key" );
if( use_ret == -(MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) ) if( use_ret == -(MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) )
mbedtls_snprintf( buf, buflen, "RSA - Key failed to pass the library's validity check" ); mbedtls_snprintf( buf, buflen, "RSA - Key failed to pass the validity check of the library" );
if( use_ret == -(MBEDTLS_ERR_RSA_PUBLIC_FAILED) ) if( use_ret == -(MBEDTLS_ERR_RSA_PUBLIC_FAILED) )
mbedtls_snprintf( buf, buflen, "RSA - The public key operation failed" ); mbedtls_snprintf( buf, buflen, "RSA - The public key operation failed" );
if( use_ret == -(MBEDTLS_ERR_RSA_PRIVATE_FAILED) ) if( use_ret == -(MBEDTLS_ERR_RSA_PRIVATE_FAILED) )
...@@ -331,6 +379,10 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) ...@@ -331,6 +379,10 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "RSA - The output buffer for decryption is not large enough" ); mbedtls_snprintf( buf, buflen, "RSA - The output buffer for decryption is not large enough" );
if( use_ret == -(MBEDTLS_ERR_RSA_RNG_FAILED) ) if( use_ret == -(MBEDTLS_ERR_RSA_RNG_FAILED) )
mbedtls_snprintf( buf, buflen, "RSA - The random generator failed to generate non-zeros" ); mbedtls_snprintf( buf, buflen, "RSA - The random generator failed to generate non-zeros" );
if( use_ret == -(MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION) )
mbedtls_snprintf( buf, buflen, "RSA - The implementation does not offer the requested operation, for example, because of security violations or lack of functionality" );
if( use_ret == -(MBEDTLS_ERR_RSA_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "RSA - RSA hardware accelerator failed" );
#endif /* MBEDTLS_RSA_C */ #endif /* MBEDTLS_RSA_C */
#if defined(MBEDTLS_SSL_TLS_C) #if defined(MBEDTLS_SSL_TLS_C)
...@@ -518,8 +570,17 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) ...@@ -518,8 +570,17 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "AES - Invalid key length" ); mbedtls_snprintf( buf, buflen, "AES - Invalid key length" );
if( use_ret == -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH) ) if( use_ret == -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH) )
mbedtls_snprintf( buf, buflen, "AES - Invalid data input length" ); mbedtls_snprintf( buf, buflen, "AES - Invalid data input length" );
if( use_ret == -(MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE) )
mbedtls_snprintf( buf, buflen, "AES - Feature not available. For example, an unsupported AES key size" );
if( use_ret == -(MBEDTLS_ERR_AES_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "AES - AES hardware accelerator failed" );
#endif /* MBEDTLS_AES_C */ #endif /* MBEDTLS_AES_C */
#if defined(MBEDTLS_ARC4_C)
if( use_ret == -(MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "ARC4 - ARC4 hardware accelerator failed" );
#endif /* MBEDTLS_ARC4_C */
#if defined(MBEDTLS_ASN1_PARSE_C) #if defined(MBEDTLS_ASN1_PARSE_C)
if( use_ret == -(MBEDTLS_ERR_ASN1_OUT_OF_DATA) ) if( use_ret == -(MBEDTLS_ERR_ASN1_OUT_OF_DATA) )
mbedtls_snprintf( buf, buflen, "ASN1 - Out of data when parsing an ASN1 data structure" ); mbedtls_snprintf( buf, buflen, "ASN1 - Out of data when parsing an ASN1 data structure" );
...@@ -566,6 +627,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) ...@@ -566,6 +627,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
#if defined(MBEDTLS_BLOWFISH_C) #if defined(MBEDTLS_BLOWFISH_C)
if( use_ret == -(MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH) ) if( use_ret == -(MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH) )
mbedtls_snprintf( buf, buflen, "BLOWFISH - Invalid key length" ); mbedtls_snprintf( buf, buflen, "BLOWFISH - Invalid key length" );
if( use_ret == -(MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "BLOWFISH - Blowfish hardware accelerator failed" );
if( use_ret == -(MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH) ) if( use_ret == -(MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH) )
mbedtls_snprintf( buf, buflen, "BLOWFISH - Invalid data input length" ); mbedtls_snprintf( buf, buflen, "BLOWFISH - Invalid data input length" );
#endif /* MBEDTLS_BLOWFISH_C */ #endif /* MBEDTLS_BLOWFISH_C */
...@@ -575,29 +638,40 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) ...@@ -575,29 +638,40 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "CAMELLIA - Invalid key length" ); mbedtls_snprintf( buf, buflen, "CAMELLIA - Invalid key length" );
if( use_ret == -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH) ) if( use_ret == -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH) )
mbedtls_snprintf( buf, buflen, "CAMELLIA - Invalid data input length" ); mbedtls_snprintf( buf, buflen, "CAMELLIA - Invalid data input length" );
if( use_ret == -(MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "CAMELLIA - Camellia hardware accelerator failed" );
#endif /* MBEDTLS_CAMELLIA_C */ #endif /* MBEDTLS_CAMELLIA_C */
#if defined(MBEDTLS_CCM_C) #if defined(MBEDTLS_CCM_C)
if( use_ret == -(MBEDTLS_ERR_CCM_BAD_INPUT) ) if( use_ret == -(MBEDTLS_ERR_CCM_BAD_INPUT) )
mbedtls_snprintf( buf, buflen, "CCM - Bad input parameters to function" ); mbedtls_snprintf( buf, buflen, "CCM - Bad input parameters to the function" );
if( use_ret == -(MBEDTLS_ERR_CCM_AUTH_FAILED) ) if( use_ret == -(MBEDTLS_ERR_CCM_AUTH_FAILED) )
mbedtls_snprintf( buf, buflen, "CCM - Authenticated decryption failed" ); mbedtls_snprintf( buf, buflen, "CCM - Authenticated decryption failed" );
if( use_ret == -(MBEDTLS_ERR_CCM_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "CCM - CCM hardware accelerator failed" );
#endif /* MBEDTLS_CCM_C */ #endif /* MBEDTLS_CCM_C */
#if defined(MBEDTLS_CMAC_C)
if( use_ret == -(MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "CMAC - CMAC hardware accelerator failed" );
#endif /* MBEDTLS_CMAC_C */
#if defined(MBEDTLS_CTR_DRBG_C) #if defined(MBEDTLS_CTR_DRBG_C)
if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED) ) if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED) )
mbedtls_snprintf( buf, buflen, "CTR_DRBG - The entropy source failed" ); mbedtls_snprintf( buf, buflen, "CTR_DRBG - The entropy source failed" );
if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG) ) if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG) )
mbedtls_snprintf( buf, buflen, "CTR_DRBG - Too many random requested in single call" ); mbedtls_snprintf( buf, buflen, "CTR_DRBG - The requested random buffer length is too big" );
if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG) ) if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG) )
mbedtls_snprintf( buf, buflen, "CTR_DRBG - Input too large (Entropy + additional)" ); mbedtls_snprintf( buf, buflen, "CTR_DRBG - The input (entropy + additional data) is too large" );
if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR) ) if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR) )
mbedtls_snprintf( buf, buflen, "CTR_DRBG - Read/write error in file" ); mbedtls_snprintf( buf, buflen, "CTR_DRBG - Read or write error in file" );
#endif /* MBEDTLS_CTR_DRBG_C */ #endif /* MBEDTLS_CTR_DRBG_C */
#if defined(MBEDTLS_DES_C) #if defined(MBEDTLS_DES_C)
if( use_ret == -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH) ) if( use_ret == -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH) )
mbedtls_snprintf( buf, buflen, "DES - The data input has an invalid length" ); mbedtls_snprintf( buf, buflen, "DES - The data input has an invalid length" );
if( use_ret == -(MBEDTLS_ERR_DES_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "DES - DES hardware accelerator failed" );
#endif /* MBEDTLS_DES_C */ #endif /* MBEDTLS_DES_C */
#if defined(MBEDTLS_ENTROPY_C) #if defined(MBEDTLS_ENTROPY_C)
...@@ -616,6 +690,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) ...@@ -616,6 +690,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
#if defined(MBEDTLS_GCM_C) #if defined(MBEDTLS_GCM_C)
if( use_ret == -(MBEDTLS_ERR_GCM_AUTH_FAILED) ) if( use_ret == -(MBEDTLS_ERR_GCM_AUTH_FAILED) )
mbedtls_snprintf( buf, buflen, "GCM - Authenticated decryption failed" ); mbedtls_snprintf( buf, buflen, "GCM - Authenticated decryption failed" );
if( use_ret == -(MBEDTLS_ERR_GCM_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "GCM - GCM hardware accelerator failed" );
if( use_ret == -(MBEDTLS_ERR_GCM_BAD_INPUT) ) if( use_ret == -(MBEDTLS_ERR_GCM_BAD_INPUT) )
mbedtls_snprintf( buf, buflen, "GCM - Bad input parameters to function" ); mbedtls_snprintf( buf, buflen, "GCM - Bad input parameters to function" );
#endif /* MBEDTLS_GCM_C */ #endif /* MBEDTLS_GCM_C */
...@@ -631,6 +707,21 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) ...@@ -631,6 +707,21 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "HMAC_DRBG - The entropy source failed" ); mbedtls_snprintf( buf, buflen, "HMAC_DRBG - The entropy source failed" );
#endif /* MBEDTLS_HMAC_DRBG_C */ #endif /* MBEDTLS_HMAC_DRBG_C */
#if defined(MBEDTLS_MD2_C)
if( use_ret == -(MBEDTLS_ERR_MD2_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "MD2 - MD2 hardware accelerator failed" );
#endif /* MBEDTLS_MD2_C */
#if defined(MBEDTLS_MD4_C)
if( use_ret == -(MBEDTLS_ERR_MD4_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "MD4 - MD4 hardware accelerator failed" );
#endif /* MBEDTLS_MD4_C */
#if defined(MBEDTLS_MD5_C)
if( use_ret == -(MBEDTLS_ERR_MD5_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "MD5 - MD5 hardware accelerator failed" );
#endif /* MBEDTLS_MD5_C */
#if defined(MBEDTLS_NET_C) #if defined(MBEDTLS_NET_C)
if( use_ret == -(MBEDTLS_ERR_NET_SOCKET_FAILED) ) if( use_ret == -(MBEDTLS_ERR_NET_SOCKET_FAILED) )
mbedtls_snprintf( buf, buflen, "NET - Failed to open a socket" ); mbedtls_snprintf( buf, buflen, "NET - Failed to open a socket" );
...@@ -668,6 +759,26 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) ...@@ -668,6 +759,26 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "PADLOCK - Input data should be aligned" ); mbedtls_snprintf( buf, buflen, "PADLOCK - Input data should be aligned" );
#endif /* MBEDTLS_PADLOCK_C */ #endif /* MBEDTLS_PADLOCK_C */
#if defined(MBEDTLS_RIPEMD160_C)
if( use_ret == -(MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "RIPEMD160 - RIPEMD160 hardware accelerator failed" );
#endif /* MBEDTLS_RIPEMD160_C */
#if defined(MBEDTLS_SHA1_C)
if( use_ret == -(MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "SHA1 - SHA-1 hardware accelerator failed" );
#endif /* MBEDTLS_SHA1_C */
#if defined(MBEDTLS_SHA256_C)
if( use_ret == -(MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "SHA256 - SHA-256 hardware accelerator failed" );
#endif /* MBEDTLS_SHA256_C */
#if defined(MBEDTLS_SHA512_C)
if( use_ret == -(MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "SHA512 - SHA-512 hardware accelerator failed" );
#endif /* MBEDTLS_SHA512_C */
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
if( use_ret == -(MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE) ) if( use_ret == -(MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE) )
mbedtls_snprintf( buf, buflen, "THREADING - The selected feature is not available" ); mbedtls_snprintf( buf, buflen, "THREADING - The selected feature is not available" );
...@@ -680,6 +791,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) ...@@ -680,6 +791,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
#if defined(MBEDTLS_XTEA_C) #if defined(MBEDTLS_XTEA_C)
if( use_ret == -(MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH) ) if( use_ret == -(MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH) )
mbedtls_snprintf( buf, buflen, "XTEA - The data input has an invalid length" ); mbedtls_snprintf( buf, buflen, "XTEA - The data input has an invalid length" );
if( use_ret == -(MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED) )
mbedtls_snprintf( buf, buflen, "XTEA - XTEA hardware accelerator failed" );
#endif /* MBEDTLS_XTEA_C */ #endif /* MBEDTLS_XTEA_C */
// END generated code // END generated code
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#endif #endif
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
#include "mbedtls/aes.h"
#if defined(MBEDTLS_PLATFORM_C) #if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h" #include "mbedtls/platform.h"
#else #else
...@@ -54,6 +55,8 @@ ...@@ -54,6 +55,8 @@
#endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
#if !defined(MBEDTLS_GCM_ALT)
/* /*
* 32-bit integer manipulation macros (big endian) * 32-bit integer manipulation macros (big endian)
*/ */
...@@ -508,6 +511,8 @@ void mbedtls_gcm_free( mbedtls_gcm_context *ctx ) ...@@ -508,6 +511,8 @@ void mbedtls_gcm_free( mbedtls_gcm_context *ctx )
mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) ); mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) );
} }
#endif /* !MBEDTLS_GCM_ALT */
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
/* /*
* AES-GCM test vectors from: * AES-GCM test vectors from:
...@@ -744,34 +749,48 @@ int mbedtls_gcm_self_test( int verbose ) ...@@ -744,34 +749,48 @@ int mbedtls_gcm_self_test( int verbose )
int i, j, ret; int i, j, ret;
mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
mbedtls_gcm_init( &ctx );
for( j = 0; j < 3; j++ ) for( j = 0; j < 3; j++ )
{ {
int key_len = 128 + 64 * j; int key_len = 128 + 64 * j;
for( i = 0; i < MAX_TESTS; i++ ) for( i = 0; i < MAX_TESTS; i++ )
{ {
mbedtls_gcm_init( &ctx );
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( " AES-GCM-%3d #%d (%s): ", mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
key_len, i, "enc" ); key_len, i, "enc" );
mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
key_len );
/*
* AES-192 is an optional feature that may be unavailable when
* there is an alternative underlying implementation i.e. when
* MBEDTLS_AES_ALT is defined.
*/
if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && key_len == 192 )
{
mbedtls_printf( "skipped\n" );
break;
}
else if( ret != 0 )
{
goto exit;
}
ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT, ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT,
pt_len[i], pt_len[i],
iv[iv_index[i]], iv_len[i], iv[iv_index[i]], iv_len[i],
additional[add_index[i]], add_len[i], additional[add_index[i]], add_len[i],
pt[pt_index[i]], buf, 16, tag_buf ); pt[pt_index[i]], buf, 16, tag_buf );
if( ret != 0 )
goto exit;
if( ret != 0 || if ( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
{ {
if( verbose != 0 ) ret = 1;
mbedtls_printf( "failed\n" ); goto exit;
return( 1 );
} }
mbedtls_gcm_free( &ctx ); mbedtls_gcm_free( &ctx );
...@@ -779,26 +798,31 @@ int mbedtls_gcm_self_test( int verbose ) ...@@ -779,26 +798,31 @@ int mbedtls_gcm_self_test( int verbose )
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( "passed\n" ); mbedtls_printf( "passed\n" );
mbedtls_gcm_init( &ctx );
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( " AES-GCM-%3d #%d (%s): ", mbedtls_printf( " AES-GCM-%3d #%d (%s): ",
key_len, i, "dec" ); key_len, i, "dec" );
mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
key_len );
if( ret != 0 )
goto exit;
ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT, ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT,
pt_len[i], pt_len[i],
iv[iv_index[i]], iv_len[i], iv[iv_index[i]], iv_len[i],
additional[add_index[i]], add_len[i], additional[add_index[i]], add_len[i],
ct[j * 6 + i], buf, 16, tag_buf ); ct[j * 6 + i], buf, 16, tag_buf );
if( ret != 0 )
goto exit;
if( ret != 0 || if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
{ {
if( verbose != 0 ) ret = 1;
mbedtls_printf( "failed\n" ); goto exit;
return( 1 );
} }
mbedtls_gcm_free( &ctx ); mbedtls_gcm_free( &ctx );
...@@ -806,66 +830,51 @@ int mbedtls_gcm_self_test( int verbose ) ...@@ -806,66 +830,51 @@ int mbedtls_gcm_self_test( int verbose )
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( "passed\n" ); mbedtls_printf( "passed\n" );
mbedtls_gcm_init( &ctx );
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
key_len, i, "enc" ); key_len, i, "enc" );
mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
key_len );
if( ret != 0 )
goto exit;
ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT, ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT,
iv[iv_index[i]], iv_len[i], iv[iv_index[i]], iv_len[i],
additional[add_index[i]], add_len[i] ); additional[add_index[i]], add_len[i] );
if( ret != 0 ) if( ret != 0 )
{ goto exit;
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
if( pt_len[i] > 32 ) if( pt_len[i] > 32 )
{ {
size_t rest_len = pt_len[i] - 32; size_t rest_len = pt_len[i] - 32;
ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf ); ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf );
if( ret != 0 ) if( ret != 0 )
{ goto exit;
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32, ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32,
buf + 32 ); buf + 32 );
if( ret != 0 ) if( ret != 0 )
{ goto exit;
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
} }
else else
{ {
ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf ); ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
if( ret != 0 ) if( ret != 0 )
{ goto exit;
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
} }
ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
if( ret != 0 || if( ret != 0 )
memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || goto exit;
if( memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
{ {
if( verbose != 0 ) ret = 1;
mbedtls_printf( "failed\n" ); goto exit;
return( 1 );
} }
mbedtls_gcm_free( &ctx ); mbedtls_gcm_free( &ctx );
...@@ -873,80 +882,75 @@ int mbedtls_gcm_self_test( int verbose ) ...@@ -873,80 +882,75 @@ int mbedtls_gcm_self_test( int verbose )
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( "passed\n" ); mbedtls_printf( "passed\n" );
mbedtls_gcm_init( &ctx );
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", mbedtls_printf( " AES-GCM-%3d #%d split (%s): ",
key_len, i, "dec" ); key_len, i, "dec" );
mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); ret = mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]],
key_len );
if( ret != 0 )
goto exit;
ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT, ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT,
iv[iv_index[i]], iv_len[i], iv[iv_index[i]], iv_len[i],
additional[add_index[i]], add_len[i] ); additional[add_index[i]], add_len[i] );
if( ret != 0 ) if( ret != 0 )
{ goto exit;
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
if( pt_len[i] > 32 ) if( pt_len[i] > 32 )
{ {
size_t rest_len = pt_len[i] - 32; size_t rest_len = pt_len[i] - 32;
ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf ); ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf );
if( ret != 0 ) if( ret != 0 )
{ goto exit;
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32, ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32,
buf + 32 ); buf + 32 );
if( ret != 0 ) if( ret != 0 )
{ goto exit;
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
} }
else else
{ {
ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf ); ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i],
buf );
if( ret != 0 ) if( ret != 0 )
{ goto exit;
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
} }
ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 );
if( ret != 0 || if( ret != 0 )
memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || goto exit;
if( memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
{ {
if( verbose != 0 ) ret = 1;
mbedtls_printf( "failed\n" ); goto exit;
return( 1 );
} }
mbedtls_gcm_free( &ctx ); mbedtls_gcm_free( &ctx );
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( "passed\n" ); mbedtls_printf( "passed\n" );
} }
} }
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( "\n" ); mbedtls_printf( "\n" );
return( 0 ); ret = 0;
exit:
if( ret != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
mbedtls_gcm_free( &ctx );
}
return( ret );
} }
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
......
...@@ -364,11 +364,14 @@ int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const cha ...@@ -364,11 +364,14 @@ int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const cha
exit: exit:
fclose( f ); fclose( f );
mbedtls_zeroize( buf, sizeof( buf ) );
return( ret ); return( ret );
} }
int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
{ {
int ret = 0;
FILE *f; FILE *f;
size_t n; size_t n;
unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
...@@ -387,14 +390,16 @@ int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const ch ...@@ -387,14 +390,16 @@ int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const ch
} }
if( fread( buf, 1, n, f ) != n ) if( fread( buf, 1, n, f ) != n )
{ ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
fclose( f ); else
return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); mbedtls_hmac_drbg_update( ctx, buf, n );
}
fclose( f ); fclose( f );
mbedtls_hmac_drbg_update( ctx, buf, n ); mbedtls_zeroize( buf, sizeof( buf ) );
if( ret != 0 )
return( ret );
return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) ); return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
} }
......
...@@ -250,9 +250,7 @@ int mbedtls_md_starts( mbedtls_md_context_t *ctx ) ...@@ -250,9 +250,7 @@ int mbedtls_md_starts( mbedtls_md_context_t *ctx )
if( ctx == NULL || ctx->md_info == NULL ) if( ctx == NULL || ctx->md_info == NULL )
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
ctx->md_info->starts_func( ctx->md_ctx ); return( ctx->md_info->starts_func( ctx->md_ctx ) );
return( 0 );
} }
int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen )
...@@ -260,9 +258,7 @@ int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, si ...@@ -260,9 +258,7 @@ int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, si
if( ctx == NULL || ctx->md_info == NULL ) if( ctx == NULL || ctx->md_info == NULL )
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
ctx->md_info->update_func( ctx->md_ctx, input, ilen ); return( ctx->md_info->update_func( ctx->md_ctx, input, ilen ) );
return( 0 );
} }
int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ) int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output )
...@@ -270,9 +266,7 @@ int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ) ...@@ -270,9 +266,7 @@ int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output )
if( ctx == NULL || ctx->md_info == NULL ) if( ctx == NULL || ctx->md_info == NULL )
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
ctx->md_info->finish_func( ctx->md_ctx, output ); return( ctx->md_info->finish_func( ctx->md_ctx, output ) );
return( 0 );
} }
int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen,
...@@ -281,9 +275,7 @@ int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, si ...@@ -281,9 +275,7 @@ int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, si
if( md_info == NULL ) if( md_info == NULL )
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
md_info->digest_func( input, ilen, output ); return( md_info->digest_func( input, ilen, output ) );
return( 0 );
} }
#if defined(MBEDTLS_FS_IO) #if defined(MBEDTLS_FS_IO)
...@@ -306,20 +298,20 @@ int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigne ...@@ -306,20 +298,20 @@ int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigne
if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 )
goto cleanup; goto cleanup;
md_info->starts_func( ctx.md_ctx ); if( ( ret = md_info->starts_func( ctx.md_ctx ) ) != 0 )
goto cleanup;
while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
md_info->update_func( ctx.md_ctx, buf, n ); if( ( ret = md_info->update_func( ctx.md_ctx, buf, n ) ) != 0 )
goto cleanup;
if( ferror( f ) != 0 ) if( ferror( f ) != 0 )
{
ret = MBEDTLS_ERR_MD_FILE_IO_ERROR; ret = MBEDTLS_ERR_MD_FILE_IO_ERROR;
goto cleanup; else
} ret = md_info->finish_func( ctx.md_ctx, output );
md_info->finish_func( ctx.md_ctx, output );
cleanup: cleanup:
mbedtls_zeroize( buf, sizeof( buf ) );
fclose( f ); fclose( f );
mbedtls_md_free( &ctx ); mbedtls_md_free( &ctx );
...@@ -329,6 +321,7 @@ cleanup: ...@@ -329,6 +321,7 @@ cleanup:
int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen ) int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen )
{ {
int ret;
unsigned char sum[MBEDTLS_MD_MAX_SIZE]; unsigned char sum[MBEDTLS_MD_MAX_SIZE];
unsigned char *ipad, *opad; unsigned char *ipad, *opad;
size_t i; size_t i;
...@@ -338,9 +331,12 @@ int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, ...@@ -338,9 +331,12 @@ int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key,
if( keylen > (size_t) ctx->md_info->block_size ) if( keylen > (size_t) ctx->md_info->block_size )
{ {
ctx->md_info->starts_func( ctx->md_ctx ); if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 )
ctx->md_info->update_func( ctx->md_ctx, key, keylen ); goto cleanup;
ctx->md_info->finish_func( ctx->md_ctx, sum ); if( ( ret = ctx->md_info->update_func( ctx->md_ctx, key, keylen ) ) != 0 )
goto cleanup;
if( ( ret = ctx->md_info->finish_func( ctx->md_ctx, sum ) ) != 0 )
goto cleanup;
keylen = ctx->md_info->size; keylen = ctx->md_info->size;
key = sum; key = sum;
...@@ -358,12 +354,16 @@ int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, ...@@ -358,12 +354,16 @@ int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key,
opad[i] = (unsigned char)( opad[i] ^ key[i] ); opad[i] = (unsigned char)( opad[i] ^ key[i] );
} }
mbedtls_zeroize( sum, sizeof( sum ) ); if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 )
goto cleanup;
if( ( ret = ctx->md_info->update_func( ctx->md_ctx, ipad,
ctx->md_info->block_size ) ) != 0 )
goto cleanup;
ctx->md_info->starts_func( ctx->md_ctx ); cleanup:
ctx->md_info->update_func( ctx->md_ctx, ipad, ctx->md_info->block_size ); mbedtls_zeroize( sum, sizeof( sum ) );
return( 0 ); return( ret );
} }
int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen )
...@@ -371,13 +371,12 @@ int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *inpu ...@@ -371,13 +371,12 @@ int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *inpu
if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL )
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
ctx->md_info->update_func( ctx->md_ctx, input, ilen ); return( ctx->md_info->update_func( ctx->md_ctx, input, ilen ) );
return( 0 );
} }
int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output ) int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output )
{ {
int ret;
unsigned char tmp[MBEDTLS_MD_MAX_SIZE]; unsigned char tmp[MBEDTLS_MD_MAX_SIZE];
unsigned char *opad; unsigned char *opad;
...@@ -386,17 +385,22 @@ int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output ) ...@@ -386,17 +385,22 @@ int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output )
opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size;
ctx->md_info->finish_func( ctx->md_ctx, tmp ); if( ( ret = ctx->md_info->finish_func( ctx->md_ctx, tmp ) ) != 0 )
ctx->md_info->starts_func( ctx->md_ctx ); return( ret );
ctx->md_info->update_func( ctx->md_ctx, opad, ctx->md_info->block_size ); if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 )
ctx->md_info->update_func( ctx->md_ctx, tmp, ctx->md_info->size ); return( ret );
ctx->md_info->finish_func( ctx->md_ctx, output ); if( ( ret = ctx->md_info->update_func( ctx->md_ctx, opad,
ctx->md_info->block_size ) ) != 0 )
return( 0 ); return( ret );
if( ( ret = ctx->md_info->update_func( ctx->md_ctx, tmp,
ctx->md_info->size ) ) != 0 )
return( ret );
return( ctx->md_info->finish_func( ctx->md_ctx, output ) );
} }
int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ) int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx )
{ {
int ret;
unsigned char *ipad; unsigned char *ipad;
if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL )
...@@ -404,15 +408,16 @@ int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ) ...@@ -404,15 +408,16 @@ int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx )
ipad = (unsigned char *) ctx->hmac_ctx; ipad = (unsigned char *) ctx->hmac_ctx;
ctx->md_info->starts_func( ctx->md_ctx ); if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 )
ctx->md_info->update_func( ctx->md_ctx, ipad, ctx->md_info->block_size ); return( ret );
return( ctx->md_info->update_func( ctx->md_ctx, ipad,
return( 0 ); ctx->md_info->block_size ) );
} }
int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, int mbedtls_md_hmac( const mbedtls_md_info_t *md_info,
const unsigned char *input, size_t ilen, const unsigned char *key, size_t keylen,
unsigned char *output ) const unsigned char *input, size_t ilen,
unsigned char *output )
{ {
mbedtls_md_context_t ctx; mbedtls_md_context_t ctx;
int ret; int ret;
...@@ -423,15 +428,19 @@ int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, ...@@ -423,15 +428,19 @@ int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key,
mbedtls_md_init( &ctx ); mbedtls_md_init( &ctx );
if( ( ret = mbedtls_md_setup( &ctx, md_info, 1 ) ) != 0 ) if( ( ret = mbedtls_md_setup( &ctx, md_info, 1 ) ) != 0 )
return( ret ); goto cleanup;
mbedtls_md_hmac_starts( &ctx, key, keylen ); if( ( ret = mbedtls_md_hmac_starts( &ctx, key, keylen ) ) != 0 )
mbedtls_md_hmac_update( &ctx, input, ilen ); goto cleanup;
mbedtls_md_hmac_finish( &ctx, output ); if( ( ret = mbedtls_md_hmac_update( &ctx, input, ilen ) ) != 0 )
goto cleanup;
if( ( ret = mbedtls_md_hmac_finish( &ctx, output ) ) != 0 )
goto cleanup;
cleanup:
mbedtls_md_free( &ctx ); mbedtls_md_free( &ctx );
return( 0 ); return( ret );
} }
int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ) int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data )
...@@ -439,9 +448,7 @@ int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ) ...@@ -439,9 +448,7 @@ int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data )
if( ctx == NULL || ctx->md_info == NULL ) if( ctx == NULL || ctx->md_info == NULL )
return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); return( MBEDTLS_ERR_MD_BAD_INPUT_DATA );
ctx->md_info->process_func( ctx->md_ctx, data ); return( ctx->md_info->process_func( ctx->md_ctx, data ) );
return( 0 );
} }
unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ) unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info )
......
...@@ -105,16 +105,18 @@ void mbedtls_md2_clone( mbedtls_md2_context *dst, ...@@ -105,16 +105,18 @@ void mbedtls_md2_clone( mbedtls_md2_context *dst,
/* /*
* MD2 context setup * MD2 context setup
*/ */
void mbedtls_md2_starts( mbedtls_md2_context *ctx ) int mbedtls_md2_starts_ret( mbedtls_md2_context *ctx )
{ {
memset( ctx->cksum, 0, 16 ); memset( ctx->cksum, 0, 16 );
memset( ctx->state, 0, 46 ); memset( ctx->state, 0, 46 );
memset( ctx->buffer, 0, 16 ); memset( ctx->buffer, 0, 16 );
ctx->left = 0; ctx->left = 0;
return( 0 );
} }
#if !defined(MBEDTLS_MD2_PROCESS_ALT) #if !defined(MBEDTLS_MD2_PROCESS_ALT)
void mbedtls_md2_process( mbedtls_md2_context *ctx ) int mbedtls_internal_md2_process( mbedtls_md2_context *ctx )
{ {
int i, j; int i, j;
unsigned char t = 0; unsigned char t = 0;
...@@ -146,14 +148,19 @@ void mbedtls_md2_process( mbedtls_md2_context *ctx ) ...@@ -146,14 +148,19 @@ void mbedtls_md2_process( mbedtls_md2_context *ctx )
( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] ); ( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] );
t = ctx->cksum[i]; t = ctx->cksum[i];
} }
return( 0 );
} }
#endif /* !MBEDTLS_MD2_PROCESS_ALT */ #endif /* !MBEDTLS_MD2_PROCESS_ALT */
/* /*
* MD2 process buffer * MD2 process buffer
*/ */
void mbedtls_md2_update( mbedtls_md2_context *ctx, const unsigned char *input, size_t ilen ) int mbedtls_md2_update_ret( mbedtls_md2_context *ctx,
const unsigned char *input,
size_t ilen )
{ {
int ret;
size_t fill; size_t fill;
while( ilen > 0 ) while( ilen > 0 )
...@@ -172,16 +179,21 @@ void mbedtls_md2_update( mbedtls_md2_context *ctx, const unsigned char *input, s ...@@ -172,16 +179,21 @@ void mbedtls_md2_update( mbedtls_md2_context *ctx, const unsigned char *input, s
if( ctx->left == 16 ) if( ctx->left == 16 )
{ {
ctx->left = 0; ctx->left = 0;
mbedtls_md2_process( ctx ); if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 )
return( ret );
} }
} }
return( 0 );
} }
/* /*
* MD2 final digest * MD2 final digest
*/ */
void mbedtls_md2_finish( mbedtls_md2_context *ctx, unsigned char output[16] ) int mbedtls_md2_finish_ret( mbedtls_md2_context *ctx,
unsigned char output[16] )
{ {
int ret;
size_t i; size_t i;
unsigned char x; unsigned char x;
...@@ -190,12 +202,16 @@ void mbedtls_md2_finish( mbedtls_md2_context *ctx, unsigned char output[16] ) ...@@ -190,12 +202,16 @@ void mbedtls_md2_finish( mbedtls_md2_context *ctx, unsigned char output[16] )
for( i = ctx->left; i < 16; i++ ) for( i = ctx->left; i < 16; i++ )
ctx->buffer[i] = x; ctx->buffer[i] = x;
mbedtls_md2_process( ctx ); if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 )
return( ret );
memcpy( ctx->buffer, ctx->cksum, 16 ); memcpy( ctx->buffer, ctx->cksum, 16 );
mbedtls_md2_process( ctx ); if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 )
return( ret );
memcpy( output, ctx->state, 16 ); memcpy( output, ctx->state, 16 );
return( 0 );
} }
#endif /* !MBEDTLS_MD2_ALT */ #endif /* !MBEDTLS_MD2_ALT */
...@@ -203,15 +219,28 @@ void mbedtls_md2_finish( mbedtls_md2_context *ctx, unsigned char output[16] ) ...@@ -203,15 +219,28 @@ void mbedtls_md2_finish( mbedtls_md2_context *ctx, unsigned char output[16] )
/* /*
* output = MD2( input buffer ) * output = MD2( input buffer )
*/ */
void mbedtls_md2( const unsigned char *input, size_t ilen, unsigned char output[16] ) int mbedtls_md2_ret( const unsigned char *input,
size_t ilen,
unsigned char output[16] )
{ {
int ret;
mbedtls_md2_context ctx; mbedtls_md2_context ctx;
mbedtls_md2_init( &ctx ); mbedtls_md2_init( &ctx );
mbedtls_md2_starts( &ctx );
mbedtls_md2_update( &ctx, input, ilen ); if( ( ret = mbedtls_md2_starts_ret( &ctx ) ) != 0 )
mbedtls_md2_finish( &ctx, output ); goto exit;
if( ( ret = mbedtls_md2_update_ret( &ctx, input, ilen ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md2_finish_ret( &ctx, output ) ) != 0 )
goto exit;
exit:
mbedtls_md2_free( &ctx ); mbedtls_md2_free( &ctx );
return( ret );
} }
#if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_SELF_TEST)
...@@ -219,7 +248,7 @@ void mbedtls_md2( const unsigned char *input, size_t ilen, unsigned char output[ ...@@ -219,7 +248,7 @@ void mbedtls_md2( const unsigned char *input, size_t ilen, unsigned char output[
/* /*
* RFC 1319 test vectors * RFC 1319 test vectors
*/ */
static const char md2_test_str[7][81] = static const unsigned char md2_test_str[7][81] =
{ {
{ "" }, { "" },
{ "a" }, { "a" },
...@@ -227,10 +256,15 @@ static const char md2_test_str[7][81] = ...@@ -227,10 +256,15 @@ static const char md2_test_str[7][81] =
{ "message digest" }, { "message digest" },
{ "abcdefghijklmnopqrstuvwxyz" }, { "abcdefghijklmnopqrstuvwxyz" },
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
{ "12345678901234567890123456789012345678901234567890123456789012" \ { "12345678901234567890123456789012345678901234567890123456789012"
"345678901234567890" } "345678901234567890" }
}; };
static const size_t md2_test_strlen[7] =
{
0, 1, 3, 14, 26, 62, 80
};
static const unsigned char md2_test_sum[7][16] = static const unsigned char md2_test_sum[7][16] =
{ {
{ 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D, { 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D,
...@@ -254,7 +288,7 @@ static const unsigned char md2_test_sum[7][16] = ...@@ -254,7 +288,7 @@ static const unsigned char md2_test_sum[7][16] =
*/ */
int mbedtls_md2_self_test( int verbose ) int mbedtls_md2_self_test( int verbose )
{ {
int i; int i, ret = 0;
unsigned char md2sum[16]; unsigned char md2sum[16];
for( i = 0; i < 7; i++ ) for( i = 0; i < 7; i++ )
...@@ -262,15 +296,14 @@ int mbedtls_md2_self_test( int verbose ) ...@@ -262,15 +296,14 @@ int mbedtls_md2_self_test( int verbose )
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( " MD2 test #%d: ", i + 1 ); mbedtls_printf( " MD2 test #%d: ", i + 1 );
mbedtls_md2( (unsigned char *) md2_test_str[i], ret = mbedtls_md2_ret( md2_test_str[i], md2_test_strlen[i], md2sum );
strlen( md2_test_str[i] ), md2sum ); if( ret != 0 )
goto fail;
if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 ) if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 )
{ {
if( verbose != 0 ) ret = 1;
mbedtls_printf( "failed\n" ); goto fail;
return( 1 );
} }
if( verbose != 0 ) if( verbose != 0 )
...@@ -281,6 +314,12 @@ int mbedtls_md2_self_test( int verbose ) ...@@ -281,6 +314,12 @@ int mbedtls_md2_self_test( int verbose )
mbedtls_printf( "\n" ); mbedtls_printf( "\n" );
return( 0 ); return( 0 );
fail:
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( ret );
} }
#endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SELF_TEST */
......
...@@ -98,7 +98,7 @@ void mbedtls_md4_clone( mbedtls_md4_context *dst, ...@@ -98,7 +98,7 @@ void mbedtls_md4_clone( mbedtls_md4_context *dst,
/* /*
* MD4 context setup * MD4 context setup
*/ */
void mbedtls_md4_starts( mbedtls_md4_context *ctx ) int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx )
{ {
ctx->total[0] = 0; ctx->total[0] = 0;
ctx->total[1] = 0; ctx->total[1] = 0;
...@@ -107,10 +107,13 @@ void mbedtls_md4_starts( mbedtls_md4_context *ctx ) ...@@ -107,10 +107,13 @@ void mbedtls_md4_starts( mbedtls_md4_context *ctx )
ctx->state[1] = 0xEFCDAB89; ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE; ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476; ctx->state[3] = 0x10325476;
return( 0 );
} }
#if !defined(MBEDTLS_MD4_PROCESS_ALT) #if !defined(MBEDTLS_MD4_PROCESS_ALT)
void mbedtls_md4_process( mbedtls_md4_context *ctx, const unsigned char data[64] ) int mbedtls_internal_md4_process( mbedtls_md4_context *ctx,
const unsigned char data[64] )
{ {
uint32_t X[16], A, B, C, D; uint32_t X[16], A, B, C, D;
...@@ -211,19 +214,24 @@ void mbedtls_md4_process( mbedtls_md4_context *ctx, const unsigned char data[64] ...@@ -211,19 +214,24 @@ void mbedtls_md4_process( mbedtls_md4_context *ctx, const unsigned char data[64]
ctx->state[1] += B; ctx->state[1] += B;
ctx->state[2] += C; ctx->state[2] += C;
ctx->state[3] += D; ctx->state[3] += D;
return( 0 );
} }
#endif /* !MBEDTLS_MD4_PROCESS_ALT */ #endif /* !MBEDTLS_MD4_PROCESS_ALT */
/* /*
* MD4 process buffer * MD4 process buffer
*/ */
void mbedtls_md4_update( mbedtls_md4_context *ctx, const unsigned char *input, size_t ilen ) int mbedtls_md4_update_ret( mbedtls_md4_context *ctx,
const unsigned char *input,
size_t ilen )
{ {
int ret;
size_t fill; size_t fill;
uint32_t left; uint32_t left;
if( ilen == 0 ) if( ilen == 0 )
return; return( 0 );
left = ctx->total[0] & 0x3F; left = ctx->total[0] & 0x3F;
fill = 64 - left; fill = 64 - left;
...@@ -238,7 +246,10 @@ void mbedtls_md4_update( mbedtls_md4_context *ctx, const unsigned char *input, s ...@@ -238,7 +246,10 @@ void mbedtls_md4_update( mbedtls_md4_context *ctx, const unsigned char *input, s
{ {
memcpy( (void *) (ctx->buffer + left), memcpy( (void *) (ctx->buffer + left),
(void *) input, fill ); (void *) input, fill );
mbedtls_md4_process( ctx, ctx->buffer );
if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 )
return( ret );
input += fill; input += fill;
ilen -= fill; ilen -= fill;
left = 0; left = 0;
...@@ -246,7 +257,9 @@ void mbedtls_md4_update( mbedtls_md4_context *ctx, const unsigned char *input, s ...@@ -246,7 +257,9 @@ void mbedtls_md4_update( mbedtls_md4_context *ctx, const unsigned char *input, s
while( ilen >= 64 ) while( ilen >= 64 )
{ {
mbedtls_md4_process( ctx, input ); if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 )
return( ret );
input += 64; input += 64;
ilen -= 64; ilen -= 64;
} }
...@@ -256,6 +269,8 @@ void mbedtls_md4_update( mbedtls_md4_context *ctx, const unsigned char *input, s ...@@ -256,6 +269,8 @@ void mbedtls_md4_update( mbedtls_md4_context *ctx, const unsigned char *input, s
memcpy( (void *) (ctx->buffer + left), memcpy( (void *) (ctx->buffer + left),
(void *) input, ilen ); (void *) input, ilen );
} }
return( 0 );
} }
static const unsigned char md4_padding[64] = static const unsigned char md4_padding[64] =
...@@ -269,8 +284,10 @@ static const unsigned char md4_padding[64] = ...@@ -269,8 +284,10 @@ static const unsigned char md4_padding[64] =
/* /*
* MD4 final digest * MD4 final digest
*/ */
void mbedtls_md4_finish( mbedtls_md4_context *ctx, unsigned char output[16] ) int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx,
unsigned char output[16] )
{ {
int ret;
uint32_t last, padn; uint32_t last, padn;
uint32_t high, low; uint32_t high, low;
unsigned char msglen[8]; unsigned char msglen[8];
...@@ -285,13 +302,20 @@ void mbedtls_md4_finish( mbedtls_md4_context *ctx, unsigned char output[16] ) ...@@ -285,13 +302,20 @@ void mbedtls_md4_finish( mbedtls_md4_context *ctx, unsigned char output[16] )
last = ctx->total[0] & 0x3F; last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
mbedtls_md4_update( ctx, (unsigned char *) md4_padding, padn ); ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn );
mbedtls_md4_update( ctx, msglen, 8 ); if( ret != 0 )
return( ret );
if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 )
return( ret );
PUT_UINT32_LE( ctx->state[0], output, 0 ); PUT_UINT32_LE( ctx->state[0], output, 0 );
PUT_UINT32_LE( ctx->state[1], output, 4 ); PUT_UINT32_LE( ctx->state[1], output, 4 );
PUT_UINT32_LE( ctx->state[2], output, 8 ); PUT_UINT32_LE( ctx->state[2], output, 8 );
PUT_UINT32_LE( ctx->state[3], output, 12 ); PUT_UINT32_LE( ctx->state[3], output, 12 );
return( 0 );
} }
#endif /* !MBEDTLS_MD4_ALT */ #endif /* !MBEDTLS_MD4_ALT */
...@@ -299,15 +323,28 @@ void mbedtls_md4_finish( mbedtls_md4_context *ctx, unsigned char output[16] ) ...@@ -299,15 +323,28 @@ void mbedtls_md4_finish( mbedtls_md4_context *ctx, unsigned char output[16] )
/* /*
* output = MD4( input buffer ) * output = MD4( input buffer )
*/ */
void mbedtls_md4( const unsigned char *input, size_t ilen, unsigned char output[16] ) int mbedtls_md4_ret( const unsigned char *input,
size_t ilen,
unsigned char output[16] )
{ {
int ret;
mbedtls_md4_context ctx; mbedtls_md4_context ctx;
mbedtls_md4_init( &ctx ); mbedtls_md4_init( &ctx );
mbedtls_md4_starts( &ctx );
mbedtls_md4_update( &ctx, input, ilen ); if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 )
mbedtls_md4_finish( &ctx, output ); goto exit;
if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 )
goto exit;
exit:
mbedtls_md4_free( &ctx ); mbedtls_md4_free( &ctx );
return( ret );
} }
#if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_SELF_TEST)
...@@ -315,7 +352,7 @@ void mbedtls_md4( const unsigned char *input, size_t ilen, unsigned char output[ ...@@ -315,7 +352,7 @@ void mbedtls_md4( const unsigned char *input, size_t ilen, unsigned char output[
/* /*
* RFC 1320 test vectors * RFC 1320 test vectors
*/ */
static const char md4_test_str[7][81] = static const unsigned char md4_test_str[7][81] =
{ {
{ "" }, { "" },
{ "a" }, { "a" },
...@@ -323,10 +360,15 @@ static const char md4_test_str[7][81] = ...@@ -323,10 +360,15 @@ static const char md4_test_str[7][81] =
{ "message digest" }, { "message digest" },
{ "abcdefghijklmnopqrstuvwxyz" }, { "abcdefghijklmnopqrstuvwxyz" },
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
{ "12345678901234567890123456789012345678901234567890123456789012" \ { "12345678901234567890123456789012345678901234567890123456789012"
"345678901234567890" } "345678901234567890" }
}; };
static const size_t md4_test_strlen[7] =
{
0, 1, 3, 14, 26, 62, 80
};
static const unsigned char md4_test_sum[7][16] = static const unsigned char md4_test_sum[7][16] =
{ {
{ 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31, { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
...@@ -350,7 +392,7 @@ static const unsigned char md4_test_sum[7][16] = ...@@ -350,7 +392,7 @@ static const unsigned char md4_test_sum[7][16] =
*/ */
int mbedtls_md4_self_test( int verbose ) int mbedtls_md4_self_test( int verbose )
{ {
int i; int i, ret = 0;
unsigned char md4sum[16]; unsigned char md4sum[16];
for( i = 0; i < 7; i++ ) for( i = 0; i < 7; i++ )
...@@ -358,15 +400,14 @@ int mbedtls_md4_self_test( int verbose ) ...@@ -358,15 +400,14 @@ int mbedtls_md4_self_test( int verbose )
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( " MD4 test #%d: ", i + 1 ); mbedtls_printf( " MD4 test #%d: ", i + 1 );
mbedtls_md4( (unsigned char *) md4_test_str[i], ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum );
strlen( md4_test_str[i] ), md4sum ); if( ret != 0 )
goto fail;
if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 ) if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
{ {
if( verbose != 0 ) ret = 1;
mbedtls_printf( "failed\n" ); goto fail;
return( 1 );
} }
if( verbose != 0 ) if( verbose != 0 )
...@@ -377,6 +418,12 @@ int mbedtls_md4_self_test( int verbose ) ...@@ -377,6 +418,12 @@ int mbedtls_md4_self_test( int verbose )
mbedtls_printf( "\n" ); mbedtls_printf( "\n" );
return( 0 ); return( 0 );
fail:
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( ret );
} }
#endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SELF_TEST */
......
...@@ -97,7 +97,7 @@ void mbedtls_md5_clone( mbedtls_md5_context *dst, ...@@ -97,7 +97,7 @@ void mbedtls_md5_clone( mbedtls_md5_context *dst,
/* /*
* MD5 context setup * MD5 context setup
*/ */
void mbedtls_md5_starts( mbedtls_md5_context *ctx ) int mbedtls_md5_starts_ret( mbedtls_md5_context *ctx )
{ {
ctx->total[0] = 0; ctx->total[0] = 0;
ctx->total[1] = 0; ctx->total[1] = 0;
...@@ -106,10 +106,13 @@ void mbedtls_md5_starts( mbedtls_md5_context *ctx ) ...@@ -106,10 +106,13 @@ void mbedtls_md5_starts( mbedtls_md5_context *ctx )
ctx->state[1] = 0xEFCDAB89; ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE; ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476; ctx->state[3] = 0x10325476;
return( 0 );
} }
#if !defined(MBEDTLS_MD5_PROCESS_ALT) #if !defined(MBEDTLS_MD5_PROCESS_ALT)
void mbedtls_md5_process( mbedtls_md5_context *ctx, const unsigned char data[64] ) int mbedtls_internal_md5_process( mbedtls_md5_context *ctx,
const unsigned char data[64] )
{ {
uint32_t X[16], A, B, C, D; uint32_t X[16], A, B, C, D;
...@@ -230,19 +233,24 @@ void mbedtls_md5_process( mbedtls_md5_context *ctx, const unsigned char data[64] ...@@ -230,19 +233,24 @@ void mbedtls_md5_process( mbedtls_md5_context *ctx, const unsigned char data[64]
ctx->state[1] += B; ctx->state[1] += B;
ctx->state[2] += C; ctx->state[2] += C;
ctx->state[3] += D; ctx->state[3] += D;
return( 0 );
} }
#endif /* !MBEDTLS_MD5_PROCESS_ALT */ #endif /* !MBEDTLS_MD5_PROCESS_ALT */
/* /*
* MD5 process buffer * MD5 process buffer
*/ */
void mbedtls_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen ) int mbedtls_md5_update_ret( mbedtls_md5_context *ctx,
const unsigned char *input,
size_t ilen )
{ {
int ret;
size_t fill; size_t fill;
uint32_t left; uint32_t left;
if( ilen == 0 ) if( ilen == 0 )
return; return( 0 );
left = ctx->total[0] & 0x3F; left = ctx->total[0] & 0x3F;
fill = 64 - left; fill = 64 - left;
...@@ -256,7 +264,9 @@ void mbedtls_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, s ...@@ -256,7 +264,9 @@ void mbedtls_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, s
if( left && ilen >= fill ) if( left && ilen >= fill )
{ {
memcpy( (void *) (ctx->buffer + left), input, fill ); memcpy( (void *) (ctx->buffer + left), input, fill );
mbedtls_md5_process( ctx, ctx->buffer ); if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 )
return( ret );
input += fill; input += fill;
ilen -= fill; ilen -= fill;
left = 0; left = 0;
...@@ -264,7 +274,9 @@ void mbedtls_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, s ...@@ -264,7 +274,9 @@ void mbedtls_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, s
while( ilen >= 64 ) while( ilen >= 64 )
{ {
mbedtls_md5_process( ctx, input ); if( ( ret = mbedtls_internal_md5_process( ctx, input ) ) != 0 )
return( ret );
input += 64; input += 64;
ilen -= 64; ilen -= 64;
} }
...@@ -273,6 +285,8 @@ void mbedtls_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, s ...@@ -273,6 +285,8 @@ void mbedtls_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, s
{ {
memcpy( (void *) (ctx->buffer + left), input, ilen ); memcpy( (void *) (ctx->buffer + left), input, ilen );
} }
return( 0 );
} }
static const unsigned char md5_padding[64] = static const unsigned char md5_padding[64] =
...@@ -286,8 +300,10 @@ static const unsigned char md5_padding[64] = ...@@ -286,8 +300,10 @@ static const unsigned char md5_padding[64] =
/* /*
* MD5 final digest * MD5 final digest
*/ */
void mbedtls_md5_finish( mbedtls_md5_context *ctx, unsigned char output[16] ) int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx,
unsigned char output[16] )
{ {
int ret;
uint32_t last, padn; uint32_t last, padn;
uint32_t high, low; uint32_t high, low;
unsigned char msglen[8]; unsigned char msglen[8];
...@@ -302,13 +318,18 @@ void mbedtls_md5_finish( mbedtls_md5_context *ctx, unsigned char output[16] ) ...@@ -302,13 +318,18 @@ void mbedtls_md5_finish( mbedtls_md5_context *ctx, unsigned char output[16] )
last = ctx->total[0] & 0x3F; last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
mbedtls_md5_update( ctx, md5_padding, padn ); if( ( ret = mbedtls_md5_update_ret( ctx, md5_padding, padn ) ) != 0 )
mbedtls_md5_update( ctx, msglen, 8 ); return( ret );
if( ( ret = mbedtls_md5_update_ret( ctx, msglen, 8 ) ) != 0 )
return( ret );
PUT_UINT32_LE( ctx->state[0], output, 0 ); PUT_UINT32_LE( ctx->state[0], output, 0 );
PUT_UINT32_LE( ctx->state[1], output, 4 ); PUT_UINT32_LE( ctx->state[1], output, 4 );
PUT_UINT32_LE( ctx->state[2], output, 8 ); PUT_UINT32_LE( ctx->state[2], output, 8 );
PUT_UINT32_LE( ctx->state[3], output, 12 ); PUT_UINT32_LE( ctx->state[3], output, 12 );
return( 0 );
} }
#endif /* !MBEDTLS_MD5_ALT */ #endif /* !MBEDTLS_MD5_ALT */
...@@ -316,15 +337,28 @@ void mbedtls_md5_finish( mbedtls_md5_context *ctx, unsigned char output[16] ) ...@@ -316,15 +337,28 @@ void mbedtls_md5_finish( mbedtls_md5_context *ctx, unsigned char output[16] )
/* /*
* output = MD5( input buffer ) * output = MD5( input buffer )
*/ */
void mbedtls_md5( const unsigned char *input, size_t ilen, unsigned char output[16] ) int mbedtls_md5_ret( const unsigned char *input,
size_t ilen,
unsigned char output[16] )
{ {
int ret;
mbedtls_md5_context ctx; mbedtls_md5_context ctx;
mbedtls_md5_init( &ctx ); mbedtls_md5_init( &ctx );
mbedtls_md5_starts( &ctx );
mbedtls_md5_update( &ctx, input, ilen ); if( ( ret = mbedtls_md5_starts_ret( &ctx ) ) != 0 )
mbedtls_md5_finish( &ctx, output ); goto exit;
if( ( ret = mbedtls_md5_update_ret( &ctx, input, ilen ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md5_finish_ret( &ctx, output ) ) != 0 )
goto exit;
exit:
mbedtls_md5_free( &ctx ); mbedtls_md5_free( &ctx );
return( ret );
} }
#if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_SELF_TEST)
...@@ -339,11 +373,11 @@ static const unsigned char md5_test_buf[7][81] = ...@@ -339,11 +373,11 @@ static const unsigned char md5_test_buf[7][81] =
{ "message digest" }, { "message digest" },
{ "abcdefghijklmnopqrstuvwxyz" }, { "abcdefghijklmnopqrstuvwxyz" },
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
{ "12345678901234567890123456789012345678901234567890123456789012" \ { "12345678901234567890123456789012345678901234567890123456789012"
"345678901234567890" } "345678901234567890" }
}; };
static const int md5_test_buflen[7] = static const size_t md5_test_buflen[7] =
{ {
0, 1, 3, 14, 26, 62, 80 0, 1, 3, 14, 26, 62, 80
}; };
...@@ -371,7 +405,7 @@ static const unsigned char md5_test_sum[7][16] = ...@@ -371,7 +405,7 @@ static const unsigned char md5_test_sum[7][16] =
*/ */
int mbedtls_md5_self_test( int verbose ) int mbedtls_md5_self_test( int verbose )
{ {
int i; int i, ret = 0;
unsigned char md5sum[16]; unsigned char md5sum[16];
for( i = 0; i < 7; i++ ) for( i = 0; i < 7; i++ )
...@@ -379,14 +413,14 @@ int mbedtls_md5_self_test( int verbose ) ...@@ -379,14 +413,14 @@ int mbedtls_md5_self_test( int verbose )
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( " MD5 test #%d: ", i + 1 ); mbedtls_printf( " MD5 test #%d: ", i + 1 );
mbedtls_md5( md5_test_buf[i], md5_test_buflen[i], md5sum ); ret = mbedtls_md5_ret( md5_test_buf[i], md5_test_buflen[i], md5sum );
if( ret != 0 )
goto fail;
if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 ) if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 )
{ {
if( verbose != 0 ) ret = 1;
mbedtls_printf( "failed\n" ); goto fail;
return( 1 );
} }
if( verbose != 0 ) if( verbose != 0 )
...@@ -397,6 +431,12 @@ int mbedtls_md5_self_test( int verbose ) ...@@ -397,6 +431,12 @@ int mbedtls_md5_self_test( int verbose )
mbedtls_printf( "\n" ); mbedtls_printf( "\n" );
return( 0 ); return( 0 );
fail:
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( ret );
} }
#endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SELF_TEST */
......
...@@ -71,20 +71,20 @@ ...@@ -71,20 +71,20 @@
#if defined(MBEDTLS_MD2_C) #if defined(MBEDTLS_MD2_C)
static void md2_starts_wrap( void *ctx ) static int md2_starts_wrap( void *ctx )
{ {
mbedtls_md2_starts( (mbedtls_md2_context *) ctx ); return( mbedtls_md2_starts_ret( (mbedtls_md2_context *) ctx ) );
} }
static void md2_update_wrap( void *ctx, const unsigned char *input, static int md2_update_wrap( void *ctx, const unsigned char *input,
size_t ilen ) size_t ilen )
{ {
mbedtls_md2_update( (mbedtls_md2_context *) ctx, input, ilen ); return( mbedtls_md2_update_ret( (mbedtls_md2_context *) ctx, input, ilen ) );
} }
static void md2_finish_wrap( void *ctx, unsigned char *output ) static int md2_finish_wrap( void *ctx, unsigned char *output )
{ {
mbedtls_md2_finish( (mbedtls_md2_context *) ctx, output ); return( mbedtls_md2_finish_ret( (mbedtls_md2_context *) ctx, output ) );
} }
static void *md2_ctx_alloc( void ) static void *md2_ctx_alloc( void )
...@@ -109,11 +109,11 @@ static void md2_clone_wrap( void *dst, const void *src ) ...@@ -109,11 +109,11 @@ static void md2_clone_wrap( void *dst, const void *src )
(const mbedtls_md2_context *) src ); (const mbedtls_md2_context *) src );
} }
static void md2_process_wrap( void *ctx, const unsigned char *data ) static int md2_process_wrap( void *ctx, const unsigned char *data )
{ {
((void) data); ((void) data);
mbedtls_md2_process( (mbedtls_md2_context *) ctx ); return( mbedtls_internal_md2_process( (mbedtls_md2_context *) ctx ) );
} }
const mbedtls_md_info_t mbedtls_md2_info = { const mbedtls_md_info_t mbedtls_md2_info = {
...@@ -124,7 +124,7 @@ const mbedtls_md_info_t mbedtls_md2_info = { ...@@ -124,7 +124,7 @@ const mbedtls_md_info_t mbedtls_md2_info = {
md2_starts_wrap, md2_starts_wrap,
md2_update_wrap, md2_update_wrap,
md2_finish_wrap, md2_finish_wrap,
mbedtls_md2, mbedtls_md2_ret,
md2_ctx_alloc, md2_ctx_alloc,
md2_ctx_free, md2_ctx_free,
md2_clone_wrap, md2_clone_wrap,
...@@ -135,20 +135,20 @@ const mbedtls_md_info_t mbedtls_md2_info = { ...@@ -135,20 +135,20 @@ const mbedtls_md_info_t mbedtls_md2_info = {
#if defined(MBEDTLS_MD4_C) #if defined(MBEDTLS_MD4_C)
static void md4_starts_wrap( void *ctx ) static int md4_starts_wrap( void *ctx )
{ {
mbedtls_md4_starts( (mbedtls_md4_context *) ctx ); return( mbedtls_md4_starts_ret( (mbedtls_md4_context *) ctx ) );
} }
static void md4_update_wrap( void *ctx, const unsigned char *input, static int md4_update_wrap( void *ctx, const unsigned char *input,
size_t ilen ) size_t ilen )
{ {
mbedtls_md4_update( (mbedtls_md4_context *) ctx, input, ilen ); return( mbedtls_md4_update_ret( (mbedtls_md4_context *) ctx, input, ilen ) );
} }
static void md4_finish_wrap( void *ctx, unsigned char *output ) static int md4_finish_wrap( void *ctx, unsigned char *output )
{ {
mbedtls_md4_finish( (mbedtls_md4_context *) ctx, output ); return( mbedtls_md4_finish_ret( (mbedtls_md4_context *) ctx, output ) );
} }
static void *md4_ctx_alloc( void ) static void *md4_ctx_alloc( void )
...@@ -170,12 +170,12 @@ static void md4_ctx_free( void *ctx ) ...@@ -170,12 +170,12 @@ static void md4_ctx_free( void *ctx )
static void md4_clone_wrap( void *dst, const void *src ) static void md4_clone_wrap( void *dst, const void *src )
{ {
mbedtls_md4_clone( (mbedtls_md4_context *) dst, mbedtls_md4_clone( (mbedtls_md4_context *) dst,
(const mbedtls_md4_context *) src ); (const mbedtls_md4_context *) src );
} }
static void md4_process_wrap( void *ctx, const unsigned char *data ) static int md4_process_wrap( void *ctx, const unsigned char *data )
{ {
mbedtls_md4_process( (mbedtls_md4_context *) ctx, data ); return( mbedtls_internal_md4_process( (mbedtls_md4_context *) ctx, data ) );
} }
const mbedtls_md_info_t mbedtls_md4_info = { const mbedtls_md_info_t mbedtls_md4_info = {
...@@ -186,7 +186,7 @@ const mbedtls_md_info_t mbedtls_md4_info = { ...@@ -186,7 +186,7 @@ const mbedtls_md_info_t mbedtls_md4_info = {
md4_starts_wrap, md4_starts_wrap,
md4_update_wrap, md4_update_wrap,
md4_finish_wrap, md4_finish_wrap,
mbedtls_md4, mbedtls_md4_ret,
md4_ctx_alloc, md4_ctx_alloc,
md4_ctx_free, md4_ctx_free,
md4_clone_wrap, md4_clone_wrap,
...@@ -197,20 +197,20 @@ const mbedtls_md_info_t mbedtls_md4_info = { ...@@ -197,20 +197,20 @@ const mbedtls_md_info_t mbedtls_md4_info = {
#if defined(MBEDTLS_MD5_C) #if defined(MBEDTLS_MD5_C)
static void md5_starts_wrap( void *ctx ) static int md5_starts_wrap( void *ctx )
{ {
mbedtls_md5_starts( (mbedtls_md5_context *) ctx ); return( mbedtls_md5_starts_ret( (mbedtls_md5_context *) ctx ) );
} }
static void md5_update_wrap( void *ctx, const unsigned char *input, static int md5_update_wrap( void *ctx, const unsigned char *input,
size_t ilen ) size_t ilen )
{ {
mbedtls_md5_update( (mbedtls_md5_context *) ctx, input, ilen ); return( mbedtls_md5_update_ret( (mbedtls_md5_context *) ctx, input, ilen ) );
} }
static void md5_finish_wrap( void *ctx, unsigned char *output ) static int md5_finish_wrap( void *ctx, unsigned char *output )
{ {
mbedtls_md5_finish( (mbedtls_md5_context *) ctx, output ); return( mbedtls_md5_finish_ret( (mbedtls_md5_context *) ctx, output ) );
} }
static void *md5_ctx_alloc( void ) static void *md5_ctx_alloc( void )
...@@ -232,12 +232,12 @@ static void md5_ctx_free( void *ctx ) ...@@ -232,12 +232,12 @@ static void md5_ctx_free( void *ctx )
static void md5_clone_wrap( void *dst, const void *src ) static void md5_clone_wrap( void *dst, const void *src )
{ {
mbedtls_md5_clone( (mbedtls_md5_context *) dst, mbedtls_md5_clone( (mbedtls_md5_context *) dst,
(const mbedtls_md5_context *) src ); (const mbedtls_md5_context *) src );
} }
static void md5_process_wrap( void *ctx, const unsigned char *data ) static int md5_process_wrap( void *ctx, const unsigned char *data )
{ {
mbedtls_md5_process( (mbedtls_md5_context *) ctx, data ); return( mbedtls_internal_md5_process( (mbedtls_md5_context *) ctx, data ) );
} }
const mbedtls_md_info_t mbedtls_md5_info = { const mbedtls_md_info_t mbedtls_md5_info = {
...@@ -248,7 +248,7 @@ const mbedtls_md_info_t mbedtls_md5_info = { ...@@ -248,7 +248,7 @@ const mbedtls_md_info_t mbedtls_md5_info = {
md5_starts_wrap, md5_starts_wrap,
md5_update_wrap, md5_update_wrap,
md5_finish_wrap, md5_finish_wrap,
mbedtls_md5, mbedtls_md5_ret,
md5_ctx_alloc, md5_ctx_alloc,
md5_ctx_free, md5_ctx_free,
md5_clone_wrap, md5_clone_wrap,
...@@ -259,20 +259,22 @@ const mbedtls_md_info_t mbedtls_md5_info = { ...@@ -259,20 +259,22 @@ const mbedtls_md_info_t mbedtls_md5_info = {
#if defined(MBEDTLS_RIPEMD160_C) #if defined(MBEDTLS_RIPEMD160_C)
static void ripemd160_starts_wrap( void *ctx ) static int ripemd160_starts_wrap( void *ctx )
{ {
mbedtls_ripemd160_starts( (mbedtls_ripemd160_context *) ctx ); return( mbedtls_ripemd160_starts_ret( (mbedtls_ripemd160_context *) ctx ) );
} }
static void ripemd160_update_wrap( void *ctx, const unsigned char *input, static int ripemd160_update_wrap( void *ctx, const unsigned char *input,
size_t ilen ) size_t ilen )
{ {
mbedtls_ripemd160_update( (mbedtls_ripemd160_context *) ctx, input, ilen ); return( mbedtls_ripemd160_update_ret( (mbedtls_ripemd160_context *) ctx,
input, ilen ) );
} }
static void ripemd160_finish_wrap( void *ctx, unsigned char *output ) static int ripemd160_finish_wrap( void *ctx, unsigned char *output )
{ {
mbedtls_ripemd160_finish( (mbedtls_ripemd160_context *) ctx, output ); return( mbedtls_ripemd160_finish_ret( (mbedtls_ripemd160_context *) ctx,
output ) );
} }
static void *ripemd160_ctx_alloc( void ) static void *ripemd160_ctx_alloc( void )
...@@ -297,9 +299,10 @@ static void ripemd160_clone_wrap( void *dst, const void *src ) ...@@ -297,9 +299,10 @@ static void ripemd160_clone_wrap( void *dst, const void *src )
(const mbedtls_ripemd160_context *) src ); (const mbedtls_ripemd160_context *) src );
} }
static void ripemd160_process_wrap( void *ctx, const unsigned char *data ) static int ripemd160_process_wrap( void *ctx, const unsigned char *data )
{ {
mbedtls_ripemd160_process( (mbedtls_ripemd160_context *) ctx, data ); return( mbedtls_internal_ripemd160_process(
(mbedtls_ripemd160_context *) ctx, data ) );
} }
const mbedtls_md_info_t mbedtls_ripemd160_info = { const mbedtls_md_info_t mbedtls_ripemd160_info = {
...@@ -310,7 +313,7 @@ const mbedtls_md_info_t mbedtls_ripemd160_info = { ...@@ -310,7 +313,7 @@ const mbedtls_md_info_t mbedtls_ripemd160_info = {
ripemd160_starts_wrap, ripemd160_starts_wrap,
ripemd160_update_wrap, ripemd160_update_wrap,
ripemd160_finish_wrap, ripemd160_finish_wrap,
mbedtls_ripemd160, mbedtls_ripemd160_ret,
ripemd160_ctx_alloc, ripemd160_ctx_alloc,
ripemd160_ctx_free, ripemd160_ctx_free,
ripemd160_clone_wrap, ripemd160_clone_wrap,
...@@ -321,20 +324,21 @@ const mbedtls_md_info_t mbedtls_ripemd160_info = { ...@@ -321,20 +324,21 @@ const mbedtls_md_info_t mbedtls_ripemd160_info = {
#if defined(MBEDTLS_SHA1_C) #if defined(MBEDTLS_SHA1_C)
static void sha1_starts_wrap( void *ctx ) static int sha1_starts_wrap( void *ctx )
{ {
mbedtls_sha1_starts( (mbedtls_sha1_context *) ctx ); return( mbedtls_sha1_starts_ret( (mbedtls_sha1_context *) ctx ) );
} }
static void sha1_update_wrap( void *ctx, const unsigned char *input, static int sha1_update_wrap( void *ctx, const unsigned char *input,
size_t ilen ) size_t ilen )
{ {
mbedtls_sha1_update( (mbedtls_sha1_context *) ctx, input, ilen ); return( mbedtls_sha1_update_ret( (mbedtls_sha1_context *) ctx,
input, ilen ) );
} }
static void sha1_finish_wrap( void *ctx, unsigned char *output ) static int sha1_finish_wrap( void *ctx, unsigned char *output )
{ {
mbedtls_sha1_finish( (mbedtls_sha1_context *) ctx, output ); return( mbedtls_sha1_finish_ret( (mbedtls_sha1_context *) ctx, output ) );
} }
static void *sha1_ctx_alloc( void ) static void *sha1_ctx_alloc( void )
...@@ -359,9 +363,10 @@ static void sha1_ctx_free( void *ctx ) ...@@ -359,9 +363,10 @@ static void sha1_ctx_free( void *ctx )
mbedtls_free( ctx ); mbedtls_free( ctx );
} }
static void sha1_process_wrap( void *ctx, const unsigned char *data ) static int sha1_process_wrap( void *ctx, const unsigned char *data )
{ {
mbedtls_sha1_process( (mbedtls_sha1_context *) ctx, data ); return( mbedtls_internal_sha1_process( (mbedtls_sha1_context *) ctx,
data ) );
} }
const mbedtls_md_info_t mbedtls_sha1_info = { const mbedtls_md_info_t mbedtls_sha1_info = {
...@@ -372,7 +377,7 @@ const mbedtls_md_info_t mbedtls_sha1_info = { ...@@ -372,7 +377,7 @@ const mbedtls_md_info_t mbedtls_sha1_info = {
sha1_starts_wrap, sha1_starts_wrap,
sha1_update_wrap, sha1_update_wrap,
sha1_finish_wrap, sha1_finish_wrap,
mbedtls_sha1, mbedtls_sha1_ret,
sha1_ctx_alloc, sha1_ctx_alloc,
sha1_ctx_free, sha1_ctx_free,
sha1_clone_wrap, sha1_clone_wrap,
...@@ -386,26 +391,28 @@ const mbedtls_md_info_t mbedtls_sha1_info = { ...@@ -386,26 +391,28 @@ const mbedtls_md_info_t mbedtls_sha1_info = {
*/ */
#if defined(MBEDTLS_SHA256_C) #if defined(MBEDTLS_SHA256_C)
static void sha224_starts_wrap( void *ctx ) static int sha224_starts_wrap( void *ctx )
{ {
mbedtls_sha256_starts( (mbedtls_sha256_context *) ctx, 1 ); return( mbedtls_sha256_starts_ret( (mbedtls_sha256_context *) ctx, 1 ) );
} }
static void sha224_update_wrap( void *ctx, const unsigned char *input, static int sha224_update_wrap( void *ctx, const unsigned char *input,
size_t ilen ) size_t ilen )
{ {
mbedtls_sha256_update( (mbedtls_sha256_context *) ctx, input, ilen ); return( mbedtls_sha256_update_ret( (mbedtls_sha256_context *) ctx,
input, ilen ) );
} }
static void sha224_finish_wrap( void *ctx, unsigned char *output ) static int sha224_finish_wrap( void *ctx, unsigned char *output )
{ {
mbedtls_sha256_finish( (mbedtls_sha256_context *) ctx, output ); return( mbedtls_sha256_finish_ret( (mbedtls_sha256_context *) ctx,
output ) );
} }
static void sha224_wrap( const unsigned char *input, size_t ilen, static int sha224_wrap( const unsigned char *input, size_t ilen,
unsigned char *output ) unsigned char *output )
{ {
mbedtls_sha256( input, ilen, output, 1 ); return( mbedtls_sha256_ret( input, ilen, output, 1 ) );
} }
static void *sha224_ctx_alloc( void ) static void *sha224_ctx_alloc( void )
...@@ -430,9 +437,10 @@ static void sha224_clone_wrap( void *dst, const void *src ) ...@@ -430,9 +437,10 @@ static void sha224_clone_wrap( void *dst, const void *src )
(const mbedtls_sha256_context *) src ); (const mbedtls_sha256_context *) src );
} }
static void sha224_process_wrap( void *ctx, const unsigned char *data ) static int sha224_process_wrap( void *ctx, const unsigned char *data )
{ {
mbedtls_sha256_process( (mbedtls_sha256_context *) ctx, data ); return( mbedtls_internal_sha256_process( (mbedtls_sha256_context *) ctx,
data ) );
} }
const mbedtls_md_info_t mbedtls_sha224_info = { const mbedtls_md_info_t mbedtls_sha224_info = {
...@@ -450,15 +458,15 @@ const mbedtls_md_info_t mbedtls_sha224_info = { ...@@ -450,15 +458,15 @@ const mbedtls_md_info_t mbedtls_sha224_info = {
sha224_process_wrap, sha224_process_wrap,
}; };
static void sha256_starts_wrap( void *ctx ) static int sha256_starts_wrap( void *ctx )
{ {
mbedtls_sha256_starts( (mbedtls_sha256_context *) ctx, 0 ); return( mbedtls_sha256_starts_ret( (mbedtls_sha256_context *) ctx, 0 ) );
} }
static void sha256_wrap( const unsigned char *input, size_t ilen, static int sha256_wrap( const unsigned char *input, size_t ilen,
unsigned char *output ) unsigned char *output )
{ {
mbedtls_sha256( input, ilen, output, 0 ); return( mbedtls_sha256_ret( input, ilen, output, 0 ) );
} }
const mbedtls_md_info_t mbedtls_sha256_info = { const mbedtls_md_info_t mbedtls_sha256_info = {
...@@ -480,26 +488,28 @@ const mbedtls_md_info_t mbedtls_sha256_info = { ...@@ -480,26 +488,28 @@ const mbedtls_md_info_t mbedtls_sha256_info = {
#if defined(MBEDTLS_SHA512_C) #if defined(MBEDTLS_SHA512_C)
static void sha384_starts_wrap( void *ctx ) static int sha384_starts_wrap( void *ctx )
{ {
mbedtls_sha512_starts( (mbedtls_sha512_context *) ctx, 1 ); return( mbedtls_sha512_starts_ret( (mbedtls_sha512_context *) ctx, 1 ) );
} }
static void sha384_update_wrap( void *ctx, const unsigned char *input, static int sha384_update_wrap( void *ctx, const unsigned char *input,
size_t ilen ) size_t ilen )
{ {
mbedtls_sha512_update( (mbedtls_sha512_context *) ctx, input, ilen ); return( mbedtls_sha512_update_ret( (mbedtls_sha512_context *) ctx,
input, ilen ) );
} }
static void sha384_finish_wrap( void *ctx, unsigned char *output ) static int sha384_finish_wrap( void *ctx, unsigned char *output )
{ {
mbedtls_sha512_finish( (mbedtls_sha512_context *) ctx, output ); return( mbedtls_sha512_finish_ret( (mbedtls_sha512_context *) ctx,
output ) );
} }
static void sha384_wrap( const unsigned char *input, size_t ilen, static int sha384_wrap( const unsigned char *input, size_t ilen,
unsigned char *output ) unsigned char *output )
{ {
mbedtls_sha512( input, ilen, output, 1 ); return( mbedtls_sha512_ret( input, ilen, output, 1 ) );
} }
static void *sha384_ctx_alloc( void ) static void *sha384_ctx_alloc( void )
...@@ -524,9 +534,10 @@ static void sha384_clone_wrap( void *dst, const void *src ) ...@@ -524,9 +534,10 @@ static void sha384_clone_wrap( void *dst, const void *src )
(const mbedtls_sha512_context *) src ); (const mbedtls_sha512_context *) src );
} }
static void sha384_process_wrap( void *ctx, const unsigned char *data ) static int sha384_process_wrap( void *ctx, const unsigned char *data )
{ {
mbedtls_sha512_process( (mbedtls_sha512_context *) ctx, data ); return( mbedtls_internal_sha512_process( (mbedtls_sha512_context *) ctx,
data ) );
} }
const mbedtls_md_info_t mbedtls_sha384_info = { const mbedtls_md_info_t mbedtls_sha384_info = {
...@@ -544,15 +555,15 @@ const mbedtls_md_info_t mbedtls_sha384_info = { ...@@ -544,15 +555,15 @@ const mbedtls_md_info_t mbedtls_sha384_info = {
sha384_process_wrap, sha384_process_wrap,
}; };
static void sha512_starts_wrap( void *ctx ) static int sha512_starts_wrap( void *ctx )
{ {
mbedtls_sha512_starts( (mbedtls_sha512_context *) ctx, 0 ); return( mbedtls_sha512_starts_ret( (mbedtls_sha512_context *) ctx, 0 ) );
} }
static void sha512_wrap( const unsigned char *input, size_t ilen, static int sha512_wrap( const unsigned char *input, size_t ilen,
unsigned char *output ) unsigned char *output )
{ {
mbedtls_sha512( input, ilen, output, 0 ); return( mbedtls_sha512_ret( input, ilen, output, 0 ) );
} }
const mbedtls_md_info_t mbedtls_sha512_info = { const mbedtls_md_info_t mbedtls_sha512_info = {
......
...@@ -82,31 +82,33 @@ static int pem_get_iv( const unsigned char *s, unsigned char *iv, ...@@ -82,31 +82,33 @@ static int pem_get_iv( const unsigned char *s, unsigned char *iv,
return( 0 ); return( 0 );
} }
static void pem_pbkdf1( unsigned char *key, size_t keylen, static int pem_pbkdf1( unsigned char *key, size_t keylen,
unsigned char *iv, unsigned char *iv,
const unsigned char *pwd, size_t pwdlen ) const unsigned char *pwd, size_t pwdlen )
{ {
mbedtls_md5_context md5_ctx; mbedtls_md5_context md5_ctx;
unsigned char md5sum[16]; unsigned char md5sum[16];
size_t use_len; size_t use_len;
int ret;
mbedtls_md5_init( &md5_ctx ); mbedtls_md5_init( &md5_ctx );
/* /*
* key[ 0..15] = MD5(pwd || IV) * key[ 0..15] = MD5(pwd || IV)
*/ */
mbedtls_md5_starts( &md5_ctx ); if( ( ret = mbedtls_md5_starts_ret( &md5_ctx ) ) != 0 )
mbedtls_md5_update( &md5_ctx, pwd, pwdlen ); goto exit;
mbedtls_md5_update( &md5_ctx, iv, 8 ); if( ( ret = mbedtls_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 )
mbedtls_md5_finish( &md5_ctx, md5sum ); goto exit;
if( ( ret = mbedtls_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 )
goto exit;
if( keylen <= 16 ) if( keylen <= 16 )
{ {
memcpy( key, md5sum, keylen ); memcpy( key, md5sum, keylen );
goto exit;
mbedtls_md5_free( &md5_ctx );
mbedtls_zeroize( md5sum, 16 );
return;
} }
memcpy( key, md5sum, 16 ); memcpy( key, md5sum, 16 );
...@@ -114,11 +116,16 @@ static void pem_pbkdf1( unsigned char *key, size_t keylen, ...@@ -114,11 +116,16 @@ static void pem_pbkdf1( unsigned char *key, size_t keylen,
/* /*
* key[16..23] = MD5(key[ 0..15] || pwd || IV]) * key[16..23] = MD5(key[ 0..15] || pwd || IV])
*/ */
mbedtls_md5_starts( &md5_ctx ); if( ( ret = mbedtls_md5_starts_ret( &md5_ctx ) ) != 0 )
mbedtls_md5_update( &md5_ctx, md5sum, 16 ); goto exit;
mbedtls_md5_update( &md5_ctx, pwd, pwdlen ); if( ( ret = mbedtls_md5_update_ret( &md5_ctx, md5sum, 16 ) ) != 0 )
mbedtls_md5_update( &md5_ctx, iv, 8 ); goto exit;
mbedtls_md5_finish( &md5_ctx, md5sum ); if( ( ret = mbedtls_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 )
goto exit;
use_len = 16; use_len = 16;
if( keylen < 32 ) if( keylen < 32 )
...@@ -126,53 +133,68 @@ static void pem_pbkdf1( unsigned char *key, size_t keylen, ...@@ -126,53 +133,68 @@ static void pem_pbkdf1( unsigned char *key, size_t keylen,
memcpy( key + 16, md5sum, use_len ); memcpy( key + 16, md5sum, use_len );
exit:
mbedtls_md5_free( &md5_ctx ); mbedtls_md5_free( &md5_ctx );
mbedtls_zeroize( md5sum, 16 ); mbedtls_zeroize( md5sum, 16 );
return( ret );
} }
#if defined(MBEDTLS_DES_C) #if defined(MBEDTLS_DES_C)
/* /*
* Decrypt with DES-CBC, using PBKDF1 for key derivation * Decrypt with DES-CBC, using PBKDF1 for key derivation
*/ */
static void pem_des_decrypt( unsigned char des_iv[8], static int pem_des_decrypt( unsigned char des_iv[8],
unsigned char *buf, size_t buflen, unsigned char *buf, size_t buflen,
const unsigned char *pwd, size_t pwdlen ) const unsigned char *pwd, size_t pwdlen )
{ {
mbedtls_des_context des_ctx; mbedtls_des_context des_ctx;
unsigned char des_key[8]; unsigned char des_key[8];
int ret;
mbedtls_des_init( &des_ctx ); mbedtls_des_init( &des_ctx );
pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ); if( ( ret = pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ) ) != 0 )
goto exit;
mbedtls_des_setkey_dec( &des_ctx, des_key ); if( ( ret = mbedtls_des_setkey_dec( &des_ctx, des_key ) ) != 0 )
mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen, goto exit;
ret = mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen,
des_iv, buf, buf ); des_iv, buf, buf );
exit:
mbedtls_des_free( &des_ctx ); mbedtls_des_free( &des_ctx );
mbedtls_zeroize( des_key, 8 ); mbedtls_zeroize( des_key, 8 );
return( ret );
} }
/* /*
* Decrypt with 3DES-CBC, using PBKDF1 for key derivation * Decrypt with 3DES-CBC, using PBKDF1 for key derivation
*/ */
static void pem_des3_decrypt( unsigned char des3_iv[8], static int pem_des3_decrypt( unsigned char des3_iv[8],
unsigned char *buf, size_t buflen, unsigned char *buf, size_t buflen,
const unsigned char *pwd, size_t pwdlen ) const unsigned char *pwd, size_t pwdlen )
{ {
mbedtls_des3_context des3_ctx; mbedtls_des3_context des3_ctx;
unsigned char des3_key[24]; unsigned char des3_key[24];
int ret;
mbedtls_des3_init( &des3_ctx ); mbedtls_des3_init( &des3_ctx );
pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ); if( ( ret = pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ) ) != 0 )
goto exit;
mbedtls_des3_set3key_dec( &des3_ctx, des3_key ); if( ( ret = mbedtls_des3_set3key_dec( &des3_ctx, des3_key ) ) != 0 )
mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen, goto exit;
ret = mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen,
des3_iv, buf, buf ); des3_iv, buf, buf );
exit:
mbedtls_des3_free( &des3_ctx ); mbedtls_des3_free( &des3_ctx );
mbedtls_zeroize( des3_key, 24 ); mbedtls_zeroize( des3_key, 24 );
return( ret );
} }
#endif /* MBEDTLS_DES_C */ #endif /* MBEDTLS_DES_C */
...@@ -180,23 +202,29 @@ static void pem_des3_decrypt( unsigned char des3_iv[8], ...@@ -180,23 +202,29 @@ static void pem_des3_decrypt( unsigned char des3_iv[8],
/* /*
* Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation
*/ */
static void pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen, static int pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen,
unsigned char *buf, size_t buflen, unsigned char *buf, size_t buflen,
const unsigned char *pwd, size_t pwdlen ) const unsigned char *pwd, size_t pwdlen )
{ {
mbedtls_aes_context aes_ctx; mbedtls_aes_context aes_ctx;
unsigned char aes_key[32]; unsigned char aes_key[32];
int ret;
mbedtls_aes_init( &aes_ctx ); mbedtls_aes_init( &aes_ctx );
pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ); if( ( ret = pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ) ) != 0 )
goto exit;
mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ); if( ( ret = mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ) ) != 0 )
mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen, goto exit;
ret = mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen,
aes_iv, buf, buf ); aes_iv, buf, buf );
exit:
mbedtls_aes_free( &aes_ctx ); mbedtls_aes_free( &aes_ctx );
mbedtls_zeroize( aes_key, keylen ); mbedtls_zeroize( aes_key, keylen );
return( ret );
} }
#endif /* MBEDTLS_AES_C */ #endif /* MBEDTLS_AES_C */
...@@ -331,6 +359,7 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const ...@@ -331,6 +359,7 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const
if( ( ret = mbedtls_base64_decode( buf, len, &len, s1, s2 - s1 ) ) != 0 ) if( ( ret = mbedtls_base64_decode( buf, len, &len, s1, s2 - s1 ) ) != 0 )
{ {
mbedtls_zeroize( buf, len );
mbedtls_free( buf ); mbedtls_free( buf );
return( MBEDTLS_ERR_PEM_INVALID_DATA + ret ); return( MBEDTLS_ERR_PEM_INVALID_DATA + ret );
} }
...@@ -341,26 +370,35 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const ...@@ -341,26 +370,35 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const
( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) )
if( pwd == NULL ) if( pwd == NULL )
{ {
mbedtls_zeroize( buf, len );
mbedtls_free( buf ); mbedtls_free( buf );
return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ); return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED );
} }
ret = 0;
#if defined(MBEDTLS_DES_C) #if defined(MBEDTLS_DES_C)
if( enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC ) if( enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC )
pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen ); ret = pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen );
else if( enc_alg == MBEDTLS_CIPHER_DES_CBC ) else if( enc_alg == MBEDTLS_CIPHER_DES_CBC )
pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen ); ret = pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen );
#endif /* MBEDTLS_DES_C */ #endif /* MBEDTLS_DES_C */
#if defined(MBEDTLS_AES_C) #if defined(MBEDTLS_AES_C)
if( enc_alg == MBEDTLS_CIPHER_AES_128_CBC ) if( enc_alg == MBEDTLS_CIPHER_AES_128_CBC )
pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen ); ret = pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen );
else if( enc_alg == MBEDTLS_CIPHER_AES_192_CBC ) else if( enc_alg == MBEDTLS_CIPHER_AES_192_CBC )
pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen ); ret = pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen );
else if( enc_alg == MBEDTLS_CIPHER_AES_256_CBC ) else if( enc_alg == MBEDTLS_CIPHER_AES_256_CBC )
pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen ); ret = pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen );
#endif /* MBEDTLS_AES_C */ #endif /* MBEDTLS_AES_C */
if( ret != 0 )
{
mbedtls_free( buf );
return( ret );
}
/* /*
* The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3 * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3
* length bytes (allow 4 to be sure) in all known use cases. * length bytes (allow 4 to be sure) in all known use cases.
...@@ -369,10 +407,12 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const ...@@ -369,10 +407,12 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const
*/ */
if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 ) if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 )
{ {
mbedtls_zeroize( buf, len );
mbedtls_free( buf ); mbedtls_free( buf );
return( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ); return( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH );
} }
#else #else
mbedtls_zeroize( buf, len );
mbedtls_free( buf ); mbedtls_free( buf );
return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE );
#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && #endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC &&
...@@ -387,6 +427,8 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const ...@@ -387,6 +427,8 @@ int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const
void mbedtls_pem_free( mbedtls_pem_context *ctx ) void mbedtls_pem_free( mbedtls_pem_context *ctx )
{ {
if( ctx->buf != NULL )
mbedtls_zeroize( ctx->buf, ctx->buflen );
mbedtls_free( ctx->buf ); mbedtls_free( ctx->buf );
mbedtls_free( ctx->info ); mbedtls_free( ctx->info );
......
...@@ -29,8 +29,6 @@ ...@@ -29,8 +29,6 @@
#include "mbedtls/pk.h" #include "mbedtls/pk.h"
#include "mbedtls/pk_internal.h" #include "mbedtls/pk_internal.h"
#include "mbedtls/bignum.h"
#if defined(MBEDTLS_RSA_C) #if defined(MBEDTLS_RSA_C)
#include "mbedtls/rsa.h" #include "mbedtls/rsa.h"
#endif #endif
...@@ -42,6 +40,7 @@ ...@@ -42,6 +40,7 @@
#endif #endif
#include <limits.h> #include <limits.h>
#include <stdint.h>
/* Implementation that should never be optimized out by the compiler */ /* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) { static void mbedtls_zeroize( void *v, size_t n ) {
...@@ -213,10 +212,10 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, ...@@ -213,10 +212,10 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options,
int ret; int ret;
const mbedtls_pk_rsassa_pss_options *pss_opts; const mbedtls_pk_rsassa_pss_options *pss_opts;
#if defined(MBEDTLS_HAVE_INT64) #if SIZE_MAX > UINT_MAX
if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
#endif /* MBEDTLS_HAVE_INT64 */ #endif /* SIZE_MAX > UINT_MAX */
if( options == NULL ) if( options == NULL )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
/* Even if RSA not activated, for the sake of RSA-alt */ /* Even if RSA not activated, for the sake of RSA-alt */
#include "mbedtls/rsa.h" #include "mbedtls/rsa.h"
#include "mbedtls/bignum.h"
#include <string.h> #include <string.h>
...@@ -51,6 +50,7 @@ ...@@ -51,6 +50,7 @@
#endif #endif
#include <limits.h> #include <limits.h>
#include <stdint.h>
#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
/* Implementation that should never be optimized out by the compiler */ /* Implementation that should never be optimized out by the compiler */
...@@ -68,7 +68,8 @@ static int rsa_can_do( mbedtls_pk_type_t type ) ...@@ -68,7 +68,8 @@ static int rsa_can_do( mbedtls_pk_type_t type )
static size_t rsa_get_bitlen( const void *ctx ) static size_t rsa_get_bitlen( const void *ctx )
{ {
return( 8 * ((const mbedtls_rsa_context *) ctx)->len ); const mbedtls_rsa_context * rsa = (const mbedtls_rsa_context *) ctx;
return( 8 * mbedtls_rsa_get_len( rsa ) );
} }
static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
...@@ -76,21 +77,23 @@ static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, ...@@ -76,21 +77,23 @@ static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg,
const unsigned char *sig, size_t sig_len ) const unsigned char *sig, size_t sig_len )
{ {
int ret; int ret;
mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx;
size_t rsa_len = mbedtls_rsa_get_len( rsa );
#if defined(MBEDTLS_HAVE_INT64) #if SIZE_MAX > UINT_MAX
if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
#endif /* MBEDTLS_HAVE_INT64 */ #endif /* SIZE_MAX > UINT_MAX */
if( sig_len < ((mbedtls_rsa_context *) ctx)->len ) if( sig_len < rsa_len )
return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
if( ( ret = mbedtls_rsa_pkcs1_verify( (mbedtls_rsa_context *) ctx, NULL, NULL, if( ( ret = mbedtls_rsa_pkcs1_verify( rsa, NULL, NULL,
MBEDTLS_RSA_PUBLIC, md_alg, MBEDTLS_RSA_PUBLIC, md_alg,
(unsigned int) hash_len, hash, sig ) ) != 0 ) (unsigned int) hash_len, hash, sig ) ) != 0 )
return( ret ); return( ret );
if( sig_len > ((mbedtls_rsa_context *) ctx)->len ) if( sig_len > rsa_len )
return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH );
return( 0 ); return( 0 );
...@@ -101,14 +104,16 @@ static int rsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, ...@@ -101,14 +104,16 @@ static int rsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
unsigned char *sig, size_t *sig_len, unsigned char *sig, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{ {
#if defined(MBEDTLS_HAVE_INT64) mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx;
#if SIZE_MAX > UINT_MAX
if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
#endif /* MBEDTLS_HAVE_INT64 */ #endif /* SIZE_MAX > UINT_MAX */
*sig_len = ((mbedtls_rsa_context *) ctx)->len; *sig_len = mbedtls_rsa_get_len( rsa );
return( mbedtls_rsa_pkcs1_sign( (mbedtls_rsa_context *) ctx, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, return( mbedtls_rsa_pkcs1_sign( rsa, f_rng, p_rng, MBEDTLS_RSA_PRIVATE,
md_alg, (unsigned int) hash_len, hash, sig ) ); md_alg, (unsigned int) hash_len, hash, sig ) );
} }
...@@ -117,10 +122,12 @@ static int rsa_decrypt_wrap( void *ctx, ...@@ -117,10 +122,12 @@ static int rsa_decrypt_wrap( void *ctx,
unsigned char *output, size_t *olen, size_t osize, unsigned char *output, size_t *olen, size_t osize,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{ {
if( ilen != ((mbedtls_rsa_context *) ctx)->len ) mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx;
if( ilen != mbedtls_rsa_get_len( rsa ) )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
return( mbedtls_rsa_pkcs1_decrypt( (mbedtls_rsa_context *) ctx, f_rng, p_rng, return( mbedtls_rsa_pkcs1_decrypt( rsa, f_rng, p_rng,
MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) ); MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) );
} }
...@@ -129,13 +136,14 @@ static int rsa_encrypt_wrap( void *ctx, ...@@ -129,13 +136,14 @@ static int rsa_encrypt_wrap( void *ctx,
unsigned char *output, size_t *olen, size_t osize, unsigned char *output, size_t *olen, size_t osize,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{ {
*olen = ((mbedtls_rsa_context *) ctx)->len; mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx;
*olen = mbedtls_rsa_get_len( rsa );
if( *olen > osize ) if( *olen > osize )
return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE );
return( mbedtls_rsa_pkcs1_encrypt( (mbedtls_rsa_context *) ctx, return( mbedtls_rsa_pkcs1_encrypt( rsa, f_rng, p_rng, MBEDTLS_RSA_PUBLIC,
f_rng, p_rng, MBEDTLS_RSA_PUBLIC, ilen, input, output ) ); ilen, input, output ) );
} }
static int rsa_check_pair_wrap( const void *pub, const void *prv ) static int rsa_check_pair_wrap( const void *pub, const void *prv )
...@@ -415,10 +423,10 @@ static int rsa_alt_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, ...@@ -415,10 +423,10 @@ static int rsa_alt_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
{ {
mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx;
#if defined(MBEDTLS_HAVE_INT64) #if SIZE_MAX > UINT_MAX
if( UINT_MAX < hash_len ) if( UINT_MAX < hash_len )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
#endif /* MBEDTLS_HAVE_INT64 */ #endif /* SIZE_MAX > UINT_MAX */
*sig_len = rsa_alt->key_len_func( rsa_alt->key ); *sig_len = rsa_alt->key_len_func( rsa_alt->key );
......
...@@ -60,12 +60,15 @@ ...@@ -60,12 +60,15 @@
#define mbedtls_free free #define mbedtls_free free
#endif #endif
#if defined(MBEDTLS_FS_IO) #if defined(MBEDTLS_FS_IO) || \
defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
/* Implementation that should never be optimized out by the compiler */ /* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) { static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = v; while( n-- ) *p++ = 0; volatile unsigned char *p = v; while( n-- ) *p++ = 0;
} }
#endif
#if defined(MBEDTLS_FS_IO)
/* /*
* Load all data from a file into a given buffer. * Load all data from a file into a given buffer.
* *
...@@ -101,7 +104,10 @@ int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ) ...@@ -101,7 +104,10 @@ int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n )
if( fread( *buf, 1, *n, f ) != *n ) if( fread( *buf, 1, *n, f ) != *n )
{ {
fclose( f ); fclose( f );
mbedtls_zeroize( *buf, *n );
mbedtls_free( *buf ); mbedtls_free( *buf );
return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); return( MBEDTLS_ERR_PK_FILE_IO_ERROR );
} }
...@@ -520,18 +526,35 @@ static int pk_get_rsapubkey( unsigned char **p, ...@@ -520,18 +526,35 @@ static int pk_get_rsapubkey( unsigned char **p,
return( MBEDTLS_ERR_PK_INVALID_PUBKEY + return( MBEDTLS_ERR_PK_INVALID_PUBKEY +
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
if( ( ret = mbedtls_asn1_get_mpi( p, end, &rsa->N ) ) != 0 || /* Import N */
( ret = mbedtls_asn1_get_mpi( p, end, &rsa->E ) ) != 0 ) if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret );
if( *p != end ) if( ( ret = mbedtls_rsa_import_raw( rsa, *p, len, NULL, 0, NULL, 0,
return( MBEDTLS_ERR_PK_INVALID_PUBKEY + NULL, 0, NULL, 0 ) ) != 0 )
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); return( MBEDTLS_ERR_PK_INVALID_PUBKEY );
*p += len;
/* Import E */
if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret );
if( ( ret = mbedtls_rsa_check_pubkey( rsa ) ) != 0 ) if( ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0,
NULL, 0, *p, len ) ) != 0 )
return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); return( MBEDTLS_ERR_PK_INVALID_PUBKEY );
rsa->len = mbedtls_mpi_size( &rsa->N ); *p += len;
if( mbedtls_rsa_complete( rsa ) != 0 ||
mbedtls_rsa_check_pubkey( rsa ) != 0 )
{
return( MBEDTLS_ERR_PK_INVALID_PUBKEY );
}
if( *p != end )
return( MBEDTLS_ERR_PK_INVALID_PUBKEY +
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
return( 0 ); return( 0 );
} }
...@@ -643,10 +666,13 @@ static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa, ...@@ -643,10 +666,13 @@ static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa,
const unsigned char *key, const unsigned char *key,
size_t keylen ) size_t keylen )
{ {
int ret; int ret, version;
size_t len; size_t len;
unsigned char *p, *end; unsigned char *p, *end;
mbedtls_mpi T;
mbedtls_mpi_init( &T );
p = (unsigned char *) key; p = (unsigned char *) key;
end = p + keylen; end = p + keylen;
...@@ -674,45 +700,88 @@ static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa, ...@@ -674,45 +700,88 @@ static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa,
end = p + len; end = p + len;
if( ( ret = mbedtls_asn1_get_int( &p, end, &rsa->ver ) ) != 0 ) if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 )
{ {
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
} }
if( rsa->ver != 0 ) if( version != 0 )
{ {
return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION );
} }
if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->N ) ) != 0 || /* Import N */
( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->E ) ) != 0 || if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->D ) ) != 0 || MBEDTLS_ASN1_INTEGER ) ) != 0 ||
( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->P ) ) != 0 || ( ret = mbedtls_rsa_import_raw( rsa, p, len, NULL, 0, NULL, 0,
( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 || NULL, 0, NULL, 0 ) ) != 0 )
( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 || goto cleanup;
( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 || p += len;
( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 )
{ /* Import E */
mbedtls_rsa_free( rsa ); if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); MBEDTLS_ASN1_INTEGER ) ) != 0 ||
} ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0,
NULL, 0, p, len ) ) != 0 )
goto cleanup;
p += len;
rsa->len = mbedtls_mpi_size( &rsa->N ); /* Import D */
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
MBEDTLS_ASN1_INTEGER ) ) != 0 ||
( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0,
p, len, NULL, 0 ) ) != 0 )
goto cleanup;
p += len;
/* Import P */
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
MBEDTLS_ASN1_INTEGER ) ) != 0 ||
( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, p, len, NULL, 0,
NULL, 0, NULL, 0 ) ) != 0 )
goto cleanup;
p += len;
/* Import Q */
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
MBEDTLS_ASN1_INTEGER ) ) != 0 ||
( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, p, len,
NULL, 0, NULL, 0 ) ) != 0 )
goto cleanup;
p += len;
/* Complete the RSA private key */
if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 )
goto cleanup;
/* Check optional parameters */
if( ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 ||
( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 ||
( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 )
goto cleanup;
if( p != end ) if( p != end )
{ {
mbedtls_rsa_free( rsa ); ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ;
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
} }
if( ( ret = mbedtls_rsa_check_privkey( rsa ) ) != 0 ) cleanup:
mbedtls_mpi_free( &T );
if( ret != 0 )
{ {
/* Wrap error code if it's coming from a lower level */
if( ( ret & 0xff80 ) == 0 )
ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret;
else
ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
mbedtls_rsa_free( rsa ); mbedtls_rsa_free( rsa );
return( ret );
} }
return( 0 ); return( ret );
} }
#endif /* MBEDTLS_RSA_C */ #endif /* MBEDTLS_RSA_C */
...@@ -844,6 +913,16 @@ static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck, ...@@ -844,6 +913,16 @@ static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck,
/* /*
* Parse an unencrypted PKCS#8 encoded private key * Parse an unencrypted PKCS#8 encoded private key
*
* Notes:
*
* - This function does not own the key buffer. It is the
* responsibility of the caller to take care of zeroizing
* and freeing it after use.
*
* - The function is responsible for freeing the provided
* PK context on failure.
*
*/ */
static int pk_parse_key_pkcs8_unencrypted_der( static int pk_parse_key_pkcs8_unencrypted_der(
mbedtls_pk_context *pk, mbedtls_pk_context *pk,
...@@ -859,7 +938,7 @@ static int pk_parse_key_pkcs8_unencrypted_der( ...@@ -859,7 +938,7 @@ static int pk_parse_key_pkcs8_unencrypted_der(
const mbedtls_pk_info_t *pk_info; const mbedtls_pk_info_t *pk_info;
/* /*
* This function parses the PrivatKeyInfo object (PKCS#8 v1.2 = RFC 5208) * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208)
* *
* PrivateKeyInfo ::= SEQUENCE { * PrivateKeyInfo ::= SEQUENCE {
* version Version, * version Version,
...@@ -932,16 +1011,22 @@ static int pk_parse_key_pkcs8_unencrypted_der( ...@@ -932,16 +1011,22 @@ static int pk_parse_key_pkcs8_unencrypted_der(
/* /*
* Parse an encrypted PKCS#8 encoded private key * Parse an encrypted PKCS#8 encoded private key
*
* To save space, the decryption happens in-place on the given key buffer.
* Also, while this function may modify the keybuffer, it doesn't own it,
* and instead it is the responsibility of the caller to zeroize and properly
* free it after use.
*
*/ */
#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
static int pk_parse_key_pkcs8_encrypted_der( static int pk_parse_key_pkcs8_encrypted_der(
mbedtls_pk_context *pk, mbedtls_pk_context *pk,
const unsigned char *key, size_t keylen, unsigned char *key, size_t keylen,
const unsigned char *pwd, size_t pwdlen ) const unsigned char *pwd, size_t pwdlen )
{ {
int ret, decrypted = 0; int ret, decrypted = 0;
size_t len; size_t len;
unsigned char buf[2048]; unsigned char *buf;
unsigned char *p, *end; unsigned char *p, *end;
mbedtls_asn1_buf pbe_alg_oid, pbe_params; mbedtls_asn1_buf pbe_alg_oid, pbe_params;
#if defined(MBEDTLS_PKCS12_C) #if defined(MBEDTLS_PKCS12_C)
...@@ -949,16 +1034,14 @@ static int pk_parse_key_pkcs8_encrypted_der( ...@@ -949,16 +1034,14 @@ static int pk_parse_key_pkcs8_encrypted_der(
mbedtls_md_type_t md_alg; mbedtls_md_type_t md_alg;
#endif #endif
memset( buf, 0, sizeof( buf ) ); p = key;
p = (unsigned char *) key;
end = p + keylen; end = p + keylen;
if( pwdlen == 0 ) if( pwdlen == 0 )
return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED );
/* /*
* This function parses the EncryptedPrivatKeyInfo object (PKCS#8) * This function parses the EncryptedPrivateKeyInfo object (PKCS#8)
* *
* EncryptedPrivateKeyInfo ::= SEQUENCE { * EncryptedPrivateKeyInfo ::= SEQUENCE {
* encryptionAlgorithm EncryptionAlgorithmIdentifier, * encryptionAlgorithm EncryptionAlgorithmIdentifier,
...@@ -970,6 +1053,7 @@ static int pk_parse_key_pkcs8_encrypted_der( ...@@ -970,6 +1053,7 @@ static int pk_parse_key_pkcs8_encrypted_der(
* EncryptedData ::= OCTET STRING * EncryptedData ::= OCTET STRING
* *
* The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo
*
*/ */
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
...@@ -985,11 +1069,10 @@ static int pk_parse_key_pkcs8_encrypted_der( ...@@ -985,11 +1069,10 @@ static int pk_parse_key_pkcs8_encrypted_der(
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
if( len > sizeof( buf ) ) buf = p;
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
/* /*
* Decrypt EncryptedData with appropriate PDE * Decrypt EncryptedData with appropriate PBE
*/ */
#if defined(MBEDTLS_PKCS12_C) #if defined(MBEDTLS_PKCS12_C)
if( mbedtls_oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 ) if( mbedtls_oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 )
...@@ -1081,10 +1164,8 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, ...@@ -1081,10 +1164,8 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
if( ret == 0 ) if( ret == 0 )
{ {
if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA );
return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ||
if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ||
( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ),
pem.buf, pem.buflen ) ) != 0 ) pem.buf, pem.buflen ) ) != 0 )
{ {
...@@ -1113,10 +1194,9 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, ...@@ -1113,10 +1194,9 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
key, pwd, pwdlen, &len ); key, pwd, pwdlen, &len );
if( ret == 0 ) if( ret == 0 )
{ {
if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ) ) == NULL ) pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY );
return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ||
( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ),
pem.buf, pem.buflen ) ) != 0 ) pem.buf, pem.buflen ) ) != 0 )
{ {
...@@ -1194,12 +1274,24 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, ...@@ -1194,12 +1274,24 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
* error * error
*/ */
#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, key, keylen,
pwd, pwdlen ) ) == 0 )
{ {
return( 0 ); unsigned char *key_copy;
if( ( key_copy = mbedtls_calloc( 1, keylen ) ) == NULL )
return( MBEDTLS_ERR_PK_ALLOC_FAILED );
memcpy( key_copy, key, keylen );
ret = pk_parse_key_pkcs8_encrypted_der( pk, key_copy, keylen,
pwd, pwdlen );
mbedtls_zeroize( key_copy, keylen );
mbedtls_free( key_copy );
} }
if( ret == 0 )
return( 0 );
mbedtls_pk_free( pk ); mbedtls_pk_free( pk );
if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH ) if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH )
...@@ -1214,29 +1306,35 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk, ...@@ -1214,29 +1306,35 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
mbedtls_pk_free( pk ); mbedtls_pk_free( pk );
#if defined(MBEDTLS_RSA_C) #if defined(MBEDTLS_RSA_C)
if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL )
return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA );
( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) ) == 0 ) if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ||
( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ),
key, keylen ) ) != 0 )
{
mbedtls_pk_free( pk );
}
else
{ {
return( 0 ); return( 0 );
} }
mbedtls_pk_free( pk );
#endif /* MBEDTLS_RSA_C */ #endif /* MBEDTLS_RSA_C */
#if defined(MBEDTLS_ECP_C) #if defined(MBEDTLS_ECP_C)
if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ) ) == NULL )
return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY );
( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), key, keylen ) ) == 0 ) if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ||
( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ),
key, keylen ) ) != 0 )
{
mbedtls_pk_free( pk );
}
else
{ {
return( 0 ); return( 0 );
} }
mbedtls_pk_free( pk );
#endif /* MBEDTLS_ECP_C */ #endif /* MBEDTLS_ECP_C */
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
......
...@@ -62,13 +62,31 @@ ...@@ -62,13 +62,31 @@
* } * }
*/ */
static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start, static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start,
mbedtls_rsa_context *rsa ) mbedtls_rsa_context *rsa )
{ {
int ret; int ret;
size_t len = 0; size_t len = 0;
mbedtls_mpi T;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( p, start, &rsa->E ) ); mbedtls_mpi_init( &T );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( p, start, &rsa->N ) );
/* Export E */
if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, NULL, NULL, &T ) ) != 0 ||
( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 )
goto end_of_export;
len += ret;
/* Export N */
if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, NULL, NULL, NULL ) ) != 0 ||
( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 )
goto end_of_export;
len += ret;
end_of_export:
mbedtls_mpi_free( &T );
if( ret < 0 )
return( ret );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED |
...@@ -83,7 +101,7 @@ static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start, ...@@ -83,7 +101,7 @@ static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start,
* EC public key is an EC point * EC public key is an EC point
*/ */
static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start, static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start,
mbedtls_ecp_keypair *ec ) mbedtls_ecp_keypair *ec )
{ {
int ret; int ret;
size_t len = 0; size_t len = 0;
...@@ -111,7 +129,7 @@ static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start, ...@@ -111,7 +129,7 @@ static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start,
* } * }
*/ */
static int pk_write_ec_param( unsigned char **p, unsigned char *start, static int pk_write_ec_param( unsigned char **p, unsigned char *start,
mbedtls_ecp_keypair *ec ) mbedtls_ecp_keypair *ec )
{ {
int ret; int ret;
size_t len = 0; size_t len = 0;
...@@ -128,7 +146,7 @@ static int pk_write_ec_param( unsigned char **p, unsigned char *start, ...@@ -128,7 +146,7 @@ static int pk_write_ec_param( unsigned char **p, unsigned char *start,
#endif /* MBEDTLS_ECP_C */ #endif /* MBEDTLS_ECP_C */
int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start,
const mbedtls_pk_context *key ) const mbedtls_pk_context *key )
{ {
int ret; int ret;
size_t len = 0; size_t len = 0;
...@@ -205,21 +223,79 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_ ...@@ -205,21 +223,79 @@ int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_
#if defined(MBEDTLS_RSA_C) #if defined(MBEDTLS_RSA_C)
if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA )
{ {
mbedtls_mpi T; /* Temporary holding the exported parameters */
mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *key ); mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *key );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->QP ) ); /*
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->DQ ) ); * Export the parameters one after another to avoid simultaneous copies.
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->DP ) ); */
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->Q ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->P ) ); mbedtls_mpi_init( &T );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->D ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->E ) ); /* Export QP */
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->N ) ); if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, NULL, &T ) ) != 0 ||
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) ); ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
goto end_of_export;
len += ret;
/* Export DQ */
if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, &T, NULL ) ) != 0 ||
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
goto end_of_export;
len += ret;
/* Export DP */
if( ( ret = mbedtls_rsa_export_crt( rsa, &T, NULL, NULL ) ) != 0 ||
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
goto end_of_export;
len += ret;
/* Export Q */
if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL,
&T, NULL, NULL ) ) != 0 ||
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
goto end_of_export;
len += ret;
/* Export P */
if ( ( ret = mbedtls_rsa_export( rsa, NULL, &T,
NULL, NULL, NULL ) ) != 0 ||
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
goto end_of_export;
len += ret;
/* Export D */
if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL,
NULL, &T, NULL ) ) != 0 ||
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
goto end_of_export;
len += ret;
/* Export E */
if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL,
NULL, NULL, &T ) ) != 0 ||
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
goto end_of_export;
len += ret;
/* Export N */
if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL,
NULL, NULL, NULL ) ) != 0 ||
( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 )
goto end_of_export;
len += ret;
end_of_export:
mbedtls_mpi_free( &T );
if( ret < 0 )
return( ret );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c,
MBEDTLS_ASN1_SEQUENCE ) ); buf, MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE ) );
} }
else else
#endif /* MBEDTLS_RSA_C */ #endif /* MBEDTLS_RSA_C */
......
...@@ -25,13 +25,26 @@ ...@@ -25,13 +25,26 @@
#include MBEDTLS_CONFIG_FILE #include MBEDTLS_CONFIG_FILE
#endif #endif
// XXX Espressif are hacks sometimes. This is BS, but is taken from
// the mbedtls platform.c from their SDK. Really, this should go
// somewhere else. Note that the prototype here for vPortFree differs (!)
// from the one in sdk-overrides.h. That's above my pay grade.
// --nwf; 2018 Feb 18
extern void *pvPortCalloc(unsigned int count, unsigned int size);
extern void vPortFree( void *pv );
#if defined(MBEDTLS_PLATFORM_C) #if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h" #include "mbedtls/platform.h"
extern int ets_snprintf(char *buf, unsigned int size, const char *format, ...); #if defined(MBEDTLS_ENTROPY_NV_SEED) && \
extern void *pvPortCalloc(unsigned int count, unsigned int size); !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO)
extern void vPortFree( void *pv ); /* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
}
#endif
#if defined(MBEDTLS_PLATFORM_MEMORY) #if defined(MBEDTLS_PLATFORM_MEMORY)
#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) #if !defined(MBEDTLS_PLATFORM_STD_CALLOC)
...@@ -232,12 +245,13 @@ int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ) ...@@ -232,12 +245,13 @@ int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len )
size_t n; size_t n;
if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL ) if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL )
return -1; return( -1 );
if( ( n = fread( buf, 1, buf_len, file ) ) != buf_len ) if( ( n = fread( buf, 1, buf_len, file ) ) != buf_len )
{ {
fclose( file ); fclose( file );
return -1; mbedtls_zeroize( buf, buf_len );
return( -1 );
} }
fclose( file ); fclose( file );
......
...@@ -46,6 +46,8 @@ ...@@ -46,6 +46,8 @@
#endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_RIPEMD160_ALT)
/* /*
* 32-bit integer manipulation macros (little endian) * 32-bit integer manipulation macros (little endian)
*/ */
...@@ -96,7 +98,7 @@ void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst, ...@@ -96,7 +98,7 @@ void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst,
/* /*
* RIPEMD-160 context setup * RIPEMD-160 context setup
*/ */
void mbedtls_ripemd160_starts( mbedtls_ripemd160_context *ctx ) int mbedtls_ripemd160_starts_ret( mbedtls_ripemd160_context *ctx )
{ {
ctx->total[0] = 0; ctx->total[0] = 0;
ctx->total[1] = 0; ctx->total[1] = 0;
...@@ -106,13 +108,16 @@ void mbedtls_ripemd160_starts( mbedtls_ripemd160_context *ctx ) ...@@ -106,13 +108,16 @@ void mbedtls_ripemd160_starts( mbedtls_ripemd160_context *ctx )
ctx->state[2] = 0x98BADCFE; ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476; ctx->state[3] = 0x10325476;
ctx->state[4] = 0xC3D2E1F0; ctx->state[4] = 0xC3D2E1F0;
return( 0 );
} }
#if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT) #if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT)
/* /*
* Process one block * Process one block
*/ */
void mbedtls_ripemd160_process( mbedtls_ripemd160_context *ctx, const unsigned char data[64] ) int mbedtls_internal_ripemd160_process( mbedtls_ripemd160_context *ctx,
const unsigned char data[64] )
{ {
uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16]; uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16];
...@@ -287,20 +292,24 @@ void mbedtls_ripemd160_process( mbedtls_ripemd160_context *ctx, const unsigned c ...@@ -287,20 +292,24 @@ void mbedtls_ripemd160_process( mbedtls_ripemd160_context *ctx, const unsigned c
ctx->state[3] = ctx->state[4] + A + Bp; ctx->state[3] = ctx->state[4] + A + Bp;
ctx->state[4] = ctx->state[0] + B + Cp; ctx->state[4] = ctx->state[0] + B + Cp;
ctx->state[0] = C; ctx->state[0] = C;
return( 0 );
} }
#endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */ #endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */
/* /*
* RIPEMD-160 process buffer * RIPEMD-160 process buffer
*/ */
void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, int mbedtls_ripemd160_update_ret( mbedtls_ripemd160_context *ctx,
const unsigned char *input, size_t ilen ) const unsigned char *input,
size_t ilen )
{ {
int ret;
size_t fill; size_t fill;
uint32_t left; uint32_t left;
if( ilen == 0 ) if( ilen == 0 )
return; return( 0 );
left = ctx->total[0] & 0x3F; left = ctx->total[0] & 0x3F;
fill = 64 - left; fill = 64 - left;
...@@ -314,7 +323,10 @@ void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, ...@@ -314,7 +323,10 @@ void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx,
if( left && ilen >= fill ) if( left && ilen >= fill )
{ {
memcpy( (void *) (ctx->buffer + left), input, fill ); memcpy( (void *) (ctx->buffer + left), input, fill );
mbedtls_ripemd160_process( ctx, ctx->buffer );
if( ( ret = mbedtls_internal_ripemd160_process( ctx, ctx->buffer ) ) != 0 )
return( ret );
input += fill; input += fill;
ilen -= fill; ilen -= fill;
left = 0; left = 0;
...@@ -322,7 +334,9 @@ void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, ...@@ -322,7 +334,9 @@ void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx,
while( ilen >= 64 ) while( ilen >= 64 )
{ {
mbedtls_ripemd160_process( ctx, input ); if( ( ret = mbedtls_internal_ripemd160_process( ctx, input ) ) != 0 )
return( ret );
input += 64; input += 64;
ilen -= 64; ilen -= 64;
} }
...@@ -331,6 +345,8 @@ void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, ...@@ -331,6 +345,8 @@ void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx,
{ {
memcpy( (void *) (ctx->buffer + left), input, ilen ); memcpy( (void *) (ctx->buffer + left), input, ilen );
} }
return( 0 );
} }
static const unsigned char ripemd160_padding[64] = static const unsigned char ripemd160_padding[64] =
...@@ -344,8 +360,10 @@ static const unsigned char ripemd160_padding[64] = ...@@ -344,8 +360,10 @@ static const unsigned char ripemd160_padding[64] =
/* /*
* RIPEMD-160 final digest * RIPEMD-160 final digest
*/ */
void mbedtls_ripemd160_finish( mbedtls_ripemd160_context *ctx, unsigned char output[20] ) int mbedtls_ripemd160_finish_ret( mbedtls_ripemd160_context *ctx,
unsigned char output[20] )
{ {
int ret;
uint32_t last, padn; uint32_t last, padn;
uint32_t high, low; uint32_t high, low;
unsigned char msglen[8]; unsigned char msglen[8];
...@@ -360,29 +378,50 @@ void mbedtls_ripemd160_finish( mbedtls_ripemd160_context *ctx, unsigned char out ...@@ -360,29 +378,50 @@ void mbedtls_ripemd160_finish( mbedtls_ripemd160_context *ctx, unsigned char out
last = ctx->total[0] & 0x3F; last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
mbedtls_ripemd160_update( ctx, ripemd160_padding, padn ); ret = mbedtls_ripemd160_update_ret( ctx, ripemd160_padding, padn );
mbedtls_ripemd160_update( ctx, msglen, 8 ); if( ret != 0 )
return( ret );
ret = mbedtls_ripemd160_update_ret( ctx, msglen, 8 );
if( ret != 0 )
return( ret );
PUT_UINT32_LE( ctx->state[0], output, 0 ); PUT_UINT32_LE( ctx->state[0], output, 0 );
PUT_UINT32_LE( ctx->state[1], output, 4 ); PUT_UINT32_LE( ctx->state[1], output, 4 );
PUT_UINT32_LE( ctx->state[2], output, 8 ); PUT_UINT32_LE( ctx->state[2], output, 8 );
PUT_UINT32_LE( ctx->state[3], output, 12 ); PUT_UINT32_LE( ctx->state[3], output, 12 );
PUT_UINT32_LE( ctx->state[4], output, 16 ); PUT_UINT32_LE( ctx->state[4], output, 16 );
return( 0 );
} }
#endif /* ! MBEDTLS_RIPEMD160_ALT */
/* /*
* output = RIPEMD-160( input buffer ) * output = RIPEMD-160( input buffer )
*/ */
void mbedtls_ripemd160( const unsigned char *input, size_t ilen, int mbedtls_ripemd160_ret( const unsigned char *input,
unsigned char output[20] ) size_t ilen,
unsigned char output[20] )
{ {
int ret;
mbedtls_ripemd160_context ctx; mbedtls_ripemd160_context ctx;
mbedtls_ripemd160_init( &ctx ); mbedtls_ripemd160_init( &ctx );
mbedtls_ripemd160_starts( &ctx );
mbedtls_ripemd160_update( &ctx, input, ilen ); if( ( ret = mbedtls_ripemd160_starts_ret( &ctx ) ) != 0 )
mbedtls_ripemd160_finish( &ctx, output ); goto exit;
if( ( ret = mbedtls_ripemd160_update_ret( &ctx, input, ilen ) ) != 0 )
goto exit;
if( ( ret = mbedtls_ripemd160_finish_ret( &ctx, output ) ) != 0 )
goto exit;
exit:
mbedtls_ripemd160_free( &ctx ); mbedtls_ripemd160_free( &ctx );
return( ret );
} }
#if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_SELF_TEST)
...@@ -391,18 +430,22 @@ void mbedtls_ripemd160( const unsigned char *input, size_t ilen, ...@@ -391,18 +430,22 @@ void mbedtls_ripemd160( const unsigned char *input, size_t ilen,
* http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html#HMAC * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html#HMAC
*/ */
#define TESTS 8 #define TESTS 8
#define KEYS 2 static const unsigned char ripemd160_test_str[TESTS][81] =
static const char *ripemd160_test_input[TESTS] =
{ {
"", { "" },
"a", { "a" },
"abc", { "abc" },
"message digest", { "message digest" },
"abcdefghijklmnopqrstuvwxyz", { "abcdefghijklmnopqrstuvwxyz" },
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
"1234567890123456789012345678901234567890" { "12345678901234567890123456789012345678901234567890123456789012"
"1234567890123456789012345678901234567890", "345678901234567890" },
};
static const size_t ripemd160_test_strlen[TESTS] =
{
0, 1, 3, 14, 26, 56, 62, 80
}; };
static const unsigned char ripemd160_test_md[TESTS][20] = static const unsigned char ripemd160_test_md[TESTS][20] =
...@@ -430,7 +473,7 @@ static const unsigned char ripemd160_test_md[TESTS][20] = ...@@ -430,7 +473,7 @@ static const unsigned char ripemd160_test_md[TESTS][20] =
*/ */
int mbedtls_ripemd160_self_test( int verbose ) int mbedtls_ripemd160_self_test( int verbose )
{ {
int i; int i, ret = 0;
unsigned char output[20]; unsigned char output[20];
memset( output, 0, sizeof output ); memset( output, 0, sizeof output );
...@@ -440,16 +483,15 @@ int mbedtls_ripemd160_self_test( int verbose ) ...@@ -440,16 +483,15 @@ int mbedtls_ripemd160_self_test( int verbose )
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( " RIPEMD-160 test #%d: ", i + 1 ); mbedtls_printf( " RIPEMD-160 test #%d: ", i + 1 );
mbedtls_ripemd160( (const unsigned char *) ripemd160_test_input[i], ret = mbedtls_ripemd160_ret( ripemd160_test_str[i],
strlen( ripemd160_test_input[i] ), ripemd160_test_strlen[i], output );
output ); if( ret != 0 )
goto fail;
if( memcmp( output, ripemd160_test_md[i], 20 ) != 0 ) if( memcmp( output, ripemd160_test_md[i], 20 ) != 0 )
{ {
if( verbose != 0 ) ret = 1;
mbedtls_printf( "failed\n" ); goto fail;
return( 1 );
} }
if( verbose != 0 ) if( verbose != 0 )
...@@ -460,6 +502,12 @@ int mbedtls_ripemd160_self_test( int verbose ) ...@@ -460,6 +502,12 @@ int mbedtls_ripemd160_self_test( int verbose )
mbedtls_printf( "\n" ); mbedtls_printf( "\n" );
return( 0 ); return( 0 );
fail:
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( ret );
} }
#endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SELF_TEST */
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
* *
* This file is part of mbed TLS (https://tls.mbed.org) * This file is part of mbed TLS (https://tls.mbed.org)
*/ */
/* /*
* The following sources were referenced in the design of this implementation * The following sources were referenced in the design of this implementation
* of the RSA algorithm: * of the RSA algorithm:
...@@ -45,6 +46,7 @@ ...@@ -45,6 +46,7 @@
#if defined(MBEDTLS_RSA_C) #if defined(MBEDTLS_RSA_C)
#include "mbedtls/rsa.h" #include "mbedtls/rsa.h"
#include "mbedtls/rsa_internal.h"
#include "mbedtls/oid.h" #include "mbedtls/oid.h"
#include <string.h> #include <string.h>
...@@ -66,11 +68,392 @@ ...@@ -66,11 +68,392 @@
#define mbedtls_free free #define mbedtls_free free
#endif #endif
#if !defined(MBEDTLS_RSA_ALT)
/* Implementation that should never be optimized out by the compiler */ /* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) { static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
} }
/* constant-time buffer comparison */
static inline int mbedtls_safer_memcmp( const void *a, const void *b, size_t n )
{
size_t i;
const unsigned char *A = (const unsigned char *) a;
const unsigned char *B = (const unsigned char *) b;
unsigned char diff = 0;
for( i = 0; i < n; i++ )
diff |= A[i] ^ B[i];
return( diff );
}
int mbedtls_rsa_import( mbedtls_rsa_context *ctx,
const mbedtls_mpi *N,
const mbedtls_mpi *P, const mbedtls_mpi *Q,
const mbedtls_mpi *D, const mbedtls_mpi *E )
{
int ret;
if( ( N != NULL && ( ret = mbedtls_mpi_copy( &ctx->N, N ) ) != 0 ) ||
( P != NULL && ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ) ||
( Q != NULL && ( ret = mbedtls_mpi_copy( &ctx->Q, Q ) ) != 0 ) ||
( D != NULL && ( ret = mbedtls_mpi_copy( &ctx->D, D ) ) != 0 ) ||
( E != NULL && ( ret = mbedtls_mpi_copy( &ctx->E, E ) ) != 0 ) )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
}
if( N != NULL )
ctx->len = mbedtls_mpi_size( &ctx->N );
return( 0 );
}
int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx,
unsigned char const *N, size_t N_len,
unsigned char const *P, size_t P_len,
unsigned char const *Q, size_t Q_len,
unsigned char const *D, size_t D_len,
unsigned char const *E, size_t E_len )
{
int ret = 0;
if( N != NULL )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->N, N, N_len ) );
ctx->len = mbedtls_mpi_size( &ctx->N );
}
if( P != NULL )
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->P, P, P_len ) );
if( Q != NULL )
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->Q, Q, Q_len ) );
if( D != NULL )
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->D, D, D_len ) );
if( E != NULL )
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->E, E, E_len ) );
cleanup:
if( ret != 0 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
return( 0 );
}
/*
* Checks whether the context fields are set in such a way
* that the RSA primitives will be able to execute without error.
* It does *not* make guarantees for consistency of the parameters.
*/
static int rsa_check_context( mbedtls_rsa_context const *ctx, int is_priv,
int blinding_needed )
{
#if !defined(MBEDTLS_RSA_NO_CRT)
/* blinding_needed is only used for NO_CRT to decide whether
* P,Q need to be present or not. */
((void) blinding_needed);
#endif
if( ctx->len != mbedtls_mpi_size( &ctx->N ) ||
ctx->len > MBEDTLS_MPI_MAX_SIZE )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
}
/*
* 1. Modular exponentiation needs positive, odd moduli.
*/
/* Modular exponentiation wrt. N is always used for
* RSA public key operations. */
if( mbedtls_mpi_cmp_int( &ctx->N, 0 ) <= 0 ||
mbedtls_mpi_get_bit( &ctx->N, 0 ) == 0 )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
}
#if !defined(MBEDTLS_RSA_NO_CRT)
/* Modular exponentiation for P and Q is only
* used for private key operations and if CRT
* is used. */
if( is_priv &&
( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 ||
mbedtls_mpi_get_bit( &ctx->P, 0 ) == 0 ||
mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 ||
mbedtls_mpi_get_bit( &ctx->Q, 0 ) == 0 ) )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
}
#endif /* !MBEDTLS_RSA_NO_CRT */
/*
* 2. Exponents must be positive
*/
/* Always need E for public key operations */
if( mbedtls_mpi_cmp_int( &ctx->E, 0 ) <= 0 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
#if defined(MBEDTLS_RSA_NO_CRT)
/* For private key operations, use D or DP & DQ
* as (unblinded) exponents. */
if( is_priv && mbedtls_mpi_cmp_int( &ctx->D, 0 ) <= 0 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
#else
if( is_priv &&
( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) <= 0 ||
mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) <= 0 ) )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
}
#endif /* MBEDTLS_RSA_NO_CRT */
/* Blinding shouldn't make exponents negative either,
* so check that P, Q >= 1 if that hasn't yet been
* done as part of 1. */
#if defined(MBEDTLS_RSA_NO_CRT)
if( is_priv && blinding_needed &&
( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 ||
mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 ) )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
}
#endif
/* It wouldn't lead to an error if it wasn't satisfied,
* but check for QP >= 1 nonetheless. */
#if !defined(MBEDTLS_RSA_NO_CRT)
if( is_priv &&
mbedtls_mpi_cmp_int( &ctx->QP, 0 ) <= 0 )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
}
#endif
return( 0 );
}
int mbedtls_rsa_complete( mbedtls_rsa_context *ctx )
{
int ret = 0;
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 );
/*
* Check whether provided parameters are enough
* to deduce all others. The following incomplete
* parameter sets for private keys are supported:
*
* (1) P, Q missing.
* (2) D and potentially N missing.
*
*/
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;
/* These three alternatives are mutually exclusive */
const int is_priv = n_missing || pq_missing || d_missing;
if( !is_priv && !is_pub )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
/*
* Step 1: Deduce N if P, Q are provided.
*/
if( !have_N && have_P && have_Q )
{
if( ( ret = mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P,
&ctx->Q ) ) != 0 )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
}
ctx->len = mbedtls_mpi_size( &ctx->N );
}
/*
* Step 2: Deduce and verify all remaining core parameters.
*/
if( pq_missing )
{
ret = mbedtls_rsa_deduce_primes( &ctx->N, &ctx->E, &ctx->D,
&ctx->P, &ctx->Q );
if( ret != 0 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
}
else if( d_missing )
{
if( ( ret = mbedtls_rsa_deduce_private_exponent( &ctx->P,
&ctx->Q,
&ctx->E,
&ctx->D ) ) != 0 )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
}
}
/*
* Step 3: Deduce all additional parameters specific
* to our current RSA implementation.
*/
#if !defined(MBEDTLS_RSA_NO_CRT)
if( is_priv )
{
ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D,
&ctx->DP, &ctx->DQ, &ctx->QP );
if( ret != 0 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
}
#endif /* MBEDTLS_RSA_NO_CRT */
/*
* Step 3: Basic sanity checks
*/
return( rsa_check_context( ctx, is_priv, 1 ) );
}
int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx,
unsigned char *N, size_t N_len,
unsigned char *P, size_t P_len,
unsigned char *Q, size_t Q_len,
unsigned char *D, size_t D_len,
unsigned char *E, size_t E_len )
{
int ret = 0;
/* Check if key is private or public */
const int 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 &&
mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 &&
mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0;
if( !is_priv )
{
/* If we're trying to export private parameters for a public key,
* something must be wrong. */
if( P != NULL || Q != NULL || D != NULL )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
}
if( N != NULL )
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->N, N, N_len ) );
if( P != NULL )
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->P, P, P_len ) );
if( Q != NULL )
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->Q, Q, Q_len ) );
if( D != NULL )
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->D, D, D_len ) );
if( E != NULL )
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->E, E, E_len ) );
cleanup:
return( ret );
}
int mbedtls_rsa_export( const mbedtls_rsa_context *ctx,
mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q,
mbedtls_mpi *D, mbedtls_mpi *E )
{
int ret;
/* Check if key is private or public */
int 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 &&
mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 &&
mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0;
if( !is_priv )
{
/* If we're trying to export private parameters for a public key,
* something must be wrong. */
if( P != NULL || Q != NULL || D != NULL )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
}
/* Export all requested core parameters. */
if( ( N != NULL && ( ret = mbedtls_mpi_copy( N, &ctx->N ) ) != 0 ) ||
( P != NULL && ( ret = mbedtls_mpi_copy( P, &ctx->P ) ) != 0 ) ||
( Q != NULL && ( ret = mbedtls_mpi_copy( Q, &ctx->Q ) ) != 0 ) ||
( D != NULL && ( ret = mbedtls_mpi_copy( D, &ctx->D ) ) != 0 ) ||
( E != NULL && ( ret = mbedtls_mpi_copy( E, &ctx->E ) ) != 0 ) )
{
return( ret );
}
return( 0 );
}
/*
* Export CRT parameters
* This must also be implemented if CRT is not used, for being able to
* write DER encoded RSA keys. The helper function mbedtls_rsa_deduce_crt
* can be used in this case.
*/
int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx,
mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP )
{
int ret;
/* Check if key is private or public */
int 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 &&
mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 &&
mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0;
if( !is_priv )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
#if !defined(MBEDTLS_RSA_NO_CRT)
/* Export all requested blinding parameters. */
if( ( DP != NULL && ( ret = mbedtls_mpi_copy( DP, &ctx->DP ) ) != 0 ) ||
( DQ != NULL && ( ret = mbedtls_mpi_copy( DQ, &ctx->DQ ) ) != 0 ) ||
( QP != NULL && ( ret = mbedtls_mpi_copy( QP, &ctx->QP ) ) != 0 ) )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
}
#else
if( ( ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D,
DP, DQ, QP ) ) != 0 )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret );
}
#endif
return( 0 );
}
/* /*
* Initialize an RSA context * Initialize an RSA context
*/ */
...@@ -96,6 +479,16 @@ void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, int hash_id ...@@ -96,6 +479,16 @@ void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, int hash_id
ctx->hash_id = hash_id; ctx->hash_id = hash_id;
} }
/*
* Get length in bytes of RSA modulus
*/
size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx )
{
return( ctx->len );
}
#if defined(MBEDTLS_GENPRIME) #if defined(MBEDTLS_GENPRIME)
/* /*
...@@ -107,7 +500,7 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, ...@@ -107,7 +500,7 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
unsigned int nbits, int exponent ) unsigned int nbits, int exponent )
{ {
int ret; int ret;
mbedtls_mpi P1, Q1, H, G; mbedtls_mpi H, G;
if( f_rng == NULL || nbits < 128 || exponent < 3 ) if( f_rng == NULL || nbits < 128 || exponent < 3 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
...@@ -115,8 +508,8 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, ...@@ -115,8 +508,8 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
if( nbits % 2 ) if( nbits % 2 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); mbedtls_mpi_init( &H );
mbedtls_mpi_init( &H ); mbedtls_mpi_init( &G ); mbedtls_mpi_init( &G );
/* /*
* find primes P and Q with Q < P so that: * find primes P and Q with Q < P so that:
...@@ -127,10 +520,10 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, ...@@ -127,10 +520,10 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
do do
{ {
MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, 0, MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, 0,
f_rng, p_rng ) ); f_rng, p_rng ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, 0, MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, 0,
f_rng, p_rng ) ); f_rng, p_rng ) );
if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 ) if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 )
continue; continue;
...@@ -140,31 +533,43 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, ...@@ -140,31 +533,43 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
continue; continue;
if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 )
mbedtls_mpi_swap( &ctx->P, &ctx->Q ); mbedtls_mpi_swap( &ctx->P, &ctx->Q );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); /* Temporarily replace P,Q by P-1, Q-1 */
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->P, &ctx->P, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->Q, &ctx->Q, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &ctx->P, &ctx->Q ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) );
} }
while( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ); while( mbedtls_mpi_cmp_int( &G, 1 ) != 0 );
/* Restore P,Q */
MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->P, &ctx->P, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->Q, &ctx->Q, 1 ) );
ctx->len = mbedtls_mpi_size( &ctx->N );
/* /*
* D = E^-1 mod ((P-1)*(Q-1)) * D = E^-1 mod ((P-1)*(Q-1))
* DP = D mod (P - 1) * DP = D mod (P - 1)
* DQ = D mod (Q - 1) * DQ = D mod (Q - 1)
* QP = Q^-1 mod P * QP = Q^-1 mod P
*/ */
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D , &ctx->E, &H ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) );
ctx->len = ( mbedtls_mpi_bitlen( &ctx->N ) + 7 ) >> 3; MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D, &ctx->E, &H ) );
#if !defined(MBEDTLS_RSA_NO_CRT)
MBEDTLS_MPI_CHK( mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D,
&ctx->DP, &ctx->DQ, &ctx->QP ) );
#endif /* MBEDTLS_RSA_NO_CRT */
/* Double-check */
MBEDTLS_MPI_CHK( mbedtls_rsa_check_privkey( ctx ) );
cleanup: cleanup:
mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &H ); mbedtls_mpi_free( &G ); mbedtls_mpi_free( &H );
mbedtls_mpi_free( &G );
if( ret != 0 ) if( ret != 0 )
{ {
...@@ -182,82 +587,48 @@ cleanup: ...@@ -182,82 +587,48 @@ cleanup:
*/ */
int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ) int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx )
{ {
if( !ctx->N.p || !ctx->E.p ) if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) != 0 )
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
if( ( ctx->N.p[0] & 1 ) == 0 ||
( ctx->E.p[0] & 1 ) == 0 )
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
if( mbedtls_mpi_bitlen( &ctx->N ) < 128 || if( mbedtls_mpi_bitlen( &ctx->N ) < 128 )
mbedtls_mpi_bitlen( &ctx->N ) > MBEDTLS_MPI_MAX_BITS ) {
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
}
if( mbedtls_mpi_bitlen( &ctx->E ) < 2 || if( mbedtls_mpi_get_bit( &ctx->E, 0 ) == 0 ||
mbedtls_mpi_bitlen( &ctx->E ) < 2 ||
mbedtls_mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 ) mbedtls_mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 )
{
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
}
return( 0 ); return( 0 );
} }
/* /*
* Check a private RSA key * Check for the consistency of all fields in an RSA private key context
*/ */
int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ) int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx )
{ {
int ret; if( mbedtls_rsa_check_pubkey( ctx ) != 0 ||
mbedtls_mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2, DP, DQ, QP; rsa_check_context( ctx, 1 /* private */, 1 /* blinding */ ) != 0 )
{
if( ( ret = mbedtls_rsa_check_pubkey( ctx ) ) != 0 )
return( ret );
if( !ctx->P.p || !ctx->Q.p || !ctx->D.p )
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
}
mbedtls_mpi_init( &PQ ); mbedtls_mpi_init( &DE ); mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); if( mbedtls_rsa_validate_params( &ctx->N, &ctx->P, &ctx->Q,
mbedtls_mpi_init( &H ); mbedtls_mpi_init( &I ); mbedtls_mpi_init( &G ); mbedtls_mpi_init( &G2 ); &ctx->D, &ctx->E, NULL, NULL ) != 0 )
mbedtls_mpi_init( &L1 ); mbedtls_mpi_init( &L2 ); mbedtls_mpi_init( &DP ); mbedtls_mpi_init( &DQ );
mbedtls_mpi_init( &QP );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G2, &P1, &Q1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &L1, &L2, &H, &G2 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &I, &DE, &L1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &DP, &ctx->D, &P1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &DQ, &ctx->D, &Q1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &QP, &ctx->Q, &ctx->P ) );
/*
* Check for a valid PKCS1v2 private key
*/
if( mbedtls_mpi_cmp_mpi( &PQ, &ctx->N ) != 0 ||
mbedtls_mpi_cmp_mpi( &DP, &ctx->DP ) != 0 ||
mbedtls_mpi_cmp_mpi( &DQ, &ctx->DQ ) != 0 ||
mbedtls_mpi_cmp_mpi( &QP, &ctx->QP ) != 0 ||
mbedtls_mpi_cmp_int( &L2, 0 ) != 0 ||
mbedtls_mpi_cmp_int( &I, 1 ) != 0 ||
mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
{ {
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
} }
cleanup: #if !defined(MBEDTLS_RSA_NO_CRT)
mbedtls_mpi_free( &PQ ); mbedtls_mpi_free( &DE ); mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); else if( mbedtls_rsa_validate_crt( &ctx->P, &ctx->Q, &ctx->D,
mbedtls_mpi_free( &H ); mbedtls_mpi_free( &I ); mbedtls_mpi_free( &G ); mbedtls_mpi_free( &G2 ); &ctx->DP, &ctx->DQ, &ctx->QP ) != 0 )
mbedtls_mpi_free( &L1 ); mbedtls_mpi_free( &L2 ); mbedtls_mpi_free( &DP ); mbedtls_mpi_free( &DQ ); {
mbedtls_mpi_free( &QP ); return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
}
if( ret == MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ) #endif
return( ret );
if( ret != 0 )
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED + ret );
return( 0 ); return( 0 );
} }
...@@ -265,9 +636,10 @@ cleanup: ...@@ -265,9 +636,10 @@ cleanup:
/* /*
* Check if contexts holding a public and private key match * Check if contexts holding a public and private key match
*/ */
int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, const mbedtls_rsa_context *prv ) int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub,
const mbedtls_rsa_context *prv )
{ {
if( mbedtls_rsa_check_pubkey( pub ) != 0 || if( mbedtls_rsa_check_pubkey( pub ) != 0 ||
mbedtls_rsa_check_privkey( prv ) != 0 ) mbedtls_rsa_check_privkey( prv ) != 0 )
{ {
return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED );
...@@ -293,6 +665,9 @@ int mbedtls_rsa_public( mbedtls_rsa_context *ctx, ...@@ -293,6 +665,9 @@ int mbedtls_rsa_public( mbedtls_rsa_context *ctx,
size_t olen; size_t olen;
mbedtls_mpi T; mbedtls_mpi T;
if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
mbedtls_mpi_init( &T ); mbedtls_mpi_init( &T );
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
...@@ -409,14 +784,15 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, ...@@ -409,14 +784,15 @@ int mbedtls_rsa_private( mbedtls_rsa_context *ctx,
mbedtls_mpi *DQ = &ctx->DQ; mbedtls_mpi *DQ = &ctx->DQ;
#endif #endif
/* Make sure we have private key info, prevent possible misuse */ if( rsa_check_context( ctx, 1 /* private key checks */,
if( ctx->P.p == NULL || ctx->Q.p == NULL || ctx->D.p == NULL ) f_rng != NULL /* blinding y/n */ ) != 0 )
{
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
}
mbedtls_mpi_init( &T ); mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 );
mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); mbedtls_mpi_init( &R );
if( f_rng != NULL ) if( f_rng != NULL )
{ {
#if defined(MBEDTLS_RSA_NO_CRT) #if defined(MBEDTLS_RSA_NO_CRT)
...@@ -566,7 +942,7 @@ cleanup: ...@@ -566,7 +942,7 @@ cleanup:
* \param slen length of the source buffer * \param slen length of the source buffer
* \param md_ctx message digest context to use * \param md_ctx message digest context to use
*/ */
static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, static int mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src,
size_t slen, mbedtls_md_context_t *md_ctx ) size_t slen, mbedtls_md_context_t *md_ctx )
{ {
unsigned char mask[MBEDTLS_MD_MAX_SIZE]; unsigned char mask[MBEDTLS_MD_MAX_SIZE];
...@@ -574,6 +950,7 @@ static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, ...@@ -574,6 +950,7 @@ static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src,
unsigned char *p; unsigned char *p;
unsigned int hlen; unsigned int hlen;
size_t i, use_len; size_t i, use_len;
int ret = 0;
memset( mask, 0, MBEDTLS_MD_MAX_SIZE ); memset( mask, 0, MBEDTLS_MD_MAX_SIZE );
memset( counter, 0, 4 ); memset( counter, 0, 4 );
...@@ -589,10 +966,14 @@ static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, ...@@ -589,10 +966,14 @@ static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src,
if( dlen < hlen ) if( dlen < hlen )
use_len = dlen; use_len = dlen;
mbedtls_md_starts( md_ctx ); if( ( ret = mbedtls_md_starts( md_ctx ) ) != 0 )
mbedtls_md_update( md_ctx, src, slen ); goto exit;
mbedtls_md_update( md_ctx, counter, 4 ); if( ( ret = mbedtls_md_update( md_ctx, src, slen ) ) != 0 )
mbedtls_md_finish( md_ctx, mask ); goto exit;
if( ( ret = mbedtls_md_update( md_ctx, counter, 4 ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md_finish( md_ctx, mask ) ) != 0 )
goto exit;
for( i = 0; i < use_len; ++i ) for( i = 0; i < use_len; ++i )
*p++ ^= mask[i]; *p++ ^= mask[i];
...@@ -602,7 +983,10 @@ static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, ...@@ -602,7 +983,10 @@ static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src,
dlen -= use_len; dlen -= use_len;
} }
exit:
mbedtls_zeroize( mask, sizeof( mask ) ); mbedtls_zeroize( mask, sizeof( mask ) );
return( ret );
} }
#endif /* MBEDTLS_PKCS1_V21 */ #endif /* MBEDTLS_PKCS1_V21 */
...@@ -654,7 +1038,8 @@ int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, ...@@ -654,7 +1038,8 @@ int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx,
p += hlen; p += hlen;
/* Construct DB */ /* Construct DB */
mbedtls_md( md_info, label, label_len, p ); if( ( ret = mbedtls_md( md_info, label, label_len, p ) ) != 0 )
return( ret );
p += hlen; p += hlen;
p += olen - 2 * hlen - 2 - ilen; p += olen - 2 * hlen - 2 - ilen;
*p++ = 1; *p++ = 1;
...@@ -662,21 +1047,24 @@ int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, ...@@ -662,21 +1047,24 @@ int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx,
mbedtls_md_init( &md_ctx ); mbedtls_md_init( &md_ctx );
if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 )
{ goto exit;
mbedtls_md_free( &md_ctx );
return( ret );
}
/* maskedDB: Apply dbMask to DB */ /* maskedDB: Apply dbMask to DB */
mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, if( ( ret = mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen,
&md_ctx ); &md_ctx ) ) != 0 )
goto exit;
/* maskedSeed: Apply seedMask to seed */ /* maskedSeed: Apply seedMask to seed */
mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, if( ( ret = mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1,
&md_ctx ); &md_ctx ) ) != 0 )
goto exit;
exit:
mbedtls_md_free( &md_ctx ); mbedtls_md_free( &md_ctx );
if( ret != 0 )
return( ret );
return( ( mode == MBEDTLS_RSA_PUBLIC ) return( ( mode == MBEDTLS_RSA_PUBLIC )
? mbedtls_rsa_public( ctx, output, output ) ? mbedtls_rsa_public( ctx, output, output )
: mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) );
...@@ -843,20 +1231,23 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, ...@@ -843,20 +1231,23 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx,
goto cleanup; goto cleanup;
} }
/* Generate lHash */
mbedtls_md( md_info, label, label_len, lhash );
/* seed: Apply seedMask to maskedSeed */ /* seed: Apply seedMask to maskedSeed */
mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, if( ( ret = mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1,
&md_ctx ); &md_ctx ) ) != 0 ||
/* DB: Apply dbMask to maskedDB */ /* DB: Apply dbMask to maskedDB */
mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, ( ret = mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen,
&md_ctx ); &md_ctx ) ) != 0 )
{
mbedtls_md_free( &md_ctx );
goto cleanup;
}
mbedtls_md_free( &md_ctx ); mbedtls_md_free( &md_ctx );
/* Generate lHash */
if( ( ret = mbedtls_md( md_info, label, label_len, lhash ) ) != 0 )
goto cleanup;
/* /*
* Check contents, in "constant-time" * Check contents, in "constant-time"
*/ */
...@@ -1107,28 +1498,28 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, ...@@ -1107,28 +1498,28 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
mbedtls_md_init( &md_ctx ); mbedtls_md_init( &md_ctx );
if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 )
{ goto exit;
mbedtls_md_free( &md_ctx );
/* No need to zeroize salt: we didn't use it. */
return( ret );
}
/* Generate H = Hash( M' ) */ /* Generate H = Hash( M' ) */
mbedtls_md_starts( &md_ctx ); if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 )
mbedtls_md_update( &md_ctx, p, 8 ); goto exit;
mbedtls_md_update( &md_ctx, hash, hashlen ); if( ( ret = mbedtls_md_update( &md_ctx, p, 8 ) ) != 0 )
mbedtls_md_update( &md_ctx, salt, slen ); goto exit;
mbedtls_md_finish( &md_ctx, p ); if( ( ret = mbedtls_md_update( &md_ctx, hash, hashlen ) ) != 0 )
mbedtls_zeroize( salt, sizeof( salt ) ); goto exit;
if( ( ret = mbedtls_md_update( &md_ctx, salt, slen ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md_finish( &md_ctx, p ) ) != 0 )
goto exit;
/* Compensate for boundary condition when applying mask */ /* Compensate for boundary condition when applying mask */
if( msb % 8 == 0 ) if( msb % 8 == 0 )
offset = 1; offset = 1;
/* maskedDB: Apply dbMask to DB */ /* maskedDB: Apply dbMask to DB */
mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, &md_ctx ); if( ( ret = mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen,
&md_ctx ) ) != 0 )
mbedtls_md_free( &md_ctx ); goto exit;
msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; msb = mbedtls_mpi_bitlen( &ctx->N ) - 1;
sig[0] &= 0xFF >> ( olen * 8 - msb ); sig[0] &= 0xFF >> ( olen * 8 - msb );
...@@ -1136,6 +1527,14 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, ...@@ -1136,6 +1527,14 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
p += hlen; p += hlen;
*p++ = 0xBC; *p++ = 0xBC;
mbedtls_zeroize( salt, sizeof( salt ) );
exit:
mbedtls_md_free( &md_ctx );
if( ret != 0 )
return( ret );
return( ( mode == MBEDTLS_RSA_PUBLIC ) return( ( mode == MBEDTLS_RSA_PUBLIC )
? mbedtls_rsa_public( ctx, sig, sig ) ? mbedtls_rsa_public( ctx, sig, sig )
: mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) ); : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) );
...@@ -1146,33 +1545,37 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, ...@@ -1146,33 +1545,37 @@ int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx,
/* /*
* Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function
*/ */
/*
* Do an RSA operation to sign the message digest /* Construct a PKCS v1.5 encoding of a hashed message
*
* This is used both for signature generation and verification.
*
* Parameters:
* - md_alg: Identifies the hash algorithm used to generate the given hash;
* MBEDTLS_MD_NONE if raw data is signed.
* - hashlen: Length of hash in case hashlen is MBEDTLS_MD_NONE.
* - hash: Buffer containing the hashed message or the raw data.
* - dst_len: Length of the encoded message.
* - dst: Buffer to hold the encoded message.
*
* Assumptions:
* - hash has size hashlen if md_alg == MBEDTLS_MD_NONE.
* - hash has size corresponding to md_alg if md_alg != MBEDTLS_MD_NONE.
* - dst points to a buffer of size at least dst_len.
*
*/ */
int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, static int rsa_rsassa_pkcs1_v15_encode( mbedtls_md_type_t md_alg,
int (*f_rng)(void *, unsigned char *, size_t), unsigned int hashlen,
void *p_rng, const unsigned char *hash,
int mode, size_t dst_len,
mbedtls_md_type_t md_alg, unsigned char *dst )
unsigned int hashlen,
const unsigned char *hash,
unsigned char *sig )
{ {
size_t nb_pad, olen, oid_size = 0; size_t oid_size = 0;
unsigned char *p = sig; size_t nb_pad = dst_len;
const char *oid = NULL; unsigned char *p = dst;
unsigned char *sig_try = NULL, *verif = NULL; const char *oid = NULL;
size_t i;
unsigned char diff;
volatile unsigned char diff_no_optimize;
int ret;
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
olen = ctx->len;
nb_pad = olen - 3;
/* Are we signing hashed or raw data? */
if( md_alg != MBEDTLS_MD_NONE ) if( md_alg != MBEDTLS_MD_NONE )
{ {
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg );
...@@ -1182,64 +1585,144 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, ...@@ -1182,64 +1585,144 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx,
if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
nb_pad -= 10 + oid_size;
hashlen = mbedtls_md_get_size( md_info ); hashlen = mbedtls_md_get_size( md_info );
/* Double-check that 8 + hashlen + oid_size can be used as a
* 1-byte ASN.1 length encoding and that there's no overflow. */
if( 8 + hashlen + oid_size >= 0x80 ||
10 + hashlen < hashlen ||
10 + hashlen + oid_size < 10 + hashlen )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
/*
* Static bounds check:
* - Need 10 bytes for five tag-length pairs.
* (Insist on 1-byte length encodings to protect against variants of
* Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification)
* - Need hashlen bytes for hash
* - Need oid_size bytes for hash alg OID.
*/
if( nb_pad < 10 + hashlen + oid_size )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
nb_pad -= 10 + hashlen + oid_size;
} }
else
{
if( nb_pad < hashlen )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
nb_pad -= hashlen; nb_pad -= hashlen;
}
if( ( nb_pad < 8 ) || ( nb_pad > olen ) ) /* Need space for signature header and padding delimiter (3 bytes),
* and 8 bytes for the minimal padding */
if( nb_pad < 3 + 8 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
nb_pad -= 3;
/* Now nb_pad is the amount of memory to be filled
* with padding, and at least 8 bytes long. */
/* Write signature header and padding */
*p++ = 0; *p++ = 0;
*p++ = MBEDTLS_RSA_SIGN; *p++ = MBEDTLS_RSA_SIGN;
memset( p, 0xFF, nb_pad ); memset( p, 0xFF, nb_pad );
p += nb_pad; p += nb_pad;
*p++ = 0; *p++ = 0;
/* Are we signing raw data? */
if( md_alg == MBEDTLS_MD_NONE ) if( md_alg == MBEDTLS_MD_NONE )
{ {
memcpy( p, hash, hashlen ); memcpy( p, hash, hashlen );
return( 0 );
} }
else
/* Signing hashed data, add corresponding ASN.1 structure
*
* DigestInfo ::= SEQUENCE {
* digestAlgorithm DigestAlgorithmIdentifier,
* digest Digest }
* DigestAlgorithmIdentifier ::= AlgorithmIdentifier
* Digest ::= OCTET STRING
*
* Schematic:
* TAG-SEQ + LEN [ TAG-SEQ + LEN [ TAG-OID + LEN [ OID ]
* TAG-NULL + LEN [ NULL ] ]
* TAG-OCTET + LEN [ HASH ] ]
*/
*p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
*p++ = (unsigned char)( 0x08 + oid_size + hashlen );
*p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
*p++ = (unsigned char)( 0x04 + oid_size );
*p++ = MBEDTLS_ASN1_OID;
*p++ = (unsigned char) oid_size;
memcpy( p, oid, oid_size );
p += oid_size;
*p++ = MBEDTLS_ASN1_NULL;
*p++ = 0x00;
*p++ = MBEDTLS_ASN1_OCTET_STRING;
*p++ = (unsigned char) hashlen;
memcpy( p, hash, hashlen );
p += hashlen;
/* Just a sanity-check, should be automatic
* after the initial bounds check. */
if( p != dst + dst_len )
{ {
/* mbedtls_zeroize( dst, dst_len );
* DigestInfo ::= SEQUENCE { return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
* digestAlgorithm DigestAlgorithmIdentifier,
* digest Digest }
*
* DigestAlgorithmIdentifier ::= AlgorithmIdentifier
*
* Digest ::= OCTET STRING
*/
*p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
*p++ = (unsigned char) ( 0x08 + oid_size + hashlen );
*p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
*p++ = (unsigned char) ( 0x04 + oid_size );
*p++ = MBEDTLS_ASN1_OID;
*p++ = oid_size & 0xFF;
memcpy( p, oid, oid_size );
p += oid_size;
*p++ = MBEDTLS_ASN1_NULL;
*p++ = 0x00;
*p++ = MBEDTLS_ASN1_OCTET_STRING;
*p++ = hashlen;
memcpy( p, hash, hashlen );
} }
if( mode == MBEDTLS_RSA_PUBLIC ) return( 0 );
return( mbedtls_rsa_public( ctx, sig, sig ) ); }
/*
* Do an RSA operation to sign the message digest
*/
int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
int mode,
mbedtls_md_type_t md_alg,
unsigned int hashlen,
const unsigned char *hash,
unsigned char *sig )
{
int ret;
unsigned char *sig_try = NULL, *verif = NULL;
if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
/*
* Prepare PKCS1-v1.5 encoding (padding and hash identifier)
*/
if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash,
ctx->len, sig ) ) != 0 )
return( ret );
/* /*
* Call respective RSA primitive
*/
if( mode == MBEDTLS_RSA_PUBLIC )
{
/* Skip verification on a public key operation */
return( mbedtls_rsa_public( ctx, sig, sig ) );
}
/* Private key operation
*
* In order to prevent Lenstra's attack, make the signature in a * In order to prevent Lenstra's attack, make the signature in a
* temporary buffer and check it before returning it. * temporary buffer and check it before returning it.
*/ */
sig_try = mbedtls_calloc( 1, ctx->len ); sig_try = mbedtls_calloc( 1, ctx->len );
if( sig_try == NULL ) if( sig_try == NULL )
return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
verif = mbedtls_calloc( 1, ctx->len ); verif = mbedtls_calloc( 1, ctx->len );
if( verif == NULL ) if( verif == NULL )
{ {
mbedtls_free( sig_try ); mbedtls_free( sig_try );
...@@ -1249,12 +1732,7 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, ...@@ -1249,12 +1732,7 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx,
MBEDTLS_MPI_CHK( mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig_try ) ); MBEDTLS_MPI_CHK( mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig_try ) );
MBEDTLS_MPI_CHK( mbedtls_rsa_public( ctx, sig_try, verif ) ); MBEDTLS_MPI_CHK( mbedtls_rsa_public( ctx, sig_try, verif ) );
/* Compare in constant time just in case */ if( mbedtls_safer_memcmp( verif, sig, ctx->len ) != 0 )
for( diff = 0, i = 0; i < ctx->len; i++ )
diff |= verif[i] ^ sig[i];
diff_no_optimize = diff;
if( diff_no_optimize != 0 )
{ {
ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED; ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED;
goto cleanup; goto cleanup;
...@@ -1319,10 +1797,11 @@ int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, ...@@ -1319,10 +1797,11 @@ int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx,
int ret; int ret;
size_t siglen; size_t siglen;
unsigned char *p; unsigned char *p;
unsigned char *hash_start;
unsigned char result[MBEDTLS_MD_MAX_SIZE]; unsigned char result[MBEDTLS_MD_MAX_SIZE];
unsigned char zeros[8]; unsigned char zeros[8];
unsigned int hlen; unsigned int hlen;
size_t slen, msb; size_t observed_salt_len, msb;
const mbedtls_md_info_t *md_info; const mbedtls_md_info_t *md_info;
mbedtls_md_context_t md_ctx; mbedtls_md_context_t md_ctx;
unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
...@@ -1362,7 +1841,6 @@ int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, ...@@ -1362,7 +1841,6 @@ int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx,
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
hlen = mbedtls_md_get_size( md_info ); hlen = mbedtls_md_get_size( md_info );
slen = siglen - hlen - 1; /* Currently length of salt + padding */
memset( zeros, 0, 8 ); memset( zeros, 0, 8 );
...@@ -1371,61 +1849,77 @@ int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, ...@@ -1371,61 +1849,77 @@ int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx,
*/ */
msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; msb = mbedtls_mpi_bitlen( &ctx->N ) - 1;
if( buf[0] >> ( 8 - siglen * 8 + msb ) )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
/* Compensate for boundary condition when applying mask */ /* Compensate for boundary condition when applying mask */
if( msb % 8 == 0 ) if( msb % 8 == 0 )
{ {
p++; p++;
siglen -= 1; siglen -= 1;
} }
if( buf[0] >> ( 8 - siglen * 8 + msb ) )
if( siglen < hlen + 2 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
hash_start = p + siglen - hlen - 1;
mbedtls_md_init( &md_ctx ); mbedtls_md_init( &md_ctx );
if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 )
{ goto exit;
mbedtls_md_free( &md_ctx );
return( ret );
}
mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx ); ret = mgf_mask( p, siglen - hlen - 1, hash_start, hlen, &md_ctx );
if( ret != 0 )
goto exit;
buf[0] &= 0xFF >> ( siglen * 8 - msb ); buf[0] &= 0xFF >> ( siglen * 8 - msb );
while( p < buf + siglen && *p == 0 ) while( p < hash_start - 1 && *p == 0 )
p++; p++;
if( p == buf + siglen || if( *p++ != 0x01 )
*p++ != 0x01 )
{ {
mbedtls_md_free( &md_ctx ); ret = MBEDTLS_ERR_RSA_INVALID_PADDING;
return( MBEDTLS_ERR_RSA_INVALID_PADDING ); goto exit;
} }
/* Actual salt len */ observed_salt_len = hash_start - p;
slen -= p - buf;
if( expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY && if( expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY &&
slen != (size_t) expected_salt_len ) observed_salt_len != (size_t) expected_salt_len )
{ {
mbedtls_md_free( &md_ctx ); ret = MBEDTLS_ERR_RSA_INVALID_PADDING;
return( MBEDTLS_ERR_RSA_INVALID_PADDING ); goto exit;
} }
/* /*
* Generate H = Hash( M' ) * Generate H = Hash( M' )
*/ */
mbedtls_md_starts( &md_ctx ); ret = mbedtls_md_starts( &md_ctx );
mbedtls_md_update( &md_ctx, zeros, 8 ); if ( ret != 0 )
mbedtls_md_update( &md_ctx, hash, hashlen ); goto exit;
mbedtls_md_update( &md_ctx, p, slen ); ret = mbedtls_md_update( &md_ctx, zeros, 8 );
mbedtls_md_finish( &md_ctx, result ); if ( ret != 0 )
goto exit;
ret = mbedtls_md_update( &md_ctx, hash, hashlen );
if ( ret != 0 )
goto exit;
ret = mbedtls_md_update( &md_ctx, p, observed_salt_len );
if ( ret != 0 )
goto exit;
ret = mbedtls_md_finish( &md_ctx, result );
if ( ret != 0 )
goto exit;
if( memcmp( hash_start, result, hlen ) != 0 )
{
ret = MBEDTLS_ERR_RSA_VERIFY_FAILED;
goto exit;
}
exit:
mbedtls_md_free( &md_ctx ); mbedtls_md_free( &md_ctx );
if( memcmp( p + slen, result, hlen ) == 0 ) return( ret );
return( 0 );
else
return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
} }
/* /*
...@@ -1465,121 +1959,64 @@ int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, ...@@ -1465,121 +1959,64 @@ int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx,
const unsigned char *hash, const unsigned char *hash,
const unsigned char *sig ) const unsigned char *sig )
{ {
int ret; int ret = 0;
size_t len, siglen, asn1_len; const size_t sig_len = ctx->len;
unsigned char *p, *p0, *end; unsigned char *encoded = NULL, *encoded_expected = NULL;
mbedtls_md_type_t msg_md_alg;
const mbedtls_md_info_t *md_info;
mbedtls_asn1_buf oid;
unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
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 );
siglen = ctx->len; /*
* Prepare expected PKCS1 v1.5 encoding of hash.
if( siglen < 16 || siglen > sizeof( buf ) ) */
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
ret = ( mode == MBEDTLS_RSA_PUBLIC )
? mbedtls_rsa_public( ctx, sig, buf )
: mbedtls_rsa_private( ctx, f_rng, p_rng, sig, buf );
if( ret != 0 )
return( ret );
p = buf;
if( *p++ != 0 || *p++ != MBEDTLS_RSA_SIGN )
return( MBEDTLS_ERR_RSA_INVALID_PADDING );
while( *p != 0 )
{
if( p >= buf + siglen - 1 || *p != 0xFF )
return( MBEDTLS_ERR_RSA_INVALID_PADDING );
p++;
}
p++; /* skip 00 byte */
/* We've read: 00 01 PS 00 where PS must be at least 8 bytes */
if( p - buf < 11 )
return( MBEDTLS_ERR_RSA_INVALID_PADDING );
len = siglen - ( p - buf );
if( len == hashlen && md_alg == MBEDTLS_MD_NONE ) if( ( encoded = mbedtls_calloc( 1, sig_len ) ) == NULL ||
( encoded_expected = mbedtls_calloc( 1, sig_len ) ) == NULL )
{ {
if( memcmp( p, hash, hashlen ) == 0 ) ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;
return( 0 ); goto cleanup;
else
return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
} }
md_info = mbedtls_md_info_from_type( md_alg ); if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, sig_len,
if( md_info == NULL ) encoded_expected ) ) != 0 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); goto cleanup;
hashlen = mbedtls_md_get_size( md_info );
end = p + len;
/* /*
* Parse the ASN.1 structure inside the PKCS#1 v1.5 structure. * Apply RSA primitive to get what should be PKCS1 encoded hash.
* Insist on 2-byte length tags, to protect against variants of
* Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification.
*/ */
p0 = p;
if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, ret = ( mode == MBEDTLS_RSA_PUBLIC )
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) ? mbedtls_rsa_public( ctx, sig, encoded )
return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, encoded );
if( p != p0 + 2 || asn1_len + 2 != len ) if( ret != 0 )
return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); goto cleanup;
p0 = p;
if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
if( p != p0 + 2 || asn1_len + 6 + hashlen != len )
return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
p0 = p;
if( ( ret = mbedtls_asn1_get_tag( &p, end, &oid.len, MBEDTLS_ASN1_OID ) ) != 0 )
return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
if( p != p0 + 2 )
return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
oid.p = p;
p += oid.len;
if( mbedtls_oid_get_md_alg( &oid, &msg_md_alg ) != 0 )
return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
if( md_alg != msg_md_alg )
return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
/* /*
* assume the algorithm parameters must be NULL * Compare
*/ */
p0 = p;
if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, MBEDTLS_ASN1_NULL ) ) != 0 )
return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
if( p != p0 + 2 )
return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
p0 = p; if( ( ret = mbedtls_safer_memcmp( encoded, encoded_expected,
if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) sig_len ) ) != 0 )
return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); {
if( p != p0 + 2 || asn1_len != hashlen ) ret = MBEDTLS_ERR_RSA_VERIFY_FAILED;
return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); goto cleanup;
}
if( memcmp( p, hash, hashlen ) != 0 ) cleanup:
return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
p += hashlen; if( encoded != NULL )
{
mbedtls_zeroize( encoded, sig_len );
mbedtls_free( encoded );
}
if( p != end ) if( encoded_expected != NULL )
return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); {
mbedtls_zeroize( encoded_expected, sig_len );
mbedtls_free( encoded_expected );
}
return( 0 ); return( ret );
} }
#endif /* MBEDTLS_PKCS1_V15 */ #endif /* MBEDTLS_PKCS1_V15 */
...@@ -1630,13 +2067,16 @@ int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ) ...@@ -1630,13 +2067,16 @@ int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src )
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->D, &src->D ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->D, &src->D ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->P, &src->P ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->P, &src->P ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Q, &src->Q ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Q, &src->Q ) );
#if !defined(MBEDTLS_RSA_NO_CRT)
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DP, &src->DP ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DP, &src->DP ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DQ, &src->DQ ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DQ, &src->DQ ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->QP, &src->QP ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->QP, &src->QP ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RN, &src->RN ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RP, &src->RP ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RP, &src->RP ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RQ, &src->RQ ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RQ, &src->RQ ) );
#endif
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RN, &src->RN ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vi, &src->Vi ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vi, &src->Vi ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vf, &src->Vf ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vf, &src->Vf ) );
...@@ -1657,16 +2097,23 @@ cleanup: ...@@ -1657,16 +2097,23 @@ cleanup:
void mbedtls_rsa_free( mbedtls_rsa_context *ctx ) void mbedtls_rsa_free( mbedtls_rsa_context *ctx )
{ {
mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->Vf ); mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->Vf );
mbedtls_mpi_free( &ctx->RQ ); mbedtls_mpi_free( &ctx->RP ); mbedtls_mpi_free( &ctx->RN ); mbedtls_mpi_free( &ctx->RN ); mbedtls_mpi_free( &ctx->D );
mbedtls_mpi_free( &ctx->QP ); mbedtls_mpi_free( &ctx->DQ ); mbedtls_mpi_free( &ctx->DP ); mbedtls_mpi_free( &ctx->Q ); mbedtls_mpi_free( &ctx->P );
mbedtls_mpi_free( &ctx->Q ); mbedtls_mpi_free( &ctx->P ); mbedtls_mpi_free( &ctx->D );
mbedtls_mpi_free( &ctx->E ); mbedtls_mpi_free( &ctx->N ); 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->DP );
#endif /* MBEDTLS_RSA_NO_CRT */
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_free( &ctx->mutex ); mbedtls_mutex_free( &ctx->mutex );
#endif #endif
} }
#endif /* !MBEDTLS_RSA_ALT */
#if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_SELF_TEST)
#include "mbedtls/sha1.h" #include "mbedtls/sha1.h"
...@@ -1706,21 +2153,6 @@ void mbedtls_rsa_free( mbedtls_rsa_context *ctx ) ...@@ -1706,21 +2153,6 @@ void mbedtls_rsa_free( mbedtls_rsa_context *ctx )
"910E4168387E3C30AA1E00C339A79508" \ "910E4168387E3C30AA1E00C339A79508" \
"8452DD96A9A5EA5D9DCA68DA636032AF" "8452DD96A9A5EA5D9DCA68DA636032AF"
#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \
"3C94D22288ACD763FD8E5600ED4A702D" \
"F84198A5F06C2E72236AE490C93F07F8" \
"3CC559CD27BC2D1CA488811730BB5725"
#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \
"D8AAEA56749EA28623272E4F7D0592AF" \
"7C1F1313CAC9471B5C523BFE592F517B" \
"407A1BD76C164B93DA2D32A383E58357"
#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \
"F38D18D2B2F0E2DD275AA977E2BF4411" \
"F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
"A74206CEC169D74BF5A8C50D6F48EA08"
#define PT_LEN 24 #define PT_LEN 24
#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \ #define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \
"\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD" "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD"
...@@ -1763,17 +2195,23 @@ int mbedtls_rsa_self_test( int verbose ) ...@@ -1763,17 +2195,23 @@ int mbedtls_rsa_self_test( int verbose )
unsigned char sha1sum[20]; unsigned char sha1sum[20];
#endif #endif
mbedtls_mpi K;
mbedtls_mpi_init( &K );
mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 );
rsa.len = KEY_LEN; MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_N ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.N , 16, RSA_N ) ); MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, &K, NULL, NULL, NULL, NULL ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.E , 16, RSA_E ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_P ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.D , 16, RSA_D ) ); MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, &K, NULL, NULL, NULL ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.P , 16, RSA_P ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_Q ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.Q , 16, RSA_Q ) ); MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, &K, NULL, NULL ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.DP, 16, RSA_DP ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_D ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.DQ, 16, RSA_DQ ) ); MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, &K, NULL ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.QP, 16, RSA_QP ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_E ) );
MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, NULL, &K ) );
MBEDTLS_MPI_CHK( mbedtls_rsa_complete( &rsa ) );
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( " RSA key validation: " ); mbedtls_printf( " RSA key validation: " );
...@@ -1792,8 +2230,9 @@ int mbedtls_rsa_self_test( int verbose ) ...@@ -1792,8 +2230,9 @@ int mbedtls_rsa_self_test( int verbose )
memcpy( rsa_plaintext, RSA_PT, PT_LEN ); memcpy( rsa_plaintext, RSA_PT, PT_LEN );
if( mbedtls_rsa_pkcs1_encrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PUBLIC, PT_LEN, if( mbedtls_rsa_pkcs1_encrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PUBLIC,
rsa_plaintext, rsa_ciphertext ) != 0 ) PT_LEN, rsa_plaintext,
rsa_ciphertext ) != 0 )
{ {
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( "failed\n" ); mbedtls_printf( "failed\n" );
...@@ -1804,9 +2243,9 @@ int mbedtls_rsa_self_test( int verbose ) ...@@ -1804,9 +2243,9 @@ int mbedtls_rsa_self_test( int verbose )
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( "passed\n PKCS#1 decryption : " ); mbedtls_printf( "passed\n PKCS#1 decryption : " );
if( mbedtls_rsa_pkcs1_decrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, &len, if( mbedtls_rsa_pkcs1_decrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE,
rsa_ciphertext, rsa_decrypted, &len, rsa_ciphertext, rsa_decrypted,
sizeof(rsa_decrypted) ) != 0 ) sizeof(rsa_decrypted) ) != 0 )
{ {
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( "failed\n" ); mbedtls_printf( "failed\n" );
...@@ -1829,10 +2268,17 @@ int mbedtls_rsa_self_test( int verbose ) ...@@ -1829,10 +2268,17 @@ int mbedtls_rsa_self_test( int verbose )
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( " PKCS#1 data sign : " ); mbedtls_printf( " PKCS#1 data sign : " );
mbedtls_sha1( rsa_plaintext, PT_LEN, sha1sum ); if( mbedtls_sha1_ret( rsa_plaintext, PT_LEN, sha1sum ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
if( mbedtls_rsa_pkcs1_sign( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 0, if( mbedtls_rsa_pkcs1_sign( &rsa, myrand, NULL,
sha1sum, rsa_ciphertext ) != 0 ) MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 0,
sha1sum, rsa_ciphertext ) != 0 )
{ {
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( "failed\n" ); mbedtls_printf( "failed\n" );
...@@ -1843,8 +2289,9 @@ int mbedtls_rsa_self_test( int verbose ) ...@@ -1843,8 +2289,9 @@ int mbedtls_rsa_self_test( int verbose )
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( "passed\n PKCS#1 sig. verify: " ); mbedtls_printf( "passed\n PKCS#1 sig. verify: " );
if( mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 0, if( mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL,
sha1sum, rsa_ciphertext ) != 0 ) MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 0,
sha1sum, rsa_ciphertext ) != 0 )
{ {
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( "failed\n" ); mbedtls_printf( "failed\n" );
...@@ -1860,6 +2307,7 @@ int mbedtls_rsa_self_test( int verbose ) ...@@ -1860,6 +2307,7 @@ int mbedtls_rsa_self_test( int verbose )
mbedtls_printf( "\n" ); mbedtls_printf( "\n" );
cleanup: cleanup:
mbedtls_mpi_free( &K );
mbedtls_rsa_free( &rsa ); mbedtls_rsa_free( &rsa );
#else /* MBEDTLS_PKCS1_V15 */ #else /* MBEDTLS_PKCS1_V15 */
((void) verbose); ((void) verbose);
......
/*
* Helper functions for the RSA module
*
* Copyright (C) 2006-2017, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_RSA_C)
#include "mbedtls/rsa.h"
#include "mbedtls/bignum.h"
#include "mbedtls/rsa_internal.h"
/*
* Compute RSA prime factors from public and private exponents
*
* Summary of algorithm:
* Setting F := lcm(P-1,Q-1), the idea is as follows:
*
* (a) For any 1 <= X < N with gcd(X,N)=1, we have X^F = 1 modulo N, so X^(F/2)
* is a square root of 1 in Z/NZ. Since Z/NZ ~= Z/PZ x Z/QZ by CRT and the
* square roots of 1 in Z/PZ and Z/QZ are +1 and -1, this leaves the four
* possibilities X^(F/2) = (+-1, +-1). If it happens that X^(F/2) = (-1,+1)
* or (+1,-1), then gcd(X^(F/2) + 1, N) will be equal to one of the prime
* factors of N.
*
* (b) If we don't know F/2 but (F/2) * K for some odd (!) K, then the same
* construction still applies since (-)^K is the identity on the set of
* roots of 1 in Z/NZ.
*
* The public and private key primitives (-)^E and (-)^D are mutually inverse
* bijections on Z/NZ if and only if (-)^(DE) is the identity on Z/NZ, i.e.
* if and only if DE - 1 is a multiple of F, say DE - 1 = F * L.
* Splitting L = 2^t * K with K odd, we have
*
* DE - 1 = FL = (F/2) * (2^(t+1)) * K,
*
* so (F / 2) * K is among the numbers
*
* (DE - 1) >> 1, (DE - 1) >> 2, ..., (DE - 1) >> ord
*
* where ord is the order of 2 in (DE - 1).
* We can therefore iterate through these numbers apply the construction
* of (a) and (b) above to attempt to factor N.
*
*/
int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N,
mbedtls_mpi const *E, mbedtls_mpi const *D,
mbedtls_mpi *P, mbedtls_mpi *Q )
{
int ret = 0;
uint16_t attempt; /* Number of current attempt */
uint16_t iter; /* Number of squares computed in the current attempt */
uint16_t order; /* Order of 2 in DE - 1 */
mbedtls_mpi T; /* Holds largest odd divisor of DE - 1 */
mbedtls_mpi K; /* Temporary holding the current candidate */
const unsigned char primes[] = { 2,
3, 5, 7, 11, 13, 17, 19, 23,
29, 31, 37, 41, 43, 47, 53, 59,
61, 67, 71, 73, 79, 83, 89, 97,
101, 103, 107, 109, 113, 127, 131, 137,
139, 149, 151, 157, 163, 167, 173, 179,
181, 191, 193, 197, 199, 211, 223, 227,
229, 233, 239, 241, 251
};
const size_t num_primes = sizeof( primes ) / sizeof( *primes );
if( P == NULL || Q == NULL || P->p != NULL || Q->p != NULL )
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 ||
mbedtls_mpi_cmp_int( D, 1 ) <= 0 ||
mbedtls_mpi_cmp_mpi( D, N ) >= 0 ||
mbedtls_mpi_cmp_int( E, 1 ) <= 0 ||
mbedtls_mpi_cmp_mpi( E, N ) >= 0 )
{
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
}
/*
* Initializations and temporary changes
*/
mbedtls_mpi_init( &K );
mbedtls_mpi_init( &T );
/* T := DE - 1 */
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, D, E ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &T, &T, 1 ) );
if( ( order = (uint16_t) mbedtls_mpi_lsb( &T ) ) == 0 )
{
ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
goto cleanup;
}
/* After this operation, T holds the largest odd divisor of DE - 1. */
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &T, order ) );
/*
* Actual work
*/
/* Skip trying 2 if N == 1 mod 8 */
attempt = 0;
if( N->p[0] % 8 == 1 )
attempt = 1;
for( ; attempt < num_primes; ++attempt )
{
mbedtls_mpi_lset( &K, primes[attempt] );
/* Check if gcd(K,N) = 1 */
MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) );
if( mbedtls_mpi_cmp_int( P, 1 ) != 0 )
continue;
/* Go through K^T + 1, K^(2T) + 1, K^(4T) + 1, ...
* and check whether they have nontrivial GCD with N. */
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &K, &K, &T, N,
Q /* temporarily use Q for storing Montgomery
* multiplication helper values */ ) );
for( iter = 1; iter <= order; ++iter )
{
/* If we reach 1 prematurely, there's no point
* in continuing to square K */
if( mbedtls_mpi_cmp_int( &K, 1 ) == 0 )
break;
MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &K, &K, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) );
if( mbedtls_mpi_cmp_int( P, 1 ) == 1 &&
mbedtls_mpi_cmp_mpi( P, N ) == -1 )
{
/*
* Have found a nontrivial divisor P of N.
* Set Q := N / P.
*/
MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( Q, NULL, N, P ) );
goto cleanup;
}
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &K ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, N ) );
}
/*
* If we get here, then either we prematurely aborted the loop because
* we reached 1, or K holds primes[attempt]^(DE - 1) mod N, which must
* be 1 if D,E,N were consistent.
* Check if that's the case and abort if not, to avoid very long,
* yet eventually failing, computations if N,D,E were not sane.
*/
if( mbedtls_mpi_cmp_int( &K, 1 ) != 0 )
{
break;
}
}
ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
cleanup:
mbedtls_mpi_free( &K );
mbedtls_mpi_free( &T );
return( ret );
}
/*
* Given P, Q and the public exponent E, deduce D.
* This is essentially a modular inversion.
*/
int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P,
mbedtls_mpi const *Q,
mbedtls_mpi const *E,
mbedtls_mpi *D )
{
int ret = 0;
mbedtls_mpi K, L;
if( D == NULL || mbedtls_mpi_cmp_int( D, 0 ) != 0 )
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 ||
mbedtls_mpi_cmp_int( Q, 1 ) <= 0 ||
mbedtls_mpi_cmp_int( E, 0 ) == 0 )
{
return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
}
mbedtls_mpi_init( &K );
mbedtls_mpi_init( &L );
/* Temporarily put K := P-1 and L := Q-1 */
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) );
/* Temporarily put D := gcd(P-1, Q-1) */
MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( D, &K, &L ) );
/* K := LCM(P-1, Q-1) */
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &L ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &K, NULL, &K, D ) );
/* Compute modular inverse of E in LCM(P-1, Q-1) */
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( D, E, &K ) );
cleanup:
mbedtls_mpi_free( &K );
mbedtls_mpi_free( &L );
return( ret );
}
/*
* Check that RSA CRT parameters are in accordance with core parameters.
*/
int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q,
const mbedtls_mpi *D, const mbedtls_mpi *DP,
const mbedtls_mpi *DQ, const mbedtls_mpi *QP )
{
int ret = 0;
mbedtls_mpi K, L;
mbedtls_mpi_init( &K );
mbedtls_mpi_init( &L );
/* Check that DP - D == 0 mod P - 1 */
if( DP != NULL )
{
if( P == NULL )
{
ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
goto cleanup;
}
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DP, D ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) );
if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
}
/* Check that DQ - D == 0 mod Q - 1 */
if( DQ != NULL )
{
if( Q == NULL )
{
ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
goto cleanup;
}
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DQ, D ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) );
if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
}
/* Check that QP * Q - 1 == 0 mod P */
if( QP != NULL )
{
if( P == NULL || Q == NULL )
{
ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
goto cleanup;
}
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, QP, Q ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, P ) );
if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
}
cleanup:
/* Wrap MPI error codes by RSA check failure error code */
if( ret != 0 &&
ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED &&
ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA )
{
ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
}
mbedtls_mpi_free( &K );
mbedtls_mpi_free( &L );
return( ret );
}
/*
* Check that core RSA parameters are sane.
*/
int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P,
const mbedtls_mpi *Q, const mbedtls_mpi *D,
const mbedtls_mpi *E,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
int ret = 0;
mbedtls_mpi K, L;
mbedtls_mpi_init( &K );
mbedtls_mpi_init( &L );
/*
* Step 1: If PRNG provided, check that P and Q are prime
*/
#if defined(MBEDTLS_GENPRIME)
if( f_rng != NULL && P != NULL &&
( ret = mbedtls_mpi_is_prime( P, f_rng, p_rng ) ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
if( f_rng != NULL && Q != NULL &&
( ret = mbedtls_mpi_is_prime( Q, f_rng, p_rng ) ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
#else
((void) f_rng);
((void) p_rng);
#endif /* MBEDTLS_GENPRIME */
/*
* Step 2: Check that 1 < N = P * Q
*/
if( P != NULL && Q != NULL && N != NULL )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, P, Q ) );
if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 ||
mbedtls_mpi_cmp_mpi( &K, N ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
}
/*
* Step 3: Check and 1 < D, E < N if present.
*/
if( N != NULL && D != NULL && E != NULL )
{
if ( mbedtls_mpi_cmp_int( D, 1 ) <= 0 ||
mbedtls_mpi_cmp_int( E, 1 ) <= 0 ||
mbedtls_mpi_cmp_mpi( D, N ) >= 0 ||
mbedtls_mpi_cmp_mpi( E, N ) >= 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
}
/*
* Step 4: Check that D, E are inverse modulo P-1 and Q-1
*/
if( P != NULL && Q != NULL && D != NULL && E != NULL )
{
if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 ||
mbedtls_mpi_cmp_int( Q, 1 ) <= 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
/* Compute DE-1 mod P-1 */
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, P, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) );
if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
/* Compute DE-1 mod Q-1 */
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) );
if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 )
{
ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
goto cleanup;
}
}
cleanup:
mbedtls_mpi_free( &K );
mbedtls_mpi_free( &L );
/* Wrap MPI error codes by RSA check failure error code */
if( ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED )
{
ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
}
return( ret );
}
int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q,
const mbedtls_mpi *D, mbedtls_mpi *DP,
mbedtls_mpi *DQ, mbedtls_mpi *QP )
{
int ret = 0;
mbedtls_mpi K;
mbedtls_mpi_init( &K );
/* DP = D mod P-1 */
if( DP != NULL )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DP, D, &K ) );
}
/* DQ = D mod Q-1 */
if( DQ != NULL )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DQ, D, &K ) );
}
/* QP = Q^{-1} mod P */
if( QP != NULL )
{
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( QP, Q, P ) );
}
cleanup:
mbedtls_mpi_free( &K );
return( ret );
}
#endif /* MBEDTLS_RSA_C */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment