|
23 | 23 | #include "nu_modutil.h"
|
24 | 24 | #include "nu_bitutil.h"
|
25 | 25 | #include "crypto-misc.h"
|
| 26 | +#include "platform/SingletonPtr.h" |
| 27 | +#include "platform/PlatformMutex.h" |
26 | 28 |
|
27 | 29 | #if DEVICE_TRNG || defined(MBEDTLS_CONFIG_HW_SUPPORT)
|
28 | 30 |
|
29 |
| -/* NOTE: There's inconsistency in cryptography related naming, Crpt or Crypto. For example, cryptography IRQ |
30 |
| - * handler could be CRPT_IRQHandler or CRYPTO_IRQHandler. To override default cryptography IRQ handler, see |
31 |
| - * device/startup_{CHIP}.c for its name or call NVIC_SetVector regardless of its name. */ |
32 |
| -void CRPT_IRQHandler(); |
| 31 | +/* Consideration for choosing proper synchronization mechanism |
| 32 | + * |
| 33 | + * 1. We choose mutex to synchronize access to crypto non-SHA AC. We can guarantee: |
| 34 | + * (1) No deadlock |
| 35 | + * We just lock mutex for a short sequence of operations rather than the whole lifetime |
| 36 | + * of crypto context. |
| 37 | + * (2) No priority inversion |
| 38 | + * Mutex supports priority inheritance and it is enabled. |
| 39 | + * 2. We choose atomic flag to synchronize access to crypto SHA AC. We can guarantee: |
| 40 | + * (1) No deadlock |
| 41 | + * With SHA AC not supporting context save & restore, we provide SHA S/W fallback when |
| 42 | + * SHA AC is not available. |
| 43 | + * (2) No biting CPU |
| 44 | + * Same reason as above. |
| 45 | + */ |
| 46 | + |
| 47 | +/* Mutex for crypto AES AC management */ |
| 48 | +static SingletonPtr<PlatformMutex> crypto_aes_mutex; |
| 49 | + |
| 50 | +/* Mutex for crypto DES AC management */ |
| 51 | +static SingletonPtr<PlatformMutex> crypto_des_mutex; |
| 52 | + |
| 53 | +/* Mutex for crypto ECC AC management */ |
| 54 | +static SingletonPtr<PlatformMutex> crypto_ecc_mutex; |
| 55 | + |
| 56 | +/* Atomic flag for crypto SHA AC management */ |
| 57 | +static core_util_atomic_flag crypto_sha_atomic_flag = CORE_UTIL_ATOMIC_FLAG_INIT; |
33 | 58 |
|
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 | 59 |
|
43 | 60 | /* Crypto (AES, DES, SHA, etc.) init counter. Crypto's keeps active as it is non-zero. */
|
44 | 61 | static uint16_t crypto_init_counter = 0U;
|
45 | 62 |
|
46 |
| -static bool crypto_submodule_acquire(uint16_t *submodule_avail); |
47 |
| -static void crypto_submodule_release(uint16_t *submodule_avail); |
48 |
| - |
49 | 63 | /* Crypto done flags */
|
50 | 64 | #define CRYPTO_DONE_OK BIT0 /* Done with OK */
|
51 | 65 | #define CRYPTO_DONE_ERR BIT1 /* Done with error */
|
@@ -81,8 +95,7 @@ void crypto_init(void)
|
81 | 95 | * NOTE: We must call secure version (from non-secure domain) because SYS/CLK regions are secure.
|
82 | 96 | */
|
83 | 97 | CLK_EnableModuleClock_S(CRPT_MODULE);
|
84 |
| - |
85 |
| - NVIC_SetVector(CRPT_IRQn, (uint32_t) CRPT_IRQHandler); |
| 98 | + |
86 | 99 | NVIC_EnableIRQ(CRPT_IRQn);
|
87 | 100 | }
|
88 | 101 | core_util_critical_section_exit();
|
@@ -131,44 +144,52 @@ void crypto_zeroize32(uint32_t *v, size_t n)
|
131 | 144 | }
|
132 | 145 | }
|
133 | 146 |
|
134 |
| -bool crypto_aes_acquire(void) |
| 147 | +void crypto_aes_acquire(void) |
135 | 148 | {
|
136 |
| - return crypto_submodule_acquire(&crypto_aes_avail); |
| 149 | + /* Don't check return code of Mutex::lock(void) |
| 150 | + * |
| 151 | + * This function treats RTOS errors as fatal system errors, so it can only return osOK. |
| 152 | + * Use of the return value is deprecated, as the return is expected to become void in |
| 153 | + * the future. |
| 154 | + */ |
| 155 | + crypto_aes_mutex->lock(); |
137 | 156 | }
|
138 | 157 |
|
139 | 158 | void crypto_aes_release(void)
|
140 | 159 | {
|
141 |
| - crypto_submodule_release(&crypto_aes_avail); |
| 160 | + crypto_aes_mutex->unlock(); |
142 | 161 | }
|
143 | 162 |
|
144 |
| -bool crypto_des_acquire(void) |
| 163 | +void crypto_des_acquire(void) |
145 | 164 | {
|
146 |
| - return crypto_submodule_acquire(&crypto_des_avail); |
| 165 | + /* Don't check return code of Mutex::lock(void) */ |
| 166 | + crypto_des_mutex->lock(); |
147 | 167 | }
|
148 | 168 |
|
149 | 169 | void crypto_des_release(void)
|
150 | 170 | {
|
151 |
| - crypto_submodule_release(&crypto_des_avail); |
| 171 | + crypto_des_mutex->unlock(); |
152 | 172 | }
|
153 | 173 |
|
154 |
| -bool crypto_sha_acquire(void) |
| 174 | +void crypto_ecc_acquire(void) |
155 | 175 | {
|
156 |
| - return crypto_submodule_acquire(&crypto_sha_avail); |
| 176 | + /* Don't check return code of Mutex::lock(void) */ |
| 177 | + crypto_ecc_mutex->lock(); |
157 | 178 | }
|
158 | 179 |
|
159 |
| -void crypto_sha_release(void) |
| 180 | +void crypto_ecc_release(void) |
160 | 181 | {
|
161 |
| - crypto_submodule_release(&crypto_sha_avail); |
| 182 | + crypto_ecc_mutex->unlock(); |
162 | 183 | }
|
163 | 184 |
|
164 |
| -bool crypto_ecc_acquire(void) |
| 185 | +bool crypto_sha_try_acquire(void) |
165 | 186 | {
|
166 |
| - return crypto_submodule_acquire(&crypto_ecc_avail); |
| 187 | + return !core_util_atomic_flag_test_and_set(&crypto_sha_atomic_flag); |
167 | 188 | }
|
168 | 189 |
|
169 |
| -void crypto_ecc_release(void) |
| 190 | +void crypto_sha_release(void) |
170 | 191 | {
|
171 |
| - crypto_submodule_release(&crypto_ecc_avail); |
| 192 | + core_util_atomic_flag_clear(&crypto_sha_atomic_flag); |
172 | 193 | }
|
173 | 194 |
|
174 | 195 | void crypto_prng_prestart(void)
|
@@ -252,18 +273,6 @@ bool crypto_dma_buffs_overlap(const void *in_buff, size_t in_buff_size, const vo
|
252 | 273 | return overlap;
|
253 | 274 | }
|
254 | 275 |
|
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 | 276 | static void crypto_submodule_prestart(volatile uint16_t *submodule_done)
|
268 | 277 | {
|
269 | 278 | *submodule_done = 0;
|
@@ -296,8 +305,13 @@ static bool crypto_submodule_wait(volatile uint16_t *submodule_done)
|
296 | 305 | return false;
|
297 | 306 | }
|
298 | 307 |
|
299 |
| -/* Crypto interrupt handler */ |
300 |
| -void CRPT_IRQHandler() |
| 308 | +/* Crypto interrupt handler |
| 309 | + * |
| 310 | + * There's inconsistency in cryptography related naming, Crpt or Crypto. For example, |
| 311 | + * cryptography IRQ handler could be CRPT_IRQHandler or CRYPTO_IRQHandler. To override |
| 312 | + * default cryptography IRQ handler, see device/startup_{CHIP}.c for its correct name |
| 313 | + * or call NVIC_SetVector() in crypto_init() regardless of its name. */ |
| 314 | +extern "C" void CRPT_IRQHandler() |
301 | 315 | {
|
302 | 316 | uint32_t intsts;
|
303 | 317 |
|
|
0 commit comments