402 lines
14 KiB
C
402 lines
14 KiB
C
/**
|
|
* @file ske_cmac.c
|
|
* @brief Semidrive CRYPTO ske cmac source file.
|
|
*
|
|
* @copyright Copyright (c) 2021 Semidrive Semiconductor.
|
|
* All rights reserved.
|
|
*/
|
|
|
|
#include <ske_cmac.h>
|
|
#ifdef SUPPORT_SKE_MODE_CMAC
|
|
|
|
/* function: ske_hp cmac internal init config
|
|
* parameters:
|
|
* ctx ------------------------ input, ske_cmac_ctx_t context pointer
|
|
* alg ------------------------ input, ske_hp algorithm
|
|
* key ------------------------ input, key in byte buffer style
|
|
* sp_key_idx ----------------- input, index of secure port key, (sp_key_idx
|
|
* & 0x7FFF) must be in [1,MAX_KEY_IDX], if the MSB(sp_key_idx) is 1, that means
|
|
* using low 128bit of the 256bit key return: SKE_SUCCESS(success), other(error)
|
|
* caution:
|
|
* 1. if key is from user input, please make sure key is not NULL(now
|
|
* sp_key_idx is useless), otherwise, key is from secure port, and (sp_key_idx &
|
|
* 0x7FFF) must be in [1,MAX_KEY_IDX]
|
|
*/
|
|
uint32_t ske_hp_cmac_init_internal(ske_cmac_ctx_t *ctx, SKE_ALG alg,
|
|
uint8_t *key, uint16_t sp_key_idx)
|
|
{
|
|
uint32_t iv[4];
|
|
|
|
uint32_clear(iv, 4);
|
|
|
|
return ske_hp_init_internal(ctx->ske_cmac_ctx, alg, SKE_MODE_CMAC,
|
|
SKE_CRYPTO_ENCRYPT, key, sp_key_idx,
|
|
(uint8_t *)iv);
|
|
}
|
|
|
|
/* function: ske_hp cmac init(CPU style)
|
|
* parameters:
|
|
* ctx ------------------------ input, ske_cmac_ctx_t context pointer
|
|
* alg ------------------------ input, ske_hp algorithm
|
|
* key ------------------------ input, key in byte buffer style
|
|
* sp_key_idx ----------------- input, index of secure port key, (sp_key_idx
|
|
* & 0x7FFF) must be in [1,MAX_KEY_IDX] return: SKE_SUCCESS(success),
|
|
* other(error) caution:
|
|
* 1. if key is from user input, please make sure key is not NULL(now
|
|
* sp_key_idx is useless), otherwise, key is from secure port, and (sp_key_idx &
|
|
* 0x7FFF) must be in [1,MAX_KEY_IDX]
|
|
*/
|
|
uint32_t ske_hp_cmac_init(ske_cmac_ctx_t *ctx, SKE_ALG alg, uint8_t *key,
|
|
uint16_t sp_key_idx)
|
|
{
|
|
/*check and keep ctx->left_bytes = 0*/
|
|
if (NULL == ctx) {
|
|
return SKE_BUFFER_NULL;
|
|
} else {
|
|
ctx->left_bytes = 0;
|
|
}
|
|
|
|
ske_hp_set_cpu_mode();
|
|
|
|
return ske_hp_cmac_init_internal(ctx, alg, key, sp_key_idx);
|
|
}
|
|
|
|
/* function: ske_hp cmac update message(CPU style)
|
|
* parameters:
|
|
* ctx ------------------------ input, ske_cmac_ctx_t context pointer
|
|
* msg ------------------------ input, message
|
|
* msg_bytes ------------------ input, byte length of message.
|
|
* return: SKE_SUCCESS(success), other(error)
|
|
* caution:
|
|
* 1. msg_bytes could be any value.
|
|
*/
|
|
uint32_t ske_hp_cmac_update(ske_cmac_ctx_t *ctx, uint8_t *msg,
|
|
uint32_t msg_bytes)
|
|
{
|
|
uint32_t blocks_bytes;
|
|
uint32_t ret;
|
|
uint8_t fill_bytes, remainder;
|
|
|
|
if (NULL == ctx) {
|
|
return SKE_BUFFER_NULL;
|
|
} else if (NULL == msg || 0 == msg_bytes) {
|
|
return SKE_SUCCESS;
|
|
} else {
|
|
;
|
|
}
|
|
|
|
/*if one block left, process it*/
|
|
if (ctx->ske_cmac_ctx->block_bytes == ctx->left_bytes) {
|
|
ret = ske_hp_update_blocks_no_output(ctx->ske_cmac_ctx, ctx->block_buf,
|
|
ctx->ske_cmac_ctx->block_bytes);
|
|
|
|
if (SKE_SUCCESS != ret) {
|
|
return ret;
|
|
} else {
|
|
ctx->left_bytes = 0;
|
|
}
|
|
}
|
|
|
|
/*padding*/
|
|
if (ctx->left_bytes) {
|
|
fill_bytes = ctx->ske_cmac_ctx->block_bytes - ctx->left_bytes;
|
|
|
|
if (msg_bytes <= fill_bytes) {
|
|
memcpy_(ctx->block_buf + ctx->left_bytes, msg, msg_bytes);
|
|
ctx->left_bytes += msg_bytes;
|
|
return SKE_SUCCESS;
|
|
} else {
|
|
memcpy_(ctx->block_buf + ctx->left_bytes, msg, fill_bytes);
|
|
ret = ske_hp_update_blocks_no_output(
|
|
ctx->ske_cmac_ctx, ctx->block_buf,
|
|
ctx->ske_cmac_ctx->block_bytes);
|
|
|
|
if (SKE_SUCCESS != ret) {
|
|
return ret;
|
|
} else {
|
|
ctx->left_bytes = 0;
|
|
msg += fill_bytes;
|
|
msg_bytes -= fill_bytes;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*process some blocks*/
|
|
blocks_bytes = (msg_bytes / ctx->ske_cmac_ctx->block_bytes) *
|
|
ctx->ske_cmac_ctx->block_bytes;
|
|
remainder = msg_bytes % ctx->ske_cmac_ctx->block_bytes;
|
|
|
|
/*process remainder*/
|
|
if (remainder) {
|
|
ret = ske_hp_update_blocks_no_output(ctx->ske_cmac_ctx, msg,
|
|
blocks_bytes);
|
|
|
|
if (SKE_SUCCESS != ret) {
|
|
return ret;
|
|
} else {
|
|
memcpy_(ctx->block_buf, msg + blocks_bytes, remainder);
|
|
ctx->left_bytes = remainder;
|
|
}
|
|
} else {
|
|
blocks_bytes -= ctx->ske_cmac_ctx->block_bytes;
|
|
ret = ske_hp_update_blocks_no_output(ctx->ske_cmac_ctx, msg,
|
|
blocks_bytes);
|
|
|
|
if (SKE_SUCCESS != ret) {
|
|
return ret;
|
|
} else {
|
|
memcpy_(ctx->block_buf, msg + blocks_bytes,
|
|
ctx->ske_cmac_ctx->block_bytes);
|
|
ctx->left_bytes = ctx->ske_cmac_ctx->block_bytes;
|
|
}
|
|
}
|
|
|
|
return SKE_SUCCESS;
|
|
}
|
|
|
|
/* function: ske_hp cmac finish, and get the mac(CPU style)
|
|
* parameters:
|
|
* ctx ------------------------ input, ske_cmac_ctx_t context pointer
|
|
* mac ------------------------ output, mac
|
|
* mac_bytes ------------------ input, mac byte length, must be bigger than
|
|
* 1, and not bigger than block length return: SKE_SUCCESS(success),
|
|
* other(error) caution:
|
|
* 1. .
|
|
*/
|
|
uint32_t ske_hp_cmac_final(ske_cmac_ctx_t *ctx, uint8_t *mac, uint8_t mac_bytes)
|
|
{
|
|
uint32_t tmp[4];
|
|
uint32_t ret;
|
|
|
|
if ((NULL == ctx) || (NULL == mac)) {
|
|
return SKE_BUFFER_NULL;
|
|
} else if ((0 == mac_bytes) ||
|
|
(mac_bytes > ctx->ske_cmac_ctx->block_bytes)) {
|
|
return SKE_INPUT_INVALID;
|
|
} else {
|
|
;
|
|
}
|
|
|
|
ske_hp_set_last_block(1);
|
|
ske_hp_set_last_block_len(ctx->left_bytes);
|
|
|
|
if (ctx->ske_cmac_ctx->block_bytes == ctx->left_bytes) {
|
|
ret = ske_hp_update_blocks_internal(ctx->ske_cmac_ctx, ctx->block_buf,
|
|
(uint8_t *)tmp,
|
|
ctx->ske_cmac_ctx->block_bytes);
|
|
|
|
if (SKE_SUCCESS != ret) {
|
|
return ret;
|
|
} else {
|
|
;
|
|
}
|
|
} else {
|
|
ctx->block_buf[ctx->left_bytes] = 0x80;
|
|
memset_(ctx->block_buf + ctx->left_bytes + 1, 0,
|
|
ctx->ske_cmac_ctx->block_bytes - 1 - ctx->left_bytes);
|
|
ret = ske_hp_update_blocks_internal(ctx->ske_cmac_ctx, ctx->block_buf,
|
|
(uint8_t *)tmp,
|
|
ctx->ske_cmac_ctx->block_bytes);
|
|
|
|
if (SKE_SUCCESS != ret) {
|
|
return ret;
|
|
} else {
|
|
;
|
|
}
|
|
}
|
|
|
|
memcpy_(mac, tmp, mac_bytes);
|
|
|
|
return SKE_SUCCESS;
|
|
}
|
|
|
|
/* function: ske_hp cmac(CPU style, one-off style)
|
|
* parameters:
|
|
* alg ------------------------ input, ske_hp algorithm
|
|
* key ------------------------ input, key in byte buffer style
|
|
* sp_key_idx ----------------- input, index of secure port key, (sp_key_idx
|
|
* & 0x7FFF) must be in [1,MAX_KEY_IDX], if the MSB(sp_key_idx) is 1, that means
|
|
* using low 128bit of the 256bit key msg ------------------------ input,
|
|
* message msg_bytes ------------------ input, byte length of message. mac
|
|
* ------------------------ output, mac mac_bytes ------------------ input, mac
|
|
* byte length, must be bigger than 1, and not bigger than block length return:
|
|
* SKE_SUCCESS(success), other(error) caution:
|
|
* 1. if key is from user input, please make sure key is not NULL(now
|
|
* sp_key_idx is useless), otherwise, key is from secure port, and (sp_key_idx &
|
|
* 0x7FFF) must be in [1,MAX_KEY_IDX]
|
|
* 2. msg_bytes could be any value(including 0).
|
|
*/
|
|
uint32_t ske_hp_cmac(SKE_ALG alg, uint8_t *key, uint16_t sp_key_idx,
|
|
uint8_t *msg, uint32_t msg_bytes, uint8_t *mac,
|
|
uint8_t mac_bytes)
|
|
{
|
|
ske_cmac_ctx_t ctx[1];
|
|
uint32_t ret;
|
|
|
|
ret = ske_hp_cmac_init(ctx, alg, key, sp_key_idx);
|
|
|
|
if (SKE_SUCCESS != ret) {
|
|
return ret;
|
|
} else {
|
|
;
|
|
}
|
|
|
|
ret = ske_hp_cmac_update(ctx, msg, msg_bytes);
|
|
|
|
if (SKE_SUCCESS != ret) {
|
|
return ret;
|
|
} else {
|
|
;
|
|
}
|
|
|
|
return ske_hp_cmac_final(ctx, mac, mac_bytes);
|
|
}
|
|
|
|
#ifdef SKE_HP_DMA_FUNCTION
|
|
/* function: ske_hp cmac dma style init
|
|
* parameters:
|
|
* ctx ------------------------ input, ske_cmac_dma_ctx_t context pointer
|
|
* alg ------------------------ input, ske_hp algorithm
|
|
* key ------------------------ input, key in byte buffer style
|
|
* sp_key_idx ----------------- input, index of secure port key, (sp_key_idx
|
|
* & 0x7FFF) must be in [1,MAX_KEY_IDX], if the MSB(sp_key_idx) is 1, that means
|
|
* using low 128bit of the 256bit key return: SKE_SUCCESS(success), other(error)
|
|
* caution:
|
|
* 1. if key is from user input, please make sure key is not NULL(now
|
|
* sp_key_idx is useless), otherwise, key is from secure port, and (sp_key_idx &
|
|
* 0x7FFF) must be in [1,MAX_KEY_IDX]
|
|
*/
|
|
uint32_t ske_hp_dma_cmac_init(ske_cmac_dma_ctx_t *ctx, SKE_ALG alg,
|
|
uint8_t *key, uint16_t sp_key_idx)
|
|
{
|
|
if (NULL == ctx) {
|
|
return SKE_BUFFER_NULL;
|
|
} else {
|
|
;
|
|
}
|
|
|
|
ske_hp_set_dma_mode();
|
|
ske_hp_disable_dma_linked_list();
|
|
|
|
return ske_hp_cmac_init_internal((ske_cmac_ctx_t *)ctx, alg, key,
|
|
sp_key_idx);
|
|
}
|
|
|
|
/* function: ske cmac dma style update update message blocks(excluding the last
|
|
* block, or the message tail) parameters: ctx ------------------------ input,
|
|
* ske_cmac_dma_ctx_t context pointer msg ------------------------ input,
|
|
* message of some blocks, excluding last block(or message tail) msg_words
|
|
* ------------------ input, word length of msg, must be a multiple of block
|
|
* word length return: SKE_SUCCESS(success), other(error) caution:
|
|
* 1. the input msg must be some blocks, and excludes the last block(or
|
|
* message tail)
|
|
*/
|
|
uint32_t ske_hp_dma_cmac_update_blocks_excluding_last_block(
|
|
ske_cmac_dma_ctx_t *ctx, uint32_t *msg, uint32_t msg_words)
|
|
{
|
|
if (NULL == ctx) {
|
|
return SKE_BUFFER_NULL;
|
|
} else if (msg_words & (ctx->ske_cmac_ctx->block_words - 1)) {
|
|
return SKE_INPUT_INVALID;
|
|
} else if ((NULL == msg) || (0 == msg_words)) {
|
|
return SKE_SUCCESS;
|
|
} else {
|
|
;
|
|
}
|
|
|
|
return ske_hp_dma_operate_without_output(ctx->ske_cmac_ctx, msg, msg_words);
|
|
}
|
|
|
|
/* function: ske_hp cmac dma style update message including the last block(or
|
|
* message tail), and get the mac parameters: ctx ------------------------
|
|
* input, ske_cmac_dma_ctx_t context pointer msg ------------------------ input,
|
|
* message including the last block(or message tail) msg_bytes
|
|
* ------------------ input, byte length of msg, could be 0 mac
|
|
* ------------------------ output, cmac, occupies a block return:
|
|
* SKE_SUCCESS(success), other(error) caution:
|
|
* 1. if the whole message length is 0, this case is supported. in this
|
|
* case, msg occupies a block, and please set msg_bytes to 0.
|
|
*/
|
|
uint32_t ske_hp_dma_cmac_update_including_last_block(ske_cmac_dma_ctx_t *ctx,
|
|
uint32_t *msg,
|
|
uint32_t msg_bytes,
|
|
uint32_t *mac)
|
|
{
|
|
uint32_t msg_words;
|
|
uint32_t remainder_bytes;
|
|
|
|
if ((NULL == ctx) || (NULL == msg) || (NULL == mac)) {
|
|
return SKE_BUFFER_NULL;
|
|
} else {
|
|
;
|
|
}
|
|
|
|
ske_hp_set_last_block(1);
|
|
|
|
/*get last block length and pad padded by software, not hardware, do not
|
|
* delete this padding action*/
|
|
if (0 == msg_bytes) {
|
|
msg[0] = 0x80;
|
|
msg[1] = 0;
|
|
msg[2] = 0;
|
|
msg[3] = 0;
|
|
|
|
msg_bytes = 1;
|
|
remainder_bytes = 1;
|
|
} else if (msg_bytes & 0x0F) {
|
|
msg[msg_bytes / 4] |= 0x80 << ((msg_bytes & 3) * 8);
|
|
remainder_bytes = msg_bytes & 0x0F;
|
|
} else {
|
|
remainder_bytes = ctx->ske_cmac_ctx->block_bytes;
|
|
}
|
|
|
|
/*set the last block message length*/
|
|
ske_hp_set_last_block_len(remainder_bytes);
|
|
|
|
msg_words = (msg_bytes + ctx->ske_cmac_ctx->block_bytes - 1) /
|
|
ctx->ske_cmac_ctx->block_bytes;
|
|
msg_words *= ctx->ske_cmac_ctx->block_words;
|
|
|
|
return ske_hp_dma_operate(ctx->ske_cmac_ctx, msg, mac, msg_words,
|
|
ctx->ske_cmac_ctx->block_words);
|
|
}
|
|
|
|
/* function: ske_hp cmac(DMA style, one-off style)
|
|
* parameters:
|
|
* alg ------------------------ input, ske_hp algorithm
|
|
* key ------------------------ input, key in byte buffer style
|
|
* sp_key_idx ----------------- input, index of secure port key, (sp_key_idx
|
|
* & 0x7FFF) must be in [1,MAX_KEY_IDX], if the MSB(sp_key_idx) is 1, that means
|
|
* using low 128bit of the 256bit key msg ------------------------ input,
|
|
* message msg_bytes ------------------ input, byte length of message. mac
|
|
* ------------------------ output, mac return: SKE_SUCCESS(success),
|
|
* other(error) caution:
|
|
* 1. if key is from user input, please make sure key is not NULL(now
|
|
* sp_key_idx is useless), otherwise, key is from secure port, and (sp_key_idx &
|
|
* 0x7FFF) must be in [1,MAX_KEY_IDX]
|
|
* 2. msg_bytes is actual byte length of message, it could be any
|
|
* value(including 0). (1). if msg_bytes is not 0, msg must have
|
|
* (msg_bytes+15)/16 blocks, if the last block is not full, please pad with
|
|
* zero. (2). if msg_bytes is 0, msg occupies a block.
|
|
*/
|
|
uint32_t ske_hp_dma_cmac(SKE_ALG alg, uint8_t *key, uint16_t sp_key_idx,
|
|
uint32_t *msg, uint32_t msg_bytes, uint32_t *mac)
|
|
{
|
|
uint32_t ret;
|
|
ske_cmac_dma_ctx_t ctx[1];
|
|
|
|
ret = ske_hp_dma_cmac_init(ctx, alg, key, sp_key_idx);
|
|
|
|
if (SKE_SUCCESS != ret) {
|
|
return ret;
|
|
} else {
|
|
;
|
|
}
|
|
|
|
return ske_hp_dma_cmac_update_including_last_block(ctx, msg, msg_bytes,
|
|
mac);
|
|
}
|
|
#endif
|
|
|
|
#endif
|