1 /*
2 * Copyright (c) 2022-2024, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <stdint.h>
34 #include <stdlib.h>
35 #include <stdbool.h>
36
37 #include <third_party/tfm/secure_fw/partitions/internal_trusted_storage/tfm_internal_trusted_storage.h> /* tfm_its_init() */
38
39 #include <ti/drivers/cryptoutils/cryptokey/CryptoKeyKeyStore_PSA_helpers.h>
40 #include <third_party/mbedtls/include/mbedtls/memory_buffer_alloc.h>
41 #include <third_party/mbedtls/include/mbedtls/platform.h>
42
43 /* Static buffer for alloc/free. The buffer size is allocated based on
44 * assumption of 16 largest symmetric keys (32B) and 16 largest asymmetric
45 * public keys (133B) that can be supported by KeyStore, with surplus bytes for
46 * additional calloc calls within mbedTLS.
47 */
48 uint8_t allocBuffer[3072];
49
50 extern psa_status_t psa_get_and_lock_key_slot_with_policy(mbedtls_svc_key_id_t key,
51 psa_key_slot_t **p_slot,
52 psa_key_usage_t usage,
53 psa_algorithm_t alg);
54
55 KeyStore_accessSemaphoreObject KeyStore_semaphoreObject = {.isAcquired = false, .isInitialized = false};
56
57 /** @brief Key handle identifier from mbedTLS 'psa_key_handle_t'. */
58 typedef psa_key_handle_t KeyStore_PSA_KeyHandle;
59
60 /* Flag to prevent multiple initialization of KeyStore driver */
61 static bool isKeyStoreInitialized = false;
62
63 /*!
64 * @cond NODOC
65 * @brief Non-public functions required by other drivers
66 *
67 * The functions may be required by other drivers and are required to
68 * ensure thread-safe behavior across multiple calls.
69 * @endcond
70 */
71
72 /*
73 * ======== KeyStore_acquireLock ========
74 */
KeyStore_acquireLock(void)75 static inline bool KeyStore_acquireLock(void)
76 {
77 SemaphoreP_Status resourceAcquired;
78
79 /* Try and obtain access to the KeyStore module */
80 resourceAcquired = SemaphoreP_pend(&KeyStore_semaphoreObject.KeyStore_accessSemaphore, SemaphoreP_WAIT_FOREVER);
81
82 return resourceAcquired == SemaphoreP_OK;
83 }
84
85 /*
86 * ======== KeyStore_releaseLock ========
87 */
KeyStore_releaseLock(void)88 static inline void KeyStore_releaseLock(void)
89 {
90 SemaphoreP_post(&KeyStore_semaphoreObject.KeyStore_accessSemaphore);
91 }
92
93 /** \defgroup key_management Key management
94 * @{
95 */
96
97 /*
98 * ======== KeyStore_PSA_purgeKey ========
99 */
KeyStore_PSA_purgeKey(KeyStore_PSA_KeyFileId key)100 int_fast16_t KeyStore_PSA_purgeKey(KeyStore_PSA_KeyFileId key)
101 {
102 int_fast16_t status = KEYSTORE_PSA_STATUS_GENERIC_ERROR;
103
104 if (!KeyStore_semaphoreObject.isAcquired)
105 {
106 if (!KeyStore_acquireLock())
107 {
108 status = KEYSTORE_PSA_STATUS_RESOURCE_UNAVAILABLE;
109 return status;
110 }
111 }
112
113 /*
114 * Only purge persistent keys, volatile keys do not have to be purged.
115 * Both type of keys will be destroyed after use by the application using
116 * KeyStore_PSA_destroyKey()
117 */
118 #if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
119 if (key.MBEDTLS_PRIVATE(key_id) > KEYSTORE_PSA_MAX_VOLATILE_KEY_ID)
120 #else
121 if (key > KEYSTORE_PSA_MAX_VOLATILE_KEY_ID)
122 #endif
123 {
124 status = psa_purge_key(key);
125 }
126
127 if (!KeyStore_semaphoreObject.isAcquired && (status != KEYSTORE_PSA_STATUS_RESOURCE_UNAVAILABLE))
128 {
129 KeyStore_releaseLock();
130 }
131 return status;
132 }
133
134 /*
135 * ======== KeyStore_cleanUp ========
136 */
KeyStore_cleanUp(int_fast16_t status)137 static int_fast16_t KeyStore_cleanUp(int_fast16_t status)
138 {
139 KeyStore_semaphoreObject.isAcquired = false;
140 if (status != KEYSTORE_PSA_STATUS_RESOURCE_UNAVAILABLE)
141 {
142 KeyStore_releaseLock();
143 }
144
145 return status;
146 }
147
148 /*
149 * ======== KeyStore_PSA_init ========
150 */
KeyStore_PSA_init(void)151 int_fast16_t KeyStore_PSA_init(void)
152 {
153 psa_status_t status = KEYSTORE_PSA_STATUS_GENERIC_ERROR;
154
155 if (!isKeyStoreInitialized)
156 {
157 mbedtls_memory_buffer_alloc_init(allocBuffer, sizeof(allocBuffer));
158 /*
159 * Applications may call psa_crypto_init() function more than once,
160 * for example in Key Store and TF-M. Once a call succeeds,
161 * subsequent calls are guaranteed to succeed.
162 */
163 status = psa_crypto_init();
164
165 if (status != PSA_SUCCESS)
166 {
167 return status;
168 }
169
170 status = tfm_its_init();
171
172 if (status != PSA_SUCCESS)
173 {
174 psa_wipe_all_key_slots();
175 return KEYSTORE_PSA_STATUS_GENERIC_ERROR;
176 }
177
178 if (!KeyStore_semaphoreObject.isInitialized)
179 {
180 SemaphoreP_constructBinary(&KeyStore_semaphoreObject.KeyStore_accessSemaphore, 1);
181 KeyStore_semaphoreObject.isInitialized = true;
182 }
183
184 isKeyStoreInitialized = true;
185 }
186 else
187 {
188 status = KEYSTORE_PSA_STATUS_SUCCESS;
189 }
190
191 return status;
192 }
193
194 /*
195 * ======== KeyStore_PSA_getKey ========
196 */
KeyStore_PSA_getKey(KeyStore_PSA_KeyFileId key,uint8_t * data,size_t dataSize,size_t * dataLength,KeyStore_PSA_Algorithm alg,KeyStore_PSA_KeyUsage usage)197 int_fast16_t KeyStore_PSA_getKey(KeyStore_PSA_KeyFileId key,
198 uint8_t *data,
199 size_t dataSize,
200 size_t *dataLength,
201 KeyStore_PSA_Algorithm alg,
202 KeyStore_PSA_KeyUsage usage)
203 {
204 psa_status_t status = KEYSTORE_PSA_STATUS_GENERIC_ERROR;
205 psa_key_slot_t *slot;
206
207 if (!KeyStore_acquireLock())
208 {
209 status = KEYSTORE_PSA_STATUS_RESOURCE_UNAVAILABLE;
210 return status;
211 }
212 KeyStore_semaphoreObject.isAcquired = true;
213
214 /*
215 * Reject a zero-length output buffer now, since this can never be a
216 * valid key representation. This way we know that data must be a valid
217 * pointer and we can do things like memset(data, ..., dataSize). */
218 if (dataSize == 0)
219 {
220 status = PSA_ERROR_BUFFER_TOO_SMALL;
221 return KeyStore_cleanUp(status);
222 }
223
224 /*
225 * Set the key to empty now, so that even when there are errors, we always
226 * set dataLength to a value between 0 and dataSize. On error, setting
227 * the key to empty is a good choice because an empty key representation is
228 * unlikely to be accepted anywhere. */
229 *dataLength = 0;
230
231 /* Fetch key material from key storage. */
232 status = psa_get_and_lock_key_slot_with_policy(key, &slot, usage, alg);
233
234 if (status != KEYSTORE_PSA_STATUS_SUCCESS)
235 {
236 /* Ignore return value for decrement of lock counter, the return value from attempting to fetch key is apt for
237 * application
238 */
239 (void)psa_unlock_key_slot(slot);
240 return KeyStore_cleanUp(status);
241 }
242
243 psa_key_attributes_t attributes = {.MBEDTLS_PRIVATE(core) = slot->attr};
244
245 status = psa_export_key_internal(&attributes, slot->key.data, slot->key.bytes, data, dataSize, dataLength);
246
247 /* Decrement lock counter on key slot after accessing the key material */
248 status = psa_unlock_key_slot(slot);
249
250 return KeyStore_cleanUp(status);
251 }
252
253 /*
254 * ======== KeyStore_PSA_importKey ========
255 */
KeyStore_PSA_importKey(KeyStore_PSA_KeyAttributes * attributes,uint8_t * data,size_t dataLength,KeyStore_PSA_KeyFileId * key)256 int_fast16_t KeyStore_PSA_importKey(KeyStore_PSA_KeyAttributes *attributes,
257 uint8_t *data,
258 size_t dataLength,
259 KeyStore_PSA_KeyFileId *key)
260 {
261 int_fast16_t status = KEYSTORE_PSA_STATUS_GENERIC_ERROR;
262
263 if (!KeyStore_acquireLock())
264 {
265 status = KEYSTORE_PSA_STATUS_RESOURCE_UNAVAILABLE;
266 return status;
267 }
268 KeyStore_semaphoreObject.isAcquired = true;
269
270 status = psa_import_key(attributes, data, dataLength, key);
271
272 return KeyStore_cleanUp(status);
273 }
274
275 /*
276 * ======== KeyStore_PSA_exportKey ========
277 */
KeyStore_PSA_exportKey(KeyStore_PSA_KeyFileId key,uint8_t * data,size_t dataSize,size_t * dataLength)278 int_fast16_t KeyStore_PSA_exportKey(KeyStore_PSA_KeyFileId key, uint8_t *data, size_t dataSize, size_t *dataLength)
279 {
280 int_fast16_t status = KEYSTORE_PSA_STATUS_GENERIC_ERROR;
281
282 if (!KeyStore_acquireLock())
283 {
284 status = KEYSTORE_PSA_STATUS_RESOURCE_UNAVAILABLE;
285 return status;
286 }
287 KeyStore_semaphoreObject.isAcquired = true;
288
289 status = psa_export_key(key, data, dataSize, dataLength);
290
291 return KeyStore_cleanUp(status);
292 }
293
294 /*
295 * ======== KeyStore_PSA_exportPublicKey ========
296 */
KeyStore_PSA_exportPublicKey(KeyStore_PSA_KeyFileId key,uint8_t * data,size_t dataSize,size_t * dataLength)297 int_fast16_t KeyStore_PSA_exportPublicKey(KeyStore_PSA_KeyFileId key,
298 uint8_t *data,
299 size_t dataSize,
300 size_t *dataLength)
301 {
302 int_fast16_t status = KEYSTORE_PSA_STATUS_GENERIC_ERROR;
303
304 if (!KeyStore_acquireLock())
305 {
306 status = KEYSTORE_PSA_STATUS_RESOURCE_UNAVAILABLE;
307 return status;
308 }
309 KeyStore_semaphoreObject.isAcquired = true;
310
311 status = psa_export_public_key(key, data, dataSize, dataLength);
312
313 return KeyStore_cleanUp(status);
314 }
315
316 /*
317 * ======== KeyStore_PSA_destroyKey ========
318 */
KeyStore_PSA_destroyKey(KeyStore_PSA_KeyFileId key)319 int_fast16_t KeyStore_PSA_destroyKey(KeyStore_PSA_KeyFileId key)
320 {
321 int_fast16_t status = KEYSTORE_PSA_STATUS_GENERIC_ERROR;
322 volatile uint32_t keyID;
323
324 /* Create a copy of the key ID */
325 SET_KEY_ID(keyID, key);
326
327 if ((keyID >= KEYSTORE_PSA_PRE_PROVISIONED_KEY_ID_MIN) && (keyID <= KEYSTORE_PSA_PRE_PROVISIONED_KEY_ID_MAX))
328 {
329 return KEYSTORE_PSA_STATUS_NOT_SUPPORTED;
330 }
331
332 if (!KeyStore_acquireLock())
333 {
334 status = KEYSTORE_PSA_STATUS_RESOURCE_UNAVAILABLE;
335 return status;
336 }
337 KeyStore_semaphoreObject.isAcquired = true;
338
339 status = psa_destroy_key(key);
340
341 return KeyStore_cleanUp(status);
342 }
343
344 /*
345 * ======== KeyStore_PSA_getKeyAttributes ========
346 */
KeyStore_PSA_getKeyAttributes(KeyStore_PSA_KeyFileId key,KeyStore_PSA_KeyAttributes * attributes)347 int_fast16_t KeyStore_PSA_getKeyAttributes(KeyStore_PSA_KeyFileId key, KeyStore_PSA_KeyAttributes *attributes)
348
349 {
350 int_fast16_t status = KEYSTORE_PSA_STATUS_GENERIC_ERROR;
351
352 if (!KeyStore_acquireLock())
353 {
354 status = KEYSTORE_PSA_STATUS_RESOURCE_UNAVAILABLE;
355 return status;
356 }
357 KeyStore_semaphoreObject.isAcquired = true;
358
359 status = psa_get_key_attributes(key, attributes);
360
361 return KeyStore_cleanUp(status);
362 }
363
364 /*
365 * ======== KeyStore_PSA_resetKeyAttributes ========
366 */
KeyStore_PSA_resetKeyAttributes(KeyStore_PSA_KeyAttributes * attributes)367 void KeyStore_PSA_resetKeyAttributes(KeyStore_PSA_KeyAttributes *attributes)
368 {
369 mbedtls_free(attributes->MBEDTLS_PRIVATE(domain_parameters));
370 memset(attributes, 0, sizeof(*attributes));
371 }
372