GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
@@ -0,0 +1,6 @@
ccflags-y += -I$(srctree)/product/driver/include
obj-y += xmedia_cipher.o
obj-y += xmedia_rsa.o
obj-y += xmedia_cipher_drv.o
obj-y += xmedia_cipher_klad.o
@@ -0,0 +1,303 @@
/*
* 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;
}
@@ -0,0 +1,72 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef __XMDEDIA_CIPHER_CONFIG_H_
#define __XMDEDIA_CIPHER_CONFIG_H_
#define CIPHER_CIPHER_REG_BASE_ADDR_PHY (0x10050000)
#define CIPHER_RSA_REG_BASE_ADDR_PHY (0x10070000)
#define CIPHER_RSA_CRG_ADDR_PHY (0x120101A0)
#define RSA_CRG_CLOCK_BIT (0x01 << 5)
#define RSA_CRG_RESET_BIT (0x01 << 4)
#define CIPHER_SPACC_CRG_ADDR_PHY (0x120101A0)
#define SPACC_CRG_CLOCK_BIT (0x01 << 9)
#define SPACC_CRG_RESET_BIT (0x01 << 8)
#define CIPHER_KLAD_REG_BASE_ADDR_PHY (0x10060000)
#define CIPHER_OTP_REG_BASE_ADDR_PHY (0x100A0000)
#define CIPHER_KLAD_CRG_ADDR_PHY (0x120101A0)
#define KLAD_CRG_CLOCK_BIT (0x01 << 1)
#define KLAD_CRG_RESET_BIT (0x01 << 0)
#define CIPHER_ERR_CIPHER_INIT 0x1
#define CIPHER_ERR_CIPHER_CONFIG_CHAN 0x2
#define CIPHER_ERR_CIPHER_DECRYPT 0x3
#define CIPHER_ERR_CIPHER_ERRCODE_1 0x4
#define CIPHER_ERR_CIPHER_ERRCODE_2 0x5
#define CIPHER_ERR_CIPHER_ERRCODE_4 0x6
#define CIPHER_ERR_CIPHER_CFG_OUTNODE 0x7
#define CIPHER_ERR_CIPHER_WAIT_TIMEOUT 0x8
#define CIPHER_ERR_CIPHER_MALLOC 0x9
#define CIPHER_ERR_CIPHER_LOAD_KEY 0xA
#define CIPHER_ERR_SHA256_MALLOC 0x10
#define CIPHER_ERR_SHA256_UPDATE 0x11
#define CIPHER_ERR_SHA256_FINAL 0x12
#define CIPHER_ERR_SHA256_START 0x13
#define CIPHER_ERR_SHA256_WAIT_TIMEOUT 0x14
#define CIPHER_ERR_RSA_MALLOC 0x20
#define CIPHER_ERR_RSA_KEY_LEN 0x21
#define CIPHER_ERR_RSA_DEC 0x22
#define CIPHER_ERR_RSA_CHECK_PADDING 0x23
#define CIPHER_ERR_RSA_BUSY_TIMEOUT 0x24
#define CIPHER_ERR_RSA_ERRORCODE 0x25
#define CIPHER_ERR_RSA_M_ZERO 0x26
#define CIPHER_ERR_RSA_M_LARGER_N 0x27
#define CIPHER_ERR_RSA_E_EQUAL_1 0x28
#define CIPHER_ERR_RSA_E_EQUAL_0 0x29
#define CIPHER_ERR_RSA_SHA256 0x2A
#define CIPHER_ERR_RSA_MGF1 0x2B
#define CIPHER_ERR_RSA_VERIFY_HASH_CMP 0x2C
#define CIPHER_ERR_RSA_VERIFY_M_LEN 0x2D
#define CIPHER_ERR_RSA_VERIFY_EM0 0x2E
#define CIPHER_ERR_RSA_VERIFY_BC 0x2F
#define CIPHER_ERR_RSA_VERIFY_DB_1 0x30
#define CIPHER_ERR_RSA_VERIFY_MASKEDDB_LEN 0x31
#define CIPHER_ERR_RSA_VERIFY_EM_FIRSTBYTE 0x32
#define CIPHER_ERR_RSA_VERIFY_EM_SECONDBYTE 0x33
#define CIPHER_ERR_RSA_VERIFY_EM_PS 0x34
#define CIPHER_ERR_RSA_VERIFY_EM_T_LEN 0x35
#define CIPHER_ERR_RSA_VERIFY_ASN1_SHA256 0x36
#define CIPHER_ERR_RSA_VERIFY_SHA256_DATA 0x37
#define CIPHER_ERR_RSA_VERIFY_SHA256_DATA_LEN 0x38
#define CIPHER_ERR_OTP_WAIT_TIMEOUT 0x40
#define CIPHER_ERR_KLAD_WAIT_TIMEOUT 0x41
#endif
@@ -0,0 +1,846 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#include "xmedia_cipher_osal.h"
#include "xmedia_cipher_reg.h"
//#include "safety.h"
/* spacc symc int entry struct which is defined by hardware, you can't change it */
struct spacc_symc_in_entry_t {
unsigned int spacc_cmd: 2;
unsigned int rev1: 6;
unsigned int sym_ctrl: 7;
unsigned int rev2: 1;
unsigned int gcm_iv_len: 4;
unsigned int rev3: 12;
unsigned int sym_start_addr_high;
unsigned int sym_start_addr;
unsigned int sym_alg_length;
unsigned int symc_iv[4]; /* 4 iv len */
};
/* spacc digest in entry struct which is defined by hardware, you can't change it */
struct spacc_digest_in_entry_t {
unsigned int spacc_cmd: 2;
unsigned int rev1: 6;
unsigned int hash_ctrl: 6;
unsigned int rev2: 18;
unsigned int hash_start_addr;
unsigned int hash_alg_length;
unsigned int hash_start_addr_high;
};
/* spacc symc out entry struct which is defined by hardware, you can't change it */
struct spacc_symc_out_entry_t {
unsigned int rev1: 8;
unsigned int aes_ctrl: 4;
unsigned int rev2: 20;
unsigned int sym_start_addr;
unsigned int sym_alg_length;
unsigned int hash_rslt_start_addr;
unsigned int tag[4]; /* 4 tag len */
};
struct spacc_digest_context {
digest_alg_en digest_alg;
digest_mode_en digest_mode;
unsigned int digest_len;
unsigned int digest_blen;
struct spacc_digest_in_entry_t* entry_digest_in;
unsigned int entry_digest_in_depth;
unsigned int digest_cur_in_nodes;
};
struct spacc_symc_context {
symc_alg_en symc_alg;
symc_mode_en symc_mode;
unsigned int symc_iv[4]; /* 4 iv len */
unsigned int symc_ivlen;
struct spacc_symc_in_entry_t* entry_symc_in;
struct spacc_symc_out_entry_t* entry_symc_out;
unsigned int entry_symc_in_depth;
unsigned int entry_symc_out_depth;
unsigned int symc_cur_in_nodes;
unsigned int symc_cur_out_nodes;
};
#define SAPCC_SYMC_IN_ENTRY_TOTAL_SIZE (sizeof(struct spacc_symc_in_entry_t) * SPACC_MAX_DEPTH)
#define SAPCC_SYMC_OUT_ENTRY_TOTAL_SIZE (sizeof(struct spacc_symc_out_entry_t) * SPACC_MAX_DEPTH)
#define SAPCC_DIGEST_IN_ENTRY_TOTAL_SIZE (sizeof(struct spacc_digest_in_entry_t) * SPACC_MAX_DEPTH)
void *g_spacc_reg_base = 0;
static struct spacc_digest_context *g_digest_context = XMEDIA_NULL;
static struct spacc_symc_context *g_symc_context = XMEDIA_NULL;
static xmedia_void* g_cipher_reg_base = XMEDIA_NULL;
static xmedia_void* cipher_entry_addr = XMEDIA_NULL;
void cipher_debug_log(unsigned short errflag)
{
char errStr[12];
errStr[0] = 'c';
errStr[1] = 'i';
errStr[2] = 'p';
errStr[3] = 'h';
errStr[4] = 'e';
errStr[5] = 'r';
errStr[6] = '#';
errStr[7] = 'E';
errStr[8] = (char)(errflag/10) + '0';
errStr[9] = (char)(errflag%10) + '0';
errStr[10] = '\n';
errStr[11] = 0;
xmedia_err_cipher(errStr);
}
/*
* spacc_digest_configure - configure the hash ctrl register.
*/
int spacc_sha256_config(unsigned int chn_num,
digest_alg_en digest_alg,
digest_mode_en digest_mode,
unsigned char hard_key)
{
struct spacc_digest_context *info = g_digest_context;
u_chann_hash_ctrl hash_ctrl;
info->digest_alg = digest_alg;
info->digest_mode = digest_mode;
info->digest_len = SHA256_RESULT_SIZE; /* 32 sha1 digest len */
info->digest_blen = SHA256_BLOCK_SIZE; /* 64 sha1 digest blen */
hash_ctrl.u32 = spacc_read(chn_n_hash_ctrl(chn_num));
hash_ctrl.bits.hash_chn_mode = digest_mode;
hash_ctrl.bits.hash_chn_agl_sel = digest_alg;
spacc_write(chn_n_hash_ctrl(chn_num), hash_ctrl.u32);
info->entry_digest_in_depth = 0;
return XMEDIA_SUCCESS;
}
/**
* spacc_digest_addbuf - filling the buf addr and length of
* data into nodes list.
*
*/
int spacc_sha256_addbuf(unsigned int chn_num,
unsigned long buf_phy,
unsigned int buf_size,
unsigned int ctrl)
{
struct spacc_digest_context *info = g_digest_context;
unsigned int id, size;
void *addr = XMEDIA_NULL;
id = info->digest_cur_in_nodes++;
addr = &info->entry_digest_in[id];
size = sizeof(struct spacc_digest_in_entry_t);
crypto_memset(addr, sizeof(info->entry_digest_in[id]), 0, size);
info->entry_digest_in[id].spacc_cmd = 0x00;
info->entry_digest_in[id].hash_start_addr = get_ulong_low(buf_phy);
info->entry_digest_in[id].hash_alg_length = buf_size;
info->entry_digest_in[id].hash_ctrl = ctrl;
info->entry_digest_in[id].hash_start_addr_high = get_ulong_high(buf_phy);
info->entry_digest_in_depth++;
info->digest_cur_in_nodes %= SPACC_MAX_DEPTH;
return XMEDIA_SUCCESS;
}
/**
* spacc_digest_get - get hash result.
*
*/
int spacc_sha256_get(unsigned int chn_num, unsigned int *digest)
{
unsigned int i;
for (i = 0; i < SHA256_RESULT_IN_WORD; i++) {
spacc_write(chn_n_hash_state_val_addr(chn_num), i);
digest[i] = spacc_read(chn_n_hash_state_val(chn_num));
}
return XMEDIA_SUCCESS;
}
/*
* spacc_digest_start - action the hash start to processing the node list.
*/
int spacc_sha256_start(unsigned int chn_num, spacc_ctrl_en spacc_ctrl, unsigned int *state)
{
unsigned int i;
u_chann_hash_in_node_cfg in_node_cfg;
struct spacc_digest_context *info = g_digest_context;
unsigned int ptr;
/* Write last state */
for (i = 0; i < SHA256_RESULT_IN_WORD; i++) {
spacc_write(chn_n_hash_state_val_addr(chn_num), i);
spacc_write(chn_n_hash_state_val(chn_num), state[i]);
}
if (info->entry_digest_in_depth == 0)
return XMEDIA_SUCCESS;
/* configure in-node */
in_node_cfg.u32 = spacc_read(chn_n_hash_in_node_cfg(chn_num));
if (in_node_cfg.bits.hash_in_node_wptr != in_node_cfg.bits.hash_in_node_rptr) {
cipher_debug_log(CIPHER_ERR_SHA256_START);
return XMEDIA_FAILURE;
}
ptr = in_node_cfg.bits.hash_in_node_wptr + info->entry_digest_in_depth;
in_node_cfg.bits.hash_in_node_wptr = ptr % SPACC_MAX_DEPTH;
in_node_cfg.bits.hash_in_node_mpackage_int_level = 1;
/* Start */
spacc_write(chn_n_hash_in_node_cfg(chn_num), in_node_cfg.u32);
return XMEDIA_SUCCESS;
}
/*
* spacc_digest_done_try - test the int status of hash channel.
*/
unsigned int spacc_sha256_done_try(unsigned int chn_num)
{
u_hash_int_raw int_raw;
unsigned int chn_mask;
int_raw.u32 = spacc_read(HASH_INT_RAW);
int_raw.bits.hash_chn_oram_raw &= 0x01 << chn_num;
chn_mask = int_raw.bits.hash_chn_oram_raw;
/* Clean raw int */
spacc_write(HASH_INT_RAW, int_raw.u32);
return chn_mask;
}
/*
* spacc_digest_get_err_code - get the error code of hash.
*/
unsigned int spacc_sha256_get_err_code(unsigned int chn_num, unsigned int *src_addr)
{
*src_addr = spacc_read(chn_n_hash_in_buf_rptr(chn_num));
return spacc_read(CALC_ERR);
}
static xmedia_void spacc_config_start_addr(unsigned long entry_phy_addr, xmedia_void *entry_via_addr)
{
xmedia_size_t page_phy;
xmedia_void *page_via = XMEDIA_NULL;
u_chann_cipher_in_node_cfg cipher_in_cfg;
u_chann_cipher_out_node_cfg cipher_out_cfg;
u_chann_hash_in_node_cfg hash_in_cfg;
page_phy = entry_phy_addr;
page_via = entry_via_addr;
/* set total num and start addr for cipher in node */
cipher_in_cfg.u32 = spacc_read(chn_n_cipher_in_node_cfg(SPACC_CHN_AES));
cipher_in_cfg.bits.cipher_in_node_total_num = SPACC_MAX_DEPTH;
spacc_write(chn_n_cipher_in_node_cfg(SPACC_CHN_AES), cipher_in_cfg.u32);
spacc_write(chn_n_cipher_in_node_start_addr(SPACC_CHN_AES), get_ulong_low(page_phy));
spacc_write(chn_n_cipher_in_node_start_addr_high(SPACC_CHN_AES), get_ulong_high(page_phy));
g_symc_context->entry_symc_in = (struct spacc_symc_in_entry_t*)page_via;
g_symc_context->symc_cur_in_nodes = cipher_in_cfg.bits.cipher_in_node_wptr;
g_symc_context->entry_symc_in_depth = 0;
page_via += SAPCC_SYMC_IN_ENTRY_TOTAL_SIZE;
page_phy += SAPCC_SYMC_IN_ENTRY_TOTAL_SIZE;
/* set total num and start addr for cipher out node */
cipher_out_cfg.u32 = spacc_read(chn_n_cipher_out_node_cfg(SPACC_CHN_AES));
cipher_out_cfg.bits.cipher_out_node_total_num = SPACC_MAX_DEPTH;
spacc_write(chn_n_cipher_out_node_cfg(SPACC_CHN_AES), cipher_out_cfg.u32);
spacc_write(chn_n_cipher_out_node_start_addr(SPACC_CHN_AES), get_ulong_low(page_phy));
spacc_write(chn_n_cipher_out_node_start_addr_high(SPACC_CHN_AES), get_ulong_high(page_phy));
g_symc_context->entry_symc_out = (struct spacc_symc_out_entry_t*)page_via;
g_symc_context->symc_cur_out_nodes = cipher_out_cfg.bits.cipher_out_node_wptr;
g_symc_context->entry_symc_out_depth = 0;
page_via += SAPCC_SYMC_OUT_ENTRY_TOTAL_SIZE;
page_phy += SAPCC_SYMC_OUT_ENTRY_TOTAL_SIZE;
/* set total num and start addr for hash in node */
hash_in_cfg.u32 = spacc_read(chn_n_hash_in_node_cfg(SPACC_CHN_SHA256));
hash_in_cfg.bits.hash_in_node_total_num = SPACC_MAX_DEPTH;
spacc_write(chn_n_hash_in_node_cfg(SPACC_CHN_SHA256), hash_in_cfg.u32);
spacc_write(chn_n_hash_in_node_start_addr(SPACC_CHN_SHA256), get_ulong_low(page_phy));
spacc_write(chn_n_hash_in_node_start_addr_high(SPACC_CHN_SHA256), get_ulong_high(page_phy));
g_digest_context->entry_digest_in = (struct spacc_digest_in_entry_t*)page_via;
g_digest_context->digest_cur_in_nodes = hash_in_cfg.bits.hash_in_node_wptr;
g_digest_context->entry_digest_in_depth = 0;
}
/**
* spacc_get_node_list_size - return the total size of nodes lists memory required by the drive.
*/
unsigned int spacc_get_node_list_size(void)
{
/*********************************************************************
0x40 + 0x40 + 0x20
*********************************************************************/
return (SAPCC_SYMC_IN_ENTRY_TOTAL_SIZE + SAPCC_SYMC_OUT_ENTRY_TOTAL_SIZE + SAPCC_DIGEST_IN_ENTRY_TOTAL_SIZE);
}
/**
* spacc_init - spacc hardware initialization.
* @reg_base: virtual address of spacc module which be accessed by CPU
* @mmu_table_addr: mmu base table physical addr, if disable mmu, set it to 0
* @entry_phy_addr: a consecutive physical memory, used for nodes
* list of symc-in, symc-out and hash-in, the size
* must large than spacc_get_node_list_size().
* @entry_via_addr: virtual address of entry_phy_addr.
*
* Description:
* spacc hardware initialization as follows:
* - reset global var.
* - enable interrupt
* - set nodes list addr
* - set mmu table addr
* - configureure hardware register
*
* Context:
* this function must be called one time in the beginning.
*/
int spacc_init(xmedia_void *reg_base, unsigned long entry_phy_addr, xmedia_void *entry_via_addr)
{
crypto_memset(g_symc_context, sizeof(struct spacc_symc_context), 0, sizeof(struct spacc_symc_context));
crypto_memset(g_digest_context, sizeof(struct spacc_digest_context), 0, sizeof(struct spacc_digest_context));
g_spacc_reg_base = reg_base;
//not enable smmu
//not enable int
/* configure start addr for in-node and out-node */
spacc_config_start_addr(entry_phy_addr, entry_via_addr);
return XMEDIA_SUCCESS;
}
/**
* spacc_deinit - spacc hardware deinit.
*/
int spacc_deinit(void)
{
return XMEDIA_SUCCESS;
}
/*
* spacc_symc_configure - configure logic register, such as alg, mode, key len and so on.
*/
int spacc_symc_config(unsigned int chn_num, spacc_symc_config_s *symc_cfg)
{
struct spacc_symc_context *info = g_symc_context;
u_chann_cipher_ctrl cipher_ctrl;
cipher_ctrl.u32 = spacc_read(chn_n_cipher_ctrl(chn_num));
cipher_ctrl.bits.sym_chn_key_sel = (symc_cfg->key_type == SYMC_KEY_SRC_USER) ? 0 : 1; // bit[14], 0:cpu config key; 1: klad config key
cipher_ctrl.bits.sym_chn_key_length = 2; // bit[11:10], 2:256bit
cipher_ctrl.bits.sym_chn_dat_width = 0; // bit[9:8], 0:128bit
cipher_ctrl.bits.sym_chn_decrypt = (symc_cfg->is_encrypt == XMEDIA_TRUE) ? 0 : 1; // bit[7], 0:encrypt; 1:decrypt
cipher_ctrl.bits.sym_chn_alg_sel = symc_cfg->symc_alg;
cipher_ctrl.bits.sym_chn_alg_mode = symc_cfg->symc_mode;
spacc_write(chn_n_cipher_ctrl(chn_num), cipher_ctrl.u32);
info->symc_alg = symc_cfg->symc_alg;
info->symc_mode = symc_cfg->symc_mode;
info->entry_symc_in_depth = 0;
info->entry_symc_out_depth = 0;
return XMEDIA_SUCCESS;
}
/**
* spacc_symc_setiv - set iv for symc.
* @chn_num: the logic channel number, must 1~7.
* @iv: the initialization vector
* @ivlen: length of iv.
*
* Description:
* here store the iv to global structure of channel, don't set to logic,
* because the IV must be set in the nodes list.
*
*/
int spacc_symc_setiv(unsigned int chn_num, unsigned char *iv, unsigned int ivlen)
{
struct spacc_symc_context *info = g_symc_context;
crypto_memset(info->symc_iv, sizeof(info->symc_iv), 0, sizeof(info->symc_iv));
crypto_memcpy(info->symc_iv, sizeof(info->symc_iv), iv, ivlen);
info->symc_ivlen = ivlen;
return XMEDIA_SUCCESS;
}
void spacc_symc_setkey(xmedia_u32 chn_num, xmedia_u32 key[SYMC_KEY_MAX_SIZE_IN_WORD], xmedia_u32 odd)
{
xmedia_u32 i = 0;
/* Set key, odd key only valid for aes ecb/cbc/ofb/cfb/ctr */
spacc_write(ODD_EVEN_KEY_SEL, odd);
for (i = 0; i < SYMC_KEY_MAX_SIZE_IN_WORD; i++) {
spacc_write(cipher_key(chn_num) + i * 4, key[i]);
}
}
int drv_cipher_setkey(cipher_ctrl *config)
{
int ret;
if (config->key_type != XMEDIA_CIPHER_KEY_SRC_USER) {
ret = drv_cipher_klad_load_key(SPACC_CHN_AES, config->key, 32, config->key_type); /* 16 key len */
if (ret != XMEDIA_SUCCESS) {
cipher_debug_log(CIPHER_ERR_CIPHER_LOAD_KEY);
return ret;
}
} else {
spacc_symc_setkey(SPACC_CHN_AES, config->key, XMEDIA_FALSE);
}
return XMEDIA_SUCCESS;
}
/*
* spacc_symc_addbuf - filling the buf addr and length of
* encrypt/decrypt data into nodes list.
*/
int spacc_symc_addbuf(unsigned int chn_num, unsigned long buf_phy,
unsigned int buf_size, spacc_buf_type_en type, unsigned int ctrl)
{
struct spacc_symc_context *info = g_symc_context;
unsigned int id, size;
void *addr = XMEDIA_NULL;
switch (type) {
case SPACC_BUF_TYPE_SYMC_IN:
id = info->symc_cur_in_nodes++;
addr = &info->entry_symc_in[id];
size = sizeof(struct spacc_symc_in_entry_t);
crypto_memset(addr, sizeof(info->entry_symc_in[id]), 0, size);
info->entry_symc_in[id].spacc_cmd = 0x00;
info->entry_symc_in[id].sym_start_addr = get_ulong_low(buf_phy);
info->entry_symc_in[id].sym_start_addr_high = get_ulong_high(buf_phy);
info->entry_symc_in[id].sym_alg_length = buf_size;
info->entry_symc_in[id].sym_ctrl = ctrl;
info->entry_symc_in_depth++;
info->symc_cur_in_nodes %= SPACC_MAX_DEPTH;
break;
case SPACC_BUF_TYPE_SYMC_OUT:
id = info->symc_cur_out_nodes++;
addr = &info->entry_symc_out[id];
size = sizeof(struct spacc_symc_out_entry_t);
crypto_memset(addr, sizeof(info->entry_symc_out[id]), 0, size);
info->entry_symc_out[id].sym_start_addr = get_ulong_low(buf_phy);
info->entry_symc_out[id].tag[0] = get_ulong_high(buf_phy);
info->entry_symc_out[id].sym_alg_length = buf_size;
info->entry_symc_out[id].aes_ctrl = ctrl;
info->entry_symc_out_depth++;
info->symc_cur_out_nodes %= SPACC_MAX_DEPTH;
break;
default:
return XMEDIA_FAILURE;
}
return XMEDIA_SUCCESS;
}
static int spacc_config_out_node(unsigned int chn_num, struct spacc_symc_context *info)
{
u_chann_cipher_out_node_cfg out_node_cfg;
unsigned int ptr;
out_node_cfg.u32 = spacc_read(chn_n_cipher_out_node_cfg(chn_num));
if (out_node_cfg.bits.cipher_out_node_wptr != out_node_cfg.bits.cipher_out_node_rptr) {
cipher_debug_log(CIPHER_ERR_CIPHER_CFG_OUTNODE);
return XMEDIA_FAILURE;
}
ptr = out_node_cfg.bits.cipher_out_node_wptr + info->entry_symc_out_depth;
out_node_cfg.bits.cipher_out_node_wptr = ptr % SPACC_MAX_DEPTH;
out_node_cfg.bits.cipher_out_node_mpackage_int_level = info->entry_symc_out_depth;
spacc_write(chn_n_cipher_out_node_cfg(chn_num), out_node_cfg.u32);
return XMEDIA_SUCCESS;
}
static void spacc_config_in_node(unsigned int chn_num, struct spacc_symc_context *info)
{
u_chann_cipher_in_node_cfg in_node_cfg;
unsigned int ptr;
in_node_cfg.u32 = spacc_read(chn_n_cipher_in_node_cfg(chn_num));
ptr = in_node_cfg.bits.cipher_in_node_wptr + info->entry_symc_in_depth;
in_node_cfg.bits.cipher_in_node_wptr = ptr % SPACC_MAX_DEPTH;
in_node_cfg.bits.cipher_in_node_mpackage_int_level = info->entry_symc_in_depth;
/* move forward the in-node ptr to action the symc working */
spacc_write(chn_n_cipher_in_node_cfg(chn_num), in_node_cfg.u32);
}
/*
* spacc_symc_done_try - test the int status of symc channel.
*/
unsigned int spacc_symc_done_try(unsigned int chn_num)
{
u_cipher_int_raw int_raw;
unsigned int chn_mask;
int_raw.u32 = spacc_read(CIPHER_INT_RAW);
int_raw.bits.cipher_chn_obuf_raw &= 0x01 << chn_num;
chn_mask = int_raw.bits.cipher_chn_obuf_raw;
/* Clean raw int */
int_raw.u32 = 0x00;
int_raw.bits.cipher_chn_obuf_raw = chn_mask;
spacc_write(CIPHER_INT_RAW, int_raw.u32);
return chn_mask ? 1 : 0;
}
/*
* spacc_symc_get_err_code - get the error code of symc.
*/
unsigned int spacc_symc_get_err_code(unsigned int chn_num,
unsigned int *src_addr,
unsigned int *dst_addr)
{
*src_addr = spacc_read(chn_n_cipher_in_buf_rptr(chn_num));
*dst_addr = spacc_read(chn_n_cipher_out_buf_rptr(chn_num));
return spacc_read(CALC_ERR);
}
/* check error code
* bit0: klad_key_use_err
* bit1: alg_len_err
* bit2: smmu_page_unvlid
*/
static xmedia_s32 spacc_cipher_check_error_code(xmedia_u32 hard_num, xmedia_u32 wait, xmedia_u32 src_addr)
{
xmedia_s32 ret = XMEDIA_SUCCESS;
if (wait & 0x01) {
cipher_debug_log(CIPHER_ERR_CIPHER_ERRCODE_1);
ret = XMEDIA_FAILURE;
}
if (wait & 0x02) {
cipher_debug_log(CIPHER_ERR_CIPHER_ERRCODE_2);
ret = XMEDIA_FAILURE;
}
if (wait & 0x04) {
cipher_debug_log(CIPHER_ERR_CIPHER_ERRCODE_4);
ret = XMEDIA_FAILURE;
}
return ret;
}
/*
* spacc_symc_start - action the symc start to processing the node list.
*/
int spacc_symc_start(unsigned int chn_num)
{
unsigned int cur, i, j, node;
u_chann_cipher_in_node_cfg in_node_cfg;
struct spacc_symc_context *info = g_symc_context;
in_node_cfg.u32 = spacc_read(chn_n_cipher_in_node_cfg(chn_num));
cur = in_node_cfg.bits.cipher_in_node_rptr;
for (j = 0; j < info->entry_symc_in_depth; j++) {
if (info->symc_ivlen > 0) {
/* Write iv to all nodes */
node = (cur + j) % SPACC_MAX_DEPTH;
for (i = 0; i < 4; i++) { /* 4 iv len */
info->entry_symc_in[node].symc_iv[i] = info->symc_iv[i];
}
info->entry_symc_in[node].gcm_iv_len = 0;
info->entry_symc_in[node].sym_ctrl |= SPACC_CTRL_SYMC_IN_FIRST;
}
}
if (spacc_config_out_node(chn_num, info) != XMEDIA_SUCCESS) {
return XMEDIA_FAILURE;
}
/* spacc_config_in_node must be placed after flush_cache, otherwwise it may be crypt timeout */
spacc_config_in_node(chn_num, info);
/* all the nodes are processing, reset the depth to 0 */
info->entry_symc_in_depth = 0;
info->entry_symc_out_depth = 0;
return XMEDIA_SUCCESS;
}
static xmedia_s32 drv_cipher_sha256_config(cipher_hash_data_s *cipher_hash_data, spacc_ctrl_en *spacc_ctrl)
{
xmedia_s32 ret;
digest_alg_en digest_alg;
digest_mode_en digest_mode;
*spacc_ctrl = SPACC_CTRL_NONE;
digest_alg = DIGEST_ALG_SHA256;
digest_mode = DIGEST_MODE_HASH;
ret = spacc_sha256_config(cipher_hash_data->hard_chn, digest_alg, digest_mode, XMEDIA_FALSE);
*spacc_ctrl = ((xmedia_u32)*spacc_ctrl) | SPACC_CTRL_HASH_IN_FIRST;
*spacc_ctrl = ((xmedia_u32)*spacc_ctrl) | SPACC_CTRL_HASH_IN_LAST;
return ret;
}
static xmedia_s32 drv_cipher_sha256_wait_done(unsigned int channel)
{
xmedia_s32 ret = XMEDIA_SUCCESS;
xmedia_u32 wait;
xmedia_u32 time_out = SPACC_TIME_OUT;
xmedia_u32 src_addr;
time_out = 0;
while (time_out++ < SPACC_TIME_OUT) {
if (spacc_sha256_done_try(channel))
break;
cipher_usleep(10);
}
if (time_out >= SPACC_TIME_OUT) {
cipher_debug_log(CIPHER_ERR_SHA256_WAIT_TIMEOUT);
ret = XMEDIA_FAILURE;
}
/* check error code
* bit0: klad_key_use_err
* bit1: alg_len_err
* bit2: smmu_page_unvlid
*/
wait = spacc_sha256_get_err_code(channel, &src_addr);
if (spacc_cipher_check_error_code(channel, wait, src_addr) != XMEDIA_SUCCESS) {
ret = XMEDIA_FAILURE;
}
return ret;
}
xmedia_s32 drv_cipher_sha256_update(cipher_hash_data_s *cipher_hash_data)
{
xmedia_s32 ret;
spacc_ctrl_en spacc_ctrl;
/* configure hash register */
ret = drv_cipher_sha256_config(cipher_hash_data, &spacc_ctrl);
if (ret != XMEDIA_SUCCESS) {
return ret;
}
/* Add the phy of data to nodes list */
ret = spacc_sha256_addbuf(cipher_hash_data->hard_chn, make_ulong(cipher_hash_data->data_phy, cipher_hash_data->data_phy_high),
cipher_hash_data->data_len, spacc_ctrl);
if (ret != XMEDIA_SUCCESS) {
return ret;
}
/* Start working */
ret = spacc_sha256_start(cipher_hash_data->hard_chn, spacc_ctrl, cipher_hash_data->sha_val);
if (ret != XMEDIA_SUCCESS) {
return ret;
}
/* Waiting hardware computing finished */
ret = drv_cipher_sha256_wait_done(cipher_hash_data->hard_chn);
if (ret == XMEDIA_SUCCESS) /* Read hash result */
spacc_sha256_get(cipher_hash_data->hard_chn, cipher_hash_data->sha_val);
return ret;
}
xmedia_s32 drv_cipher_sha256_final(cipher_hash_data_s *cipher_hash_data)
{
return drv_cipher_sha256_update(cipher_hash_data);
}
static xmedia_s32 drv_cipher_reset(xmedia_void)
{
xmedia_u32 *pvirt = XMEDIA_NULL;
xmedia_u32 spacc_stat = 0;
pvirt = cipher_ioremap_nocache(CIPHER_SPACC_CRG_ADDR_PHY, 16); /* 16 */
/* open clock, reset */
spacc_stat = hal_cipher_read_reg(pvirt);
spacc_stat |= SPACC_CRG_CLOCK_BIT;
spacc_stat |= SPACC_CRG_RESET_BIT;
hal_cipher_write_reg(pvirt, spacc_stat);
cipher_usleep(10); /* 10us */
/* cancel reset */
spacc_stat &= ~SPACC_CRG_RESET_BIT;
hal_cipher_write_reg(pvirt, spacc_stat);
//enable_spacc_safety();
cipher_iounmap(pvirt);
pvirt = XMEDIA_NULL;
return XMEDIA_SUCCESS;
}
static xmedia_s32 drv_cipher_symc_wait_done(xmedia_u32 hw_chan, xmedia_u32 time_out)
{
xmedia_s32 ret = XMEDIA_SUCCESS;
xmedia_u32 wait;
xmedia_u32 src_addr, dst_addr;
time_out = 0;
while (time_out++ < SPACC_TIME_OUT) {
if (spacc_symc_done_try(hw_chan))
break;
cipher_usleep(10);
}
if (time_out >= SPACC_TIME_OUT) {
cipher_debug_log(CIPHER_ERR_CIPHER_WAIT_TIMEOUT);
ret = XMEDIA_FAILURE;
}
wait = spacc_symc_get_err_code(hw_chan, &src_addr, &dst_addr);
if (spacc_cipher_check_error_code(hw_chan, wait, src_addr) != XMEDIA_SUCCESS) {
ret = XMEDIA_FAILURE;
}
return ret;
}
xmedia_s32 drv_cipher_init(xmedia_void)
{
xmedia_u32 malloc_size;
dcache_disable();
g_cipher_reg_base = cipher_ioremap_nocache(CIPHER_CIPHER_REG_BASE_ADDR_PHY, 0x2000);
if (drv_cipher_reset() != XMEDIA_SUCCESS) {
return XMEDIA_FAILURE;
}
malloc_size = spacc_get_node_list_size();
cipher_entry_addr = cipher_malloc(malloc_size);
if (cipher_entry_addr == XMEDIA_NULL) {
cipher_debug_log(CIPHER_ERR_CIPHER_MALLOC);
return XMEDIA_FAILURE;
}
/*sizeof(struct spacc_digest_context) == 0x1C*/
g_digest_context = cipher_malloc(sizeof(struct spacc_digest_context));
if (g_digest_context == XMEDIA_NULL) {
cipher_debug_log(CIPHER_ERR_CIPHER_MALLOC);
cipher_free(cipher_entry_addr);
cipher_entry_addr = XMEDIA_NULL;
return XMEDIA_FAILURE;
}
/*sizeof(struct spacc_digest_context) == 0x34*/
g_symc_context = cipher_malloc(sizeof(struct spacc_symc_context));
if (g_symc_context == XMEDIA_NULL) {
cipher_free(cipher_entry_addr);
cipher_entry_addr = XMEDIA_NULL;
cipher_free(g_digest_context);
g_digest_context = XMEDIA_NULL;
cipher_debug_log(CIPHER_ERR_CIPHER_MALLOC);
return XMEDIA_FAILURE;
}
crypto_memset(cipher_entry_addr, malloc_size, 0, malloc_size);
spacc_init(g_cipher_reg_base, (unsigned long)cipher_entry_addr, cipher_entry_addr);
return XMEDIA_SUCCESS;
}
xmedia_s32 drv_cipher_deinit(xmedia_void)
{
spacc_deinit();
cipher_free(cipher_entry_addr);
cipher_entry_addr = XMEDIA_NULL;
cipher_iounmap(g_cipher_reg_base);
cipher_free(g_digest_context);
g_digest_context = XMEDIA_NULL;
cipher_free(g_symc_context);
g_symc_context = XMEDIA_NULL;
dcache_enable();
return XMEDIA_SUCCESS;
}
xmedia_s32 drv_cipher_config_aes_chn(cipher_ctrl *config, xmedia_bool is_encrypt)
{
xmedia_s32 ret;
spacc_symc_config_s symc_cfg;
symc_cfg.symc_alg = SYMC_ALG_AES;
symc_cfg.symc_mode = config->work_mode;
symc_cfg.symc_width = SYMC_DAT_WIDTH_128;
symc_cfg.key_len = 32;
symc_cfg.is_encrypt = is_encrypt;
symc_cfg.key_type = config->key_type;
ret = spacc_symc_config(SPACC_CHN_AES, &symc_cfg);
if (ret != XMEDIA_SUCCESS) {
return ret;
}
ret = drv_cipher_setkey(config);
if (ret != XMEDIA_SUCCESS) {
return ret;
}
ret = spacc_symc_setiv(SPACC_CHN_AES, (xmedia_u8*)config->iv, sizeof(config->iv));
return ret;
}
xmedia_s32 drv_cipher_aes(cipher_data_s *ci_data)
{
xmedia_s32 ret;
xmedia_size_t src_phy_addr, dest_phy_addr;
src_phy_addr = make_ulong(ci_data->src_phy_addr, ci_data->src_phy_addr_high);
dest_phy_addr = make_ulong(ci_data->dest_phy_addr, ci_data->dest_phy_addr_high);
/* Add in buffer */
ret = spacc_symc_addbuf(SPACC_CHN_AES, src_phy_addr, ci_data->data_length,
SPACC_BUF_TYPE_SYMC_IN, SPACC_CTRL_SYMC_IN_LAST);
if (ret != XMEDIA_SUCCESS) {
return ret;
}
/* Add out buffer */
ret = spacc_symc_addbuf(SPACC_CHN_AES, dest_phy_addr, ci_data->data_length,
SPACC_BUF_TYPE_SYMC_OUT, SPACC_CTRL_SYMC_OUT_LAST);
if (ret != XMEDIA_SUCCESS) {
return ret;
}
/* Start working */
spacc_symc_start(SPACC_CHN_AES);
/* Waiting hardware computing finished */
ret = drv_cipher_symc_wait_done(SPACC_CHN_AES, SPACC_TIME_OUT);
if (ret != XMEDIA_SUCCESS) {
return ret;
}
return XMEDIA_SUCCESS;
}
@@ -0,0 +1,144 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef _SPACC_BODY_H_
#define _SPACC_BODY_H_
#define SHA256_RESULT_SIZE 32
#define SHA256_RESULT_IN_WORD 8
#define SHA256_BLOCK_SIZE 64
#define SHA256_PADDING_MAX_SIZE 128
#define SPACC_CHN_MASK 0xFE
#define SPACC_CHN_AES 0x1
#define SPACC_CHN_SHA256 0x1
#define SPACC_MAX_DEPTH 2
#define SYMC_KEY_MAX_SIZE_IN_WORD 8
#define get_ulong_low(dw) (unsigned int)(dw)
#define get_ulong_high(dw) 0
#define make_ulong(low, high) (low)
#define make_size(low) (((unsigned long)(low##High) << 32) | (low))
#define SPACC_TIME_OUT 300000
#define RSA_TIMEOUT_CNT 300000
typedef enum {
DIGEST_MODE_HASH,
DIGEST_MODE_HMAC,
DIGEST_MODE_COUNT,
} digest_mode_en;
typedef enum {
DIGEST_ALG_SHA1,
DIGEST_ALG_SHA224,
DIGEST_ALG_SHA256,
DIGEST_ALG_SHA384,
DIGEST_ALG_SHA512,
DIGEST_ALG_SM3,
DIGEST_ALG_COUNT,
} digest_alg_en;
typedef enum {
SYMC_ALG_DES = 0,
SYMC_ALG_3DES,
SYMC_ALG_AES,
SYMC_ALG_SM4,
SYMC_ALG_SM1,
SYMC_ALG_NULL_CIPHER,
SYMC_ALG_COUNT,
} symc_alg_en;
typedef enum {
SYMC_DAT_WIDTH_128 = 0,
SYMC_DAT_WIDTH_64 = 0,
SYMC_DAT_WIDTH_8,
SYMC_DAT_WIDTH_1,
SYMC_DAT_WIDTH_COUNT,
} symc_dat_width_en;
typedef enum {
SYMC_MODE_ECB = 0,
SYMC_MODE_CBC,
SYMC_MODE_CFB,
SYMC_MODE_OFB,
SYMC_MODE_CTR,
SYMC_MODE_COUNT,
} symc_mode_en;
typedef enum {
SPACC_BUF_TYPE_SYMC_IN,
SPACC_BUF_TYPE_SYMC_OUT,
SPACC_BUF_TYPE_DIGEST_IN,
SPACC_BUF_TYPE_COUNT,
} spacc_buf_type_en;
typedef enum {
SPACC_CTRL_NONE = 0x00,
SPACC_CTRL_SYMC_IN_GCM_A = 0x00,
SPACC_CTRL_SYMC_IN_GCM_P = 0x08,
SPACC_CTRL_SYMC_IN_GCM_LEN = 0x10,
SPACC_CTRL_SYMC_IN_CCM_N = 0x00,
SPACC_CTRL_SYMC_IN_CCM_A = 0x08,
SPACC_CTRL_SYMC_IN_CCM_P = 0x10,
SPACC_CTRL_SYMC_IN_CBC_OUTPUT_DISABLE = 0x04,
SPACC_CTRL_SYMC_IN_FIRST = 0x01,
SPACC_CTRL_SYMC_IN_LAST = 0x02,
SPACC_CTRL_HASH_IN_PAD = 0x04,
SPACC_CTRL_HASH_IN_FIRST = 0x01,
SPACC_CTRL_HASH_IN_LAST = 0x02,
SPACC_CTRL_HASH_IN_AUTO_PADDING = 0x04,
SPACC_CTRL_HASH_IN_HMAC_END = 0x08,
SPACC_CTRL_SYMC_OUT_LAST = 0x02,
SPACC_CTRL_SYMC_CCM_LAST = 0x20,
SPACC_CTRL_SYMC_ODD_KEY = 0x40,
SPACC_CTRL_SYMC_EVEN_KEY = 0x00,
SPACC_CTRL_COUNT,
} spacc_ctrl_en;
typedef struct {
xmedia_u32 hard_chn;
xmedia_u32 sha_val[SHA256_RESULT_IN_WORD]; /* 16 size */
xmedia_u32 data_phy;
xmedia_u32 data_phy_high;
xmedia_u32 data_len;
} cipher_hash_data_s;
typedef struct {
xmedia_u32 src_phy_addr;
xmedia_u32 src_phy_addr_high;
xmedia_u32 dest_phy_addr;
xmedia_u32 dest_phy_addr_high;
xmedia_u32 data_length;
} cipher_data_s;
typedef enum {
SYMC_KEY_SRC_USER = 0x0,
SYMC_KEY_SRC_KLAD_0,
SYMC_KEY_SRC_KLAD_1,
SYMC_KEY_SRC_KLAD_2,
SYMC_KEY_SRC_KLAD_3,
SYMC_KEY_SRC_BUTT,
} symc_key_type;
typedef struct {
symc_alg_en symc_alg;
symc_mode_en symc_mode;
symc_dat_width_en symc_width;
xmedia_u32 key_len;
xmedia_bool is_encrypt;
symc_key_type key_type;
} spacc_symc_config_s;
xmedia_s32 drv_cipher_sha256_update(cipher_hash_data_s *cipher_hash_data);
xmedia_s32 drv_cipher_sha256_final(cipher_hash_data_s *cipher_hash_data);
xmedia_s32 drv_cipher_init(xmedia_void);
xmedia_s32 drv_cipher_deinit(xmedia_void);
xmedia_s32 drv_cipher_config_aes_chn(cipher_ctrl *config, xmedia_bool is_encrypt);
xmedia_s32 drv_cipher_aes(cipher_data_s *ci_data);
xmedia_s32 drv_cipher_klad_load_key(xmedia_u32 chn_id, xmedia_u32* data_in, xmedia_u32 key_len, xmedia_cipher_key_type key_type);
void cipher_debug_log(unsigned short errflag);
#endif
@@ -0,0 +1,251 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#include "xmedia_cipher_osal.h"
/*KLAD*/
#define KLAD_REG_BASE_ADDR g_klad_base
#define KLAD_REG_KLAD_CTRL (KLAD_REG_BASE_ADDR + 0x0420)
#define KLAD_REG_DAT_IN (KLAD_REG_BASE_ADDR + 0x0400)
#define KLAD_KEY_LEN 4
#define CIPHER_WAIT_IDEL_TIMES 300000
/*OTP USER*/
#define OTP_USER_IF_BASE g_efuse_otp_reg_base
#define OTP_USER_WORK_MODE (OTP_USER_IF_BASE + 0x0000)
#define OTP_USER_OP_START (OTP_USER_IF_BASE + 0x0004)
#define OTP_USER_KEY_INDEX (OTP_USER_IF_BASE + 0x0008)
#define OTP_USER_CTRL_STA (OTP_USER_IF_BASE + 0x003C)
#define REG_SYS_OTP_CLK_ADDR_PHY 0x120101BC
#define OTP_CRG_CLOCK_BIT (0x01 << 1)
typedef enum {
OTP_USER_KEY0,
OTP_USER_KEY1,
OTP_USER_KEY2,
OTP_USER_KEY3,
OTP_USER_KEY_ROOTKEY,
OTP_USER_KEY_HMACKEY,
OTP_USER_KEY_UNKNOWN,
} otp_user_key_index_e;
typedef enum {
OTP_IDEL_WORK_MODE,
OTP_READ_LOCK_STA_MODE,
OTP_LOAD_CIPHER_KEY_MODE,
OTP_WRITE_KEY_ID_OR_PASSWD_MODE,
OTP_KEY_ID_OR_PASSWD_CRC_MODE,
OTP_SET_FLAG_ENABLE_MODE,
OTP_WRITE_USER_ROOM_MODE,
OTP_READ_USER_ROOM_MODE,
OTP_UNKOOWN_MODE,
} otp_user_work_mode_e;
typedef enum {
OTP_KEY_LENGTH_64BIT,
OTP_KEY_LENGTH_128BIT,
OTP_KEY_LENGTH_256BIT,
OTP_KEY_LENGTH_UNSUPPORT,
} otp_user_key_length_e;
static xmedia_void *g_klad_base = XMEDIA_NULL;
static xmedia_void *g_efuse_otp_reg_base = XMEDIA_NULL;
static xmedia_u32 g_klad_init_flag = 0;
/* OTP init */
static xmedia_s32 hal_efuse_otp_init(xmedia_void)
{
xmedia_u32 crg_value = 0;
xmedia_u32 *sys_addr = XMEDIA_NULL;
sys_addr = cipher_ioremap_nocache(REG_SYS_OTP_CLK_ADDR_PHY, 0x100);
crg_value = hal_cipher_read_reg(sys_addr);
crg_value |= OTP_CRG_CLOCK_BIT; /* set the bit 0, clock opened */
hal_cipher_write_reg(sys_addr, crg_value);
cipher_iounmap(sys_addr);
sys_addr = XMEDIA_NULL;
g_efuse_otp_reg_base = cipher_ioremap_nocache(CIPHER_OTP_REG_BASE_ADDR_PHY, 0x100);
return XMEDIA_SUCCESS;
}
static xmedia_void hal_klad_init(xmedia_void)
{
xmedia_u32 crg_value;
xmedia_u32 *sys_addr;
sys_addr = cipher_ioremap_nocache(CIPHER_KLAD_CRG_ADDR_PHY, 0x100);
crg_value = hal_cipher_read_reg(sys_addr);
crg_value |= KLAD_CRG_RESET_BIT; /* reset */
crg_value |= KLAD_CRG_CLOCK_BIT; /* set the bit 0, clock opened */
hal_cipher_write_reg(sys_addr, crg_value);
cipher_usleep(10);
/* clock select and cancel reset 0x30100 */
crg_value &= (~KLAD_CRG_RESET_BIT); /* cancel reset */
crg_value |= KLAD_CRG_CLOCK_BIT; /* set the bit 0, clock opened */
hal_cipher_write_reg(sys_addr, crg_value);
cipher_iounmap(sys_addr);
}
xmedia_void xmedia_cipher_klad_deinit(xmedia_void)
{
if (g_klad_base != XMEDIA_NULL) {
cipher_iounmap(g_klad_base);
g_klad_base = XMEDIA_NULL;
}
if (g_efuse_otp_reg_base != XMEDIA_NULL) {
cipher_iounmap(g_efuse_otp_reg_base);
g_efuse_otp_reg_base = XMEDIA_NULL;
}
g_klad_init_flag = 0;
return ;
}
static xmedia_s32 hal_otp_wait_free(xmedia_void)
{
xmedia_u32 timeout_cnt = 0;
xmedia_u32 reg_value = 0;
while (1) {
reg_value = hal_cipher_read_reg(OTP_USER_CTRL_STA);
if ((reg_value & 0x1) == 0) /* bit0:otp_op_busy 0:idle, 1:busy */
return XMEDIA_SUCCESS;
timeout_cnt++;
if (timeout_cnt >= CIPHER_WAIT_IDEL_TIMES) {
cipher_debug_log(CIPHER_ERR_OTP_WAIT_TIMEOUT); /*OTP_WaitFree TimeOut!*/
break;
}
cipher_usleep(10);
}
return XMEDIA_FAILURE;
}
static xmedia_s32 hal_otp_wait_op_done(xmedia_void)
{
xmedia_u32 timeout_cnt = 0;
xmedia_u32 reg_value = 0;
while (1) {
reg_value = hal_cipher_read_reg(OTP_USER_CTRL_STA);
if (reg_value & 0x2) { /* bit[1] otp_user_cmd_finish */
return XMEDIA_SUCCESS;
}
timeout_cnt++;
if (timeout_cnt >= CIPHER_WAIT_IDEL_TIMES) {
cipher_debug_log(CIPHER_ERR_OTP_WAIT_TIMEOUT); /*OTP_Wait_OP_done TimeOut!*/
break;
}
cipher_usleep(10);
}
return XMEDIA_FAILURE;
}
static xmedia_s32 hal_cipher_wait_klad_done(void)
{
xmedia_u32 timeout_cnt = 0;
xmedia_u32 reg_value;
while (1) {
reg_value = hal_cipher_read_reg(KLAD_REG_KLAD_CTRL);
if ((reg_value & 0x2) == 0x00) /* bit[1] start: 1 busy; 0 free */
return XMEDIA_SUCCESS;
timeout_cnt++;
if (timeout_cnt >= CIPHER_WAIT_IDEL_TIMES) {
cipher_debug_log(CIPHER_ERR_KLAD_WAIT_TIMEOUT); /*Klad time out!*/
break;
}
cipher_usleep(10);
}
return XMEDIA_FAILURE;
}
xmedia_s32 drv_cipher_klad_load_key(xmedia_u32 chn_id, xmedia_u32* data_in, xmedia_u32 key_len, xmedia_cipher_key_type key_type)
{
xmedia_u32 i = 0, j = 0, ctrl = 0, gh = 0;
if (g_klad_init_flag == 0) {
g_klad_base = cipher_ioremap_nocache(CIPHER_KLAD_REG_BASE_ADDR_PHY, 0x100);
if (hal_efuse_otp_init() != XMEDIA_SUCCESS) {
cipher_iounmap(g_klad_base);
return XMEDIA_FAILURE;
}
hal_klad_init();
g_klad_init_flag = 1;
}
/*1: set otp key to klad*/
/*wait otp idle*/
if (XMEDIA_SUCCESS != hal_otp_wait_free())
return XMEDIA_FAILURE;
/*select key 0*/
hal_cipher_write_reg(OTP_USER_KEY_INDEX, (xmedia_u32)(key_type - 1));
/*mode*/
hal_cipher_write_reg(OTP_USER_WORK_MODE, (xmedia_u32)OTP_LOAD_CIPHER_KEY_MODE);
/*op start*/
hal_cipher_write_reg(OTP_USER_OP_START, (xmedia_u32)0x1acce551);
if (XMEDIA_SUCCESS != hal_otp_wait_op_done())
return XMEDIA_FAILURE;
/*
*klad config
*bit[18:16]: Klad2ci addr
*bit[4:3]: klad type, 00:cipher's klad, 01:rsa's klad
*bit[2]: high/low 128bit flag. 0:low 128bit 1:high 128bit
*bit[1]: 1:start
*bit[0]: 1:decrypt
*/
ctrl = chn_id << 16;
ctrl |= (xmedia_u32)XMEDIA_CIPHER_KLAD_TARGET_AES << 3;
ctrl |= (xmedia_u32)1;
hal_cipher_write_reg(KLAD_REG_KLAD_CTRL, ctrl);
for (i = 0; i < key_len / 16; i++) {
gh = (i == 1 ? 1 : 0);
for (j = 0; j < 4; j++) {
hal_cipher_write_reg(KLAD_REG_DAT_IN + j * KLAD_KEY_LEN, data_in[i * 4 + j]);
}
/* start */
ctrl = hal_cipher_read_reg(KLAD_REG_KLAD_CTRL);
ctrl &= ~(0x01 << 2);
ctrl |= gh << 2;
ctrl |= 0x2;
hal_cipher_write_reg(KLAD_REG_KLAD_CTRL, ctrl);
//wait lock done
if (XMEDIA_SUCCESS != hal_cipher_wait_klad_done())
return XMEDIA_FAILURE;
}
return XMEDIA_SUCCESS;
}
@@ -0,0 +1,69 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef __XMDEDIA_CIPHER_OSAL_H_
#define __XMDEDIA_CIPHER_OSAL_H_
#include "linux/lotus/securec.h"
#include "linux/delay.h"
#include "common.h"
#include "xmedia_type.h"
#include "xmedia_cipher.h"
#include "xmedia_cipher_drv.h"
#include "xmedia_cipher_config.h"
/**************************** M A C R O ****************************/
#define cipher_min(a, b) ((a) < (b) ? (a) : (b))
#define get_ulong_low(dw) (unsigned int)(dw)
#define get_ulong_high(dw) 0
#define make_ulong(low, high) (low)
#define u32_to_point(addr) ((xmedia_void*)((xmedia_size_t)(addr)))
#define point_to_u32(addr) ((xmedia_u32)((xmedia_size_t)(addr)))
#define hal_cipher_read_reg(addr) (*(volatile unsigned int *)(addr))
#define hal_cipher_write_reg(addr, result) (*(volatile unsigned int *)(addr) = (result))
//#define hal_cipher_read_reg(addr) reg_get(addr)
//#define hal_cipher_write_reg(addr, result) reg_set(addr, result)
#define hal_set_bit(src, bit) ((src) |= (1 << (bit)))
#define hal_clear_bit(src, bit) ((src) &= ~(1 << (bit)))
#define cipher_cpu_to_be16(v) (((v) << 8) | ((v) >> 8))
//#define cipher_cpu_to_be32(v) (((v) >> 24) | (((v) >> 8) & 0xff00) | (((v) << 8) & 0xff0000) | ((v) << 24))
#define cipher_cpu_to_be32(v) (((v) >> 24) | (((v) >> 8) & 0xff00) | (((v)&0x0000ff00)<<8) | (((v)&0x000000ff)<<24))
#define cipher_cpu_to_be64(x) ((xmedia_u64)( \
(((x) & 0x00000000000000ffULL) << 56) | (((x) & 0x000000000000ff00ULL) << 40) | \
(((x) & 0x0000000000ff0000ULL) << 24) | (((x) & 0x00000000ff000000ULL) << 8) | \
(((x) & 0x000000ff00000000ULL) >> 8) | (((x) & 0x0000ff0000000000ULL) >> 24) | \
(((x) & 0x00ff000000000000ULL) >> 40) | (((x) & 0xff00000000000000ULL) >> 56)))
/**************************** S T D L I B ****************************/
#define cipher_ioremap_nocache(addr, size) (xmedia_void*)(addr)
#define cipher_iounmap(x)
#define CIPHER_MUTEX xmedia_void *
#define cipher_mutex_init(x)
#define cipher_mutex_lock(x)
#define cipher_mutex_unlock(x)
#define cipher_mutex_destroy(x)
#define CIPHER_QUEUE_HEAD xmedia_void *
#define cipher_queue_init(x)
#define cipher_queue_wait_up(x)
#define cipher_queue_wait_timeout(head, con, time)
#define cipher_malloc(x) malloc(x)
#define cipher_free(x) free(x)
#define crypto_memset(d,dmax,c,l) memset_s(d,dmax,c,l)
#define crypto_memcmp(a,b,c) ((0 == memcmp(a,b,c))?(XMEDIA_SUCCESS):(XMEDIA_FAILURE))
#define crypto_memcpy(d,dmax,s,l) memcpy_s(d,dmax,s,l)
#define cipher_msleep(msec) udelay((msec)*1000)
#define cipher_usleep(usec) udelay(usec)
#define xmedia_err_cipher(a) printf("%s", a)
#endif
@@ -0,0 +1,468 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#ifndef _XMDEDIA_CIPHER_REG_H_
#define _XMDEDIA_CIPHER_REG_H_
#define cipher_key(id) (g_spacc_reg_base + 0x0500 + (id) * 0x20)
#define ODD_EVEN_KEY_SEL (g_spacc_reg_base + 0x0690)
#define CALC_ERR (g_spacc_reg_base + 0x0720)
#define CIPHER_INT_RAW (g_spacc_reg_base + 0x0808)
#define chn_n_cipher_ctrl(id) (g_spacc_reg_base + 0x0800 + (id) * 0x80)
#define chn_n_cipher_in_node_cfg(id) (g_spacc_reg_base + 0x0804 + (id) * 0x80)
#define chn_n_cipher_in_node_start_addr(id) (g_spacc_reg_base + 0x0808 + (id) * 0x80)
#define chn_n_cipher_in_buf_rptr(id) (g_spacc_reg_base + 0x080C + (id) * 0x80)
#define chn_n_cipher_out_node_cfg(id) (g_spacc_reg_base + 0x0830 + (id) * 0x80)
#define chn_n_cipher_out_node_start_addr(id) (g_spacc_reg_base + 0x0834 + (id) * 0x80)
#define chn_n_cipher_out_buf_rptr(id) (g_spacc_reg_base + 0x0838 + (id) * 0x80)
#define chn_n_cipher_in_node_start_addr_high(id) (g_spacc_reg_base + 0x0860 + (id) * 0x80)
#define chn_n_cipher_out_node_start_addr_high(id) (g_spacc_reg_base + 0x0870 + (id) * 0x80)
#define HASH_INT_RAW (g_spacc_reg_base + 0x0C0C)
#define chn_n_hash_ctrl(id) (g_spacc_reg_base + 0x0C00 + (id) * 0x80)
#define chn_n_hash_in_node_cfg(id) (g_spacc_reg_base + 0x0C04 + (id) * 0x80)
#define chn_n_hash_in_node_start_addr(id) (g_spacc_reg_base + 0x0C08 + (id) * 0x80)
#define chn_n_hash_in_buf_rptr(id) (g_spacc_reg_base + 0x0C0C + (id) * 0x80)
#define chn_n_hash_state_val(id) (g_spacc_reg_base + 0x0740 + (id) * 0x08)
#define chn_n_hash_state_val_addr(id) (g_spacc_reg_base + 0x0744 + (id) * 0x08)
#define chn_n_hash_in_node_start_addr_high(id) (g_spacc_reg_base + 0x0C20 + (id) * 0x80)
#define spacc_read(addr) *(volatile unsigned int *)(addr)
#define spacc_write(addr, val) *(volatile unsigned int *)(addr) = (val)
/* Define the union u_hdcp_mode_ctrl */
typedef union {
/* Define the struct bits */
struct {
unsigned int hdcp_mode_en : 1 ; /* [0] */
unsigned int hdcp_rootkey_sel : 2 ; /* [2..1] */
unsigned int reserved_0 : 1 ; /* [3] */
unsigned int hdmi_tx_hdcp14_wr_en : 1 ; /* [4] */
unsigned int hdmi_rx_hdcp14_wr_en : 1 ; /* [5] */
unsigned int hdmi_rx_hdcp22_wr_en : 1 ; /* [6] */
unsigned int reserved_1 : 1 ; /* [7] */
unsigned int hdcp_wr_sel : 2 ; /* [9..8] */
unsigned int reserved_2 : 22 ; /* [31..10] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_hdcp_mode_ctrl;
/* Define the union u_sec_chn_cfg */
typedef union {
/* Define the struct bits */
struct {
unsigned int cipher_sec_chn_cfg : 8 ; /* [7..0] */
unsigned int cipher_sec_chn_cfg_lock : 1 ; /* [8] */
unsigned int reserved_0 : 7 ; /* [15..9] */
unsigned int hash_sec_chn_cfg : 8 ; /* [23..16] */
unsigned int hash_sec_chn_cfg_lock : 1 ; /* [24] */
unsigned int reserved_1 : 7 ; /* [31..25] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_sec_chn_cfg;
/* Define the union u_mem_ema_cfg */
typedef union {
/* Define the struct bits */
struct {
unsigned int rfs_ema : 3 ; /* [2..0] */
unsigned int reserved_0 : 1 ; /* [3] */
unsigned int rfs_emaw : 2 ; /* [5..4] */
unsigned int reserved_1 : 2 ; /* [7..6] */
unsigned int rft_emaa : 3 ; /* [10..8] */
unsigned int rft_emab : 3 ; /* [13..11] */
unsigned int rft_emasa : 1 ; /* [14] */
unsigned int rft_colldisn : 1 ; /* [15] */
unsigned int reserved_2 : 16 ; /* [31..16] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_mem_ema_cfg;
/* Define the union u_key_st */
typedef union {
/* Define the struct bits */
struct {
unsigned int key_req_cur_st : 2 ; /* [1..0] */
unsigned int reserved_0 : 30 ; /* [31..2] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_key_st;
/* Define the union u_calc_st0 */
typedef union {
/* Define the struct bits */
struct {
unsigned int cipher_calc_cur_st : 4 ; /* [3..0] */
unsigned int reserved_0 : 4 ; /* [7..4] */
unsigned int hash_calc_cur_st : 4 ; /* [11..8] */
unsigned int hdcp_key_ksv_crc4 : 4 ; /* [15..12] */
unsigned int reserved_1 : 16 ; /* [31..16] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_calc_st0;
/* Define the union u_calc_err */
typedef union {
/* Define the struct bits */
struct {
unsigned int klad_key_use_err : 1 ; /* [0] */
unsigned int alg_len_err : 1 ; /* [1] */
unsigned int smmu_page_unvlid : 1 ; /* [2] */
unsigned int reserved_0 : 29 ; /* [31..3] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_calc_err;
/* Define the union u_chann_hash_state_val_addr */
typedef union {
/* Define the struct bits */
struct {
unsigned int hash_state_val_addr : 4 ; /* [3..0] */
unsigned int reserved_0 : 28 ; /* [31..4] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_chann_hash_state_val_addr;
/* Define the union u_chan0_cipher_ctrl */
typedef union {
/* Define the struct bits */
struct {
unsigned int sym_ch0_start : 1 ; /* [0] */
unsigned int sym_ch0_alg_mode : 3 ; /* [3..1] */
unsigned int sym_ch0_alg_sel : 3 ; /* [6..4] */
unsigned int sym_ch0_decrypt : 1 ; /* [7] */
unsigned int sym_ch0_dat_width : 2 ; /* [9..8] */
unsigned int sym_ch0_key_length : 2 ; /* [11..10] */
unsigned int sym_ch0_ccm_gcm_input_flag : 2 ; /* [13..12] */
unsigned int sym_ch0_key_sel : 1 ; /* [14] */
unsigned int sym_ch0_ivin_sel : 1 ; /* [15] */
unsigned int reserved_0 : 2 ; /* [17..16] */
unsigned int sym_ch0_sm1_round_num : 2 ; /* [19..18] */
unsigned int sym_ch0_gcm_iv_len : 4 ; /* [23..20] */
unsigned int sym_ch0_ccm_gcm_pc_last : 1 ; /* [24] */
unsigned int sym_ccm_gcm_last_block : 4 ; /* [28..25] */
unsigned int reserved_1 : 3 ; /* [31..28] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_chan0_cipher_ctrl;
/* Define the union u_cipher_int_status */
typedef union {
/* Define the struct bits */
struct {
unsigned int reserved_0 : 1 ; /* [0] */
unsigned int cipher_chn_ibuf_int : 7 ; /* [7..1] */
unsigned int cipher_chn_obuf_int : 8 ; /* [15..8] */
unsigned int reserved_1 : 16 ; /* [31..16] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_cipher_int_status;
/* Define the union u_cipher_int_en */
typedef union {
/* Define the struct bits */
struct {
unsigned int reserved_0 : 1 ; /* [0] */
unsigned int cipher_chn_ibuf_en : 7 ; /* [7..1] */
unsigned int cipher_chn_obuf_en : 8 ; /* [15..8] */
unsigned int reserved_1 : 14 ; /* [29..16] */
unsigned int cipher_sec_int_en : 1 ; /* [30] */
unsigned int cipher_nsec_int_en : 1 ; /* [31] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_cipher_int_en;
/* Define the union u_cipher_int_raw */
typedef union {
/* Define the struct bits */
struct {
unsigned int reserved_0 : 1 ; /* [0] */
unsigned int cipher_chn_ibuf_raw : 7 ; /* [7..1] */
unsigned int cipher_chn_obuf_raw : 8 ; /* [15..8] */
unsigned int reserved_1 : 16 ; /* [31..16] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_cipher_int_raw;
/* Define the union u_cipher_in_smmu_en */
typedef union {
/* Define the struct bits */
struct {
unsigned int cipher_in_chan_rd_dat_smmu_en : 7 ; /* [6..0] */
unsigned int reserved_0 : 9 ; /* [15..7] */
unsigned int cipher_in_chan_rd_node_smmu_en : 7 ; /* [22..16] */
unsigned int reserved_1 : 9 ; /* [31..23] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_cipher_in_smmu_en;
/* Define the union u_out_smmu_en */
typedef union {
/* Define the struct bits */
struct {
unsigned int out_chan_wr_dat_smmu_en : 7 ; /* [6..0] */
unsigned int reserved_0 : 9 ; /* [15..7] */
unsigned int out_chan_rd_node_smmu_en : 7 ; /* [22..16] */
unsigned int reserved_1 : 9 ; /* [31..23] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_out_smmu_en;
/* Define the union u_in_st */
typedef union {
/* Define the struct bits */
struct {
unsigned int hash_in_ctrl_cur_st : 5 ; /* [4..0] */
unsigned int sym_in_ctrl_cur_st : 3 ; /* [7..5] */
unsigned int sym_hash_req_cur_st : 4 ; /* [11..8] */
unsigned int reserved_0 : 20 ; /* [31..12] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_in_st;
/* Define the union u_out_st */
typedef union {
/* Define the struct bits */
struct {
unsigned int out_cur_st : 5 ; /* [4..0] */
unsigned int reserved_0 : 27 ; /* [31..5] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_out_st;
/* Define the union u_chann_cipher_ctrl */
typedef union {
/* Define the struct bits */
struct {
unsigned int reserved_0 : 1 ; /* [0] */
unsigned int sym_chn_alg_mode : 3 ; /* [3..1] */
unsigned int sym_chn_alg_sel : 3 ; /* [6..4] */
unsigned int sym_chn_decrypt : 1 ; /* [7] */
unsigned int sym_chn_dat_width : 2 ; /* [9..8] */
unsigned int sym_chn_key_length : 2 ; /* [11..10] */
unsigned int reserved_1 : 2 ; /* [13..12] */
unsigned int sym_chn_key_sel : 1 ; /* [14] */
unsigned int reserved_2 : 1 ; /* [15] */
unsigned int sym_chn_dout_byte_swap_en : 1 ; /* [16] */
unsigned int sym_chn_din_byte_swap_en : 1 ; /* [17] */
unsigned int sym_chn_sm1_round_num : 2 ; /* [19..18] */
unsigned int reserved_3 : 2 ; /* [21..20] */
unsigned int weight : 10 ; /* [31..22] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_chann_cipher_ctrl;
/* Define the union u_chann_cipher_in_node_cfg */
typedef union {
/* Define the struct bits */
struct {
unsigned int cipher_in_node_mpackage_int_level : 7 ; /* [6..0] */
unsigned int reserved_0 : 1 ; /* [7] */
unsigned int cipher_in_node_rptr : 7 ; /* [14..8] */
unsigned int reserved_1 : 1 ; /* [15] */
unsigned int cipher_in_node_wptr : 7 ; /* [22..16] */
unsigned int reserved_2 : 1 ; /* [23] */
unsigned int cipher_in_node_total_num : 7 ; /* [30..24] */
unsigned int reserved_3 : 1 ; /* [31] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_chann_cipher_in_node_cfg;
/* Define the union u_chann_cipher_in_left_byte */
typedef union {
/* Define the struct bits */
struct {
unsigned int in_left_byte0 : 24 ; /* [23..0] */
unsigned int in_byte_cnt : 2 ; /* [25..24] */
unsigned int in_word_cnt : 2 ; /* [27..26] */
unsigned int reserved_0 : 4 ; /* [31..28] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_chann_cipher_in_left_byte;
/* Define the union u_chann_cipher_out_node_cfg */
typedef union {
/* Define the struct bits */
struct {
unsigned int cipher_out_node_mpackage_int_level : 7 ; /* [6..0] */
unsigned int reserved_0 : 1 ; /* [7] */
unsigned int cipher_out_node_rptr : 7 ; /* [14..8] */
unsigned int reserved_1 : 1 ; /* [15] */
unsigned int cipher_out_node_wptr : 7 ; /* [22..16] */
unsigned int reserved_2 : 1 ; /* [23] */
unsigned int cipher_out_node_total_num : 7 ; /* [30..24] */
unsigned int reserved_3 : 1 ; /* [31] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_chann_cipher_out_node_cfg;
/* Define the union u_chann_cipher_out_left_byte */
typedef union {
/* Define the struct bits */
struct {
unsigned int out_left_byte0 : 24 ; /* [23..0] */
unsigned int out_byte_cnt : 2 ; /* [25..24] */
unsigned int out_word_cnt : 2 ; /* [27..26] */
unsigned int reserved_0 : 4 ; /* [31..28] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_chann_cipher_out_left_byte;
/* Define the union u_chan0_hash_ctrl */
typedef union {
/* Define the struct bits */
struct {
unsigned int hash_ch0_start : 1 ; /* [0] */
unsigned int hash_ch0_agl_sel : 3 ; /* [3..1] */
unsigned int hash_ch0_hmac_calc_step : 1 ; /* [4] */
unsigned int hash_ch0_mode : 1 ; /* [5] */
unsigned int hash_ch0_key_sel : 1 ; /* [6] */
unsigned int reserved_0 : 2 ; /* [8..7] */
unsigned int hash_ch0_auto_padding_en : 1 ; /* [9] */
unsigned int hash_ch0_hmac_key_addr : 3 ; /* [12..10] */
unsigned int hash_ch0_used : 1 ; /* [13] */
unsigned int hash_ch0_sec_alarm : 1 ; /* [13] */
unsigned int reserved_1 : 17 ; /* [31..15] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_chan0_hash_ctrl;
/* Define the union u_hash_int_status */
typedef union {
/* Define the struct bits */
struct {
unsigned int reserved_0 : 18 ; /* [17..0] */
unsigned int hash_ch0_oram_int : 1 ; /* [18] */
unsigned int hash_ch1_oram_int : 1 ; /* [19] */
unsigned int hash_ch2_oram_int : 1 ; /* [20] */
unsigned int hash_ch3_oram_int : 1 ; /* [21] */
unsigned int hash_ch4_oram_int : 1 ; /* [22] */
unsigned int hash_ch5_oram_int : 1 ; /* [23] */
unsigned int hash_ch6_oram_int : 1 ; /* [24] */
unsigned int hash_ch7_oram_int : 1 ; /* [25] */
unsigned int reserved_1 : 6 ; /* [31..26] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_hash_int_status;
/* Define the union u_hash_int_en */
typedef union {
/* Define the struct bits */
struct {
unsigned int reserved_0 : 18 ; /* [17..0] */
unsigned int hash_chn_oram_en : 8 ; /* [25..18] */
unsigned int reserved_1 : 4 ; /* [29..26] */
unsigned int hash_sec_int_en : 1 ; /* [30] */
unsigned int hash_int_en : 1 ; /* [31] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_hash_int_en;
/* Define the union u_hash_int_raw */
typedef union {
/* Define the struct bits */
struct {
unsigned int reserved_0 : 18 ; /* [17..0] */
unsigned int hash_chn_oram_raw : 8 ; /* [25..18] */
unsigned int reserved_1 : 6 ; /* [31..26] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_hash_int_raw;
/* Define the union u_hash_in_smmu_en */
typedef union {
/* Define the struct bits */
struct {
unsigned int hash_in_chan_rd_dat_smmu_en : 7 ; /* [6..0] */
unsigned int reserved_0 : 9 ; /* [15..7] */
unsigned int hash_in_chan_rd_node_smmu_en : 7 ; /* [22..16] */
unsigned int reserved_1 : 9 ; /* [31..23] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_hash_in_smmu_en;
/* Define the union u_chann_hash_ctrl */
typedef union {
/* Define the struct bits */
struct {
unsigned int reserved_0 : 1 ; /* [0] */
unsigned int hash_chn_agl_sel : 3 ; /* [3..1] */
unsigned int reserved_1 : 1 ; /* [4] */
unsigned int hash_chn_mode : 1 ; /* [5] */
unsigned int hash_chn_key_sel : 1 ; /* [6] */
unsigned int hash_chn_dat_in_byte_swap_en : 1 ; /* [7] */
unsigned int hash_chn_dat_in_bit_swap_en : 1 ; /* [8] */
unsigned int hash_chn_auto_padding_en : 1 ; /* [9] */
unsigned int hash_chn_hmac_key_addr : 3 ; /* [12..10] */
unsigned int reserved_2 : 19 ; /* [31..13] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_chann_hash_ctrl;
/* Define the union u_chann_hash_in_node_cfg */
typedef union {
/* Define the struct bits */
struct {
unsigned int hash_in_node_mpackage_int_level : 8 ; /* [7..0] */
unsigned int hash_in_node_rptr : 8 ; /* [15..8] */
unsigned int hash_in_node_wptr : 8 ; /* [23..16] */
unsigned int hash_in_node_total_num : 8 ; /* [31..24] */
} bits;
/* Define an unsigned member */
unsigned int u32;
} u_chann_hash_in_node_cfg;
#endif
@@ -0,0 +1,754 @@
/*
* Copyright (c) XMEDIA. All rights reserved.
*/
#include "xmedia_cipher_osal.h"
//#include "safety.h"
/************************************************************/
static xmedia_void *g_rsa_reg_base = XMEDIA_NULL;
static xmedia_void *g_rsa_reg_crg = XMEDIA_NULL;
static xmedia_u32 rsa_init_flag = 0;
/************************************************************/
#define RSA_REG_BASE_RSA g_rsa_reg_base
#define SEC_RSA_BUSY_REG (RSA_REG_BASE_RSA + 0x010C)
#define SEC_RSA_MOD_REG (RSA_REG_BASE_RSA + 0x0110)
#define SEC_RSA_WSEC_REG (RSA_REG_BASE_RSA + 0x0104)
#define SEC_RSA_WDAT_REG (RSA_REG_BASE_RSA + 0x0108)
#define SEC_RSA_RRSLT_REG (RSA_REG_BASE_RSA + 0x0120)
#define SEC_RSA_START_REG (RSA_REG_BASE_RSA + 0x0114)
#define SEC_RSA_ERROR_REG (RSA_REG_BASE_RSA + 0x0124)
#define RSA_DATA_CLR_KEY (1 << 2)
#define RSA_DATA_CLR_INPUT (2 << 2)
#define RSA_DATA_CLR_OUTPUT (4 << 2)
#define RSA_MOD_SEL (3 << 0)
#define RSA_MOD_SEL_OPT (0 << 0)
#define RSA_MOD_SEL_RAM_CLAER (2 << 0)
#define RSA_BUSY (1 << 0)
#define RSA_START (1 << 0)
#define RSA_MAX_KEY_LEN 512
#define CRC16_POLYNOMIAL 0x1021
#define RSA_PKCS1_PSS_MGF1_SHA256_MALLOC_SIZE 0x44
#define RSA_PKCS1_PSS_PADDING_CHECK_MALLOC_SIZE 0x48
#define ASN1_HASH_SHA256 "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20"
#define SHA256_DATA_BYTE_LEN 32
typedef enum {
RSA_DATA_TYPE_CONTEXT,
RSA_DATA_TYPE_MODULE,
RSA_DATA_TYPE_KEY,
} rsa_data_type_e;
typedef enum {
RSA_KEY_WIDTH_1K = 0x00,
RSA_KEY_WIDTH_2K = 0x01,
RSA_KEY_WIDTH_4K = 0x02,
RSA_KEY_WIDTH_3K = 0x03,
RSA_KEY_WIDTH_BUTT = 0xff,
} rsa_key_width_e;
typedef struct {
xmedia_u32 hlen;
xmedia_u32 klen;
xmedia_u32 em_bit;
xmedia_u8 *in_data;
xmedia_u32 in_len;
} rsa_padding_s;
typedef struct {
xmedia_u8 *masked_db;
xmedia_u8 *masked_seed;
xmedia_u8 salt[RSA_MAX_KEY_LEN];
xmedia_u32 msb_bits;
xmedia_u32 slen;
xmedia_u32 key_len;
} rsa_pkcs1_pss_s;
typedef struct {
xmedia_u8 *input_data;
xmedia_u8 *output_data;
xmedia_u32 data_len;
xmedia_u8 *rsa_n;
xmedia_u8 *rsa_k;
xmedia_u16 rsa_n_len;
xmedia_u16 rsa_k_len;
} rsa_data_s;
static xmedia_void hal_rsa_start(xmedia_void)
{
hal_cipher_write_reg(SEC_RSA_START_REG, 0x01);
}
static xmedia_s32 hal_rsa_wait_free(xmedia_void)
{
xmedia_u32 value;
xmedia_u32 try_count = 0;
do {
value = hal_cipher_read_reg(SEC_RSA_BUSY_REG);
if ((value & RSA_BUSY) == 0)
return XMEDIA_SUCCESS;
try_count++;
cipher_usleep(10);
} while (try_count < RSA_TIMEOUT_CNT);
return XMEDIA_FAILURE;
}
static xmedia_void hal_rsa_clear_ram(xmedia_void)
{
xmedia_u32 value;
value = hal_cipher_read_reg(SEC_RSA_MOD_REG);
value &= 0x60;
value |= RSA_DATA_CLR_INPUT | RSA_DATA_CLR_OUTPUT | RSA_DATA_CLR_KEY | RSA_MOD_SEL_RAM_CLAER;
hal_cipher_write_reg(SEC_RSA_MOD_REG, value);
}
static xmedia_void hal_rsa_config_mode(rsa_key_width_e ken_width)
{
xmedia_u32 value;
value = ((xmedia_u32)ken_width << 5) | RSA_MOD_SEL_OPT; /* 5 left shift */
hal_cipher_write_reg(SEC_RSA_MOD_REG, value);
}
static xmedia_void hal_rsa_write_data(rsa_data_type_e data_type,
xmedia_u8 *data,
xmedia_u32 data_len,
xmedia_u32 length,
xmedia_u32 random[2]) /* 2 random size */
{
xmedia_u32 *reg = XMEDIA_NULL;
xmedia_u8 *pos = XMEDIA_NULL;
xmedia_u32 i, value;
xmedia_bool id = 0;
if (data_type == RSA_DATA_TYPE_CONTEXT)
reg = SEC_RSA_WDAT_REG;
else
reg = SEC_RSA_WSEC_REG;
pos = data;
for (i = 0; i < length; i += 4) { /* 4 groups */
value = (xmedia_u32)pos[0];
value |= ((xmedia_u32)pos[1]) << 8; /* 1 index, 8 left shift */
value |= ((xmedia_u32)pos[2]) << 16; /* 2 index, 16 left shift */
value |= ((xmedia_u32)pos[3]) << 24; /* 3 index, 24 left shift */
if (data_type != RSA_DATA_TYPE_CONTEXT)
value ^= random[id];
hal_cipher_write_reg(reg, value);
pos += 4; /* 4 groups */
id = (xmedia_u32)id ^ 0x01;
}
}
static xmedia_void hal_rsa_read_data(xmedia_u8 *data, xmedia_u32 data_len, xmedia_u32 klen)
{
xmedia_u32 value;
xmedia_u8 *pos = XMEDIA_NULL;
xmedia_u32 i;
pos = data;
for (i = 0; i < klen; i += 4) { /* 4 groups */
value = hal_cipher_read_reg(SEC_RSA_RRSLT_REG);
pos[0] = (xmedia_u8)(value & 0xFF);
pos[1] = (xmedia_u8)((value >> 8) & 0xFF); /* 1 index, 8 right shift */
pos[2] = (xmedia_u8)((value >> 16) & 0xFF); /* 2 index, 16 right shift */
pos[3] = (xmedia_u8)((value >> 24) & 0xFF); /* 3 index, 24 right shift */
pos += 4; /* 4 groups */
}
}
static xmedia_u32 hal_rsa_get_error_code(xmedia_void)
{
xmedia_u32 value;
value = hal_cipher_read_reg(SEC_RSA_ERROR_REG);
return value;
}
static xmedia_void hal_rsa_enable(xmedia_void)
{
xmedia_u32 value;
value = hal_cipher_read_reg(g_rsa_reg_crg);
hal_set_bit(value, 5); /* 5bit clock opened */
hal_cipher_write_reg(g_rsa_reg_crg, value);
cipher_usleep(10);
hal_clear_bit(value, 4); /* 4bit cancel reset */
hal_cipher_write_reg(g_rsa_reg_crg, value);
cipher_usleep(10);
//enable_rsa_safety();
}
static xmedia_void hal_rsa_disable(xmedia_void)
{
xmedia_u32 value;
value = hal_cipher_read_reg(g_rsa_reg_crg);
hal_set_bit(value, 4); /* 4bit reset */
hal_cipher_write_reg(g_rsa_reg_crg, value);
cipher_usleep(10);
hal_clear_bit(value, 5); /* 5bit clock closed */
hal_cipher_write_reg(g_rsa_reg_crg, value);
cipher_usleep(10);
}
static xmedia_u32 rsa_get_bit_num(xmedia_u8 *big_num, xmedia_u32 num_len)
{
static const xmedia_s8 bits[16] = {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4}; /* 16 bits size */
xmedia_u32 i;
for (i = 0; i < num_len; i++) {
xmedia_u32 num;
num = bits[(big_num[i] & 0xF0) >> 4]; /* 4 right shift */
if (num > 0)
return (num_len - i - 1) * 8 + num + 4; /* 8, 4 */
num = bits[big_num[i] & 0xF];
if (num > 0)
return (num_len - i - 1) * 8 + num; /* 8 */
}
return 0;
}
static xmedia_s32 rsa_pkcs1_mgf1(xmedia_u8 *seed, xmedia_u32 seed_len, xmedia_u8 *mask, xmedia_u32 mask_len)
{
xmedia_s32 ret = XMEDIA_FAILURE;
xmedia_u32 i, out_len;
xmedia_u8 *ptr_cnt = XMEDIA_NULL;
xmedia_u8 *ptr_md = XMEDIA_NULL;
xmedia_u8 *ptr_seed = XMEDIA_NULL;
xmedia_u8 *ptr_malloc = XMEDIA_NULL;
ptr_malloc = (xmedia_u8 *)cipher_malloc(RSA_PKCS1_PSS_MGF1_SHA256_MALLOC_SIZE);
if (ptr_malloc == XMEDIA_NULL) {
cipher_debug_log(CIPHER_ERR_RSA_MALLOC);
return XMEDIA_FAILURE;
}
crypto_memset(ptr_malloc, RSA_PKCS1_PSS_MGF1_SHA256_MALLOC_SIZE, 0, RSA_PKCS1_PSS_MGF1_SHA256_MALLOC_SIZE);
ptr_cnt = ptr_malloc;
ptr_md = ptr_malloc + 4;
ptr_seed = (ptr_malloc + 4 + SHA256_RESULT_SIZE);
crypto_memcpy(ptr_seed, (RSA_PKCS1_PSS_MGF1_SHA256_MALLOC_SIZE - SHA256_RESULT_SIZE - 4), seed, seed_len);
/* PKCS#1 V2.1*/
for (i = 0, out_len = 0; out_len < mask_len; i++) {
xmedia_u32 j, md_len;
//sha256 fixed
md_len = 32;
ptr_cnt[0] = (xmedia_u8)((i >> 24) & 0xFF); /* 0 ptr_cnt index, 24 right shift */
ptr_cnt[1] = (xmedia_u8)((i >> 16) & 0xFF); /* 1 ptr_cnt index, 16 right shift */
ptr_cnt[2] = (xmedia_u8)((i >> 8) & 0xFF); /* 2 ptr_cnt index, 8 right shift */
ptr_cnt[3] = (xmedia_u8)(i & 0xFF); /* 3 ptr_cnt index */
ret = xmedia_cipher_sha256_init();
ret |= xmedia_cipher_sha256_update(ptr_seed, seed_len);
ret |= xmedia_cipher_sha256_update(ptr_cnt, 4); /* 4 ptr_cnt size */
ret |= xmedia_cipher_sha256_final(ptr_md);
if(ret != XMEDIA_SUCCESS)
{
cipher_debug_log(CIPHER_ERR_RSA_SHA256); /*sha256 failed*/
goto free_ptr;
}
for (j = 0; (j < md_len) && (out_len < mask_len); j++)
mask[out_len++] ^= ptr_md[j];
}
free_ptr:
cipher_free(ptr_malloc);
ptr_malloc = XMEDIA_NULL;
return ret;
}
static xmedia_s32 rsa_padding_check_pkcs1_pss_hash(rsa_padding_s *pad, xmedia_u8 *mhash, rsa_pkcs1_pss_s *pss)
{
xmedia_s32 ret;
xmedia_u32 mlen;
xmedia_u8 *ptr_m = XMEDIA_NULL;
xmedia_u8 arr_h[SHA256_RESULT_SIZE];
/*8+32+32*/
mlen = pss->slen + pad->hlen + 8; /* 8 */
ptr_m = (xmedia_u8 *)cipher_malloc(RSA_PKCS1_PSS_PADDING_CHECK_MALLOC_SIZE);
if(ptr_m == XMEDIA_NULL)
{
return XMEDIA_FAILURE;
}
crypto_memset(arr_h, SHA256_RESULT_SIZE, 0, SHA256_RESULT_SIZE);
crypto_memset(ptr_m, RSA_PKCS1_PSS_PADDING_CHECK_MALLOC_SIZE, 0, mlen);
/* M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt */
crypto_memset(ptr_m, mlen, 0x00, 8); /* 8, 0 counts */
crypto_memcpy(&ptr_m[8], mlen - 8, mhash, pad->hlen); /* 8, 0 counts */
crypto_memcpy(&ptr_m[8 + pad->hlen], mlen - 8 - pad->hlen, pss->salt, pss->slen); /* 8, 0 counts */
ret = xmedia_cipher_sha256_init();
ret |= xmedia_cipher_sha256_update(ptr_m, mlen);
ret |= xmedia_cipher_sha256_final(arr_h);
cipher_free(ptr_m); /* Must free ptr_m befort return */
ptr_m = XMEDIA_NULL;
if(ret != XMEDIA_SUCCESS)
{
cipher_debug_log(CIPHER_ERR_RSA_SHA256); /*sha256 failed*/
return XMEDIA_FAILURE;
}
if(crypto_memcmp(arr_h, pss->masked_seed, pad->hlen) != XMEDIA_SUCCESS)
{
cipher_debug_log(CIPHER_ERR_RSA_VERIFY_HASH_CMP); /*masked_seed cmp failed*/
return XMEDIA_FAILURE;
}
return XMEDIA_SUCCESS;
}
static xmedia_s32 rsa_padding_check_pkcs1_pss(rsa_padding_s *pad, xmedia_u8 *mhash)
{
xmedia_u32 ret;
xmedia_u32 index, tmp_len;
rsa_pkcs1_pss_s pss;
crypto_memset(&pss, sizeof(rsa_pkcs1_pss_s), 0, sizeof(rsa_pkcs1_pss_s));
pss.slen = pad->hlen;
pss.key_len = (pad->em_bit + 7) / 8; /* 7, 8 */
pss.msb_bits = (pad->em_bit - 1) & 0x07;
if (pss.key_len < (pad->hlen + pss.slen + 2)) { /* 2 */
cipher_debug_log(CIPHER_ERR_RSA_VERIFY_M_LEN); /*message too long*/
return XMEDIA_FAILURE;
}
if (pad->in_data[0] & (0xFF << pss.msb_bits)) {
cipher_debug_log(CIPHER_ERR_RSA_VERIFY_EM0); /*inconsistent, EM[0] invalid*/
return XMEDIA_FAILURE;
}
if (pss.msb_bits == 0) {
pad->in_data++;
pss.key_len--;
}
pss.masked_db = pad->in_data;
pss.masked_seed = pad->in_data + pss.key_len - pad->hlen - 1;
if (pad->in_data[pss.key_len - 1] != 0xBC) {
cipher_debug_log(CIPHER_ERR_RSA_VERIFY_BC); /*inconsistent, EM[key_len - 1] != 0xBC*/
return XMEDIA_FAILURE;
}
/* formula: maskedDB = DB xor dbMask, DB = PS || 0x01 || salt */
ret = rsa_pkcs1_mgf1(pss.masked_seed, pad->hlen, pss.masked_db, pss.key_len - pad->hlen - 1);
if(ret != XMEDIA_SUCCESS)
{
cipher_debug_log(CIPHER_ERR_RSA_MGF1); /*rsa_pkcs1_mgf1 failed*/
return XMEDIA_FAILURE;
}
if (pss.msb_bits)
pss.masked_db[0] &= 0xFF >> (8 - pss.msb_bits); /* 8 */
tmp_len = pss.key_len - pss.slen - pad->hlen - 2; /* 2 */
if (tmp_len >= RSA_MAX_KEY_LEN - 1) { /* -1 is for index++, avoid masked_db overflow */
cipher_debug_log(CIPHER_ERR_RSA_VERIFY_MASKEDDB_LEN); /*operate masked_db maybe overflow*/
return XMEDIA_FAILURE;
}
for (index = 0; index < tmp_len; index++) {
if (pss.masked_db[index] != 0x00) {
break;
}
}
pss.slen = pss.key_len - pad->hlen - index - 2;
if(pss.masked_db[index] != 0x1)
{
cipher_debug_log(CIPHER_ERR_RSA_VERIFY_DB_1); /*check masked_db failed*/
return XMEDIA_FAILURE;
}
index++;
crypto_memcpy(pss.salt, sizeof(pss.salt), &pss.masked_db[index], pss.slen);
return rsa_padding_check_pkcs1_pss_hash(pad, mhash, &pss);
}
static xmedia_s32 rsa_padding_check_pkcs1_v15(xmedia_u8 *mhash, xmedia_u32 hash_len, xmedia_u8 *em, xmedia_u32 key_len)
{
xmedia_u8 *data_hash[32];
xmedia_u8 *p;
xmedia_u32 t_len;
if (hash_len != SHA256_DATA_BYTE_LEN) {
cipher_debug_log(CIPHER_ERR_RSA_VERIFY_SHA256_DATA_LEN); /* only support sha256 */
return XMEDIA_FAILURE;
}
/* EM = 0x00 || 0x01 || PS || 0x00 || T */
p = em;
if (*p++ != 0x0) {
cipher_debug_log(CIPHER_ERR_RSA_VERIFY_EM_FIRSTBYTE); /* EM's first byte must be 0 */
return XMEDIA_FAILURE;
}
if (*p++ != 0x1) {
cipher_debug_log(CIPHER_ERR_RSA_VERIFY_EM_SECONDBYTE); /* EM's second byte must be 1 */
return XMEDIA_FAILURE;
}
while (*p != 0) {
if ((p >= em + key_len - 1) || (*p != 0xFF)) {
cipher_debug_log(CIPHER_ERR_RSA_VERIFY_EM_PS); /* PS's every byte is 0xff */
return XMEDIA_FAILURE;
}
p++;
}
p++; // skip 0x0 before T
t_len = key_len- (xmedia_u32)(p - em);
if (t_len != (19 + hash_len)) {
cipher_debug_log(CIPHER_ERR_RSA_VERIFY_EM_T_LEN); /* T length must be 51 (19 + 32), just for sha256 */
return XMEDIA_FAILURE;
}
if (memcmp(p, ASN1_HASH_SHA256, 19)) {
cipher_debug_log(CIPHER_ERR_RSA_VERIFY_ASN1_SHA256); /* just for sha256 */
return XMEDIA_FAILURE;
}
if (memcmp(p + 19, mhash, hash_len)) {
cipher_debug_log(CIPHER_ERR_RSA_VERIFY_SHA256_DATA); /* sha256 data invalid */
return XMEDIA_FAILURE;
}
return XMEDIA_SUCCESS;
}
static xmedia_s32 drv_cipher_calc_rsa(rsa_data_s *rsa_data);
static xmedia_s32 rsa_public(const cipher_rsa_pub_key *pub_key, const xmedia_u8 *input, xmedia_u8 *output)
{
rsa_data_s rsa_data;
rsa_data.rsa_n = pub_key->n;
rsa_data.rsa_k = pub_key->e;
rsa_data.rsa_n_len = pub_key->n_len;
rsa_data.rsa_k_len = pub_key->e_len;
rsa_data.input_data = (xmedia_u8 *)input;
rsa_data.output_data = output;
rsa_data.data_len = pub_key->n_len;
return drv_cipher_calc_rsa(&rsa_data);
}
static xmedia_s32 rsa_verify_pad_init(rsa_padding_s *pad, const cipher_rsa_verify *rsa_verify,
cipher_verify_data *verify_data, xmedia_u8 *arr_em)
{
/*fix here: only support sha256*/
pad->hlen = SHA256_RESULT_SIZE; /* 32 pad hlen */
pad->klen = rsa_verify->pub_key.n_len;
pad->in_data = arr_em;
pad->in_len = verify_data->sign_len;
if(verify_data->sign_len != pad->klen)
{
return XMEDIA_FAILURE;
}
return rsa_public(&rsa_verify->pub_key, verify_data->sign, pad->in_data);
}
static xmedia_s32 drv_rsa_init(xmedia_void)
{
g_rsa_reg_crg = cipher_ioremap_nocache(CIPHER_RSA_CRG_ADDR_PHY, 16); /* 16 */
g_rsa_reg_base = cipher_ioremap_nocache(CIPHER_RSA_REG_BASE_ADDR_PHY, 0x1000);
return XMEDIA_SUCCESS;
}
static xmedia_void drv_rsa_deinit(xmedia_void)
{
if (g_rsa_reg_base != XMEDIA_NULL) {
cipher_iounmap(g_rsa_reg_base);
g_rsa_reg_base = XMEDIA_NULL;
}
if (g_rsa_reg_crg != XMEDIA_NULL) {
cipher_iounmap(g_rsa_reg_crg);
g_rsa_reg_crg = XMEDIA_NULL;
}
}
static xmedia_s32 drv_rsa_wait_done(xmedia_void)
{
return hal_rsa_wait_free();
}
static xmedia_s32 drv_cipher_check_rsa_data(xmedia_u8 *rsa_n, xmedia_u8 *rsa_e, xmedia_u8 *rsa_mc, xmedia_u32 length)
{
xmedia_u32 i;
/* formula: rsa_mc > 0 */
for (i = 0; i < length; i++) {
if (rsa_mc[i] > 0)
break;
}
if (i >= length) {
cipher_debug_log(CIPHER_ERR_RSA_M_ZERO); /*RSA M/C is zero, error*/
return XMEDIA_FAILURE;
}
/* formula: rsa_mc < rsa_n */
for (i = 0; i < length; i++) {
if(rsa_mc[i] < rsa_n[i])
break;
if(rsa_mc[i] == rsa_n[i])
continue;
if (rsa_mc[i] > rsa_n[i])
{
cipher_debug_log(CIPHER_ERR_RSA_M_LARGER_N); /*RSA M/C is larger than rsa_n, error!*/
return XMEDIA_FAILURE;
}
}
if (i >= length) {
cipher_debug_log(CIPHER_ERR_RSA_M_LARGER_N); /*RSA M/C is larger than rsa_n, error!*/
return XMEDIA_FAILURE;
}
/* formula: rsa_e > 1 */
for (i = 0; i < length; i++) {
if (rsa_e[i] > 0)
break;
}
if ((i == length -1) && (rsa_e[i] == 1)) {
cipher_debug_log(CIPHER_ERR_RSA_E_EQUAL_1); /*RSA D/rsa_e is 1, error!*/
return XMEDIA_FAILURE;
}
if (i >= length) {
cipher_debug_log(CIPHER_ERR_RSA_E_EQUAL_0); /*RSA D/rsa_e is zero, error!*/
return XMEDIA_FAILURE;
}
return XMEDIA_SUCCESS;
}
static xmedia_s32 drv_cipher_clear_rsa_ram(xmedia_void)
{
if (hal_rsa_wait_free() != XMEDIA_SUCCESS) {
cipher_debug_log(CIPHER_ERR_RSA_BUSY_TIMEOUT); /*RSA is busy and timeout,error!*/
return XMEDIA_FAILURE;
}
hal_rsa_clear_ram();
hal_rsa_start();
if (drv_rsa_wait_done() != XMEDIA_SUCCESS) {
cipher_debug_log(CIPHER_ERR_RSA_BUSY_TIMEOUT); /*RSA is busy and timeout,error!*/
return XMEDIA_FAILURE;
}
return XMEDIA_SUCCESS;
}
static xmedia_void drv_rsa_rand_mask(rsa_data_s *rsa_data,
xmedia_u32 key_len,
xmedia_u32 *random)
{
return;
}
static void drv_rsa_cipher_klad(rsa_data_s *rsa_data, xmedia_u32 key_len, xmedia_u32 *random)
{
hal_rsa_write_data(RSA_DATA_TYPE_KEY, rsa_data->rsa_k,
rsa_data->rsa_n_len, key_len, random);
return;
}
static xmedia_s32 drv_rsa_key_info(rsa_data_s *rsa_data,
xmedia_u32 *key_len,
rsa_key_width_e *key_width)
{
/* Only support the key width of 1024, 2048 and 4096 */
if (rsa_data->rsa_n_len <= 128) { /* key n size 128 */
*key_len = 128; /* key n size 128 */
*key_width = RSA_KEY_WIDTH_1K;
} else if (rsa_data->rsa_n_len <= 256) { /* key n size 256 */
*key_len = 256; /* key n size 256 */
*key_width = RSA_KEY_WIDTH_2K;
} else if (rsa_data->rsa_n_len <= 384) { /* key n size 384 */
*key_len = 384; /* key n size 384 */
*key_width = RSA_KEY_WIDTH_3K;
} else if (rsa_data->rsa_n_len <= 512) { /* key n size 512 */
*key_len = 512; /* key n size 512 */
*key_width = RSA_KEY_WIDTH_4K;
} else {
cipher_debug_log(CIPHER_ERR_RSA_KEY_LEN);
return XMEDIA_FAILURE;
}
return XMEDIA_SUCCESS;
}
static xmedia_s32 drv_cipher_calc_rsa_ex(rsa_data_s *rsa_data,
xmedia_u32 key_len,
rsa_key_width_e key_width)
{
xmedia_s32 ret = XMEDIA_FAILURE;
xmedia_u32 err_code = 0;
xmedia_u64 random = 0;
ret = drv_cipher_check_rsa_data(rsa_data->rsa_n, rsa_data->rsa_k, rsa_data->input_data, key_len);
if (ret != XMEDIA_SUCCESS) {
return ret;
}
hal_rsa_enable();
ret = hal_rsa_wait_free();
if (ret != XMEDIA_SUCCESS) {
cipher_debug_log(CIPHER_ERR_RSA_BUSY_TIMEOUT); /*RSA is busy!*/
goto exit;
}
/* Config Mode */
hal_rsa_config_mode(key_width);
//V500 not support,reserved!
drv_rsa_rand_mask(rsa_data, key_len, (xmedia_u32 *)&random);
/* Write rsa_n, rsa_e, rsa_m */
hal_rsa_write_data(RSA_DATA_TYPE_MODULE,
rsa_data->rsa_n, rsa_data->rsa_n_len, key_len, (xmedia_u32 *)&random);
/* V500 not support rand mask,random reserved! */
drv_rsa_cipher_klad(rsa_data, key_len, (xmedia_u32 *)&random);
hal_rsa_write_data(RSA_DATA_TYPE_CONTEXT,
rsa_data->input_data, rsa_data->rsa_n_len, key_len, (xmedia_u32 *)&random);
/* Sart */
hal_rsa_start();
ret = drv_rsa_wait_done();
if (ret != XMEDIA_SUCCESS) {
cipher_debug_log(CIPHER_ERR_RSA_BUSY_TIMEOUT); /*RSA is busy and timeout,error!*/
goto exit;
}
/* Get result */
hal_rsa_read_data(rsa_data->output_data, rsa_data->rsa_n_len, key_len);
err_code = hal_rsa_get_error_code();
if (err_code == 0) {
ret = XMEDIA_SUCCESS;
} else {
cipher_debug_log(CIPHER_ERR_RSA_ERRORCODE); /*RSA is err!*/
ret = XMEDIA_FAILURE;
}
exit:
(void)drv_cipher_clear_rsa_ram();
hal_rsa_disable();
return ret;
}
static xmedia_s32 drv_cipher_calc_rsa(rsa_data_s *rsa_data)
{
xmedia_s32 ret;
xmedia_u32 key_len = 0;
rsa_data_s cipher_rsa_data;
rsa_key_width_e key_width = RSA_KEY_WIDTH_BUTT;
ret = drv_rsa_key_info(rsa_data, &key_len, &key_width);
if (ret != XMEDIA_SUCCESS)
return ret;
crypto_memset(&cipher_rsa_data, sizeof(rsa_data_s), 0, sizeof(rsa_data_s));
cipher_rsa_data.rsa_n = rsa_data->rsa_n;
cipher_rsa_data.rsa_k = rsa_data->rsa_k;
cipher_rsa_data.rsa_n_len = key_len;
cipher_rsa_data.rsa_k_len = key_len;
cipher_rsa_data.input_data = rsa_data->input_data;
cipher_rsa_data.data_len = key_len;
cipher_rsa_data.output_data = rsa_data->output_data;
ret = drv_cipher_calc_rsa_ex(&cipher_rsa_data, key_len, key_width);
return ret;
}
xmedia_s32 xmedia_cipher_rsa_deinit(xmedia_void)
{
if (rsa_init_flag == 1) {
drv_rsa_deinit();
rsa_init_flag = 0;
}
return XMEDIA_SUCCESS;
}
xmedia_s32 xmedia_cipher_rsa_verify(const cipher_rsa_verify *rsa_verify, cipher_verify_data *verify_data)
{
xmedia_s32 ret;
rsa_padding_s pad;
xmedia_u8 arr_em[RSA_MAX_KEY_LEN];
if (rsa_init_flag == 0) {
if (drv_rsa_init() != XMEDIA_SUCCESS) {
return XMEDIA_FAILURE;
}
rsa_init_flag = 1;
}
crypto_memset(arr_em, sizeof(arr_em), 0, sizeof(arr_em));
crypto_memset(&pad, sizeof(rsa_padding_s), 0, sizeof(rsa_padding_s));
ret = rsa_verify_pad_init(&pad, rsa_verify, verify_data, arr_em);
if (ret != XMEDIA_SUCCESS) {
cipher_debug_log(CIPHER_ERR_RSA_DEC);
return XMEDIA_FAILURE;
}
if (rsa_verify->scheme == XMEDIA_CIPHER_RSA_SIGN_SCHEME_RSASSA_PKCS1_V15_SHA256) {
ret = rsa_padding_check_pkcs1_v15(verify_data->hash_data, SHA256_DATA_BYTE_LEN, arr_em, rsa_verify->pub_key.n_len);
if (ret != XMEDIA_SUCCESS) {
cipher_debug_log(CIPHER_ERR_RSA_CHECK_PADDING);
return XMEDIA_FAILURE;
}
} else {
pad.em_bit = rsa_get_bit_num(rsa_verify->pub_key.n, pad.klen);
ret = rsa_padding_check_pkcs1_pss(&pad, verify_data->hash_data);
if (ret != XMEDIA_SUCCESS) {
cipher_debug_log(CIPHER_ERR_RSA_CHECK_PADDING);
return XMEDIA_FAILURE;
}
}
return XMEDIA_SUCCESS;
}