helpfor studient

Dependents:   STM32_F103-C8T6basecanblink_led

Fork of mbed-dev by mbed official

Committer:
AnnaBridge
Date:
Tue Mar 20 16:56:18 2018 +0000
Revision:
183:a56a73fd2a6f
Parent:
181:96ed750bd169
mbed-dev library. Release version 160

Who changed what in which revision?

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