• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* BEGIN_HEADER */
2
3/* This test file is specific to the ITS implementation in PSA Crypto
4 * on top of stdio. It expects to know what the stdio name of a file is
5 * based on its keystore name.
6 *
7 * Note that if you need to make a change that affects how files are
8 * stored, this may indicate that the key store is changing in a
9 * backward-incompatible way! Think carefully about backward compatibility
10 * before changing how test data is constructed or validated.
11 */
12
13#include "../library/psa_crypto_its.h"
14
15#include "test/psa_helpers.h"
16
17/* Internal definitions of the implementation, copied for the sake of
18 * some of the tests and of the cleanup code. */
19#define PSA_ITS_STORAGE_PREFIX ""
20#define PSA_ITS_STORAGE_FILENAME_PATTERN "%08lx%08lx"
21#define PSA_ITS_STORAGE_SUFFIX ".psa_its"
22#define PSA_ITS_STORAGE_FILENAME_LENGTH         \
23    ( sizeof( PSA_ITS_STORAGE_PREFIX ) - 1 + /*prefix without terminating 0*/ \
24      16 + /*UID (64-bit number in hex)*/                               \
25      16 + /*UID (64-bit number in hex)*/                               \
26      sizeof( PSA_ITS_STORAGE_SUFFIX ) - 1 + /*suffix without terminating 0*/ \
27      1 /*terminating null byte*/ )
28#define PSA_ITS_STORAGE_TEMP \
29    PSA_ITS_STORAGE_PREFIX "tempfile" PSA_ITS_STORAGE_SUFFIX
30static void psa_its_fill_filename( psa_storage_uid_t uid, char *filename )
31{
32    /* Break up the UID into two 32-bit pieces so as not to rely on
33     * long long support in snprintf. */
34    mbedtls_snprintf( filename, PSA_ITS_STORAGE_FILENAME_LENGTH,
35                      "%s" PSA_ITS_STORAGE_FILENAME_PATTERN "%s",
36                      PSA_ITS_STORAGE_PREFIX,
37                      (unsigned long) ( uid >> 32 ),
38                      (unsigned long) ( uid & 0xffffffff ),
39                      PSA_ITS_STORAGE_SUFFIX );
40}
41
42/* Maximum uid used by the test, recorded so that cleanup() can delete
43 * all files. 0xffffffffffffffff is always cleaned up, so it does not
44 * need to and should not be taken into account for uid_max. */
45static psa_storage_uid_t uid_max = 0;
46
47static void cleanup( void )
48{
49    /* Call remove() on all the files that a test might have created.
50     * We ignore the error if the file exists but remove() fails because
51     * it can't be checked portably (except by attempting to open the file
52     * first, which is needlessly slow and complicated here). A failure of
53     * remove() on an existing file is very unlikely anyway and would not
54     * have significant consequences other than perhaps failing the next
55     * test case. */
56    char filename[PSA_ITS_STORAGE_FILENAME_LENGTH];
57    psa_storage_uid_t uid;
58    for( uid = 0; uid < uid_max; uid++ )
59    {
60        psa_its_fill_filename( uid, filename );
61        (void) remove( filename );
62    }
63    psa_its_fill_filename( (psa_storage_uid_t)( -1 ), filename );
64    (void) remove( filename );
65    (void) remove( PSA_ITS_STORAGE_TEMP );
66    uid_max = 0;
67}
68
69static psa_status_t psa_its_set_wrap( psa_storage_uid_t uid,
70                                      uint32_t data_length,
71                                      const void *p_data,
72                                      psa_storage_create_flags_t create_flags )
73{
74    if( uid_max != (psa_storage_uid_t)( -1 ) && uid_max < uid )
75        uid_max = uid;
76    return( psa_its_set( uid, data_length, p_data, create_flags ) );
77}
78
79/* END_HEADER */
80
81/* BEGIN_DEPENDENCIES
82 * depends_on:MBEDTLS_PSA_ITS_FILE_C
83 * END_DEPENDENCIES
84 */
85
86/* BEGIN_CASE */
87void set_get_remove( int uid_arg, int flags_arg, data_t *data )
88{
89    psa_storage_uid_t uid = uid_arg;
90    uint32_t flags = flags_arg;
91    struct psa_storage_info_t info;
92    unsigned char *buffer = NULL;
93    size_t ret_len = 0;
94
95    ASSERT_ALLOC( buffer, data->len );
96
97    PSA_ASSERT( psa_its_set_wrap( uid, data->len, data->x, flags ) );
98
99    PSA_ASSERT( psa_its_get_info( uid, &info ) );
100    TEST_ASSERT( info.size == data->len );
101    TEST_ASSERT( info.flags == flags );
102    PSA_ASSERT( psa_its_get( uid, 0, data->len, buffer, &ret_len ) );
103    ASSERT_COMPARE( data->x, data->len, buffer, ret_len );
104
105    PSA_ASSERT( psa_its_remove( uid ) );
106
107exit:
108    mbedtls_free( buffer );
109    cleanup( );
110}
111/* END_CASE */
112
113/* BEGIN_CASE */
114void set_overwrite( int uid_arg,
115                    int flags1_arg, data_t *data1,
116                    int flags2_arg, data_t *data2 )
117{
118    psa_storage_uid_t uid = uid_arg;
119    uint32_t flags1 = flags1_arg;
120    uint32_t flags2 = flags2_arg;
121    struct psa_storage_info_t info;
122    unsigned char *buffer = NULL;
123    size_t ret_len = 0;
124
125    ASSERT_ALLOC( buffer, MAX( data1->len, data2->len ) );
126
127    PSA_ASSERT( psa_its_set_wrap( uid, data1->len, data1->x, flags1 ) );
128    PSA_ASSERT( psa_its_get_info( uid, &info ) );
129    TEST_ASSERT( info.size == data1->len );
130    TEST_ASSERT( info.flags == flags1 );
131    PSA_ASSERT( psa_its_get( uid, 0, data1->len, buffer, &ret_len ) );
132    ASSERT_COMPARE( data1->x, data1->len, buffer, ret_len );
133
134    PSA_ASSERT( psa_its_set_wrap( uid, data2->len, data2->x, flags2 ) );
135    PSA_ASSERT( psa_its_get_info( uid, &info ) );
136    TEST_ASSERT( info.size == data2->len );
137    TEST_ASSERT( info.flags == flags2 );
138    ret_len = 0;
139    PSA_ASSERT( psa_its_get( uid, 0, data2->len, buffer, &ret_len ) );
140    ASSERT_COMPARE( data2->x, data2->len, buffer, ret_len );
141
142    PSA_ASSERT( psa_its_remove( uid ) );
143
144exit:
145    mbedtls_free( buffer );
146    cleanup( );
147}
148/* END_CASE */
149
150/* BEGIN_CASE */
151void set_multiple( int first_id, int count )
152{
153    psa_storage_uid_t uid0 = first_id;
154    psa_storage_uid_t uid;
155    char stored[40];
156    char retrieved[40];
157    size_t ret_len = 0;
158
159    memset( stored, '.', sizeof( stored ) );
160    for( uid = uid0; uid < uid0 + count; uid++ )
161    {
162        mbedtls_snprintf( stored, sizeof( stored ),
163                          "Content of file 0x%08lx", (unsigned long) uid );
164        PSA_ASSERT( psa_its_set_wrap( uid, sizeof( stored ), stored, 0 ) );
165    }
166
167    for( uid = uid0; uid < uid0 + count; uid++ )
168    {
169        mbedtls_snprintf( stored, sizeof( stored ),
170                          "Content of file 0x%08lx", (unsigned long) uid );
171        PSA_ASSERT( psa_its_get( uid, 0, sizeof( stored ), retrieved, &ret_len ) );
172        ASSERT_COMPARE( retrieved, ret_len,
173                        stored, sizeof( stored ) );
174        PSA_ASSERT( psa_its_remove( uid ) );
175        TEST_ASSERT( psa_its_get( uid, 0, 0, NULL, NULL ) ==
176                     PSA_ERROR_DOES_NOT_EXIST );
177    }
178
179exit:
180    cleanup( );
181}
182/* END_CASE */
183
184/* BEGIN_CASE */
185void nonexistent( int uid_arg, int create_and_remove )
186{
187    psa_storage_uid_t uid = uid_arg;
188    struct psa_storage_info_t info;
189
190    if( create_and_remove )
191    {
192        PSA_ASSERT( psa_its_set_wrap( uid, 0, NULL, 0 ) );
193        PSA_ASSERT( psa_its_remove( uid ) );
194    }
195
196    TEST_ASSERT( psa_its_remove( uid ) == PSA_ERROR_DOES_NOT_EXIST );
197    TEST_ASSERT( psa_its_get_info( uid, &info ) ==
198                 PSA_ERROR_DOES_NOT_EXIST );
199    TEST_ASSERT( psa_its_get( uid, 0, 0, NULL, NULL ) ==
200                 PSA_ERROR_DOES_NOT_EXIST );
201
202exit:
203    cleanup( );
204}
205/* END_CASE */
206
207/* BEGIN_CASE */
208void get_at( int uid_arg, data_t *data,
209             int offset, int length_arg,
210             int expected_status )
211{
212    psa_storage_uid_t uid = uid_arg;
213    unsigned char *buffer = NULL;
214    psa_status_t status;
215    size_t length = length_arg >= 0 ? length_arg : 0;
216    unsigned char *trailer;
217    size_t i;
218    size_t ret_len = 0;
219
220    ASSERT_ALLOC( buffer, length + 16 );
221    trailer = buffer + length;
222    memset( trailer, '-', 16 );
223
224    PSA_ASSERT( psa_its_set_wrap( uid, data->len, data->x, 0 ) );
225
226    status = psa_its_get( uid, offset, length_arg, buffer, &ret_len );
227    TEST_ASSERT( status == (psa_status_t) expected_status );
228    if( status == PSA_SUCCESS )
229        ASSERT_COMPARE( data->x + offset, (size_t) length_arg,
230                        buffer, ret_len );
231    for( i = 0; i < 16; i++ )
232        TEST_ASSERT( trailer[i] == '-' );
233    PSA_ASSERT( psa_its_remove( uid ) );
234
235exit:
236    mbedtls_free( buffer );
237    cleanup( );
238}
239/* END_CASE */
240
241/* BEGIN_CASE */
242void get_fail( int uid_arg, data_t *data,
243               int overwrite_magic, int cut_header,
244               int expected_status )
245{
246    psa_storage_uid_t uid = uid_arg;
247    unsigned char *buffer = NULL;
248    psa_status_t status;
249    size_t n;
250    size_t ret_len = 0;
251    char filename[PSA_ITS_STORAGE_FILENAME_LENGTH];
252    FILE *stream = NULL;
253    char bad_char = 'X';
254
255    PSA_ASSERT( psa_its_set_wrap( uid, data->len, data->x, 0 ) );
256
257    psa_its_fill_filename( uid, filename );
258    stream = fopen( filename, "rb+" );
259    TEST_ASSERT( NULL != stream );
260    if( 0 != overwrite_magic )
261    {
262        /* Overwrite the 1st byte of the file, the ITS magic number */
263        TEST_ASSERT( fseek( stream, 0, SEEK_SET ) == 0 );
264        n = fwrite( &bad_char, 1, 1, stream );
265        TEST_ASSERT( 1 == n );
266    }
267    if( 0 != cut_header )
268    {
269        /* Reopen file and truncate it to 0 byte by specifying the 'w' flag */
270        stream = freopen( filename, "wb", stream );
271        TEST_ASSERT( NULL != stream );
272    }
273    fclose( stream );
274    stream = NULL;
275
276    status = psa_its_get( uid, 0, 0, buffer, &ret_len );
277    TEST_ASSERT( status == (psa_status_t) expected_status );
278    TEST_ASSERT( 0 == ret_len );
279    PSA_ASSERT( psa_its_remove( uid ) );
280
281    /* Check if the file is really deleted. */
282    stream = fopen( filename, "rb" );
283    TEST_ASSERT( NULL == stream );
284
285exit:
286    if( stream != NULL )
287        fclose( stream );
288
289    mbedtls_free( buffer );
290    cleanup( );
291}
292/* END_CASE */
293
294/* BEGIN_CASE */
295void set_fail( int uid_arg, data_t *data,
296               int expected_status )
297{
298    psa_storage_uid_t uid = uid_arg;
299    TEST_ASSERT( psa_its_set_wrap( uid, data->len, data->x, 0 ) ==
300                 (psa_status_t) expected_status );
301
302    exit:
303    cleanup( );
304}
305/* END_CASE */
306