2018-06-15 14:06:04 +02:00
|
|
|
/*
|
|
|
|
* PSA file storage backend for persistent keys
|
|
|
|
*/
|
|
|
|
/* Copyright (C) 2018, ARM Limited, All Rights Reserved
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
|
|
* not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*
|
|
|
|
* This file is part of mbed TLS (https://tls.mbed.org)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if defined(MBEDTLS_CONFIG_FILE)
|
|
|
|
#include MBEDTLS_CONFIG_FILE
|
|
|
|
#else
|
|
|
|
#include "mbedtls/config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_FILE_C)
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "psa/crypto.h"
|
|
|
|
#include "psa_crypto_storage_backend.h"
|
|
|
|
#include "mbedtls/platform_util.h"
|
|
|
|
|
|
|
|
#if defined(MBEDTLS_PLATFORM_C)
|
|
|
|
#include "mbedtls/platform.h"
|
|
|
|
#else
|
2019-02-12 17:40:27 +01:00
|
|
|
#include <stdio.h>
|
2018-06-15 14:06:04 +02:00
|
|
|
#define mbedtls_snprintf snprintf
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* This option sets where files are to be stored. If this is left unset,
|
|
|
|
* the files by default will be stored in the same location as the program,
|
|
|
|
* which may not be desired or possible. */
|
|
|
|
#if !defined(CRYPTO_STORAGE_FILE_LOCATION)
|
|
|
|
#define CRYPTO_STORAGE_FILE_LOCATION ""
|
|
|
|
#endif
|
|
|
|
|
|
|
|
enum { MAX_LOCATION_LEN = sizeof(CRYPTO_STORAGE_FILE_LOCATION) + 40 };
|
|
|
|
|
Support encoding an owner in key file IDs
Differentiate between _key identifiers_, which are always `uint32_t`,
and _key file identifiers_, which are platform-dependent. Normally,
the two are the same.
In `psa/crypto_platform.h`, define `psa_app_key_id_t` (which is always
32 bits, the standard key identifier type) and
`psa_key_file_id_t` (which will be different in some service builds).
A subsequent commit will introduce a platform where the two are different.
It would make sense for the function declarations in `psa/crypto.h` to
use `psa_key_file_id_t`. However this file is currently part of the
PSA Crypto API specification, so it must stick to the standard type
`psa_key_id_t`. Hence, as long as the specification and Mbed Crypto
are not separate, use the implementation-specific file
`psa/crypto_platform.h` to define `psa_key_id_t` as `psa_key_file_id_t`.
In the library, systematically use `psa_key_file_id_t`.
perl -i -pe 's/psa_key_id_t/psa_key_file_id_t/g' library/*.[hc]
2019-02-19 13:24:37 +01:00
|
|
|
static void key_id_to_location( const psa_key_file_id_t key,
|
2018-12-03 16:48:09 +01:00
|
|
|
char *location,
|
|
|
|
size_t location_size )
|
2018-06-15 14:06:04 +02:00
|
|
|
{
|
|
|
|
mbedtls_snprintf( location, location_size,
|
2018-12-03 16:48:14 +01:00
|
|
|
CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_%lu",
|
|
|
|
(unsigned long) key );
|
2018-06-15 14:06:04 +02:00
|
|
|
}
|
|
|
|
|
Support encoding an owner in key file IDs
Differentiate between _key identifiers_, which are always `uint32_t`,
and _key file identifiers_, which are platform-dependent. Normally,
the two are the same.
In `psa/crypto_platform.h`, define `psa_app_key_id_t` (which is always
32 bits, the standard key identifier type) and
`psa_key_file_id_t` (which will be different in some service builds).
A subsequent commit will introduce a platform where the two are different.
It would make sense for the function declarations in `psa/crypto.h` to
use `psa_key_file_id_t`. However this file is currently part of the
PSA Crypto API specification, so it must stick to the standard type
`psa_key_id_t`. Hence, as long as the specification and Mbed Crypto
are not separate, use the implementation-specific file
`psa/crypto_platform.h` to define `psa_key_id_t` as `psa_key_file_id_t`.
In the library, systematically use `psa_key_file_id_t`.
perl -i -pe 's/psa_key_id_t/psa_key_file_id_t/g' library/*.[hc]
2019-02-19 13:24:37 +01:00
|
|
|
psa_status_t psa_crypto_storage_load( const psa_key_file_id_t key, uint8_t *data,
|
2018-06-15 14:06:04 +02:00
|
|
|
size_t data_size )
|
|
|
|
{
|
|
|
|
psa_status_t status = PSA_SUCCESS;
|
|
|
|
FILE *file;
|
|
|
|
size_t num_read;
|
|
|
|
char slot_location[MAX_LOCATION_LEN];
|
|
|
|
|
2018-12-03 16:48:09 +01:00
|
|
|
key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
|
2018-06-15 14:06:04 +02:00
|
|
|
file = fopen( slot_location, "rb" );
|
|
|
|
if( file == NULL )
|
|
|
|
{
|
|
|
|
status = PSA_ERROR_STORAGE_FAILURE;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
num_read = fread( data, 1, data_size, file );
|
|
|
|
if( num_read != data_size )
|
|
|
|
status = PSA_ERROR_STORAGE_FAILURE;
|
|
|
|
|
|
|
|
exit:
|
|
|
|
if( file != NULL )
|
|
|
|
fclose( file );
|
|
|
|
return( status );
|
|
|
|
}
|
|
|
|
|
Support encoding an owner in key file IDs
Differentiate between _key identifiers_, which are always `uint32_t`,
and _key file identifiers_, which are platform-dependent. Normally,
the two are the same.
In `psa/crypto_platform.h`, define `psa_app_key_id_t` (which is always
32 bits, the standard key identifier type) and
`psa_key_file_id_t` (which will be different in some service builds).
A subsequent commit will introduce a platform where the two are different.
It would make sense for the function declarations in `psa/crypto.h` to
use `psa_key_file_id_t`. However this file is currently part of the
PSA Crypto API specification, so it must stick to the standard type
`psa_key_id_t`. Hence, as long as the specification and Mbed Crypto
are not separate, use the implementation-specific file
`psa/crypto_platform.h` to define `psa_key_id_t` as `psa_key_file_id_t`.
In the library, systematically use `psa_key_file_id_t`.
perl -i -pe 's/psa_key_id_t/psa_key_file_id_t/g' library/*.[hc]
2019-02-19 13:24:37 +01:00
|
|
|
int psa_is_key_present_in_storage( const psa_key_file_id_t key )
|
2018-06-15 14:06:04 +02:00
|
|
|
{
|
|
|
|
char slot_location[MAX_LOCATION_LEN];
|
|
|
|
FILE *file;
|
|
|
|
|
2018-12-03 16:48:09 +01:00
|
|
|
key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
|
2018-06-15 14:06:04 +02:00
|
|
|
|
|
|
|
file = fopen( slot_location, "r" );
|
|
|
|
if( file == NULL )
|
|
|
|
{
|
|
|
|
/* File doesn't exist */
|
|
|
|
return( 0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose( file );
|
|
|
|
return( 1 );
|
|
|
|
}
|
|
|
|
|
Support encoding an owner in key file IDs
Differentiate between _key identifiers_, which are always `uint32_t`,
and _key file identifiers_, which are platform-dependent. Normally,
the two are the same.
In `psa/crypto_platform.h`, define `psa_app_key_id_t` (which is always
32 bits, the standard key identifier type) and
`psa_key_file_id_t` (which will be different in some service builds).
A subsequent commit will introduce a platform where the two are different.
It would make sense for the function declarations in `psa/crypto.h` to
use `psa_key_file_id_t`. However this file is currently part of the
PSA Crypto API specification, so it must stick to the standard type
`psa_key_id_t`. Hence, as long as the specification and Mbed Crypto
are not separate, use the implementation-specific file
`psa/crypto_platform.h` to define `psa_key_id_t` as `psa_key_file_id_t`.
In the library, systematically use `psa_key_file_id_t`.
perl -i -pe 's/psa_key_id_t/psa_key_file_id_t/g' library/*.[hc]
2019-02-19 13:24:37 +01:00
|
|
|
psa_status_t psa_crypto_storage_store( const psa_key_file_id_t key,
|
2018-06-15 14:06:04 +02:00
|
|
|
const uint8_t *data,
|
|
|
|
size_t data_length )
|
|
|
|
{
|
|
|
|
psa_status_t status = PSA_SUCCESS;
|
|
|
|
int ret;
|
|
|
|
size_t num_written;
|
|
|
|
char slot_location[MAX_LOCATION_LEN];
|
|
|
|
FILE *file;
|
|
|
|
/* The storage location corresponding to "key slot 0" is used as a
|
|
|
|
* temporary location in order to make the apparition of the actual slot
|
|
|
|
* file atomic. 0 is not a valid key slot number, so this should not
|
|
|
|
* affect actual keys. */
|
|
|
|
const char *temp_location = CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_0";
|
|
|
|
|
2018-12-03 16:48:09 +01:00
|
|
|
key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
|
2018-06-15 14:06:04 +02:00
|
|
|
|
|
|
|
if( psa_is_key_present_in_storage( key ) == 1 )
|
2019-02-14 12:48:10 +01:00
|
|
|
return( PSA_ERROR_ALREADY_EXISTS );
|
2018-06-15 14:06:04 +02:00
|
|
|
|
|
|
|
file = fopen( temp_location, "wb" );
|
|
|
|
if( file == NULL )
|
|
|
|
{
|
|
|
|
status = PSA_ERROR_STORAGE_FAILURE;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
num_written = fwrite( data, 1, data_length, file );
|
|
|
|
if( num_written != data_length )
|
|
|
|
{
|
|
|
|
status = PSA_ERROR_STORAGE_FAILURE;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = fclose( file );
|
|
|
|
file = NULL;
|
|
|
|
if( ret != 0 )
|
|
|
|
{
|
|
|
|
status = PSA_ERROR_STORAGE_FAILURE;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( rename( temp_location, slot_location ) != 0 )
|
|
|
|
{
|
|
|
|
status = PSA_ERROR_STORAGE_FAILURE;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
exit:
|
|
|
|
if( file != NULL )
|
|
|
|
fclose( file );
|
|
|
|
remove( temp_location );
|
|
|
|
return( status );
|
|
|
|
}
|
|
|
|
|
Support encoding an owner in key file IDs
Differentiate between _key identifiers_, which are always `uint32_t`,
and _key file identifiers_, which are platform-dependent. Normally,
the two are the same.
In `psa/crypto_platform.h`, define `psa_app_key_id_t` (which is always
32 bits, the standard key identifier type) and
`psa_key_file_id_t` (which will be different in some service builds).
A subsequent commit will introduce a platform where the two are different.
It would make sense for the function declarations in `psa/crypto.h` to
use `psa_key_file_id_t`. However this file is currently part of the
PSA Crypto API specification, so it must stick to the standard type
`psa_key_id_t`. Hence, as long as the specification and Mbed Crypto
are not separate, use the implementation-specific file
`psa/crypto_platform.h` to define `psa_key_id_t` as `psa_key_file_id_t`.
In the library, systematically use `psa_key_file_id_t`.
perl -i -pe 's/psa_key_id_t/psa_key_file_id_t/g' library/*.[hc]
2019-02-19 13:24:37 +01:00
|
|
|
psa_status_t psa_destroy_persistent_key( const psa_key_file_id_t key )
|
2018-06-15 14:06:04 +02:00
|
|
|
{
|
|
|
|
FILE *file;
|
|
|
|
char slot_location[MAX_LOCATION_LEN];
|
|
|
|
|
2018-12-03 16:48:09 +01:00
|
|
|
key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
|
2018-06-15 14:06:04 +02:00
|
|
|
|
|
|
|
/* Only try remove the file if it exists */
|
|
|
|
file = fopen( slot_location, "rb" );
|
|
|
|
if( file != NULL )
|
|
|
|
{
|
|
|
|
fclose( file );
|
|
|
|
|
|
|
|
if( remove( slot_location ) != 0 )
|
|
|
|
return( PSA_ERROR_STORAGE_FAILURE );
|
|
|
|
}
|
|
|
|
return( PSA_SUCCESS );
|
|
|
|
}
|
|
|
|
|
Support encoding an owner in key file IDs
Differentiate between _key identifiers_, which are always `uint32_t`,
and _key file identifiers_, which are platform-dependent. Normally,
the two are the same.
In `psa/crypto_platform.h`, define `psa_app_key_id_t` (which is always
32 bits, the standard key identifier type) and
`psa_key_file_id_t` (which will be different in some service builds).
A subsequent commit will introduce a platform where the two are different.
It would make sense for the function declarations in `psa/crypto.h` to
use `psa_key_file_id_t`. However this file is currently part of the
PSA Crypto API specification, so it must stick to the standard type
`psa_key_id_t`. Hence, as long as the specification and Mbed Crypto
are not separate, use the implementation-specific file
`psa/crypto_platform.h` to define `psa_key_id_t` as `psa_key_file_id_t`.
In the library, systematically use `psa_key_file_id_t`.
perl -i -pe 's/psa_key_id_t/psa_key_file_id_t/g' library/*.[hc]
2019-02-19 13:24:37 +01:00
|
|
|
psa_status_t psa_crypto_storage_get_data_length( const psa_key_file_id_t key,
|
2018-06-15 14:06:04 +02:00
|
|
|
size_t *data_length )
|
|
|
|
{
|
|
|
|
psa_status_t status = PSA_SUCCESS;
|
|
|
|
FILE *file;
|
|
|
|
long file_size;
|
|
|
|
char slot_location[MAX_LOCATION_LEN];
|
|
|
|
|
2018-12-03 16:48:09 +01:00
|
|
|
key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
|
2018-06-15 14:06:04 +02:00
|
|
|
|
|
|
|
file = fopen( slot_location, "rb" );
|
|
|
|
if( file == NULL )
|
2019-02-14 12:48:10 +01:00
|
|
|
return( PSA_ERROR_DOES_NOT_EXIST );
|
2018-06-15 14:06:04 +02:00
|
|
|
|
|
|
|
if( fseek( file, 0, SEEK_END ) != 0 )
|
|
|
|
{
|
|
|
|
status = PSA_ERROR_STORAGE_FAILURE;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
file_size = ftell( file );
|
|
|
|
|
|
|
|
if( file_size < 0 )
|
|
|
|
{
|
|
|
|
status = PSA_ERROR_STORAGE_FAILURE;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if LONG_MAX > SIZE_MAX
|
|
|
|
if( (unsigned long) file_size > SIZE_MAX )
|
|
|
|
{
|
|
|
|
status = PSA_ERROR_STORAGE_FAILURE;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
*data_length = (size_t) file_size;
|
|
|
|
|
|
|
|
exit:
|
|
|
|
fclose( file );
|
|
|
|
return( status );
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_FILE_C */
|