1 /* Copyright (c) 2024 Nordic Semiconductor
2 * SPDX-License-Identifier: Apache-2.0
3 */
4 #include <../library/psa_crypto_driver_wrappers.h>
5 #include <zephyr/secure_storage/its/transform.h>
6 #include <zephyr/secure_storage/its/transform/aead_get.h>
7 #include <zephyr/sys/__assert.h>
8
psa_aead_crypt(psa_key_usage_t operation,secure_storage_its_uid_t uid,const uint8_t nonce[static CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_SIZE],size_t add_data_len,const void * add_data,size_t input_len,const void * input,size_t output_size,void * output,size_t * output_len)9 static psa_status_t psa_aead_crypt(psa_key_usage_t operation, secure_storage_its_uid_t uid,
10 const uint8_t nonce
11 [static CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_SIZE],
12 size_t add_data_len, const void *add_data, size_t input_len,
13 const void *input, size_t output_size, void *output,
14 size_t *output_len)
15 {
16 psa_status_t ret;
17 psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
18 uint8_t key[CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE];
19 psa_key_type_t key_type;
20 psa_algorithm_t alg;
21 psa_status_t (*aead_crypt)(const psa_key_attributes_t *attributes, const uint8_t *key,
22 size_t key_size, psa_algorithm_t alg, const uint8_t *nonce,
23 size_t nonce_length, const uint8_t *add_data,
24 size_t add_data_len, const uint8_t *input, size_t input_len,
25 uint8_t *output, size_t output_size, size_t *output_len);
26
27 secure_storage_its_transform_aead_get_scheme(&key_type, &alg);
28
29 psa_set_key_usage_flags(&key_attributes, operation);
30 psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
31 psa_set_key_type(&key_attributes, key_type);
32 psa_set_key_algorithm(&key_attributes, alg);
33 psa_set_key_bits(&key_attributes, sizeof(key) * 8);
34
35 /* Avoid calling psa_aead_*crypt() because that would require importing keys into
36 * PSA Crypto. This gets called from PSA Crypto for storing persistent keys so,
37 * even if using PSA_KEY_LIFETIME_VOLATILE, it would corrupt the global key store
38 * which holds all the active keys in the PSA Crypto core.
39 */
40 aead_crypt = (operation == PSA_KEY_USAGE_ENCRYPT) ?
41 psa_driver_wrapper_aead_encrypt : psa_driver_wrapper_aead_decrypt;
42
43 ret = secure_storage_its_transform_aead_get_key(uid, key);
44 if (ret != PSA_SUCCESS) {
45 return ret;
46 }
47
48 ret = aead_crypt(&key_attributes, key, sizeof(key), alg, nonce,
49 CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_SIZE, add_data,
50 add_data_len, input, input_len, output, output_size, output_len);
51
52 mbedtls_platform_zeroize(key, sizeof(key));
53 return ret;
54 }
55
56 enum { CIPHERTEXT_MAX_SIZE
57 = PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(CONFIG_SECURE_STORAGE_ITS_MAX_DATA_SIZE) };
58
59 BUILD_ASSERT(CONFIG_SECURE_STORAGE_ITS_TRANSFORM_OUTPUT_OVERHEAD
60 == CIPHERTEXT_MAX_SIZE - CONFIG_SECURE_STORAGE_ITS_MAX_DATA_SIZE
61 + CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_SIZE);
62
63 BUILD_ASSERT(SECURE_STORAGE_ALL_CREATE_FLAGS
64 <= (1 << (8 * sizeof(secure_storage_packed_create_flags_t))) - 1);
65
66 struct stored_entry {
67 secure_storage_packed_create_flags_t create_flags;
68 uint8_t nonce[CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_NONCE_SIZE];
69 uint8_t ciphertext[CIPHERTEXT_MAX_SIZE]; /* Keep last as this is variable in size. */
70 } __packed;
71 BUILD_ASSERT(sizeof(struct stored_entry) == SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE);
72
73 /** @return The length of a `struct stored_entry` whose `ciphertext` is `len` bytes long. */
74 #define STORED_ENTRY_LEN(len) (sizeof(struct stored_entry) - CIPHERTEXT_MAX_SIZE + len)
75
76 struct additional_data {
77 secure_storage_its_uid_t uid;
78 secure_storage_packed_create_flags_t create_flags;
79 } __packed;
80
secure_storage_its_transform_to_store(secure_storage_its_uid_t uid,size_t data_len,const void * data,secure_storage_packed_create_flags_t create_flags,uint8_t stored_data[static SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE],size_t * stored_data_len)81 psa_status_t secure_storage_its_transform_to_store(
82 secure_storage_its_uid_t uid, size_t data_len, const void *data,
83 secure_storage_packed_create_flags_t create_flags,
84 uint8_t stored_data[static SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE],
85 size_t *stored_data_len)
86 {
87 psa_status_t ret;
88 struct stored_entry *stored_entry = (struct stored_entry *)stored_data;
89 const struct additional_data add_data = {.uid = uid, .create_flags = create_flags};
90 size_t ciphertext_len;
91
92 stored_entry->create_flags = create_flags;
93
94 ret = secure_storage_its_transform_aead_get_nonce(stored_entry->nonce);
95 if (ret != PSA_SUCCESS) {
96 return ret;
97 }
98
99 ret = psa_aead_crypt(PSA_KEY_USAGE_ENCRYPT, uid, stored_entry->nonce, sizeof(add_data),
100 &add_data, data_len, data, sizeof(stored_entry->ciphertext),
101 &stored_entry->ciphertext, &ciphertext_len);
102 if (ret == PSA_SUCCESS) {
103 *stored_data_len = STORED_ENTRY_LEN(ciphertext_len);
104 }
105 return ret;
106 }
107
secure_storage_its_transform_from_store(secure_storage_its_uid_t uid,size_t stored_data_len,const uint8_t stored_data[static SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE],size_t data_size,void * data,size_t * data_len,psa_storage_create_flags_t * create_flags)108 psa_status_t secure_storage_its_transform_from_store(
109 secure_storage_its_uid_t uid, size_t stored_data_len,
110 const uint8_t stored_data[static SECURE_STORAGE_ITS_TRANSFORM_MAX_STORED_DATA_SIZE],
111 size_t data_size, void *data, size_t *data_len,
112 psa_storage_create_flags_t *create_flags)
113 {
114 if (stored_data_len < STORED_ENTRY_LEN(0)) {
115 return PSA_ERROR_STORAGE_FAILURE;
116 }
117
118 psa_status_t ret;
119 struct stored_entry *stored_entry = (struct stored_entry *)stored_data;
120 const struct additional_data add_data = {.uid = uid,
121 .create_flags = stored_entry->create_flags};
122 const size_t ciphertext_len = stored_data_len - STORED_ENTRY_LEN(0);
123
124 ret = psa_aead_crypt(PSA_KEY_USAGE_DECRYPT, uid, stored_entry->nonce, sizeof(add_data),
125 &add_data, ciphertext_len, stored_entry->ciphertext, data_size, data,
126 data_len);
127 if (ret == PSA_SUCCESS) {
128 *create_flags = stored_entry->create_flags;
129 }
130 return ret;
131 }
132