755 lines
22 KiB
C
755 lines
22 KiB
C
/*
|
|
* 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;
|
|
}
|