1038 lines
30 KiB
C
1038 lines
30 KiB
C
/***************************************************************************
|
|
*
|
|
* Copyright 2015-2020 BES.
|
|
* All rights reserved. All unpublished rights reserved.
|
|
*
|
|
* No part of this work may be used or reproduced in any form or by any
|
|
* means, or stored in a database or retrieval system, without prior written
|
|
* permission of BES.
|
|
*
|
|
* Use of this work is governed by a license granted by BES.
|
|
* This work contains confidential and proprietary information of
|
|
* BES. which is protected by copyright, trade secret,
|
|
* trademark and other intellectual property rights.
|
|
*
|
|
****************************************************************************/
|
|
#include "plat_addr_map.h"
|
|
|
|
#ifdef SEC_ENG_BASE
|
|
|
|
#include "hal_sec_eng.h"
|
|
#include "reg_sec_eng.h"
|
|
#include "reg_dma.h"
|
|
#include "cmsis_nvic.h"
|
|
#include "hal_cmu.h"
|
|
#include "hal_dma.h"
|
|
#include "hal_timer.h"
|
|
#include "hal_trace.h"
|
|
|
|
#define SE_DMA_CHAN_NUM 2
|
|
#define SE_DMA_DESC_NUM 4
|
|
|
|
#define SE_DMA_MAX_DESC_XFER_SIZE (HAL_DMA_MAX_DESC_XFER_SIZE & ~(4 - 1))
|
|
|
|
#define SE_DMA_RX_CHAN 0
|
|
#define SE_DMA_TX_CHAN 1
|
|
|
|
// Trigger DMA request when RX-FIFO count >= threshold
|
|
#define SE_DMA_RX_FIFO_TRIG_LEVEL 8
|
|
// Trigger DMA request when TX-FIFO count <= threshold
|
|
#define SE_DMA_TX_FIFO_TRIG_LEVEL 8
|
|
|
|
enum SE_ACC_CLK_T {
|
|
SE_ACC_CLK_DMA = (1 << 1),
|
|
SE_ACC_CLK_ACC_BUS = (1 << 2),
|
|
SE_ACC_CLK_CRYPT = (1 << 3),
|
|
SE_ACC_CLK_ECP = (1 << 4),
|
|
SE_ACC_CLK_HASH = (1 << 5),
|
|
SE_ACC_CLK_SCRATCH = (1 << 6),
|
|
SE_ACC_CLK_ZMODP = (1 << 7),
|
|
SE_ACC_CLK_MCT = (1 << 8),
|
|
SE_ACC_CLK_OTP = (1 << 9),
|
|
SE_ACC_CLK_EBG = (1 << 10),
|
|
};
|
|
|
|
enum SE_ACC_RST_T {
|
|
SE_ACC_RST_DMA = (1 << 1),
|
|
SE_ACC_RST_ACC_BUS = (1 << 2),
|
|
SE_ACC_RST_CRYPT = (1 << 3),
|
|
SE_ACC_RST_ECP = (1 << 4),
|
|
SE_ACC_RST_HASH = (1 << 5),
|
|
SE_ACC_RST_SCRATCH = (1 << 6),
|
|
SE_ACC_RST_ZMODP = (1 << 7),
|
|
SE_ACC_RST_MCT = (1 << 8),
|
|
SE_ACC_RST_OTP = (1 << 9),
|
|
SE_ACC_RST_EBG = (1 << 10),
|
|
};
|
|
|
|
enum SE_ACC_INT_T {
|
|
SE_ACC_INT_AES = (1 << 1),
|
|
SE_ACC_INT_DES = (1 << 2),
|
|
SE_ACC_INT_RC4 = (1 << 3),
|
|
SE_ACC_INT_OTP = (1 << 4),
|
|
SE_ACC_INT_ECP = (1 << 6),
|
|
SE_ACC_INT_MCT = (1 << 7),
|
|
SE_ACC_INT_HASH = (1 << 8),
|
|
SE_ACC_INT_ZMODP = (1 << 9),
|
|
SE_ACC_INT_SCRATCH = (1 << 10),
|
|
};
|
|
|
|
enum SE_DMA_PERIPH_T {
|
|
SE_DMA_PERIPH_TX = 0,
|
|
SE_DMA_PERIPH_RX,
|
|
|
|
SE_DMA_PERIPH_QTY,
|
|
};
|
|
|
|
enum SE_CRYPT_TYPE_T {
|
|
SE_CRYPT_NONE = 0,
|
|
SE_CRYPT_AES,
|
|
SE_CRYPT_DES,
|
|
SE_CRYPT_RC4,
|
|
|
|
SE_CRYPT_QTY,
|
|
};
|
|
|
|
enum SE_AES_KEY_LEN_T {
|
|
SE_AES_KEY_128 = 0,
|
|
SE_AES_KEY_192,
|
|
SE_AES_KEY_256,
|
|
|
|
SE_AES_KEY_LEN_QTY,
|
|
};
|
|
|
|
enum SE_HASH_OP_T {
|
|
SE_HASH_OP_INIT = 1,
|
|
SE_HASH_OP_UPDATE,
|
|
SE_HASH_OP_FINAL,
|
|
};
|
|
|
|
static struct DMA_T * const se_dma = (struct DMA_T *)SEDMA_BASE;
|
|
|
|
static struct SE_ADEC_T * const se_adec = (struct SE_ADEC_T *)SE_ADEC_BASE;
|
|
static struct SE_ACB_T * const se_acb = (struct SE_ACB_T *)SE_ACB_BASE;
|
|
static struct SE_DMACFG_T * const se_dmacfg = (struct SE_DMACFG_T *)SE_DMACFG_BASE;
|
|
static struct SE_CRYPT_T * const se_crypt = (struct SE_CRYPT_T *)SE_CRYPT_BASE;
|
|
POSSIBLY_UNUSED static struct SE_HASH_T * const se_hash = (struct SE_HASH_T *)SE_HASH_BASE;
|
|
POSSIBLY_UNUSED static struct SE_OTP_T * const se_otp = (struct SE_OTP_T *)SE_OTP_BASE;
|
|
|
|
static bool se_enabled;
|
|
|
|
static HAL_SC_DONE_HANDLER_T se_done_hdlr;
|
|
|
|
static uint32_t in_addr;
|
|
static uint32_t total_in_len;
|
|
static uint32_t cur_in_len;
|
|
|
|
static uint32_t out_addr;
|
|
static uint32_t total_out_len;
|
|
static uint32_t cur_out_len;
|
|
|
|
static struct HAL_DMA_DESC_T dma_desc[SE_DMA_CHAN_NUM][SE_DMA_DESC_NUM];
|
|
|
|
static uint32_t se_dma_init_rx_desc(uint32_t out, uint32_t out_len, uint32_t src, uint32_t ctrl);
|
|
static uint32_t se_dma_init_tx_desc(uint32_t in, uint32_t in_len, uint32_t dst, uint32_t ctrl);
|
|
#ifdef SEC_ENG_HAS_HASH
|
|
static uint32_t se_hash_get_digest_len(void);
|
|
static void read_mreg(const volatile uint32_t *reg, void *mem, uint32_t len);
|
|
#endif
|
|
|
|
static void sec_eng_irq_handler(void)
|
|
{
|
|
enum HAL_SE_DONE_ERR_T err;
|
|
uint32_t all_int;
|
|
uint32_t aes_int = 0;
|
|
uint32_t hash_int = 0;
|
|
|
|
all_int = se_adec->ADEC_INT;
|
|
|
|
if (all_int & SE_ACC_INT_AES) {
|
|
aes_int = se_crypt->AES_INTRPT;
|
|
|
|
// Clear IRQs
|
|
se_crypt->AES_INTRPT = aes_int;
|
|
se_adec->ADEC_INT = SE_ACC_INT_AES;
|
|
|
|
if (aes_int & (AES_INTRPT_ERROR1 | AES_INTRPT_ERROR2)) {
|
|
if (se_done_hdlr) {
|
|
if ((aes_int & (AES_INTRPT_ERROR1 | AES_INTRPT_ERROR2)) == (AES_INTRPT_ERROR1 | AES_INTRPT_ERROR2)) {
|
|
err = HAL_SE_DONE_ERR_ENG_ERR1_ERR2;
|
|
} else if (aes_int & AES_INTRPT_ERROR1) {
|
|
err = HAL_SE_DONE_ERR_ENG_ERR1;
|
|
} else {
|
|
err = HAL_SE_DONE_ERR_ENG_ERR2;
|
|
}
|
|
se_done_hdlr((void *)out_addr, 0, err);
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef SEC_ENG_HAS_HASH
|
|
if (all_int & SE_ACC_INT_HASH) {
|
|
hash_int = se_hash->HASH_STATUS;
|
|
|
|
// Clear IRQs
|
|
se_hash->HASH_STATUS = hash_int;
|
|
se_adec->ADEC_INT = SE_ACC_INT_HASH;
|
|
|
|
if (hash_int & HASH_STATUS_HASH_DONE) {
|
|
if (se_done_hdlr) {
|
|
enum HAL_SE_RET_T ret;
|
|
uint32_t digest[16];
|
|
uint32_t len;
|
|
|
|
ret = hal_se_hash_get_digest(&digest[0], sizeof(digest), &len);
|
|
if (ret == HAL_SE_OK) {
|
|
se_done_hdlr(&digest[0], len, HAL_SE_DONE_OK);
|
|
} else {
|
|
se_done_hdlr(NULL, 0, HAL_SE_DONE_OK);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
LOG_INFO(0, "%s: all_int=0x%08X aes_int=0x%08X hash_int=%d", __func__, all_int, aes_int, hash_int);
|
|
}
|
|
|
|
static void sedma_irq_handler(void)
|
|
{
|
|
uint8_t hwch;
|
|
uint32_t remains;
|
|
uint32_t len;
|
|
uint32_t ctrl;
|
|
bool tcint, errint;
|
|
|
|
for (hwch = 0; hwch < SE_DMA_CHAN_NUM; hwch++) {
|
|
if ((se_dma->INTSTAT & DMA_STAT_CHAN(hwch)) == 0) {
|
|
continue;
|
|
}
|
|
|
|
/* Check counter terminal status */
|
|
tcint = !!(se_dma->INTTCSTAT & DMA_STAT_CHAN(hwch));
|
|
/* Check error terminal status */
|
|
errint = !!(se_dma->INTERRSTAT & DMA_STAT_CHAN(hwch));
|
|
|
|
if (tcint || errint) {
|
|
if (tcint) {
|
|
/* Clear terminate counter Interrupt pending */
|
|
se_dma->INTTCCLR = DMA_STAT_CHAN(hwch);
|
|
}
|
|
if (errint) {
|
|
/* Clear error counter Interrupt pending */
|
|
se_dma->INTERRCLR = DMA_STAT_CHAN(hwch);
|
|
}
|
|
|
|
remains = GET_BITFIELD(se_dma->CH[hwch].CONTROL, DMA_CONTROL_TRANSFERSIZE);
|
|
if (errint) {
|
|
se_dma->CH[hwch].CONFIG &= ~DMA_CONFIG_EN;
|
|
if (se_done_hdlr) {
|
|
se_done_hdlr((uint8_t *)out_addr, 0,
|
|
(hwch == SE_DMA_RX_CHAN) ? HAL_SE_DONE_ERR_DMA_OUT : HAL_SE_DONE_ERR_DMA_IN);
|
|
}
|
|
} else {
|
|
if (hwch == SE_DMA_RX_CHAN) {
|
|
if (cur_out_len < total_out_len) {
|
|
len = total_out_len - cur_out_len;
|
|
ctrl = se_dma->CH[hwch].CONTROL & ~DMA_CONTROL_TC_IRQ;
|
|
cur_out_len += se_dma_init_rx_desc(out_addr + cur_out_len, len, se_dma->CH[hwch].SRCADDR, ctrl);
|
|
se_dma->CH[SE_DMA_RX_CHAN].CONFIG |= DMA_CONFIG_EN;
|
|
} else {
|
|
if (se_done_hdlr) {
|
|
if (remains) {
|
|
se_done_hdlr((void *)out_addr, cur_out_len - remains, HAL_SE_DONE_ERR_DMA_IN_REMAIN);
|
|
} else {
|
|
se_done_hdlr((void *)out_addr, cur_out_len, HAL_SE_DONE_OK);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (cur_in_len < total_in_len) {
|
|
len = total_in_len - cur_in_len;
|
|
ctrl = se_dma->CH[hwch].CONTROL & ~DMA_CONTROL_TC_IRQ;
|
|
cur_in_len += se_dma_init_tx_desc(in_addr + cur_in_len, len, se_dma->CH[hwch].DSTADDR, ctrl);
|
|
se_dma->CH[SE_DMA_TX_CHAN].CONFIG |= DMA_CONFIG_EN;
|
|
} else {
|
|
if (remains) {
|
|
if (se_done_hdlr) {
|
|
se_done_hdlr((void *)out_addr, 0, HAL_SE_DONE_ERR_DMA_IN_REMAIN);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
LOG_INFO(0, "%s: ch=%d tcint=%d errint=%d remains=%u", __func__, hwch, tcint, errint, remains);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void se_dma_open(void)
|
|
{
|
|
uint8_t i;
|
|
|
|
se_adec->ADEC_CTRL |= ADEC_CTRL_CLK_EN_15_0(SE_ACC_CLK_DMA) | ADEC_CTRL_RST_15_0(SE_ACC_RST_DMA);
|
|
se_adec->ADEC_CTRL &= ~ADEC_CTRL_RST_15_0(SE_ACC_RST_DMA);
|
|
se_adec->ADEC_INT_MSK = ~0UL;
|
|
|
|
se_dmacfg->DMA_CTRL = DMA_CTRL_RX_DMA_EN | DMA_CTRL_TX_DMA_EN;
|
|
se_dmacfg->DMA_RDL = SE_DMA_RX_FIFO_TRIG_LEVEL;
|
|
se_dmacfg->DMA_TDL = SE_DMA_TX_FIFO_TRIG_LEVEL;
|
|
|
|
/* Reset all channel configuration register */
|
|
for (i = 0; i < SE_DMA_CHAN_NUM; i++) {
|
|
se_dma->CH[i].CONFIG = 0;
|
|
}
|
|
|
|
/* Clear all DMA interrupt and error flag */
|
|
se_dma->INTTCCLR = ~0UL;
|
|
se_dma->INTERRCLR = ~0UL;
|
|
|
|
se_dma->DMACONFIG = (se_dma->DMACONFIG & ~(DMA_DMACONFIG_AHB1_BIGENDIAN |
|
|
DMA_DMACONFIG_AHB2_BIGENDIAN)) | DMA_DMACONFIG_EN;
|
|
|
|
NVIC_SetVector(SEDMA_IRQn, (uint32_t)sedma_irq_handler);
|
|
NVIC_SetPriority(SEDMA_IRQn, IRQ_PRIORITY_NORMAL);
|
|
NVIC_ClearPendingIRQ(SEDMA_IRQn);
|
|
NVIC_EnableIRQ(SEDMA_IRQn);
|
|
}
|
|
|
|
static void se_dma_cancel_rx(void)
|
|
{
|
|
se_dma->CH[SE_DMA_RX_CHAN].CONFIG &= ~DMA_CONFIG_EN;
|
|
}
|
|
|
|
static void se_dma_cancel_tx(void)
|
|
{
|
|
se_dma->CH[SE_DMA_TX_CHAN].CONFIG &= ~DMA_CONFIG_EN;
|
|
}
|
|
|
|
static void se_dma_close(void)
|
|
{
|
|
NVIC_DisableIRQ(SEDMA_IRQn);
|
|
se_dma_cancel_rx();
|
|
se_dma_cancel_tx();
|
|
se_dma->DMACONFIG = 0;
|
|
}
|
|
|
|
static uint32_t se_dma_init_rx_desc(uint32_t out, uint32_t out_len, uint32_t src, uint32_t ctrl)
|
|
{
|
|
uint32_t len;
|
|
uint32_t cfg_len;
|
|
uint32_t desc_idx;
|
|
uint32_t i;
|
|
|
|
len = out_len;
|
|
if (len > SE_DMA_MAX_DESC_XFER_SIZE * 4) {
|
|
len = SE_DMA_MAX_DESC_XFER_SIZE * 4;
|
|
}
|
|
len &= ~(4 - 1);
|
|
ctrl = SET_BITFIELD(ctrl, DMA_CONTROL_TRANSFERSIZE, len / 4);
|
|
if (len >= out_len) {
|
|
// Always enable IRQ at the end of each xfer
|
|
ctrl |= DMA_CONTROL_TC_IRQ;
|
|
}
|
|
se_dma->CH[SE_DMA_RX_CHAN].CONTROL = ctrl;
|
|
se_dma->CH[SE_DMA_RX_CHAN].SRCADDR = src;
|
|
se_dma->CH[SE_DMA_RX_CHAN].DSTADDR = out;
|
|
|
|
if (len >= out_len) {
|
|
se_dma->CH[SE_DMA_RX_CHAN].LLI = 0;
|
|
return len;
|
|
}
|
|
|
|
cfg_len = len;
|
|
desc_idx = 0;
|
|
while (desc_idx < SE_DMA_DESC_NUM && cfg_len < out_len) {
|
|
len = out_len - cfg_len;
|
|
if (len > SE_DMA_MAX_DESC_XFER_SIZE * 4) {
|
|
len = SE_DMA_MAX_DESC_XFER_SIZE * 4;
|
|
}
|
|
len &= ~(4 - 1);
|
|
ctrl = SET_BITFIELD(ctrl, DMA_CONTROL_TRANSFERSIZE, len / 4);
|
|
dma_desc[SE_DMA_RX_CHAN][desc_idx].ctrl = ctrl;
|
|
dma_desc[SE_DMA_RX_CHAN][desc_idx].src = src;
|
|
dma_desc[SE_DMA_RX_CHAN][desc_idx].dst = out + cfg_len;
|
|
cfg_len += len;
|
|
desc_idx++;
|
|
}
|
|
|
|
// Always enable IRQ at the end of each xfer
|
|
dma_desc[SE_DMA_RX_CHAN][desc_idx - 1].ctrl |= DMA_CONTROL_TC_IRQ;
|
|
|
|
for (i = 0; i + 1 < desc_idx; i++) {
|
|
dma_desc[SE_DMA_RX_CHAN][i].lli = (uint32_t)&dma_desc[SE_DMA_RX_CHAN][i + 1];
|
|
}
|
|
dma_desc[SE_DMA_RX_CHAN][desc_idx - 1].lli = 0;
|
|
|
|
se_dma->CH[SE_DMA_RX_CHAN].LLI = (uint32_t)&dma_desc[SE_DMA_RX_CHAN][0];
|
|
|
|
return cfg_len;
|
|
}
|
|
|
|
static void se_dma_enable_rx(void *out, uint32_t out_len)
|
|
{
|
|
uint32_t ctrl;
|
|
|
|
ASSERT((out_len & (4 - 1)) == 0, "%s: out_len must align to 4 bytes: %u", __func__, out_len);
|
|
|
|
out_addr = (uint32_t)out;
|
|
total_out_len = out_len;
|
|
|
|
/* Reset the Interrupt status */
|
|
se_dma->INTTCCLR = DMA_STAT_CHAN(SE_DMA_RX_CHAN);
|
|
se_dma->INTERRCLR = DMA_STAT_CHAN(SE_DMA_RX_CHAN);
|
|
|
|
ctrl = DMA_CONTROL_SBSIZE(HAL_DMA_BSIZE_8) |
|
|
DMA_CONTROL_DBSIZE(HAL_DMA_BSIZE_16) |
|
|
DMA_CONTROL_SWIDTH(HAL_DMA_WIDTH_WORD) |
|
|
DMA_CONTROL_DWIDTH(HAL_DMA_WIDTH_BYTE) |
|
|
DMA_CONTROL_DI;
|
|
|
|
cur_out_len = se_dma_init_rx_desc((uint32_t)out, out_len, (uint32_t)&se_dmacfg->DMA_RXFIFO, ctrl);
|
|
|
|
se_dma->CH[SE_DMA_RX_CHAN].CONFIG = DMA_CONFIG_SRCPERIPH(SE_DMA_PERIPH_RX) |
|
|
DMA_CONFIG_TRANSFERTYPE(HAL_DMA_FLOW_P2M_DMA) |
|
|
DMA_CONFIG_ERR_IRQMASK | DMA_CONFIG_TC_IRQMASK;
|
|
se_dma->CH[SE_DMA_RX_CHAN].CONFIG |= DMA_CONFIG_EN;
|
|
}
|
|
|
|
static uint32_t se_dma_init_tx_desc(uint32_t in, uint32_t in_len, uint32_t dst, uint32_t ctrl)
|
|
{
|
|
uint32_t len;
|
|
uint32_t cfg_len;
|
|
uint32_t desc_idx;
|
|
uint32_t i;
|
|
|
|
len = in_len;
|
|
if (len > SE_DMA_MAX_DESC_XFER_SIZE) {
|
|
len = SE_DMA_MAX_DESC_XFER_SIZE;
|
|
}
|
|
ctrl = SET_BITFIELD(ctrl, DMA_CONTROL_TRANSFERSIZE, len);
|
|
se_dma->CH[SE_DMA_TX_CHAN].CONTROL = ctrl;
|
|
se_dma->CH[SE_DMA_TX_CHAN].SRCADDR = in;
|
|
se_dma->CH[SE_DMA_TX_CHAN].DSTADDR = dst;
|
|
|
|
if (len >= in_len) {
|
|
se_dma->CH[SE_DMA_TX_CHAN].LLI = 0;
|
|
return len;
|
|
}
|
|
|
|
cfg_len = len;
|
|
desc_idx = 0;
|
|
while (desc_idx < SE_DMA_DESC_NUM && cfg_len < in_len) {
|
|
len = in_len - cfg_len;
|
|
if (len > SE_DMA_MAX_DESC_XFER_SIZE) {
|
|
len = SE_DMA_MAX_DESC_XFER_SIZE;
|
|
}
|
|
ctrl = SET_BITFIELD(ctrl, DMA_CONTROL_TRANSFERSIZE, len);
|
|
dma_desc[SE_DMA_TX_CHAN][desc_idx].ctrl = ctrl;
|
|
dma_desc[SE_DMA_TX_CHAN][desc_idx].src = in + cfg_len;
|
|
dma_desc[SE_DMA_TX_CHAN][desc_idx].dst = dst;
|
|
cfg_len += len;
|
|
desc_idx++;
|
|
}
|
|
|
|
if (cfg_len < in_len) {
|
|
// Enable IRQ at the end of xfer
|
|
dma_desc[SE_DMA_TX_CHAN][desc_idx - 1].ctrl |= DMA_CONTROL_TC_IRQ;
|
|
}
|
|
|
|
for (i = 0; i + 1 < desc_idx; i++) {
|
|
dma_desc[SE_DMA_TX_CHAN][i].lli = (uint32_t)&dma_desc[SE_DMA_TX_CHAN][i + 1];
|
|
}
|
|
dma_desc[SE_DMA_TX_CHAN][desc_idx - 1].lli = 0;
|
|
|
|
se_dma->CH[SE_DMA_TX_CHAN].LLI = (uint32_t)&dma_desc[SE_DMA_TX_CHAN][0];
|
|
|
|
return cfg_len;
|
|
}
|
|
|
|
static void se_dma_enable_tx(const void *in, uint32_t in_len)
|
|
{
|
|
uint32_t ctrl;
|
|
|
|
if (in_len & (4 - 1)) {
|
|
in_len = (in_len + (4 - 1)) & ~(4 - 1);
|
|
}
|
|
|
|
in_addr = (uint32_t)in;
|
|
total_in_len = in_len;
|
|
|
|
/* Reset the Interrupt status */
|
|
se_dma->INTTCCLR = DMA_STAT_CHAN(SE_DMA_TX_CHAN);
|
|
se_dma->INTERRCLR = DMA_STAT_CHAN(SE_DMA_TX_CHAN);
|
|
|
|
ctrl = DMA_CONTROL_SBSIZE(HAL_DMA_BSIZE_16) |
|
|
DMA_CONTROL_DBSIZE(HAL_DMA_BSIZE_8) |
|
|
DMA_CONTROL_SWIDTH(HAL_DMA_WIDTH_BYTE) |
|
|
DMA_CONTROL_DWIDTH(HAL_DMA_WIDTH_WORD) |
|
|
DMA_CONTROL_SI;
|
|
|
|
cur_in_len = se_dma_init_tx_desc((uint32_t)in, in_len, (uint32_t)&se_dmacfg->DMA_TXFIFO, ctrl);
|
|
|
|
se_dma->CH[SE_DMA_TX_CHAN].CONFIG = DMA_CONFIG_DSTPERIPH(SE_DMA_PERIPH_TX) |
|
|
DMA_CONFIG_TRANSFERTYPE(HAL_DMA_FLOW_M2P_DMA) |
|
|
DMA_CONFIG_ERR_IRQMASK | DMA_CONFIG_TC_IRQMASK;
|
|
se_dma->CH[SE_DMA_TX_CHAN].CONFIG |= DMA_CONFIG_EN;
|
|
}
|
|
|
|
enum HAL_SE_RET_T hal_se_open(void)
|
|
{
|
|
if (se_enabled) {
|
|
return HAL_SE_ALREADY_OPENED;
|
|
}
|
|
|
|
se_enabled = true;
|
|
|
|
hal_cmu_clock_enable(HAL_CMU_MOD_H_SEC_ENG);
|
|
hal_cmu_clock_enable(HAL_CMU_MOD_P_SEC_ENG);
|
|
hal_cmu_reset_clear(HAL_CMU_MOD_H_SEC_ENG);
|
|
hal_cmu_reset_clear(HAL_CMU_MOD_P_SEC_ENG);
|
|
|
|
se_dma_open();
|
|
|
|
NVIC_SetVector(SEC_ENG_IRQn, (uint32_t)sec_eng_irq_handler);
|
|
NVIC_SetPriority(SEC_ENG_IRQn, IRQ_PRIORITY_NORMAL);
|
|
NVIC_ClearPendingIRQ(SEC_ENG_IRQn);
|
|
NVIC_EnableIRQ(SEC_ENG_IRQn);
|
|
|
|
return HAL_SE_OK;
|
|
}
|
|
|
|
enum HAL_SE_RET_T hal_se_close(void)
|
|
{
|
|
if (!se_enabled) {
|
|
return HAL_SE_NOT_OPENED;
|
|
}
|
|
|
|
NVIC_DisableIRQ(SEC_ENG_IRQn);
|
|
|
|
se_dma_close();
|
|
|
|
se_adec->ADEC_INT_MSK = ~0UL;
|
|
se_adec->ADEC_CTRL = ~0UL;
|
|
se_adec->ADEC_CTRL2 = ~0UL;
|
|
se_adec->ADEC_CTRL = 0x0000FFFF;
|
|
se_adec->ADEC_CTRL2 = 0x0000FFFF;
|
|
|
|
hal_cmu_reset_set(HAL_CMU_MOD_H_SEC_ENG);
|
|
hal_cmu_reset_set(HAL_CMU_MOD_P_SEC_ENG);
|
|
hal_cmu_clock_disable(HAL_CMU_MOD_H_SEC_ENG);
|
|
hal_cmu_clock_disable(HAL_CMU_MOD_P_SEC_ENG);
|
|
|
|
se_enabled = false;
|
|
|
|
return HAL_SE_OK;
|
|
}
|
|
|
|
static void write_mreg(volatile uint32_t *reg, const void *mem, uint32_t len)
|
|
{
|
|
const uint32_t *p32 = (const uint32_t *)mem;
|
|
uint32_t i;
|
|
bool aligned_state;
|
|
|
|
aligned_state = config_unaligned_access(true);
|
|
|
|
i = 0;
|
|
while (i < len) {
|
|
*reg++ = *p32++;
|
|
i += 4;
|
|
}
|
|
|
|
config_unaligned_access(aligned_state);
|
|
}
|
|
|
|
POSSIBLY_UNUSED static void read_mreg(const volatile uint32_t *reg, void *mem, uint32_t len)
|
|
{
|
|
uint32_t *p32 = (uint32_t *)mem;
|
|
uint32_t i;
|
|
bool aligned_state;
|
|
|
|
aligned_state = config_unaligned_access(true);
|
|
|
|
i = 0;
|
|
while (i < len) {
|
|
*p32++ = *reg++;
|
|
i += 4;
|
|
}
|
|
|
|
config_unaligned_access(aligned_state);
|
|
}
|
|
|
|
enum HAL_SE_RET_T se_aes_crypt(const struct HAL_SE_AES_CFG_T *cfg, bool decrypt)
|
|
{
|
|
enum SE_AES_KEY_LEN_T key_len_t;
|
|
uint8_t modular;
|
|
|
|
if (!se_enabled) {
|
|
return HAL_SE_NOT_OPENED;
|
|
}
|
|
|
|
if (cfg == NULL) {
|
|
return HAL_SE_CFG_NULL;
|
|
}
|
|
if (cfg->in == NULL) {
|
|
return HAL_SE_INPUT_NULL;
|
|
}
|
|
if (cfg->out == NULL) {
|
|
return HAL_SE_OUTPUT_NULL;
|
|
}
|
|
if (cfg->key == NULL) {
|
|
return HAL_SE_KEY_NULL;
|
|
}
|
|
if (cfg->mode >= HAL_SE_AES_MODE_QTY) {
|
|
return HAL_SE_BAD_AES_MODE;
|
|
}
|
|
if (cfg->mode != HAL_SE_AES_ECB && cfg->iv == NULL) {
|
|
return HAL_SE_IV_NULL;
|
|
}
|
|
if (cfg->in_len < 16) {
|
|
return HAL_SE_BAD_INPUT_LEN;
|
|
}
|
|
if (cfg->mode == HAL_SE_AES_ECB) {
|
|
if (cfg->in_len & (16 - 1)) {
|
|
return HAL_SE_BAD_INPUT_LEN;
|
|
}
|
|
} else {
|
|
// TODO: Support padding or CBC CTS mode?
|
|
if (cfg->in_len & (16 - 1)) {
|
|
return HAL_SE_BAD_INPUT_LEN;
|
|
}
|
|
}
|
|
if (cfg->mode == HAL_SE_AES_KEY_WRAP) {
|
|
if (cfg->in_len & (8 - 1)) {
|
|
return HAL_SE_BAD_INPUT_LEN;
|
|
}
|
|
if (decrypt) {
|
|
if (cfg->out_len + 8 != cfg->in_len) {
|
|
return HAL_SE_BAD_OUTPUT_LEN;
|
|
}
|
|
} else {
|
|
if (cfg->out_len != cfg->in_len + 8) {
|
|
return HAL_SE_BAD_OUTPUT_LEN;
|
|
}
|
|
}
|
|
} else {
|
|
// If padding enabled,
|
|
// 1) ENC: cfg->out_len == ((cfg->in_len + 16) & ~(16 - 1))
|
|
// 2) DEC: cfg->out_len == cfg->in_len
|
|
if (cfg->out_len != cfg->in_len) {
|
|
return HAL_SE_BAD_OUTPUT_LEN;
|
|
}
|
|
}
|
|
modular = 0;
|
|
if (cfg->mode == HAL_SE_AES_CTR) {
|
|
if (cfg->ctr_modular > 128) {
|
|
return HAL_SE_BAD_AES_MODULAR;
|
|
} else if (cfg->ctr_modular < 128) {
|
|
modular = cfg->ctr_modular;
|
|
}
|
|
}
|
|
|
|
if (cfg->key_len == 16) {
|
|
key_len_t = SE_AES_KEY_128;
|
|
} else if (cfg->key_len == 24) {
|
|
key_len_t = SE_AES_KEY_192;
|
|
} else if (cfg->key_len == 32) {
|
|
key_len_t = SE_AES_KEY_256;
|
|
} else {
|
|
return HAL_SE_BAD_KEY_LEN;
|
|
}
|
|
|
|
if (se_crypt->AES_STATUS & AES_STATUS_BUSY) {
|
|
return HAL_SE_ENG_BUSY;
|
|
}
|
|
if (se_dma->ENBLDCHNS & (DMA_STAT_CHAN(SE_DMA_RX_CHAN) | DMA_STAT_CHAN(SE_DMA_TX_CHAN))) {
|
|
return HAL_SE_DMA_BUSY;
|
|
}
|
|
|
|
se_done_hdlr = cfg->done_hdlr;
|
|
|
|
se_adec->ADEC_CTRL |= ADEC_CTRL_CLK_EN_15_0(SE_ACC_CLK_CRYPT) | ADEC_CTRL_RST_15_0(SE_ACC_RST_CRYPT);
|
|
se_adec->ADEC_CTRL &= ~ADEC_CTRL_RST_15_0(SE_ACC_RST_CRYPT);
|
|
se_adec->ADEC_INT = SE_ACC_INT_AES;
|
|
se_adec->ADEC_INT_MSK &= ~SE_ACC_INT_AES;
|
|
|
|
se_dmacfg->DMA_FIFOCLR = DMA_FIFOCLR_RXFIFO_CLR | DMA_FIFOCLR_TXFIFO_CLR;
|
|
|
|
se_acb->ACB_CTRL &= ~(ACB_CTRL_WR_CB_CTRL | ACB_CTRL_RD_CB_CTRL);
|
|
|
|
se_crypt->ENGINE_SELECT = ENGINE_SELECT_SELECT(SE_CRYPT_AES);
|
|
// TODO: Set cts_mode, rkey
|
|
se_crypt->AES_CFG = AES_CFG_MODULAR(modular) | AES_CFG_MODE(cfg->mode) |
|
|
AES_CFG_KEYLEN(key_len_t) | (decrypt ? AES_CFG_DECRYPT : 0);
|
|
se_crypt->AES_INTRPT = ~0UL;
|
|
se_crypt->AES_INTRPT_SRC_EN = AES_INTRPT_SRC_EN_ERROR1 | AES_INTRPT_SRC_EN_ERROR2;
|
|
//se_crypt->AES_INTRPT_SRC_EN |= AES_INTRPT_SRC_EN_DONE;
|
|
// TODO: Set outputblock, resume
|
|
se_crypt->AES_CTRL |= AES_CTRL_RESET;
|
|
se_crypt->AES_CTRL &= ~AES_CTRL_RESET;
|
|
|
|
write_mreg(&se_crypt->KEY1[0], cfg->key, cfg->key_len);
|
|
if (cfg->mode != HAL_SE_AES_ECB) {
|
|
write_mreg(&se_crypt->IV[0], cfg->iv, 16);
|
|
if (cfg->mode == HAL_SE_AES_XTS) {
|
|
write_mreg(&se_crypt->KEY2[0], cfg->key2, cfg->key_len);
|
|
}
|
|
}
|
|
|
|
se_dma_enable_tx(cfg->in, cfg->in_len);
|
|
se_dma_enable_rx(cfg->out, cfg->out_len);
|
|
|
|
se_crypt->AES_STREAM_SIZE = cfg->in_len;
|
|
se_crypt->AES_CMD = AES_CMD_START;
|
|
|
|
return HAL_SE_OK;
|
|
}
|
|
|
|
enum HAL_SE_RET_T hal_se_aes_encrypt(const struct HAL_SE_AES_CFG_T *cfg)
|
|
{
|
|
return se_aes_crypt(cfg, false);
|
|
}
|
|
|
|
enum HAL_SE_RET_T hal_se_aes_decrypt(const struct HAL_SE_AES_CFG_T *cfg)
|
|
{
|
|
return se_aes_crypt(cfg, true);
|
|
}
|
|
|
|
int hal_se_aes_busy(void)
|
|
{
|
|
if (se_enabled) {
|
|
if (se_crypt->AES_STATUS & AES_STATUS_BUSY) {
|
|
return true;
|
|
}
|
|
if (se_dma->ENBLDCHNS & DMA_STAT_CHAN(SE_DMA_RX_CHAN)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
enum HAL_SE_RET_T hal_se_aes_reset(void)
|
|
{
|
|
uint32_t lock;
|
|
|
|
if (!se_enabled) {
|
|
return HAL_SE_NOT_OPENED;
|
|
}
|
|
|
|
lock = int_lock();
|
|
se_dma_cancel_rx();
|
|
se_dma_cancel_tx();
|
|
/* Clear all DMA interrupt and error flag */
|
|
se_dma->INTTCCLR = ~0UL;
|
|
se_dma->INTERRCLR = ~0UL;
|
|
|
|
se_adec->ADEC_CTRL |= ADEC_CTRL_CLK_EN_15_0(SE_ACC_CLK_CRYPT) | ADEC_CTRL_RST_15_0(SE_ACC_RST_CRYPT);
|
|
se_crypt->AES_INTRPT = ~0UL;
|
|
se_adec->ADEC_INT = SE_ACC_INT_AES;
|
|
int_unlock(lock);
|
|
|
|
return HAL_SE_OK;
|
|
}
|
|
|
|
#ifdef SEC_ENG_HAS_HASH
|
|
enum HAL_SE_RET_T se_hash_init(enum HAL_SE_HASH_MODE_T mode, const void *key, uint32_t key_len)
|
|
{
|
|
uint32_t val;
|
|
bool hmac;
|
|
|
|
if (!se_enabled) {
|
|
return HAL_SE_NOT_OPENED;
|
|
}
|
|
|
|
if (mode >= HAL_SE_HASH_QTY) {
|
|
return HAL_SE_BAD_MODE;
|
|
}
|
|
|
|
hmac = (key_len > 0);
|
|
if (hmac) {
|
|
if (key == NULL) {
|
|
return HAL_SE_KEY_NULL;
|
|
}
|
|
if (mode == HAL_SE_HASH_SHA384 || mode == HAL_SE_HASH_SHA512) {
|
|
if (key_len > 128) {
|
|
return HAL_SE_BAD_KEY_LEN;
|
|
}
|
|
} else {
|
|
if (key_len > 64) {
|
|
return HAL_SE_BAD_KEY_LEN;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (se_hash->HASH_STATUS & HASH_STATUS_HASH_BUSY) {
|
|
return HAL_SE_ENG_BUSY;
|
|
}
|
|
if (se_dma->ENBLDCHNS & DMA_STAT_CHAN(SE_DMA_TX_CHAN)) {
|
|
return HAL_SE_DMA_BUSY;
|
|
}
|
|
|
|
se_adec->ADEC_CTRL |= ADEC_CTRL_CLK_EN_15_0(SE_ACC_CLK_HASH) | ADEC_CTRL_RST_15_0(SE_ACC_RST_HASH);
|
|
se_adec->ADEC_CTRL &= ~ADEC_CTRL_RST_15_0(SE_ACC_RST_HASH);
|
|
se_adec->ADEC_INT = SE_ACC_INT_HASH;
|
|
se_adec->ADEC_INT_MSK |= SE_ACC_INT_HASH;
|
|
|
|
se_dmacfg->DMA_FIFOCLR = DMA_FIFOCLR_TXFIFO_CLR;
|
|
|
|
se_acb->ACB_CTRL |= ACB_CTRL_RD_CB_CTRL;
|
|
|
|
se_hash->HASH_CFG = HASH_CFG_ALG_SELECT(mode);
|
|
val = se_hash->HASH_CTRL;
|
|
//val |= HASH_CTRL_RESET;
|
|
se_hash->HASH_CTRL = val;
|
|
val &= ~(HASH_CTRL_RESET | HASH_CTRL_HW_PADDING);
|
|
se_hash->HASH_CTRL = val;
|
|
val = SET_BITFIELD(val, HASH_CTRL_HASH_OP_MODE, SE_HASH_OP_INIT);
|
|
se_hash->HASH_CTRL = val;
|
|
if (hmac) {
|
|
se_hash->HASH_CFG |= HASH_CFG_HASH_MODE;
|
|
write_mreg(&se_hash->HMAC_KEY[0], key, key_len);
|
|
se_hash->HMAC_KEY_LEN = key_len;
|
|
}
|
|
se_hash->HASH_CMD = HASH_CMD_START;
|
|
|
|
// HASH: 500ns; HMAC: 3000ns
|
|
while ((se_hash->HASH_STATUS & HASH_STATUS_HASH_DONE) == 0);
|
|
|
|
return HAL_SE_OK;
|
|
}
|
|
|
|
enum HAL_SE_RET_T hal_se_hash_init(enum HAL_SE_HASH_MODE_T mode)
|
|
{
|
|
return se_hash_init(mode, NULL, 0);
|
|
}
|
|
|
|
enum HAL_SE_RET_T se_hash_start(const struct HAL_SE_HASH_CFG_T *cfg, enum SE_HASH_OP_T op, uint64_t total_in_len)
|
|
{
|
|
enum SE_HASH_OP_T prev_op;
|
|
uint32_t val;
|
|
|
|
if (!se_enabled) {
|
|
return HAL_SE_NOT_OPENED;
|
|
}
|
|
|
|
if (cfg == NULL) {
|
|
return HAL_SE_CFG_NULL;
|
|
}
|
|
if (op == SE_HASH_OP_FINAL) {
|
|
if (cfg->in == NULL && cfg->in_len) {
|
|
return HAL_SE_INPUT_NULL;
|
|
}
|
|
} else {
|
|
if (cfg->in == NULL) {
|
|
return HAL_SE_INPUT_NULL;
|
|
}
|
|
if (cfg->in_len == 0) {
|
|
return HAL_SE_BAD_INPUT_LEN;
|
|
}
|
|
if (cfg->in_len & (64 - 1)) {
|
|
return HAL_SE_BAD_INPUT_LEN;
|
|
}
|
|
}
|
|
|
|
prev_op = GET_BITFIELD(se_hash->HASH_CTRL, HASH_CTRL_HASH_OP_MODE);
|
|
if (prev_op != SE_HASH_OP_INIT && prev_op != SE_HASH_OP_UPDATE) {
|
|
return HAL_SE_BAD_OP;
|
|
}
|
|
if (se_hash->HASH_STATUS & HASH_STATUS_HASH_BUSY) {
|
|
return HAL_SE_ENG_BUSY;
|
|
}
|
|
if (se_dma->ENBLDCHNS & DMA_STAT_CHAN(SE_DMA_TX_CHAN)) {
|
|
return HAL_SE_DMA_BUSY;
|
|
}
|
|
|
|
se_done_hdlr = cfg->done_hdlr;
|
|
|
|
se_hash->HASH_STATUS = ~0UL;
|
|
se_adec->ADEC_INT = SE_ACC_INT_HASH;
|
|
se_adec->ADEC_INT_MSK &= ~SE_ACC_INT_HASH;
|
|
|
|
se_dmacfg->DMA_FIFOCLR = DMA_FIFOCLR_TXFIFO_CLR;
|
|
|
|
if (cfg->in_len) {
|
|
se_dma_enable_tx(cfg->in, cfg->in_len);
|
|
}
|
|
|
|
val = se_hash->HASH_CTRL;
|
|
val = SET_BITFIELD(val, HASH_CTRL_HASH_OP_MODE, op);
|
|
if (op == SE_HASH_OP_UPDATE) {
|
|
val &= ~HASH_CTRL_HW_PADDING;
|
|
} else {
|
|
val |= HASH_CTRL_HW_PADDING;
|
|
}
|
|
se_hash->HASH_CTRL = val;
|
|
if (op == SE_HASH_OP_FINAL) {
|
|
se_hash->HASH_MSG_SIZE_L = (uint32_t)total_in_len;
|
|
se_hash->HASH_MSG_SIZE_H = (uint32_t)(total_in_len >> 32);
|
|
}
|
|
se_hash->HASH_SEG_SIZE = cfg->in_len;
|
|
se_hash->HASH_CMD = HASH_CMD_START;
|
|
|
|
return HAL_SE_OK;
|
|
}
|
|
|
|
enum HAL_SE_RET_T hal_se_hash_update(const struct HAL_SE_HASH_CFG_T *cfg)
|
|
{
|
|
return se_hash_start(cfg, SE_HASH_OP_UPDATE, 0);
|
|
}
|
|
|
|
enum HAL_SE_RET_T hal_se_hash_final(const struct HAL_SE_HASH_CFG_T *cfg, uint64_t total_in_len)
|
|
{
|
|
return se_hash_start(cfg, SE_HASH_OP_FINAL, total_in_len);
|
|
}
|
|
|
|
enum HAL_SE_RET_T hal_se_hash(enum HAL_SE_HASH_MODE_T mode, const struct HAL_SE_HASH_CFG_T *cfg)
|
|
{
|
|
enum HAL_SE_RET_T ret;
|
|
|
|
ret = hal_se_hash_init(mode);
|
|
if (ret != HAL_SE_OK) {
|
|
return ret;
|
|
}
|
|
ret = hal_se_hash_final(cfg, cfg->in_len);
|
|
return ret;
|
|
}
|
|
|
|
static uint32_t se_hash_get_digest_len(void)
|
|
{
|
|
enum HAL_SE_HASH_MODE_T mode;
|
|
uint32_t max_len;
|
|
|
|
mode = GET_BITFIELD(se_hash->HASH_CFG, HASH_CFG_ALG_SELECT);
|
|
if (mode == HAL_SE_HASH_MD5) {
|
|
max_len = 16;
|
|
} else if (mode == HAL_SE_HASH_SHA1) {
|
|
max_len = 20;
|
|
} else if (mode == HAL_SE_HASH_SHA224) {
|
|
max_len = 28;
|
|
} else if (mode == HAL_SE_HASH_SHA256) {
|
|
max_len = 32;
|
|
} else if (mode == HAL_SE_HASH_SHA384) {
|
|
max_len = 48;
|
|
} else {
|
|
max_len = 64;
|
|
}
|
|
|
|
return max_len;
|
|
}
|
|
|
|
enum HAL_SE_RET_T hal_se_hash_get_digest(void *out, uint32_t out_len, uint32_t *real_len)
|
|
{
|
|
enum SE_HASH_OP_T prev_op;
|
|
uint32_t max_len;
|
|
int i;
|
|
|
|
if (!se_enabled) {
|
|
return HAL_SE_NOT_OPENED;
|
|
}
|
|
|
|
if (out == NULL) {
|
|
return HAL_SE_OUTPUT_NULL;
|
|
}
|
|
if (out_len & (4 - 1)) {
|
|
return HAL_SE_BAD_OUTPUT_LEN;
|
|
}
|
|
|
|
prev_op = GET_BITFIELD(se_hash->HASH_CTRL, HASH_CTRL_HASH_OP_MODE);
|
|
if (prev_op != SE_HASH_OP_FINAL) {
|
|
return HAL_SE_BAD_OP;
|
|
}
|
|
if (se_hash->HASH_STATUS & HASH_STATUS_HASH_BUSY) {
|
|
return HAL_SE_ENG_BUSY;
|
|
}
|
|
if (se_dma->ENBLDCHNS & DMA_STAT_CHAN(SE_DMA_TX_CHAN)) {
|
|
return HAL_SE_DMA_BUSY;
|
|
}
|
|
|
|
max_len = se_hash_get_digest_len();
|
|
if (out_len > max_len) {
|
|
out_len = max_len;
|
|
}
|
|
if (real_len) {
|
|
*real_len = out_len;
|
|
}
|
|
if (out_len > 32) {
|
|
for (i = 0; i < out_len / 8; i++) {
|
|
read_mreg(&se_hash->HASH_CTX_H[i], out, 4);
|
|
read_mreg(&se_hash->HASH_CTX[i], out + 4, 4);
|
|
out += 8;
|
|
}
|
|
} else {
|
|
read_mreg(&se_hash->HASH_CTX[0], out, out_len);
|
|
}
|
|
|
|
return HAL_SE_OK;
|
|
}
|
|
|
|
int hal_se_hash_busy(void)
|
|
{
|
|
if (se_enabled) {
|
|
if (se_hash->HASH_STATUS & HASH_STATUS_HASH_BUSY) {
|
|
return true;
|
|
}
|
|
if (se_dma->ENBLDCHNS & DMA_STAT_CHAN(SE_DMA_TX_CHAN)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
enum HAL_SE_RET_T hal_se_hash_reset(void)
|
|
{
|
|
uint32_t lock;
|
|
|
|
if (!se_enabled) {
|
|
return HAL_SE_NOT_OPENED;
|
|
}
|
|
|
|
lock = int_lock();
|
|
se_dma_cancel_tx();
|
|
/* Clear all DMA interrupt and error flag */
|
|
se_dma->INTTCCLR = ~0UL;
|
|
se_dma->INTERRCLR = ~0UL;
|
|
|
|
se_adec->ADEC_CTRL |= ADEC_CTRL_CLK_EN_15_0(SE_ACC_CLK_HASH) | ADEC_CTRL_RST_15_0(SE_ACC_RST_HASH);
|
|
se_hash->HASH_STATUS = ~0UL;
|
|
se_adec->ADEC_INT = SE_ACC_INT_HASH;
|
|
int_unlock(lock);
|
|
|
|
return HAL_SE_OK;
|
|
}
|
|
|
|
enum HAL_SE_RET_T hal_se_hmac_init(enum HAL_SE_HASH_MODE_T mode, const void *key, uint32_t key_len)
|
|
{
|
|
if (key_len == 0) {
|
|
return HAL_SE_BAD_KEY_LEN;
|
|
}
|
|
|
|
return se_hash_init(mode, key, key_len);
|
|
}
|
|
|
|
enum HAL_SE_RET_T hal_se_hmac_update(const struct HAL_SE_HASH_CFG_T *cfg) __attribute__((alias("hal_se_hash_update")));
|
|
|
|
enum HAL_SE_RET_T hal_se_hmac_final(const struct HAL_SE_HASH_CFG_T *cfg, uint64_t total_in_len) __attribute__((alias("hal_se_hash_final")));
|
|
|
|
enum HAL_SE_RET_T hal_se_hmac(enum HAL_SE_HASH_MODE_T mode, const void *key, uint32_t key_len, const struct HAL_SE_HASH_CFG_T *cfg)
|
|
{
|
|
enum HAL_SE_RET_T ret;
|
|
|
|
ret = hal_se_hmac_init(mode, key, key_len);
|
|
if (ret != HAL_SE_OK) {
|
|
return ret;
|
|
}
|
|
ret = hal_se_hmac_final(cfg, cfg->in_len);
|
|
return ret;
|
|
}
|
|
|
|
enum HAL_SE_RET_T hal_se_hmac_get_digest(void *out, uint32_t out_len, uint32_t *real_len) __attribute__((alias("hal_se_hash_get_digest")));
|
|
|
|
int hal_se_hmac_busy(void) __attribute__((alias("hal_se_hash_busy")));
|
|
|
|
enum HAL_SE_RET_T hal_se_hmac_reset(void) __attribute__((alias("hal_se_hash_reset")));
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|