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