[MBEDTLS] Update to version 2.7.9. CORE-15280

This commit is contained in:
Thomas Faber 2019-01-05 11:14:58 +01:00
parent e5fc2b4ce3
commit 0ba5bc40fb
No known key found for this signature in database
GPG Key ID: 076E7C3D44720826
28 changed files with 733 additions and 427 deletions

View File

@ -333,14 +333,36 @@ int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start,
return( (int) len ); return( (int) len );
} }
mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **head,
/* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(),
* which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */
static mbedtls_asn1_named_data *asn1_find_named_data(
mbedtls_asn1_named_data *list,
const char *oid, size_t len )
{
while( list != NULL )
{
if( list->oid.len == len &&
memcmp( list->oid.p, oid, len ) == 0 )
{
break;
}
list = list->next;
}
return( list );
}
mbedtls_asn1_named_data *mbedtls_asn1_store_named_data(
mbedtls_asn1_named_data **head,
const char *oid, size_t oid_len, const char *oid, size_t oid_len,
const unsigned char *val, const unsigned char *val,
size_t val_len ) size_t val_len )
{ {
mbedtls_asn1_named_data *cur; mbedtls_asn1_named_data *cur;
if( ( cur = mbedtls_asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL )
{ {
// Add new entry if not present yet based on OID // Add new entry if not present yet based on OID
// //

View File

@ -320,6 +320,10 @@ int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos )
return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 ); return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 );
} }
/* Get a specific byte, without range checks. */
#define GET_BYTE( X, i ) \
( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff )
/* /*
* Set a bit to a specific value of 0 or 1 * Set a bit to a specific value of 0 or 1
*/ */
@ -703,19 +707,40 @@ cleanup:
/* /*
* Export X into unsigned binary data, big endian * Export X into unsigned binary data, big endian
*/ */
int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ) int mbedtls_mpi_write_binary( const mbedtls_mpi *X,
unsigned char *buf, size_t buflen )
{ {
size_t i, j, n; size_t stored_bytes = X->n * ciL;
size_t bytes_to_copy;
unsigned char *p;
size_t i;
n = mbedtls_mpi_size( X ); if( stored_bytes < buflen )
{
/* There is enough space in the output buffer. Write initial
* null bytes and record the position at which to start
* writing the significant bytes. In this case, the execution
* trace of this function does not depend on the value of the
* number. */
bytes_to_copy = stored_bytes;
p = buf + buflen - stored_bytes;
memset( buf, 0, buflen - stored_bytes );
}
else
{
/* The output buffer is smaller than the allocated size of X.
* However X may fit if its leading bytes are zero. */
bytes_to_copy = buflen;
p = buf;
for( i = bytes_to_copy; i < stored_bytes; i++ )
{
if( GET_BYTE( X, i ) != 0 )
return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL );
}
}
if( buflen < n ) for( i = 0; i < bytes_to_copy; i++ )
return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); p[bytes_to_copy - i - 1] = GET_BYTE( X, i );
memset( buf, 0, buflen );
for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- )
buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) );
return( 0 ); return( 0 );
} }
@ -2055,12 +2080,12 @@ cleanup:
/* /*
* Miller-Rabin pseudo-primality test (HAC 4.24) * Miller-Rabin pseudo-primality test (HAC 4.24)
*/ */
static int mpi_miller_rabin( const mbedtls_mpi *X, static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds,
int (*f_rng)(void *, unsigned char *, size_t), int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng ) void *p_rng )
{ {
int ret, count; int ret, count;
size_t i, j, k, n, s; size_t i, j, k, s;
mbedtls_mpi W, R, T, A, RR; mbedtls_mpi W, R, T, A, RR;
mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A ); mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A );
@ -2076,27 +2101,12 @@ static int mpi_miller_rabin( const mbedtls_mpi *X,
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) );
i = mbedtls_mpi_bitlen( X ); i = mbedtls_mpi_bitlen( X );
/*
* HAC, table 4.4
*/
n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 :
( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 :
( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 );
for( i = 0; i < n; i++ ) for( i = 0; i < rounds; i++ )
{ {
/* /*
* pick a random A, 1 < A < |X| - 1 * pick a random A, 1 < A < |X| - 1
*/ */
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 )
{
j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W );
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) );
}
A.p[0] |= 3;
count = 0; count = 0;
do { do {
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) );
@ -2104,7 +2114,7 @@ static int mpi_miller_rabin( const mbedtls_mpi *X,
j = mbedtls_mpi_bitlen( &A ); j = mbedtls_mpi_bitlen( &A );
k = mbedtls_mpi_bitlen( &W ); k = mbedtls_mpi_bitlen( &W );
if (j > k) { if (j > k) {
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) ); A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1;
} }
if (count++ > 30) { if (count++ > 30) {
@ -2159,7 +2169,7 @@ cleanup:
/* /*
* Pseudo-primality test: small factors, then Miller-Rabin * Pseudo-primality test: small factors, then Miller-Rabin
*/ */
int mbedtls_mpi_is_prime( const mbedtls_mpi *X, static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds,
int (*f_rng)(void *, unsigned char *, size_t), int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng ) void *p_rng )
{ {
@ -2185,7 +2195,17 @@ int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
return( ret ); return( ret );
} }
return( mpi_miller_rabin( &XX, f_rng, p_rng ) ); return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) );
}
/*
* Pseudo-primality test, error probability 2^-80
*/
int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng )
{
return mpi_is_prime_internal( X, 40, f_rng, p_rng );
} }
/* /*
@ -2197,6 +2217,7 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
{ {
int ret; int ret;
size_t k, n; size_t k, n;
int rounds;
mbedtls_mpi_uint r; mbedtls_mpi_uint r;
mbedtls_mpi Y; mbedtls_mpi Y;
@ -2207,6 +2228,13 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
n = BITS_TO_LIMBS( nbits ); n = BITS_TO_LIMBS( nbits );
/*
* 2^-80 error probability, number of rounds chosen per HAC, table 4.4
*/
rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 :
( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 :
( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 );
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) );
k = mbedtls_mpi_bitlen( X ); k = mbedtls_mpi_bitlen( X );
@ -2218,7 +2246,7 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
if( dh_flag == 0 ) if( dh_flag == 0 )
{ {
while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 ) while( ( ret = mpi_is_prime_internal( X, rounds, f_rng, p_rng ) ) != 0 )
{ {
if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
goto cleanup; goto cleanup;
@ -2254,8 +2282,10 @@ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag,
*/ */
if( ( ret = mpi_check_small_factors( X ) ) == 0 && if( ( ret = mpi_check_small_factors( X ) ) == 0 &&
( ret = mpi_check_small_factors( &Y ) ) == 0 && ( ret = mpi_check_small_factors( &Y ) ) == 0 &&
( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 && ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) )
( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 ) == 0 &&
( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) )
== 0 )
{ {
break; break;
} }

View File

@ -213,9 +213,13 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
const unsigned char *iv, size_t iv_len ) const unsigned char *iv, size_t iv_len )
{ {
size_t actual_iv_size; size_t actual_iv_size;
if( NULL == ctx || NULL == ctx->cipher_info )
if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
else if( NULL == iv && iv_len != 0 )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
if( NULL == iv && iv_len == 0 )
ctx->iv_size = 0;
/* avoid buffer overflow in ctx->iv */ /* avoid buffer overflow in ctx->iv */
if( iv_len > MBEDTLS_MAX_IV_LENGTH ) if( iv_len > MBEDTLS_MAX_IV_LENGTH )
@ -231,9 +235,11 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
if( actual_iv_size > iv_len ) if( actual_iv_size > iv_len )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
} }
if ( actual_iv_size != 0 )
memcpy( ctx->iv, iv, actual_iv_size ); {
ctx->iv_size = actual_iv_size; memcpy( ctx->iv, iv, actual_iv_size );
ctx->iv_size = actual_iv_size;
}
return( 0 ); return( 0 );
} }

