1178 lines
28 KiB
C
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
|