Merge branch 'mbedtls-2.16-restricted' into mbedtls-2.16.7r0

This commit is contained in:
Janos Follath 2020-06-25 09:19:21 +01:00
commit f69b919844
12 changed files with 565 additions and 5 deletions

View File

@ -0,0 +1,16 @@
Changes
* The ECP module, enabled by `MBEDTLS_ECP_C`, now depends on
`MBEDTLS_CTR_DRBG_C`, `MBEDTLS_HMAC_DRBG_C`, `MBEDTLS_SHA512_C` or
`MBEDTLS_SHA256_C` for some side-channel coutermeasures. If side channels
are not a concern, this dependency can be avoided by enabling the new
option `MBEDTLS_ECP_NO_INTERNAL_RNG`.
Security
* Fix side channel in mbedtls_ecp_check_pub_priv() and
mbedtls_pk_parse_key() / mbedtls_pk_parse_keyfile() (when loading a
private key that didn't include the uncompressed public key), as well as
mbedtls_ecp_mul() / mbedtls_ecp_mul_restartable() when called with a NULL
f_rng argument. An attacker with access to precise enough timing and
memory access information (typically an untrusted operating system
attacking a secure enclave) could fully recover the ECC private key.
Found and reported by Alejandro Cabrera Aldaya and Billy Brumley.

View File

@ -0,0 +1,7 @@
Security
* Fix issue in Lucky 13 counter-measure that could make it ineffective when
hardware accelerators were used (using one of the MBEDTLS_SHAxxx_ALT
macros). This would cause the original Lucky 13 attack to be possible in
those configurations, allowing an active network attacker to recover
plaintext after repeated timing measurements under some conditions.
Reported and fix suggested by Luc Perneel in #3246.

View File

@ -167,6 +167,16 @@
#error "MBEDTLS_ECP_C defined, but not all prerequisites" #error "MBEDTLS_ECP_C defined, but not all prerequisites"
#endif #endif
#if defined(MBEDTLS_ECP_C) && !( \
defined(MBEDTLS_ECP_ALT) || \
defined(MBEDTLS_CTR_DRBG_C) || \
defined(MBEDTLS_HMAC_DRBG_C) || \
defined(MBEDTLS_SHA512_C) || \
defined(MBEDTLS_SHA256_C) || \
defined(MBEDTLS_ECP_NO_INTERNAL_RNG))
#error "MBEDTLS_ECP_C requires a DRBG or SHA-2 module unless MBEDTLS_ECP_NO_INTERNAL_RNG is defined or an alternative implementation is used"
#endif
#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_ASN1_PARSE_C) #if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_ASN1_PARSE_C)
#error "MBEDTLS_PK_PARSE_C defined, but not all prerequesites" #error "MBEDTLS_PK_PARSE_C defined, but not all prerequesites"
#endif #endif

View File