View File

@ -206,7 +206,7 @@ static const mbedtls_cipher_info_t aes_128_ecb_info = {
MBEDTLS_MODE_ECB, MBEDTLS_MODE_ECB,
128, 128,
"AES-128-ECB", "AES-128-ECB",
16, 0,
0, 0,
16, 16,
&aes_info &aes_info
@ -217,7 +217,7 @@ static const mbedtls_cipher_info_t aes_192_ecb_info = {
MBEDTLS_MODE_ECB, MBEDTLS_MODE_ECB,
192, 192,
"AES-192-ECB", "AES-192-ECB",
16, 0,
0, 0,
16, 16,
&aes_info &aes_info
@ -228,7 +228,7 @@ static const mbedtls_cipher_info_t aes_256_ecb_info = {
MBEDTLS_MODE_ECB, MBEDTLS_MODE_ECB,
256, 256,
"AES-256-ECB", "AES-256-ECB",
16, 0,
0, 0,
16, 16,
&aes_info &aes_info

View File

@ -285,9 +285,7 @@ static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
* Crypt counter block * Crypt counter block
*/ */
if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 ) if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 )
{ goto exit;
return( ret );
}
p += MBEDTLS_CTR_DRBG_BLOCKSIZE; p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
} }
@ -299,29 +297,44 @@ static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
* Update key and counter * Update key and counter
*/ */
if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
{ goto exit;
return( ret );
}
memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE ); memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE );
return( 0 ); exit:
mbedtls_zeroize( tmp, sizeof( tmp ) );
return( ret );
} }
void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
const unsigned char *additional, size_t add_len ) const unsigned char *additional,
size_t add_len )
{ {
unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
int ret;
if( add_len > 0 ) if( add_len == 0 )
{ return( 0 );
/* MAX_INPUT would be more logical here, but we have to match
* block_cipher_df()'s limits since we can't propagate errors */
if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
block_cipher_df( add_input, additional, add_len ); if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
ctr_drbg_update_internal( ctx, add_input ); goto exit;
} if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
goto exit;
exit:
mbedtls_zeroize( add_input, sizeof( add_input ) );
return( ret );
}
/* Deprecated function, kept for backward compatibility. */
void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
const unsigned char *additional,
size_t add_len )
{
/* MAX_INPUT would be more logical here, but we have to match
* block_cipher_df()'s limits since we can't propagate errors */
if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
(void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
} }
int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
@ -361,20 +374,18 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
* Reduce to 384 bits * Reduce to 384 bits
*/ */
if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 ) if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
{ goto exit;
return( ret );
}
/* /*
* Update state * Update state
*/ */
if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 ) if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
{ goto exit;
return( ret );
}
ctx->reseed_counter = 1; ctx->reseed_counter = 1;
return( 0 ); exit:
mbedtls_zeroize( seed, sizeof( seed ) );
return( ret );
} }
int mbedtls_ctr_drbg_random_with_add( void *p_rng, int mbedtls_ctr_drbg_random_with_add( void *p_rng,
@ -410,13 +421,9 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng,
if( add_len > 0 ) if( add_len > 0 )
{ {
if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
{ goto exit;
return( ret );
}
if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
{ goto exit;
return( ret );
}
} }
while( output_len > 0 ) while( output_len > 0 )
@ -432,9 +439,7 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng,
* Crypt counter block * Crypt counter block
*/ */
if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 ) if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 )
{ goto exit;
return( ret );
}
use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE :
output_len; output_len;
@ -447,12 +452,13 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng,
} }
if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
{ goto exit;
return( ret );
}
ctx->reseed_counter++; ctx->reseed_counter++;
exit:
mbedtls_zeroize( add_input, sizeof( add_input ) );
mbedtls_zeroize( tmp, sizeof( tmp ) );
return( 0 ); return( 0 );
} }
@ -524,7 +530,7 @@ int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char
if( fread( buf, 1, n, f ) != n ) if( fread( buf, 1, n, f ) != n )
ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
else else
mbedtls_ctr_drbg_update( ctx, buf, n ); ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
fclose( f ); fclose( f );

View File

@ -411,7 +411,7 @@ int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt )
} }
/* /*
* Compare two points lazyly * Compare two points lazily
*/ */
int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
const mbedtls_ecp_point *Q ) const mbedtls_ecp_point *Q )

View File

