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