346 lines
7.2 KiB
C
346 lines
7.2 KiB
C
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
|
|
/*
|
|
* common/cmd_sha2.c
|
|
*
|
|
* Copyright (C) 2020 Amlogic, Inc. All rights reserved.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* Functions in this file implement Amlogic SHA2 function
|
|
*
|
|
* Author : [email protected]
|
|
*
|
|
* Feature: implement uboot command for SHA2 common usage
|
|
* command : sha2 addr_in len [addr_out]
|
|
* addr_in[IN] : DDR address for input buffer
|
|
* len[IN] : total data size to be processed for SHA2
|
|
* addr_out[OUT]: user defined output buffer for the SHA2 (if not set then the SHA2 of input will shown only but not stored)
|
|
*
|
|
* History: 1. 2017.06.01 function init
|
|
*
|
|
*
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <malloc.h>
|
|
#include <asm/arch/regs.h>
|
|
#include <u-boot/sha256.h>
|
|
#include <u-boot/sha1.h>
|
|
|
|
#define DATA_MAX_LEN (1 << 31) //max length of SHA2 is 2 GB
|
|
static int do_sha2(cmd_tbl_t *cmdtp, int flag, int argc,
|
|
char * const argv[])
|
|
{
|
|
int nReturn=CMD_RET_USAGE;
|
|
ulong addr_in,nLength,addr_out=0;
|
|
unsigned char szSHA2[32];
|
|
unsigned char *pSHA2 = szSHA2;
|
|
int nSHA2Type = 256;
|
|
char *endp;
|
|
int i;
|
|
|
|
/* need at least three arguments */
|
|
if (argc < 3)
|
|
goto exit;
|
|
|
|
nReturn = __LINE__;
|
|
|
|
if ( 0 == *argv[1] )
|
|
{
|
|
printf("[addr_in] format error! \n" );
|
|
goto exit;
|
|
}
|
|
addr_in = simple_strtoul(argv[1], &endp, 16);
|
|
if ( 0 != *endp )
|
|
{
|
|
printf("[addr_in] format error! \n" );
|
|
goto exit;
|
|
}
|
|
nReturn = __LINE__;
|
|
|
|
if ( 0 == *argv[2])
|
|
{
|
|
printf("[Length] format error! \n" );
|
|
goto exit;
|
|
}
|
|
nLength = simple_strtoul(argv[2], &endp, 16);
|
|
if ( 0 != *endp )
|
|
{
|
|
printf("[Length] format error! \n" );
|
|
goto exit;
|
|
}
|
|
if ( !nLength || nLength > DATA_MAX_LEN)
|
|
{
|
|
printf("Length range: 0x00000001 ~ 0x%08x Byte! \n", DATA_MAX_LEN );
|
|
goto exit;
|
|
}
|
|
|
|
nReturn = __LINE__;
|
|
|
|
|
|
|
|
if (argc > 3)
|
|
{
|
|
if ( 0 == *argv[3] )
|
|
{
|
|
printf("[addr_out] format error! \n" );
|
|
goto exit;
|
|
}
|
|
addr_out = simple_strtoul(argv[3], &endp, 16);
|
|
if ( 0 != *endp )
|
|
{
|
|
printf("[addr_out] format error! \n" );
|
|
goto exit;
|
|
}
|
|
pSHA2=(unsigned char *)addr_out;
|
|
}
|
|
|
|
sha256_csum_wd((unsigned char *)addr_in, nLength,pSHA2,0);
|
|
printf("\nSHA%d of addr_in: 0x%08x, len: 0x%08x ", nSHA2Type, (unsigned int)addr_in, (unsigned int)nLength);
|
|
if (argc > 3)
|
|
printf(", addr_out: 0x%08x \n", (unsigned int)addr_out);
|
|
printf("\n");
|
|
|
|
for (i=0; i<SHA256_SUM_LEN; i++)
|
|
printf("%02x%s", pSHA2[i], ((i+1) % 16==0) ? "\n" :" ");
|
|
|
|
nReturn = 0;
|
|
|
|
exit:
|
|
|
|
return nReturn;
|
|
}
|
|
|
|
#undef DATA_MAX_LEN
|
|
|
|
U_BOOT_CMD(
|
|
sha2, 4, 1, do_sha2,
|
|
"SHA2 command",
|
|
"addr_in len [addr_out] \n"
|
|
);
|
|
|
|
|
|
|
|
/*
|
|
* Feature: implement uboot command for test SHA2 common usage
|
|
* command : sha2test [writeval] [len]
|
|
* writeval[IN] : the value of data for test(default is 0x01)
|
|
* len[IN] : total data size to be processed for SHA2 (default is 128k bytes)
|
|
*
|
|
* History: 1. 2017.06.01 function init
|
|
*
|
|
*
|
|
*/
|
|
|
|
//#define CONFIG_AML_SHA2_TEST
|
|
#if defined(CONFIG_AML_SHA2_TEST)
|
|
|
|
#define writel(val,reg) (*((volatile unsigned *)(reg)))=(val)
|
|
#define readl(reg) (*((volatile unsigned *)(reg)))
|
|
#define TEST_MAX_LEN (10<<20)
|
|
#define TEST_MIN_LEN (64)
|
|
#ifndef P_ISA_TIMERE
|
|
#define P_ISA_TIMERE (volatile unsigned int *)(ISA_TIMERE)
|
|
#endif
|
|
static int do_sha2test(cmd_tbl_t *cmdtp, int flag, int argc,
|
|
char * const argv[])
|
|
{
|
|
|
|
int nReturn = __LINE__;
|
|
unsigned char *pBuffer = 0;
|
|
|
|
int i;
|
|
long nLength = TEST_MAX_LEN;
|
|
unsigned int byPattern = 1;
|
|
char *endp;
|
|
int nSHA2Type = 256;
|
|
unsigned int ntime1,ntime2,ntime;
|
|
unsigned char szSHA2[32];
|
|
int testLength[8]={TEST_MAX_LEN,1024*1024,100*1024,10*1024,1024,512,128,TEST_MIN_LEN};
|
|
int c=0;
|
|
|
|
#ifdef CONFIG_AML_HW_SHA2
|
|
printf("aml log : Amlogic HW SHA2\n");
|
|
#elif defined(CONFIG_ARMV8_CE_SHA256)
|
|
printf("aml log : ARMCE SHA2\n");
|
|
#else
|
|
printf("aml log : Software SHA2\n");
|
|
#endif
|
|
|
|
|
|
//pattern
|
|
if (argc > 1)
|
|
{
|
|
if ( 0 == *argv[1] )
|
|
{
|
|
printf("[writeval] format error! \n" );
|
|
goto exit;
|
|
}
|
|
byPattern = simple_strtoul(argv[1], &endp, 16);
|
|
if ( 0 != *endp )
|
|
{
|
|
printf("[writeval] format error! \n" );
|
|
goto exit;
|
|
}
|
|
if ( byPattern > 0xff)
|
|
{
|
|
printf("writeval range: 0x00 ~ 0xff! \n" );
|
|
goto exit;
|
|
}
|
|
|
|
}
|
|
|
|
nReturn = __LINE__;
|
|
|
|
//length
|
|
if (argc > 2)
|
|
{
|
|
if ( 0== *argv[2] )
|
|
{
|
|
printf("[Length] format error! \n" );
|
|
goto exit;
|
|
}
|
|
nLength = simple_strtoul(argv[2], &endp, 16);
|
|
if ( 0 != *endp )
|
|
{
|
|
printf("[Length] format error! \n" );
|
|
goto exit;
|
|
}
|
|
|
|
if ( !nLength || nLength > TEST_MAX_LEN)
|
|
{
|
|
printf("Length range: 0x00000001 ~ 0x%08x Byte! \n", TEST_MAX_LEN );
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
nReturn = __LINE__;
|
|
|
|
pBuffer=(unsigned char*)malloc(nLength);
|
|
|
|
if (!pBuffer)
|
|
{
|
|
printf("malloc fail! \n" );
|
|
goto exit;
|
|
}
|
|
|
|
//set buffer with dedicated pattern
|
|
memset(pBuffer,byPattern,nLength);
|
|
|
|
|
|
do
|
|
{
|
|
ntime1=readl(P_ISA_TIMERE);
|
|
sha256_csum_wd(pBuffer, nLength,szSHA2,0 );
|
|
ntime2=readl(P_ISA_TIMERE);
|
|
|
|
ntime = ntime2 - ntime1;
|
|
|
|
printf("\nSHA%d of val:0x%02x, len:0x%08lx, time:%d us, BW:%ld kB/s\n",
|
|
nSHA2Type, (unsigned int)byPattern, nLength, ntime,
|
|
(long)((nLength * 1000000 >> 10) / ntime));
|
|
|
|
//SHA2 dump
|
|
for (i=0; i<SHA256_SUM_LEN; i++)
|
|
printf("%02x%s", szSHA2[i], ((i+1) % 16==0) ? "\n" :" ");
|
|
|
|
if (argc > 2)
|
|
break;
|
|
|
|
nLength =testLength[++c];
|
|
}
|
|
while (nLength > TEST_MIN_LEN) ;
|
|
|
|
nReturn = 0;
|
|
|
|
exit:
|
|
|
|
if (pBuffer)
|
|
{
|
|
free(pBuffer);
|
|
pBuffer = 0;
|
|
}
|
|
|
|
return nReturn;
|
|
|
|
}
|
|
|
|
#undef writel
|
|
#undef readl
|
|
#undef TEST_MAX_LEN
|
|
#undef TEST_MIN_LEN
|
|
|
|
U_BOOT_CMD(
|
|
sha2test, 3, 1, do_sha2test,
|
|
"test SHA2 function",
|
|
"[writeval] [len] \n"
|
|
);
|
|
|
|
static char *sha1_msg =
|
|
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
|
|
|
|
static uint8_t sha1_hash[20] = {
|
|
0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
|
|
0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1
|
|
};
|
|
|
|
static char *sha256_msg =
|
|
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
|
|
|
|
static uint8_t sha256_hash[] = {
|
|
0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
|
|
0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
|
|
0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
|
|
0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1
|
|
};
|
|
|
|
static int do_sha_test(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|
{
|
|
uint32_t test_case = 0;
|
|
char *endp = 0;
|
|
uint8_t output[32];
|
|
int ret = 0;
|
|
|
|
if (argc != 2) {
|
|
cmd_usage(cmdtp);
|
|
return 1;
|
|
}
|
|
|
|
test_case = ustrtoul(argv[1], &endp, 0);
|
|
|
|
switch (test_case) {
|
|
case 0:
|
|
flush_dcache_range((uintptr_t)sha256_msg, strlen(sha256_msg));
|
|
sha256_csum_wd((uint8_t *)sha256_msg, strlen(sha256_msg),
|
|
output, sizeof(output));
|
|
ret = memcmp(sha256_hash, output, 32);
|
|
if (ret)
|
|
printf("test:%s sha256 failed\n", __func__);
|
|
else
|
|
printf("test:%s sha256 passed\n", __func__);
|
|
return 0;
|
|
case 1:
|
|
flush_dcache_range((uintptr_t)sha1_msg, strlen(sha1_msg));
|
|
sha1_csum_wd((uint8_t *)sha1_msg, strlen(sha1_msg),
|
|
output, sizeof(output));
|
|
ret = memcmp(sha1_hash, output, 20);
|
|
if (ret)
|
|
printf("test:%s sha1 failed\n", __func__);
|
|
else
|
|
printf("test:%s sha1 passed\n", __func__);
|
|
return 0;
|
|
default:
|
|
printf("Unknown test case\n");
|
|
return 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
U_BOOT_CMD(shatest, 2, 0, do_sha_test,
|
|
"shatest <test case>",
|
|
"run small sha test cases\n"
|
|
);
|
|
#endif //#if defined(CONFIG_AML_SHA2_TEST)
|