mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			Merge pull request #9656 from OpenNuvoton/nuvoton_m2351_fix-crypto-ac-mgmt
M2351: Fix crypto AC managementpull/9677/head
						commit
						1712a2b76c
					
				| 
						 | 
				
			
			@ -23,29 +23,43 @@
 | 
			
		|||
#include "nu_modutil.h"
 | 
			
		||||
#include "nu_bitutil.h"
 | 
			
		||||
#include "crypto-misc.h"
 | 
			
		||||
#include "platform/SingletonPtr.h"
 | 
			
		||||
#include "platform/PlatformMutex.h"
 | 
			
		||||
 | 
			
		||||
#if DEVICE_TRNG || defined(MBEDTLS_CONFIG_HW_SUPPORT)
 | 
			
		||||
 | 
			
		||||
/* NOTE: There's inconsistency in cryptography related naming, Crpt or Crypto. For example, cryptography IRQ
 | 
			
		||||
 *       handler could be CRPT_IRQHandler or CRYPTO_IRQHandler. To override default cryptography IRQ handler, see
 | 
			
		||||
 *       device/startup_{CHIP}.c for its name or call NVIC_SetVector regardless of its name. */
 | 
			
		||||
void CRPT_IRQHandler();
 | 
			
		||||
/* Consideration for choosing proper synchronization mechanism
 | 
			
		||||
 *
 | 
			
		||||
 * 1. We choose mutex to synchronize access to crypto non-SHA AC. We can guarantee:
 | 
			
		||||
 *    (1) No deadlock
 | 
			
		||||
 *        We just lock mutex for a short sequence of operations rather than the whole lifetime
 | 
			
		||||
 *        of crypto context.
 | 
			
		||||
 *    (2) No priority inversion
 | 
			
		||||
 *        Mutex supports priority inheritance and it is enabled.
 | 
			
		||||
 * 2. We choose atomic flag to synchronize access to crypto SHA AC. We can guarantee:
 | 
			
		||||
 *    (1) No deadlock
 | 
			
		||||
 *        With SHA AC not supporting context save & restore, we provide SHA S/W fallback when
 | 
			
		||||
 *        SHA AC is not available.
 | 
			
		||||
 *    (2) No biting CPU
 | 
			
		||||
 *        Same reason as above.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Mutex for crypto AES AC management */
 | 
			
		||||
static SingletonPtr<PlatformMutex> crypto_aes_mutex;
 | 
			
		||||
 | 
			
		||||
/* Mutex for crypto DES AC management */
 | 
			
		||||
static SingletonPtr<PlatformMutex> crypto_des_mutex;
 | 
			
		||||
 | 
			
		||||
/* Mutex for crypto ECC AC management */
 | 
			
		||||
static SingletonPtr<PlatformMutex> crypto_ecc_mutex;
 | 
			
		||||
 | 
			
		||||
/* Atomic flag for crypto SHA AC management */
 | 
			
		||||
static core_util_atomic_flag crypto_sha_atomic_flag = CORE_UTIL_ATOMIC_FLAG_INIT;
 | 
			
		||||
 | 
			
		||||
/* Track if AES H/W is available */
 | 
			
		||||
static uint16_t crypto_aes_avail = 1;
 | 
			
		||||
/* Track if DES H/W is available */
 | 
			
		||||
static uint16_t crypto_des_avail = 1;
 | 
			
		||||
/* Track if SHA H/W is available */
 | 
			
		||||
static uint16_t crypto_sha_avail = 1;
 | 
			
		||||
/* Track if ECC H/W is available */
 | 
			
		||||
static uint16_t crypto_ecc_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;
 | 
			
		||||
 | 
			
		||||
static bool crypto_submodule_acquire(uint16_t *submodule_avail);
 | 
			
		||||
static void crypto_submodule_release(uint16_t *submodule_avail);
 | 
			
		||||
 | 
			
		||||
/* Crypto done flags */
 | 
			
		||||
#define CRYPTO_DONE_OK              BIT0    /* Done with OK */
 | 
			
		||||
#define CRYPTO_DONE_ERR             BIT1    /* Done with error */
 | 
			
		||||
