blob: f12fe00348f97a79fe645b1c1ca3fa3438a45010 [file] [log] [blame]
Darryl Greendb2b8db2018-06-15 13:06:04 +01001/*
2 * PSA persistent key storage
3 */
Bence Szépkúti86974652020-06-15 11:59:37 +02004/*
5 * Copyright (C) 2018, ARM Limited, All Rights Reserved
Darryl Greendb2b8db2018-06-15 13:06:04 +01006 * SPDX-License-Identifier: Apache-2.0
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License"); you may
9 * not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 * This file is part of mbed TLS (https://tls.mbed.org)
21 */
22
23#if defined(MBEDTLS_CONFIG_FILE)
24#include MBEDTLS_CONFIG_FILE
25#else
26#include "mbedtls/config.h"
27#endif
28
29#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
30
31#include <stdlib.h>
32#include <string.h>
33
itayzafrir7723ab12019-02-14 10:28:02 +020034#include "psa_crypto_service_integration.h"
Darryl Greendb2b8db2018-06-15 13:06:04 +010035#include "psa/crypto.h"
36#include "psa_crypto_storage.h"
Darryl Greendb2b8db2018-06-15 13:06:04 +010037#include "mbedtls/platform_util.h"
38
Gilles Peskine5e80d912019-02-24 17:10:18 +010039#if defined(MBEDTLS_PSA_ITS_FILE_C)
40#include "psa_crypto_its.h"
41#else /* Native ITS implementation */
42#include "psa/error.h"
43#include "psa/internal_trusted_storage.h"
44#endif
45
Darryl Greendb2b8db2018-06-15 13:06:04 +010046#if defined(MBEDTLS_PLATFORM_C)
47#include "mbedtls/platform.h"
48#else
Jaeden Amerodb29ab52019-02-12 16:40:27 +000049#include <stdlib.h>
Darryl Greendb2b8db2018-06-15 13:06:04 +010050#define mbedtls_calloc calloc
51#define mbedtls_free free
52#endif
53
Gilles Peskinec8336cb2019-07-22 19:26:12 +020054
55
56/****************************************************************/
57/* Key storage */
58/****************************************************************/
59
Gilles Peskine088b77f2019-02-24 17:00:27 +010060/* Determine a file name (ITS file identifier) for the given key file
61 * identifier. The file name must be distinct from any file that is used
62 * for a purpose other than storing a key. Currently, the only such file
63 * is the random seed file whose name is PSA_CRYPTO_ITS_RANDOM_SEED_UID
64 * and whose value is 0xFFFFFF52. */
65static psa_storage_uid_t psa_its_identifier_of_slot( psa_key_file_id_t file_id )
66{
67#if defined(MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER) && \
68 defined(PSA_CRYPTO_SECURE)
69 /* Encode the owner in the upper 32 bits. This means that if
70 * owner values are nonzero (as they are on a PSA platform),
71 * no key file will ever have a value less than 0x100000000, so
72 * the whole range 0..0xffffffff is available for non-key files. */
73 uint32_t unsigned_owner = (uint32_t) file_id.owner;
74 return( (uint64_t) unsigned_owner << 32 | file_id.key_id );
75#else
76 /* Use the key id directly as a file name.
77 * psa_is_key_file_id_valid() in psa_crypto_slot_management.c
78 * is responsible for ensuring that key identifiers do not have a
79 * value that is reserved for non-key files. */
80 return( file_id );
81#endif
82}
83
Gilles Peskine5e80d912019-02-24 17:10:18 +010084/**
85 * \brief Load persistent data for the given key slot number.
86 *
87 * This function reads data from a storage backend and returns the data in a
88 * buffer.
89 *
90 * \param key Persistent identifier of the key to be loaded. This
91 * should be an occupied storage location.
92 * \param[out] data Buffer where the data is to be written.
93 * \param data_size Size of the \c data buffer in bytes.
94 *
95 * \retval PSA_SUCCESS
96 * \retval PSA_ERROR_STORAGE_FAILURE
97 * \retval PSA_ERROR_DOES_NOT_EXIST
98 */
99static psa_status_t psa_crypto_storage_load( const psa_key_file_id_t key,
100 uint8_t *data,
101 size_t data_size )
Gilles Peskine088b77f2019-02-24 17:00:27 +0100102{
103 psa_status_t status;
104 psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key );
105 struct psa_storage_info_t data_identifier_info;
Simon D Hughesbda5a212019-07-10 16:34:21 +0100106 size_t data_length = 0;
Gilles Peskine088b77f2019-02-24 17:00:27 +0100107
108 status = psa_its_get_info( data_identifier, &data_identifier_info );
109 if( status != PSA_SUCCESS )
110 return( status );
111
Simon D Hughesbda5a212019-07-10 16:34:21 +0100112 status = psa_its_get( data_identifier, 0, (uint32_t) data_size, data, &data_length );
113 if( data_size != data_length )
114 return( PSA_ERROR_STORAGE_FAILURE );
Gilles Peskine088b77f2019-02-24 17:00:27 +0100115
116 return( status );
117}
118
119int psa_is_key_present_in_storage( const psa_key_file_id_t key )
120{
121 psa_status_t ret;
122 psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key );
123 struct psa_storage_info_t data_identifier_info;
124
125 ret = psa_its_get_info( data_identifier, &data_identifier_info );
126
127 if( ret == PSA_ERROR_DOES_NOT_EXIST )
128 return( 0 );
129 return( 1 );
130}
131
Gilles Peskine5e80d912019-02-24 17:10:18 +0100132/**
133 * \brief Store persistent data for the given key slot number.
134 *
135 * This function stores the given data buffer to a persistent storage.
136 *
137 * \param key Persistent identifier of the key to be stored. This
138 * should be an unoccupied storage location.
139 * \param[in] data Buffer containing the data to be stored.
140 * \param data_length The number of bytes
141 * that make up the data.
142 *
143 * \retval PSA_SUCCESS
144 * \retval PSA_ERROR_INSUFFICIENT_STORAGE
145 * \retval PSA_ERROR_STORAGE_FAILURE
146 * \retval PSA_ERROR_ALREADY_EXISTS
147 */
148static psa_status_t psa_crypto_storage_store( const psa_key_file_id_t key,
149 const uint8_t *data,
150 size_t data_length )
Gilles Peskine088b77f2019-02-24 17:00:27 +0100151{
152 psa_status_t status;
153 psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key );
154 struct psa_storage_info_t data_identifier_info;
155
156 if( psa_is_key_present_in_storage( key ) == 1 )
157 return( PSA_ERROR_ALREADY_EXISTS );
158
Gilles Peskinefad3a3e2019-02-25 13:36:21 +0100159 status = psa_its_set( data_identifier, (uint32_t) data_length, data, 0 );
Gilles Peskine088b77f2019-02-24 17:00:27 +0100160 if( status != PSA_SUCCESS )
161 {
162 return( PSA_ERROR_STORAGE_FAILURE );
163 }
164
165 status = psa_its_get_info( data_identifier, &data_identifier_info );
166 if( status != PSA_SUCCESS )
167 {
168 goto exit;
169 }
170
171 if( data_identifier_info.size != data_length )
172 {
173 status = PSA_ERROR_STORAGE_FAILURE;
174 goto exit;
175 }
176
177exit:
178 if( status != PSA_SUCCESS )
179 psa_its_remove( data_identifier );
180 return( status );
181}
182
183psa_status_t psa_destroy_persistent_key( const psa_key_file_id_t key )
184{
185 psa_status_t ret;
186 psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key );
187 struct psa_storage_info_t data_identifier_info;
188
189 ret = psa_its_get_info( data_identifier, &data_identifier_info );
190 if( ret == PSA_ERROR_DOES_NOT_EXIST )
191 return( PSA_SUCCESS );
192
193 if( psa_its_remove( data_identifier ) != PSA_SUCCESS )
194 return( PSA_ERROR_STORAGE_FAILURE );
195
196 ret = psa_its_get_info( data_identifier, &data_identifier_info );
197 if( ret != PSA_ERROR_DOES_NOT_EXIST )
198 return( PSA_ERROR_STORAGE_FAILURE );
199
200 return( PSA_SUCCESS );
201}
202
Gilles Peskine5e80d912019-02-24 17:10:18 +0100203/**
204 * \brief Get data length for given key slot number.
205 *
206 * \param key Persistent identifier whose stored data length
207 * is to be obtained.
208 * \param[out] data_length The number of bytes that make up the data.
209 *
210 * \retval PSA_SUCCESS
211 * \retval PSA_ERROR_STORAGE_FAILURE
212 */
213static psa_status_t psa_crypto_storage_get_data_length(
214 const psa_key_file_id_t key,
215 size_t *data_length )
Gilles Peskine088b77f2019-02-24 17:00:27 +0100216{
217 psa_status_t status;
218 psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key );
219 struct psa_storage_info_t data_identifier_info;
220
221 status = psa_its_get_info( data_identifier, &data_identifier_info );
222 if( status != PSA_SUCCESS )
223 return( status );
224
225 *data_length = (size_t) data_identifier_info.size;
226
227 return( PSA_SUCCESS );
228}
229
Darryl Greendb2b8db2018-06-15 13:06:04 +0100230/*
231 * 32-bit integer manipulation macros (little endian)
232 */
233#ifndef GET_UINT32_LE
Gilles Peskine274a2632019-07-23 11:27:38 +0200234#define GET_UINT32_LE( n, b, i ) \
Darryl Greendb2b8db2018-06-15 13:06:04 +0100235{ \
236 (n) = ( (uint32_t) (b)[(i) ] ) \
237 | ( (uint32_t) (b)[(i) + 1] << 8 ) \
238 | ( (uint32_t) (b)[(i) + 2] << 16 ) \
239 | ( (uint32_t) (b)[(i) + 3] << 24 ); \
240}
241#endif
242
243#ifndef PUT_UINT32_LE
Gilles Peskine274a2632019-07-23 11:27:38 +0200244#define PUT_UINT32_LE( n, b, i ) \
Darryl Greendb2b8db2018-06-15 13:06:04 +0100245{ \
246 (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
247 (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
248 (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
249 (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
250}
251#endif
252
Moran Peker96ebf9e2018-06-28 18:02:17 +0300253/**
254 * Persistent key storage magic header.
255 */
256#define PSA_KEY_STORAGE_MAGIC_HEADER "PSA\0KEY"
257#define PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH ( sizeof( PSA_KEY_STORAGE_MAGIC_HEADER ) )
258
Darryl Greendb2b8db2018-06-15 13:06:04 +0100259typedef struct {
Moran Peker96ebf9e2018-06-28 18:02:17 +0300260 uint8_t magic[PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH];
Darryl Greendb2b8db2018-06-15 13:06:04 +0100261 uint8_t version[4];
Gilles Peskine0e8d4952019-07-23 14:46:52 +0200262 uint8_t lifetime[sizeof( psa_key_lifetime_t )];
Gilles Peskinef65ed6f2019-12-04 17:18:41 +0100263 uint8_t type[4]; /* Size=4 for a 2-byte type to keep the structure more
264 * regular and aligned and to make potential future
265 * extensibility easier. */
Darryl Greendb2b8db2018-06-15 13:06:04 +0100266 uint8_t policy[sizeof( psa_key_policy_t )];
267 uint8_t data_len[4];
268 uint8_t key_data[];
269} psa_persistent_key_storage_format;
270
271void psa_format_key_data_for_storage( const uint8_t *data,
272 const size_t data_length,
Gilles Peskine4ed0e6f2019-07-30 20:22:33 +0200273 const psa_core_key_attributes_t *attr,
Darryl Greendb2b8db2018-06-15 13:06:04 +0100274 uint8_t *storage_data )
275{
276 psa_persistent_key_storage_format *storage_format =
277 (psa_persistent_key_storage_format *) storage_data;
278
Moran Peker96ebf9e2018-06-28 18:02:17 +0300279 memcpy( storage_format->magic, PSA_KEY_STORAGE_MAGIC_HEADER, PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH );
Gilles Peskine274a2632019-07-23 11:27:38 +0200280 PUT_UINT32_LE( 0, storage_format->version, 0 );
Gilles Peskine4ed0e6f2019-07-30 20:22:33 +0200281 PUT_UINT32_LE( attr->lifetime, storage_format->lifetime, 0 );
Gilles Peskinef65ed6f2019-12-04 17:18:41 +0100282 PUT_UINT32_LE( (uint32_t) attr->type, storage_format->type, 0 );
Gilles Peskine4ed0e6f2019-07-30 20:22:33 +0200283 PUT_UINT32_LE( attr->policy.usage, storage_format->policy, 0 );
284 PUT_UINT32_LE( attr->policy.alg, storage_format->policy, sizeof( uint32_t ) );
285 PUT_UINT32_LE( attr->policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) );
Gilles Peskine274a2632019-07-23 11:27:38 +0200286 PUT_UINT32_LE( data_length, storage_format->data_len, 0 );
Darryl Greendb2b8db2018-06-15 13:06:04 +0100287 memcpy( storage_format->key_data, data, data_length );
288}
289
Moran Peker96ebf9e2018-06-28 18:02:17 +0300290static psa_status_t check_magic_header( const uint8_t *data )
291{
292 if( memcmp( data, PSA_KEY_STORAGE_MAGIC_HEADER,
293 PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH ) != 0 )
294 return( PSA_ERROR_STORAGE_FAILURE );
295 return( PSA_SUCCESS );
296}
297
Darryl Greendb2b8db2018-06-15 13:06:04 +0100298psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data,
299 size_t storage_data_length,
300 uint8_t **key_data,
301 size_t *key_data_length,
Gilles Peskine4ed0e6f2019-07-30 20:22:33 +0200302 psa_core_key_attributes_t *attr )
Darryl Greendb2b8db2018-06-15 13:06:04 +0100303{
Moran Peker96ebf9e2018-06-28 18:02:17 +0300304 psa_status_t status;
Darryl Greendb2b8db2018-06-15 13:06:04 +0100305 const psa_persistent_key_storage_format *storage_format =
306 (const psa_persistent_key_storage_format *)storage_data;
307 uint32_t version;
Gilles Peskinef65ed6f2019-12-04 17:18:41 +0100308 uint32_t type;
Darryl Greendb2b8db2018-06-15 13:06:04 +0100309
Moran Peker96ebf9e2018-06-28 18:02:17 +0300310 if( storage_data_length < sizeof(*storage_format) )
311 return( PSA_ERROR_STORAGE_FAILURE );
312
313 status = check_magic_header( storage_data );
314 if( status != PSA_SUCCESS )
315 return( status );
316
Gilles Peskine274a2632019-07-23 11:27:38 +0200317 GET_UINT32_LE( version, storage_format->version, 0 );
Darryl Greendb2b8db2018-06-15 13:06:04 +0100318 if( version != 0 )
319 return( PSA_ERROR_STORAGE_FAILURE );
320
Gilles Peskine274a2632019-07-23 11:27:38 +0200321 GET_UINT32_LE( *key_data_length, storage_format->data_len, 0 );
Darryl Greendb2b8db2018-06-15 13:06:04 +0100322 if( *key_data_length > ( storage_data_length - sizeof(*storage_format) ) ||
323 *key_data_length > PSA_CRYPTO_MAX_STORAGE_SIZE )
324 return( PSA_ERROR_STORAGE_FAILURE );
325
Gilles Peskine3495b582019-04-25 13:47:06 +0200326 if( *key_data_length == 0 )
327 {
328 *key_data = NULL;
329 }
330 else
331 {
332 *key_data = mbedtls_calloc( 1, *key_data_length );
333 if( *key_data == NULL )
334 return( PSA_ERROR_INSUFFICIENT_MEMORY );
335 memcpy( *key_data, storage_format->key_data, *key_data_length );
336 }
Darryl Greendb2b8db2018-06-15 13:06:04 +0100337
Gilles Peskine4ed0e6f2019-07-30 20:22:33 +0200338 GET_UINT32_LE( attr->lifetime, storage_format->lifetime, 0 );
Gilles Peskinef65ed6f2019-12-04 17:18:41 +0100339 GET_UINT32_LE( type, storage_format->type, 0 );
340 if( type <= (psa_key_type_t) -1 )
341 attr->type = (psa_key_type_t) type;
342 else
343 return( PSA_ERROR_STORAGE_FAILURE );
Gilles Peskine4ed0e6f2019-07-30 20:22:33 +0200344 GET_UINT32_LE( attr->policy.usage, storage_format->policy, 0 );
345 GET_UINT32_LE( attr->policy.alg, storage_format->policy, sizeof( uint32_t ) );
346 GET_UINT32_LE( attr->policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) );
Darryl Greendb2b8db2018-06-15 13:06:04 +0100347
Darryl Greendb2b8db2018-06-15 13:06:04 +0100348 return( PSA_SUCCESS );
349}
350
Gilles Peskine4ed0e6f2019-07-30 20:22:33 +0200351psa_status_t psa_save_persistent_key( const psa_core_key_attributes_t *attr,
Darryl Greendb2b8db2018-06-15 13:06:04 +0100352 const uint8_t *data,
353 const size_t data_length )
354{
355 size_t storage_data_length;
356 uint8_t *storage_data;
357 psa_status_t status;
358
359 if( data_length > PSA_CRYPTO_MAX_STORAGE_SIZE )
360 return PSA_ERROR_INSUFFICIENT_STORAGE;
361 storage_data_length = data_length + sizeof( psa_persistent_key_storage_format );
362
363 storage_data = mbedtls_calloc( 1, storage_data_length );
364 if( storage_data == NULL )
365 return( PSA_ERROR_INSUFFICIENT_MEMORY );
366
Gilles Peskine4ed0e6f2019-07-30 20:22:33 +0200367 psa_format_key_data_for_storage( data, data_length, attr, storage_data );
Darryl Greendb2b8db2018-06-15 13:06:04 +0100368
Gilles Peskine4ed0e6f2019-07-30 20:22:33 +0200369 status = psa_crypto_storage_store( attr->id,
Darryl Greendb2b8db2018-06-15 13:06:04 +0100370 storage_data, storage_data_length );
371
372 mbedtls_free( storage_data );
373
374 return( status );
375}
376
377void psa_free_persistent_key_data( uint8_t *key_data, size_t key_data_length )
378{
379 if( key_data != NULL )
380 {
381 mbedtls_platform_zeroize( key_data, key_data_length );
382 }
383 mbedtls_free( key_data );
384}
385
Gilles Peskine4ed0e6f2019-07-30 20:22:33 +0200386psa_status_t psa_load_persistent_key( psa_core_key_attributes_t *attr,
Darryl Greendb2b8db2018-06-15 13:06:04 +0100387 uint8_t **data,
388 size_t *data_length )
389{
390 psa_status_t status = PSA_SUCCESS;
391 uint8_t *loaded_data;
392 size_t storage_data_length = 0;
Gilles Peskine4ed0e6f2019-07-30 20:22:33 +0200393 psa_key_id_t key = attr->id;
Darryl Greendb2b8db2018-06-15 13:06:04 +0100394
395 status = psa_crypto_storage_get_data_length( key, &storage_data_length );
396 if( status != PSA_SUCCESS )
397 return( status );
398
399 loaded_data = mbedtls_calloc( 1, storage_data_length );
400
401 if( loaded_data == NULL )
402 return( PSA_ERROR_INSUFFICIENT_MEMORY );
403
404 status = psa_crypto_storage_load( key, loaded_data, storage_data_length );
405 if( status != PSA_SUCCESS )
406 goto exit;
407
408 status = psa_parse_key_data_from_storage( loaded_data, storage_data_length,
Gilles Peskine4ed0e6f2019-07-30 20:22:33 +0200409 data, data_length, attr );
Darryl Greendb2b8db2018-06-15 13:06:04 +0100410
411exit:
412 mbedtls_free( loaded_data );
413 return( status );
414}
415
Gilles Peskinec8336cb2019-07-22 19:26:12 +0200416
417
418/****************************************************************/
419/* Transactions */
420/****************************************************************/
421
422#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
423
424psa_crypto_transaction_t psa_crypto_transaction;
425
426psa_status_t psa_crypto_save_transaction( void )
427{
428 struct psa_storage_info_t p_info;
429 psa_status_t status;
Jaeden Amero2ce22a52019-10-28 15:25:10 +0000430 status = psa_its_get_info( PSA_CRYPTO_ITS_TRANSACTION_UID, &p_info );
Gilles Peskinec8336cb2019-07-22 19:26:12 +0200431 if( status == PSA_SUCCESS )
432 {
433 /* This shouldn't happen: we're trying to start a transaction while
434 * there is still a transaction that hasn't been replayed. */
435 return( PSA_ERROR_CORRUPTION_DETECTED );
436 }
437 else if( status != PSA_ERROR_DOES_NOT_EXIST )
438 return( status );
439 return( psa_its_set( PSA_CRYPTO_ITS_TRANSACTION_UID,
440 sizeof( psa_crypto_transaction ),
441 &psa_crypto_transaction,
442 0 ) );
443}
444
445psa_status_t psa_crypto_load_transaction( void )
446{
Gilles Peskine8b663892019-07-31 17:57:57 +0200447 psa_status_t status;
448 size_t length;
449 status = psa_its_get( PSA_CRYPTO_ITS_TRANSACTION_UID, 0,
450 sizeof( psa_crypto_transaction ),
451 &psa_crypto_transaction, &length );
452 if( status != PSA_SUCCESS )
453 return( status );
454 if( length != sizeof( psa_crypto_transaction ) )
455 return( PSA_ERROR_STORAGE_FAILURE );
456 return( PSA_SUCCESS );
Gilles Peskinec8336cb2019-07-22 19:26:12 +0200457}
458
459psa_status_t psa_crypto_stop_transaction( void )
460{
461 psa_status_t status = psa_its_remove( PSA_CRYPTO_ITS_TRANSACTION_UID );
462 /* Whether or not updating the storage succeeded, the transaction is
463 * finished now. It's too late to go back, so zero out the in-memory
464 * data. */
465 memset( &psa_crypto_transaction, 0, sizeof( psa_crypto_transaction ) );
466 return( status );
467}
468
469#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */
470
471
472
473/****************************************************************/
474/* Random generator state */
475/****************************************************************/
476
Gilles Peskinee3dbdd82019-02-25 11:04:06 +0100477#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
478psa_status_t mbedtls_psa_storage_inject_entropy( const unsigned char *seed,
479 size_t seed_size )
480{
481 psa_status_t status;
482 struct psa_storage_info_t p_info;
483
484 status = psa_its_get_info( PSA_CRYPTO_ITS_RANDOM_SEED_UID, &p_info );
485
486 if( PSA_ERROR_DOES_NOT_EXIST == status ) /* No seed exists */
487 {
488 status = psa_its_set( PSA_CRYPTO_ITS_RANDOM_SEED_UID, seed_size, seed, 0 );
489 }
490 else if( PSA_SUCCESS == status )
491 {
492 /* You should not be here. Seed needs to be injected only once */
493 status = PSA_ERROR_NOT_PERMITTED;
494 }
495 return( status );
496}
497#endif /* MBEDTLS_PSA_INJECT_ENTROPY */
498
Gilles Peskinec8336cb2019-07-22 19:26:12 +0200499
500
501/****************************************************************/
502/* The end */
503/****************************************************************/
504
Darryl Greendb2b8db2018-06-15 13:06:04 +0100505#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */