Gate entropy injection through a dedicated configuration option

Entropy injection has specific testing requirements. Therefore it
should depend on a specific option.
This commit is contained in:
Gilles Peskine 2019-02-25 11:04:06 +01:00
parent 6bf4baef95
commit e3dbdd8d90
11 changed files with 125 additions and 31 deletions

View file

@ -1231,6 +1231,19 @@
*/
//#define MBEDTLS_PSA_CRYPTO_SPM
/**
* \def MBEDTLS_PSA_INJECT_ENTROPY
*
* Enable support for entropy injection at first boot. This feature is
* required on systems that do not have a built-in entropy source (TRNG).
* This feature is currently not supported on systems that have a built-in
* entropy source.
*
* Requires: MBEDTLS_PSA_CRYPTO_STORAGE_C, MBEDTLS_ENTROPY_NV_SEED
*
*/
//#define MBEDTLS_PSA_INJECT_ENTROPY
/**
* \def MBEDTLS_RSA_NO_CRT
*
@ -2715,7 +2728,7 @@
*
* Requires: MBEDTLS_FS_IO
*/
//#define MBEDTLS_PSA_ITS_FILE_C
#define MBEDTLS_PSA_ITS_FILE_C
/**
* \def MBEDTLS_RIPEMD160_C

View file

@ -530,6 +530,17 @@
#error "MBEDTLS_PSA_CRYPTO_STORAGE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \
!( defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) && \
defined(MBEDTLS_ENTROPY_NV_SEED) )
#error "MBEDTLS_PSA_INJECT_ENTROPY defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \
!defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)
#error "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with actual entropy sources"
#endif
#if defined(MBEDTLS_PSA_ITS_FILE_C) && \
!defined(MBEDTLS_FS_IO)
#error "MBEDTLS_PSA_ITS_FILE_C defined, but not all prerequisites"

View file

@ -1251,6 +1251,19 @@
*/
//#define MBEDTLS_PSA_CRYPTO_SPM
/**
* \def MBEDTLS_PSA_INJECT_ENTROPY
*
* Enable support for entropy injection at first boot. This feature is
* required on systems that do not have a built-in entropy source (TRNG).
* This feature is currently not supported on systems that have a built-in
* entropy source.
*
* Requires: MBEDTLS_PSA_CRYPTO_STORAGE_C, MBEDTLS_ENTROPY_NV_SEED
*
*/
//#define MBEDTLS_PSA_INJECT_ENTROPY
/**
* \def MBEDTLS_RSA_NO_CRT
*

View file

@ -114,10 +114,9 @@ void mbedtls_psa_crypto_free( void );
* This is an Mbed TLS extension.
*
* \note This function is only available on the following platforms:
* * If the compile-time options MBEDTLS_ENTROPY_NV_SEED and
* MBEDTLS_PSA_CRYPTO_STORAGE_C are both enabled. Note that you
* must provide compatible implementations of mbedtls_nv_seed_read
* and mbedtls_nv_seed_write.
* * If the compile-time option MBEDTLS_PSA_INJECT_ENTROPY is enabled.
* Note that you must provide compatible implementations of
* mbedtls_nv_seed_read and mbedtls_nv_seed_write.
* * In a client-server integration of PSA Cryptography, on the client side,
* if the server supports this feature.
* \param[in] seed Buffer containing the seed value to inject.

View file

@ -60,7 +60,6 @@
#include "mbedtls/ecdh.h"
#include "mbedtls/ecp.h"
#include "mbedtls/entropy.h"
#include "mbedtls/entropy_poll.h"
#include "mbedtls/error.h"
#include "mbedtls/gcm.h"
#include "mbedtls/md2.h"
@ -4419,13 +4418,12 @@ psa_status_t psa_generate_random( uint8_t *output,
return( mbedtls_to_psa_error( ret ) );
}
#if defined(MBEDTLS_ENTROPY_NV_SEED) && \
defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
#include "mbedtls/entropy_poll.h"
psa_status_t mbedtls_psa_inject_entropy( const unsigned char *seed,
size_t seed_size )
{
psa_status_t status;
struct psa_storage_info_t p_info;
if( global_data.initialized )
return( PSA_ERROR_NOT_PERMITTED );
@ -4434,20 +4432,9 @@ psa_status_t mbedtls_psa_inject_entropy( const unsigned char *seed,
( seed_size > MBEDTLS_ENTROPY_MAX_SEED_SIZE ) )
return( PSA_ERROR_INVALID_ARGUMENT );
status = psa_its_get_info( PSA_CRYPTO_ITS_RANDOM_SEED_UID, &p_info );
if( PSA_ERROR_DOES_NOT_EXIST == status ) /* No seed exists */
{
status = psa_its_set( PSA_CRYPTO_ITS_RANDOM_SEED_UID, seed_size, seed, 0 );
}
else if( PSA_SUCCESS == status )
{
/* You should not be here. Seed needs to be injected only once */
status = PSA_ERROR_NOT_PERMITTED;
}
return( status );
return( mbedtls_psa_storage_inject_entropy( seed, seed_size ) );
}
#endif
#endif /* MBEDTLS_PSA_INJECT_ENTROPY */
psa_status_t psa_generate_key( psa_key_handle_t handle,
psa_key_type_t type,

View file

@ -391,4 +391,26 @@ exit:
return( status );
}
#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
psa_status_t mbedtls_psa_storage_inject_entropy( const unsigned char *seed,
size_t seed_size )
{
psa_status_t status;
struct psa_storage_info_t p_info;
status = psa_its_get_info( PSA_CRYPTO_ITS_RANDOM_SEED_UID, &p_info );
if( PSA_ERROR_DOES_NOT_EXIST == status ) /* No seed exists */
{
status = psa_its_set( PSA_CRYPTO_ITS_RANDOM_SEED_UID, seed_size, seed, 0 );
}
else if( PSA_SUCCESS == status )
{
/* You should not be here. Seed needs to be injected only once */
status = PSA_ERROR_NOT_PERMITTED;
}
return( status );
}
#endif /* MBEDTLS_PSA_INJECT_ENTROPY */
#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */

