1/* BEGIN_HEADER */ 2#include <stdint.h> 3#include <string.h> 4 5#include <psa/crypto.h> 6 7#include "mbedtls/entropy.h" 8#include "entropy_poll.h" 9 10/* Calculating the minimum allowed entropy size in bytes */ 11#define MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE MAX(MBEDTLS_ENTROPY_MIN_PLATFORM, \ 12 MBEDTLS_ENTROPY_BLOCK_SIZE) 13 14#if defined(MBEDTLS_PSA_INJECT_ENTROPY) 15#include <psa_crypto_its.h> 16 17/* Check the entropy seed file. 18 * 19 * \param expected_size Expected size in bytes. 20 * If 0, the file must not exist. 21 * 22 * \retval 1 Either \p expected_size is nonzero and 23 * the entropy seed file exists and has exactly this size, 24 * or \p expected_size is zero and the file does not exist. 25 * \retval 0 Either \p expected_size is nonzero but 26 * the entropy seed file does not exist or has a different size, 27 * or \p expected_size is zero but the file exists. 28 * In this case, the test case is marked as failed. 29 * 30 * \note We enforce that the seed is in a specific ITS file. 31 * This must not change, otherwise we break backward compatibility if 32 * the library is upgraded on a device with an existing seed. 33 */ 34int check_random_seed_file(size_t expected_size) 35{ 36 /* The value of the random seed UID must not change. Otherwise that would 37 * break upgrades of the library on devices that already contain a seed 38 * file. If this test assertion fails, you've presumably broken backward 39 * compatibility! */ 40 TEST_EQUAL(PSA_CRYPTO_ITS_RANDOM_SEED_UID, 0xFFFFFF52); 41 42 struct psa_storage_info_t info = { 0, 0 }; 43 psa_status_t status = psa_its_get_info(PSA_CRYPTO_ITS_RANDOM_SEED_UID, 44 &info); 45 46 if (expected_size == 0) { 47 TEST_EQUAL(status, PSA_ERROR_DOES_NOT_EXIST); 48 } else { 49 TEST_EQUAL(status, PSA_SUCCESS); 50 TEST_EQUAL(info.size, expected_size); 51 } 52 return 1; 53 54exit: 55 return 0; 56} 57 58/* Remove the entropy seed file. 59 * 60 * See check_random_seed_file() regarding abstraction boundaries. 61 */ 62psa_status_t remove_seed_file(void) 63{ 64 return psa_its_remove(PSA_CRYPTO_ITS_RANDOM_SEED_UID); 65} 66 67#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ 68 69/* END_HEADER */ 70 71/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ 72void external_rng_failure_generate() 73{ 74 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; 75 psa_set_key_type(&attributes, PSA_KEY_TYPE_DERIVE); 76 psa_set_key_bits(&attributes, 128); 77 mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT; 78 uint8_t output[1]; 79 80 PSA_ASSERT(psa_crypto_init()); 81 82 PSA_ASSERT(psa_generate_random(output, sizeof(output))); 83 PSA_ASSERT(psa_generate_key(&attributes, &key)); 84 PSA_ASSERT(psa_destroy_key(key)); 85 86 mbedtls_test_disable_insecure_external_rng(); 87 TEST_EQUAL(PSA_ERROR_INSUFFICIENT_ENTROPY, 88 psa_generate_random(output, sizeof(output))); 89 TEST_EQUAL(PSA_ERROR_INSUFFICIENT_ENTROPY, 90 psa_generate_key(&attributes, &key)); 91 92exit: 93 psa_destroy_key(key); 94 PSA_DONE(); 95} 96/* END_CASE */ 97 98/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ 99void external_rng_failure_sign(int key_type, data_t *key_data, int alg, 100 int input_size_arg) 101{ 102 /* This test case is only expected to pass if the signature mechanism 103 * requires randomness, either because it is a randomized signature 104 * or because the implementation uses blinding. */ 105 106 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; 107 psa_set_key_type(&attributes, key_type); 108 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); 109 psa_set_key_algorithm(&attributes, alg); 110 mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT; 111 size_t input_size = input_size_arg; 112 uint8_t *input = NULL; 113 uint8_t *signature = NULL; 114 size_t signature_size = PSA_SIGNATURE_MAX_SIZE; 115 size_t signature_length; 116 117 TEST_CALLOC(input, input_size); 118 TEST_CALLOC(signature, signature_size); 119 120 PSA_ASSERT(psa_crypto_init()); 121 PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len, 122 &key)); 123 PSA_ASSERT(psa_sign_hash(key, alg, 124 input, input_size, 125 signature, signature_size, 126 &signature_length)); 127 PSA_ASSERT(psa_destroy_key(key)); 128 129 mbedtls_test_disable_insecure_external_rng(); 130 /* Import the key again, because for RSA Mbed TLS caches blinding values 131 * in the key object and this could perturb the test. */ 132 PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len, 133 &key)); 134 TEST_EQUAL(PSA_ERROR_INSUFFICIENT_ENTROPY, 135 psa_sign_hash(key, alg, 136 input, input_size, 137 signature, signature_size, 138 &signature_length)); 139 PSA_ASSERT(psa_destroy_key(key)); 140 141exit: 142 psa_destroy_key(key); 143 PSA_DONE(); 144 mbedtls_free(input); 145 mbedtls_free(signature); 146} 147/* END_CASE */ 148 149/* BEGIN_CASE depends_on:MBEDTLS_PSA_INJECT_ENTROPY */ 150void validate_entropy_seed_injection(int seed_length_a, 151 int expected_status_a, 152 int seed_length_b, 153 int expected_status_b) 154{ 155 psa_status_t status; 156 uint8_t output[32] = { 0 }; 157 uint8_t zeros[32] = { 0 }; 158 uint8_t *seed = NULL; 159 int i; 160 int seed_size; 161 if (seed_length_a > seed_length_b) { 162 seed_size = seed_length_a; 163 } else { 164 seed_size = seed_length_b; 165 } 166 TEST_CALLOC(seed, seed_size); 167 /* fill seed with some data */ 168 for (i = 0; i < seed_size; ++i) { 169 seed[i] = i; 170 } 171 status = remove_seed_file(); 172 TEST_ASSERT((status == PSA_SUCCESS) || 173 (status == PSA_ERROR_DOES_NOT_EXIST)); 174 if (!check_random_seed_file(0)) { 175 goto exit; 176 } 177 178 status = mbedtls_psa_inject_entropy(seed, seed_length_a); 179 TEST_EQUAL(status, expected_status_a); 180 if (!check_random_seed_file(expected_status_a == PSA_SUCCESS ? seed_length_a : 181 0)) { 182 goto exit; 183 } 184 185 status = mbedtls_psa_inject_entropy(seed, seed_length_b); 186 TEST_EQUAL(status, expected_status_b); 187 if (!check_random_seed_file(expected_status_a == PSA_SUCCESS ? seed_length_a : 188 expected_status_b == PSA_SUCCESS ? seed_length_b : 189 0)) { 190 goto exit; 191 } 192 193 PSA_ASSERT(psa_crypto_init()); 194 PSA_ASSERT(psa_generate_random(output, 195 sizeof(output))); 196 TEST_ASSERT(memcmp(output, zeros, sizeof(output)) != 0); 197 198exit: 199 mbedtls_free(seed); 200 PSA_DONE(); 201 mbedtls_test_inject_entropy_restore(); 202} 203/* END_CASE */ 204 205/* BEGIN_CASE depends_on:MBEDTLS_PSA_INJECT_ENTROPY */ 206void run_entropy_inject_with_crypto_init() 207{ 208 psa_status_t status; 209 size_t i; 210 uint8_t seed[MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE] = { 0 }; 211 /* fill seed with some data */ 212 for (i = 0; i < sizeof(seed); ++i) { 213 seed[i] = i; 214 } 215 216 status = remove_seed_file(); 217 TEST_ASSERT((status == PSA_SUCCESS) || 218 (status == PSA_ERROR_DOES_NOT_EXIST)); 219 if (!check_random_seed_file(0)) { 220 goto exit; 221 } 222 status = mbedtls_psa_inject_entropy(seed, sizeof(seed)); 223 PSA_ASSERT(status); 224 TEST_ASSERT(check_random_seed_file(sizeof(seed))); 225 status = remove_seed_file(); 226 TEST_EQUAL(status, PSA_SUCCESS); 227 if (!check_random_seed_file(0)) { 228 goto exit; 229 } 230 231 status = psa_crypto_init(); 232 TEST_EQUAL(status, PSA_ERROR_INSUFFICIENT_ENTROPY); 233 status = mbedtls_psa_inject_entropy(seed, sizeof(seed)); 234 PSA_ASSERT(status); 235 if (!check_random_seed_file(sizeof(seed))) { 236 goto exit; 237 } 238 239 status = psa_crypto_init(); 240 PSA_ASSERT(status); 241 PSA_DONE(); 242 243 /* The seed is written by nv_seed callback functions therefore the injection will fail */ 244 status = mbedtls_psa_inject_entropy(seed, sizeof(seed)); 245 TEST_EQUAL(status, PSA_ERROR_NOT_PERMITTED); 246 247exit: 248 PSA_DONE(); 249 mbedtls_test_inject_entropy_restore(); 250} 251/* END_CASE */ 252