blob: d7c33624e2539453bcee56b88529e8043718a35f [file] [log] [blame]
Darryl Greendb2b8db2018-06-15 13:06:04 +01001/*
2 * PSA file storage backend for persistent keys
3 */
4/* Copyright (C) 2018, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * This file is part of mbed TLS (https://tls.mbed.org)
20 */
21
22#if defined(MBEDTLS_CONFIG_FILE)
23#include MBEDTLS_CONFIG_FILE
24#else
25#include "mbedtls/config.h"
26#endif
27
28#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_FILE_C)
29
30#include <string.h>
31
32#include "psa/crypto.h"
33#include "psa_crypto_storage_backend.h"
34#include "mbedtls/platform_util.h"
35
36#if defined(MBEDTLS_PLATFORM_C)
37#include "mbedtls/platform.h"
38#else
Jaeden Amerodb29ab52019-02-12 16:40:27 +000039#include <stdio.h>
Darryl Greendb2b8db2018-06-15 13:06:04 +010040#define mbedtls_snprintf snprintf
41#endif
42
43/* This option sets where files are to be stored. If this is left unset,
44 * the files by default will be stored in the same location as the program,
45 * which may not be desired or possible. */
46#if !defined(CRYPTO_STORAGE_FILE_LOCATION)
47#define CRYPTO_STORAGE_FILE_LOCATION ""
48#endif
49
50enum { MAX_LOCATION_LEN = sizeof(CRYPTO_STORAGE_FILE_LOCATION) + 40 };
51
Gilles Peskine8d4919b2018-12-03 16:48:09 +010052static void key_id_to_location( const psa_key_id_t key,
53 char *location,
54 size_t location_size )
Darryl Greendb2b8db2018-06-15 13:06:04 +010055{
56 mbedtls_snprintf( location, location_size,
Gilles Peskinea23eafc2018-12-03 16:48:14 +010057 CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_%lu",
58 (unsigned long) key );
Darryl Greendb2b8db2018-06-15 13:06:04 +010059}
60
Gilles Peskine8d4919b2018-12-03 16:48:09 +010061psa_status_t psa_crypto_storage_load( const psa_key_id_t key, uint8_t *data,
Darryl Greendb2b8db2018-06-15 13:06:04 +010062 size_t data_size )
63{
64 psa_status_t status = PSA_SUCCESS;
65 FILE *file;
66 size_t num_read;
67 char slot_location[MAX_LOCATION_LEN];
68
Gilles Peskine8d4919b2018-12-03 16:48:09 +010069 key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
Darryl Greendb2b8db2018-06-15 13:06:04 +010070 file = fopen( slot_location, "rb" );
71 if( file == NULL )
72 {
73 status = PSA_ERROR_STORAGE_FAILURE;
74 goto exit;
75 }
76 num_read = fread( data, 1, data_size, file );
77 if( num_read != data_size )
78 status = PSA_ERROR_STORAGE_FAILURE;
79
80exit:
81 if( file != NULL )
82 fclose( file );
83 return( status );
84}
85
Gilles Peskine8d4919b2018-12-03 16:48:09 +010086int psa_is_key_present_in_storage( const psa_key_id_t key )
Darryl Greendb2b8db2018-06-15 13:06:04 +010087{
88 char slot_location[MAX_LOCATION_LEN];
89 FILE *file;
90
Gilles Peskine8d4919b2018-12-03 16:48:09 +010091 key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
Darryl Greendb2b8db2018-06-15 13:06:04 +010092
93 file = fopen( slot_location, "r" );
94 if( file == NULL )
95 {
96 /* File doesn't exist */
97 return( 0 );
98 }
99
100 fclose( file );
101 return( 1 );
102}
103
Gilles Peskine8d4919b2018-12-03 16:48:09 +0100104psa_status_t psa_crypto_storage_store( const psa_key_id_t key,
Darryl Greendb2b8db2018-06-15 13:06:04 +0100105 const uint8_t *data,
106 size_t data_length )
107{
108 psa_status_t status = PSA_SUCCESS;
109 int ret;
110 size_t num_written;
111 char slot_location[MAX_LOCATION_LEN];
112 FILE *file;
113 /* The storage location corresponding to "key slot 0" is used as a
114 * temporary location in order to make the apparition of the actual slot
115 * file atomic. 0 is not a valid key slot number, so this should not
116 * affect actual keys. */
117 const char *temp_location = CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_0";
118
Gilles Peskine8d4919b2018-12-03 16:48:09 +0100119 key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
Darryl Greendb2b8db2018-06-15 13:06:04 +0100120
121 if( psa_is_key_present_in_storage( key ) == 1 )
122 return( PSA_ERROR_OCCUPIED_SLOT );
123
124 file = fopen( temp_location, "wb" );
125 if( file == NULL )
126 {
127 status = PSA_ERROR_STORAGE_FAILURE;
128 goto exit;
129 }
130
131 num_written = fwrite( data, 1, data_length, file );
132 if( num_written != data_length )
133 {
134 status = PSA_ERROR_STORAGE_FAILURE;
135 goto exit;
136 }
137
138 ret = fclose( file );
139 file = NULL;
140 if( ret != 0 )
141 {
142 status = PSA_ERROR_STORAGE_FAILURE;
143 goto exit;
144 }
145
146 if( rename( temp_location, slot_location ) != 0 )
147 {
148 status = PSA_ERROR_STORAGE_FAILURE;
149 goto exit;
150 }
151
152exit:
153 if( file != NULL )
154 fclose( file );
155 remove( temp_location );
156 return( status );
157}
158
Gilles Peskine8d4919b2018-12-03 16:48:09 +0100159psa_status_t psa_destroy_persistent_key( const psa_key_id_t key )
Darryl Greendb2b8db2018-06-15 13:06:04 +0100160{
161 FILE *file;
162 char slot_location[MAX_LOCATION_LEN];
163
Gilles Peskine8d4919b2018-12-03 16:48:09 +0100164 key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
Darryl Greendb2b8db2018-06-15 13:06:04 +0100165
166 /* Only try remove the file if it exists */
167 file = fopen( slot_location, "rb" );
168 if( file != NULL )
169 {
170 fclose( file );
171
172 if( remove( slot_location ) != 0 )
173 return( PSA_ERROR_STORAGE_FAILURE );
174 }
175 return( PSA_SUCCESS );
176}
177
Gilles Peskine8d4919b2018-12-03 16:48:09 +0100178psa_status_t psa_crypto_storage_get_data_length( const psa_key_id_t key,
Darryl Greendb2b8db2018-06-15 13:06:04 +0100179 size_t *data_length )
180{
181 psa_status_t status = PSA_SUCCESS;
182 FILE *file;
183 long file_size;
184 char slot_location[MAX_LOCATION_LEN];
185
Gilles Peskine8d4919b2018-12-03 16:48:09 +0100186 key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
Darryl Greendb2b8db2018-06-15 13:06:04 +0100187
188 file = fopen( slot_location, "rb" );
189 if( file == NULL )
190 return( PSA_ERROR_EMPTY_SLOT );
191
192 if( fseek( file, 0, SEEK_END ) != 0 )
193 {
194 status = PSA_ERROR_STORAGE_FAILURE;
195 goto exit;
196 }
197
198 file_size = ftell( file );
199
200 if( file_size < 0 )
201 {
202 status = PSA_ERROR_STORAGE_FAILURE;
203 goto exit;
204 }
205
206#if LONG_MAX > SIZE_MAX
207 if( (unsigned long) file_size > SIZE_MAX )
208 {
209 status = PSA_ERROR_STORAGE_FAILURE;
210 goto exit;
211 }
212#endif
213 *data_length = (size_t) file_size;
214
215exit:
216 fclose( file );
217 return( status );
218}
219
220#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_FILE_C */