View file

@ -203,6 +203,22 @@ psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data,
psa_key_type_t *type,
psa_key_policy_t *policy );
#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
/** Backend side of mbedtls_psa_inject_entropy().
*
* This function stores the supplied data into the entropy seed file.
*
* \retval #PSA_SUCCESS
* Success
* \retval #PSA_ERROR_STORAGE_FAILURE
* \retval #PSA_ERROR_INSUFFICIENT_STORAGE
* \retval #PSA_ERROR_NOT_PERMITTED
* The entropy seed file already exists.
*/
psa_status_t mbedtls_psa_storage_inject_entropy( const unsigned char *seed,
size_t seed_size );
#endif /* MBEDTLS_PSA_INJECT_ENTROPY */
#ifdef __cplusplus
}
#endif

View file

@ -432,6 +432,9 @@ static const char *features[] = {
#if defined(MBEDTLS_PSA_CRYPTO_SPM)
"MBEDTLS_PSA_CRYPTO_SPM",
#endif /* MBEDTLS_PSA_CRYPTO_SPM */
#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
"MBEDTLS_PSA_INJECT_ENTROPY",
#endif /* MBEDTLS_PSA_INJECT_ENTROPY */
#if defined(MBEDTLS_RSA_NO_CRT)
"MBEDTLS_RSA_NO_CRT",
#endif /* MBEDTLS_RSA_NO_CRT */

View file

@ -1194,6 +1194,14 @@ int query_config( const char *config )
}
#endif /* MBEDTLS_PSA_CRYPTO_SPM */
#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
if( strcmp( "MBEDTLS_PSA_INJECT_ENTROPY", config ) == 0 )
{
MACRO_EXPANSION_TO_STR( MBEDTLS_PSA_INJECT_ENTROPY );
return( 0 );
}
#endif /* MBEDTLS_PSA_INJECT_ENTROPY */
#if defined(MBEDTLS_RSA_NO_CRT)
if( strcmp( "MBEDTLS_RSA_NO_CRT", config ) == 0 )
{

View file

@ -102,6 +102,7 @@ MBEDTLS_NO_UDBL_DIVISION
MBEDTLS_NO_64BIT_MULTIPLICATION
MBEDTLS_PSA_CRYPTO_SPM
MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER
MBEDTLS_PSA_INJECT_ENTROPY
MBEDTLS_USE_PSA_CRYPTO
_ALT\s*$
);