@ -94,6 +94,7 @@ int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len
#include <sys/syscall.h> #include <sys/syscall.h>
#if defined(SYS_getrandom) #if defined(SYS_getrandom)
#define HAVE_GETRANDOM #define HAVE_GETRANDOM
#include <errno.h>
static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags )
{ {
@ -103,47 +104,8 @@ static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags )
memset( buf, 0, buflen ); memset( buf, 0, buflen );
#endif #endif
#endif #endif
return( syscall( SYS_getrandom, buf, buflen, flags ) ); return( syscall( SYS_getrandom, buf, buflen, flags ) );
} }
#include <sys/utsname.h>
/* Check if version is at least 3.17.0 */
static int check_version_3_17_plus( void )
{
int minor;
struct utsname un;
const char *ver;
/* Get version information */
uname(&un);
ver = un.release;
/* Check major version; assume a single digit */
if( ver[0] < '3' || ver[0] > '9' || ver [1] != '.' )
return( -1 );
if( ver[0] - '0' > 3 )
return( 0 );
/* Ok, so now we know major == 3, check minor.
* Assume 1 or 2 digits. */
if( ver[2] < '0' || ver[2] > '9' )
return( -1 );
minor = ver[2] - '0';
if( ver[3] >= '0' && ver[3] <= '9' )
minor = 10 * minor + ver[3] - '0';
else if( ver [3] != '.' )
return( -1 );
if( minor < 17 )
return( -1 );
return( 0 );
}
static int has_getrandom = -1;
#endif /* SYS_getrandom */ #endif /* SYS_getrandom */
#endif /* __linux__ */ #endif /* __linux__ */
@ -154,22 +116,21 @@ int mbedtls_platform_entropy_poll( void *data,
{ {
FILE *file; FILE *file;
size_t read_len; size_t read_len;
int ret;
((void) data); ((void) data);
#if defined(HAVE_GETRANDOM) #if defined(HAVE_GETRANDOM)
if( has_getrandom == -1 ) ret = getrandom_wrapper( output, len, 0 );
has_getrandom = ( check_version_3_17_plus() == 0 ); if( ret >= 0 )
if( has_getrandom )
{ {
int ret;
if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 )
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
*olen = ret; *olen = ret;
return( 0 ); return( 0 );
} }
else if( errno != ENOSYS )
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
/* Fall through if the system call isn't known. */
#else
((void) ret);
#endif /* HAVE_GETRANDOM */ #endif /* HAVE_GETRANDOM */
*olen = 0; *olen = 0;

View File

@ -72,29 +72,56 @@ void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
/* /*
* HMAC_DRBG update, using optional additional data (10.1.2.2) * HMAC_DRBG update, using optional additional data (10.1.2.2)
*/ */
void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
const unsigned char *additional, size_t add_len ) const unsigned char *additional,
size_t add_len )
{ {
size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1; unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
unsigned char sep[1]; unsigned char sep[1];
unsigned char K[MBEDTLS_MD_MAX_SIZE]; unsigned char K[MBEDTLS_MD_MAX_SIZE];
int ret;
for( sep[0] = 0; sep[0] < rounds; sep[0]++ ) for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
{ {
/* Step 1 or 4 */ /* Step 1 or 4 */
mbedtls_md_hmac_reset( &ctx->md_ctx ); if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); goto exit;
mbedtls_md_hmac_update( &ctx->md_ctx, sep, 1 ); if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
ctx->V, md_len ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
sep, 1 ) ) != 0 )
goto exit;
if( rounds == 2 ) if( rounds == 2 )
mbedtls_md_hmac_update( &ctx->md_ctx, additional, add_len ); {
mbedtls_md_hmac_finish( &ctx->md_ctx, K ); if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
additional, add_len ) ) != 0 )
goto exit;
}
if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 )
goto exit;
/* Step 2 or 5 */ /* Step 2 or 5 */
mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ); if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 )
mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); goto exit;
mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ); if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
ctx->V, md_len ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
goto exit;
} }
exit:
mbedtls_zeroize( K, sizeof( K ) );
return( ret );
}
void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
const unsigned char *additional,
size_t add_len )
{
(void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len );
} }
/* /*
@ -114,10 +141,13 @@ int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
* Use the V memory location, which is currently all 0, to initialize the * Use the V memory location, which is currently all 0, to initialize the
* MD context with an all-zero key. Then set V to its initial value. * MD context with an all-zero key. Then set V to its initial value.
*/ */
mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedtls_md_get_size( md_info ) ); if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V,
mbedtls_md_get_size( md_info ) ) ) != 0 )
return( ret );
memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) ); memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
mbedtls_hmac_drbg_update( ctx, data, data_len ); if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 )
return( ret );
return( 0 ); return( 0 );
} }
@ -130,6 +160,7 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
{ {
unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT]; unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
size_t seedlen; size_t seedlen;
int ret;
/* III. Check input length */ /* III. Check input length */
if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT || if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
@ -141,7 +172,8 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ); memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
/* IV. Gather entropy_len bytes of entropy for the seed */ /* IV. Gather entropy_len bytes of entropy for the seed */
if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 ) if( ( ret = ctx->f_entropy( ctx->p_entropy,
seed, ctx->entropy_len ) ) != 0 )
return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
seedlen = ctx->entropy_len; seedlen = ctx->entropy_len;
@ -154,13 +186,16 @@ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
} }
/* 2. Update state */ /* 2. Update state */
mbedtls_hmac_drbg_update( ctx, seed, seedlen ); if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 )
goto exit;
/* 3. Reset reseed_counter */ /* 3. Reset reseed_counter */
ctx->reseed_counter = 1; ctx->reseed_counter = 1;
exit:
/* 4. Done */ /* 4. Done */
return( 0 ); mbedtls_zeroize( seed, seedlen );
return( ret );
} }
/* /*
@ -186,7 +221,8 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
* Use the V memory location, which is currently all 0, to initialize the * Use the V memory location, which is currently all 0, to initialize the
* MD context with an all-zero key. Then set V to its initial value. * MD context with an all-zero key. Then set V to its initial value.
*/ */
mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ); if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 )
return( ret );
memset( ctx->V, 0x01, md_size ); memset( ctx->V, 0x01, md_size );
ctx->f_entropy = f_entropy; ctx->f_entropy = f_entropy;
@ -279,16 +315,24 @@ int mbedtls_hmac_drbg_random_with_add( void *p_rng,
/* 2. Use additional data if any */ /* 2. Use additional data if any */
if( additional != NULL && add_len != 0 ) if( additional != NULL && add_len != 0 )
mbedtls_hmac_drbg_update( ctx, additional, add_len ); {
if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
additional, add_len ) ) != 0 )
goto exit;
}
/* 3, 4, 5. Generate bytes */ /* 3, 4, 5. Generate bytes */
while( left != 0 ) while( left != 0 )
{ {
size_t use_len = left > md_len ? md_len : left; size_t use_len = left > md_len ? md_len : left;
mbedtls_md_hmac_reset( &ctx->md_ctx ); if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); goto exit;
mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ); if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
ctx->V, md_len ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
goto exit;
memcpy( out, ctx->V, use_len ); memcpy( out, ctx->V, use_len );
out += use_len; out += use_len;
@ -296,13 +340,16 @@ int mbedtls_hmac_drbg_random_with_add( void *p_rng,
} }
/* 6. Update */ /* 6. Update */
mbedtls_hmac_drbg_update( ctx, additional, add_len ); if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
additional, add_len ) ) != 0 )
goto exit;
/* 7. Update reseed counter */ /* 7. Update reseed counter */
ctx->reseed_counter++; ctx->reseed_counter++;
exit:
/* 8. Done */ /* 8. Done */
return( 0 ); return( ret );
} }
/* /*
@ -394,7 +441,7 @@ 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; ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
else else
mbedtls_hmac_drbg_update( ctx, buf, n ); ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
fclose( f ); fclose( f );

View File

@ -54,6 +54,8 @@ 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;
} }
#if defined(MBEDTLS_ASN1_PARSE_C)
static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params, static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params,
mbedtls_asn1_buf *salt, int *iterations ) mbedtls_asn1_buf *salt, int *iterations )
{ {
@ -232,6 +234,8 @@ exit:
return( ret ); return( ret );
} }
#endif /* MBEDTLS_ASN1_PARSE_C */
static void pkcs12_fill_buffer( unsigned char *data, size_t data_len, static void pkcs12_fill_buffer( unsigned char *data, size_t data_len,
const unsigned char *filler, size_t fill_len ) const unsigned char *filler, size_t fill_len )
{ {

View File

@ -56,22 +56,7 @@
#define mbedtls_printf printf #define mbedtls_printf printf
#endif #endif
#if !defined(MBEDTLS_ASN1_PARSE_C) #if defined(MBEDTLS_ASN1_PARSE_C)
int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode,
const unsigned char *pwd, size_t pwdlen,
const unsigned char *data, size_t datalen,
unsigned char *output )
{
((void) pbe_params);
((void) mode);
((void) pwd);
((void) pwdlen);
((void) data);
((void) datalen);
((void) output);
return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE );
}
#else
static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params, static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params,
mbedtls_asn1_buf *salt, int *iterations, mbedtls_asn1_buf *salt, int *iterations,
int *keylen, mbedtls_md_type_t *md_type ) int *keylen, mbedtls_md_type_t *md_type )

View File

@ -1304,6 +1304,7 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
return( 0 ); return( 0 );
mbedtls_pk_free( pk ); mbedtls_pk_free( pk );
mbedtls_pk_init( pk );
if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH ) if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH )
{ {
@ -1315,39 +1316,42 @@ int mbedtls_pk_parse_key( mbedtls_pk_context *pk,
return( 0 ); return( 0 );
mbedtls_pk_free( pk ); mbedtls_pk_free( pk );
mbedtls_pk_init( pk );
#if defined(MBEDTLS_RSA_C) #if defined(MBEDTLS_RSA_C)
pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA );
if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || if( mbedtls_pk_setup( pk, pk_info ) == 0 &&
( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) == 0 )
key, keylen ) ) != 0 )
{
mbedtls_pk_free( pk );
}
else
{ {
return( 0 ); return( 0 );
} }
mbedtls_pk_free( pk );
mbedtls_pk_init( pk );
#endif /* MBEDTLS_RSA_C */ #endif /* MBEDTLS_RSA_C */
#if defined(MBEDTLS_ECP_C) #if defined(MBEDTLS_ECP_C)
pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY );
if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || if( mbedtls_pk_setup( pk, pk_info ) == 0 &&
( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ),
key, keylen ) ) != 0 ) key, keylen ) == 0 )
{
mbedtls_pk_free( pk );
}
else
{ {
return( 0 ); return( 0 );
} }
mbedtls_pk_free( pk );
#endif /* MBEDTLS_ECP_C */ #endif /* MBEDTLS_ECP_C */
/* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't,
* it is ok to leave the PK context initialized but not
* freed: It is the caller's responsibility to call pk_init()
* before calling this function, and to call pk_free()
* when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C
* isn't, this leads to mbedtls_pk_free() being called
* twice, once here and once by the caller, but this is
* also ok and in line with the mbedtls_pk_free() calls
* on failed PEM parsing attempts. */
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
} }

View File

@ -39,7 +39,14 @@ static void mbedtls_zeroize( void *v, size_t n ) {
} }
#endif #endif
#if defined(MBEDTLS_PLATFORM_MEMORY) /* The compile time configuration of memory allocation via the macros
* MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO takes precedence over the runtime
* configuration via mbedtls_platform_set_calloc_free(). So, omit everything
* related to the latter if MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO are defined. */
#if defined(MBEDTLS_PLATFORM_MEMORY) && \
!( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && \
defined(MBEDTLS_PLATFORM_FREE_MACRO) )
#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) #if !defined(MBEDTLS_PLATFORM_STD_CALLOC)
static void *platform_calloc_uninit( size_t n, size_t size ) static void *platform_calloc_uninit( size_t n, size_t size )
{ {
@ -70,7 +77,9 @@ int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ),
mbedtls_free = free_func; mbedtls_free = free_func;
return( 0 ); return( 0 );
} }
#endif /* MBEDTLS_PLATFORM_MEMORY */ #endif /* MBEDTLS_PLATFORM_MEMORY &&
!( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&
defined(MBEDTLS_PLATFORM_FREE_MACRO) ) */
#if defined(_WIN32) #if defined(_WIN32)
#include <stdarg.h> #include <stdarg.h>

View File

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

View File

