blob: 87420be98a58e826cb9fe0169e2c6aa5c8815cda [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,
Gilles Peskinea23eafc2018-12-03 16:48:14 +010056 CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_%lu",
57 (unsigned long) key );
Darryl Greendb2b8db2018-06-15 13:06:04 +010058}
59
Gilles Peskine8d4919b2018-12-03 16:48:09 +010060psa_status_t psa_crypto_storage_load( const psa_key_id_t key, uint8_t *data,
Darryl Greendb2b8db2018-06-15 13:06:04 +010061 size_t data_size )
62{
63 psa_status_t status = PSA_SUCCESS;
64 FILE *file;
65 size_t num_read;
66 char slot_location[MAX_LOCATION_LEN];
67
Gilles Peskine8d4919b2018-12-03 16:48:09 +010068 key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
Darryl Greendb2b8db2018-06-15 13:06:04 +010069 file = fopen( slot_location, "rb" );
70 if( file == NULL )
71 {
72 status = PSA_ERROR_STORAGE_FAILURE;
73 goto exit;
74 }
75 num_read = fread( data, 1, data_size, file );
76 if( num_read != data_size )
77 status = PSA_ERROR_STORAGE_FAILURE;
78
79exit:
80 if( file != NULL )
81 fclose( file );
82 return( status );
83}
84
Gilles Peskine8d4919b2018-12-03 16:48:09 +010085int psa_is_key_present_in_storage( const psa_key_id_t key )
Darryl Greendb2b8db2018-06-15 13:06:04 +010086{
87 char slot_location[MAX_LOCATION_LEN];
88 FILE *file;
89
Gilles Peskine8d4919b2018-12-03 16:48:09 +010090 key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
Darryl Greendb2b8db2018-06-15 13:06:04 +010091
92 file = fopen( slot_location, "r" );
93 if( file == NULL )
94 {
95 /* File doesn't exist */
96 return( 0 );
97 }
98
99 fclose( file );
100 return( 1 );
101}
102
Gilles Peskine8d4919b2018-12-03 16:48:09 +0100103psa_status_t psa_crypto_storage_store( const psa_key_id_t key,
Darryl Greendb2b8db2018-06-15 13:06:04 +0100104 const uint8_t *data,
105 size_t data_length )
106{
107 psa_status_t status = PSA_SUCCESS;
108 int ret;
109 size_t num_written;
110 char slot_location[MAX_LOCATION_LEN];
111 FILE *file;
112 /* The storage location corresponding to "key slot 0" is used as a
113 * temporary location in order to make the apparition of the actual slot
114 * file atomic. 0 is not a valid key slot number, so this should not
115 * affect actual keys. */
116 const char *temp_location = CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_0";
117
Gilles Peskine8d4919b2018-12-03 16:48:09 +0100118 key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
Darryl Greendb2b8db2018-06-15 13:06:04 +0100119
120 if( psa_is_key_present_in_storage( key ) == 1 )
121 return( PSA_ERROR_OCCUPIED_SLOT );
122
123 file = fopen( temp_location, "wb" );
124 if( file == NULL )
125 {
126 status = PSA_ERROR_STORAGE_FAILURE;
127 goto exit;
128 }
129
130 num_written = fwrite( data, 1, data_length, file );
131 if( num_written != data_length )
132 {
133 status = PSA_ERROR_STORAGE_FAILURE;
134 goto exit;
135 }
136
137 ret = fclose( file );
138 file = NULL;
139 if( ret != 0 )
140 {
141 status = PSA_ERROR_STORAGE_FAILURE;
142 goto exit;
143 }
144
145 if( rename( temp_location, slot_location ) != 0 )
146 {
147 status = PSA_ERROR_STORAGE_FAILURE;
148 goto exit;
149 }
150
151exit:
152 if( file != NULL )
153 fclose( file );
154 remove( temp_location );
155 return( status );
156}
157
Gilles Peskine8d4919b2018-12-03 16:48:09 +0100158psa_status_t psa_destroy_persistent_key( const psa_key_id_t key )
Darryl Greendb2b8db2018-06-15 13:06:04 +0100159{
160 FILE *file;
161 char slot_location[MAX_LOCATION_LEN];
162
Gilles Peskine8d4919b2018-12-03 16:48:09 +0100163 key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
Darryl Greendb2b8db2018-06-15 13:06:04 +0100164
165 /* Only try remove the file if it exists */
166 file = fopen( slot_location, "rb" );
167 if( file != NULL )
168 {
169 fclose( file );
170
171 if( remove( slot_location ) != 0 )
172 return( PSA_ERROR_STORAGE_FAILURE );
173 }
174 return( PSA_SUCCESS );
175}
176
Gilles Peskine8d4919b2018-12-03 16:48:09 +0100177psa_status_t psa_crypto_storage_get_data_length( const psa_key_id_t key,
Darryl Greendb2b8db2018-06-15 13:06:04 +0100178 size_t *data_length )
179{
180 psa_status_t status = PSA_SUCCESS;
181 FILE *file;
182 long file_size;
183 char slot_location[MAX_LOCATION_LEN];
184
Gilles Peskine8d4919b2018-12-03 16:48:09 +0100185 key_id_to_location( key, slot_location, MAX_LOCATION_LEN );
Darryl Greendb2b8db2018-06-15 13:06:04 +0100186
187 file = fopen( slot_location, "rb" );
188 if( file == NULL )
189 return( PSA_ERROR_EMPTY_SLOT );
190
191 if( fseek( file, 0, SEEK_END ) != 0 )
192 {
193 status = PSA_ERROR_STORAGE_FAILURE;
194 goto exit;
195 }
196
197 file_size = ftell( file );
198
199 if( file_size < 0 )
200 {
201 status = PSA_ERROR_STORAGE_FAILURE;
202 goto exit;
203 }
204
205#if LONG_MAX > SIZE_MAX
206 if( (unsigned long) file_size > SIZE_MAX )
207 {
208 status = PSA_ERROR_STORAGE_FAILURE;
209 goto exit;
210 }
211#endif
212 *data_length = (size_t) file_size;
213
214exit:
215 fclose( file );
216 return( status );
217}
218
219#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_FILE_C */