View file

@ -2,17 +2,38 @@
#include <stdint.h>
#include "psa/crypto.h"
#include "psa_prot_internal_storage.h"
#include "mbedtls/entropy.h"
#include "mbedtls/entropy_poll.h"
#if defined(MBEDTLS_PSA_ITS_FILE_C)
#include <stdio.h>
#else
#include <psa/internal_trusted_storage.h>
#endif
/* Calculating the minimum allowed entropy size in bytes */
#define MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_BLOCK_SIZE)
/* Remove the entropy seed file. Since the library does not expose a way
* to do this (it would be a security risk if such a function was ever
* accessible in production), implement this functionality in a white-box
* manner. */
psa_status_t remove_seed_file( void )
{
#if defined(MBEDTLS_PSA_ITS_FILE_C)
if( remove( "00000000ffffff52.psa_its" ) == 0 )
return( PSA_SUCCESS );
else
return( PSA_ERROR_DOES_NOT_EXIST );
#else
return( psa_its_remove( PSA_CRYPTO_ITS_RANDOM_SEED_UID ) );
#endif
}
/* END_HEADER */
/* BEGIN_DEPENDENCIES
* depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_PSA_CRYPTO_STORAGE_C
* depends_on:MBEDTLS_PSA_INJECT_ENTROPY
* END_DEPENDENCIES
*/
@ -42,7 +63,7 @@ void validate_entropy_seed_injection( int seed_length_a,
{
seed[i] = i;
}
status = psa_its_remove( PSA_CRYPTO_ITS_RANDOM_SEED_UID );
status = remove_seed_file( );
TEST_ASSERT( ( status == PSA_SUCCESS ) ||
( status == PSA_ERROR_DOES_NOT_EXIST ) );
status = mbedtls_psa_inject_entropy( seed, seed_length_a );
@ -55,7 +76,7 @@ void validate_entropy_seed_injection( int seed_length_a,
TEST_ASSERT( memcmp( output, zeros, sizeof( output ) ) != 0 );
exit:
mbedtls_free( seed );
psa_its_remove( PSA_CRYPTO_ITS_RANDOM_SEED_UID );
remove_seed_file( );
mbedtls_psa_crypto_free( );
}
/* END_CASE */
@ -64,19 +85,19 @@ exit:
void run_entropy_inject_with_crypto_init( )
{
psa_status_t status;
int i;
size_t i;
uint8_t seed[MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE] = { 0 };
/* fill seed with some data */
for( i = 0; i < sizeof( seed ); ++i )
{
seed[i] = i;
}
status = psa_its_remove( PSA_CRYPTO_ITS_RANDOM_SEED_UID );
status = remove_seed_file( );
TEST_ASSERT( ( status == PSA_SUCCESS ) ||
( status == PSA_ERROR_DOES_NOT_EXIST ) );
status = mbedtls_psa_inject_entropy( seed, sizeof( seed ) );
PSA_ASSERT( status );
status = psa_its_remove( PSA_CRYPTO_ITS_RANDOM_SEED_UID );
status = remove_seed_file( );
TEST_EQUAL( status, PSA_SUCCESS );
status = psa_crypto_init( );
TEST_EQUAL( status, PSA_ERROR_INSUFFICIENT_ENTROPY );
@ -89,7 +110,7 @@ void run_entropy_inject_with_crypto_init( )
status = mbedtls_psa_inject_entropy( seed, sizeof( seed ) );
TEST_EQUAL( status, PSA_ERROR_NOT_PERMITTED );
exit:
psa_its_remove( PSA_CRYPTO_ITS_RANDOM_SEED_UID );
remove_seed_file( );
mbedtls_psa_crypto_free( );
}
/* END_CASE */