diff --git a/features/mbedtls/targets/TARGET_NUVOTON/TARGET_M480/aes/aes_alt.c b/features/mbedtls/targets/TARGET_NUVOTON/TARGET_M480/aes/aes_alt.c index 725f95c58f..855d415f78 100644 --- a/features/mbedtls/targets/TARGET_NUVOTON/TARGET_M480/aes/aes_alt.c +++ b/features/mbedtls/targets/TARGET_NUVOTON/TARGET_M480/aes/aes_alt.c @@ -176,17 +176,9 @@ static void __nvt_aes_crypt( mbedtls_aes_context *ctx, AES_SetDMATransfer(0, (uint32_t)pIn, (uint32_t)pOut, dataSize); - g_AES_done = 0; - /* Ensure memory accesses above are completed before DMA is started - * - * Replacing __DSB() with __DMB() is also OK in this case. - * - * Refer to "multi-master systems" section with DMA in: - * https://static.docs.arm.com/dai0321/a/DAI0321A_programming_guide_memory_barriers_for_m_profile.pdf - */ - __DSB(); + crypto_aes_prestart(); AES_Start(0, CRYPTO_DMA_ONE_SHOT); - while (!g_AES_done); + crypto_aes_wait(); if( pOut != output ) { memcpy(output, au8OutputData, dataSize); diff --git a/features/mbedtls/targets/TARGET_NUVOTON/TARGET_NUC472/aes/aes_alt.c b/features/mbedtls/targets/TARGET_NUVOTON/TARGET_NUC472/aes/aes_alt.c index 67df8f5425..f8a1c97d5e 100644 --- a/features/mbedtls/targets/TARGET_NUVOTON/TARGET_NUC472/aes/aes_alt.c +++ b/features/mbedtls/targets/TARGET_NUVOTON/TARGET_NUC472/aes/aes_alt.c @@ -176,17 +176,9 @@ static void __nvt_aes_crypt( mbedtls_aes_context *ctx, AES_SetDMATransfer(0, (uint32_t)pIn, (uint32_t)pOut, dataSize); - g_AES_done = 0; - /* Ensure memory accesses above are completed before DMA is started - * - * Replacing __DSB() with __DMB() is also OK in this case. - * - * Refer to "multi-master systems" section with DMA in: - * https://static.docs.arm.com/dai0321/a/DAI0321A_programming_guide_memory_barriers_for_m_profile.pdf - */ - __DSB(); + crypto_aes_prestart(); AES_Start(0, CRYPTO_DMA_ONE_SHOT); - while (!g_AES_done); + crypto_aes_wait(); if( pOut != output ) { memcpy(output, au8OutputData, dataSize); diff --git a/targets/TARGET_NUVOTON/TARGET_M480/crypto/crypto-misc.c b/targets/TARGET_NUVOTON/TARGET_M480/crypto/crypto-misc.c index 4c4c52d04f..bc7a58a30c 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/crypto/crypto-misc.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/crypto/crypto-misc.c @@ -24,9 +24,6 @@ #include "nu_bitutil.h" #include "crypto-misc.h" -volatile int g_PRNG_done; -volatile int g_AES_done; - /* Track if AES H/W is available */ static uint16_t crypto_aes_avail = 1; /* Track if DES H/W is available */ @@ -40,6 +37,14 @@ static uint16_t crypto_init_counter = 0U; static bool crypto_submodule_acquire(uint16_t *submodule_avail); static void crypto_submodule_release(uint16_t *submodule_avail); +/* Track if PRNG H/W operation is done */ +static volatile uint16_t crypto_prng_done; +/* Track if AES H/W operation is done */ +static volatile uint16_t crypto_aes_done; + +static void crypto_submodule_prestart(volatile uint16_t *submodule_done); +static bool crypto_submodule_wait(volatile uint16_t *submodule_done); + /* As crypto init counter changes from 0 to 1: * * 1. Enable crypto clock @@ -125,6 +130,26 @@ void crypto_sha_release(void) crypto_submodule_release(&crypto_sha_avail); } +void crypto_prng_prestart(void) +{ + crypto_submodule_prestart(&crypto_prng_done); +} + +bool crypto_prng_wait(void) +{ + return crypto_submodule_wait(&crypto_prng_done); +} + +void crypto_aes_prestart(void) +{ + crypto_submodule_prestart(&crypto_aes_done); +} + +bool crypto_aes_wait(void) +{ + return crypto_submodule_wait(&crypto_aes_done); +} + bool crypto_dma_buff_compat(const void *buff, size_t buff_size, size_t size_aligned_to) { uint32_t buff_ = (uint32_t) buff; @@ -146,14 +171,35 @@ static void crypto_submodule_release(uint16_t *submodule_avail) while (! core_util_atomic_cas_u16(submodule_avail, &expectedCurrentValue, 1)); } +static void crypto_submodule_prestart(volatile uint16_t *submodule_done) +{ + *submodule_done = 0; + + /* Ensure memory accesses above are completed before DMA is started + * + * Replacing __DSB() with __DMB() is also OK in this case. + * + * Refer to "multi-master systems" section with DMA in: + * https://static.docs.arm.com/dai0321/a/DAI0321A_programming_guide_memory_barriers_for_m_profile.pdf + */ + __DSB(); +} + +static bool crypto_submodule_wait(volatile uint16_t *submodule_done) +{ + while (! *submodule_done); + + return true; +} + /* Crypto interrupt handler */ void CRYPTO_IRQHandler() { if (PRNG_GET_INT_FLAG()) { - g_PRNG_done = 1; + crypto_prng_done = 1; PRNG_CLR_INT_FLAG(); } else if (AES_GET_INT_FLAG()) { - g_AES_done = 1; + crypto_aes_done = 1; AES_CLR_INT_FLAG(); } } diff --git a/targets/TARGET_NUVOTON/TARGET_M480/crypto/crypto-misc.h b/targets/TARGET_NUVOTON/TARGET_M480/crypto/crypto-misc.h index 4bee4f644c..bec4a96ba5 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/crypto/crypto-misc.h +++ b/targets/TARGET_NUVOTON/TARGET_M480/crypto/crypto-misc.h @@ -23,14 +23,6 @@ extern "C" { #endif -/* Flags to indicate crypto H/W operation has done - * - * Crypto driver would clear it before trigger and wait for it. - * Crypto interrupt handler would set it on done or error. - */ -extern volatile int g_PRNG_done; -extern volatile int g_AES_done; - /* Init/Uninit crypto module */ void crypto_init(void); void crypto_uninit(void); @@ -54,6 +46,27 @@ void crypto_des_release(void); bool crypto_sha_acquire(void); void crypto_sha_release(void); +/* Flow control between crypto/xxx start and crypto/xxx ISR + * + * crypto_xxx_prestart/crypto_xxx_wait encapsulate control flow between crypto/xxx start and crypto/xxx ISR. + * + * crypto_xxx_prestart will also address synchronization issue with memory barrier instruction. + * + * On finish, return of crypto_xxx_wait indicates success or not: + * true if successful + * false if failed + * + * Example: Start AES H/W and wait for its finish + * crypto_aes_prestart(); + * AES_Start(); + * crypto_aes_wait(); + */ +void crypto_prng_prestart(void); +bool crypto_prng_wait(void); +void crypto_aes_prestart(void); +bool crypto_aes_wait(void); + + /* Check if buffer can be used for crypto DMA. It has the following requirements: * (1) Word-aligned buffer base address * (2) Crypto submodule (AES, DES, SHA, etc.) dependent buffer size alignment. Must be 2 power. diff --git a/targets/TARGET_NUVOTON/TARGET_M480/trng_api.c b/targets/TARGET_NUVOTON/TARGET_M480/trng_api.c index eeb0a34730..305be2bd21 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/trng_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/trng_api.c @@ -36,8 +36,9 @@ static void trng_get(unsigned char *pConversionData) p32ConversionData = (uint32_t *)pConversionData; PRNG_Open(PRNG_KEY_SIZE_256, 1, us_ticker_read()); + crypto_prng_prestart(); PRNG_Start(); - while (!g_PRNG_done); + crypto_prng_wait(); PRNG_Read(p32ConversionData); } @@ -85,4 +86,3 @@ int trng_get_bytes(trng_t *obj, uint8_t *output, size_t length, size_t *output_l } #endif - diff --git a/targets/TARGET_NUVOTON/TARGET_NUC472/crypto/crypto-misc.c b/targets/TARGET_NUVOTON/TARGET_NUC472/crypto/crypto-misc.c index 4c4c52d04f..bc7a58a30c 100644 --- a/targets/TARGET_NUVOTON/TARGET_NUC472/crypto/crypto-misc.c +++ b/targets/TARGET_NUVOTON/TARGET_NUC472/crypto/crypto-misc.c @@ -24,9 +24,6 @@ #include "nu_bitutil.h" #include "crypto-misc.h" -volatile int g_PRNG_done; -volatile int g_AES_done; - /* Track if AES H/W is available */ static uint16_t crypto_aes_avail = 1; /* Track if DES H/W is available */ @@ -40,6 +37,14 @@ static uint16_t crypto_init_counter = 0U; static bool crypto_submodule_acquire(uint16_t *submodule_avail); static void crypto_submodule_release(uint16_t *submodule_avail); +/* Track if PRNG H/W operation is done */ +static volatile uint16_t crypto_prng_done; +/* Track if AES H/W operation is done */ +static volatile uint16_t crypto_aes_done; + +static void crypto_submodule_prestart(volatile uint16_t *submodule_done); +static bool crypto_submodule_wait(volatile uint16_t *submodule_done); + /* As crypto init counter changes from 0 to 1: * * 1. Enable crypto clock @@ -125,6 +130,26 @@ void crypto_sha_release(void) crypto_submodule_release(&crypto_sha_avail); } +void crypto_prng_prestart(void) +{ + crypto_submodule_prestart(&crypto_prng_done); +} + +bool crypto_prng_wait(void) +{ + return crypto_submodule_wait(&crypto_prng_done); +} + +void crypto_aes_prestart(void) +{ + crypto_submodule_prestart(&crypto_aes_done); +} + +bool crypto_aes_wait(void) +{ + return crypto_submodule_wait(&crypto_aes_done); +} + bool crypto_dma_buff_compat(const void *buff, size_t buff_size, size_t size_aligned_to) { uint32_t buff_ = (uint32_t) buff; @@ -146,14 +171,35 @@ static void crypto_submodule_release(uint16_t *submodule_avail) while (! core_util_atomic_cas_u16(submodule_avail, &expectedCurrentValue, 1)); } +static void crypto_submodule_prestart(volatile uint16_t *submodule_done) +{ + *submodule_done = 0; + + /* Ensure memory accesses above are completed before DMA is started + * + * Replacing __DSB() with __DMB() is also OK in this case. + * + * Refer to "multi-master systems" section with DMA in: + * https://static.docs.arm.com/dai0321/a/DAI0321A_programming_guide_memory_barriers_for_m_profile.pdf + */ + __DSB(); +} + +static bool crypto_submodule_wait(volatile uint16_t *submodule_done) +{ + while (! *submodule_done); + + return true; +} + /* Crypto interrupt handler */ void CRYPTO_IRQHandler() { if (PRNG_GET_INT_FLAG()) { - g_PRNG_done = 1; + crypto_prng_done = 1; PRNG_CLR_INT_FLAG(); } else if (AES_GET_INT_FLAG()) { - g_AES_done = 1; + crypto_aes_done = 1; AES_CLR_INT_FLAG(); } } diff --git a/targets/TARGET_NUVOTON/TARGET_NUC472/crypto/crypto-misc.h b/targets/TARGET_NUVOTON/TARGET_NUC472/crypto/crypto-misc.h index 4bee4f644c..bec4a96ba5 100644 --- a/targets/TARGET_NUVOTON/TARGET_NUC472/crypto/crypto-misc.h +++ b/targets/TARGET_NUVOTON/TARGET_NUC472/crypto/crypto-misc.h @@ -23,14 +23,6 @@ extern "C" { #endif -/* Flags to indicate crypto H/W operation has done - * - * Crypto driver would clear it before trigger and wait for it. - * Crypto interrupt handler would set it on done or error. - */ -extern volatile int g_PRNG_done; -extern volatile int g_AES_done; - /* Init/Uninit crypto module */ void crypto_init(void); void crypto_uninit(void); @@ -54,6 +46,27 @@ void crypto_des_release(void); bool crypto_sha_acquire(void); void crypto_sha_release(void); +/* Flow control between crypto/xxx start and crypto/xxx ISR + * + * crypto_xxx_prestart/crypto_xxx_wait encapsulate control flow between crypto/xxx start and crypto/xxx ISR. + * + * crypto_xxx_prestart will also address synchronization issue with memory barrier instruction. + * + * On finish, return of crypto_xxx_wait indicates success or not: + * true if successful + * false if failed + * + * Example: Start AES H/W and wait for its finish + * crypto_aes_prestart(); + * AES_Start(); + * crypto_aes_wait(); + */ +void crypto_prng_prestart(void); +bool crypto_prng_wait(void); +void crypto_aes_prestart(void); +bool crypto_aes_wait(void); + + /* Check if buffer can be used for crypto DMA. It has the following requirements: * (1) Word-aligned buffer base address * (2) Crypto submodule (AES, DES, SHA, etc.) dependent buffer size alignment. Must be 2 power. diff --git a/targets/TARGET_NUVOTON/TARGET_NUC472/trng_api.c b/targets/TARGET_NUVOTON/TARGET_NUC472/trng_api.c index b705b7c585..153e1ef42c 100644 --- a/targets/TARGET_NUVOTON/TARGET_NUC472/trng_api.c +++ b/targets/TARGET_NUVOTON/TARGET_NUC472/trng_api.c @@ -23,7 +23,6 @@ #include #include #include "cmsis.h" -#include "NUC472_442.h" #include "us_ticker_api.h" #include "trng_api.h" #include "crypto-misc.h" @@ -41,8 +40,9 @@ static void trng_get(unsigned char *pConversionData) p32ConversionData = (uint32_t *)pConversionData; PRNG_Open(PRNG_KEY_SIZE_256, 1, us_ticker_read()); + crypto_prng_prestart(); PRNG_Start(); - while (!g_PRNG_done); + crypto_prng_wait(); PRNG_Read(p32ConversionData); } @@ -88,6 +88,5 @@ int trng_get_bytes(trng_t *obj, uint8_t *output, size_t length, size_t *output_l *output_length = cur_length; return 0; } - -#endif +#endif