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