| 
						 | 
				
			
			@ -81,8 +95,7 @@ void crypto_init(void)
 | 
			
		|||
         * NOTE: We must call secure version (from non-secure domain) because SYS/CLK regions are secure.
 | 
			
		||||
         */
 | 
			
		||||
        CLK_EnableModuleClock_S(CRPT_MODULE);
 | 
			
		||||
        
 | 
			
		||||
        NVIC_SetVector(CRPT_IRQn, (uint32_t) CRPT_IRQHandler);
 | 
			
		||||
 | 
			
		||||
        NVIC_EnableIRQ(CRPT_IRQn);
 | 
			
		||||
    }
 | 
			
		||||
    core_util_critical_section_exit();
 | 
			
		||||
| 
						 | 
				
			
			@ -131,44 +144,52 @@ void crypto_zeroize32(uint32_t *v, size_t n)
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool crypto_aes_acquire(void)
 | 
			
		||||
void crypto_aes_acquire(void)
 | 
			
		||||
{
 | 
			
		||||
    return crypto_submodule_acquire(&crypto_aes_avail);
 | 
			
		||||
    /* Don't check return code of Mutex::lock(void)
 | 
			
		||||
     *
 | 
			
		||||
     * This function treats RTOS errors as fatal system errors, so it can only return osOK.
 | 
			
		||||
     * Use of the return value is deprecated, as the return is expected to become void in
 | 
			
		||||
     * the future.
 | 
			
		||||
     */
 | 
			
		||||
    crypto_aes_mutex->lock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void crypto_aes_release(void)
 | 
			
		||||
{
 | 
			
		||||
    crypto_submodule_release(&crypto_aes_avail);
 | 
			
		||||
    crypto_aes_mutex->unlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool crypto_des_acquire(void)
 | 
			
		||||
void crypto_des_acquire(void)
 | 
			
		||||
{
 | 
			
		||||
    return crypto_submodule_acquire(&crypto_des_avail);
 | 
			
		||||
    /* Don't check return code of Mutex::lock(void) */
 | 
			
		||||
    crypto_des_mutex->lock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void crypto_des_release(void)
 | 
			
		||||
{
 | 
			
		||||
    crypto_submodule_release(&crypto_des_avail);
 | 
			
		||||
    crypto_des_mutex->unlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool crypto_sha_acquire(void)
 | 
			
		||||
void crypto_ecc_acquire(void)
 | 
			
		||||
{
 | 
			
		||||
    return crypto_submodule_acquire(&crypto_sha_avail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void crypto_sha_release(void)
 | 
			
		||||
{
 | 
			
		||||
    crypto_submodule_release(&crypto_sha_avail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool crypto_ecc_acquire(void)
 | 
			
		||||
{
 | 
			
		||||
    return crypto_submodule_acquire(&crypto_ecc_avail);
 | 
			
		||||
    /* Don't check return code of Mutex::lock(void) */
 | 
			
		||||
    crypto_ecc_mutex->lock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void crypto_ecc_release(void)
 | 
			
		||||
{
 | 
			
		||||
    crypto_submodule_release(&crypto_ecc_avail);
 | 
			
		||||
    crypto_ecc_mutex->unlock();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool crypto_sha_try_acquire(void)
 | 
			
		||||
{
 | 
			
		||||
    return !core_util_atomic_flag_test_and_set(&crypto_sha_atomic_flag);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void crypto_sha_release(void)
 | 
			
		||||
{
 | 
			
		||||
    core_util_atomic_flag_clear(&crypto_sha_atomic_flag);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void crypto_prng_prestart(void)
 | 
			
		||||
| 
						 | 
				
			
			@ -252,18 +273,6 @@ bool crypto_dma_buffs_overlap(const void *in_buff, size_t in_buff_size, const vo
 | 
			
		|||
    return overlap;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool crypto_submodule_acquire(uint16_t *submodule_avail)
 | 
			
		||||
{
 | 
			
		||||
    uint16_t expectedCurrentValue = 1;
 | 
			
		||||
    return core_util_atomic_cas_u16(submodule_avail, &expectedCurrentValue, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void crypto_submodule_release(uint16_t *submodule_avail)
 | 
			
		||||
{
 | 
			
		||||
    uint16_t expectedCurrentValue = 0;
 | 
			
		||||
    while (! core_util_atomic_cas_u16(submodule_avail, &expectedCurrentValue, 1));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void crypto_submodule_prestart(volatile uint16_t *submodule_done)
 | 
			
		||||
{
 | 
			
		||||
    *submodule_done = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -296,8 +305,13 @@ static bool crypto_submodule_wait(volatile uint16_t *submodule_done)
 | 
			
		|||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Crypto interrupt handler */
 | 
			
		||||
void CRPT_IRQHandler()
 | 
			
		||||
/* Crypto interrupt handler
 | 
			
		||||
 * 
 | 
			
		||||
 * There's inconsistency in cryptography related naming, Crpt or Crypto. For example,
 | 
			
		||||
 * cryptography IRQ handler could be CRPT_IRQHandler or CRYPTO_IRQHandler. To override
 | 
			
		||||
 * default cryptography IRQ handler, see device/startup_{CHIP}.c for its correct name
 | 
			
		||||
 * or call NVIC_SetVector() in crypto_init() regardless of its name. */
 | 
			
		||||
extern "C" void CRPT_IRQHandler()
 | 
			
		||||
{
 | 
			
		||||
    uint32_t intsts;
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			@ -66,26 +66,33 @@ void crypto_uninit(void);
 | 
			
		|||
void crypto_zeroize(void *v, size_t n);
 | 
			
		||||
void crypto_zeroize32(uint32_t *v, size_t n);
 | 
			
		||||
 | 
			
		||||
/* Acquire/release ownership of AES H/W */
 | 
			
		||||
/* NOTE: If "acquire" succeeds, "release" must be done to pair it. */
 | 
			
		||||
bool crypto_aes_acquire(void);
 | 
			
		||||
/* Acquire/release ownership of crypto sub-module
 | 
			
		||||
 * 
 | 
			
		||||
 * \note            "acquire" is blocking until ownership is acquired
 | 
			
		||||
 *
 | 
			
		||||
 * \note            "acquire"/"release" must be paired.
 | 
			
		||||
 *
 | 
			
		||||
 * \note            Recursive "acquire" is allowed because the underlying synchronization
 | 
			
		||||
 *                  primitive mutex supports it.
 | 
			
		||||
 */
 | 
			
		||||
void crypto_aes_acquire(void);
 | 
			
		||||
void crypto_aes_release(void);
 | 
			
		||||
 | 
			
		||||
/* Acquire/release ownership of DES H/W */
 | 
			
		||||
/* NOTE: If "acquire" succeeds, "release" must be done to pair it. */
 | 
			
		||||
bool crypto_des_acquire(void);
 | 
			
		||||
void crypto_des_acquire(void);
 | 
			
		||||
void crypto_des_release(void);
 | 
			
		||||
 | 
			
		||||
/* Acquire/release ownership of SHA H/W */
 | 
			
		||||
/* NOTE: If "acquire" succeeds, "release" must be done to pair it. */
 | 
			
		||||
bool crypto_sha_acquire(void);
 | 
			
		||||
void crypto_sha_release(void);
 | 
			
		||||
 | 
			
		||||
/* Acquire/release ownership of ECC H/W */
 | 
			
		||||
/* NOTE: If "acquire" succeeds, "release" must be done to pair it. */
 | 
			
		||||
bool crypto_ecc_acquire(void);
 | 
			
		||||
void crypto_ecc_acquire(void);
 | 
			
		||||
void crypto_ecc_release(void);
 | 
			
		||||
 | 
			
		||||
/* Acquire/release ownership of crypto sub-module
 | 
			
		||||
 * 
 | 
			
		||||
 * \return          false if crytpo sub-module is held by another thread or
 | 
			
		||||
 *                  another mbedtls context.
 | 
			
		||||
 *                  true if successful
 | 
			
		||||
 *
 | 
			
		||||
 * \note            Successful "try_acquire" and "release" must be paired.
 | 
			
		||||
 */
 | 
			
		||||
bool crypto_sha_try_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.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,10 +19,6 @@
 | 
			
		|||
#include "mbed_assert.h"
 | 
			
		||||
#include "mbed_critical.h"
 | 
			
		||||
#include "mbed_error.h"
 | 
			
		||||
#if MBED_CONF_RTOS_PRESENT
 | 
			
		||||
#include "cmsis_os2.h"
 | 
			
		||||
#endif
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include "nu_modutil.h"
 | 
			
		||||
#include "nu_bitutil.h"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,10 +19,6 @@
 | 
			
		|||
#include "mbed_assert.h"
 | 
			
		||||
#include "mbed_critical.h"
 | 
			
		||||
#include "mbed_error.h"
 | 
			
		||||
#if MBED_CONF_RTOS_PRESENT
 | 
			
		||||
#include "cmsis_os2.h"
 | 
			
		||||
#endif
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
#include "nu_modutil.h"
 | 
			
		||||
#include "nu_bitutil.h"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue