304 lines
10 KiB
C
304 lines
10 KiB
C
/*
|
|
* Copyright (c) XMEDIA. All rights reserved.
|
|
*/
|
|
|
|
#include "xmedia_cipher_osal.h"
|
|
#define SHA256_H0 0x6a09e667
|
|
#define SHA256_H1 0xbb67ae85
|
|
#define SHA256_H2 0x3c6ef372
|
|
#define SHA256_H3 0xa54ff53a
|
|
#define SHA256_H4 0x510e527f
|
|
#define SHA256_H5 0x9b05688c
|
|
#define SHA256_H6 0x1f83d9ab
|
|
#define SHA256_H7 0x5be0cd19
|
|
|
|
typedef struct {
|
|
xmedia_u8 block_size;
|
|
xmedia_u8 sha_len;
|
|
xmedia_u8 last_block_size;
|
|
xmedia_u8 reserve;
|
|
xmedia_u32 total_data_len;
|
|
xmedia_u32 sha_val[SHA256_RESULT_IN_WORD];
|
|
xmedia_u8 last_block[SHA256_PADDING_MAX_SIZE];
|
|
} hash_info_s;
|
|
|
|
static hash_info_s* g_cipher_hash_data = XMEDIA_NULL;
|
|
static xmedia_s32 g_cipher_init_flag = 0;
|
|
|
|
static xmedia_u32 hash_msg_padding(xmedia_u8 *msg, xmedia_u32 byte_len, xmedia_u32 total_len, xmedia_u32 block_size)
|
|
{
|
|
xmedia_u32 tmp;
|
|
xmedia_u32 padding_len;
|
|
|
|
if (block_size == 0) {
|
|
return XMEDIA_FAILURE;
|
|
}
|
|
|
|
tmp = total_len % block_size;
|
|
|
|
padding_len = (tmp < 56) ? (56 - tmp) : (120 - tmp); /* 56, 120 */
|
|
padding_len += 8; /* 8 padding len */
|
|
|
|
/* Format(binary): {data|1000...00| fix_data_len(bits)} */
|
|
msg[byte_len++] = 0x80;
|
|
crypto_memset(&msg[byte_len], SHA256_PADDING_MAX_SIZE, 0, padding_len - 1 - 8); /* 2, 8 */
|
|
byte_len += padding_len - 1 - 8; /* 8 */
|
|
|
|
/* write 8 bytes fix data length */
|
|
msg[byte_len++] = 0x00;
|
|
msg[byte_len++] = 0x00;
|
|
msg[byte_len++] = 0x00;
|
|
msg[byte_len++] = (xmedia_u8)((total_len >> 29) & 0x07); /* 29 right shift */
|
|
msg[byte_len++] = (xmedia_u8)((total_len >> 21) & 0xff); /* 21 right shift */
|
|
msg[byte_len++] = (xmedia_u8)((total_len >> 13) & 0xff); /* 13 right shift */
|
|
msg[byte_len++] = (xmedia_u8)((total_len >> 5) & 0xff); /* 5 right shift */
|
|
msg[byte_len++] = (xmedia_u8)((total_len << 3) & 0xff); /* 3 right shift */
|
|
|
|
return byte_len;
|
|
}
|
|
|
|
static xmedia_s32 cipher_hash_update_block(hash_info_s *hash_info, xmedia_u8 *input_data, xmedia_u32 input_data_len)
|
|
{
|
|
xmedia_s32 ret;
|
|
cipher_hash_data_s hash_data;
|
|
|
|
crypto_memset(&hash_data, sizeof(cipher_hash_data_s), 0, sizeof(cipher_hash_data_s));
|
|
hash_data.hard_chn = SPACC_CHN_SHA256;
|
|
crypto_memcpy(hash_data.sha_val, sizeof(hash_data.sha_val), hash_info->sha_val, sizeof(hash_info->sha_val));
|
|
|
|
hash_data.data_len = input_data_len;
|
|
hash_data.data_phy = get_ulong_low(input_data);
|
|
hash_data.data_phy_high = get_ulong_high(input_data);
|
|
ret = drv_cipher_sha256_update(&hash_data);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
return ret;
|
|
}
|
|
|
|
crypto_memcpy(hash_info->sha_val, sizeof(hash_info->sha_val), hash_data.sha_val, sizeof(hash_data.sha_val));
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
static xmedia_s32 cipher_hash_updata_tail(hash_info_s *hash_info,
|
|
xmedia_u8 *data_phy, xmedia_u8 *input_data, xmedia_u32 input_data_len)
|
|
{
|
|
xmedia_s32 ret = XMEDIA_SUCCESS;
|
|
|
|
/* process the tail of last update */
|
|
if (hash_info->last_block_size > 0) {
|
|
crypto_memcpy(hash_info->last_block + hash_info->last_block_size,
|
|
SHA256_PADDING_MAX_SIZE - hash_info->last_block_size,
|
|
input_data,
|
|
hash_info->block_size - hash_info->last_block_size);
|
|
crypto_memcpy(data_phy, SHA256_BLOCK_SIZE, hash_info->last_block, hash_info->block_size);
|
|
ret = cipher_hash_update_block(hash_info, data_phy, hash_info->block_size);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
return ret;
|
|
}
|
|
input_data_len -= hash_info->block_size - hash_info->last_block_size;
|
|
input_data += hash_info->block_size - hash_info->last_block_size;
|
|
}
|
|
|
|
if (input_data_len >= hash_info->block_size) {
|
|
xmedia_u32 size;
|
|
size = input_data_len - (input_data_len % hash_info->block_size);
|
|
ret = cipher_hash_update_block(hash_info, input_data, size);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
return ret;
|
|
}
|
|
input_data_len -= size;
|
|
input_data += size;
|
|
}
|
|
|
|
/* save tail data */
|
|
crypto_memset(hash_info->last_block, SHA256_PADDING_MAX_SIZE, 0, SHA256_PADDING_MAX_SIZE);
|
|
hash_info->last_block_size = input_data_len;
|
|
crypto_memcpy(hash_info->last_block, SHA256_PADDING_MAX_SIZE, input_data, input_data_len);
|
|
|
|
return ret;
|
|
}
|
|
|
|
xmedia_s32 xmedia_cipher_deinit()
|
|
{
|
|
if (g_cipher_hash_data != XMEDIA_NULL) {
|
|
cipher_free(g_cipher_hash_data);
|
|
g_cipher_hash_data = XMEDIA_NULL;
|
|
}
|
|
|
|
if (g_cipher_init_flag == 0) {
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
if (drv_cipher_deinit() != XMEDIA_SUCCESS) {
|
|
return XMEDIA_FAILURE;
|
|
} else {
|
|
g_cipher_init_flag = 0;
|
|
}
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
xmedia_s32 xmedia_cipher_aes256(cipher_ctrl *ctrl, xmedia_bool is_encrypt, xmedia_size_t src_phy_addr,
|
|
xmedia_size_t dest_phy_addr, xmedia_u32 byte_len)
|
|
{
|
|
cipher_data_s ci_data;
|
|
xmedia_s32 ret;
|
|
|
|
if (g_cipher_init_flag == 0) {
|
|
if (drv_cipher_init() != XMEDIA_SUCCESS) {
|
|
cipher_debug_log(CIPHER_ERR_CIPHER_INIT);
|
|
return XMEDIA_FAILURE;
|
|
}
|
|
|
|
g_cipher_init_flag = 1;
|
|
}
|
|
|
|
ret = drv_cipher_config_aes_chn(ctrl, is_encrypt);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
cipher_debug_log(CIPHER_ERR_CIPHER_CONFIG_CHAN);
|
|
return ret;
|
|
}
|
|
|
|
ci_data.src_phy_addr = get_ulong_low(src_phy_addr);
|
|
ci_data.src_phy_addr_high = get_ulong_high(src_phy_addr);
|
|
ci_data.dest_phy_addr = get_ulong_low(dest_phy_addr);
|
|
ci_data.dest_phy_addr_high = get_ulong_high(dest_phy_addr);
|
|
ci_data.data_length = byte_len;
|
|
|
|
ret = drv_cipher_aes(&ci_data);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
cipher_debug_log(CIPHER_ERR_CIPHER_DECRYPT);
|
|
return ret;
|
|
}
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
xmedia_s32 xmedia_cipher_aes256_encrypt(cipher_ctrl *ctrl, xmedia_size_t src_phy_addr, xmedia_size_t dest_phy_addr, xmedia_u32 byte_len)
|
|
{
|
|
return xmedia_cipher_aes256(ctrl, XMEDIA_TRUE, src_phy_addr, dest_phy_addr, byte_len);
|
|
}
|
|
|
|
xmedia_s32 xmedia_cipher_aes256_decrypt(cipher_ctrl *ctrl, xmedia_size_t src_phy_addr, xmedia_size_t dest_phy_addr, xmedia_u32 byte_len)
|
|
{
|
|
return xmedia_cipher_aes256(ctrl, XMEDIA_FALSE, src_phy_addr, dest_phy_addr, byte_len);
|
|
}
|
|
|
|
xmedia_s32 xmedia_cipher_sha256_init()
|
|
{
|
|
if (g_cipher_init_flag == 0) {
|
|
if (drv_cipher_init() != XMEDIA_SUCCESS) {
|
|
cipher_debug_log(CIPHER_ERR_CIPHER_INIT);
|
|
return XMEDIA_FAILURE;
|
|
}
|
|
g_cipher_init_flag = 1;
|
|
}
|
|
|
|
if (g_cipher_hash_data == XMEDIA_NULL) {
|
|
/*sizeof(hash_info_s) = 0xA8*/
|
|
g_cipher_hash_data = cipher_malloc(sizeof(hash_info_s));
|
|
if (g_cipher_hash_data == XMEDIA_NULL) {
|
|
cipher_debug_log(CIPHER_ERR_SHA256_MALLOC);
|
|
return XMEDIA_FAILURE;
|
|
}
|
|
}
|
|
|
|
crypto_memset(g_cipher_hash_data, sizeof(hash_info_s), 0, sizeof(hash_info_s));
|
|
g_cipher_hash_data->block_size = SHA256_BLOCK_SIZE; /* 64 sha256 block size */
|
|
g_cipher_hash_data->sha_len = SHA256_RESULT_SIZE;
|
|
g_cipher_hash_data->sha_val[0] = cipher_cpu_to_be32(SHA256_H0); /* 0 sha256 index */
|
|
g_cipher_hash_data->sha_val[1] = cipher_cpu_to_be32(SHA256_H1); /* 1 sha256 index */
|
|
g_cipher_hash_data->sha_val[2] = cipher_cpu_to_be32(SHA256_H2); /* 2 sha256 index */
|
|
g_cipher_hash_data->sha_val[3] = cipher_cpu_to_be32(SHA256_H3); /* 3 sha256 index */
|
|
g_cipher_hash_data->sha_val[4] = cipher_cpu_to_be32(SHA256_H4); /* 4 sha256 index */
|
|
g_cipher_hash_data->sha_val[5] = cipher_cpu_to_be32(SHA256_H5); /* 5 sha256 index */
|
|
g_cipher_hash_data->sha_val[6] = cipher_cpu_to_be32(SHA256_H6); /* 6 sha256 index */
|
|
g_cipher_hash_data->sha_val[7] = cipher_cpu_to_be32(SHA256_H7); /* 7 sha256 index */
|
|
|
|
return XMEDIA_SUCCESS;
|
|
}
|
|
|
|
xmedia_s32 xmedia_cipher_sha256_update(xmedia_u8 *input_data, xmedia_u32 input_data_len)
|
|
{
|
|
xmedia_s32 ret = XMEDIA_SUCCESS;
|
|
xmedia_u8 *data_phy = XMEDIA_NULL;
|
|
hash_info_s *hash_info = g_cipher_hash_data;
|
|
xmedia_u32 size;
|
|
|
|
if (input_data_len == 0)
|
|
return XMEDIA_SUCCESS;
|
|
|
|
if (hash_info == XMEDIA_NULL) {
|
|
return XMEDIA_FAILURE;
|
|
}
|
|
|
|
data_phy = (xmedia_u8 *)cipher_malloc(SHA256_BLOCK_SIZE);
|
|
if (data_phy == XMEDIA_NULL) {
|
|
cipher_debug_log(CIPHER_ERR_SHA256_MALLOC);
|
|
return XMEDIA_FAILURE;
|
|
}
|
|
crypto_memset(data_phy, SHA256_BLOCK_SIZE, 0, SHA256_BLOCK_SIZE);
|
|
|
|
hash_info->total_data_len += input_data_len;
|
|
size = hash_info->last_block_size + input_data_len;
|
|
if (size < hash_info->block_size) {
|
|
crypto_memcpy(hash_info->last_block + hash_info->last_block_size,
|
|
(SHA256_PADDING_MAX_SIZE - hash_info->last_block_size), input_data, input_data_len);
|
|
hash_info->last_block_size += input_data_len;
|
|
goto free_data_phy;
|
|
}
|
|
|
|
ret = cipher_hash_updata_tail(hash_info, data_phy, input_data, input_data_len);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
cipher_debug_log(CIPHER_ERR_SHA256_UPDATE);
|
|
}
|
|
|
|
free_data_phy:
|
|
cipher_free(data_phy);
|
|
data_phy = XMEDIA_NULL;
|
|
return ret;
|
|
}
|
|
|
|
xmedia_s32 xmedia_cipher_sha256_final(xmedia_u8 *output_hash)
|
|
{
|
|
xmedia_s32 ret;
|
|
hash_info_s *hash_info = g_cipher_hash_data;
|
|
cipher_hash_data_s hash_data;
|
|
xmedia_u32 tmp;
|
|
xmedia_u8 *data_phy = XMEDIA_NULL;
|
|
|
|
if (hash_info == XMEDIA_NULL) {
|
|
return XMEDIA_FAILURE;
|
|
}
|
|
|
|
data_phy = (xmedia_u8 *)cipher_malloc(SHA256_PADDING_MAX_SIZE);
|
|
if (data_phy == XMEDIA_NULL) {
|
|
cipher_debug_log(CIPHER_ERR_SHA256_MALLOC);
|
|
return XMEDIA_FAILURE;
|
|
}
|
|
|
|
crypto_memset(data_phy, SHA256_PADDING_MAX_SIZE, 0, SHA256_PADDING_MAX_SIZE);
|
|
crypto_memset(&hash_data, sizeof(cipher_hash_data_s), 0, sizeof(cipher_hash_data_s));
|
|
|
|
tmp = hash_msg_padding(hash_info->last_block, hash_info->last_block_size, hash_info->total_data_len, hash_info->block_size);
|
|
|
|
crypto_memcpy(data_phy, SHA256_PADDING_MAX_SIZE, hash_info->last_block, tmp);
|
|
|
|
hash_data.data_len = tmp;
|
|
hash_data.data_phy = get_ulong_low(data_phy);
|
|
hash_data.data_phy_high = get_ulong_high(data_phy);
|
|
crypto_memcpy(hash_data.sha_val, sizeof(hash_data.sha_val), hash_info->sha_val, sizeof(hash_info->sha_val));
|
|
hash_data.hard_chn = SPACC_CHN_SHA256;
|
|
|
|
ret = drv_cipher_sha256_final(&hash_data);
|
|
if (ret != XMEDIA_SUCCESS) {
|
|
cipher_debug_log(CIPHER_ERR_SHA256_FINAL);
|
|
}
|
|
crypto_memcpy(output_hash, SHA256_RESULT_SIZE, hash_data.sha_val, hash_info->sha_len);
|
|
|
|
cipher_free(data_phy);
|
|
data_phy = XMEDIA_NULL;
|
|
|
|
return ret;
|
|
}
|