@ -807,6 +807,28 @@
*/ */
#define MBEDTLS_ECP_NIST_OPTIM #define MBEDTLS_ECP_NIST_OPTIM
/**
* \def MBEDTLS_ECP_NO_INTERNAL_RNG
*
* When this option is disabled, mbedtls_ecp_mul() will make use of an
* internal RNG when called with a NULL \c f_rng argument, in order to protect
* against some side-channel attacks.
*
* This protection introduces a dependency of the ECP module on one of the
* DRBG or SHA modules (HMAC-DRBG, CTR-DRBG, SHA-512 or SHA-256.) For very
* constrained applications that don't require this protection (for example,
* because you're only doing signature verification, so not manipulating any
* secret, or because local/physical side-channel attacks are outside your
* threat model), it might be desirable to get rid of that dependency.
*
* \warning Enabling this option makes some uses of ECP vulnerable to some
* side-channel attacks. Only enable it if you know that's not a problem for
* your use case.
*
* Uncomment this macro to disable some counter-measures in ECP.
*/
//#define MBEDTLS_ECP_NO_INTERNAL_RNG
/** /**
* \def MBEDTLS_ECP_RESTARTABLE * \def MBEDTLS_ECP_RESTARTABLE
* *

View File

@ -840,6 +840,9 @@ int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp,
* intermediate results to prevent potential timing attacks * intermediate results to prevent potential timing attacks
* targeting these results. We recommend always providing * targeting these results. We recommend always providing
* a non-NULL \p f_rng. The overhead is negligible. * a non-NULL \p f_rng. The overhead is negligible.
* Note: unless #MBEDTLS_ECP_NO_INTERNAL_RNG is defined, when
* \p f_rng is NULL, an internal RNG (seeded from the value
* of \p m) will be used instead.
* *
* \param grp The ECP group to use. * \param grp The ECP group to use.
* This must be initialized and have group parameters * This must be initialized and have group parameters

View File

@ -125,6 +125,8 @@ typedef struct mbedtls_md_context_t
* \brief This function returns the list of digests supported by the * \brief This function returns the list of digests supported by the
* generic digest module. * generic digest module.
* *
* \note The list starts with the strongest available hashes.
*
* \return A statically allocated array of digests. Each element * \return A statically allocated array of digests. Each element
* in the returned list is an integer belonging to the * in the returned list is an integer belonging to the
* message-digest enumeration #mbedtls_md_type_t. * message-digest enumeration #mbedtls_md_type_t.

View File

@ -131,6 +131,20 @@
#include "mbedtls/ecp_internal.h" #include "mbedtls/ecp_internal.h"
#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
#if defined(MBEDTLS_HMAC_DRBG_C)
#include "mbedtls/hmac_drbg.h"
#elif defined(MBEDTLS_CTR_DRBG_C)
#include "mbedtls/ctr_drbg.h"
#elif defined(MBEDTLS_SHA512_C)
#include "mbedtls/sha512.h"
#elif defined(MBEDTLS_SHA256_C)
#include "mbedtls/sha256.h"
#else
#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
#endif
#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
!defined(inline) && !defined(__cplusplus) !defined(inline) && !defined(__cplusplus)
#define inline __inline #define inline __inline
@ -144,6 +158,233 @@
static unsigned long add_count, dbl_count, mul_count; static unsigned long add_count, dbl_count, mul_count;
#endif #endif
#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
/*
* Currently ecp_mul() takes a RNG function as an argument, used for
* side-channel protection, but it can be NULL. The initial reasoning was
* that people will pass non-NULL RNG when they care about side-channels, but
* unfortunately we have some APIs that call ecp_mul() with a NULL RNG, with
* no opportunity for the user to do anything about it.
*
* The obvious strategies for addressing that include:
* - change those APIs so that they take RNG arguments;
* - require a global RNG to be available to all crypto modules.
*
* Unfortunately those would break compatibility. So what we do instead is
* have our own internal DRBG instance, seeded from the secret scalar.
*
* The following is a light-weight abstraction layer for doing that with
* HMAC_DRBG (first choice) or CTR_DRBG.
*/
#if defined(MBEDTLS_HMAC_DRBG_C)
/* DRBG context type */
typedef mbedtls_hmac_drbg_context ecp_drbg_context;
/* DRBG context init */
static inline void ecp_drbg_init( ecp_drbg_context *ctx )
{
mbedtls_hmac_drbg_init( ctx );
}
/* DRBG context free */
static inline void ecp_drbg_free( ecp_drbg_context *ctx )
{
mbedtls_hmac_drbg_free( ctx );
}
/* DRBG function */
static inline int ecp_drbg_random( void *p_rng,
unsigned char *output, size_t output_len )
{
return( mbedtls_hmac_drbg_random( p_rng, output, output_len ) );
}
/* DRBG context seeding */
static int ecp_drbg_seed( ecp_drbg_context *ctx,
const mbedtls_mpi *secret, size_t secret_len )
{
int ret;
unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
/* The list starts with strong hashes */
const mbedtls_md_type_t md_type = mbedtls_md_list()[0];
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_type );
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
secret_bytes, secret_len ) );
ret = mbedtls_hmac_drbg_seed_buf( ctx, md_info, secret_bytes, secret_len );
cleanup:
mbedtls_platform_zeroize( secret_bytes, secret_len );
return( ret );
}
#elif defined(MBEDTLS_CTR_DRBG_C)
/* DRBG context type */
typedef mbedtls_ctr_drbg_context ecp_drbg_context;
/* DRBG context init */
static inline void ecp_drbg_init( ecp_drbg_context *ctx )
{
mbedtls_ctr_drbg_init( ctx );
}
/* DRBG context free */
static inline void ecp_drbg_free( ecp_drbg_context *ctx )
{
mbedtls_ctr_drbg_free( ctx );
}
/* DRBG function */
static inline int ecp_drbg_random( void *p_rng,
unsigned char *output, size_t output_len )
{
return( mbedtls_ctr_drbg_random( p_rng, output, output_len ) );
}
/*
* Since CTR_DRBG doesn't have a seed_buf() function the way HMAC_DRBG does,
* we need to pass an entropy function when seeding. So we use a dummy
* function for that, and pass the actual entropy as customisation string.
* (During seeding of CTR_DRBG the entropy input and customisation string are
* concatenated before being used to update the secret state.)
*/
static int ecp_ctr_drbg_null_entropy(void *ctx, unsigned char *out, size_t len)
{
(void) ctx;
memset( out, 0, len );
return( 0 );
}
/* DRBG context seeding */
static int ecp_drbg_seed( ecp_drbg_context *ctx,
const mbedtls_mpi *secret, size_t secret_len )
{
int ret;
unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES];
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret,
secret_bytes, secret_len ) );
ret = mbedtls_ctr_drbg_seed( ctx, ecp_ctr_drbg_null_entropy, NULL,
secret_bytes, secret_len );
cleanup:
mbedtls_platform_zeroize( secret_bytes, secret_len );
return( ret );
}
#elif defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_SHA256_C)
/* This will be used in the self-test function */
#define ECP_ONE_STEP_KDF
/*
* We need to expand secret data (the scalar) into a longer stream of bytes.
*
* We'll use the One-Step KDF from NIST SP 800-56C, with option 1 (H is a hash
* function) and empty FixedInfo. (Though we'll make it fit the DRBG API for
* convenience, this is not a full-fledged DRBG, but we don't need one here.)
*
* We need a basic hash abstraction layer to use whatever SHA-2 is available.
*/
#if defined(MBEDTLS_SHA512_C)
#define HASH_FUNC( in, ilen, out ) mbedtls_sha512_ret( in, ilen, out, 0 );
#define HASH_BLOCK_BYTES ( 512 / 8 )
#elif defined(MBEDTLS_SHA256_C)
#define HASH_FUNC( in, ilen, out ) mbedtls_sha256_ret( in, ilen, out, 0 );
#define HASH_BLOCK_BYTES ( 256 / 8 )
#endif /* SHA512/SHA256 abstraction */
/*
* State consists of a 32-bit counter plus the secret value.
*
* We stored them concatenated in a single buffer as that's what will get
* passed to the hash function.
*/
typedef struct {
size_t total_len;
uint8_t buf[4 + MBEDTLS_ECP_MAX_BYTES];
} ecp_drbg_context;
static void ecp_drbg_init( ecp_drbg_context *ctx )
{
memset( ctx, 0, sizeof( ecp_drbg_context ) );
}
static void ecp_drbg_free( ecp_drbg_context *ctx )
{
mbedtls_platform_zeroize( ctx, sizeof( ecp_drbg_context ) );
}
static int ecp_drbg_seed( ecp_drbg_context *ctx,
const mbedtls_mpi *secret, size_t secret_len )
{
ctx->total_len = 4 + secret_len;
memset( ctx->buf, 0, 4);
return( mbedtls_mpi_write_binary( secret, ctx->buf + 4, secret_len ) );
}
static int ecp_drbg_random( void *p_rng, unsigned char *output, size_t output_len )
{
ecp_drbg_context *ctx = p_rng;
int ret;
size_t len_done = 0;
uint8_t tmp[HASH_BLOCK_BYTES];
while( len_done < output_len )
{
uint8_t use_len;
/* This function is only called for coordinate randomisation, which
* happens only twice in a scalar multiplication. Each time needs a
* random value in the range [2, p-1], and gets it by drawing len(p)
* bytes from this function, and retrying up to 10 times if unlucky.
*
* So for the largest curve, each scalar multiplication draws at most
* 20 * 66 bytes. The minimum block size is 32 (SHA-256), so with
* rounding that means a most 20 * 3 blocks.
*
* Since we don't need to draw more that 255 blocks, don't bother
* with carry propagation and just return an error instead. We can
* change that it we even need to draw more blinding values.
*/
ctx->buf[3] += 1;
if( ctx->buf[3] == 0 )
return( MBEDTLS_ERR_ECP_RANDOM_FAILED );
ret = HASH_FUNC( ctx->buf, ctx->total_len, tmp );
if( ret != 0 )
return( ret );
if( output_len - len_done > HASH_BLOCK_BYTES )
use_len = HASH_BLOCK_BYTES;
else
use_len = output_len - len_done;
memcpy( output + len_done, tmp, use_len );
len_done += use_len;
}
mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
return( 0 );
}
#else /* DRBG/SHA modules */
#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid."
#endif /* DRBG/SHA modules */
#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
#if defined(MBEDTLS_ECP_RESTARTABLE) #if defined(MBEDTLS_ECP_RESTARTABLE)
/* /*
* Maximum number of "basic operations" to be done in a row. * Maximum number of "basic operations" to be done in a row.
@ -191,6 +432,10 @@ struct mbedtls_ecp_restart_mul
ecp_rsm_comb_core, /* ecp_mul_comb_core() */ ecp_rsm_comb_core, /* ecp_mul_comb_core() */
ecp_rsm_final_norm, /* do the final normalization */ ecp_rsm_final_norm, /* do the final normalization */
} state; } state;
#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
ecp_drbg_context drbg_ctx;
unsigned char drbg_seeded;
#endif
}; };
/* /*
@ -203,6 +448,10 @@ static void ecp_restart_rsm_init( mbedtls_ecp_restart_mul_ctx *ctx )
ctx->T = NULL; ctx->T = NULL;
ctx->T_size = 0; ctx->T_size = 0;
ctx->state = ecp_rsm_init; ctx->state = ecp_rsm_init;
#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
ecp_drbg_init( &ctx->drbg_ctx );
ctx->drbg_seeded = 0;
#endif
} }
/* /*
@ -224,6 +473,10 @@ static void ecp_restart_rsm_free( mbedtls_ecp_restart_mul_ctx *ctx )
mbedtls_free( ctx->T ); mbedtls_free( ctx->T );
} }
#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
ecp_drbg_free( &ctx->drbg_ctx );
#endif
ecp_restart_rsm_init( ctx ); ecp_restart_rsm_init( ctx );
} }
@ -1846,7 +2099,9 @@ static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R
i = d; i = d;
MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, T_size, x[i] ) ); MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, T_size, x[i] ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) );
#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
if( f_rng != 0 ) if( f_rng != 0 )
#endif
MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) );
} }
@ -1967,6 +2222,7 @@ static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp,
rs_ctx->rsm->state = ecp_rsm_final_norm; rs_ctx->rsm->state = ecp_rsm_final_norm;
final_norm: final_norm:
MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
#endif #endif
/* /*
* Knowledge of the jacobian coordinates may leak the last few bits of the * Knowledge of the jacobian coordinates may leak the last few bits of the
@ -1979,10 +2235,11 @@ final_norm:
* *
* Avoid the leak by randomizing coordinates before we normalize them. * Avoid the leak by randomizing coordinates before we normalize them.
*/ */
#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
if( f_rng != 0 ) if( f_rng != 0 )
#endif
MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, RR, f_rng, p_rng ) ); MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, RR, f_rng, p_rng ) );
MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV );
MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) ); MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) );
#if defined(MBEDTLS_ECP_RESTARTABLE) #if defined(MBEDTLS_ECP_RESTARTABLE)
@ -2051,11 +2308,44 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
int ret; int ret;
unsigned char w, p_eq_g, i; unsigned char w, p_eq_g, i;
size_t d; size_t d;
unsigned char T_size, T_ok; unsigned char T_size = 0, T_ok = 0;
mbedtls_ecp_point *T; mbedtls_ecp_point *T = NULL;
#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
ecp_drbg_context drbg_ctx;
ecp_drbg_init( &drbg_ctx );
#endif
ECP_RS_ENTER( rsm ); ECP_RS_ENTER( rsm );
#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
if( f_rng == NULL )
{
/* Adjust pointers */
f_rng = &ecp_drbg_random;
#if defined(MBEDTLS_ECP_RESTARTABLE)
if( rs_ctx != NULL && rs_ctx->rsm != NULL )
p_rng = &rs_ctx->rsm->drbg_ctx;
else
#endif
p_rng = &drbg_ctx;
/* Initialize internal DRBG if necessary */
#if defined(MBEDTLS_ECP_RESTARTABLE)
if( rs_ctx == NULL || rs_ctx->rsm == NULL ||
rs_ctx->rsm->drbg_seeded == 0 )
#endif
{
const size_t m_len = ( grp->nbits + 7 ) / 8;
MBEDTLS_MPI_CHK( ecp_drbg_seed( p_rng, m, m_len ) );
}
#if defined(MBEDTLS_ECP_RESTARTABLE)
if( rs_ctx != NULL && rs_ctx->rsm != NULL )
rs_ctx->rsm->drbg_seeded = 1;
#endif
}
#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
/* Is P the base point ? */ /* Is P the base point ? */
#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 &&
@ -2127,6 +2417,10 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
cleanup: cleanup:
#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
ecp_drbg_free( &drbg_ctx );
#endif
/* does T belong to the group? */ /* does T belong to the group? */
if( T == grp->T ) if( T == grp->T )
T = NULL; T = NULL;
@ -2317,9 +2611,23 @@ static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
unsigned char b; unsigned char b;
mbedtls_ecp_point RP; mbedtls_ecp_point RP;
mbedtls_mpi PX; mbedtls_mpi PX;
#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
ecp_drbg_context drbg_ctx;
ecp_drbg_init( &drbg_ctx );
#endif
mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX ); mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX );
#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
if( f_rng == NULL )
{
const size_t m_len = ( grp->nbits + 7 ) / 8;
MBEDTLS_MPI_CHK( ecp_drbg_seed( &drbg_ctx, m, m_len ) );
f_rng = &ecp_drbg_random;
p_rng = &drbg_ctx;
}
#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */
/* Save PX and read from P before writing to R, in case P == R */ /* Save PX and read from P before writing to R, in case P == R */
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) );
MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) ); MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) );
@ -2333,7 +2641,9 @@ static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
MOD_ADD( RP.X ); MOD_ADD( RP.X );
/* Randomize coordinates of the starting point */ /* Randomize coordinates of the starting point */
#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
if( f_rng != NULL ) if( f_rng != NULL )
#endif
MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) ); MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) );
/* Loop invariant: R = result so far, RP = R + P */ /* Loop invariant: R = result so far, RP = R + P */
@ -2366,12 +2676,18 @@ static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
* *
* Avoid the leak by randomizing coordinates before we normalize them. * Avoid the leak by randomizing coordinates before we normalize them.
*/ */
#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
if( f_rng != NULL ) if( f_rng != NULL )
#endif
MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) ); MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) );
MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) ); MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) );
cleanup: cleanup:
#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
ecp_drbg_free( &drbg_ctx );
#endif
mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX ); mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX );
return( ret ); return( ret );
@ -2926,6 +3242,76 @@ cleanup:
#if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_SELF_TEST)
#if defined(ECP_ONE_STEP_KDF)
/*
* There are no test vectors from NIST for the One-Step KDF in SP 800-56C,
* but unofficial ones can be found at:
* https://github.com/patrickfav/singlestep-kdf/wiki/NIST-SP-800-56C-Rev1:-Non-Official-Test-Vectors
*
* We only use the ones with empty fixedInfo, and for brevity's sake, only
* 40-bytes output (with SHA-256 that's more than one block, and with SHA-512
* less than one block).
*/
#if defined(MBEDTLS_SHA512_C)
static const uint8_t test_kdf_z[16] = {
0x3b, 0xa9, 0x79, 0xe9, 0xbc, 0x5e, 0x3e, 0xc7,
0x61, 0x30, 0x36, 0xb6, 0xf5, 0x1c, 0xd5, 0xaa,
};
static const uint8_t test_kdf_out[40] = {
0x3e, 0xf6, 0xda, 0xf9, 0x51, 0x60, 0x70, 0x5f,
0xdf, 0x21, 0xcd, 0xab, 0xac, 0x25, 0x7b, 0x05,
0xfe, 0xc1, 0xab, 0x7c, 0xc9, 0x68, 0x43, 0x25,
0x8a, 0xfc, 0x40, 0x6e, 0x5b, 0xf7, 0x98, 0x27,
0x10, 0xfa, 0x7b, 0x93, 0x52, 0xd4, 0x16, 0xaa,
};
#elif defined(MBEDTLS_SHA256_C)
static const uint8_t test_kdf_z[16] = {
0xc8, 0x3e, 0x35, 0x8e, 0x99, 0xa6, 0x89, 0xc6,
0x7d, 0xb4, 0xfe, 0x39, 0xcf, 0x8f, 0x26, 0xe1,
};
static const uint8_t test_kdf_out[40] = {
0x7d, 0xf6, 0x41, 0xf8, 0x3c, 0x47, 0xdc, 0x28,
0x5f, 0x7f, 0xaa, 0xde, 0x05, 0x64, 0xd6, 0x25,
0x00, 0x6a, 0x47, 0xd9, 0x1e, 0xa4, 0xa0, 0x8c,
0xd7, 0xf7, 0x0c, 0x99, 0xaa, 0xa0, 0x72, 0x66,
0x69, 0x0e, 0x25, 0xaa, 0xa1, 0x63, 0x14, 0x79,
};
#endif
static int ecp_kdf_self_test( void )
{
int ret;
ecp_drbg_context kdf_ctx;
mbedtls_mpi scalar;
uint8_t out[sizeof( test_kdf_out )];
ecp_drbg_init( &kdf_ctx );
mbedtls_mpi_init( &scalar );
memset( out, 0, sizeof( out ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &scalar,
test_kdf_z, sizeof( test_kdf_z ) ) );
MBEDTLS_MPI_CHK( ecp_drbg_seed( &kdf_ctx,
&scalar, sizeof( test_kdf_z ) ) );
MBEDTLS_MPI_CHK( ecp_drbg_random( &kdf_ctx, out, sizeof( out ) ) );
if( memcmp( out, test_kdf_out, sizeof( out ) ) != 0 )
ret = -1;
cleanup:
ecp_drbg_free( &kdf_ctx );
mbedtls_mpi_free( &scalar );
return( ret );
}
#endif /* ECP_ONE_STEP_KDF */
/* /*
* Checkup routine * Checkup routine
*/ */
@ -3037,6 +3423,24 @@ int mbedtls_ecp_self_test( int verbose )
if( verbose != 0 ) if( verbose != 0 )
mbedtls_printf( "passed\n" ); mbedtls_printf( "passed\n" );
#if defined(ECP_ONE_STEP_KDF)
if( verbose != 0 )
mbedtls_printf( " ECP test #3 (internal KDF): " );
ret = ecp_kdf_self_test();
if( ret != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
ret = 1;
goto cleanup;
}
if( verbose != 0 )
mbedtls_printf( "passed\n" );
#endif /* ECP_ONE_STEP_KDF */
cleanup: cleanup:
if( ret < 0 && verbose != 0 ) if( ret < 0 && verbose != 0 )

