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