mirror of
https://xff.cz/git/u-boot/
synced 2025-09-01 16:52:14 +02:00
449 lines
10 KiB
C
Executable File
449 lines
10 KiB
C
Executable File
/*
|
|
* (C) Copyright 2013-2016
|
|
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
|
|
#include "common.h"
|
|
#include "asm/io.h"
|
|
#include "asm/arch/ccmu.h"
|
|
#include "asm/arch/ss.h"
|
|
#include "asm/arch/mmu.h"
|
|
#include "ss_op.h"
|
|
|
|
#define ALG_SHA256 (0x13)
|
|
#define ALG_RSA (0x20)
|
|
#define ALG_MD5 (0x10)
|
|
#define ALG_TRANG (0x1C)
|
|
|
|
static u32 __aw_endian4(u32 data)
|
|
{
|
|
u32 d1, d2, d3, d4;
|
|
d1= (data&0xff)<<24;
|
|
d2= (data&0xff00)<<8;
|
|
d3= (data&0xff0000)>>8;
|
|
d4= (data&0xff000000)>>24;
|
|
|
|
return (d1|d2|d3|d4);
|
|
}
|
|
|
|
static u32 __sha_padding(u32 data_size, u8* text, u32 hash_mode)
|
|
{
|
|
u32 i;
|
|
u32 k, q;
|
|
u32 size;
|
|
u32 padding_buf[16];
|
|
u8 *ptext;
|
|
|
|
k = data_size/64;
|
|
q = data_size%64;
|
|
|
|
ptext = (u8*)padding_buf;
|
|
memset(padding_buf, 0, 16 * sizeof(u32));
|
|
if(q==0){
|
|
padding_buf[0] = 0x00000080;
|
|
|
|
if(hash_mode)
|
|
{
|
|
padding_buf[14] = data_size>>29;
|
|
padding_buf[15] = data_size<<3;
|
|
padding_buf[14] = __aw_endian4(padding_buf[14]);
|
|
padding_buf[15] = __aw_endian4(padding_buf[15]);
|
|
}
|
|
else
|
|
{
|
|
padding_buf[14] = data_size<<3;
|
|
padding_buf[15] = data_size>>29;
|
|
}
|
|
|
|
for(i=0; i<64; i++){
|
|
text[k*64 + i] = ptext[i];
|
|
}
|
|
size = (k + 1)*64;
|
|
}else if(q<56)
|
|
{
|
|
for(i=0; i<q; i++){
|
|
ptext[i] = text[k*64 + i];
|
|
}
|
|
ptext[q] = 0x80;
|
|
|
|
if(hash_mode)
|
|
{
|
|
padding_buf[14] = data_size>>29;
|
|
padding_buf[15] = data_size<<3;
|
|
padding_buf[14] = __aw_endian4(padding_buf[14]);
|
|
padding_buf[15] = __aw_endian4(padding_buf[15]);
|
|
}
|
|
else
|
|
{
|
|
padding_buf[14] = data_size<<3;
|
|
padding_buf[15] = data_size>>29;
|
|
}
|
|
|
|
for(i=0; i<64; i++){
|
|
text[k*64 + i] = ptext[i];
|
|
}
|
|
size = (k + 1)*64;
|
|
}else{
|
|
for(i=0; i<q; i++){
|
|
ptext[i] = text[k*64 + i];
|
|
}
|
|
ptext[q] = 0x80;
|
|
for(i=0; i<64; i++){
|
|
text[k*64 + i] = ptext[i];
|
|
}
|
|
|
|
//send last 512-bits text to SHA1/MD5
|
|
for(i=0; i<16; i++){
|
|
padding_buf[i] = 0x0;
|
|
}
|
|
|
|
if(hash_mode)
|
|
{
|
|
padding_buf[14] = data_size>>29;
|
|
padding_buf[15] = data_size<<3;
|
|
padding_buf[14] = __aw_endian4(padding_buf[14]);
|
|
padding_buf[15] = __aw_endian4(padding_buf[15]);
|
|
}
|
|
else
|
|
{
|
|
padding_buf[14] = data_size<<3;
|
|
padding_buf[15] = data_size>>29;
|
|
}
|
|
|
|
for(i=0; i<64; i++){
|
|
text[(k + 1)*64 + i] = ptext[i];
|
|
}
|
|
size = (k + 2)*64;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
|
|
|
|
static void __rsa_padding(u8 *dst_buf, u8 *src_buf, u32 data_len, u32 group_len)
|
|
{
|
|
int i = 0;
|
|
|
|
memset(dst_buf, 0, group_len);
|
|
for(i = group_len - data_len; i < group_len; i++)
|
|
{
|
|
dst_buf[i] = src_buf[group_len - 1 - i];
|
|
}
|
|
}
|
|
|
|
void sunxi_ss_open(void)
|
|
{
|
|
ss_open();
|
|
}
|
|
|
|
void sunxi_ss_close(void)
|
|
{
|
|
ss_close();
|
|
}
|
|
|
|
int sunxi_md5_calc(u8 *dst_addr, u32 dst_len, u8 *src_addr, u32 src_len)
|
|
{
|
|
u32 word_len = 0, src_align_len = 0;
|
|
u32 total_bit_len = 0;
|
|
task_queue task0 __aligned(CACHE_LINE_SIZE) = {0};
|
|
/* sha256 2word, sha512 4word*/
|
|
ALLOC_CACHE_ALIGN_BUFFER(u32, total_package_len, 4);
|
|
ALLOC_CACHE_ALIGN_BUFFER(u8, p_sign, CACHE_LINE_SIZE);
|
|
ss_open();
|
|
memset(p_sign, 0, sizeof(p_sign));
|
|
|
|
if (ss_get_ver() < 2) {
|
|
/* CE1.0 */
|
|
src_align_len = __sha_padding(src_len, (u8 *)src_addr, 1);
|
|
word_len = src_align_len>>2;
|
|
|
|
task0.task_id = 0;
|
|
task0.common_ctl = (ALG_MD5)|(1U << 31);
|
|
task0.data_len = word_len;
|
|
|
|
} else {
|
|
/* CE2.0 */
|
|
src_align_len = ALIGN(src_len, 4);
|
|
word_len = src_align_len>>2;
|
|
|
|
total_bit_len = src_len<<3;
|
|
total_package_len[0] = total_bit_len;
|
|
total_package_len[1] = 0;
|
|
|
|
task0.task_id = 0;
|
|
task0.common_ctl = (ALG_MD5)|(1<<15)|(1U << 31);
|
|
task0.key_descriptor = (u32)total_package_len;
|
|
task0.data_len = total_bit_len;
|
|
}
|
|
|
|
task0.source[0].addr = (uint)src_addr;
|
|
task0.source[0].length = word_len;
|
|
task0.destination[0].addr = (uint)p_sign;
|
|
task0.destination[0].length = dst_len>>2;
|
|
task0.next_descriptor = 0;
|
|
|
|
flush_cache((u32)&task0, sizeof(task0));
|
|
flush_cache((u32)p_sign, CACHE_LINE_SIZE);
|
|
flush_cache((u32)src_addr, src_align_len);
|
|
flush_cache((u32)total_package_len, sizeof(total_package_len));
|
|
|
|
ss_set_drq((u32)&task0);
|
|
ss_irq_enable(task0.task_id);
|
|
ss_ctrl_start(ALG_MD5);
|
|
ss_wait_finish(task0.task_id);
|
|
ss_pending_clear(task0.task_id);
|
|
ss_ctrl_stop();
|
|
ss_irq_disable(task0.task_id);
|
|
if (ss_check_err()) {
|
|
printf("SS %s fail 0x%x\n", __func__, ss_check_err());
|
|
}
|
|
|
|
invalidate_dcache_range((ulong)p_sign, (ulong)p_sign + CACHE_LINE_SIZE);
|
|
/*copy data*/
|
|
memcpy(dst_addr, p_sign, dst_len);
|
|
return 0;
|
|
}
|
|
|
|
|
|
int sunxi_sha_calc(u8 *dst_addr, u32 dst_len,
|
|
u8 *src_addr, u32 src_len)
|
|
{
|
|
u32 word_len = 0,src_align_len = 0;
|
|
u32 total_bit_len = 0;
|
|
task_queue task0 __aligned(CACHE_LINE_SIZE) = {0};
|
|
/* sha256 2word, sha512 4word*/
|
|
ALLOC_CACHE_ALIGN_BUFFER(u32, total_package_len, 4);
|
|
ALLOC_CACHE_ALIGN_BUFFER(u8, p_sign, CACHE_LINE_SIZE);
|
|
|
|
memset(p_sign, 0, sizeof(p_sign));
|
|
|
|
if(ss_get_ver() < 2)
|
|
{
|
|
/* CE1.0 */
|
|
src_align_len = __sha_padding(src_len, (u8 *)src_addr, 1);
|
|
word_len = src_align_len>>2;
|
|
|
|
task0.task_id = 0;
|
|
task0.common_ctl = (ALG_SHA256)|(1U << 31);
|
|
task0.data_len = word_len;
|
|
|
|
}
|
|
else
|
|
{
|
|
/* CE2.0 */
|
|
src_align_len = ALIGN(src_len,4);
|
|
word_len = src_align_len>>2;
|
|
|
|
total_bit_len = src_len<<3;
|
|
total_package_len[0] = total_bit_len;
|
|
total_package_len[1] = 0;
|
|
|
|
task0.task_id = 0;
|
|
task0.common_ctl = (ALG_SHA256)|(1<<15)|(1U << 31);
|
|
task0.key_descriptor = (u32)total_package_len;
|
|
task0.data_len = total_bit_len;
|
|
}
|
|
|
|
task0.source[0].addr = (uint)src_addr;
|
|
task0.source[0].length = word_len;
|
|
task0.destination[0].addr = (uint)p_sign;
|
|
task0.destination[0].length = 32>>2;
|
|
task0.next_descriptor = 0;
|
|
|
|
flush_cache((u32)&task0, sizeof(task0));
|
|
flush_cache((u32)p_sign, CACHE_LINE_SIZE);
|
|
flush_cache((u32)src_addr, src_align_len);
|
|
flush_cache((u32)total_package_len, sizeof(total_package_len));
|
|
|
|
ss_set_drq((u32)&task0);
|
|
ss_irq_enable(task0.task_id);
|
|
ss_ctrl_start(ALG_SHA256);
|
|
ss_wait_finish(task0.task_id);
|
|
ss_pending_clear(task0.task_id);
|
|
ss_ctrl_stop();
|
|
ss_irq_disable(task0.task_id);
|
|
if(ss_check_err())
|
|
{
|
|
printf("SS %s fail 0x%x\n",__func__,ss_check_err());
|
|
}
|
|
|
|
invalidate_dcache_range((ulong)p_sign,(ulong)p_sign+CACHE_LINE_SIZE);
|
|
//copy data
|
|
memcpy(dst_addr, p_sign, 32);
|
|
return 0;
|
|
}
|
|
|
|
s32 sunxi_rsa_calc(u8 * n_addr, u32 n_len,
|
|
u8 * e_addr, u32 e_len,
|
|
u8 * dst_addr, u32 dst_len,
|
|
u8 * src_addr, u32 src_len)
|
|
{
|
|
const u32 TEMP_BUFF_LEN = ((2048>>3) + CACHE_LINE_SIZE);
|
|
|
|
u32 mod_bit_size = 2048;
|
|
u32 mod_size_len_inbytes = mod_bit_size/8;
|
|
u32 data_word_len = mod_size_len_inbytes/4;
|
|
|
|
task_queue task0 __aligned(CACHE_LINE_SIZE) = {0};
|
|
ALLOC_CACHE_ALIGN_BUFFER(u8, p_n, TEMP_BUFF_LEN);
|
|
ALLOC_CACHE_ALIGN_BUFFER(u8, p_e, TEMP_BUFF_LEN);
|
|
ALLOC_CACHE_ALIGN_BUFFER(u8, p_src, TEMP_BUFF_LEN);
|
|
ALLOC_CACHE_ALIGN_BUFFER(u8, p_dst, TEMP_BUFF_LEN);
|
|
|
|
__rsa_padding(p_src, src_addr, src_len, mod_size_len_inbytes);
|
|
__rsa_padding(p_n, n_addr, n_len, mod_size_len_inbytes);
|
|
memset(p_e, 0, mod_size_len_inbytes);
|
|
memcpy(p_e, e_addr, e_len);
|
|
|
|
if(ss_get_ver() < 2)
|
|
{
|
|
/* CE1.0 */
|
|
task0.task_id = 0;
|
|
task0.common_ctl = (ALG_RSA | (1U<<31));
|
|
task0.symmetric_ctl = 0;
|
|
task0.asymmetric_ctl = (2<<28); /* rsa2048 */
|
|
task0.key_descriptor = (uint)p_e;
|
|
task0.iv_descriptor = (uint)p_n;
|
|
task0.ctr_descriptor = 0;
|
|
task0.data_len = data_word_len;
|
|
task0.source[0].addr= (uint)p_src;
|
|
task0.source[0].length = data_word_len;
|
|
task0.destination[0].addr= (uint)p_dst;
|
|
task0.destination[0].length = data_word_len;
|
|
task0.next_descriptor = 0;
|
|
}
|
|
else
|
|
{
|
|
/* CE2.0 */
|
|
task0.task_id = 0;
|
|
task0.common_ctl = (ALG_RSA | (1U<<31));
|
|
task0.symmetric_ctl = 0;
|
|
task0.asymmetric_ctl = (2048/32); /* rsa2048 */
|
|
task0.ctr_descriptor = 0;
|
|
|
|
task0.source[0].addr= (uint)p_e;
|
|
task0.source[0].length = data_word_len;
|
|
task0.source[1].addr= (uint)p_n;
|
|
task0.source[1].length = data_word_len;
|
|
task0.source[2].addr= (uint)p_src;
|
|
task0.source[2].length = data_word_len;
|
|
|
|
task0.data_len += task0.source[0].length;
|
|
task0.data_len += task0.source[1].length;
|
|
task0.data_len += task0.source[2].length;
|
|
task0.data_len *= 4; /* byte len */
|
|
|
|
task0.destination[0].addr= (uint)p_dst;
|
|
task0.destination[0].length = data_word_len;
|
|
}
|
|
|
|
flush_cache((u32)&task0, sizeof(task0));
|
|
flush_cache((u32)p_n, mod_size_len_inbytes);
|
|
flush_cache((u32)p_e, mod_size_len_inbytes);
|
|
flush_cache((u32)p_src, mod_size_len_inbytes);
|
|
flush_cache((u32)p_dst, mod_size_len_inbytes);
|
|
|
|
ss_set_drq((u32)&task0);
|
|
ss_irq_enable(task0.task_id);
|
|
ss_ctrl_start(ALG_RSA);
|
|
ss_wait_finish(task0.task_id);
|
|
ss_pending_clear(task0.task_id);
|
|
ss_ctrl_stop();
|
|
ss_irq_disable(task0.task_id);
|
|
if(ss_check_err())
|
|
{
|
|
printf("SS %s fail 0x%x\n",__func__,ss_check_err());
|
|
}
|
|
|
|
invalidate_dcache_range((ulong)p_dst,(ulong)p_dst+mod_size_len_inbytes);
|
|
__rsa_padding(dst_addr, p_dst, mod_bit_size/64, mod_bit_size/64);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int sunxi_create_rssk(u8 *rssk_buf, u32 rssk_byte)
|
|
{
|
|
u32 total_bit_len = 0;
|
|
task_queue task0 __aligned(CACHE_LINE_SIZE) = {0};
|
|
|
|
ALLOC_CACHE_ALIGN_BUFFER(u32, total_package_len, 4);
|
|
ALLOC_CACHE_ALIGN_BUFFER(u8, p_sign, CACHE_LINE_SIZE);
|
|
|
|
memset(p_sign, 0, sizeof(p_sign));
|
|
sunxi_ss_open();
|
|
if (rssk_buf == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
total_bit_len = rssk_byte << 3;
|
|
total_package_len[0] = total_bit_len;
|
|
total_package_len[1] = 0;
|
|
|
|
task0.task_id = 0;
|
|
task0.common_ctl = (ALG_TRANG)|(0x1U<<31);
|
|
task0.key_descriptor = (uint)total_package_len;
|
|
task0.data_len = total_bit_len;
|
|
task0.source[0].addr = 0;
|
|
task0.source[0].length = 0;
|
|
task0.destination[0].addr = (uint)p_sign;
|
|
task0.destination[0].length = (rssk_byte>>2);
|
|
task0.next_descriptor = 0;
|
|
|
|
flush_cache((u32)&task0, sizeof(task0));
|
|
flush_cache((u32)p_sign, CACHE_LINE_SIZE);
|
|
flush_cache((u32)total_package_len, sizeof(total_package_len));
|
|
|
|
ss_set_drq((u32)&task0);
|
|
ss_irq_enable(task0.task_id);
|
|
ss_ctrl_start(ALG_TRANG);
|
|
ss_wait_finish(task0.task_id);
|
|
ss_pending_clear(task0.task_id);
|
|
ss_ctrl_stop();
|
|
ss_irq_disable(task0.task_id);
|
|
|
|
if (ss_check_err()) {
|
|
printf("RSSK %s fail 0x%x\n", __func__, ss_check_err());
|
|
}
|
|
|
|
invalidate_dcache_range((ulong)p_sign, (ulong)p_sign+CACHE_LINE_SIZE);
|
|
/*copy data*/
|
|
memcpy(rssk_buf, p_sign, rssk_byte);
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
#ifdef SUNXI_HASH_TEST
|
|
int do_sha256_test(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|
{
|
|
u8 hash[32] = {0};
|
|
u32 x1 = simple_strtol(argv[1], NULL, 16);
|
|
u32 x2 = simple_strtol(argv[2], NULL, 16);
|
|
if(argc < 3)
|
|
{
|
|
return -1;
|
|
}
|
|
printf("src = 0x%x, len = 0x%x\n", x1,x2);
|
|
|
|
tick_printf("sha256 test start 0\n");
|
|
sunxi_ss_open();
|
|
sunxi_sha_calc(hash, 32, (u8*)x1,x2);
|
|
tick_printf("sha256 test end\n");
|
|
sunxi_dump(hash,32);
|
|
|
|
return 0;
|
|
}
|
|
|
|
U_BOOT_CMD(
|
|
sha256_test, 3, 0, do_sha256_test,
|
|
"do a sha256 test, arg1: src address, arg2: len(hex)",
|
|
"NULL"
|
|
);
|
|
#endif
|
|
|