View File

@ -2296,10 +2296,20 @@ static int ssl_decrypt_buf( mbedtls_ssl_context *ssl )
ssl_read_memory( ssl->in_msg + ssl->in_msglen, padlen ); ssl_read_memory( ssl->in_msg + ssl->in_msglen, padlen );
mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, mac_expect ); mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, mac_expect );
/* Call mbedtls_md_process at least once due to cache attacks /* Dummy calls to compression function.
* that observe whether md_process() was called of not */ * Call mbedtls_md_process at least once due to cache attacks
* that observe whether md_process() was called of not.
* Respect the usual start-(process|update)-finish sequence for
* the sake of hardware accelerators that might require it. */
mbedtls_md_starts( &ssl->transform_in->md_ctx_dec );
for( j = 0; j < extra_run + 1; j++ ) for( j = 0; j < extra_run + 1; j++ )
mbedtls_md_process( &ssl->transform_in->md_ctx_dec, ssl->in_msg ); mbedtls_md_process( &ssl->transform_in->md_ctx_dec, ssl->in_msg );
{
/* The switch statement above already checks that we're using
* one of MD-5, SHA-1, SHA-256 or SHA-384. */
unsigned char tmp[384 / 8];
mbedtls_md_finish( &ssl->transform_in->md_ctx_dec, tmp );
}
mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec ); mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec );

