|
19 | 19 | #include "mbed_assert.h"
|
20 | 20 | #include "mbed_critical.h"
|
21 | 21 | #include "mbed_error.h"
|
| 22 | +#if MBED_CONF_RTOS_PRESENT |
| 23 | +#include "cmsis_os2.h" |
| 24 | +#endif |
| 25 | +#include <string.h> |
22 | 26 | #include <limits.h>
|
23 | 27 | #include "nu_modutil.h"
|
24 | 28 | #include "nu_bitutil.h"
|
25 | 29 | #include "crypto-misc.h"
|
| 30 | +#include "platform/SingletonPtr.h" |
| 31 | +#include "platform/PlatformMutex.h" |
26 | 32 |
|
27 | 33 | #if DEVICE_TRNG || defined(MBEDTLS_CONFIG_HW_SUPPORT)
|
28 | 34 |
|
| 35 | +/* Consideration for choosing proper synchronization mechanism |
| 36 | + * |
| 37 | + * 1. We choose mutex to synchronize access to crypto non-SHA AC. We can guarantee: |
| 38 | + * (1) No deadlock |
| 39 | + * We just lock mutex for a short sequence of operations rather than the whole lifetime |
| 40 | + * of crypto context. |
| 41 | + * (2) No priority inversion |
| 42 | + * Mutex supports priority inheritance and it is enabled. |
| 43 | + * 2. We choose atomic flag to synchronize access to crypto SHA AC. We can guarantee: |
| 44 | + * (1) No deadlock |
| 45 | + * With SHA AC not supporting context save & restore, we provide SHA S/W fallback when |
| 46 | + * SHA AC is not available. |
| 47 | + * (2) No biting CPU |
| 48 | + * Same reason as above. |
| 49 | + */ |
| 50 | + |
| 51 | +/* Mutex for crypto AES AC management */ |
| 52 | +static SingletonPtr<PlatformMutex> crypto_aes_mutex; |
| 53 | + |
| 54 | +/* Mutex for crypto DES AC management */ |
| 55 | +static SingletonPtr<PlatformMutex> crypto_des_mutex; |
| 56 | + |
| 57 | +/* Mutex for crypto ECC AC management */ |
| 58 | +static SingletonPtr<PlatformMutex> crypto_ecc_mutex; |
| 59 | + |
| 60 | +/* Atomic flag for crypto SHA AC management */ |
| 61 | +static core_util_atomic_flag crypto_sha_atomic_flag = CORE_UTIL_ATOMIC_FLAG_INIT; |
| 62 | + |
29 | 63 | /* NOTE: There's inconsistency in cryptography related naming, Crpt or Crypto. For example, cryptography IRQ
|
30 | 64 | * handler could be CRPT_IRQHandler or CRYPTO_IRQHandler. To override default cryptography IRQ handler, see
|
31 | 65 | * device/startup_{CHIP}.c for its name or call NVIC_SetVector regardless of its name. */
|
32 | 66 | void CRPT_IRQHandler();
|
33 | 67 |
|
34 |
| -/* Track if AES H/W is available */ |
35 |
| -static uint16_t crypto_aes_avail = 1; |
36 |
| -/* Track if DES H/W is available */ |
37 |
| -static uint16_t crypto_des_avail = 1; |
38 |
| -/* Track if SHA H/W is available */ |
39 |
| -static uint16_t crypto_sha_avail = 1; |
40 |
| -/* Track if ECC H/W is available */ |
41 |
| -static uint16_t crypto_ecc_avail = 1; |
42 | 68 |
|
43 | 69 | /* Crypto (AES, DES, SHA, etc.) init counter. Crypto's keeps active as it is non-zero. */
|
44 | 70 | static uint16_t crypto_init_counter = 0U;
|
45 | 71 |
|
46 |
| -static bool crypto_submodule_acquire(uint16_t *submodule_avail); |
47 |
| -static void crypto_submodule_release(uint16_t *submodule_avail); |
48 |
| - |
49 | 72 | /* Crypto done flags */
|
50 | 73 | #define CRYPTO_DONE_OK BIT0 /* Done with OK */
|
51 | 74 | #define CRYPTO_DONE_ERR BIT1 /* Done with error */
|
@@ -131,44 +154,52 @@ void crypto_zeroize32(uint32_t *v, size_t n)
|
131 | 154 | }
|
132 | 155 | }
|
133 | 156 |
|
134 |
| -bool crypto_aes_acquire(void) |
| 157 | +void crypto_aes_acquire(void) |
135 | 158 | {
|
136 |
| - return crypto_submodule_acquire(&crypto_aes_avail); |
| 159 | + /* Don't check return code of Mutex::lock(void) |
| 160 | + * |
| 161 | + * This function treats RTOS errors as fatal system errors, so it can only return osOK. |
| 162 | + * Use of the return value is deprecated, as the return is expected to become void in |
| 163 | + * the future. |
| 164 | + */ |
| 165 | + crypto_aes_mutex->lock(); |
137 | 166 | }
|
138 | 167 |
|
139 | 168 | void crypto_aes_release(void)
|
140 | 169 | {
|
141 |
| - crypto_submodule_release(&crypto_aes_avail); |
| 170 | + crypto_aes_mutex->unlock(); |
142 | 171 | }
|
143 | 172 |
|
144 |
| -bool crypto_des_acquire(void) |
| 173 | +void crypto_des_acquire(void) |
145 | 174 | {
|
146 |
| - return crypto_submodule_acquire(&crypto_des_avail); |
| 175 | + /* Don't check return code of Mutex::lock(void) */ |
| 176 | + crypto_des_mutex->lock(); |
147 | 177 | }
|
148 | 178 |
|
149 | 179 | void crypto_des_release(void)
|
150 | 180 | {
|
151 |
| - crypto_submodule_release(&crypto_des_avail); |
| 181 | + crypto_des_mutex->unlock(); |
152 | 182 | }
|
153 | 183 |
|
154 |
| -bool crypto_sha_acquire(void) |
| 184 | +void crypto_ecc_acquire(void) |
155 | 185 | {
|
156 |
| - return crypto_submodule_acquire(&crypto_sha_avail); |
| 186 | + /* Don't check return code of Mutex::lock(void) */ |
| 187 | + crypto_ecc_mutex->lock(); |
157 | 188 | }
|
158 | 189 |
|
159 |
| -void crypto_sha_release(void) |
| 190 | +void crypto_ecc_release(void) |
160 | 191 | {
|
161 |
| - crypto_submodule_release(&crypto_sha_avail); |
| 192 | + crypto_ecc_mutex->unlock(); |
162 | 193 | }
|
163 | 194 |
|
164 |
| -bool crypto_ecc_acquire(void) |
| 195 | +bool crypto_sha_try_acquire(void) |
165 | 196 | {
|
166 |
| - return crypto_submodule_acquire(&crypto_ecc_avail); |
| 197 | + return !core_util_atomic_flag_test_and_set(&crypto_sha_atomic_flag); |
167 | 198 | }
|
168 | 199 |
|
169 |
| -void crypto_ecc_release(void) |
| 200 | +void crypto_sha_release(void) |
170 | 201 | {
|
171 |
| - crypto_submodule_release(&crypto_ecc_avail); |
| 202 | + core_util_atomic_flag_clear(&crypto_sha_atomic_flag); |
172 | 203 | }
|
173 | 204 |
|
174 | 205 | void crypto_prng_prestart(void)
|
@@ -252,18 +283,6 @@ bool crypto_dma_buffs_overlap(const void *in_buff, size_t in_buff_size, const vo
|
252 | 283 | return overlap;
|
253 | 284 | }
|
254 | 285 |
|
255 |
| -static bool crypto_submodule_acquire(uint16_t *submodule_avail) |
256 |
| -{ |
257 |
| - uint16_t expectedCurrentValue = 1; |
258 |
| - return core_util_atomic_cas_u16(submodule_avail, &expectedCurrentValue, 0); |
259 |
| -} |
260 |
| - |
261 |
| -static void crypto_submodule_release(uint16_t *submodule_avail) |
262 |
| -{ |
263 |
| - uint16_t expectedCurrentValue = 0; |
264 |
| - while (! core_util_atomic_cas_u16(submodule_avail, &expectedCurrentValue, 1)); |
265 |
| -} |
266 |
| - |
267 | 286 | static void crypto_submodule_prestart(volatile uint16_t *submodule_done)
|
268 | 287 | {
|
269 | 288 | *submodule_done = 0;
|
|
0 commit comments