mbed library sources. Supersedes mbed-src. Edited target satm32f446 for user USART3 pins

Dependents:   IGLOO_board

Fork of mbed-dev by mbed official

Committer:
Anna Bridge
Date:
Wed Jan 17 15:23:54 2018 +0000
Revision:
180:96ed750bd169
Child:
182:a56a73fd2a6f
mbed-dev libray. Release version 158

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Anna Bridge 180:96ed750bd169 1 /* mbed Microcontroller Library
Anna Bridge 180:96ed750bd169 2 * Copyright (c) 2015-2016 Nuvoton
Anna Bridge 180:96ed750bd169 3 *
Anna Bridge 180:96ed750bd169 4 * Licensed under the Apache License, Version 2.0 (the "License");
Anna Bridge 180:96ed750bd169 5 * you may not use this file except in compliance with the License.
Anna Bridge 180:96ed750bd169 6 * You may obtain a copy of the License at
Anna Bridge 180:96ed750bd169 7 *
Anna Bridge 180:96ed750bd169 8 * http://www.apache.org/licenses/LICENSE-2.0
Anna Bridge 180:96ed750bd169 9 *
Anna Bridge 180:96ed750bd169 10 * Unless required by applicable law or agreed to in writing, software
Anna Bridge 180:96ed750bd169 11 * distributed under the License is distributed on an "AS IS" BASIS,
Anna Bridge 180:96ed750bd169 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Anna Bridge 180:96ed750bd169 13 * See the License for the specific language governing permissions and
Anna Bridge 180:96ed750bd169 14 * limitations under the License.
Anna Bridge 180:96ed750bd169 15 */
Anna Bridge 180:96ed750bd169 16
Anna Bridge 180:96ed750bd169 17
Anna Bridge 180:96ed750bd169 18 #include "cmsis.h"
Anna Bridge 180:96ed750bd169 19 #include "mbed_assert.h"
Anna Bridge 180:96ed750bd169 20 #include "mbed_critical.h"
Anna Bridge 180:96ed750bd169 21 #include "mbed_error.h"
Anna Bridge 180:96ed750bd169 22 #include <limits.h>
Anna Bridge 180:96ed750bd169 23 #include "nu_modutil.h"
Anna Bridge 180:96ed750bd169 24 #include "nu_bitutil.h"
Anna Bridge 180:96ed750bd169 25 #include "crypto-misc.h"
Anna Bridge 180:96ed750bd169 26
Anna Bridge 180:96ed750bd169 27 /* Track if AES H/W is available */
Anna Bridge 180:96ed750bd169 28 static uint16_t crypto_aes_avail = 1;
Anna Bridge 180:96ed750bd169 29 /* Track if DES H/W is available */
Anna Bridge 180:96ed750bd169 30 static uint16_t crypto_des_avail = 1;
Anna Bridge 180:96ed750bd169 31 /* Track if SHA H/W is available */
Anna Bridge 180:96ed750bd169 32 static uint16_t crypto_sha_avail = 1;
Anna Bridge 180:96ed750bd169 33
Anna Bridge 180:96ed750bd169 34 /* Crypto (AES, DES, SHA, etc.) init counter. Crypto's keeps active as it is non-zero. */
Anna Bridge 180:96ed750bd169 35 static uint16_t crypto_init_counter = 0U;
Anna Bridge 180:96ed750bd169 36
Anna Bridge 180:96ed750bd169 37 static bool crypto_submodule_acquire(uint16_t *submodule_avail);
Anna Bridge 180:96ed750bd169 38 static void crypto_submodule_release(uint16_t *submodule_avail);
Anna Bridge 180:96ed750bd169 39
Anna Bridge 180:96ed750bd169 40 /* Track if PRNG H/W operation is done */
Anna Bridge 180:96ed750bd169 41 static volatile uint16_t crypto_prng_done;
Anna Bridge 180:96ed750bd169 42 /* Track if AES H/W operation is done */
Anna Bridge 180:96ed750bd169 43 static volatile uint16_t crypto_aes_done;
Anna Bridge 180:96ed750bd169 44 /* Track if DES H/W operation is done */
Anna Bridge 180:96ed750bd169 45 static volatile uint16_t crypto_des_done;
Anna Bridge 180:96ed750bd169 46
Anna Bridge 180:96ed750bd169 47 static void crypto_submodule_prestart(volatile uint16_t *submodule_done);
Anna Bridge 180:96ed750bd169 48 static bool crypto_submodule_wait(volatile uint16_t *submodule_done);
Anna Bridge 180:96ed750bd169 49
Anna Bridge 180:96ed750bd169 50 /* As crypto init counter changes from 0 to 1:
Anna Bridge 180:96ed750bd169 51 *
Anna Bridge 180:96ed750bd169 52 * 1. Enable crypto clock
Anna Bridge 180:96ed750bd169 53 * 2. Enable crypto interrupt
Anna Bridge 180:96ed750bd169 54 */
Anna Bridge 180:96ed750bd169 55 void crypto_init(void)
Anna Bridge 180:96ed750bd169 56 {
Anna Bridge 180:96ed750bd169 57 core_util_critical_section_enter();
Anna Bridge 180:96ed750bd169 58 if (crypto_init_counter == USHRT_MAX) {
Anna Bridge 180:96ed750bd169 59 core_util_critical_section_exit();
Anna Bridge 180:96ed750bd169 60 error("Crypto clock enable counter would overflow (> USHRT_MAX)");
Anna Bridge 180:96ed750bd169 61 }
Anna Bridge 180:96ed750bd169 62 core_util_atomic_incr_u16(&crypto_init_counter, 1);
Anna Bridge 180:96ed750bd169 63 if (crypto_init_counter == 1) {
Anna Bridge 180:96ed750bd169 64 SYS_UnlockReg(); // Unlock protected register
Anna Bridge 180:96ed750bd169 65 CLK_EnableModuleClock(CRPT_MODULE);
Anna Bridge 180:96ed750bd169 66 SYS_LockReg(); // Lock protected register
Anna Bridge 180:96ed750bd169 67
Anna Bridge 180:96ed750bd169 68 NVIC_EnableIRQ(CRPT_IRQn);
Anna Bridge 180:96ed750bd169 69 }
Anna Bridge 180:96ed750bd169 70 core_util_critical_section_exit();
Anna Bridge 180:96ed750bd169 71 }
Anna Bridge 180:96ed750bd169 72
Anna Bridge 180:96ed750bd169 73 /* As crypto init counter changes from 1 to 0:
Anna Bridge 180:96ed750bd169 74 *
Anna Bridge 180:96ed750bd169 75 * 1. Disable crypto interrupt
Anna Bridge 180:96ed750bd169 76 * 2. Disable crypto clock
Anna Bridge 180:96ed750bd169 77 */
Anna Bridge 180:96ed750bd169 78 void crypto_uninit(void)
Anna Bridge 180:96ed750bd169 79 {
Anna Bridge 180:96ed750bd169 80 core_util_critical_section_enter();
Anna Bridge 180:96ed750bd169 81 if (crypto_init_counter == 0) {
Anna Bridge 180:96ed750bd169 82 core_util_critical_section_exit();
Anna Bridge 180:96ed750bd169 83 error("Crypto clock enable counter would underflow (< 0)");
Anna Bridge 180:96ed750bd169 84 }
Anna Bridge 180:96ed750bd169 85 core_util_atomic_decr_u16(&crypto_init_counter, 1);
Anna Bridge 180:96ed750bd169 86 if (crypto_init_counter == 0) {
Anna Bridge 180:96ed750bd169 87 NVIC_DisableIRQ(CRPT_IRQn);
Anna Bridge 180:96ed750bd169 88
Anna Bridge 180:96ed750bd169 89 SYS_UnlockReg(); // Unlock protected register
Anna Bridge 180:96ed750bd169 90 CLK_DisableModuleClock(CRPT_MODULE);
Anna Bridge 180:96ed750bd169 91 SYS_LockReg(); // Lock protected register
Anna Bridge 180:96ed750bd169 92 }
Anna Bridge 180:96ed750bd169 93 core_util_critical_section_exit();
Anna Bridge 180:96ed750bd169 94 }
Anna Bridge 180:96ed750bd169 95
Anna Bridge 180:96ed750bd169 96 /* Implementation that should never be optimized out by the compiler */
Anna Bridge 180:96ed750bd169 97 void crypto_zeroize(void *v, size_t n)
Anna Bridge 180:96ed750bd169 98 {
Anna Bridge 180:96ed750bd169 99 volatile unsigned char *p = (unsigned char*) v;
Anna Bridge 180:96ed750bd169 100 while (n--) {
Anna Bridge 180:96ed750bd169 101 *p++ = 0;
Anna Bridge 180:96ed750bd169 102 }
Anna Bridge 180:96ed750bd169 103 }
Anna Bridge 180:96ed750bd169 104
Anna Bridge 180:96ed750bd169 105 bool crypto_aes_acquire(void)
Anna Bridge 180:96ed750bd169 106 {
Anna Bridge 180:96ed750bd169 107 return crypto_submodule_acquire(&crypto_aes_avail);
Anna Bridge 180:96ed750bd169 108 }
Anna Bridge 180:96ed750bd169 109
Anna Bridge 180:96ed750bd169 110 void crypto_aes_release(void)
Anna Bridge 180:96ed750bd169 111 {
Anna Bridge 180:96ed750bd169 112 crypto_submodule_release(&crypto_aes_avail);
Anna Bridge 180:96ed750bd169 113 }
Anna Bridge 180:96ed750bd169 114
Anna Bridge 180:96ed750bd169 115 bool crypto_des_acquire(void)
Anna Bridge 180:96ed750bd169 116 {
Anna Bridge 180:96ed750bd169 117 return crypto_submodule_acquire(&crypto_des_avail);
Anna Bridge 180:96ed750bd169 118 }
Anna Bridge 180:96ed750bd169 119
Anna Bridge 180:96ed750bd169 120 void crypto_des_release(void)
Anna Bridge 180:96ed750bd169 121 {
Anna Bridge 180:96ed750bd169 122 crypto_submodule_release(&crypto_des_avail);
Anna Bridge 180:96ed750bd169 123 }
Anna Bridge 180:96ed750bd169 124
Anna Bridge 180:96ed750bd169 125 bool crypto_sha_acquire(void)
Anna Bridge 180:96ed750bd169 126 {
Anna Bridge 180:96ed750bd169 127 return crypto_submodule_acquire(&crypto_sha_avail);
Anna Bridge 180:96ed750bd169 128 }
Anna Bridge 180:96ed750bd169 129
Anna Bridge 180:96ed750bd169 130 void crypto_sha_release(void)
Anna Bridge 180:96ed750bd169 131 {
Anna Bridge 180:96ed750bd169 132 crypto_submodule_release(&crypto_sha_avail);
Anna Bridge 180:96ed750bd169 133 }
Anna Bridge 180:96ed750bd169 134
Anna Bridge 180:96ed750bd169 135 void crypto_prng_prestart(void)
Anna Bridge 180:96ed750bd169 136 {
Anna Bridge 180:96ed750bd169 137 crypto_submodule_prestart(&crypto_prng_done);
Anna Bridge 180:96ed750bd169 138 }
Anna Bridge 180:96ed750bd169 139
Anna Bridge 180:96ed750bd169 140 bool crypto_prng_wait(void)
Anna Bridge 180:96ed750bd169 141 {
Anna Bridge 180:96ed750bd169 142 return crypto_submodule_wait(&crypto_prng_done);
Anna Bridge 180:96ed750bd169 143 }
Anna Bridge 180:96ed750bd169 144
Anna Bridge 180:96ed750bd169 145 void crypto_aes_prestart(void)
Anna Bridge 180:96ed750bd169 146 {
Anna Bridge 180:96ed750bd169 147 crypto_submodule_prestart(&crypto_aes_done);
Anna Bridge 180:96ed750bd169 148 }
Anna Bridge 180:96ed750bd169 149
Anna Bridge 180:96ed750bd169 150 bool crypto_aes_wait(void)
Anna Bridge 180:96ed750bd169 151 {
Anna Bridge 180:96ed750bd169 152 return crypto_submodule_wait(&crypto_aes_done);
Anna Bridge 180:96ed750bd169 153 }
Anna Bridge 180:96ed750bd169 154
Anna Bridge 180:96ed750bd169 155 void crypto_des_prestart(void)
Anna Bridge 180:96ed750bd169 156 {
Anna Bridge 180:96ed750bd169 157 crypto_submodule_prestart(&crypto_des_done);
Anna Bridge 180:96ed750bd169 158 }
Anna Bridge 180:96ed750bd169 159
Anna Bridge 180:96ed750bd169 160 bool crypto_des_wait(void)
Anna Bridge 180:96ed750bd169 161 {
Anna Bridge 180:96ed750bd169 162 return crypto_submodule_wait(&crypto_des_done);
Anna Bridge 180:96ed750bd169 163 }
Anna Bridge 180:96ed750bd169 164
Anna Bridge 180:96ed750bd169 165 bool crypto_dma_buff_compat(const void *buff, size_t buff_size, size_t size_aligned_to)
Anna Bridge 180:96ed750bd169 166 {
Anna Bridge 180:96ed750bd169 167 uint32_t buff_ = (uint32_t) buff;
Anna Bridge 180:96ed750bd169 168
Anna Bridge 180:96ed750bd169 169 return (((buff_ & 0x03) == 0) && /* Word-aligned buffer base address */
Anna Bridge 180:96ed750bd169 170 ((buff_size & (size_aligned_to - 1)) == 0) && /* Crypto submodule dependent buffer size alignment */
Anna Bridge 180:96ed750bd169 171 (((buff_ >> 28) == 0x2) && (buff_size <= (0x30000000 - buff_)))); /* 0x20000000-0x2FFFFFFF */
Anna Bridge 180:96ed750bd169 172 }
Anna Bridge 180:96ed750bd169 173
Anna Bridge 180:96ed750bd169 174 /* Overlap cases
Anna Bridge 180:96ed750bd169 175 *
Anna Bridge 180:96ed750bd169 176 * 1. in_buff in front of out_buff:
Anna Bridge 180:96ed750bd169 177 *
Anna Bridge 180:96ed750bd169 178 * in in_end
Anna Bridge 180:96ed750bd169 179 * | |
Anna Bridge 180:96ed750bd169 180 * ||||||||||||||||
Anna Bridge 180:96ed750bd169 181 * ||||||||||||||||
Anna Bridge 180:96ed750bd169 182 * | |
Anna Bridge 180:96ed750bd169 183 * out out_end
Anna Bridge 180:96ed750bd169 184 *
Anna Bridge 180:96ed750bd169 185 * 2. out_buff in front of in_buff:
Anna Bridge 180:96ed750bd169 186 *
Anna Bridge 180:96ed750bd169 187 * in in_end
Anna Bridge 180:96ed750bd169 188 * | |
Anna Bridge 180:96ed750bd169 189 * ||||||||||||||||
Anna Bridge 180:96ed750bd169 190 * ||||||||||||||||
Anna Bridge 180:96ed750bd169 191 * | |
Anna Bridge 180:96ed750bd169 192 * out out_end
Anna Bridge 180:96ed750bd169 193 */
Anna Bridge 180:96ed750bd169 194 bool crypto_dma_buffs_overlap(const void *in_buff, size_t in_buff_size, const void *out_buff, size_t out_buff_size)
Anna Bridge 180:96ed750bd169 195 {
Anna Bridge 180:96ed750bd169 196 uint32_t in = (uint32_t) in_buff;
Anna Bridge 180:96ed750bd169 197 uint32_t in_end = in + in_buff_size;
Anna Bridge 180:96ed750bd169 198 uint32_t out = (uint32_t) out_buff;
Anna Bridge 180:96ed750bd169 199 uint32_t out_end = out + out_buff_size;
Anna Bridge 180:96ed750bd169 200
Anna Bridge 180:96ed750bd169 201 bool overlap = (in <= out && out < in_end) || (out <= in && in < out_end);
Anna Bridge 180:96ed750bd169 202
Anna Bridge 180:96ed750bd169 203 return overlap;
Anna Bridge 180:96ed750bd169 204 }
Anna Bridge 180:96ed750bd169 205
Anna Bridge 180:96ed750bd169 206 static bool crypto_submodule_acquire(uint16_t *submodule_avail)
Anna Bridge 180:96ed750bd169 207 {
Anna Bridge 180:96ed750bd169 208 uint16_t expectedCurrentValue = 1;
Anna Bridge 180:96ed750bd169 209 return core_util_atomic_cas_u16(submodule_avail, &expectedCurrentValue, 0);
Anna Bridge 180:96ed750bd169 210 }
Anna Bridge 180:96ed750bd169 211
Anna Bridge 180:96ed750bd169 212 static void crypto_submodule_release(uint16_t *submodule_avail)
Anna Bridge 180:96ed750bd169 213 {
Anna Bridge 180:96ed750bd169 214 uint16_t expectedCurrentValue = 0;
Anna Bridge 180:96ed750bd169 215 while (! core_util_atomic_cas_u16(submodule_avail, &expectedCurrentValue, 1));
Anna Bridge 180:96ed750bd169 216 }
Anna Bridge 180:96ed750bd169 217
Anna Bridge 180:96ed750bd169 218 static void crypto_submodule_prestart(volatile uint16_t *submodule_done)
Anna Bridge 180:96ed750bd169 219 {
Anna Bridge 180:96ed750bd169 220 *submodule_done = 0;
Anna Bridge 180:96ed750bd169 221
Anna Bridge 180:96ed750bd169 222 /* Ensure memory accesses above are completed before DMA is started
Anna Bridge 180:96ed750bd169 223 *
Anna Bridge 180:96ed750bd169 224 * Replacing __DSB() with __DMB() is also OK in this case.
Anna Bridge 180:96ed750bd169 225 *
Anna Bridge 180:96ed750bd169 226 * Refer to "multi-master systems" section with DMA in:
Anna Bridge 180:96ed750bd169 227 * https://static.docs.arm.com/dai0321/a/DAI0321A_programming_guide_memory_barriers_for_m_profile.pdf
Anna Bridge 180:96ed750bd169 228 */
Anna Bridge 180:96ed750bd169 229 __DSB();
Anna Bridge 180:96ed750bd169 230 }
Anna Bridge 180:96ed750bd169 231
Anna Bridge 180:96ed750bd169 232 static bool crypto_submodule_wait(volatile uint16_t *submodule_done)
Anna Bridge 180:96ed750bd169 233 {
Anna Bridge 180:96ed750bd169 234 while (! *submodule_done);
Anna Bridge 180:96ed750bd169 235
Anna Bridge 180:96ed750bd169 236 /* Ensure while loop above and subsequent code are not reordered */
Anna Bridge 180:96ed750bd169 237 __DSB();
Anna Bridge 180:96ed750bd169 238
Anna Bridge 180:96ed750bd169 239 return true;
Anna Bridge 180:96ed750bd169 240 }
Anna Bridge 180:96ed750bd169 241
Anna Bridge 180:96ed750bd169 242 /* Crypto interrupt handler */
Anna Bridge 180:96ed750bd169 243 void CRYPTO_IRQHandler()
Anna Bridge 180:96ed750bd169 244 {
Anna Bridge 180:96ed750bd169 245 if (PRNG_GET_INT_FLAG()) {
Anna Bridge 180:96ed750bd169 246 crypto_prng_done = 1;
Anna Bridge 180:96ed750bd169 247 PRNG_CLR_INT_FLAG();
Anna Bridge 180:96ed750bd169 248 } else if (AES_GET_INT_FLAG()) {
Anna Bridge 180:96ed750bd169 249 crypto_aes_done = 1;
Anna Bridge 180:96ed750bd169 250 AES_CLR_INT_FLAG();
Anna Bridge 180:96ed750bd169 251 } else if (TDES_GET_INT_FLAG()) {
Anna Bridge 180:96ed750bd169 252 crypto_des_done = 1;
Anna Bridge 180:96ed750bd169 253 TDES_CLR_INT_FLAG();
Anna Bridge 180:96ed750bd169 254 }
Anna Bridge 180:96ed750bd169 255 }