From 41f4e1a12c6ceb50b2fa9c9180f7597a874a5623 Mon Sep 17 00:00:00 2001 From: ccli8 Date: Tue, 26 Sep 2017 14:16:35 +0800 Subject: [PATCH] Coordinate crypto init among AES/DES/SHA/PRNG Add counter to track crypto init among crypto sub-modules. It includes: 1. Enable crypto clock 2. Enable crypto interrupt As counter gets zero, crypto clock is disabled to save power. --- .../TARGET_NUVOTON/TARGET_M480/aes/aes_alt.c | 24 ++++----- .../TARGET_NUVOTON/TARGET_M480/crypto-misc.c | 51 +++++++++++++++++-- .../TARGET_NUVOTON/TARGET_M480/crypto-misc.h | 1 + .../TARGET_NUVOTON/TARGET_M480/des/des_alt.c | 8 ++- .../TARGET_M480/sha/sha_alt_hw.c | 9 ++++ .../TARGET_NUC472/aes/aes_alt.c | 24 ++++----- .../TARGET_NUC472/crypto-misc.c | 51 +++++++++++++++++-- .../TARGET_NUC472/crypto-misc.h | 1 + .../TARGET_NUC472/des/des_alt.c | 8 ++- .../TARGET_NUC472/sha/sha_alt_hw.c | 6 +++ targets/TARGET_NUVOTON/TARGET_M480/trng_api.c | 19 ++++--- .../TARGET_NUVOTON/TARGET_NUC472/trng_api.c | 15 +++--- 12 files changed, 161 insertions(+), 56 deletions(-) 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 878f8d9abb..749c66f8ef 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 @@ -34,8 +34,7 @@ #include "mbed_assert.h" #include "mbed_error.h" #include "nu_bitutil.h" - - +#include "crypto-misc.h" /* Implementation that should never be optimized out by the compiler */ static void mbedtls_zeroize( void *v, size_t n ) @@ -69,15 +68,6 @@ static bool aes_dma_buff_compat(const void *buff, unsigned buff_size) void mbedtls_aes_init( mbedtls_aes_context *ctx ) { memset( ctx, 0, sizeof( mbedtls_aes_context ) ); - - /* Unlock protected registers */ - SYS_UnlockReg(); - CLK_EnableModuleClock(CRPT_MODULE); - /* Lock protected registers */ - SYS_LockReg(); - - NVIC_EnableIRQ(CRPT_IRQn); - AES_ENABLE_INT(); } void mbedtls_aes_free( mbedtls_aes_context *ctx ) @@ -153,6 +143,11 @@ static void __nvt_aes_crypt( mbedtls_aes_context *ctx, error("Buffer for AES alter. DMA requires to be word-aligned and located in 0x20000000-0x2FFFFFFF region."); } + /* Init crypto module */ + crypto_init(); + /* Enable AES interrupt */ + AES_ENABLE_INT(); + /* We support multiple contexts with context save & restore and so needs just one * H/W channel. Always use H/W channel #0. */ @@ -182,7 +177,7 @@ static void __nvt_aes_crypt( mbedtls_aes_context *ctx, g_AES_done = 0; AES_Start(0, CRYPTO_DMA_ONE_SHOT); while (!g_AES_done); - + if( pOut != output ) { if (dataSize > MAX_DMA_CHAIN_SIZE) { error("Internal AES alter. error. DMA buffer is too small."); @@ -195,6 +190,11 @@ static void __nvt_aes_crypt( mbedtls_aes_context *ctx, ctx->iv[1] = CRPT->AES_FDBCK[1]; ctx->iv[2] = CRPT->AES_FDBCK[2]; ctx->iv[3] = CRPT->AES_FDBCK[3]; + + /* Disable AES interrupt */ + AES_DISABLE_INT(); + /* Uninit crypto module */ + crypto_uninit(); } /* diff --git a/features/mbedtls/targets/TARGET_NUVOTON/TARGET_M480/crypto-misc.c b/features/mbedtls/targets/TARGET_NUVOTON/TARGET_M480/crypto-misc.c index c5d49bb0dd..42bb503edf 100644 --- a/features/mbedtls/targets/TARGET_NUVOTON/TARGET_M480/crypto-misc.c +++ b/features/mbedtls/targets/TARGET_NUVOTON/TARGET_M480/crypto-misc.c @@ -17,21 +17,62 @@ #include "cmsis.h" #include "mbed_assert.h" +#include "mbed_critical.h" +#include "mbed_error.h" +#include #include "nu_modutil.h" #include "nu_bitutil.h" #include "crypto-misc.h" -static int crypto_inited = 0; static int crypto_sha_avail = 1; +/* Crypto (AES, DES, SHA, etc.) init counter. Crypto's keeps active as it is non-zero. */ +static uint16_t crypto_init_counter = 0U; + +/* As crypto init counter changes from 0 to 1: + * + * 1. Enable crypto clock + * 2. Enable crypto interrupt + */ void crypto_init(void) { - if (crypto_inited) { - return; + core_util_critical_section_enter(); + if (crypto_init_counter == USHRT_MAX) { + core_util_critical_section_exit(); + error("Crypto clock enable counter would overflow (> USHRT_MAX)"); } - crypto_inited = 1; + core_util_atomic_incr_u16(&crypto_init_counter, 1); + if (crypto_init_counter == 1) { + SYS_UnlockReg(); // Unlock protected register + CLK_EnableModuleClock(CRPT_MODULE); + SYS_LockReg(); // Lock protected register + + NVIC_EnableIRQ(CRPT_IRQn); + } + core_util_critical_section_exit(); +} - CLK_EnableModuleClock(CRPT_MODULE); +/* As crypto init counter changes from 1 to 0: + * + * 1. Disable crypto interrupt + * 2. Disable crypto clock + */ +void crypto_uninit(void) +{ + core_util_critical_section_enter(); + if (crypto_init_counter == 0) { + core_util_critical_section_exit(); + error("Crypto clock enable counter would underflow (< 0)"); + } + core_util_atomic_decr_u16(&crypto_init_counter, 1); + if (crypto_init_counter == 0) { + NVIC_DisableIRQ(CRPT_IRQn); + + SYS_UnlockReg(); // Unlock protected register + CLK_DisableModuleClock(CRPT_MODULE); + SYS_LockReg(); // Lock protected register + } + core_util_critical_section_exit(); } /* Implementation that should never be optimized out by the compiler */ diff --git a/features/mbedtls/targets/TARGET_NUVOTON/TARGET_M480/crypto-misc.h b/features/mbedtls/targets/TARGET_NUVOTON/TARGET_M480/crypto-misc.h index 8d55449712..a6d2f70bb4 100644 --- a/features/mbedtls/targets/TARGET_NUVOTON/TARGET_M480/crypto-misc.h +++ b/features/mbedtls/targets/TARGET_NUVOTON/TARGET_M480/crypto-misc.h @@ -22,6 +22,7 @@ extern "C" { #endif void crypto_init(void); +void crypto_uninit(void); void crypto_zeroize(void *v, size_t n); int crypto_sha_acquire(void); void crypto_sha_release(void); diff --git a/features/mbedtls/targets/TARGET_NUVOTON/TARGET_M480/des/des_alt.c b/features/mbedtls/targets/TARGET_NUVOTON/TARGET_M480/des/des_alt.c index e8ca4624a1..078af8e172 100644 --- a/features/mbedtls/targets/TARGET_NUVOTON/TARGET_M480/des/des_alt.c +++ b/features/mbedtls/targets/TARGET_NUVOTON/TARGET_M480/des/des_alt.c @@ -49,7 +49,6 @@ static int mbedtls_des_docrypt(uint16_t keyopt, uint8_t key[3][MBEDTLS_DES_KEY_S void mbedtls_des_init(mbedtls_des_context *ctx) { - crypto_init(); memset(ctx, 0, sizeof(mbedtls_des_context)); } @@ -64,7 +63,6 @@ void mbedtls_des_free( mbedtls_des_context *ctx ) void mbedtls_des3_init( mbedtls_des3_context *ctx ) { - crypto_init(); memset(ctx, 0, sizeof(mbedtls_des3_context)); } @@ -329,6 +327,9 @@ static int mbedtls_des_docrypt(uint16_t keyopt, uint8_t key[3][MBEDTLS_DES_KEY_S error("Buffer for DES alter. DMA requires to be word-aligned and located in 0x20000000-0x2FFFFFFF region."); } + /* Init crypto module */ + crypto_init(); + // NOTE: Don't call driver function TDES_Open in BSP because it doesn't support TDES_CTL[3KEYS] setting. CRPT->TDES_CTL = (0 << CRPT_TDES_CTL_CHANNEL_Pos) | (enc << CRPT_TDES_CTL_ENCRPT_Pos) | tdes_opmode | (TDES_IN_OUT_WHL_SWAP << CRPT_TDES_CTL_BLKSWAP_Pos); @@ -418,6 +419,9 @@ static int mbedtls_des_docrypt(uint16_t keyopt, uint8_t key[3][MBEDTLS_DES_KEY_S } } + /* Uninit crypto module */ + crypto_uninit(); + return 0; } diff --git a/features/mbedtls/targets/TARGET_NUVOTON/TARGET_M480/sha/sha_alt_hw.c b/features/mbedtls/targets/TARGET_NUVOTON/TARGET_M480/sha/sha_alt_hw.c index 521165383a..57fc0139b1 100644 --- a/features/mbedtls/targets/TARGET_NUVOTON/TARGET_M480/sha/sha_alt_hw.c +++ b/features/mbedtls/targets/TARGET_NUVOTON/TARGET_M480/sha/sha_alt_hw.c @@ -39,6 +39,7 @@ void crypto_sha_getinternstate(unsigned char output[], size_t olen); void mbedtls_sha1_hw_init(crypto_sha_context *ctx) { + /* Init crypto module */ crypto_init(); memset(ctx, 0, sizeof(crypto_sha_context)); } @@ -49,6 +50,8 @@ void mbedtls_sha1_hw_free(crypto_sha_context *ctx) return; } + /* Uninit crypto module */ + crypto_uninit(); crypto_zeroize(ctx, sizeof(crypto_sha_context)); } @@ -113,6 +116,7 @@ void mbedtls_sha1_hw_process(crypto_sha_context *ctx, const unsigned char data[6 void mbedtls_sha256_hw_init(crypto_sha_context *ctx) { + /* Init crypto module */ crypto_init(); memset(ctx, 0, sizeof(crypto_sha_context)); } @@ -123,6 +127,8 @@ void mbedtls_sha256_hw_free(crypto_sha_context *ctx) return; } + /* Uninit crypto module */ + crypto_uninit(); crypto_zeroize(ctx, sizeof(crypto_sha_context)); } @@ -189,6 +195,7 @@ void mbedtls_sha256_hw_process(crypto_sha_context *ctx, const unsigned char data void mbedtls_sha512_hw_init(crypto_sha_context *ctx) { + /* Init crypto module */ crypto_init(); memset(ctx, 0, sizeof(crypto_sha_context)); } @@ -199,6 +206,8 @@ void mbedtls_sha512_hw_free(crypto_sha_context *ctx) return; } + /* Uninit crypto module */ + crypto_uninit(); crypto_zeroize(ctx, sizeof(crypto_sha_context)); } 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 c8bd88e23a..5af0bebacc 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 @@ -34,8 +34,7 @@ #include "mbed_assert.h" #include "mbed_error.h" #include "nu_bitutil.h" - - +#include "crypto-misc.h" /* Implementation that should never be optimized out by the compiler */ static void mbedtls_zeroize( void *v, size_t n ) @@ -69,15 +68,6 @@ static bool aes_dma_buff_compat(const void *buff, unsigned buff_size) void mbedtls_aes_init( mbedtls_aes_context *ctx ) { memset( ctx, 0, sizeof( mbedtls_aes_context ) ); - - /* Unlock protected registers */ - SYS_UnlockReg(); - CLK_EnableModuleClock(CRPT_MODULE); - /* Lock protected registers */ - SYS_LockReg(); - - NVIC_EnableIRQ(CRPT_IRQn); - AES_ENABLE_INT(); } void mbedtls_aes_free( mbedtls_aes_context *ctx ) @@ -153,6 +143,11 @@ static void __nvt_aes_crypt( mbedtls_aes_context *ctx, error("Buffer for AES alter. DMA requires to be word-aligned and located in 0x20000000-0x2FFFFFFF region."); } + /* Init crypto module */ + crypto_init(); + /* Enable AES interrupt */ + AES_ENABLE_INT(); + /* We support multiple contexts with context save & restore and so needs just one * H/W channel. Always use H/W channel #0. */ @@ -182,7 +177,7 @@ static void __nvt_aes_crypt( mbedtls_aes_context *ctx, g_AES_done = 0; AES_Start(0, CRYPTO_DMA_ONE_SHOT); while (!g_AES_done); - + if( pOut != output ) { if (dataSize > MAX_DMA_CHAIN_SIZE) { error("Internal AES alter. error. DMA buffer is too small."); @@ -195,6 +190,11 @@ static void __nvt_aes_crypt( mbedtls_aes_context *ctx, ctx->iv[1] = CRPT->AES_FDBCK1; ctx->iv[2] = CRPT->AES_FDBCK2; ctx->iv[3] = CRPT->AES_FDBCK3; + + /* Disable AES interrupt */ + AES_DISABLE_INT(); + /* Uninit crypto module */ + crypto_uninit(); } /* diff --git a/features/mbedtls/targets/TARGET_NUVOTON/TARGET_NUC472/crypto-misc.c b/features/mbedtls/targets/TARGET_NUVOTON/TARGET_NUC472/crypto-misc.c index c5d49bb0dd..42bb503edf 100644 --- a/features/mbedtls/targets/TARGET_NUVOTON/TARGET_NUC472/crypto-misc.c +++ b/features/mbedtls/targets/TARGET_NUVOTON/TARGET_NUC472/crypto-misc.c @@ -17,21 +17,62 @@ #include "cmsis.h" #include "mbed_assert.h" +#include "mbed_critical.h" +#include "mbed_error.h" +#include #include "nu_modutil.h" #include "nu_bitutil.h" #include "crypto-misc.h" -static int crypto_inited = 0; static int crypto_sha_avail = 1; +/* Crypto (AES, DES, SHA, etc.) init counter. Crypto's keeps active as it is non-zero. */ +static uint16_t crypto_init_counter = 0U; + +/* As crypto init counter changes from 0 to 1: + * + * 1. Enable crypto clock + * 2. Enable crypto interrupt + */ void crypto_init(void) { - if (crypto_inited) { - return; + core_util_critical_section_enter(); + if (crypto_init_counter == USHRT_MAX) { + core_util_critical_section_exit(); + error("Crypto clock enable counter would overflow (> USHRT_MAX)"); } - crypto_inited = 1; + core_util_atomic_incr_u16(&crypto_init_counter, 1); + if (crypto_init_counter == 1) { + SYS_UnlockReg(); // Unlock protected register + CLK_EnableModuleClock(CRPT_MODULE); + SYS_LockReg(); // Lock protected register + + NVIC_EnableIRQ(CRPT_IRQn); + } + core_util_critical_section_exit(); +} - CLK_EnableModuleClock(CRPT_MODULE); +/* As crypto init counter changes from 1 to 0: + * + * 1. Disable crypto interrupt + * 2. Disable crypto clock + */ +void crypto_uninit(void) +{ + core_util_critical_section_enter(); + if (crypto_init_counter == 0) { + core_util_critical_section_exit(); + error("Crypto clock enable counter would underflow (< 0)"); + } + core_util_atomic_decr_u16(&crypto_init_counter, 1); + if (crypto_init_counter == 0) { + NVIC_DisableIRQ(CRPT_IRQn); + + SYS_UnlockReg(); // Unlock protected register + CLK_DisableModuleClock(CRPT_MODULE); + SYS_LockReg(); // Lock protected register + } + core_util_critical_section_exit(); } /* Implementation that should never be optimized out by the compiler */ diff --git a/features/mbedtls/targets/TARGET_NUVOTON/TARGET_NUC472/crypto-misc.h b/features/mbedtls/targets/TARGET_NUVOTON/TARGET_NUC472/crypto-misc.h index 8d55449712..a6d2f70bb4 100644 --- a/features/mbedtls/targets/TARGET_NUVOTON/TARGET_NUC472/crypto-misc.h +++ b/features/mbedtls/targets/TARGET_NUVOTON/TARGET_NUC472/crypto-misc.h @@ -22,6 +22,7 @@ extern "C" { #endif void crypto_init(void); +void crypto_uninit(void); void crypto_zeroize(void *v, size_t n); int crypto_sha_acquire(void); void crypto_sha_release(void); diff --git a/features/mbedtls/targets/TARGET_NUVOTON/TARGET_NUC472/des/des_alt.c b/features/mbedtls/targets/TARGET_NUVOTON/TARGET_NUC472/des/des_alt.c index e8ca4624a1..078af8e172 100644 --- a/features/mbedtls/targets/TARGET_NUVOTON/TARGET_NUC472/des/des_alt.c +++ b/features/mbedtls/targets/TARGET_NUVOTON/TARGET_NUC472/des/des_alt.c @@ -49,7 +49,6 @@ static int mbedtls_des_docrypt(uint16_t keyopt, uint8_t key[3][MBEDTLS_DES_KEY_S void mbedtls_des_init(mbedtls_des_context *ctx) { - crypto_init(); memset(ctx, 0, sizeof(mbedtls_des_context)); } @@ -64,7 +63,6 @@ void mbedtls_des_free( mbedtls_des_context *ctx ) void mbedtls_des3_init( mbedtls_des3_context *ctx ) { - crypto_init(); memset(ctx, 0, sizeof(mbedtls_des3_context)); } @@ -329,6 +327,9 @@ static int mbedtls_des_docrypt(uint16_t keyopt, uint8_t key[3][MBEDTLS_DES_KEY_S error("Buffer for DES alter. DMA requires to be word-aligned and located in 0x20000000-0x2FFFFFFF region."); } + /* Init crypto module */ + crypto_init(); + // NOTE: Don't call driver function TDES_Open in BSP because it doesn't support TDES_CTL[3KEYS] setting. CRPT->TDES_CTL = (0 << CRPT_TDES_CTL_CHANNEL_Pos) | (enc << CRPT_TDES_CTL_ENCRPT_Pos) | tdes_opmode | (TDES_IN_OUT_WHL_SWAP << CRPT_TDES_CTL_BLKSWAP_Pos); @@ -418,6 +419,9 @@ static int mbedtls_des_docrypt(uint16_t keyopt, uint8_t key[3][MBEDTLS_DES_KEY_S } } + /* Uninit crypto module */ + crypto_uninit(); + return 0; } diff --git a/features/mbedtls/targets/TARGET_NUVOTON/TARGET_NUC472/sha/sha_alt_hw.c b/features/mbedtls/targets/TARGET_NUVOTON/TARGET_NUC472/sha/sha_alt_hw.c index a653cd7a96..ab8181cc65 100644 --- a/features/mbedtls/targets/TARGET_NUVOTON/TARGET_NUC472/sha/sha_alt_hw.c +++ b/features/mbedtls/targets/TARGET_NUVOTON/TARGET_NUC472/sha/sha_alt_hw.c @@ -39,6 +39,7 @@ void crypto_sha_getinternstate(unsigned char output[], size_t olen); void mbedtls_sha1_hw_init(crypto_sha_context *ctx) { + /* Init crypto module */ crypto_init(); memset(ctx, 0, sizeof(crypto_sha_context)); } @@ -49,6 +50,8 @@ void mbedtls_sha1_hw_free(crypto_sha_context *ctx) return; } + /* Uninit crypto module */ + crypto_uninit(); crypto_zeroize(ctx, sizeof(crypto_sha_context)); } @@ -113,6 +116,7 @@ void mbedtls_sha1_hw_process(crypto_sha_context *ctx, const unsigned char data[6 void mbedtls_sha256_hw_init(crypto_sha_context *ctx) { + /* Init crypto module */ crypto_init(); memset(ctx, 0, sizeof(crypto_sha_context)); } @@ -123,6 +127,8 @@ void mbedtls_sha256_hw_free(crypto_sha_context *ctx) return; } + /* Uninit crypto module */ + crypto_uninit(); crypto_zeroize(ctx, sizeof(crypto_sha_context)); } diff --git a/targets/TARGET_NUVOTON/TARGET_M480/trng_api.c b/targets/TARGET_NUVOTON/TARGET_M480/trng_api.c index 24d15537e4..74cabee52a 100644 --- a/targets/TARGET_NUVOTON/TARGET_M480/trng_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M480/trng_api.c @@ -21,6 +21,7 @@ #include "cmsis.h" #include "us_ticker_api.h" #include "trng_api.h" +#include "crypto-misc.h" /* * Get Random number generator. @@ -63,23 +64,21 @@ static void trng_get(unsigned char *pConversionData) void trng_init(trng_t *obj) { (void)obj; - /* Unlock protected registers */ - SYS_UnlockReg(); - /* Enable IP clock */ - CLK_EnableModuleClock(CRPT_MODULE); - - /* Lock protected registers */ - SYS_LockReg(); - - NVIC_EnableIRQ(CRPT_IRQn); + + /* Init crypto module */ + crypto_init(); + PRNG_ENABLE_INT(); } void trng_free(trng_t *obj) { (void)obj; + PRNG_DISABLE_INT(); - NVIC_DisableIRQ(CRPT_IRQn); + + /* Uninit crypto module */ + crypto_uninit(); } int trng_get_bytes(trng_t *obj, uint8_t *output, size_t length, size_t *output_length) diff --git a/targets/TARGET_NUVOTON/TARGET_NUC472/trng_api.c b/targets/TARGET_NUVOTON/TARGET_NUC472/trng_api.c index a1f55b48f6..1b6b24cf06 100644 --- a/targets/TARGET_NUVOTON/TARGET_NUC472/trng_api.c +++ b/targets/TARGET_NUVOTON/TARGET_NUC472/trng_api.c @@ -26,6 +26,7 @@ #include "NUC472_442.h" #include "us_ticker_api.h" #include "trng_api.h" +#include "crypto-misc.h" /* * Get Random number generator. @@ -68,23 +69,21 @@ static void trng_get(unsigned char *pConversionData) void trng_init(trng_t *obj) { (void)obj; - /* Unlock protected registers */ - SYS_UnlockReg(); - /* Enable IP clock */ - CLK_EnableModuleClock(CRPT_MODULE); - /* Lock protected registers */ - SYS_LockReg(); + /* Init crypto module */ + crypto_init(); - NVIC_EnableIRQ(CRPT_IRQn); PRNG_ENABLE_INT(); } void trng_free(trng_t *obj) { (void)obj; + PRNG_DISABLE_INT(); - NVIC_DisableIRQ(CRPT_IRQn); + + /* Uninit crypto module */ + crypto_uninit(); } int trng_get_bytes(trng_t *obj, uint8_t *output, size_t length, size_t *output_length)