NCBI C++ ToolKit
psa_its_file.c
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /*
2  * PSA ITS simulator over stdio files.
3  */
4 /*
5  * Copyright The Mbed TLS Contributors
6  * 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 
21 #include "common.h"
22 
23 #if defined(MBEDTLS_PSA_ITS_FILE_C)
24 
25 #include "mbedtls/platform.h"
26 
27 #if defined(_WIN32)
28 #include <windows.h>
29 #endif
30 
31 #include "psa_crypto_its.h"
32 
33 #include <limits.h>
34 #include <stdint.h>
35 #include <stdio.h>
36 #include <string.h>
37 
38 #if !defined(PSA_ITS_STORAGE_PREFIX)
39 #define PSA_ITS_STORAGE_PREFIX ""
40 #endif
41 
42 #define PSA_ITS_STORAGE_FILENAME_PATTERN "%08x%08x"
43 #define PSA_ITS_STORAGE_SUFFIX ".psa_its"
44 #define PSA_ITS_STORAGE_FILENAME_LENGTH \
45  (sizeof(PSA_ITS_STORAGE_PREFIX) - 1 + /*prefix without terminating 0*/ \
46  16 + /*UID (64-bit number in hex)*/ \
47  sizeof(PSA_ITS_STORAGE_SUFFIX) - 1 + /*suffix without terminating 0*/ \
48  1 /*terminating null byte*/)
49 #define PSA_ITS_STORAGE_TEMP \
50  PSA_ITS_STORAGE_PREFIX "tempfile" PSA_ITS_STORAGE_SUFFIX
51 
52 /* The maximum value of psa_storage_info_t.size */
53 #define PSA_ITS_MAX_SIZE 0xffffffff
54 
55 #define PSA_ITS_MAGIC_STRING "PSA\0ITS\0"
56 #define PSA_ITS_MAGIC_LENGTH 8
57 
58 /* As rename fails on Windows if the new filepath already exists,
59  * use MoveFileExA with the MOVEFILE_REPLACE_EXISTING flag instead.
60  * Returns 0 on success, nonzero on failure. */
61 #if defined(_WIN32)
62 #define rename_replace_existing(oldpath, newpath) \
63  (!MoveFileExA(oldpath, newpath, MOVEFILE_REPLACE_EXISTING))
64 #else
65 #define rename_replace_existing(oldpath, newpath) rename(oldpath, newpath)
66 #endif
67 
68 typedef struct {
70  uint8_t size[sizeof(uint32_t)];
73 
74 static void psa_its_fill_filename(psa_storage_uid_t uid, char *filename)
75 {
76  /* Break up the UID into two 32-bit pieces so as not to rely on
77  * long long support in snprintf. */
81  (unsigned) (uid >> 32),
82  (unsigned) (uid & 0xffffffff),
84 }
85 
87  struct psa_storage_info_t *p_info,
88  FILE **p_stream)
89 {
90  char filename[PSA_ITS_STORAGE_FILENAME_LENGTH];
91  psa_its_file_header_t header;
92  size_t n;
93 
94  *p_stream = NULL;
95  psa_its_fill_filename(uid, filename);
96  *p_stream = fopen(filename, "rb");
97  if (*p_stream == NULL) {
99  }
100 
101  n = fread(&header, 1, sizeof(header), *p_stream);
102  if (n != sizeof(header)) {
103  return PSA_ERROR_DATA_CORRUPT;
104  }
105  if (memcmp(header.magic, PSA_ITS_MAGIC_STRING,
106  PSA_ITS_MAGIC_LENGTH) != 0) {
107  return PSA_ERROR_DATA_CORRUPT;
108  }
109 
110  p_info->size = (header.size[0] |
111  header.size[1] << 8 |
112  header.size[2] << 16 |
113  header.size[3] << 24);
114  p_info->flags = (header.flags[0] |
115  header.flags[1] << 8 |
116  header.flags[2] << 16 |
117  header.flags[3] << 24);
118  return PSA_SUCCESS;
119 }
120 
122  struct psa_storage_info_t *p_info)
123 {
124  psa_status_t status;
125  FILE *stream = NULL;
126  status = psa_its_read_file(uid, p_info, &stream);
127  if (stream != NULL) {
128  fclose(stream);
129  }
130  return status;
131 }
132 
134  uint32_t data_offset,
135  uint32_t data_length,
136  void *p_data,
137  size_t *p_data_length)
138 {
139  psa_status_t status;
140  FILE *stream = NULL;
141  size_t n;
142  struct psa_storage_info_t info;
143 
144  status = psa_its_read_file(uid, &info, &stream);
145  if (status != PSA_SUCCESS) {
146  goto exit;
147  }
149  if (data_offset + data_length < data_offset) {
150  goto exit;
151  }
152 #if SIZE_MAX < 0xffffffff
153  if (data_offset + data_length > SIZE_MAX) {
154  goto exit;
155  }
156 #endif
157  if (data_offset + data_length > info.size) {
158  goto exit;
159  }
160 
161  status = PSA_ERROR_STORAGE_FAILURE;
162 #if LONG_MAX < 0xffffffff
163  while (data_offset > LONG_MAX) {
164  if (fseek(stream, LONG_MAX, SEEK_CUR) != 0) {
165  goto exit;
166  }
167  data_offset -= LONG_MAX;
168  }
169 #endif
170  if (fseek(stream, data_offset, SEEK_CUR) != 0) {
171  goto exit;
172  }
173  n = fread(p_data, 1, data_length, stream);
174  if (n != data_length) {
175  goto exit;
176  }
177  status = PSA_SUCCESS;
178  if (p_data_length != NULL) {
179  *p_data_length = n;
180  }
181 
182 exit:
183  if (stream != NULL) {
184  fclose(stream);
185  }
186  return status;
187 }
188 
190  uint32_t data_length,
191  const void *p_data,
192  psa_storage_create_flags_t create_flags)
193 {
194  if (uid == 0) {
196  }
197 
199  char filename[PSA_ITS_STORAGE_FILENAME_LENGTH];
200  FILE *stream = NULL;
201  psa_its_file_header_t header;
202  size_t n;
203 
205  MBEDTLS_PUT_UINT32_LE(data_length, header.size, 0);
206  MBEDTLS_PUT_UINT32_LE(create_flags, header.flags, 0);
207 
208  psa_its_fill_filename(uid, filename);
209  stream = fopen(PSA_ITS_STORAGE_TEMP, "wb");
210  if (stream == NULL) {
211  goto exit;
212  }
213 
215  n = fwrite(&header, 1, sizeof(header), stream);
216  if (n != sizeof(header)) {
217  goto exit;
218  }
219  if (data_length != 0) {
220  n = fwrite(p_data, 1, data_length, stream);
221  if (n != data_length) {
222  goto exit;
223  }
224  }
225  status = PSA_SUCCESS;
226 
227 exit:
228  if (stream != NULL) {
229  int ret = fclose(stream);
230  if (status == PSA_SUCCESS && ret != 0) {
232  }
233  }
234  if (status == PSA_SUCCESS) {
235  if (rename_replace_existing(PSA_ITS_STORAGE_TEMP, filename) != 0) {
236  status = PSA_ERROR_STORAGE_FAILURE;
237  }
238  }
239  /* The temporary file may still exist, but only in failure cases where
240  * we're already reporting an error. So there's nothing we can do on
241  * failure. If the function succeeded, and in some error cases, the
242  * temporary file doesn't exist and so remove() is expected to fail.
243  * Thus we just ignore the return status of remove(). */
245  return status;
246 }
247 
249 {
250  char filename[PSA_ITS_STORAGE_FILENAME_LENGTH];
251  FILE *stream;
252  psa_its_fill_filename(uid, filename);
253  stream = fopen(filename, "rb");
254  if (stream == NULL) {
256  }
257  fclose(stream);
258  if (remove(filename) != 0) {
260  }
261  return PSA_SUCCESS;
262 }
263 
264 #endif /* MBEDTLS_PSA_ITS_FILE_C */
#define MBEDTLS_PUT_UINT32_LE(n, data, offset)
Put in memory a 32 bits unsigned integer in little-endian order.
Definition: common.h:182
static void DLIST_NAME() remove(DLIST_LIST_TYPE *list, DLIST_TYPE *item)
Definition: dlist.tmpl.h:90
#define NULL
Definition: ncbistd.hpp:225
#define SIZE_MAX
Definition: ncbistd.hpp:217
int32_t psa_status_t
Function return status.
Definition: crypto_types.h:62
#define PSA_ERROR_DOES_NOT_EXIST
Asking for an item that doesn't exist.
#define PSA_SUCCESS
The action was completed successfully.
Definition: crypto_values.h:68
#define PSA_ERROR_INVALID_ARGUMENT
The parameters passed to the function are invalid.
#define PSA_ERROR_INSUFFICIENT_STORAGE
There is not enough persistent storage.
#define PSA_ERROR_DATA_CORRUPT
Stored data has been corrupted.
#define PSA_ERROR_STORAGE_FAILURE
There was a storage failure that may have led to data loss.
#define PSA_ERROR_INVALID_HANDLE
The key identifier is not valid.
exit(2)
yy_size_t n
static MDB_envinfo info
Definition: mdb_load.c:37
#define fseek
#define mbedtls_snprintf
This file contains the definitions and functions of the Mbed TLS platform abstraction layer.
Interface of trusted storage that crypto is built on.
psa_status_t psa_its_set(psa_storage_uid_t uid, uint32_t data_length, const void *p_data, psa_storage_create_flags_t create_flags)
create a new or modify an existing uid/value pair
uint32_t psa_storage_create_flags_t
Flags used when creating a data entry.
psa_status_t psa_its_get(psa_storage_uid_t uid, uint32_t data_offset, uint32_t data_length, void *p_data, size_t *p_data_length)
Retrieve the value associated with a provided uid.
psa_status_t psa_its_remove(psa_storage_uid_t uid)
Remove the provided key and its associated data from the storage.
psa_status_t psa_its_get_info(psa_storage_uid_t uid, struct psa_storage_info_t *p_info)
Retrieve the metadata about the provided uid.
uint64_t psa_storage_uid_t
A type for UIDs used for identifying data.
static void psa_its_fill_filename(psa_storage_uid_t uid, char *filename)
Definition: psa_its_file.c:74
#define PSA_ITS_STORAGE_SUFFIX
Definition: psa_its_file.c:43
static psa_status_t psa_its_read_file(psa_storage_uid_t uid, struct psa_storage_info_t *p_info, FILE **p_stream)
Definition: psa_its_file.c:86
#define PSA_ITS_STORAGE_FILENAME_PATTERN
Definition: psa_its_file.c:42
#define PSA_ITS_STORAGE_PREFIX
Definition: psa_its_file.c:39
#define PSA_ITS_MAGIC_STRING
Definition: psa_its_file.c:55
#define PSA_ITS_STORAGE_TEMP
Definition: psa_its_file.c:49
#define rename_replace_existing(oldpath, newpath)
Definition: psa_its_file.c:65
#define PSA_ITS_STORAGE_FILENAME_LENGTH
Definition: psa_its_file.c:44
#define PSA_ITS_MAGIC_LENGTH
Definition: psa_its_file.c:56
unsigned int uint32_t
Definition: stdint.h:126
unsigned char uint8_t
Definition: stdint.h:124
uint8_t size[sizeof(uint32_t)]
Definition: psa_its_file.c:70
uint8_t flags[sizeof(psa_storage_create_flags_t)]
Definition: psa_its_file.c:71
A container for metadata associated with a specific uid.
psa_storage_create_flags_t flags
The flags set when the uid was created.
uint32_t size
The size of the data associated with a uid.
#define SEEK_CUR
Definition: zconf.h:499
Modified on Tue Nov 28 02:28:29 2023 by modify_doxy.py rev. 669887