@ -2093,7 +2093,7 @@ static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl,
* *
* opaque psk_identity_hint<0..2^16-1>; * opaque psk_identity_hint<0..2^16-1>;
*/ */
if( (*p) > end - 2 ) if( end - (*p) < 2 )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message " MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message "
"(psk_identity_hint length)" ) ); "(psk_identity_hint length)" ) );
@ -2102,7 +2102,7 @@ static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl,
len = (*p)[0] << 8 | (*p)[1]; len = (*p)[0] << 8 | (*p)[1];
*p += 2; *p += 2;
if( (*p) > end - len ) if( end - (*p) < (int) len )
{ {
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message " MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message "
"(psk_identity_hint length)" ) ); "(psk_identity_hint length)" ) );

View File

@ -103,7 +103,7 @@ static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx )
uint32_t current_time = (uint32_t) mbedtls_time( NULL ); uint32_t current_time = (uint32_t) mbedtls_time( NULL );
uint32_t key_time = ctx->keys[ctx->active].generation_time; uint32_t key_time = ctx->keys[ctx->active].generation_time;
if( current_time > key_time && if( current_time >= key_time &&
current_time - key_time < ctx->ticket_lifetime ) current_time - key_time < ctx->ticket_lifetime )
{ {
return( 0 ); return( 0 );
@ -194,9 +194,9 @@ static int ssl_save_session( const mbedtls_ssl_session *session,
if( left < 3 + cert_len ) if( left < 3 + cert_len )
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
*p++ = (unsigned char)( cert_len >> 16 & 0xFF ); *p++ = (unsigned char)( ( cert_len >> 16 ) & 0xFF );
*p++ = (unsigned char)( cert_len >> 8 & 0xFF ); *p++ = (unsigned char)( ( cert_len >> 8 ) & 0xFF );
*p++ = (unsigned char)( cert_len & 0xFF ); *p++ = (unsigned char)( ( cert_len ) & 0xFF );
if( session->peer_cert != NULL ) if( session->peer_cert != NULL )
memcpy( p, session->peer_cert->raw.p, cert_len ); memcpy( p, session->peer_cert->raw.p, cert_len );
@ -221,14 +221,14 @@ static int ssl_load_session( mbedtls_ssl_session *session,
size_t cert_len; size_t cert_len;
#endif /* MBEDTLS_X509_CRT_PARSE_C */ #endif /* MBEDTLS_X509_CRT_PARSE_C */
if( p + sizeof( mbedtls_ssl_session ) > end ) if( sizeof( mbedtls_ssl_session ) > (size_t)( end - p ) )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
memcpy( session, p, sizeof( mbedtls_ssl_session ) ); memcpy( session, p, sizeof( mbedtls_ssl_session ) );
p += sizeof( mbedtls_ssl_session ); p += sizeof( mbedtls_ssl_session );
#if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_X509_CRT_PARSE_C)
if( p + 3 > end ) if( 3 > (size_t)( end - p ) )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2];
@ -242,7 +242,7 @@ static int ssl_load_session( mbedtls_ssl_session *session,
{ {
int ret; int ret;
if( p + cert_len > end ) if( cert_len > (size_t)( end - p ) )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
@ -253,7 +253,7 @@ static int ssl_load_session( mbedtls_ssl_session *session,
mbedtls_x509_crt_init( session->peer_cert ); mbedtls_x509_crt_init( session->peer_cert );
if( ( ret = mbedtls_x509_crt_parse_der( session->peer_cert, if( ( ret = mbedtls_x509_crt_parse_der( session->peer_cert,
p, cert_len ) ) != 0 ) p, cert_len ) ) != 0 )
{ {
mbedtls_x509_crt_free( session->peer_cert ); mbedtls_x509_crt_free( session->peer_cert );
mbedtls_free( session->peer_cert ); mbedtls_free( session->peer_cert );

View File

@ -2133,13 +2133,13 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
correct = 0; correct = 0;
} }
auth_done++; auth_done++;
/*
* Finally check the correct flag
*/
if( correct == 0 )
return( MBEDTLS_ERR_SSL_INVALID_MAC );
} }
/*
* Finally check the correct flag
*/
if( correct == 0 )
return( MBEDTLS_ERR_SSL_INVALID_MAC );
#endif /* SSL_SOME_MODES_USE_MAC */ #endif /* SSL_SOME_MODES_USE_MAC */
/* Make extra sure authentication was performed, exactly once */ /* Make extra sure authentication was performed, exactly once */
@ -3237,6 +3237,7 @@ static int ssl_reassemble_dtls_handshake( mbedtls_ssl_context *ssl )
memcpy( ssl->in_msg, ssl->handshake->hs_msg, ssl->in_hslen ); memcpy( ssl->in_msg, ssl->handshake->hs_msg, ssl->in_hslen );
mbedtls_zeroize( ssl->handshake->hs_msg, ssl->in_hslen );
mbedtls_free( ssl->handshake->hs_msg ); mbedtls_free( ssl->handshake->hs_msg );
ssl->handshake->hs_msg = NULL; ssl->handshake->hs_msg = NULL;

View File

@ -53,6 +53,7 @@
#include <windows.h> #include <windows.h>
#include <winbase.h> #include <winbase.h>
#include <process.h>
struct _hr_time struct _hr_time
{ {
@ -268,18 +269,17 @@ unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int
/* It's OK to use a global because alarm() is supposed to be global anyway */ /* It's OK to use a global because alarm() is supposed to be global anyway */
static DWORD alarmMs; static DWORD alarmMs;
static DWORD WINAPI TimerProc( LPVOID TimerContext ) static void TimerProc( void *TimerContext )
{ {
((void) TimerContext); (void) TimerContext;
Sleep( alarmMs ); Sleep( alarmMs );
mbedtls_timing_alarmed = 1; mbedtls_timing_alarmed = 1;
return( TRUE ); /* _endthread will be called implicitly on return
* That ensures execution of thread funcition's epilogue */
} }
void mbedtls_set_alarm( int seconds ) void mbedtls_set_alarm( int seconds )
{ {
DWORD ThreadId;
if( seconds == 0 ) if( seconds == 0 )
{ {
/* No need to create a thread for this simple case. /* No need to create a thread for this simple case.
@ -290,7 +290,7 @@ void mbedtls_set_alarm( int seconds )
mbedtls_timing_alarmed = 0; mbedtls_timing_alarmed = 0;
alarmMs = seconds * 1000; alarmMs = seconds * 1000;
CloseHandle( CreateThread( NULL, 0, TimerProc, NULL, 0, &ThreadId ) ); (void) _beginthread( TimerProc, 0, NULL );
} }
#else /* _WIN32 && !EFIX64 && !EFI32 */ #else /* _WIN32 && !EFIX64 && !EFI32 */

View File

@ -42,7 +42,6 @@
#include "mbedtls/x509_crt.h" #include "mbedtls/x509_crt.h"
#include "mbedtls/oid.h" #include "mbedtls/oid.h"
#include <stdio.h>
#include <string.h> #include <string.h>
#if defined(MBEDTLS_PEM_PARSE_C) #if defined(MBEDTLS_PEM_PARSE_C)
@ -52,6 +51,7 @@
#if defined(MBEDTLS_PLATFORM_C) #if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h" #include "mbedtls/platform.h"
#else #else
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#define mbedtls_free free #define mbedtls_free free
#define mbedtls_calloc calloc #define mbedtls_calloc calloc
@ -1365,6 +1365,135 @@ static int x509_info_ext_key_usage( char **buf, size_t *size,
return( 0 ); return( 0 );
} }
/*
* Like memcmp, but case-insensitive and always returns -1 if different
*/
static int x509_memcasecmp( const void *s1, const void *s2, size_t len )
{
size_t i;
unsigned char diff;
const unsigned char *n1 = s1, *n2 = s2;
for( i = 0; i < len; i++ )
{
diff = n1[i] ^ n2[i];
if( diff == 0 )
continue;
if( diff == 32 &&
( ( n1[i] >= 'a' && n1[i] <= 'z' ) ||
( n1[i] >= 'A' && n1[i] <= 'Z' ) ) )
{
continue;
}
return( -1 );
}
return( 0 );
}
/*
* Return 0 if name matches wildcard, -1 otherwise
*/
static int x509_check_wildcard( const char *cn, mbedtls_x509_buf *name )
{
size_t i;
size_t cn_idx = 0, cn_len = strlen( cn );
if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
return( 0 );
for( i = 0; i < cn_len; ++i )
{
if( cn[i] == '.' )
{
cn_idx = i;
break;
}
}
if( cn_idx == 0 )
return( -1 );
if( cn_len - cn_idx == name->len - 1 &&
x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
{
return( 0 );
}
return( -1 );
}
/*
* Compare two X.509 strings, case-insensitive, and allowing for some encoding
* variations (but not all).
*
* Return 0 if equal, -1 otherwise.
*/
static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b )
{
if( a->tag == b->tag &&
a->len == b->len &&
memcmp( a->p, b->p, b->len ) == 0 )
{
return( 0 );
}
if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
a->len == b->len &&
x509_memcasecmp( a->p, b->p, b->len ) == 0 )
{
return( 0 );
}
return( -1 );
}
/*
* Compare two X.509 Names (aka rdnSequence).
*
* See RFC 5280 section 7.1, though we don't implement the whole algorithm:
* we sometimes return unequal when the full algorithm would return equal,
* but never the other way. (In particular, we don't do Unicode normalisation
* or space folding.)
*
* Return 0 if equal, -1 otherwise.
*/
static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b )
{
/* Avoid recursion, it might not be optimised by the compiler */
while( a != NULL || b != NULL )
{
if( a == NULL || b == NULL )
return( -1 );
/* type */
if( a->oid.tag != b->oid.tag ||
a->oid.len != b->oid.len ||
memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 )
{
return( -1 );
}
/* value */
if( x509_string_cmp( &a->val, &b->val ) != 0 )
return( -1 );
/* structure of the list of sets */
if( a->next_merged != b->next_merged )
return( -1 );
a = a->next;
b = b->next;
}
/* a == NULL == b */
return( 0 );
}
/* /*
* Return an informational string about the certificate. * Return an informational string about the certificate.
*/ */
@ -1657,9 +1786,7 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
while( crl_list != NULL ) while( crl_list != NULL )
{ {
if( crl_list->version == 0 || if( crl_list->version == 0 ||
crl_list->issuer_raw.len != ca->subject_raw.len || x509_name_cmp( &crl_list->issuer, &ca->subject ) != 0 )
memcmp( crl_list->issuer_raw.p, ca->subject_raw.p,
crl_list->issuer_raw.len ) != 0 )
{ {
crl_list = crl_list->next; crl_list = crl_list->next;
continue; continue;
@ -1669,7 +1796,8 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
* Check if the CA is configured to sign CRLs * Check if the CA is configured to sign CRLs
*/ */
#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) #if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
if( mbedtls_x509_crt_check_key_usage( ca, MBEDTLS_X509_KU_CRL_SIGN ) != 0 ) if( mbedtls_x509_crt_check_key_usage( ca,
MBEDTLS_X509_KU_CRL_SIGN ) != 0 )
{ {
flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED;
break; break;
@ -1729,135 +1857,6 @@ static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
} }
#endif /* MBEDTLS_X509_CRL_PARSE_C */ #endif /* MBEDTLS_X509_CRL_PARSE_C */
/*
* Like memcmp, but case-insensitive and always returns -1 if different
*/
static int x509_memcasecmp( const void *s1, const void *s2, size_t len )
{
size_t i;
unsigned char diff;
const unsigned char *n1 = s1, *n2 = s2;
for( i = 0; i < len; i++ )
{
diff = n1[i] ^ n2[i];
if( diff == 0 )
continue;
if( diff == 32 &&
( ( n1[i] >= 'a' && n1[i] <= 'z' ) ||
( n1[i] >= 'A' && n1[i] <= 'Z' ) ) )
{
continue;
}
return( -1 );
}
return( 0 );
}
/*
* Return 0 if name matches wildcard, -1 otherwise
*/
static int x509_check_wildcard( const char *cn, mbedtls_x509_buf *name )
{
size_t i;
size_t cn_idx = 0, cn_len = strlen( cn );
if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' )
return( 0 );
for( i = 0; i < cn_len; ++i )
{
if( cn[i] == '.' )
{
cn_idx = i;
break;
}
}
if( cn_idx == 0 )
return( -1 );
if( cn_len - cn_idx == name->len - 1 &&
x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
{
return( 0 );
}
return( -1 );
}
/*
* Compare two X.509 strings, case-insensitive, and allowing for some encoding
* variations (but not all).
*
* Return 0 if equal, -1 otherwise.
*/
static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b )
{
if( a->tag == b->tag &&
a->len == b->len &&
memcmp( a->p, b->p, b->len ) == 0 )
{
return( 0 );
}
if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) &&
a->len == b->len &&
x509_memcasecmp( a->p, b->p, b->len ) == 0 )
{
return( 0 );
}
return( -1 );
}
/*
* Compare two X.509 Names (aka rdnSequence).
*
* See RFC 5280 section 7.1, though we don't implement the whole algorithm:
* we sometimes return unequal when the full algorithm would return equal,
* but never the other way. (In particular, we don't do Unicode normalisation
* or space folding.)
*
* Return 0 if equal, -1 otherwise.
*/
static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b )
{
/* Avoid recursion, it might not be optimised by the compiler */
while( a != NULL || b != NULL )
{
if( a == NULL || b == NULL )
return( -1 );
/* type */
if( a->oid.tag != b->oid.tag ||
a->oid.len != b->oid.len ||
memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 )
{
return( -1 );
}
/* value */
if( x509_string_cmp( &a->val, &b->val ) != 0 )
return( -1 );
/* structure of the list of sets */
if( a->next_merged != b->next_merged )
return( -1 );
a = a->next;
b = b->next;
}
/* a == NULL == b */
return( 0 );
}
/* /*
* Check if 'parent' is a suitable parent (signing CA) for 'child'. * Check if 'parent' is a suitable parent (signing CA) for 'child'.
* Return 0 if yes, -1 if not. * Return 0 if yes, -1 if not.

View File

@ -172,19 +172,19 @@
#define MULADDC_INIT \ #define MULADDC_INIT \
asm( \ asm( \
"xorq %%r8, %%r8 \n\t" "xorq %%r8, %%r8\n"
#define MULADDC_CORE \ #define MULADDC_CORE \
"movq (%%rsi), %%rax \n\t" \ "movq (%%rsi), %%rax\n" \
"mulq %%rbx \n\t" \ "mulq %%rbx\n" \
"addq $8, %%rsi \n\t" \ "addq $8, %%rsi\n" \
"addq %%rcx, %%rax \n\t" \ "addq %%rcx, %%rax\n" \
"movq %%r8, %%rcx \n\t" \ "movq %%r8, %%rcx\n" \
"adcq $0, %%rdx \n\t" \ "adcq $0, %%rdx\n" \
"nop \n\t" \ "nop \n" \
"addq %%rax, (%%rdi) \n\t" \ "addq %%rax, (%%rdi)\n" \
"adcq %%rdx, %%rcx \n\t" \ "adcq %%rdx, %%rcx\n" \
"addq $8, %%rdi \n\t" "addq $8, %%rdi\n"
#define MULADDC_STOP \ #define MULADDC_STOP \
: "+c" (c), "+D" (d), "+S" (s) \ : "+c" (c), "+D" (d), "+S" (s) \

View File

@ -124,6 +124,10 @@
#error "MBEDTLS_ECP_C defined, but not all prerequisites" #error "MBEDTLS_ECP_C defined, but not all prerequisites"
#endif #endif
#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_ASN1_PARSE_C)
#error "MBEDTLS_PK_PARSE_C defined, but not all prerequesites"
#endif
#if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \ #if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \
!defined(MBEDTLS_SHA256_C)) !defined(MBEDTLS_SHA256_C))
#error "MBEDTLS_ENTROPY_C defined, but not all prerequisites" #error "MBEDTLS_ENTROPY_C defined, but not all prerequisites"

View File

@ -1190,7 +1190,7 @@
/** /**
* \def MBEDTLS_SSL_RENEGOTIATION * \def MBEDTLS_SSL_RENEGOTIATION
* *
* Disable support for TLS renegotiation. * Enable support for TLS renegotiation.
* *
* The two main uses of renegotiation are (1) refresh keys on long-lived * The two main uses of renegotiation are (1) refresh keys on long-lived
* connections and (2) client authentication after the initial handshake. * connections and (2) client authentication after the initial handshake.

View File

@ -229,14 +229,37 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
* *
* \param ctx The CTR_DRBG context. * \param ctx The CTR_DRBG context.
* \param additional The data to update the state with. * \param additional The data to update the state with.
* \param add_len Length of \p additional data. * \param add_len Length of \p additional in bytes. This must be at
* most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
* *
* \note If \p add_len is greater than #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, * \return \c 0 on success.
* only the first #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used. * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if
* The remaining Bytes are silently discarded. * \p add_len is more than
* #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
* \return An error from the underlying AES cipher on failure.
*/
int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
const unsigned char *additional,
size_t add_len );
/**
* \brief This function updates the state of the CTR_DRBG context.
*
* \warning This function cannot report errors. You should use
* mbedtls_ctr_drbg_update_ret() instead.
*
* \note If \p add_len is greater than
* #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, only the first
* #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used.
* The remaining Bytes are silently discarded.
*
* \param ctx The CTR_DRBG context.
* \param additional The data to update the state with.
* \param add_len Length of \p additional data.
*/ */
void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
const unsigned char *additional, size_t add_len ); const unsigned char *additional,
size_t add_len );
/** /**
* \brief This function updates a CTR_DRBG instance with additional * \brief This function updates a CTR_DRBG instance with additional

View File

@ -197,11 +197,31 @@ void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx,
* \param additional Additional data to update state with, or NULL * \param additional Additional data to update state with, or NULL
* \param add_len Length of additional data, or 0 * \param add_len Length of additional data, or 0
* *
* \return \c 0 on success, or an error from the underlying
* hash calculation.
*
* \note Additional data is optional, pass NULL and 0 as second
* third argument if no additional data is being used.
*/
int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
const unsigned char *additional, size_t add_len );
/**
* \brief HMAC_DRBG update state
*
* \warning This function cannot report errors. You should use
* mbedtls_hmac_drbg_update_ret() instead.
*
* \param ctx HMAC_DRBG context
* \param additional Additional data to update state with, or NULL
* \param add_len Length of additional data, or 0
*
* \note Additional data is optional, pass NULL and 0 as second * \note Additional data is optional, pass NULL and 0 as second
* third argument if no additional data is being used. * third argument if no additional data is being used.
*/ */
void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
const unsigned char *additional, size_t add_len ); const unsigned char *additional,
size_t add_len );
/** /**
* \brief HMAC_DRBG reseeding (extracts data from entropy source) * \brief HMAC_DRBG reseeding (extracts data from entropy source)

View File

@ -48,6 +48,8 @@
extern "C" { extern "C" {
#endif #endif
#if defined(MBEDTLS_ASN1_PARSE_C)
/** /**
* \brief PKCS12 Password Based function (encryption / decryption) * \brief PKCS12 Password Based function (encryption / decryption)
* for pbeWithSHAAnd128BitRC4 * for pbeWithSHAAnd128BitRC4
@ -89,6 +91,8 @@ int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode,
const unsigned char *input, size_t len, const unsigned char *input, size_t len,
unsigned char *output ); unsigned char *output );
#endif /* MBEDTLS_ASN1_PARSE_C */
/** /**
* \brief The PKCS#12 derivation function uses a password and a salt * \brief The PKCS#12 derivation function uses a password and a salt
* to produce pseudo-random bits for a particular "purpose". * to produce pseudo-random bits for a particular "purpose".

View File

@ -46,6 +46,8 @@
extern "C" { extern "C" {
#endif #endif
#if defined(MBEDTLS_ASN1_PARSE_C)
/** /**
* \brief PKCS#5 PBES2 function * \brief PKCS#5 PBES2 function
* *
@ -64,6 +66,8 @@ int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode,
const unsigned char *data, size_t datalen, const unsigned char *data, size_t datalen,
unsigned char *output ); unsigned char *output );
#endif /* MBEDTLS_ASN1_PARSE_C */
/** /**
* \brief PKCS#5 PBKDF2 using HMAC * \brief PKCS#5 PBKDF2 using HMAC
* *

View File

@ -1620,6 +1620,14 @@ void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf,
* whether it matches those preferences - the server can then * whether it matches those preferences - the server can then
* decide what it wants to do with it. * decide what it wants to do with it.
* *
* \note The provided \p pk_key needs to match the public key in the
* first certificate in \p own_cert, or all handshakes using
* that certificate will fail. It is your responsibility
* to ensure that; this function will not perform any check.
* You may use mbedtls_pk_check_pair() in order to perform
* this check yourself, but be aware that this function can
* be computationally expensive on some key types.
*
* \param conf SSL configuration * \param conf SSL configuration
* \param own_cert own public certificate chain * \param own_cert own public certificate chain
* \param pk_key own private key * \param pk_key own private key
@ -2289,13 +2297,14 @@ size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl );
/** /**
* \brief Return the result of the certificate verification * \brief Return the result of the certificate verification
* *
* \param ssl SSL context * \param ssl The SSL context to use.
* *
* \return 0 if successful, * \return \c 0 if the certificate verification was successful.
* -1 if result is not available (eg because the handshake was * \return \c -1u if the result is not available. This may happen
* aborted too early), or * e.g. if the handshake aborts early, or a verification
* a combination of BADCERT_xxx and BADCRL_xxx flags, see * callback returned a fatal error.
* x509.h * \return A bitwise combination of \c MBEDTLS_X509_BADCERT_XXX
* and \c MBEDTLS_X509_BADCRL_XXX failure flags; see x509.h.
*/ */
uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ); uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl );

View File

@ -42,16 +42,16 @@
*/ */
#define MBEDTLS_VERSION_MAJOR 2 #define MBEDTLS_VERSION_MAJOR 2
#define MBEDTLS_VERSION_MINOR 7 #define MBEDTLS_VERSION_MINOR 7
#define MBEDTLS_VERSION_PATCH 6 #define MBEDTLS_VERSION_PATCH 9
/** /**
* The single version number has the following structure: * The single version number has the following structure:
* MMNNPP00 * MMNNPP00
* Major version | Minor version | Patch version * Major version | Minor version | Patch version
*/ */
#define MBEDTLS_VERSION_NUMBER 0x02070600 #define MBEDTLS_VERSION_NUMBER 0x02070900
#define MBEDTLS_VERSION_STRING "2.7.6" #define MBEDTLS_VERSION_STRING "2.7.9"
#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.7.6" #define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.7.9"
#if defined(MBEDTLS_VERSION_C) #if defined(MBEDTLS_VERSION_C)

View File

@ -177,19 +177,34 @@ int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *bu
size_t buflen ); size_t buflen );
/** /**
* \brief Parse one or more certificates and add them * \brief Parse one DER-encoded or one or more concatenated PEM-encoded
* to the chained list. Parses permissively. If some * certificates and add them to the chained list.
* certificates can be parsed, the result is the number
* of failed certificates it encountered. If none complete
* correctly, the first error is returned.
* *
* \param chain points to the start of the chain * For CRTs in PEM encoding, the function parses permissively:
* \param buf buffer holding the certificate data in PEM or DER format * if at least one certificate can be parsed, the function
* \param buflen size of the buffer * returns the number of certificates for which parsing failed
* (including the terminating null byte for PEM data) * (hence \c 0 if all certificates were parsed successfully).
* If no certificate could be parsed, the function returns
* the first (negative) error encountered during parsing.
*
* PEM encoded certificates may be interleaved by other data
* such as human readable descriptions of their content, as
* long as the certificates are enclosed in the PEM specific
* '-----{BEGIN/END} CERTIFICATE-----' delimiters.
*
* \param chain The chain to which to add the parsed certificates.
* \param buf The buffer holding the certificate data in PEM or DER format.
* For certificates in PEM encoding, this may be a concatenation
* of multiple certificates; for DER encoding, the buffer must
* comprise exactly one certificate.
* \param buflen The size of \p buf, including the terminating \c NULL byte
* in case of PEM encoded data.
*
* \return \c 0 if all certificates were parsed successfully.
* \return The (positive) number of certificates that couldn't
* be parsed if parsing was partly successful (see above).
* \return A negative X509 or PEM error code otherwise.
* *
* \return 0 if all certificates parsed successfully, a positive number
* if partly successful or a specific X509 or PEM error code
*/ */
int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ); int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen );