Files
1CAR/drivers/source/crypto/cacc/hash_hmac/hash.c
2025-10-25 21:11:06 +08:00

1178 lines
28 KiB
C

/*****************************************************************************
*
*
*Copyright (c) 2021-2029 Semidrive Incorporated. All rights reserved.
*Software License Agreement
*
******************************************************************************
*/
#include <hash.h>
#define LOCAL_TRACE 0
/*HASH IV definition*/
#ifndef HASH_CPU_BIG_ENDIAN
#ifdef SUPPORT_HASH_SM3
uint32_t const SM3_IV[8] = {
0x6F168073, 0xB9B21449, 0xD7422417, 0x00068ADA,
0xBC306FA9, 0xAA383116, 0x4DEE8DE3, 0x4E0EFBB0,
};
#endif
#ifdef SUPPORT_HASH_MD5
uint32_t const MD5_IV[4] = {
0x67452301,
0xefcdab89,
0x98badcfe,
0x10325476,
};
#endif
#ifdef SUPPORT_HASH_SHA256
uint32_t const SHA256_IV[8] = {
0x67E6096A, 0x85AE67BB, 0x72F36E3C, 0x3AF54FA5,
0x7F520E51, 0x8C68059B, 0xABD9831F, 0x19CDE05B,
};
#endif
#ifdef SUPPORT_HASH_SHA384
uint32_t const SHA384_IV[16] = {
0x5D9DBBCB, 0xD89E05C1, 0x2A299A62, 0x07D57C36, 0x5A015991, 0x17DD7030,
0xD8EC2F15, 0x39590EF7, 0x67263367, 0x310BC0FF, 0x874AB48E, 0x11155868,
0x0D2E0CDB, 0xA78FF964, 0x1D48B547, 0xA44FFABE,
};
#endif
#ifdef SUPPORT_HASH_SHA512
uint32_t const SHA512_IV[16] = {
0x67E6096A, 0x08C9BCF3, 0x85AE67BB, 0x3BA7CA84, 0x72F36E3C, 0x2BF894FE,
0x3AF54FA5, 0xF1361D5F, 0x7F520E51, 0xD182E6AD, 0x8C68059B, 0x1F6C3E2B,
0xABD9831F, 0x6BBD41FB, 0x19CDE05B, 0x79217E13,
};
#endif
#ifdef SUPPORT_HASH_SHA1
uint32_t const SHA1_IV[5] = {
0x01234567, 0x89ABCDEF, 0xFEDCBA98, 0x76543210, 0xF0E1D2C3,
};
#endif
#ifdef SUPPORT_HASH_SHA224
uint32_t const SHA224_IV[8] = {
0xD89E05C1, 0x07D57C36, 0x17DD7030, 0x39590EF7,
0x310BC0FF, 0x11155868, 0xA78FF964, 0xA44FFABE,
};
#endif
#ifdef SUPPORT_HASH_SHA512_224
uint32_t const SHA512_224_IV[16] = {
0xC8373D8C, 0xA24D5419, 0x6699E173, 0xD6D4DC89, 0xAEB7FA1D, 0x829CFF32,
0x14D59D67, 0xCF9F2F58, 0x692B6D0F, 0xA84DD47B, 0x736FE377, 0x4289C404,
0xA8859D3F, 0xC8361D6A, 0xADE61211, 0xA192D691,
};
#endif
#ifdef SUPPORT_HASH_SHA512_256
uint32_t const SHA512_256_IV[16] = {
0x94213122, 0x2CF72BFC, 0xA35F559F, 0xC2644CC8, 0x6BB89323, 0x51B1536F,
0x19773896, 0xBDEA4059, 0xE23E2896, 0xE3FF8EA8, 0x251E5EBE, 0x92398653,
0xFC99012B, 0xAAB8852C, 0xDC2DB70E, 0xA22CC581,
};
#endif
#else
#ifdef SUPPORT_HASH_SM3
uint32_t const SM3_IV[8] = {
0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600,
0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e,
};
#endif
#ifdef SUPPORT_HASH_MD5
uint32_t const MD5_IV[4] = {
0x01234567,
0x89ABCDEF,
0xFEDCBA98,
0x76543210,
};
#endif
#ifdef SUPPORT_HASH_SHA256
uint32_t const SHA256_IV[8] = {
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
};
#endif
#ifdef SUPPORT_HASH_SHA384
uint32_t const SHA384_IV[16] = {
0xcbbb9d5d, 0xc1059ed8, 0x629a292a, 0x367cd507, 0x9159015a, 0x3070dd17,
0x152fecd8, 0xf70e5939, 0x67332667, 0xffc00b31, 0x8eb44a87, 0x68581511,
0xdb0c2e0d, 0x64f98fa7, 0x47b5481d, 0xbefa4fa4,
};
#endif
#ifdef SUPPORT_HASH_SHA512
uint32_t const SHA512_IV[16] = {
0x6a09e667, 0xf3bcc908, 0xbb67ae85, 0x84caa73b, 0x3c6ef372, 0xfe94f82b,
0xa54ff53a, 0x5f1d36f1, 0x510e527f, 0xade682d1, 0x9b05688c, 0x2b3e6c1f,
0x1f83d9ab, 0xfb41bd6b, 0x5be0cd19, 0x137e2179,
};
#endif
#ifdef SUPPORT_HASH_SHA1
uint32_t const SHA1_IV[5] = {
0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0,
};
#endif
#ifdef SUPPORT_HASH_SHA224
uint32_t const SHA224_IV[8] = {
0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4,
};
#endif
#ifdef SUPPORT_HASH_SHA512_224
uint32_t const SHA512_224_IV[16] = {
0x8C3D37C8, 0x19544DA2, 0x73E19966, 0x89DCD4D6, 0x1DFAB7AE, 0x32FF9C82,
0x679DD514, 0x582F9FCF, 0x0F6D2B69, 0x7BD44DA8, 0x77E36F73, 0x04C48942,
0x3F9D85A8, 0x6A1D36C8, 0x1112E6AD, 0x91D692A1,
};
#endif
#ifdef SUPPORT_HASH_SHA512_256
uint32_t const SHA512_256_IV[16] = {
0x22312194, 0xFC2BF72C, 0x9F555FA3, 0xC84C64C2, 0x2393B86B, 0x6F53B151,
0x96387719, 0x5940EABD, 0x96283EE2, 0xA88EFFE3, 0xBE5E1E25, 0x53863992,
0x2B0199FC, 0x2C85B8AA, 0x0EB72DDC, 0x81C52CA2,
};
#endif
#endif
/* function: check whether the hash algorithm is valid or not
* parameters:
* hash_alg ------------------- input, specific hash algorithm
* return: HASH_SUCCESS(valid), other(invalid)
* caution:
* 1.
*/
uint8_t check_hash_alg(HASH_ALG hash_alg)
{
uint8_t ret;
switch (hash_alg) {
#ifdef SUPPORT_HASH_SM3
case HASH_SM3:
#endif
#ifdef SUPPORT_HASH_MD5
case HASH_MD5:
#endif
#ifdef SUPPORT_HASH_SHA256
case HASH_SHA256:
#endif
#ifdef SUPPORT_HASH_SHA384
case HASH_SHA384:
#endif
#ifdef SUPPORT_HASH_SHA512
case HASH_SHA512:
#endif
#ifdef SUPPORT_HASH_SHA1
case HASH_SHA1:
#endif
#ifdef SUPPORT_HASH_SHA224
case HASH_SHA224:
#endif
#ifdef SUPPORT_HASH_SHA512_224
case HASH_SHA512_224:
#endif
#ifdef SUPPORT_HASH_SHA512_256
case HASH_SHA512_256:
#endif
#ifdef SUPPORT_HASH_SHA3_224
case HASH_SHA3_224:
#endif
#ifdef SUPPORT_HASH_SHA3_256
case HASH_SHA3_256:
#endif
#ifdef SUPPORT_HASH_SHA3_384
case HASH_SHA3_384:
#endif
#ifdef SUPPORT_HASH_SHA3_512
case HASH_SHA3_512:
#endif
ret = HASH_SUCCESS;
break;
default:
ret = HASH_INPUT_INVALID;
break;
}
return ret;
}
/* function: get hash block word length
* parameters:
* hash_alg ------------------- input, specific hash algorithm
* return: hash block word length
* caution:
* 1. please make sure hash_alg is valid
*/
uint8_t hash_get_block_word_len(HASH_ALG hash_alg)
{
uint8_t block_words;
switch (hash_alg) {
#ifdef SUPPORT_HASH_SM3
case HASH_SM3:
#endif
#ifdef SUPPORT_HASH_MD5
case HASH_MD5:
#endif
#ifdef SUPPORT_HASH_SHA1
case HASH_SHA1:
#endif
#ifdef SUPPORT_HASH_SHA256
case HASH_SHA256:
#endif
#ifdef SUPPORT_HASH_SHA224
case HASH_SHA224:
#endif
#if (defined(SUPPORT_HASH_SM3) || defined(SUPPORT_HASH_MD5) || \
defined(SUPPORT_HASH_SHA1) || defined(SUPPORT_HASH_SHA256) || \
defined(SUPPORT_HASH_SHA224))
block_words = 16;
break;
#endif
#ifdef SUPPORT_HASH_SHA384
case HASH_SHA384:
#endif
#ifdef SUPPORT_HASH_SHA512
case HASH_SHA512:
#endif
#ifdef SUPPORT_HASH_SHA512_224
case HASH_SHA512_224:
#endif
#ifdef SUPPORT_HASH_SHA512_256
case HASH_SHA512_256:
#endif
#if (defined(SUPPORT_HASH_SHA384) || defined(SUPPORT_HASH_SHA512) || \
defined(SUPPORT_HASH_SHA512_224) || defined(SUPPORT_HASH_SHA512_256))
block_words = 32;
break;
#endif
#ifdef SUPPORT_HASH_SHA3_224
case HASH_SHA3_224:
block_words = 36;
break;
#endif
#ifdef SUPPORT_HASH_SHA3_256
case HASH_SHA3_256:
block_words = 34;
break;
#endif
#ifdef SUPPORT_HASH_SHA3_384
case HASH_SHA3_384:
block_words = 26;
break;
#endif
#ifdef SUPPORT_HASH_SHA3_512
case HASH_SHA3_512:
block_words = 18;
break;
#endif
default:
block_words = 0;
break;
}
return block_words;
}
/* function: get hash iterator word length
* parameters:
* hash_alg ------------------- input, specific hash algorithm
* return: hash iterator word length
* caution:
* 1. please make sure hash_alg is valid
*/
uint8_t hash_get_iterator_word_len(HASH_ALG hash_alg)
{
uint8_t iterator_words;
switch (hash_alg) {
#ifdef SUPPORT_HASH_MD5
case HASH_MD5:
iterator_words = 4;
break;
#endif
#ifdef SUPPORT_HASH_SHA1
case HASH_SHA1:
iterator_words = 5;
break;
#endif
#ifdef SUPPORT_HASH_SM3
case HASH_SM3:
#endif
#ifdef SUPPORT_HASH_SHA256
case HASH_SHA256:
#endif
#ifdef SUPPORT_HASH_SHA224
case HASH_SHA224:
#endif
#if (defined(SUPPORT_HASH_SM3) || defined(SUPPORT_HASH_SHA256) || \
defined(SUPPORT_HASH_SHA224))
iterator_words = 8;
break;
#endif
#ifdef SUPPORT_HASH_SHA384
case HASH_SHA384:
#endif
#ifdef SUPPORT_HASH_SHA512
case HASH_SHA512:
#endif
#ifdef SUPPORT_HASH_SHA512_224
case HASH_SHA512_224:
#endif
#ifdef SUPPORT_HASH_SHA512_256
case HASH_SHA512_256:
#endif
#if (defined(SUPPORT_HASH_SHA384) || defined(SUPPORT_HASH_SHA512) || \
defined(SUPPORT_HASH_SHA512_224) || defined(SUPPORT_HASH_SHA512_256))
iterator_words = 16;
break;
#endif
#ifdef SUPPORT_HASH_SHA3_224
case HASH_SHA3_224:
#endif
#ifdef SUPPORT_HASH_SHA3_256
case HASH_SHA3_256:
#endif
#ifdef SUPPORT_HASH_SHA3_384
case HASH_SHA3_384:
#endif
#ifdef SUPPORT_HASH_SHA3_512
case HASH_SHA3_512:
#endif
#if (defined(SUPPORT_HASH_SHA3_224) || defined(SUPPORT_HASH_SHA3_256) || \
defined(SUPPORT_HASH_SHA3_384) || defined(SUPPORT_HASH_SHA3_512))
iterator_words = 50;
break;
#endif
default:
iterator_words = 0;
break;
}
return iterator_words;
}
/* function: get hash digest word length
* parameters:
* hash_alg ------------------- input, specific hash algorithm
* return: hash digest word length
* caution:
* 1. please make sure hash_alg is valid
*/
uint8_t hash_get_digest_word_len(HASH_ALG hash_alg)
{
uint8_t digest_words;
switch (hash_alg) {
#ifdef SUPPORT_HASH_MD5
case HASH_MD5:
digest_words = 4;
break;
#endif
#ifdef SUPPORT_HASH_SHA1
case HASH_SHA1:
digest_words = 5;
break;
#endif
#ifdef SUPPORT_HASH_SHA224
case HASH_SHA224:
#endif
#ifdef SUPPORT_HASH_SHA512_224
case HASH_SHA512_224:
#endif
#if (defined(SUPPORT_HASH_SHA224) || defined(SUPPORT_HASH_SHA512_224))
digest_words = 7;
break;
#endif
#ifdef SUPPORT_HASH_SM3
case HASH_SM3:
#endif
#ifdef SUPPORT_HASH_SHA256
case HASH_SHA256:
#endif
#ifdef SUPPORT_HASH_SHA512_256
case HASH_SHA512_256:
#endif
#if (defined(SUPPORT_HASH_SM3) || defined(SUPPORT_HASH_SHA256) || \
defined(SUPPORT_HASH_SHA512_256))
digest_words = 8;
break;
#endif
#ifdef SUPPORT_HASH_SHA384
case HASH_SHA384:
digest_words = 12;
break;
#endif
#ifdef SUPPORT_HASH_SHA512
case HASH_SHA512:
digest_words = 16;
break;
#endif
#ifdef SUPPORT_HASH_SHA3_224
case HASH_SHA3_224:
digest_words = 7;
break;
#endif
#ifdef SUPPORT_HASH_SHA3_256
case HASH_SHA3_256:
digest_words = 8;
break;
#endif
#ifdef SUPPORT_HASH_SHA3_384
case HASH_SHA3_384:
digest_words = 12;
break;
#endif
#ifdef SUPPORT_HASH_SHA3_512
case HASH_SHA3_512:
digest_words = 16;
break;
#endif
default:
digest_words = 0;
break;
}
return digest_words;
}
/* function: hash message total byte length a = a+b
* parameters:
* a -------------------------- input&output, big number a, total byte
* length of hash message a_words -------------------- input, word length of
* buffer a b -------------------------- input, integer to be added to a return:
* 0(success), other(error, hash total length overflow) caution:
*/
uint8_t hash_total_len_add_uint32(uint32_t *a, uint32_t a_words, uint32_t b)
{
uint32_t i;
for (i = 0; i < a_words; i++) {
a[i] += b;
if (a[i] < b) {
b = 1;
} else {
break;
}
}
if (i == a_words) {
return 1;
} else if (a[a_words - 1] & 0xE0000000) {
/*bit length overflow*/
return 1;
} else {
return 0;
}
}
/* function: transform hash message total byte length to bit length
* parameters:
* a -------------------------- input&output, big number a
* a_words -------------------- input, word length of buffer a
* return: none
* caution:
*/
void hash_total_bytelen_2_bitlen(uint32_t *a, uint32_t a_words)
{
int32_t i;
for (i = a_words - 1; i > 0; i--) {
a[i] <<= 3;
a[i] |= a[i - 1] >> (32 - 3);
}
a[i] <<= 3;
}
/* function: input actual bit length of current input message
* parameters:
* bits ----------------------- input, actual bit length of current input
* message return: none caution:
* 1. before starting please set the actual message bit length
*/
void hash_set_tx_bit_len(hash_ctx_t *ctx, uint32_t block_count)
{
uint32_t tmp = ctx->block_byte_len * block_count;
hash_set_msg_len(tmp);
}
/* function: input hash IV
* parameters:
* hash_alg ------------------- input, specific hash algorithm
* hash_iterator_words -------- input, iterator word length
* return: none
* caution:
* 1.
*/
void hash_set_IV(HASH_ALG hash_alg, uint8_t hash_iterator_words)
{
uint32_t *iv;
switch (hash_alg) {
#ifdef SUPPORT_HASH_SM3
case HASH_SM3:
iv = (uint32_t *)SM3_IV;
break;
#endif
#ifdef SUPPORT_HASH_MD5
case HASH_MD5:
iv = (uint32_t *)MD5_IV;
break;
#endif
#ifdef SUPPORT_HASH_SHA256
case HASH_SHA256:
iv = (uint32_t *)SHA256_IV;
break;
#endif
#ifdef SUPPORT_HASH_SHA384
case HASH_SHA384:
iv = (uint32_t *)SHA384_IV;
break;
#endif
#ifdef SUPPORT_HASH_SHA1
case HASH_SHA1:
iv = (uint32_t *)SHA1_IV;
break;
#endif
#ifdef SUPPORT_HASH_SHA512
case HASH_SHA512:
iv = (uint32_t *)SHA512_IV;
break;
#endif
#ifdef SUPPORT_HASH_SHA224
case HASH_SHA224:
iv = (uint32_t *)SHA224_IV;
break;
#endif
#ifdef SUPPORT_HASH_SHA512_224
case HASH_SHA512_224:
iv = (uint32_t *)SHA512_224_IV;
break;
#endif
#ifdef SUPPORT_HASH_SHA512_256
case HASH_SHA512_256:
iv = (uint32_t *)SHA512_256_IV;
break;
#endif
// here iv = NULL means SHA3 IV is zero of 1600 bits
default:
iv = NULL;
break;
}
hash_set_iterator(iv, hash_iterator_words);
}
/* function: start HASH iteration calc
* parameters:
* ctx ------------------------ input, hash_ctx_t context pointer
* return: none
* caution:
*/
void hash_start_calculate(hash_ctx_t *ctx)
{
if (ctx->first_update_flag) {
hash_set_IV(ctx->hash_alg, ctx->iterator_word_len);
ctx->first_update_flag = 0;
} else {
;
}
hash_start();
}
/* function: init HASH
* parameters:
* ctx ------------------------ input, hash_ctx_t context pointer
* hash_alg ------------------- input, specific hash algorithm
* return: HASH_SUCCESS(success), other(error)
* caution:
* 1. please make sure hash_alg is valid
*/
uint32_t hash_init(hash_ctx_t *ctx, HASH_ALG hash_alg)
{
if (NULL == ctx) {
return HASH_BUFFER_NULL;
} else if (HASH_SUCCESS != check_hash_alg(hash_alg)) {
return HASH_INPUT_INVALID;
} else {
;
}
memset_(ctx, 0, sizeof(hash_ctx_t));
hash_set_cpu_mode();
hash_set_hash_mode();
hash_set_endian_uint32();
hash_clear_msg_len();
hash_disable_cpu_interruption();
hash_set_last_block(0);
hash_set_alg(hash_alg);
hash_update_config();
ctx->hash_alg = hash_alg;
ctx->block_byte_len = hash_get_block_word_len(hash_alg) << 2;
ctx->iterator_word_len = hash_get_iterator_word_len(hash_alg);
ctx->digest_byte_len = hash_get_digest_word_len(hash_alg) << 2;
ctx->status.busy = 0;
ctx->first_update_flag = 1;
ctx->finish_flag = 0;
uint32_clear(ctx->total, ctx->block_byte_len / 32);
return HASH_SUCCESS;
}
/* function: hash iterate calc with some blocks
* parameters:
* ctx ------------------------ input, hash_ctx_t context pointer
* msg ------------------------ input, message of some blocks
* block_count ---------------- input, count of blocks
* return: none
* caution:
* 1. please make sure the three parameters is valid
*/
static void hash_calc_blocks(hash_ctx_t *ctx, const uint8_t *msg,
uint32_t block_count)
{
uint8_t block_word_len = (ctx->block_byte_len) >> 2;
#if CONFIG_HASH_SUPPORT_MUL_THREAD
/*set the input iterator data*/
if (1 != ctx->first_update_flag) {
hash_set_iterator(ctx->iterator, ctx->iterator_word_len);
} else {
;
}
#endif
/*set the bit length of the input blocks*/
hash_set_tx_bit_len(ctx, block_count);
hash_start_calculate(ctx);
while (block_count--) {
/*input the block message*/
hash_input_msg((uint8_t *)msg, block_word_len);
msg += ctx->block_byte_len;
}
hash_wait_till_done();
#if CONFIG_HASH_SUPPORT_MUL_THREAD
/*if message update not done, get the new iterator hash value*/
if (1 != ctx->finish_flag) {
hash_get_iterator((uint8_t *)(ctx->iterator), ctx->iterator_word_len);
} else {
;
}
#endif
}
/* function: hash iterate calc with padding
* parameters:
* ctx ------------------------ input, hash_ctx_t context pointer
* msg ------------------------ input, message that contains the last
* block(maybe not full) bytes ---------------------- input, byte length of msg
* return: none
* caution:
* 1. msg contains the last byte of the total message while the total
* message length is not a multiple of hash block length, otherwise byte length
* of msg is zero.
* 2. at present this function does not support the case that byte length of
* msg is a multiple of hash block length. actually msg_bytes here must be less
* than the hash block byte length, namely, this function is just for the
* remainder message, and will do padding, finally get digest.
* 3. before calling this function, some blocks(could be 0 block) must be
* calculated.
*/
static void hash_calc_rand_len_msg(hash_ctx_t *ctx, const uint8_t *msg,
uint32_t msg_bytes)
{
#if CONFIG_HASH_SUPPORT_MUL_THREAD
/*set the input iterator data*/
if (1 != ctx->first_update_flag) {
hash_set_iterator(ctx->iterator, ctx->iterator_word_len);
} else {
;
}
#endif
hash_set_last_block(1);
hash_start_calculate(ctx);
hash_input_msg((uint8_t *)msg, (msg_bytes + 3) / 4);
hash_wait_till_done();
}
/* function: hash update message
* parameters:
* ctx ------------------------ input, hash_ctx_t context pointer
* msg ------------------------ input, message
* msg_bytes ------------------ input, byte length of the input message
* return: HASH_SUCCESS(success), other(error)
* caution:
* 1. please make sure the three parameters are valid, and ctx is
* initialized
*/
uint32_t hash_update(hash_ctx_t *ctx, const uint8_t *msg, uint32_t msg_bytes)
{
uint32_t count;
uint8_t left, fill;
if ((NULL == ctx)) {
return HASH_BUFFER_NULL;
} else if ((NULL == msg) || (0 == msg_bytes)) {
return HASH_SUCCESS;
} else {
;
}
/*start to update processing*/
ctx->status.busy = 1;
#if CONFIG_HASH_SUPPORT_MUL_THREAD
hash_set_cpu_mode();
hash_set_hash_mode();
hash_set_endian_uint32();
hash_disable_cpu_interruption();
/*set not the last block*/
hash_set_last_block(0);
hash_set_alg(ctx->hash_alg);
hash_update_config();
#endif
/*byte length of valid message left in block buffer*/
/*byte length that block buffer need to fill a block*/
left = ctx->total[0] % (ctx->block_byte_len);
fill = (ctx->block_byte_len) - left;
if (hash_check_whether_sha3_alg(ctx->hash_alg)) {
ctx->total[0] = (left + msg_bytes) % (ctx->block_byte_len);
} else {
/*update total byte length*/
if (hash_total_len_add_uint32(ctx->total, ctx->block_byte_len / 32,
msg_bytes)) {
return HASH_LEN_OVERFLOW;
} else {
;
}
}
if (left) {
if (msg_bytes >= fill) {
memcpy_(ctx->hash_buffer + left, (uint8_t *)msg, fill);
hash_calc_blocks(ctx, ctx->hash_buffer, 1);
msg_bytes -= fill;
msg += fill;
} else {
memcpy_(ctx->hash_buffer + left, (uint8_t *)msg, msg_bytes);
goto end;
}
} else {
;
}
/*process some blocks*/
count = msg_bytes / (ctx->block_byte_len);
if (count) {
hash_calc_blocks(ctx, msg, count);
} else {
;
}
/*process the remainder*/
msg += (ctx->block_byte_len) * count;
msg_bytes = msg_bytes % (ctx->block_byte_len);
if (msg_bytes) {
memcpy_(ctx->hash_buffer, (uint8_t *)msg, msg_bytes);
} else {
;
}
end:
/*update end, status becomes idle*/
ctx->status.busy = 0;
return HASH_SUCCESS;
}
/* function: message update done, get the digest
* parameters:
* ctx ------------------------ input, hash_ctx_t context pointer
* digest --------------------- output, hash digest
* return: HASH_SUCCESS(success), other(error)
* caution:
* 1. please make sure the ctx is valid and initialized
* 2. please make sure the digest buffer is sufficient
*/
uint32_t hash_final(hash_ctx_t *ctx, uint8_t *digest)
{
uint8_t tmp;
if ((NULL == ctx) || (NULL == digest)) {
return HASH_BUFFER_NULL;
} else {
;
}
#if CONFIG_HASH_SUPPORT_MUL_THREAD
hash_set_cpu_mode();
hash_set_endian_uint32();
hash_disable_cpu_interruption();
/*set not the last block*/
hash_set_last_block(0);
hash_set_alg(ctx->hash_alg);
hash_update_config();
#endif
/*the last block calc*/
ctx->finish_flag = 1;
/*get the byte length of the remainder msg(less than one block)*/
tmp = ctx->total[0] % (ctx->block_byte_len);
if (hash_check_whether_sha3_alg(ctx->hash_alg)) {
/*set remainder msg bit length*/
hash_set_msg_len(tmp);
} else {
/*set total msg bit length*/
hash_total_bytelen_2_bitlen(ctx->total, (ctx->block_byte_len) / 32);
hash_set_msg_total_bit_len(ctx->total, ctx->block_byte_len);
}
/*input the remainder msg(less than one block)*/
hash_calc_rand_len_msg(ctx, ctx->hash_buffer, tmp);
/*get the hash result*/
hash_get_iterator(digest, (ctx->digest_byte_len) >> 2);
/*clear the context*/
memset_(ctx, 0, sizeof(hash_ctx_t));
return HASH_SUCCESS;
}
/* function: input whole message and get its digest
* parameters:
* hash_alg ------------------- input, specific hash algorithm
* msg ------------------------ input, message
* msg_bytes ------------------ input, byte length of the input message, it
* could be 0 digest --------------------- output, hash digest return:
* HASH_SUCCESS(success), other(error) caution:
* 1. please make sure the digest buffer is sufficient
*/
uint32_t hash(HASH_ALG hash_alg, uint8_t *msg, uint32_t msg_bytes,
uint8_t *digest)
{
hash_ctx_t ctx[1];
uint32_t ret;
ret = hash_init(ctx, hash_alg);
if (HASH_SUCCESS != ret) {
return ret;
} else {
;
}
ret = hash_update(ctx, msg, msg_bytes);
if (HASH_SUCCESS != ret) {
return ret;
} else {
;
}
ret = hash_final(ctx, digest);
if (HASH_SUCCESS != ret) {
memset_(digest, 0, ctx->digest_byte_len);
} else {
;
}
/*clear the context*/
memset_(ctx, 0, sizeof(hash_ctx_t));
return ret;
}
#ifdef HASH_DMA_FUNCTION
/* function: init dma hash
* parameters:
* ctx ------------------------ input, hash_dma_ctx_t context pointer
* hash_alg ------------------- input, specific hash algorithm
* callback ------------------- callback function pointer
* return: HASH_SUCCESS(success), other(error)
* caution:
*/
uint32_t hash_dma_init(hash_dma_ctx_t *ctx, HASH_ALG hash_alg,
HASH_CALLBACK callback)
{
if (NULL == ctx || NULL == callback) {
return HASH_BUFFER_NULL;
} else if (HASH_SUCCESS != check_hash_alg(hash_alg)) {
return HASH_INPUT_INVALID;
} else {
;
}
hash_set_cpu_mode();
hash_set_hash_mode();
hash_set_endian_uint32();
hash_clear_msg_len();
hash_disable_cpu_interruption();
hash_set_last_block(0);
hash_set_alg(hash_alg);
hash_update_config();
hash_clear_risp();
hash_set_dma_wlen(hash_get_digest_word_len(hash_alg) * 32);
hash_set_dma_mode();
/*init context*/
ctx->hash_alg = hash_alg;
ctx->block_word_len = hash_get_block_word_len(hash_alg);
ctx->callback = callback;
uint32_clear(ctx->total, sizeof(ctx->total) / 4);
/*set IV*/
hash_set_IV(hash_alg, hash_get_iterator_word_len(hash_alg));
return HASH_SUCCESS;
}
/* function: dma hash update some message blocks
* parameters:
* ctx ------------------------ input, hash_dma_ctx_t context pointer
* msg ------------------------ input, message blocks
* msg_words ------------------ input, word length of the input message,
* must be multiple of hash block word length iterator -------------------
* output, hash temporary result return: HASH_SUCCESS(success), other(error)
* caution:
* 1. please make sure the four parameters are valid, and ctx is initialized
*/
uint32_t hash_dma_update_blocks(hash_dma_ctx_t *ctx, uint32_t *msg,
uint32_t msg_words, uint32_t *iterator)
{
uint32_t msgByteLen;
if ((NULL == ctx) || (NULL == iterator)) {
return HASH_BUFFER_NULL;
} else if ((NULL == msg) || (0 == msg_words)) {
return HASH_SUCCESS;
} else if (msg_words % ctx->block_word_len) {
return HASH_INPUT_INVALID;
} else {
;
}
msgByteLen = msg_words * 4;
if (!hash_check_whether_sha3_alg(ctx->hash_alg)) {
/*update total byte length*/
if (hash_total_len_add_uint32(ctx->total, ctx->block_word_len / 8,
msgByteLen)) {
return HASH_LEN_OVERFLOW;
}
}
hash_set_msg_len(msgByteLen);
hash_dma_operate(msg, iterator, msgByteLen * 8, ctx->callback);
return HASH_SUCCESS;
}
/* function: dma hash final(input the remainder message and get the digest)
* parameters:
* ctx ------------------------ input, hash_dma_ctx_t context pointer
* remainder_msg -------------- input, remainder message
* remainder_bytes ------------ input, byte length of the remainder message,
* must be in [0, BLOCK_BYTE_LEN-1], here BLOCK_BYTE_LEN is block byte length of
* HASH digest --------------------- output, hash digest return:
* HASH_SUCCESS(success), other(error) caution:
* 1. please make sure the four parameters are valid, and ctx is initialized
*/
uint32_t hash_dma_final(hash_dma_ctx_t *ctx, uint32_t *remainder_msg,
uint32_t remainder_bytes, uint32_t *digest)
{
if ((NULL == ctx) || (NULL == digest)) {
return HASH_BUFFER_NULL;
} else {
;
}
if ((NULL == remainder_msg)) {
remainder_bytes = 0;
} else {
;
}
if (remainder_bytes >= (ctx->block_word_len << 2)) {
return HASH_INPUT_INVALID;
} else {
;
}
/*set the last block*/
hash_set_last_block(1);
if (hash_check_whether_sha3_alg(ctx->hash_alg)) {
hash_set_msg_len(remainder_bytes);
} else {
/*update total byte length*/
if (hash_total_len_add_uint32(ctx->total, ctx->block_word_len / 8,
remainder_bytes)) {
return HASH_LEN_OVERFLOW;
} else {
;
}
/*set total length of message*/
hash_total_bytelen_2_bitlen(ctx->total, (ctx->block_word_len) / 8);
hash_set_msg_total_bit_len(ctx->total, ctx->block_word_len * 4);
}
hash_dma_operate(remainder_msg, digest, remainder_bytes * 8, NULL);
memset_(ctx, 0, sizeof(hash_dma_ctx_t));
return HASH_SUCCESS;
}
/* function: dma hash digest calculate
* parameters:
* hash_alg ------------------- input, specific hash algorithm
* msg ------------------------ input, message
* msg_bytes ------------------ input, byte length of the message, it could
* be 0 digest --------------------- output, hash digest callback
* ------------------- callback function pointer return: HASH_SUCCESS(success),
* other(error) caution:
* 1. please make sure the four parameters are valid
*/
uint32_t hash_dma(HASH_ALG hash_alg, uint32_t *msg, uint32_t msg_bytes,
uint32_t *digest, HASH_CALLBACK callback)
{
uint32_t blocks_words, remainder_bytes;
uint32_t ret;
hash_dma_ctx_t ctx[1];
if ((NULL == msg)) {
msg_bytes = 0;
} else {
;
}
if (NULL == digest) {
return HASH_BUFFER_NULL;
} else {
;
}
ret = hash_dma_init(ctx, hash_alg, callback);
if (HASH_SUCCESS != ret) {
return ret;
} else {
;
}
remainder_bytes = msg_bytes % (ctx->block_word_len << 2);
blocks_words = (msg_bytes - remainder_bytes) / 4;
ret = hash_dma_update_blocks(ctx, (uint32_t *)msg, blocks_words, digest);
if (HASH_SUCCESS != ret) {
return ret;
} else {
return hash_dma_final(ctx, (uint32_t *)(msg + blocks_words),
remainder_bytes, digest);
}
}
#endif