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, MBEDTLS_ENTROPY_BLOCK_SIZE)
12
13#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
14
15#if defined(MBEDTLS_PSA_ITS_FILE_C)
16#include <stdio.h>
17#else
18#include <psa/internal_trusted_storage.h>
19#endif
20
21/* Remove the entropy seed file. Since the library does not expose a way
22 * to do this (it would be a security risk if such a function was ever
23 * accessible in production), implement this functionality in a white-box
24 * manner. */
25psa_status_t remove_seed_file( void )
26{
27#if defined(MBEDTLS_PSA_ITS_FILE_C)
28    if( remove( "00000000ffffff52.psa_its" ) == 0 )
29        return( PSA_SUCCESS );
30    else
31        return( PSA_ERROR_DOES_NOT_EXIST );
32#else
33    return( psa_its_remove( PSA_CRYPTO_ITS_RANDOM_SEED_UID ) );
34#endif
35}
36
37#endif /* MBEDTLS_PSA_INJECT_ENTROPY */
38
39/* END_HEADER */
40
41/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
42void external_rng_failure_generate( )
43{
44    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
45    psa_set_key_type( &attributes, PSA_KEY_TYPE_DERIVE );
46    psa_set_key_bits( &attributes, 128 );
47    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
48    uint8_t output[1];
49
50    PSA_ASSERT( psa_crypto_init( ) );
51
52    PSA_ASSERT( psa_generate_random( output, sizeof( output ) ) );
53    PSA_ASSERT( psa_generate_key( &attributes, &key ) );
54    PSA_ASSERT( psa_destroy_key( key ) );
55
56    mbedtls_test_disable_insecure_external_rng( );
57    TEST_EQUAL( PSA_ERROR_INSUFFICIENT_ENTROPY,
58                psa_generate_random( output, sizeof( output ) ) );
59    TEST_EQUAL( PSA_ERROR_INSUFFICIENT_ENTROPY,
60                psa_generate_key( &attributes, &key ) );
61
62exit:
63    psa_destroy_key( key );
64    PSA_DONE( );
65}
66/* END_CASE */
67
68/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
69void external_rng_failure_sign( int key_type, data_t *key_data, int alg,
70                                int input_size_arg )
71{
72    /* This test case is only expected to pass if the signature mechanism
73     * requires randomness, either because it is a randomized signature
74     * or because the implementation uses blinding. */
75
76    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
77    psa_set_key_type( &attributes, key_type );
78    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH );
79    psa_set_key_algorithm( &attributes, alg );
80    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
81    size_t input_size = input_size_arg;
82    uint8_t *input = NULL;
83    uint8_t *signature = NULL;
84    size_t signature_size = PSA_SIGNATURE_MAX_SIZE;
85    size_t signature_length;
86
87    ASSERT_ALLOC( input, input_size );
88    ASSERT_ALLOC( signature, signature_size );
89
90    PSA_ASSERT( psa_crypto_init( ) );
91    PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
92                                &key ) );
93    PSA_ASSERT( psa_sign_hash( key, alg,
94                               input, input_size,
95                               signature, signature_size,
96                               &signature_length ) );
97    PSA_ASSERT( psa_destroy_key( key ) );
98
99    mbedtls_test_disable_insecure_external_rng( );
100    /* Import the key again, because for RSA Mbed TLS caches blinding values
101     * in the key object and this could perturb the test. */
102    PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
103                                &key ) );
104    TEST_EQUAL( PSA_ERROR_INSUFFICIENT_ENTROPY,
105                psa_sign_hash( key, alg,
106                               input, input_size,
107                               signature, signature_size,
108                               &signature_length ) );
109    PSA_ASSERT( psa_destroy_key( key ) );
110
111exit:
112    psa_destroy_key( key );
113    PSA_DONE( );
114    mbedtls_free( input );
115    mbedtls_free( signature );
116}
117/* END_CASE */
118
119/* BEGIN_CASE depends_on:MBEDTLS_PSA_INJECT_ENTROPY */
120void validate_entropy_seed_injection( int seed_length_a,
121                                      int expected_status_a,
122                                      int seed_length_b,
123                                      int expected_status_b )
124{
125    psa_status_t status;
126    uint8_t output[32] = { 0 };
127    uint8_t zeros[32] = { 0 };
128    uint8_t *seed = NULL;
129    int i;
130    int seed_size;
131    if( seed_length_a > seed_length_b )
132    {
133        seed_size = seed_length_a;
134    }
135    else
136    {
137        seed_size = seed_length_b;
138    }
139    ASSERT_ALLOC( seed, seed_size );
140    /* fill seed with some data */
141    for( i = 0; i < seed_size; ++i )
142    {
143        seed[i] = i;
144    }
145    status =  remove_seed_file( );
146    TEST_ASSERT( ( status == PSA_SUCCESS ) ||
147                 ( status == PSA_ERROR_DOES_NOT_EXIST ) );
148    status = mbedtls_psa_inject_entropy( seed, seed_length_a );
149    TEST_EQUAL( status, expected_status_a );
150    status = mbedtls_psa_inject_entropy( seed, seed_length_b );
151    TEST_EQUAL( status, expected_status_b );
152    PSA_ASSERT( psa_crypto_init( ) );
153    PSA_ASSERT( psa_generate_random( output,
154                                     sizeof( output ) ) );
155    TEST_ASSERT( memcmp( output, zeros, sizeof( output ) ) != 0 );
156exit:
157    mbedtls_free( seed );
158    remove_seed_file( );
159    PSA_DONE( );
160}
161/* END_CASE */
162
163/* BEGIN_CASE depends_on:MBEDTLS_PSA_INJECT_ENTROPY */
164void run_entropy_inject_with_crypto_init( )
165{
166    psa_status_t status;
167    size_t i;
168    uint8_t seed[MBEDTLS_PSA_INJECT_ENTROPY_MIN_SIZE] = { 0 };
169    /* fill seed with some data */
170    for( i = 0; i < sizeof( seed ); ++i )
171    {
172        seed[i] = i;
173    }
174    status =  remove_seed_file( );
175    TEST_ASSERT( ( status == PSA_SUCCESS ) ||
176                 ( status == PSA_ERROR_DOES_NOT_EXIST ) );
177    status = mbedtls_psa_inject_entropy( seed, sizeof( seed ) );
178    PSA_ASSERT( status );
179    status =  remove_seed_file( );
180    TEST_EQUAL( status, PSA_SUCCESS );
181    status = psa_crypto_init( );
182    TEST_EQUAL( status, PSA_ERROR_INSUFFICIENT_ENTROPY );
183    status = mbedtls_psa_inject_entropy( seed, sizeof( seed ) );
184    PSA_ASSERT( status );
185    status = psa_crypto_init( );
186    PSA_ASSERT( status );
187    PSA_DONE( );
188    /* The seed is written by nv_seed callback functions therefore the injection will fail */
189    status = mbedtls_psa_inject_entropy( seed, sizeof( seed ) );
190    TEST_EQUAL( status, PSA_ERROR_NOT_PERMITTED );
191exit:
192    remove_seed_file( );
193    PSA_DONE( );
194}
195/* END_CASE */
196