mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Wed Feb 20 22:31:08 2019 +0000
Revision:
189:f392fc9709a3
mbed library release version 165

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AnnaBridge 189:f392fc9709a3 1 /* mbed Microcontroller Library
AnnaBridge 189:f392fc9709a3 2 * Copyright (c) 2015-2016 Nuvoton
AnnaBridge 189:f392fc9709a3 3 *
AnnaBridge 189:f392fc9709a3 4 * Licensed under the Apache License, Version 2.0 (the "License");
AnnaBridge 189:f392fc9709a3 5 * you may not use this file except in compliance with the License.
AnnaBridge 189:f392fc9709a3 6 * You may obtain a copy of the License at
AnnaBridge 189:f392fc9709a3 7 *
AnnaBridge 189:f392fc9709a3 8 * http://www.apache.org/licenses/LICENSE-2.0
AnnaBridge 189:f392fc9709a3 9 *
AnnaBridge 189:f392fc9709a3 10 * Unless required by applicable law or agreed to in writing, software
AnnaBridge 189:f392fc9709a3 11 * distributed under the License is distributed on an "AS IS" BASIS,
AnnaBridge 189:f392fc9709a3 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
AnnaBridge 189:f392fc9709a3 13 * See the License for the specific language governing permissions and
AnnaBridge 189:f392fc9709a3 14 * limitations under the License.
AnnaBridge 189:f392fc9709a3 15 */
AnnaBridge 189:f392fc9709a3 16
AnnaBridge 189:f392fc9709a3 17
AnnaBridge 189:f392fc9709a3 18 #include "cmsis.h"
AnnaBridge 189:f392fc9709a3 19 #include "mbed_assert.h"
AnnaBridge 189:f392fc9709a3 20 #include "mbed_critical.h"
AnnaBridge 189:f392fc9709a3 21 #include "mbed_error.h"
AnnaBridge 189:f392fc9709a3 22 #if MBED_CONF_RTOS_PRESENT
AnnaBridge 189:f392fc9709a3 23 #include "cmsis_os2.h"
AnnaBridge 189:f392fc9709a3 24 #endif
AnnaBridge 189:f392fc9709a3 25 #include <string.h>
AnnaBridge 189:f392fc9709a3 26 #include <limits.h>
AnnaBridge 189:f392fc9709a3 27 #include "nu_modutil.h"
AnnaBridge 189:f392fc9709a3 28 #include "nu_bitutil.h"
AnnaBridge 189:f392fc9709a3 29 #include "crypto-misc.h"
AnnaBridge 189:f392fc9709a3 30 #include "platform/SingletonPtr.h"
AnnaBridge 189:f392fc9709a3 31 #include "platform/PlatformMutex.h"
AnnaBridge 189:f392fc9709a3 32
AnnaBridge 189:f392fc9709a3 33 /* Consideration for choosing proper synchronization mechanism
AnnaBridge 189:f392fc9709a3 34 *
AnnaBridge 189:f392fc9709a3 35 * 1. We choose mutex to synchronize access to crypto non-SHA AC. We can guarantee:
AnnaBridge 189:f392fc9709a3 36 * (1) No deadlock
AnnaBridge 189:f392fc9709a3 37 * We just lock mutex for a short sequence of operations rather than the whole lifetime
AnnaBridge 189:f392fc9709a3 38 * of crypto context.
AnnaBridge 189:f392fc9709a3 39 * (2) No priority inversion
AnnaBridge 189:f392fc9709a3 40 * Mutex supports priority inheritance and it is enabled.
AnnaBridge 189:f392fc9709a3 41 * 2. We choose atomic flag to synchronize access to crypto SHA AC. We can guarantee:
AnnaBridge 189:f392fc9709a3 42 * (1) No deadlock
AnnaBridge 189:f392fc9709a3 43 * With SHA AC not supporting context save & restore, we provide SHA S/W fallback when
AnnaBridge 189:f392fc9709a3 44 * SHA AC is not available.
AnnaBridge 189:f392fc9709a3 45 * (2) No biting CPU
AnnaBridge 189:f392fc9709a3 46 * Same reason as above.
AnnaBridge 189:f392fc9709a3 47 */
AnnaBridge 189:f392fc9709a3 48
AnnaBridge 189:f392fc9709a3 49 /* Mutex for crypto AES AC management */
AnnaBridge 189:f392fc9709a3 50 static SingletonPtr<PlatformMutex> crypto_aes_mutex;
AnnaBridge 189:f392fc9709a3 51
AnnaBridge 189:f392fc9709a3 52 /* Mutex for crypto DES AC management */
AnnaBridge 189:f392fc9709a3 53 static SingletonPtr<PlatformMutex> crypto_des_mutex;
AnnaBridge 189:f392fc9709a3 54
AnnaBridge 189:f392fc9709a3 55 /* Atomic flag for crypto SHA AC management */
AnnaBridge 189:f392fc9709a3 56 static core_util_atomic_flag crypto_sha_atomic_flag = CORE_UTIL_ATOMIC_FLAG_INIT;
AnnaBridge 189:f392fc9709a3 57
AnnaBridge 189:f392fc9709a3 58
AnnaBridge 189:f392fc9709a3 59 /* Crypto (AES, DES, SHA, etc.) init counter. Crypto's keeps active as it is non-zero. */
AnnaBridge 189:f392fc9709a3 60 static uint16_t crypto_init_counter = 0U;
AnnaBridge 189:f392fc9709a3 61
AnnaBridge 189:f392fc9709a3 62 /* Crypto done flags */
AnnaBridge 189:f392fc9709a3 63 #define CRYPTO_DONE_OK BIT0 /* Done with OK */
AnnaBridge 189:f392fc9709a3 64 #define CRYPTO_DONE_ERR BIT1 /* Done with error */
AnnaBridge 189:f392fc9709a3 65
AnnaBridge 189:f392fc9709a3 66 /* Track if PRNG H/W operation is done */
AnnaBridge 189:f392fc9709a3 67 static volatile uint16_t crypto_prng_done;
AnnaBridge 189:f392fc9709a3 68 /* Track if AES H/W operation is done */
AnnaBridge 189:f392fc9709a3 69 static volatile uint16_t crypto_aes_done;
AnnaBridge 189:f392fc9709a3 70 /* Track if DES H/W operation is done */
AnnaBridge 189:f392fc9709a3 71 static volatile uint16_t crypto_des_done;
AnnaBridge 189:f392fc9709a3 72
AnnaBridge 189:f392fc9709a3 73 static void crypto_submodule_prestart(volatile uint16_t *submodule_done);
AnnaBridge 189:f392fc9709a3 74 static bool crypto_submodule_wait(volatile uint16_t *submodule_done);
AnnaBridge 189:f392fc9709a3 75
AnnaBridge 189:f392fc9709a3 76 /* As crypto init counter changes from 0 to 1:
AnnaBridge 189:f392fc9709a3 77 *
AnnaBridge 189:f392fc9709a3 78 * 1. Enable crypto clock
AnnaBridge 189:f392fc9709a3 79 * 2. Enable crypto interrupt
AnnaBridge 189:f392fc9709a3 80 */
AnnaBridge 189:f392fc9709a3 81 void crypto_init(void)
AnnaBridge 189:f392fc9709a3 82 {
AnnaBridge 189:f392fc9709a3 83 core_util_critical_section_enter();
AnnaBridge 189:f392fc9709a3 84 if (crypto_init_counter == USHRT_MAX) {
AnnaBridge 189:f392fc9709a3 85 core_util_critical_section_exit();
AnnaBridge 189:f392fc9709a3 86 error("Crypto clock enable counter would overflow (> USHRT_MAX)");
AnnaBridge 189:f392fc9709a3 87 }
AnnaBridge 189:f392fc9709a3 88 core_util_atomic_incr_u16(&crypto_init_counter, 1);
AnnaBridge 189:f392fc9709a3 89 if (crypto_init_counter == 1) {
AnnaBridge 189:f392fc9709a3 90 SYS_UnlockReg(); // Unlock protected register
AnnaBridge 189:f392fc9709a3 91 CLK_EnableModuleClock(CRPT_MODULE);
AnnaBridge 189:f392fc9709a3 92 SYS_LockReg(); // Lock protected register
AnnaBridge 189:f392fc9709a3 93
AnnaBridge 189:f392fc9709a3 94 NVIC_EnableIRQ(CRPT_IRQn);
AnnaBridge 189:f392fc9709a3 95 }
AnnaBridge 189:f392fc9709a3 96 core_util_critical_section_exit();
AnnaBridge 189:f392fc9709a3 97 }
AnnaBridge 189:f392fc9709a3 98
AnnaBridge 189:f392fc9709a3 99 /* As crypto init counter changes from 1 to 0:
AnnaBridge 189:f392fc9709a3 100 *
AnnaBridge 189:f392fc9709a3 101 * 1. Disable crypto interrupt
AnnaBridge 189:f392fc9709a3 102 * 2. Disable crypto clock
AnnaBridge 189:f392fc9709a3 103 */
AnnaBridge 189:f392fc9709a3 104 void crypto_uninit(void)
AnnaBridge 189:f392fc9709a3 105 {
AnnaBridge 189:f392fc9709a3 106 core_util_critical_section_enter();
AnnaBridge 189:f392fc9709a3 107 if (crypto_init_counter == 0) {
AnnaBridge 189:f392fc9709a3 108 core_util_critical_section_exit();
AnnaBridge 189:f392fc9709a3 109 error("Crypto clock enable counter would underflow (< 0)");
AnnaBridge 189:f392fc9709a3 110 }
AnnaBridge 189:f392fc9709a3 111 core_util_atomic_decr_u16(&crypto_init_counter, 1);
AnnaBridge 189:f392fc9709a3 112 if (crypto_init_counter == 0) {
AnnaBridge 189:f392fc9709a3 113 NVIC_DisableIRQ(CRPT_IRQn);
AnnaBridge 189:f392fc9709a3 114
AnnaBridge 189:f392fc9709a3 115 SYS_UnlockReg(); // Unlock protected register
AnnaBridge 189:f392fc9709a3 116 CLK_DisableModuleClock(CRPT_MODULE);
AnnaBridge 189:f392fc9709a3 117 SYS_LockReg(); // Lock protected register
AnnaBridge 189:f392fc9709a3 118 }
AnnaBridge 189:f392fc9709a3 119 core_util_critical_section_exit();
AnnaBridge 189:f392fc9709a3 120 }
AnnaBridge 189:f392fc9709a3 121
AnnaBridge 189:f392fc9709a3 122 /* Implementation that should never be optimized out by the compiler */
AnnaBridge 189:f392fc9709a3 123 void crypto_zeroize(void *v, size_t n)
AnnaBridge 189:f392fc9709a3 124 {
AnnaBridge 189:f392fc9709a3 125 volatile unsigned char *p = (volatile unsigned char*) v;
AnnaBridge 189:f392fc9709a3 126 while (n--) {
AnnaBridge 189:f392fc9709a3 127 *p++ = 0;
AnnaBridge 189:f392fc9709a3 128 }
AnnaBridge 189:f392fc9709a3 129 }
AnnaBridge 189:f392fc9709a3 130
AnnaBridge 189:f392fc9709a3 131 void crypto_aes_acquire(void)
AnnaBridge 189:f392fc9709a3 132 {
AnnaBridge 189:f392fc9709a3 133 /* Don't check return code of Mutex::lock(void)
AnnaBridge 189:f392fc9709a3 134 *
AnnaBridge 189:f392fc9709a3 135 * This function treats RTOS errors as fatal system errors, so it can only return osOK.
AnnaBridge 189:f392fc9709a3 136 * Use of the return value is deprecated, as the return is expected to become void in
AnnaBridge 189:f392fc9709a3 137 * the future.
AnnaBridge 189:f392fc9709a3 138 */
AnnaBridge 189:f392fc9709a3 139 crypto_aes_mutex->lock();
AnnaBridge 189:f392fc9709a3 140 }
AnnaBridge 189:f392fc9709a3 141
AnnaBridge 189:f392fc9709a3 142 void crypto_aes_release(void)
AnnaBridge 189:f392fc9709a3 143 {
AnnaBridge 189:f392fc9709a3 144 crypto_aes_mutex->unlock();
AnnaBridge 189:f392fc9709a3 145 }
AnnaBridge 189:f392fc9709a3 146
AnnaBridge 189:f392fc9709a3 147 void crypto_des_acquire(void)
AnnaBridge 189:f392fc9709a3 148 {
AnnaBridge 189:f392fc9709a3 149 /* Don't check return code of Mutex::lock(void) */
AnnaBridge 189:f392fc9709a3 150 crypto_des_mutex->lock();
AnnaBridge 189:f392fc9709a3 151 }
AnnaBridge 189:f392fc9709a3 152
AnnaBridge 189:f392fc9709a3 153 void crypto_des_release(void)
AnnaBridge 189:f392fc9709a3 154 {
AnnaBridge 189:f392fc9709a3 155 crypto_des_mutex->unlock();
AnnaBridge 189:f392fc9709a3 156 }
AnnaBridge 189:f392fc9709a3 157
AnnaBridge 189:f392fc9709a3 158 bool crypto_sha_try_acquire(void)
AnnaBridge 189:f392fc9709a3 159 {
AnnaBridge 189:f392fc9709a3 160 return !core_util_atomic_flag_test_and_set(&crypto_sha_atomic_flag);
AnnaBridge 189:f392fc9709a3 161 }
AnnaBridge 189:f392fc9709a3 162
AnnaBridge 189:f392fc9709a3 163 void crypto_sha_release(void)
AnnaBridge 189:f392fc9709a3 164 {
AnnaBridge 189:f392fc9709a3 165 core_util_atomic_flag_clear(&crypto_sha_atomic_flag);
AnnaBridge 189:f392fc9709a3 166 }
AnnaBridge 189:f392fc9709a3 167
AnnaBridge 189:f392fc9709a3 168 void crypto_prng_prestart(void)
AnnaBridge 189:f392fc9709a3 169 {
AnnaBridge 189:f392fc9709a3 170 crypto_submodule_prestart(&crypto_prng_done);
AnnaBridge 189:f392fc9709a3 171 }
AnnaBridge 189:f392fc9709a3 172
AnnaBridge 189:f392fc9709a3 173 bool crypto_prng_wait(void)
AnnaBridge 189:f392fc9709a3 174 {
AnnaBridge 189:f392fc9709a3 175 return crypto_submodule_wait(&crypto_prng_done);
AnnaBridge 189:f392fc9709a3 176 }
AnnaBridge 189:f392fc9709a3 177
AnnaBridge 189:f392fc9709a3 178 void crypto_aes_prestart(void)
AnnaBridge 189:f392fc9709a3 179 {
AnnaBridge 189:f392fc9709a3 180 crypto_submodule_prestart(&crypto_aes_done);
AnnaBridge 189:f392fc9709a3 181 }
AnnaBridge 189:f392fc9709a3 182
AnnaBridge 189:f392fc9709a3 183 bool crypto_aes_wait(void)
AnnaBridge 189:f392fc9709a3 184 {
AnnaBridge 189:f392fc9709a3 185 return crypto_submodule_wait(&crypto_aes_done);
AnnaBridge 189:f392fc9709a3 186 }
AnnaBridge 189:f392fc9709a3 187
AnnaBridge 189:f392fc9709a3 188 void crypto_des_prestart(void)
AnnaBridge 189:f392fc9709a3 189 {
AnnaBridge 189:f392fc9709a3 190 crypto_submodule_prestart(&crypto_des_done);
AnnaBridge 189:f392fc9709a3 191 }
AnnaBridge 189:f392fc9709a3 192
AnnaBridge 189:f392fc9709a3 193 bool crypto_des_wait(void)
AnnaBridge 189:f392fc9709a3 194 {
AnnaBridge 189:f392fc9709a3 195 return crypto_submodule_wait(&crypto_des_done);
AnnaBridge 189:f392fc9709a3 196 }
AnnaBridge 189:f392fc9709a3 197
AnnaBridge 189:f392fc9709a3 198 bool crypto_dma_buff_compat(const void *buff, size_t buff_size, size_t size_aligned_to)
AnnaBridge 189:f392fc9709a3 199 {
AnnaBridge 189:f392fc9709a3 200 uint32_t buff_ = (uint32_t) buff;
AnnaBridge 189:f392fc9709a3 201
AnnaBridge 189:f392fc9709a3 202 return (((buff_ & 0x03) == 0) && /* Word-aligned buffer base address */
AnnaBridge 189:f392fc9709a3 203 ((buff_size & (size_aligned_to - 1)) == 0) && /* Crypto submodule dependent buffer size alignment */
AnnaBridge 189:f392fc9709a3 204 (((buff_ >> 28) == 0x2) && (buff_size <= (0x30000000 - buff_)))); /* 0x20000000-0x2FFFFFFF */
AnnaBridge 189:f392fc9709a3 205 }
AnnaBridge 189:f392fc9709a3 206
AnnaBridge 189:f392fc9709a3 207 /* Overlap cases
AnnaBridge 189:f392fc9709a3 208 *
AnnaBridge 189:f392fc9709a3 209 * 1. in_buff in front of out_buff:
AnnaBridge 189:f392fc9709a3 210 *
AnnaBridge 189:f392fc9709a3 211 * in in_end
AnnaBridge 189:f392fc9709a3 212 * | |
AnnaBridge 189:f392fc9709a3 213 * ||||||||||||||||
AnnaBridge 189:f392fc9709a3 214 * ||||||||||||||||
AnnaBridge 189:f392fc9709a3 215 * | |
AnnaBridge 189:f392fc9709a3 216 * out out_end
AnnaBridge 189:f392fc9709a3 217 *
AnnaBridge 189:f392fc9709a3 218 * 2. out_buff in front of in_buff:
AnnaBridge 189:f392fc9709a3 219 *
AnnaBridge 189:f392fc9709a3 220 * in in_end
AnnaBridge 189:f392fc9709a3 221 * | |
AnnaBridge 189:f392fc9709a3 222 * ||||||||||||||||
AnnaBridge 189:f392fc9709a3 223 * ||||||||||||||||
AnnaBridge 189:f392fc9709a3 224 * | |
AnnaBridge 189:f392fc9709a3 225 * out out_end
AnnaBridge 189:f392fc9709a3 226 */
AnnaBridge 189:f392fc9709a3 227 bool crypto_dma_buffs_overlap(const void *in_buff, size_t in_buff_size, const void *out_buff, size_t out_buff_size)
AnnaBridge 189:f392fc9709a3 228 {
AnnaBridge 189:f392fc9709a3 229 uint32_t in = (uint32_t) in_buff;
AnnaBridge 189:f392fc9709a3 230 uint32_t in_end = in + in_buff_size;
AnnaBridge 189:f392fc9709a3 231 uint32_t out = (uint32_t) out_buff;
AnnaBridge 189:f392fc9709a3 232 uint32_t out_end = out + out_buff_size;
AnnaBridge 189:f392fc9709a3 233
AnnaBridge 189:f392fc9709a3 234 bool overlap = (in <= out && out < in_end) || (out <= in && in < out_end);
AnnaBridge 189:f392fc9709a3 235
AnnaBridge 189:f392fc9709a3 236 return overlap;
AnnaBridge 189:f392fc9709a3 237 }
AnnaBridge 189:f392fc9709a3 238
AnnaBridge 189:f392fc9709a3 239 static void crypto_submodule_prestart(volatile uint16_t *submodule_done)
AnnaBridge 189:f392fc9709a3 240 {
AnnaBridge 189:f392fc9709a3 241 *submodule_done = 0;
AnnaBridge 189:f392fc9709a3 242
AnnaBridge 189:f392fc9709a3 243 /* Ensure memory accesses above are completed before DMA is started
AnnaBridge 189:f392fc9709a3 244 *
AnnaBridge 189:f392fc9709a3 245 * Replacing __DSB() with __DMB() is also OK in this case.
AnnaBridge 189:f392fc9709a3 246 *
AnnaBridge 189:f392fc9709a3 247 * Refer to "multi-master systems" section with DMA in:
AnnaBridge 189:f392fc9709a3 248 * https://static.docs.arm.com/dai0321/a/DAI0321A_programming_guide_memory_barriers_for_m_profile.pdf
AnnaBridge 189:f392fc9709a3 249 */
AnnaBridge 189:f392fc9709a3 250 __DSB();
AnnaBridge 189:f392fc9709a3 251 }
AnnaBridge 189:f392fc9709a3 252
AnnaBridge 189:f392fc9709a3 253 static bool crypto_submodule_wait(volatile uint16_t *submodule_done)
AnnaBridge 189:f392fc9709a3 254 {
AnnaBridge 189:f392fc9709a3 255 while (! *submodule_done);
AnnaBridge 189:f392fc9709a3 256
AnnaBridge 189:f392fc9709a3 257 /* Ensure while loop above and subsequent code are not reordered */
AnnaBridge 189:f392fc9709a3 258 __DSB();
AnnaBridge 189:f392fc9709a3 259
AnnaBridge 189:f392fc9709a3 260 if ((*submodule_done & CRYPTO_DONE_OK)) {
AnnaBridge 189:f392fc9709a3 261 /* Done with OK */
AnnaBridge 189:f392fc9709a3 262 return true;
AnnaBridge 189:f392fc9709a3 263 } else if ((*submodule_done & CRYPTO_DONE_ERR)) {
AnnaBridge 189:f392fc9709a3 264 /* Done with error */
AnnaBridge 189:f392fc9709a3 265 return false;
AnnaBridge 189:f392fc9709a3 266 }
AnnaBridge 189:f392fc9709a3 267
AnnaBridge 189:f392fc9709a3 268 return false;
AnnaBridge 189:f392fc9709a3 269 }
AnnaBridge 189:f392fc9709a3 270
AnnaBridge 189:f392fc9709a3 271 /* Crypto interrupt handler */
AnnaBridge 189:f392fc9709a3 272 extern "C" void CRYPTO_IRQHandler()
AnnaBridge 189:f392fc9709a3 273 {
AnnaBridge 189:f392fc9709a3 274 uint32_t intsts;
AnnaBridge 189:f392fc9709a3 275
AnnaBridge 189:f392fc9709a3 276 if ((intsts = PRNG_GET_INT_FLAG()) != 0) {
AnnaBridge 189:f392fc9709a3 277 /* Done with OK */
AnnaBridge 189:f392fc9709a3 278 crypto_prng_done |= CRYPTO_DONE_OK;
AnnaBridge 189:f392fc9709a3 279 /* Clear interrupt flag */
AnnaBridge 189:f392fc9709a3 280 PRNG_CLR_INT_FLAG();
AnnaBridge 189:f392fc9709a3 281 } else if ((intsts = AES_GET_INT_FLAG()) != 0) {
AnnaBridge 189:f392fc9709a3 282 /* Done with OK */
AnnaBridge 189:f392fc9709a3 283 crypto_aes_done |= CRYPTO_DONE_OK;
AnnaBridge 189:f392fc9709a3 284 /* Clear interrupt flag */
AnnaBridge 189:f392fc9709a3 285 AES_CLR_INT_FLAG();
AnnaBridge 189:f392fc9709a3 286 } else if ((intsts = TDES_GET_INT_FLAG()) != 0) {
AnnaBridge 189:f392fc9709a3 287 /* Done with OK */
AnnaBridge 189:f392fc9709a3 288 crypto_des_done |= CRYPTO_DONE_OK;
AnnaBridge 189:f392fc9709a3 289 /* Clear interrupt flag */
AnnaBridge 189:f392fc9709a3 290 TDES_CLR_INT_FLAG();
AnnaBridge 189:f392fc9709a3 291 }
AnnaBridge 189:f392fc9709a3 292 }