662 lines
19 KiB
C
662 lines
19 KiB
C
|
|
/*
|
||
|
|
* Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include "cipher_adapt.h"
|
||
|
|
#include "drv_rng.h"
|
||
|
|
#include "drv_klad.h"
|
||
|
|
|
||
|
|
#ifdef RSA_ENABLE
|
||
|
|
|
||
|
|
CIPHER_MUTEX g_rsa_mutex_kernel;
|
||
|
|
static gk_void *g_rsa_reg_base = GK_NULL;
|
||
|
|
static gk_void *g_rsa_reg_crg = GK_NULL;
|
||
|
|
static gk_u32 g_rsa_done = GK_FALSE;
|
||
|
|
|
||
|
|
#define cipher_rsa_return_invalid_param(param) \
|
||
|
|
do { \
|
||
|
|
if (param) { \
|
||
|
|
gk_err_cipher("Invalid params!\n"); \
|
||
|
|
return GK_ERR_CIPHER_INVALID_PARA; \
|
||
|
|
} \
|
||
|
|
} while (0)
|
||
|
|
|
||
|
|
#define RSA_INTERRUPT_ENABLE
|
||
|
|
#define RSA_IRQ_NUMBER 136
|
||
|
|
|
||
|
|
#define CIPHER_RSA_REG_BASE_RSA g_rsa_reg_base
|
||
|
|
#define SEC_RSA_BUSY_REG (CIPHER_RSA_REG_BASE_RSA + 0x50)
|
||
|
|
#define SEC_RSA_MOD_REG (CIPHER_RSA_REG_BASE_RSA + 0x54)
|
||
|
|
#define SEC_RSA_WSEC_REG (CIPHER_RSA_REG_BASE_RSA + 0x58)
|
||
|
|
#define SEC_RSA_WDAT_REG (CIPHER_RSA_REG_BASE_RSA + 0x5c)
|
||
|
|
#define SEC_RSA_RPKT_REG (CIPHER_RSA_REG_BASE_RSA + 0x60)
|
||
|
|
#define SEC_RSA_RRSLT_REG (CIPHER_RSA_REG_BASE_RSA + 0x64)
|
||
|
|
#define SEC_RSA_START_REG (CIPHER_RSA_REG_BASE_RSA + 0x68)
|
||
|
|
#define SEC_RSA_ADDR_REG (CIPHER_RSA_REG_BASE_RSA + 0x6C)
|
||
|
|
#define SEC_RSA_ERROR_REG (CIPHER_RSA_REG_BASE_RSA + 0x70)
|
||
|
|
#define SEC_RSA_CRC16_REG (CIPHER_RSA_REG_BASE_RSA + 0x74)
|
||
|
|
#define SEC_RSA_KEY_RANDOM_1 (CIPHER_RSA_REG_BASE_RSA + 0x7c)
|
||
|
|
#define SEC_RSA_INT_EN (CIPHER_RSA_REG_BASE_RSA + 0x80)
|
||
|
|
#define SEC_RSA_INT_STATUS (CIPHER_RSA_REG_BASE_RSA + 0x84)
|
||
|
|
#define SEC_RSA_INT_RAW (CIPHER_RSA_REG_BASE_RSA + 0x88)
|
||
|
|
#define SEC_RSA_INT_ERR_CLR (CIPHER_RSA_REG_BASE_RSA + 0x8c)
|
||
|
|
#define SEC_RSA_KEY_RANDOM_2 (CIPHER_RSA_REG_BASE_RSA + 0x94)
|
||
|
|
#define SEC_RSA_VERSION (CIPHER_RSA_REG_BASE_RSA + 0x90)
|
||
|
|
|
||
|
|
#define RSA_DATA_CLR (7 << 4)
|
||
|
|
#define RSA_DATA_CLR_KEY (1 << 4)
|
||
|
|
#define RSA_DATA_CLR_INPUT (2 << 4)
|
||
|
|
#define RSA_DATA_CLR_OUTPUT (4 << 4)
|
||
|
|
#define RSA_MOD_SEL (3 << 0)
|
||
|
|
#define RSA_MOD_SEL_OPT (0 << 0)
|
||
|
|
#define RSA_MOD_SEL_KEY_UPDATA (1 << 0)
|
||
|
|
#define RSA_MOD_SEL_RAM_CLAER (2 << 0)
|
||
|
|
#define RSA_MOD_SEL_CRC16 (3 << 0)
|
||
|
|
#define RSA_BUSY (1 << 0)
|
||
|
|
#define RSA_START (1 << 0)
|
||
|
|
|
||
|
|
#define RSA_RTY_CNT 50000
|
||
|
|
#define RSA_TIME_OUT 1000
|
||
|
|
|
||
|
|
#define RSA_RETRY_CNT 3
|
||
|
|
|
||
|
|
#define CRC16_POLYNOMIAL 0x1021
|
||
|
|
|
||
|
|
typedef enum {
|
||
|
|
CIPHER_RSA_DATA_TYPE_CONTEXT,
|
||
|
|
CIPHER_RSA_DATA_TYPE_MODULE,
|
||
|
|
CIPHER_RSA_DATA_TYPE_KEY,
|
||
|
|
} cipher_rsa_data_type_e;
|
||
|
|
|
||
|
|
typedef enum {
|
||
|
|
CIPHER_RSA_KEY_WIDTH_1K = 0x00,
|
||
|
|
CIPHER_RSA_KEY_WIDTH_2K = 0x01,
|
||
|
|
CIPHER_RSA_KEY_WIDTH_4K = 0x02,
|
||
|
|
CIPHER_RSA_KEY_WIDTH_3K = 0x03,
|
||
|
|
CIPHER_RSA_KEY_WIDTH_BUTT = 0xff,
|
||
|
|
} cipher_rsa_key_width_e;
|
||
|
|
|
||
|
|
static gk_void hal_rsa_start(gk_void)
|
||
|
|
{
|
||
|
|
hal_cipher_write_reg(SEC_RSA_START_REG, 0x05);
|
||
|
|
}
|
||
|
|
|
||
|
|
static gk_s32 hal_rsa_wait_free(gk_void)
|
||
|
|
{
|
||
|
|
gk_u32 value;
|
||
|
|
gk_u32 try_count = 0;
|
||
|
|
|
||
|
|
do {
|
||
|
|
hal_cipher_read_reg(SEC_RSA_BUSY_REG, &value);
|
||
|
|
if ((value & RSA_BUSY) == 0)
|
||
|
|
return GK_SUCCESS;
|
||
|
|
try_count++;
|
||
|
|
cipher_msleep(1);
|
||
|
|
} while (try_count < RSA_RTY_CNT);
|
||
|
|
|
||
|
|
return GK_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
static gk_void hal_rsa_clear_ram(gk_void)
|
||
|
|
{
|
||
|
|
gk_u32 value;
|
||
|
|
|
||
|
|
hal_cipher_read_reg(SEC_RSA_MOD_REG, &value);
|
||
|
|
value &= 0x0c;
|
||
|
|
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 gk_void hal_rsa_config_mode(cipher_rsa_key_width_e ken_width)
|
||
|
|
{
|
||
|
|
gk_u32 value;
|
||
|
|
|
||
|
|
value = ((gk_u32)ken_width << 2) | RSA_MOD_SEL_OPT; /* 2 left shift */
|
||
|
|
hal_cipher_write_reg(SEC_RSA_MOD_REG, value);
|
||
|
|
}
|
||
|
|
|
||
|
|
static gk_void hal_rsa_write_data(cipher_rsa_data_type_e data_type,
|
||
|
|
gk_u8 *data,
|
||
|
|
gk_u32 data_len,
|
||
|
|
gk_u32 length,
|
||
|
|
gk_u32 random[2]) /* 2 random size */
|
||
|
|
{
|
||
|
|
gk_u32 *reg = GK_NULL;
|
||
|
|
gk_u8 *pos = GK_NULL;
|
||
|
|
gk_u32 i, value;
|
||
|
|
gk_bool id = 0;
|
||
|
|
|
||
|
|
if (data_type == CIPHER_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 = (gk_u32)pos[0];
|
||
|
|
value |= ((gk_u32)pos[1]) << 8; /* 1 index, 8 left shift */
|
||
|
|
value |= ((gk_u32)pos[2]) << 16; /* 2 index, 16 left shift */
|
||
|
|
value |= ((gk_u32)pos[3]) << 24; /* 3 index, 24 left shift */
|
||
|
|
if (data_type != CIPHER_RSA_DATA_TYPE_CONTEXT)
|
||
|
|
value ^= random[id];
|
||
|
|
|
||
|
|
hal_cipher_write_reg(reg, value);
|
||
|
|
pos += 4; /* 4 groups */
|
||
|
|
id = (gk_u32)id ^ 0x01;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
static gk_void hal_rsa_read_data(gk_u8 *data, gk_u32 data_len, gk_u32 klen)
|
||
|
|
{
|
||
|
|
gk_u32 value;
|
||
|
|
gk_u8 *pos = GK_NULL;
|
||
|
|
gk_u32 i;
|
||
|
|
|
||
|
|
pos = data;
|
||
|
|
for (i = 0; i < klen; i += 4) { /* 4 groups */
|
||
|
|
hal_cipher_read_reg(SEC_RSA_RRSLT_REG, &value);
|
||
|
|
pos[0] = (gk_u8)(value & 0xFF);
|
||
|
|
pos[1] = (gk_u8)((value >> 8) & 0xFF); /* 1 index, 8 right shift */
|
||
|
|
pos[2] = (gk_u8)((value >> 16) & 0xFF); /* 2 index, 16 right shift */
|
||
|
|
pos[3] = (gk_u8)((value >> 24) & 0xFF); /* 3 index, 24 right shift */
|
||
|
|
pos += 4; /* 4 groups */
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
static gk_u32 hal_rsa_get_error_code(gk_void)
|
||
|
|
{
|
||
|
|
gk_u32 value;
|
||
|
|
|
||
|
|
hal_cipher_read_reg(SEC_RSA_ERROR_REG, &value);
|
||
|
|
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
|
||
|
|
static gk_void hal_rsa_disable_int(gk_void)
|
||
|
|
{
|
||
|
|
(gk_void)hal_cipher_write_reg(SEC_RSA_INT_EN, 0x00);
|
||
|
|
}
|
||
|
|
|
||
|
|
static gk_void hal_rsa_enable(gk_void)
|
||
|
|
{
|
||
|
|
gk_u32 value;
|
||
|
|
|
||
|
|
hal_cipher_read_reg(g_rsa_reg_crg, &value);
|
||
|
|
hal_set_bit(value, 15); /* 15bit clock opened */
|
||
|
|
hal_cipher_write_reg(g_rsa_reg_crg, value);
|
||
|
|
cipher_msleep(1);
|
||
|
|
|
||
|
|
hal_clear_bit(value, 14); /* 14bit cancel reset */
|
||
|
|
hal_cipher_write_reg(g_rsa_reg_crg, value);
|
||
|
|
cipher_msleep(1);
|
||
|
|
|
||
|
|
#ifdef INT_ENABLE
|
||
|
|
hal_rsa_enable_int();
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
static gk_void hal_rsa_disable(gk_void)
|
||
|
|
{
|
||
|
|
gk_u32 value;
|
||
|
|
|
||
|
|
hal_cipher_read_reg(g_rsa_reg_crg, &value);
|
||
|
|
|
||
|
|
hal_set_bit(value, 14); /* 14bit reset */
|
||
|
|
hal_cipher_write_reg(g_rsa_reg_crg, value);
|
||
|
|
cipher_msleep(1);
|
||
|
|
|
||
|
|
hal_clear_bit(value, 15); /* 15bit clock closed */
|
||
|
|
hal_cipher_write_reg(g_rsa_reg_crg, value);
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef RSA_RAND_MASK
|
||
|
|
|
||
|
|
static gk_u16 g_crc_table[256]; /* 256 table size */
|
||
|
|
|
||
|
|
static gk_void drv_rsa_crc16_init(gk_void)
|
||
|
|
{
|
||
|
|
gk_u16 remainder;
|
||
|
|
gk_u16 n, m;
|
||
|
|
gk_u16 *table = g_crc_table;
|
||
|
|
|
||
|
|
for (n = 0; n < 256; n++) { /* 256 */
|
||
|
|
remainder = (gk_u16)n << 8; /* 8 left shift */
|
||
|
|
for (m = 8; m > 0; m--) { /* 8 */
|
||
|
|
if (remainder & 0x8000)
|
||
|
|
remainder = (remainder << 1) ^ CRC16_POLYNOMIAL;
|
||
|
|
else
|
||
|
|
remainder = (remainder << 1);
|
||
|
|
}
|
||
|
|
*(table + n) = remainder;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
static gk_u16 drv_rsa_crc16_block(gk_u16 crc, gk_u8 block[8], gk_u8 random[8]) /* 8 */
|
||
|
|
{
|
||
|
|
gk_u8 i, j;
|
||
|
|
gk_u8 val;
|
||
|
|
|
||
|
|
for (i = 0; i < 2; i++) { /* 2 */
|
||
|
|
for (j = 0; j < 4; j++) { /* 4 */
|
||
|
|
val = block[i * 4 + 3 - j] ^ random[i * 4 + 3 - j]; /* 4, 3 */
|
||
|
|
crc = (crc << 8) ^ g_crc_table[((crc >> 8) ^ val) & 0xFF]; /* 8 right shift */
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return crc;
|
||
|
|
}
|
||
|
|
|
||
|
|
static gk_u16 drv_rsa_key_crc(gk_u8 *rsa_n, gk_u8 *rsa_k, gk_u32 klen, gk_u32 random[2]) /* 2 */
|
||
|
|
{
|
||
|
|
gk_u32 i;
|
||
|
|
gk_u16 crc = 0;
|
||
|
|
|
||
|
|
for (i = 0; i < klen; i += 8) /* 8 */
|
||
|
|
crc = drv_rsa_crc16_block(crc, rsa_n + i, (gk_u8*)random);
|
||
|
|
|
||
|
|
for (i = 0; i < klen; i += 8) /* 8 */
|
||
|
|
crc = drv_rsa_crc16_block(crc, rsa_k + i, (gk_u8*)random);
|
||
|
|
|
||
|
|
return crc;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
CIPHER_QUEUE_HEAD g_rsa_wait_queue;
|
||
|
|
#ifdef INT_ENABLE
|
||
|
|
static CIPHER_IRQRETURN_T drv_rsa_isr(gk_s32 irq, gk_void *dev_id)
|
||
|
|
{
|
||
|
|
gk_u32 int_stat;
|
||
|
|
|
||
|
|
int_stat = hal_rsa_get_int();
|
||
|
|
|
||
|
|
gk_info_cipher("RSA INT: 0x%x\n", int_stat);
|
||
|
|
|
||
|
|
if (int_stat & 0x01) {
|
||
|
|
g_rsa_done = GK_TRUE;
|
||
|
|
gk_info_cipher("RSA Done\n");
|
||
|
|
cipher_queue_wait_up(&g_rsa_wait_queue);
|
||
|
|
}
|
||
|
|
|
||
|
|
hal_rsa_clr_int();
|
||
|
|
|
||
|
|
return CIPHER_IRQ_HANDLED;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
gk_s32 drv_rsa_init(gk_void)
|
||
|
|
{
|
||
|
|
gk_u32 rsa_stat = 0;
|
||
|
|
gk_u32 rng_stat = 0;
|
||
|
|
#ifdef INT_ENABLE
|
||
|
|
gk_s32 ret;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
cipher_mutex_init(&g_rsa_mutex_kernel);
|
||
|
|
cipher_queue_init(&g_rsa_wait_queue);
|
||
|
|
|
||
|
|
g_rsa_reg_crg = cipher_ioremap_nocache(CIPHER_RSA_CRG_ADDR_PHY, 16); /* 16 */
|
||
|
|
if (g_rsa_reg_crg == 0) {
|
||
|
|
gk_err_cipher("ioremap_nocache phy addr err:%x.\n", CIPHER_RSA_CRG_ADDR_PHY);
|
||
|
|
return GK_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* rng reset and clock */
|
||
|
|
hal_cipher_read_reg(CIPHER_RNG_CRG_ADDR_PHY, &rng_stat);
|
||
|
|
rng_stat |= RNG_CRG_CLOCK_BIT;
|
||
|
|
rng_stat &= ~RNG_CRG_RESET_BIT;
|
||
|
|
hal_cipher_write_reg(CIPHER_RNG_CRG_ADDR_PHY, rng_stat);
|
||
|
|
cipher_msleep(5); /* sleep 5ms */
|
||
|
|
|
||
|
|
/* rsa reset and clock */
|
||
|
|
hal_cipher_read_reg(CIPHER_RSA_CRG_ADDR_PHY, &rsa_stat);
|
||
|
|
rsa_stat |= RSA_CRG_CLOCK_BIT;
|
||
|
|
rsa_stat |= RSA_CRG_RESET_BIT;
|
||
|
|
hal_cipher_write_reg(CIPHER_RSA_CRG_ADDR_PHY, rsa_stat);
|
||
|
|
cipher_msleep(5); /* sleep 5ms */
|
||
|
|
|
||
|
|
/* rsa cancel reset */
|
||
|
|
rsa_stat &= ~RSA_CRG_RESET_BIT;
|
||
|
|
hal_cipher_write_reg(CIPHER_RSA_CRG_ADDR_PHY, rsa_stat);
|
||
|
|
|
||
|
|
cipher_iounmap(g_rsa_reg_crg);
|
||
|
|
g_rsa_reg_crg = GK_NULL;
|
||
|
|
|
||
|
|
g_rsa_reg_base = cipher_ioremap_nocache(CIPHER_RSA_REG_BASE_ADDR_PHY, 0x1000);
|
||
|
|
if (g_rsa_reg_base == GK_NULL) {
|
||
|
|
gk_err_cipher("ioremap_nocache rsa Reg failed\n");
|
||
|
|
return GK_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef INT_ENABLE
|
||
|
|
/* request irq */
|
||
|
|
ret = cipher_request_irq(RSA_IRQ_NUMBER, drv_rsa_isr, "rsa");
|
||
|
|
if (ret != GK_SUCCESS) {
|
||
|
|
hal_rsa_disable_int();
|
||
|
|
gk_err_cipher("Irq request failure, ret=%#x.\n", ret);
|
||
|
|
return GK_FAILURE;
|
||
|
|
}
|
||
|
|
hal_rsa_enable_int();
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef RSA_RAND_MASK
|
||
|
|
drv_rsa_crc16_init();
|
||
|
|
#endif
|
||
|
|
|
||
|
|
return GK_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
gk_void drv_rsa_deinit(gk_void)
|
||
|
|
{
|
||
|
|
hal_rsa_disable_int();
|
||
|
|
|
||
|
|
#ifdef INT_ENABLE
|
||
|
|
cipher_free_irq(RSA_IRQ_NUMBER, "rsa");
|
||
|
|
#endif
|
||
|
|
|
||
|
|
if (g_rsa_reg_base != GK_NULL) {
|
||
|
|
cipher_iounmap(g_rsa_reg_base);
|
||
|
|
g_rsa_reg_base = GK_NULL;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
static gk_s32 drv_rsa_wait_done(gk_void)
|
||
|
|
{
|
||
|
|
#ifdef INT_ENABLE
|
||
|
|
if (cipher_queue_wait_timeout(&g_rsa_wait_queue, &g_rsa_done, RSA_TIME_OUT) == 0) {
|
||
|
|
gk_err_cipher("RSA time out! \n");
|
||
|
|
return GK_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
return GK_SUCCESS;
|
||
|
|
#else
|
||
|
|
return hal_rsa_wait_free();
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
static gk_s32 drv_cipher_check_rsa_data(gk_u8 *rsa_n, gk_u8 *rsa_e, gk_u8 *rsa_mc, gk_u32 length)
|
||
|
|
{
|
||
|
|
gk_u32 i;
|
||
|
|
|
||
|
|
/* formula: rsa_mc > 0 */
|
||
|
|
for (i = 0; i < length; i++) {
|
||
|
|
if (rsa_mc[i] > 0)
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if (i >= length) {
|
||
|
|
gk_err_cipher("RSA M/C is zero, error!\n");
|
||
|
|
return GK_ERR_CIPHER_INVALID_PARA;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* formula: rsa_mc < rsa_n */
|
||
|
|
for (i = 0; i < length; i++) {
|
||
|
|
if (rsa_mc[i] < rsa_n[i])
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if (i >= length) {
|
||
|
|
gk_err_cipher("RSA M/C is larger than rsa_n, error!\n");
|
||
|
|
return GK_ERR_CIPHER_INVALID_PARA;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* formula: rsa_e >= 1 */
|
||
|
|
for (i = 0; i < length; i++) {
|
||
|
|
if (rsa_e[i] > 0)
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if (i >= length) {
|
||
|
|
gk_err_cipher("RSA D/rsa_e is zero, error!\n");
|
||
|
|
return GK_ERR_CIPHER_INVALID_PARA;
|
||
|
|
}
|
||
|
|
|
||
|
|
return GK_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
static gk_s32 drv_cipher_clear_rsa_ram(gk_void)
|
||
|
|
{
|
||
|
|
if (hal_rsa_wait_free() != GK_SUCCESS) {
|
||
|
|
gk_err_cipher("RSA is busy and timeout,error!\n");
|
||
|
|
return GK_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
g_rsa_done = GK_FALSE;
|
||
|
|
|
||
|
|
hal_rsa_clear_ram();
|
||
|
|
hal_rsa_start();
|
||
|
|
|
||
|
|
if (drv_rsa_wait_done() != GK_SUCCESS) {
|
||
|
|
gk_err_cipher("RSA is busy and timeout,error!\n");
|
||
|
|
return GK_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
return GK_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
static gk_u8 g_rsa_n[CIPHER_MAX_RSA_KEY_LEN];
|
||
|
|
static gk_u8 g_rsa_k[CIPHER_MAX_RSA_KEY_LEN];
|
||
|
|
static gk_u8 g_rsa_m[CIPHER_MAX_RSA_KEY_LEN];
|
||
|
|
|
||
|
|
static gk_void drv_rsa_rand_mask(cipher_rsa_data_s *rsa_data,
|
||
|
|
gk_u32 key_len,
|
||
|
|
gk_u32 *random)
|
||
|
|
{
|
||
|
|
#ifdef RSA_RAND_MASK
|
||
|
|
gk_u16 crc;
|
||
|
|
|
||
|
|
random[0] = drv_cipher_rand();
|
||
|
|
random[1] = drv_cipher_rand();
|
||
|
|
crc = drv_rsa_key_crc(rsa_data->rsa_n, rsa_data->rsa_k, key_len, random);
|
||
|
|
gk_info_cipher("CRC16: 0x%x\n", crc);
|
||
|
|
hal_rsa_set_random(random);
|
||
|
|
hal_rsa_set_crc(crc);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
static gk_s32 drv_rsa_cipher_klad(cipher_rsa_data_s *rsa_data,
|
||
|
|
gk_u32 key_len,
|
||
|
|
gk_u32 *random)
|
||
|
|
{
|
||
|
|
gk_s32 ret = GK_SUCCESS;
|
||
|
|
#ifdef CIPHER_KLAD_SUPPORT
|
||
|
|
if (rsa_data->ca_type != GK_CIPHER_KEY_SRC_USER) {
|
||
|
|
drv_cipher_klad_load_key(0, rsa_data->ca_type,
|
||
|
|
GK_CIPHER_KLAD_TARGET_RSA, rsa_data->rsa_k, rsa_data->rsa_k_len);
|
||
|
|
if (ret != GK_SUCCESS) {
|
||
|
|
gk_err_cipher("drv_cipher_klad_load_key, error!\n");
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
hal_rsa_write_data(CIPHER_RSA_DATA_TYPE_KEY, rsa_data->rsa_k,
|
||
|
|
rsa_data->rsa_n_len, key_len, random);
|
||
|
|
}
|
||
|
|
#else
|
||
|
|
hal_rsa_write_data(CIPHER_RSA_DATA_TYPE_KEY, rsa_data->rsa_k,
|
||
|
|
rsa_data->rsa_n_len, key_len, random);
|
||
|
|
#endif
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
static gk_s32 drv_rsa_key_info(cipher_rsa_data_s *rsa_data,
|
||
|
|
gk_u32 *key_len,
|
||
|
|
cipher_rsa_key_width_e *key_width)
|
||
|
|
{
|
||
|
|
gk_u8 *p = GK_NULL;
|
||
|
|
|
||
|
|
/* 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 = CIPHER_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 = CIPHER_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 = CIPHER_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 = CIPHER_RSA_KEY_WIDTH_4K;
|
||
|
|
} else {
|
||
|
|
gk_err_cipher("rsa_n_len(0x%x) is invalid\n", rsa_data->rsa_n_len);
|
||
|
|
return GK_ERR_CIPHER_INVALID_POINT;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* if dataLen < key_len, padding 0 before data */
|
||
|
|
p = g_rsa_n + (*key_len - rsa_data->rsa_n_len);
|
||
|
|
if (cipher_copy_from_user(p, rsa_data->rsa_n, rsa_data->rsa_n_len)) {
|
||
|
|
gk_err_cipher("copy data from user fail!\n");
|
||
|
|
return GK_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
p = g_rsa_k + (*key_len - rsa_data->rsa_k_len);
|
||
|
|
if (cipher_copy_from_user(p, rsa_data->rsa_k, rsa_data->rsa_k_len)) {
|
||
|
|
gk_err_cipher("copy data from user fail!\n");
|
||
|
|
return GK_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
p = g_rsa_m + (*key_len - rsa_data->data_len);
|
||
|
|
if (cipher_copy_from_user(p, rsa_data->input_data, rsa_data->data_len)) {
|
||
|
|
gk_err_cipher("copy data from user fail!\n");
|
||
|
|
return GK_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
return GK_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
static gk_s32 drv_cipher_calc_rsa_ex(cipher_rsa_data_s *rsa_data,
|
||
|
|
gk_u32 key_len,
|
||
|
|
cipher_rsa_key_width_e key_width)
|
||
|
|
{
|
||
|
|
gk_u8 err_cnt;
|
||
|
|
gk_s32 ret;
|
||
|
|
gk_u32 err_code;
|
||
|
|
gk_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 != GK_SUCCESS) {
|
||
|
|
gk_err_cipher("RSA data invalid!\n");
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
g_rsa_done = GK_FALSE;
|
||
|
|
|
||
|
|
for (err_cnt = 0; err_cnt < RSA_RETRY_CNT; err_cnt++) {
|
||
|
|
hal_rsa_enable();
|
||
|
|
|
||
|
|
ret = hal_rsa_wait_free();
|
||
|
|
if (ret != GK_SUCCESS) {
|
||
|
|
gk_err_cipher("RSA is busy!\n");
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Config Mode */
|
||
|
|
hal_rsa_config_mode(key_width);
|
||
|
|
|
||
|
|
drv_rsa_rand_mask(rsa_data, key_len, (gk_u32 *)&random);
|
||
|
|
|
||
|
|
/* Write rsa_n, rsa_e, rsa_m */
|
||
|
|
hal_rsa_write_data(CIPHER_RSA_DATA_TYPE_MODULE,
|
||
|
|
rsa_data->rsa_n, rsa_data->rsa_n_len, key_len, (gk_u32 *)&random);
|
||
|
|
|
||
|
|
ret = drv_rsa_cipher_klad(rsa_data, key_len, (gk_u32 *)&random);
|
||
|
|
if (ret != GK_SUCCESS)
|
||
|
|
return ret;
|
||
|
|
|
||
|
|
hal_rsa_write_data(CIPHER_RSA_DATA_TYPE_CONTEXT,
|
||
|
|
rsa_data->input_data, rsa_data->rsa_n_len, key_len, (gk_u32 *)&random);
|
||
|
|
|
||
|
|
/* Sart */
|
||
|
|
hal_rsa_start();
|
||
|
|
|
||
|
|
ret = drv_rsa_wait_done();
|
||
|
|
if (ret != GK_SUCCESS) {
|
||
|
|
gk_err_cipher("RSA is busy and timeout,error!\n");
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Get result */
|
||
|
|
hal_rsa_read_data(rsa_data->output_data, rsa_data->rsa_n_len, key_len);
|
||
|
|
|
||
|
|
if (drv_cipher_clear_rsa_ram() != GK_SUCCESS)
|
||
|
|
return GK_FAILURE;
|
||
|
|
|
||
|
|
err_code = hal_rsa_get_error_code();
|
||
|
|
|
||
|
|
hal_rsa_disable();
|
||
|
|
|
||
|
|
if (err_code == 0)
|
||
|
|
return GK_SUCCESS;
|
||
|
|
else
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
gk_err_cipher("RSA is err: chipset error code: 0x%x!\n", err_code);
|
||
|
|
return GK_FAILURE;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
static gk_s32 drv_cipher_calc_rsa(cipher_rsa_data_s *rsa_data)
|
||
|
|
{
|
||
|
|
gk_s32 ret;
|
||
|
|
gk_u32 key_len = 0;
|
||
|
|
cipher_rsa_data_s cipher_rsa_data;
|
||
|
|
cipher_rsa_key_width_e key_width = CIPHER_RSA_KEY_WIDTH_BUTT;
|
||
|
|
|
||
|
|
cipher_rsa_return_invalid_param(rsa_data == GK_NULL);
|
||
|
|
cipher_rsa_return_invalid_param(rsa_data->input_data == GK_NULL);
|
||
|
|
cipher_rsa_return_invalid_param(rsa_data->output_data == GK_NULL);
|
||
|
|
cipher_rsa_return_invalid_param(rsa_data->rsa_n == GK_NULL);
|
||
|
|
cipher_rsa_return_invalid_param(rsa_data->rsa_k == GK_NULL);
|
||
|
|
cipher_rsa_return_invalid_param(rsa_data->data_len != rsa_data->rsa_n_len);
|
||
|
|
cipher_rsa_return_invalid_param(rsa_data->rsa_k_len > rsa_data->rsa_n_len);
|
||
|
|
|
||
|
|
crypto_memset(g_rsa_n, sizeof(g_rsa_n), 0, sizeof(g_rsa_n));
|
||
|
|
crypto_memset(g_rsa_k, sizeof(g_rsa_k), 0, sizeof(g_rsa_k));
|
||
|
|
crypto_memset(g_rsa_m, sizeof(g_rsa_m), 0, sizeof(g_rsa_m));
|
||
|
|
|
||
|
|
ret = drv_rsa_key_info(rsa_data, &key_len, &key_width);
|
||
|
|
if (ret != GK_SUCCESS)
|
||
|
|
return ret;
|
||
|
|
|
||
|
|
crypto_memset(&cipher_rsa_data, sizeof(cipher_rsa_data), 0, sizeof(cipher_rsa_data_s));
|
||
|
|
cipher_rsa_data.rsa_n = g_rsa_n;
|
||
|
|
cipher_rsa_data.rsa_k = g_rsa_k;
|
||
|
|
cipher_rsa_data.rsa_n_len = key_len;
|
||
|
|
cipher_rsa_data.rsa_k_len = key_len;
|
||
|
|
cipher_rsa_data.input_data = g_rsa_m;
|
||
|
|
cipher_rsa_data.data_len = key_len;
|
||
|
|
cipher_rsa_data.output_data = g_rsa_m;
|
||
|
|
cipher_rsa_data.ca_type = rsa_data->ca_type;
|
||
|
|
|
||
|
|
ret = drv_cipher_calc_rsa_ex(&cipher_rsa_data, key_len, key_width);
|
||
|
|
if (ret != GK_SUCCESS)
|
||
|
|
return GK_FAILURE;
|
||
|
|
|
||
|
|
if (cipher_copy_to_user(rsa_data->output_data,
|
||
|
|
g_rsa_m + (key_len - rsa_data->rsa_n_len), rsa_data->rsa_n_len)) {
|
||
|
|
gk_err_cipher("copy data to user fail!\n");
|
||
|
|
return GK_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|
||
|
|
gk_s32 gk_drv_cipher_calc_rsa(cipher_rsa_data_s *rsa_data)
|
||
|
|
{
|
||
|
|
gk_s32 ret;
|
||
|
|
|
||
|
|
if (rsa_data == GK_NULL) {
|
||
|
|
gk_err_cipher("Invalid params!\n");
|
||
|
|
return GK_ERR_CIPHER_INVALID_PARA;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (cipher_mutex_lock(&g_rsa_mutex_kernel)) {
|
||
|
|
gk_err_cipher("down_interruptible failed!\n");
|
||
|
|
return GK_FAILURE;
|
||
|
|
}
|
||
|
|
|
||
|
|
ret = drv_cipher_calc_rsa(rsa_data);
|
||
|
|
|
||
|
|
cipher_mutex_unlock(&g_rsa_mutex_kernel);
|
||
|
|
|
||
|
|
return ret;
|
||
|
|
}
|
||
|
|
|