View File

@ -378,6 +378,9 @@ static const char *features[] = {
#if defined(MBEDTLS_ECP_NIST_OPTIM) #if defined(MBEDTLS_ECP_NIST_OPTIM)
"MBEDTLS_ECP_NIST_OPTIM", "MBEDTLS_ECP_NIST_OPTIM",
#endif /* MBEDTLS_ECP_NIST_OPTIM */ #endif /* MBEDTLS_ECP_NIST_OPTIM */
#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
"MBEDTLS_ECP_NO_INTERNAL_RNG",
#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
#if defined(MBEDTLS_ECP_RESTARTABLE) #if defined(MBEDTLS_ECP_RESTARTABLE)
"MBEDTLS_ECP_RESTARTABLE", "MBEDTLS_ECP_RESTARTABLE",
#endif /* MBEDTLS_ECP_RESTARTABLE */ #endif /* MBEDTLS_ECP_RESTARTABLE */

View File

@ -1005,6 +1005,14 @@ int query_config( const char *config )
} }
#endif /* MBEDTLS_ECP_NIST_OPTIM */ #endif /* MBEDTLS_ECP_NIST_OPTIM */
#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG)
if( strcmp( "MBEDTLS_ECP_NO_INTERNAL_RNG", config ) == 0 )
{
MACRO_EXPANSION_TO_STR( MBEDTLS_ECP_NO_INTERNAL_RNG );
return( 0 );
}
#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */
#if defined(MBEDTLS_ECP_RESTARTABLE) #if defined(MBEDTLS_ECP_RESTARTABLE)
if( strcmp( "MBEDTLS_ECP_RESTARTABLE", config ) == 0 ) if( strcmp( "MBEDTLS_ECP_RESTARTABLE", config ) == 0 )
{ {

View File

@ -113,6 +113,7 @@ my @excluded = qw(
MBEDTLS_CTR_DRBG_USE_128_BIT_KEY MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
MBEDTLS_DEPRECATED_REMOVED MBEDTLS_DEPRECATED_REMOVED
MBEDTLS_DEPRECATED_WARNING MBEDTLS_DEPRECATED_WARNING
MBEDTLS_ECP_NO_INTERNAL_RNG
MBEDTLS_HAVE_SSE2 MBEDTLS_HAVE_SSE2
MBEDTLS_MEMORY_BACKTRACE MBEDTLS_MEMORY_BACKTRACE
MBEDTLS_MEMORY_BUFFER_ALLOC_C MBEDTLS_MEMORY_BUFFER_ALLOC_C

View File

@ -896,6 +896,80 @@ component_test_no_hmac_drbg () {
# so there's little value in running those lengthy tests here. # so there's little value in running those lengthy tests here.
} }
component_test_no_drbg_all_hashes () {
# this tests the internal ECP DRBG using a KDF based on SHA-512
msg "build: Default minus DRBGs"
scripts/config.pl unset MBEDTLS_CTR_DRBG_C
scripts/config.pl unset MBEDTLS_HMAC_DRBG_C
scripts/config.pl unset MBEDTLS_ECDSA_DETERMINISTIC # requires HMAC_DRBG
scripts/config.pl unset MBEDTLS_PSA_CRYPTO_C # requires a DRBG
scripts/config.pl unset MBEDTLS_PSA_CRYPTO_STORAGE_C # requires PSA Crypto
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
make
msg "test: Default minus DRBGs"
make test
# no SSL tests as they all depend on having a DRBG
}
component_test_no_drbg_no_sha512 () {
# this tests the internal ECP DRBG using a KDF based on SHA-256
msg "build: Default minus DRBGs minus SHA-512"
scripts/config.pl unset MBEDTLS_CTR_DRBG_C
scripts/config.pl unset MBEDTLS_HMAC_DRBG_C
scripts/config.pl unset MBEDTLS_ECDSA_DETERMINISTIC # requires HMAC_DRBG
scripts/config.pl unset MBEDTLS_PSA_CRYPTO_C # requires a DRBG
scripts/config.pl unset MBEDTLS_PSA_CRYPTO_STORAGE_C # requires PSA Crypto
scripts/config.pl unset MBEDTLS_SHA512_C
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
make
msg "test: Default minus DRBGs minus SHA-512"
make test
# no SSL tests as they all depend on having a DRBG
}
component_test_ecp_no_internal_rng () {
msg "build: Default plus ECP_NO_INTERNAL_RNG minus DRBG modules"
scripts/config.pl set MBEDTLS_ECP_NO_INTERNAL_RNG
scripts/config.pl unset MBEDTLS_CTR_DRBG_C
scripts/config.pl unset MBEDTLS_HMAC_DRBG_C
scripts/config.pl unset MBEDTLS_ECDSA_DETERMINISTIC # requires HMAC_DRBG
scripts/config.pl unset MBEDTLS_PSA_CRYPTO_C # requires a DRBG
scripts/config.pl unset MBEDTLS_PSA_CRYPTO_STORAGE_C # requires PSA Crypto
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
make
msg "test: ECP_NO_INTERNAL_RNG, no DRBG module"
make test
# no SSL tests as they all depend on having a DRBG
}
component_test_ecp_restartable_no_internal_rng () {
msg "build: Default plus ECP_RESTARTABLE and ECP_NO_INTERNAL_RNG, no DRBG"
scripts/config.pl set MBEDTLS_ECP_NO_INTERNAL_RNG
scripts/config.pl set MBEDTLS_ECP_RESTARTABLE
scripts/config.pl unset MBEDTLS_CTR_DRBG_C
scripts/config.pl unset MBEDTLS_HMAC_DRBG_C
scripts/config.pl unset MBEDTLS_ECDSA_DETERMINISTIC # requires HMAC_DRBG
scripts/config.pl unset MBEDTLS_PSA_CRYPTO_C # requires CTR_DRBG
scripts/config.pl unset MBEDTLS_PSA_CRYPTO_STORAGE_C # requires PSA Crypto
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
make
msg "test: ECP_RESTARTABLE and ECP_NO_INTERNAL_RNG, no DRBG module"
make test
# no SSL tests as they all depend on having a DRBG
}
component_test_small_ssl_out_content_len () { component_test_small_ssl_out_content_len () {
msg "build: small SSL_OUT_CONTENT_LEN (ASan build)" msg "build: small SSL_OUT_CONTENT_LEN (ASan build)"
scripts/config.pl set MBEDTLS_SSL_IN_CONTENT_LEN 16384 scripts/config.pl set MBEDTLS_SSL_IN_CONTENT_LEN 16384