blob: 8af3d081fd3b38213dbb8f6015b8d4a1a448b0e4 [file] [log] [blame]
Darryl Greendb2b8db2018-06-15 13:06:04 +01001/*
2 * PSA persistent key storage
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_C)
29
30#include <stdlib.h>
31#include <string.h>
32
itayzafrir7723ab12019-02-14 10:28:02 +020033#include "psa_crypto_service_integration.h"
Darryl Greendb2b8db2018-06-15 13:06:04 +010034#include "psa/crypto.h"
35#include "psa_crypto_storage.h"
36#include "psa_crypto_storage_backend.h"
37#include "mbedtls/platform_util.h"
38
39#if defined(MBEDTLS_PLATFORM_C)
40#include "mbedtls/platform.h"
41#else
Jaeden Amerodb29ab52019-02-12 16:40:27 +000042#include <stdlib.h>
Darryl Greendb2b8db2018-06-15 13:06:04 +010043#define mbedtls_calloc calloc
44#define mbedtls_free free
45#endif
46
Gilles Peskine088b77f2019-02-24 17:00:27 +010047#if defined(MBEDTLS_PSA_ITS_FILE_C)
48#include "psa_crypto_its.h"
49#else /* Native ITS implementation */
50#include "psa/error.h"
51#include "psa_crypto_service_integration.h"
52#include "psa/internal_trusted_storage.h"
53#endif
54
55/* Determine a file name (ITS file identifier) for the given key file
56 * identifier. The file name must be distinct from any file that is used
57 * for a purpose other than storing a key. Currently, the only such file
58 * is the random seed file whose name is PSA_CRYPTO_ITS_RANDOM_SEED_UID
59 * and whose value is 0xFFFFFF52. */
60static psa_storage_uid_t psa_its_identifier_of_slot( psa_key_file_id_t file_id )
61{
62#if defined(MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER) && \
63 defined(PSA_CRYPTO_SECURE)
64 /* Encode the owner in the upper 32 bits. This means that if
65 * owner values are nonzero (as they are on a PSA platform),
66 * no key file will ever have a value less than 0x100000000, so
67 * the whole range 0..0xffffffff is available for non-key files. */
68 uint32_t unsigned_owner = (uint32_t) file_id.owner;
69 return( (uint64_t) unsigned_owner << 32 | file_id.key_id );
70#else
71 /* Use the key id directly as a file name.
72 * psa_is_key_file_id_valid() in psa_crypto_slot_management.c
73 * is responsible for ensuring that key identifiers do not have a
74 * value that is reserved for non-key files. */
75 return( file_id );
76#endif
77}
78
79psa_status_t psa_crypto_storage_load( const psa_key_file_id_t key, uint8_t *data,
80 size_t data_size )
81{
82 psa_status_t status;
83 psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key );
84 struct psa_storage_info_t data_identifier_info;
85
86 status = psa_its_get_info( data_identifier, &data_identifier_info );
87 if( status != PSA_SUCCESS )
88 return( status );
89
90 status = psa_its_get( data_identifier, 0, data_size, data );
91
92 return( status );
93}
94
95int psa_is_key_present_in_storage( const psa_key_file_id_t key )
96{
97 psa_status_t ret;
98 psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key );
99 struct psa_storage_info_t data_identifier_info;
100
101 ret = psa_its_get_info( data_identifier, &data_identifier_info );
102
103 if( ret == PSA_ERROR_DOES_NOT_EXIST )
104 return( 0 );
105 return( 1 );
106}
107
108psa_status_t psa_crypto_storage_store( const psa_key_file_id_t key,
109 const uint8_t *data,
110 size_t data_length )
111{
112 psa_status_t status;
113 psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key );
114 struct psa_storage_info_t data_identifier_info;
115
116 if( psa_is_key_present_in_storage( key ) == 1 )
117 return( PSA_ERROR_ALREADY_EXISTS );
118
119 status = psa_its_set( data_identifier, data_length, data, 0 );
120 if( status != PSA_SUCCESS )
121 {
122 return( PSA_ERROR_STORAGE_FAILURE );
123 }
124
125 status = psa_its_get_info( data_identifier, &data_identifier_info );
126 if( status != PSA_SUCCESS )
127 {
128 goto exit;
129 }
130
131 if( data_identifier_info.size != data_length )
132 {
133 status = PSA_ERROR_STORAGE_FAILURE;
134 goto exit;
135 }
136
137exit:
138 if( status != PSA_SUCCESS )
139 psa_its_remove( data_identifier );
140 return( status );
141}
142
143psa_status_t psa_destroy_persistent_key( const psa_key_file_id_t key )
144{
145 psa_status_t ret;
146 psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key );
147 struct psa_storage_info_t data_identifier_info;
148
149 ret = psa_its_get_info( data_identifier, &data_identifier_info );
150 if( ret == PSA_ERROR_DOES_NOT_EXIST )
151 return( PSA_SUCCESS );
152
153 if( psa_its_remove( data_identifier ) != PSA_SUCCESS )
154 return( PSA_ERROR_STORAGE_FAILURE );
155
156 ret = psa_its_get_info( data_identifier, &data_identifier_info );
157 if( ret != PSA_ERROR_DOES_NOT_EXIST )
158 return( PSA_ERROR_STORAGE_FAILURE );
159
160 return( PSA_SUCCESS );
161}
162
163psa_status_t psa_crypto_storage_get_data_length( const psa_key_file_id_t key,
164 size_t *data_length )
165{
166 psa_status_t status;
167 psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key );
168 struct psa_storage_info_t data_identifier_info;
169
170 status = psa_its_get_info( data_identifier, &data_identifier_info );
171 if( status != PSA_SUCCESS )
172 return( status );
173
174 *data_length = (size_t) data_identifier_info.size;
175
176 return( PSA_SUCCESS );
177}
178
Darryl Greendb2b8db2018-06-15 13:06:04 +0100179/*
180 * 32-bit integer manipulation macros (little endian)
181 */
182#ifndef GET_UINT32_LE
183#define GET_UINT32_LE(n,b,i) \
184{ \
185 (n) = ( (uint32_t) (b)[(i) ] ) \
186 | ( (uint32_t) (b)[(i) + 1] << 8 ) \
187 | ( (uint32_t) (b)[(i) + 2] << 16 ) \
188 | ( (uint32_t) (b)[(i) + 3] << 24 ); \
189}
190#endif
191
192#ifndef PUT_UINT32_LE
193#define PUT_UINT32_LE(n,b,i) \
194{ \
195 (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
196 (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
197 (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
198 (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
199}
200#endif
201
Moran Peker96ebf9e2018-06-28 18:02:17 +0300202/**
203 * Persistent key storage magic header.
204 */
205#define PSA_KEY_STORAGE_MAGIC_HEADER "PSA\0KEY"
206#define PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH ( sizeof( PSA_KEY_STORAGE_MAGIC_HEADER ) )
207
Darryl Greendb2b8db2018-06-15 13:06:04 +0100208typedef struct {
Moran Peker96ebf9e2018-06-28 18:02:17 +0300209 uint8_t magic[PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH];
Darryl Greendb2b8db2018-06-15 13:06:04 +0100210 uint8_t version[4];
211 uint8_t type[sizeof( psa_key_type_t )];
212 uint8_t policy[sizeof( psa_key_policy_t )];
213 uint8_t data_len[4];
214 uint8_t key_data[];
215} psa_persistent_key_storage_format;
216
217void psa_format_key_data_for_storage( const uint8_t *data,
218 const size_t data_length,
219 const psa_key_type_t type,
220 const psa_key_policy_t *policy,
221 uint8_t *storage_data )
222{
223 psa_persistent_key_storage_format *storage_format =
224 (psa_persistent_key_storage_format *) storage_data;
225
Moran Peker96ebf9e2018-06-28 18:02:17 +0300226 memcpy( storage_format->magic, PSA_KEY_STORAGE_MAGIC_HEADER, PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH );
Darryl Greendb2b8db2018-06-15 13:06:04 +0100227 PUT_UINT32_LE(0, storage_format->version, 0);
228 PUT_UINT32_LE(type, storage_format->type, 0);
229 PUT_UINT32_LE(policy->usage, storage_format->policy, 0);
230 PUT_UINT32_LE(policy->alg, storage_format->policy, sizeof( uint32_t ));
231 PUT_UINT32_LE(data_length, storage_format->data_len, 0);
232 memcpy( storage_format->key_data, data, data_length );
233}
234
Moran Peker96ebf9e2018-06-28 18:02:17 +0300235static psa_status_t check_magic_header( const uint8_t *data )
236{
237 if( memcmp( data, PSA_KEY_STORAGE_MAGIC_HEADER,
238 PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH ) != 0 )
239 return( PSA_ERROR_STORAGE_FAILURE );
240 return( PSA_SUCCESS );
241}
242
Darryl Greendb2b8db2018-06-15 13:06:04 +0100243psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data,
244 size_t storage_data_length,
245 uint8_t **key_data,
246 size_t *key_data_length,
247 psa_key_type_t *type,
248 psa_key_policy_t *policy )
249{
Moran Peker96ebf9e2018-06-28 18:02:17 +0300250 psa_status_t status;
Darryl Greendb2b8db2018-06-15 13:06:04 +0100251 const psa_persistent_key_storage_format *storage_format =
252 (const psa_persistent_key_storage_format *)storage_data;
253 uint32_t version;
254
Moran Peker96ebf9e2018-06-28 18:02:17 +0300255 if( storage_data_length < sizeof(*storage_format) )
256 return( PSA_ERROR_STORAGE_FAILURE );
257
258 status = check_magic_header( storage_data );
259 if( status != PSA_SUCCESS )
260 return( status );
261
Darryl Greendb2b8db2018-06-15 13:06:04 +0100262 GET_UINT32_LE(version, storage_format->version, 0);
263 if( version != 0 )
264 return( PSA_ERROR_STORAGE_FAILURE );
265
266 GET_UINT32_LE(*key_data_length, storage_format->data_len, 0);
267 if( *key_data_length > ( storage_data_length - sizeof(*storage_format) ) ||
268 *key_data_length > PSA_CRYPTO_MAX_STORAGE_SIZE )
269 return( PSA_ERROR_STORAGE_FAILURE );
270
271 *key_data = mbedtls_calloc( 1, *key_data_length );
272 if( *key_data == NULL )
273 return( PSA_ERROR_INSUFFICIENT_MEMORY );
274
275 GET_UINT32_LE(*type, storage_format->type, 0);
276 GET_UINT32_LE(policy->usage, storage_format->policy, 0);
277 GET_UINT32_LE(policy->alg, storage_format->policy, sizeof( uint32_t ));
278
279 memcpy( *key_data, storage_format->key_data, *key_data_length );
280
281 return( PSA_SUCCESS );
282}
283
Gilles Peskine5b229a02019-02-19 13:24:37 +0100284psa_status_t psa_save_persistent_key( const psa_key_file_id_t key,
Darryl Greendb2b8db2018-06-15 13:06:04 +0100285 const psa_key_type_t type,
286 const psa_key_policy_t *policy,
287 const uint8_t *data,
288 const size_t data_length )
289{
290 size_t storage_data_length;
291 uint8_t *storage_data;
292 psa_status_t status;
293
294 if( data_length > PSA_CRYPTO_MAX_STORAGE_SIZE )
295 return PSA_ERROR_INSUFFICIENT_STORAGE;
296 storage_data_length = data_length + sizeof( psa_persistent_key_storage_format );
297
298 storage_data = mbedtls_calloc( 1, storage_data_length );
299 if( storage_data == NULL )
300 return( PSA_ERROR_INSUFFICIENT_MEMORY );
301
302 psa_format_key_data_for_storage( data, data_length, type, policy,
303 storage_data );
304
305 status = psa_crypto_storage_store( key,
306 storage_data, storage_data_length );
307
308 mbedtls_free( storage_data );
309
310 return( status );
311}
312
313void psa_free_persistent_key_data( uint8_t *key_data, size_t key_data_length )
314{
315 if( key_data != NULL )
316 {
317 mbedtls_platform_zeroize( key_data, key_data_length );
318 }
319 mbedtls_free( key_data );
320}
321
Gilles Peskine5b229a02019-02-19 13:24:37 +0100322psa_status_t psa_load_persistent_key( psa_key_file_id_t key,
Darryl Greendb2b8db2018-06-15 13:06:04 +0100323 psa_key_type_t *type,
324 psa_key_policy_t *policy,
325 uint8_t **data,
326 size_t *data_length )
327{
328 psa_status_t status = PSA_SUCCESS;
329 uint8_t *loaded_data;
330 size_t storage_data_length = 0;
331
332 status = psa_crypto_storage_get_data_length( key, &storage_data_length );
333 if( status != PSA_SUCCESS )
334 return( status );
335
336 loaded_data = mbedtls_calloc( 1, storage_data_length );
337
338 if( loaded_data == NULL )
339 return( PSA_ERROR_INSUFFICIENT_MEMORY );
340
341 status = psa_crypto_storage_load( key, loaded_data, storage_data_length );
342 if( status != PSA_SUCCESS )
343 goto exit;
344
345 status = psa_parse_key_data_from_storage( loaded_data, storage_data_length,
346 data, data_length, type, policy );
347
348exit:
349 mbedtls_free( loaded_data );
350 return( status );
351}
352
353#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */