1/* BEGIN_HEADER */ 2#include <stdint.h> 3 4/* Some tests in this module configure entropy sources. */ 5#include "psa_crypto_invasive.h" 6 7#include "mbedtls/entropy.h" 8#include "entropy_poll.h" 9 10#define ENTROPY_MIN_NV_SEED_SIZE \ 11 MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_BLOCK_SIZE) 12 13#include "psa_crypto_random_impl.h" 14#if defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE) 15/* PSA crypto uses the HMAC_DRBG module. It reads from the entropy source twice: 16 * once for the initial entropy and once for a nonce. The nonce length is 17 * half the entropy length. For SHA-256, SHA-384 or SHA-512, the 18 * entropy length is 256 per the documentation of mbedtls_hmac_drbg_seed(), 19 * and PSA crypto doesn't support other hashes for HMAC_DRBG. */ 20#define ENTROPY_NONCE_LEN ( 256 / 2 ) 21#else 22/* PSA crypto uses the CTR_DRBG module. In some configurations, it needs 23 * to read from the entropy source twice: once for the initial entropy 24 * and once for a nonce. */ 25#include "mbedtls/ctr_drbg.h" 26#define ENTROPY_NONCE_LEN MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN 27#endif 28 29#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) 30 31typedef struct 32{ 33 size_t threshold; /* Minimum bytes to make mbedtls_entropy_func happy */ 34 size_t max_steps; 35 size_t *length_sequence; 36 size_t step; 37} fake_entropy_state_t; 38static int fake_entropy_source( void *state_arg, 39 unsigned char *output, size_t len, 40 size_t *olen ) 41{ 42 fake_entropy_state_t *state = state_arg; 43 size_t i; 44 45 if( state->step >= state->max_steps ) 46 return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); 47 48 *olen = MIN( len, state->length_sequence[state->step] ); 49 for( i = 0; i < *olen; i++ ) 50 output[i] = i; 51 ++state->step; 52 return( 0 ); 53} 54 55#define ENTROPY_SOURCE_PLATFORM 0x00000001 56#define ENTROPY_SOURCE_TIMING 0x00000002 57#define ENTROPY_SOURCE_HARDWARE 0x00000004 58#define ENTROPY_SOURCE_NV_SEED 0x00000008 59#define ENTROPY_SOURCE_FAKE 0x40000000 60 61static uint32_t custom_entropy_sources_mask; 62static fake_entropy_state_t fake_entropy_state; 63 64/* This is a modified version of mbedtls_entropy_init() from entropy.c 65 * which chooses entropy sources dynamically. */ 66static void custom_entropy_init( mbedtls_entropy_context *ctx ) 67{ 68 ctx->source_count = 0; 69 memset( ctx->source, 0, sizeof( ctx->source ) ); 70 71#if defined(MBEDTLS_THREADING_C) 72 mbedtls_mutex_init( &ctx->mutex ); 73#endif 74 75 ctx->accumulator_started = 0; 76#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) 77 mbedtls_sha512_init( &ctx->accumulator ); 78#else 79 mbedtls_sha256_init( &ctx->accumulator ); 80#endif 81 82#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) 83 if( custom_entropy_sources_mask & ENTROPY_SOURCE_PLATFORM ) 84 mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL, 85 MBEDTLS_ENTROPY_MIN_PLATFORM, 86 MBEDTLS_ENTROPY_SOURCE_STRONG ); 87#endif 88#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) 89 if( custom_entropy_sources_mask & ENTROPY_SOURCE_HARDWARE ) 90 mbedtls_entropy_add_source( ctx, mbedtls_hardware_poll, NULL, 91 MBEDTLS_ENTROPY_MIN_HARDWARE, 92 MBEDTLS_ENTROPY_SOURCE_STRONG ); 93#endif 94#if defined(MBEDTLS_ENTROPY_NV_SEED) 95 if( custom_entropy_sources_mask & ENTROPY_SOURCE_NV_SEED ) 96 { 97 mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL, 98 MBEDTLS_ENTROPY_BLOCK_SIZE, 99 MBEDTLS_ENTROPY_SOURCE_STRONG ); 100 ctx->initial_entropy_run = 0; 101 } 102 else 103 { 104 /* Skip the NV seed even though it's compiled in. */ 105 ctx->initial_entropy_run = 1; 106 } 107#endif 108 109 if( custom_entropy_sources_mask & ENTROPY_SOURCE_FAKE ) 110 mbedtls_entropy_add_source( ctx, 111 fake_entropy_source, &fake_entropy_state, 112 fake_entropy_state.threshold, 113 MBEDTLS_ENTROPY_SOURCE_STRONG ); 114} 115 116#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */ 117 118/* END_HEADER */ 119 120/* BEGIN_DEPENDENCIES 121 * depends_on:MBEDTLS_PSA_CRYPTO_C 122 * END_DEPENDENCIES 123 */ 124 125/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ 126void create_nv_seed( ) 127{ 128 static unsigned char seed[ENTROPY_MIN_NV_SEED_SIZE]; 129 TEST_ASSERT( mbedtls_nv_seed_write( seed, sizeof( seed ) ) >= 0 ); 130} 131/* END_CASE */ 132 133/* BEGIN_CASE */ 134void init_deinit( int count ) 135{ 136 psa_status_t status; 137 int i; 138 for( i = 0; i < count; i++ ) 139 { 140 status = psa_crypto_init( ); 141 PSA_ASSERT( status ); 142 status = psa_crypto_init( ); 143 PSA_ASSERT( status ); 144 PSA_DONE( ); 145 } 146} 147/* END_CASE */ 148 149/* BEGIN_CASE */ 150void deinit_without_init( int count ) 151{ 152 int i; 153 for( i = 0; i < count; i++ ) 154 { 155 PSA_ASSERT( psa_crypto_init( ) ); 156 PSA_DONE( ); 157 } 158 PSA_DONE( ); 159} 160/* END_CASE */ 161 162/* BEGIN_CASE */ 163void validate_module_init_generate_random( int count ) 164{ 165 psa_status_t status; 166 uint8_t random[10] = { 0 }; 167 int i; 168 for( i = 0; i < count; i++ ) 169 { 170 status = psa_crypto_init( ); 171 PSA_ASSERT( status ); 172 PSA_DONE( ); 173 } 174 status = psa_generate_random( random, sizeof( random ) ); 175 TEST_EQUAL( status, PSA_ERROR_BAD_STATE ); 176} 177/* END_CASE */ 178 179/* BEGIN_CASE */ 180void validate_module_init_key_based( int count ) 181{ 182 psa_status_t status; 183 uint8_t data[10] = { 0 }; 184 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; 185 mbedtls_svc_key_id_t key = mbedtls_svc_key_id_make( 0xdead, 0xdead ); 186 int i; 187 188 for( i = 0; i < count; i++ ) 189 { 190 status = psa_crypto_init( ); 191 PSA_ASSERT( status ); 192 PSA_DONE( ); 193 } 194 psa_set_key_type( &attributes, PSA_KEY_TYPE_RAW_DATA ); 195 status = psa_import_key( &attributes, data, sizeof( data ), &key ); 196 TEST_EQUAL( status, PSA_ERROR_BAD_STATE ); 197 TEST_ASSERT( mbedtls_svc_key_id_is_null( key ) ); 198} 199/* END_CASE */ 200 201/* BEGIN_CASE depends_on:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ 202void custom_entropy_sources( int sources_arg, int expected_init_status_arg ) 203{ 204 psa_status_t expected_init_status = expected_init_status_arg; 205 uint8_t random[10] = { 0 }; 206 207 custom_entropy_sources_mask = sources_arg; 208 PSA_ASSERT( mbedtls_psa_crypto_configure_entropy_sources( 209 custom_entropy_init, mbedtls_entropy_free ) ); 210 211 TEST_EQUAL( psa_crypto_init( ), expected_init_status ); 212 if( expected_init_status != PSA_SUCCESS ) 213 goto exit; 214 215 PSA_ASSERT( psa_generate_random( random, sizeof( random ) ) ); 216 217exit: 218 PSA_DONE( ); 219} 220/* END_CASE */ 221 222/* BEGIN_CASE depends_on:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ 223void fake_entropy_source( int threshold, 224 int amount1, 225 int amount2, 226 int amount3, 227 int amount4, 228 int expected_init_status_arg ) 229{ 230 psa_status_t expected_init_status = expected_init_status_arg; 231 uint8_t random[10] = { 0 }; 232 size_t lengths[4]; 233 234 fake_entropy_state.threshold = threshold; 235 fake_entropy_state.step = 0; 236 fake_entropy_state.max_steps = 0; 237 if( amount1 >= 0 ) 238 lengths[fake_entropy_state.max_steps++] = amount1; 239 if( amount2 >= 0 ) 240 lengths[fake_entropy_state.max_steps++] = amount2; 241 if( amount3 >= 0 ) 242 lengths[fake_entropy_state.max_steps++] = amount3; 243 if( amount4 >= 0 ) 244 lengths[fake_entropy_state.max_steps++] = amount4; 245 fake_entropy_state.length_sequence = lengths; 246 247 custom_entropy_sources_mask = ENTROPY_SOURCE_FAKE; 248 PSA_ASSERT( mbedtls_psa_crypto_configure_entropy_sources( 249 custom_entropy_init, mbedtls_entropy_free ) ); 250 251 TEST_EQUAL( psa_crypto_init( ), expected_init_status ); 252 if( expected_init_status != PSA_SUCCESS ) 253 goto exit; 254 255 PSA_ASSERT( psa_generate_random( random, sizeof( random ) ) ); 256 257exit: 258 PSA_DONE( ); 259} 260/* END_CASE */ 261 262/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:!MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ 263void entropy_from_nv_seed( int seed_size_arg, 264 int expected_init_status_arg ) 265{ 266 psa_status_t expected_init_status = expected_init_status_arg; 267 uint8_t random[10] = { 0 }; 268 uint8_t *seed = NULL; 269 size_t seed_size = seed_size_arg; 270 271 ASSERT_ALLOC( seed, seed_size ); 272 TEST_ASSERT( mbedtls_nv_seed_write( seed, seed_size ) >= 0 ); 273 274 custom_entropy_sources_mask = ENTROPY_SOURCE_NV_SEED; 275 PSA_ASSERT( mbedtls_psa_crypto_configure_entropy_sources( 276 custom_entropy_init, mbedtls_entropy_free ) ); 277 278 TEST_EQUAL( psa_crypto_init( ), expected_init_status ); 279 if( expected_init_status != PSA_SUCCESS ) 280 goto exit; 281 282 PSA_ASSERT( psa_generate_random( random, sizeof( random ) ) ); 283 284exit: 285 mbedtls_free( seed ); 286 PSA_DONE( ); 287} 288/* END_CASE */ 289