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