SmartAudio/lichee/brandy/u-boot-2011.09/common/cmd_sunxi_verify.c

292 lines
7.4 KiB
C
Raw Normal View History

2018-07-13 01:31:50 +00:00
/*
* (C) Copyright 2000-2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/*
* Allwinner boot verify trust-chain
*/
#include <common.h>
#include <openssl_ext.h>
#include <private_toc.h>
#include <asm/arch/ss.h>
#include <sunxi_verify.h>
#include <sunxi_board.h>
static int sunxi_certif_pubkey_check( sunxi_key_t *pubkey, u8 *hash_buf);
static int sunxi_root_certif_pk_verify(sunxi_certif_info_t *sunxi_certif, u8 *buf, u32 len, u8 *hash_buf);
/*
************************************************************************************************************
*
* function
*
* name :
*
* parmeters :
*
* return :
*
* note :
*
*
************************************************************************************************************
*/
int sunxi_verify_signature(void *buff, uint len, const char *cert_name)
{
u8 hash_of_file[32];
int ret;
struct sbrom_toc1_head_info *toc1_head;
struct sbrom_toc1_item_info *toc1_item;
sunxi_certif_info_t sub_certif;
int i;
memset(hash_of_file, 0, 32);
sunxi_ss_open();
ret = sunxi_sha_calc(hash_of_file, 32, buff, len);
if(ret)
{
printf("sunxi_verify_signature err: calc hash failed\n");
//sunxi_ss_close();
return -1;
}
//sunxi_ss_close();
printf("show hash of file\n");
sunxi_dump(hash_of_file, 32);
//<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>toc1<63><31>֤<EFBFBD><D6A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
toc1_head = (struct sbrom_toc1_head_info *)CONFIG_TOC1_STORE_IN_DRAM_BASE;
toc1_item = (struct sbrom_toc1_item_info *)(CONFIG_TOC1_STORE_IN_DRAM_BASE + sizeof(struct sbrom_toc1_head_info));
for(i=1;i<toc1_head->items_nr;i++, toc1_item++)
{
if(toc1_item->type == TOC_ITEM_ENTRY_TYPE_BIN_CERTIF)
{
printf("find cert name %s\n", toc1_item->name);
if(!strcmp((const char *)toc1_item->name, cert_name))
{
//ȡ<><C8A1>֤<EFBFBD><D6A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><D5B9>
if(sunxi_certif_probe_ext(&sub_certif, (u8 *)(CONFIG_TOC1_STORE_IN_DRAM_BASE + toc1_item->data_offset), toc1_item->data_len))
{
printf("%s error: cant verify the content certif\n", __func__);
return -1;
}
//<2F>Ƚ<EFBFBD><C8BD><EFBFBD>չ<EFBFBD><D5B9><EFBFBD><EFBFBD>hash
printf("show hash in certif\n");
sunxi_dump(sub_certif.extension.value[0], 32);
if(memcmp(hash_of_file, sub_certif.extension.value[0], 32))
{
printf("hash compare is not correct\n");
printf(">>>>>>>hash of file<<<<<<<<<<\n");
sunxi_dump(hash_of_file, 32);
printf(">>>>>>>hash in certif<<<<<<<<<<\n");
sunxi_dump(sub_certif.extension.value[0], 32);
return -1;
}
return 0;
}
}
}
printf("cant find a certif belong to %s\n", cert_name);
return -1;
}
/*
************************************************************************************************************
*
* function
*
* name :
*
* parmeters :
*
* return :
*
* note :
*
*
************************************************************************************************************
*/
int sunxi_verify_rotpk_hash(void *input_hash_buf, int len)
{
u8 hash_of_pubkey[32];
struct sbrom_toc1_item_info *toc1_item;
sunxi_certif_info_t root_certif;
if(len < 32)
{
printf("the input hash is not equal to 32 bytes\n");
return -1;
}
memset(hash_of_pubkey, 0, 32);
sunxi_ss_open();
//<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>toc1<63><31>֤<EFBFBD><D6A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
toc1_item = (struct sbrom_toc1_item_info *)(CONFIG_TOC1_STORE_IN_DRAM_BASE + sizeof(struct sbrom_toc1_head_info));
if(toc1_item->type == TOC_ITEM_ENTRY_TYPE_NULL)
{
printf("find cert name %s\n", toc1_item->name);
//ȡ<><C8A1>֤<EFBFBD><D6A4><EFBFBD>Ĺ<EFBFBD>Կ
if(sunxi_root_certif_pk_verify(&root_certif, (u8 *)(CONFIG_TOC1_STORE_IN_DRAM_BASE + toc1_item->data_offset), \
toc1_item->data_len, hash_of_pubkey))
{
printf("%s error: cant get the content certif publickey hash\n", __func__);
return -1;
}
//<2F>Ƚ<EFBFBD>hashֵ
printf("show hash of publickey in certif\n");
sunxi_dump(input_hash_buf, 32);
if(memcmp(input_hash_buf, hash_of_pubkey, 32))
{
printf("hash compare is not correct\n");
printf(">>>>>>>hash of certif<<<<<<<<<<\n");
sunxi_dump(hash_of_pubkey, 32);
printf(">>>>>>>hash of user input<<<<<<<<<<\n");
sunxi_dump(input_hash_buf, 32);
return -1;
}
return 0;
}
return -1;
}
/*
************************************************************************************************************
*
* function
*
* name :
*
* parmeters :
*
* return :
*
* note :
*
*
************************************************************************************************************
*/
#define RSA_BIT_WITDH 2048
static int sunxi_certif_pubkey_check( sunxi_key_t *pubkey, u8 *hash_buf)
{
char rotpk_hash[256];
char all_zero[32];
char pk[RSA_BIT_WITDH/8 * 2 + 256]; /*For the stupid sha padding */
memset(all_zero, 0, 32);
memset(pk, 0x91, sizeof(pk));
char *align = (char *)(((u32)pk+31)&(~31));
if( *(pubkey->n) ){
memcpy(align, pubkey->n, pubkey->n_len);
memcpy(align+pubkey->n_len, pubkey->e, pubkey->e_len);
}else{
memcpy(align, pubkey->n+1, pubkey->n_len-1);
memcpy(align+pubkey->n_len-1, pubkey->e, pubkey->e_len);
}
if(sunxi_sha_calc( (u8 *)rotpk_hash, 32, (u8 *)align, RSA_BIT_WITDH/8*2 ))
{
printf("sunxi_sha_calc: calc pubkey sha256 with hardware err\n");
return -1;
}
memcpy(hash_buf, rotpk_hash, 32);
return 0;
}
/*
************************************************************************************************************
*
* function
*
* name :
*
* parmeters : buf: ֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ len<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><EFBFBD><EFBFBD>
*
* return :
*
* note : ֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD>У<EFBFBD><EFBFBD>
*
*
************************************************************************************************************
*/
static int sunxi_root_certif_pk_verify(sunxi_certif_info_t *sunxi_certif, u8 *buf, u32 len, u8 *hash_buf)
{
X509 *certif;
int ret;
//<2F>ڴ<EFBFBD><DAB4><EFBFBD>ʼ<EFBFBD><CABC>
sunxi_certif_mem_reset();
//<2F><><EFBFBD><EFBFBD>֤<EFBFBD><D6A4>
ret = sunxi_certif_create(&certif, buf, len);
if(ret < 0)
{
printf("fail to create a certif\n");
return -1;
}
//<2F><>ȡ֤<C8A1>鹫Կ
ret = sunxi_certif_probe_pubkey(certif, &sunxi_certif->pubkey);
if(ret)
{
printf("fail to probe the public key\n");
return -1;
}
ret = sunxi_certif_pubkey_check(&sunxi_certif->pubkey, hash_buf);
if(ret){
printf("fail to check the public key hash against efuse\n");
return -1;
}
sunxi_certif_free(certif);
return 0;
}
int do_rotpk_test(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
u8 input_hash_buf[32];
int ret;
memset(input_hash_buf, 0, 32);
ret = sunxi_verify_rotpk_hash(input_hash_buf, 32);
return ret;
}
U_BOOT_CMD(
rotpk_test, 3, 0, do_rotpk_test,
"test the rotpk key",
"usage: rotpk_test"
);