blob: 95857fa406938e1f5ce7dce93f64ce7d77809400 [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
39#define mbedtls_snprintf snprintf
40#endif
41
42/* This option sets where files are to be stored. If this is left unset,
43 * the files by default will be stored in the same location as the program,
44 * which may not be desired or possible. */
45#if !defined(CRYPTO_STORAGE_FILE_LOCATION)
46#define CRYPTO_STORAGE_FILE_LOCATION ""
47#endif
48
49enum { MAX_LOCATION_LEN = sizeof(CRYPTO_STORAGE_FILE_LOCATION) + 40 };
50
Gilles Peskine8d4919b2018-12-03 16:48:09 +010051static void key_id_to_location( const psa_key_id_t key,
52 char *location,
53 size_t location_size )
Darryl Greendb2b8db2018-06-15 13:06:04 +010054{
55 mbedtls_snprintf( location, location_size,
56 CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_%d", key );
57}
58
Gilles Peskine8d4919b2018-12-03 16:48:09 +010059psa_status_t psa_crypto_storage_load( const psa_key_id_t key, uint8_t *data,
Darryl Greendb2b8db2018-06-15 13:06:04 +010060 size_t data_size )
61{
62 psa_status_t status = PSA_SUCCESS;
63 FILE *file;
64 size_t num_read;
65 char slot_location[MAX_LOCATION_LEN];
66
Gilles Peskine8d4919b2018-12-03 16:48:09 +010067 key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
Darryl Greendb2b8db2018-06-15 13:06:04 +010068 file = fopen( slot_location, "rb" );
69 if( file == NULL )
70 {
71 status = PSA_ERROR_STORAGE_FAILURE;
72 goto exit;
73 }
74 num_read = fread( data, 1, data_size, file );
75 if( num_read != data_size )
76 status = PSA_ERROR_STORAGE_FAILURE;
77
78exit:
79 if( file != NULL )
80 fclose( file );
81 return( status );
82}
83
Gilles Peskine8d4919b2018-12-03 16:48:09 +010084int psa_is_key_present_in_storage( const psa_key_id_t key )
Darryl Greendb2b8db2018-06-15 13:06:04 +010085{
86 char slot_location[MAX_LOCATION_LEN];
87 FILE *file;
88
Gilles Peskine8d4919b2018-12-03 16:48:09 +010089 key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
Darryl Greendb2b8db2018-06-15 13:06:04 +010090
91 file = fopen( slot_location, "r" );
92 if( file == NULL )
93 {
94 /* File doesn't exist */
95 return( 0 );
96 }
97
98 fclose( file );
99 return( 1 );
100}
101
Gilles Peskine8d4919b2018-12-03 16:48:09 +0100102psa_status_t psa_crypto_storage_store( const psa_key_id_t key,
Darryl Greendb2b8db2018-06-15 13:06:04 +0100103 const uint8_t *data,
104 size_t data_length )
105{
106 psa_status_t status = PSA_SUCCESS;
107 int ret;
108 size_t num_written;
109 char slot_location[MAX_LOCATION_LEN];
110 FILE *file;
111 /* The storage location corresponding to "key slot 0" is used as a
112 * temporary location in order to make the apparition of the actual slot
113 * file atomic. 0 is not a valid key slot number, so this should not
114 * affect actual keys. */
115 const char *temp_location = CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_0";
116
Gilles Peskine8d4919b2018-12-03 16:48:09 +0100117 key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
Darryl Greendb2b8db2018-06-15 13:06:04 +0100118
119 if( psa_is_key_present_in_storage( key ) == 1 )
120 return( PSA_ERROR_OCCUPIED_SLOT );
121
122 file = fopen( temp_location, "wb" );
123 if( file == NULL )
124 {
125 status = PSA_ERROR_STORAGE_FAILURE;
126 goto exit;
127 }
128
129 num_written = fwrite( data, 1, data_length, file );
130 if( num_written != data_length )
131 {
132 status = PSA_ERROR_STORAGE_FAILURE;
133 goto exit;
134 }
135
136 ret = fclose( file );
137 file = NULL;
138 if( ret != 0 )
139 {
140 status = PSA_ERROR_STORAGE_FAILURE;
141 goto exit;
142 }
143
144 if( rename( temp_location, slot_location ) != 0 )
145 {
146 status = PSA_ERROR_STORAGE_FAILURE;
147 goto exit;
148 }
149
150exit:
151 if( file != NULL )
152 fclose( file );
153 remove( temp_location );
154 return( status );
155}
156
Gilles Peskine8d4919b2018-12-03 16:48:09 +0100157psa_status_t psa_destroy_persistent_key( const psa_key_id_t key )
Darryl Greendb2b8db2018-06-15 13:06:04 +0100158{
159 FILE *file;
160 char slot_location[MAX_LOCATION_LEN];
161
Gilles Peskine8d4919b2018-12-03 16:48:09 +0100162 key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
Darryl Greendb2b8db2018-06-15 13:06:04 +0100163
164 /* Only try remove the file if it exists */
165 file = fopen( slot_location, "rb" );
166 if( file != NULL )
167 {
168 fclose( file );
169
170 if( remove( slot_location ) != 0 )
171 return( PSA_ERROR_STORAGE_FAILURE );
172 }
173 return( PSA_SUCCESS );
174}
175
Gilles Peskine8d4919b2018-12-03 16:48:09 +0100176psa_status_t psa_crypto_storage_get_data_length( const psa_key_id_t key,
Darryl Greendb2b8db2018-06-15 13:06:04 +0100177 size_t *data_length )
178{
179 psa_status_t status = PSA_SUCCESS;
180 FILE *file;
181 long file_size;
182 char slot_location[MAX_LOCATION_LEN];
183
Gilles Peskine8d4919b2018-12-03 16:48:09 +0100184 key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
Darryl Greendb2b8db2018-06-15 13:06:04 +0100185
186 file = fopen( slot_location, "rb" );
187 if( file == NULL )
188 return( PSA_ERROR_EMPTY_SLOT );
189
190 if( fseek( file, 0, SEEK_END ) != 0 )
191 {
192 status = PSA_ERROR_STORAGE_FAILURE;
193 goto exit;
194 }
195
196 file_size = ftell( file );
197
198 if( file_size < 0 )
199 {
200 status = PSA_ERROR_STORAGE_FAILURE;
201 goto exit;
202 }
203
204#if LONG_MAX > SIZE_MAX
205 if( (unsigned long) file_size > SIZE_MAX )
206 {
207 status = PSA_ERROR_STORAGE_FAILURE;
208 goto exit;
209 }
210#endif
211 *data_length = (size_t) file_size;
212
213exit:
214 fclose( file );
215 return( status );
216}
217
218#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_FILE_C */