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

1595 lines
40 KiB
C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Driver for NAND support, Rick Bronson
* borrowed heavily from:
* (c) 1999 Machine Vision Holdings, Inc.
* (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org>
*
* Ported 'dynenv' to 'nand env.oob' command
* (C) 2010 Nanometrics, Inc.
* 'dynenv' -- Dynamic environment offset in NAND OOB
* (C) Copyright 2006-2007 OpenMoko, Inc.
* Added 16-bit nand support
* (C) 2004 Texas Instruments
*
* Copyright 2010 Freescale Semiconductor
* The portions of this file whose copyright is held by Freescale and which
* are not considered a derived work of GPL v2-only code may be distributed
* and/or modified 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.
*/
/*
A. 加密解密
1. 密钥的产生
1) 找出两个相异的大素数P和Q令NP×QMP1*Q1
2) 找出与M互素的大数E且E<M用欧氏算法计算出大数D使D×E≡1 MOD M。
3) 丢弃P和Q公开ED和N。E和N即加密密钥(公钥)D和N即解密密钥(私钥)。
2. 加密的步骤
1) 计算N的有效位数tn以字节数计将最高位的零忽略掉令tn1tn1。比如N0x012A05其有效位数tn5tn14
2) 将明文数据A分割成tn1位以字节数计的块每块看成一个大数块数记为bn。从而保证了每块都小于N。
3) 对A的每一块Ai进行BiAi^E MOD N运算。Bi就是密文数据的一块将所有密文块合并起来就得到了密文数据B。
3. 解密的步骤
1) 同加密的第一步。
2) 将密文数据B分割成tn位以字节数计的块每块看成一个大数块数记为bn。
3) 对B的每一块Bi进行CiBi^D MOD N运算。Ci就是密文数据的一块将所有密文块合并起来就得到了密文数据C。
*/
#include <common.h>
#include <command.h>
#include <malloc.h>
#include <superblock.h>
#include <fastboot.h>
#include <sys_partition.h>
#include <sunxi_mbr.h>
#include <android_misc.h>
DECLARE_GLOBAL_DATA_PTR;
int signature_erase_all(sunxi_mbr_t *mbr);
#ifndef CONFIG_OPENSSL
typedef struct public_key_pairs_t
{
unsigned int public_key; // e
unsigned int divider; // n
}
public_key_pairs;
typedef struct private_key_pairs_t
{
unsigned int private_key; // d
unsigned int divider; // n
}
private_key_pairs;
#define P (127)
#define Q (401)
#define N ((P) * (Q))
#define M ((P-1) * (Q-1))
#define E (53)
public_key_pairs pblc_keys;
private_key_pairs prvt_keys;
void rsa_dump(void);
static unsigned int probe_gcd(unsigned int divdend, unsigned int divder)
{
unsigned int ret = divdend % divder;
while(ret)
{
divdend = divder;
divder = ret;
ret = divdend % divder;
}
return divder;
}
unsigned probe_high_level_power_mod(unsigned int base_value, unsigned int power, unsigned int divider)
{
unsigned int ret = 1;
base_value %= divider;
while(power > 0)
{
if(power & 1)
{
ret = (ret * base_value) % divider;
}
power /= 2;
base_value = (base_value * base_value) % divider;
}
return ret;
}
unsigned rsa_init(void)
{
unsigned int k;
unsigned int product;
unsigned int m_value;
m_value = M;
k = 1;
if(probe_gcd(m_value, E) == 1) //e,M互质
{
do
{
product = M * k + 1;
if(!(product % E))
{
pblc_keys.public_key = E;
pblc_keys.divider = N;
prvt_keys.private_key = product/E;
prvt_keys.divider = N;
#ifdef DEBUG_MODE
rsa_dump();
#endif
return 0;
}
k ++;
}
while(1);
}
return -1;
}
void rsa_dump(void)
{
printf("base value\n");
printf("M = %d(%d * %d), N = %d(%d * %d)\n", M, P-1, Q-1, N, P, Q);
printf("public key: \n");
printf("{e, n} = %d, %d\n", pblc_keys.public_key, pblc_keys.divider);
printf("private key: \n");
printf("{d, n} = %d, %d\n", prvt_keys.private_key, prvt_keys.divider);
}
void rsa_encrypt( unsigned int *input, unsigned int length, unsigned int *output )
{
unsigned int i;
for(i=0;i<length;i++)
{
output[i] = probe_high_level_power_mod(input[i], pblc_keys.public_key, pblc_keys.divider);
}
return ;
}
void rsa_decrypt( unsigned int *input, unsigned int length, unsigned int *output )
{
unsigned int i;
for(i=0;i<length;i++)
{
output[i] = probe_high_level_power_mod(input[i], prvt_keys.private_key, prvt_keys.divider);
}
return ;
}
/*
************************************************************************************************************
hash function
************************************************************************************************************
*/
unsigned int cryptTable[0x500];
unsigned int seed1 = 0x7FED7FED;
unsigned int seed2 = 0xEEEEEEEE;
int key = 0;
/*
************************************************************************************************************
*
* function
*
* name :
*
* parmeters :
*
* return :
*
* note : 返回数组
*
*
************************************************************************************************************
*/
void prepareCryptTable(void)
{
// unsigned int seed = 0x00100001, index1 = 0, index2 = 0, i;
//
// for( index1 = 0; index1 < 0x100; index1++ )
// {
// for( index2 = index1, i = 0; i < 5; i++, index2 += 0x100 )
// {
// unsigned long temp1, temp2;
//
// seed = (seed * 125 + 3) % 0x2AAAAB;
// temp1 = (seed & 0xFFFF) << 0x10;
// seed = (seed * 125 + 3) % 0x2AAAAB;
// temp2 = (seed & 0xFFFF);
//
// cryptTable[index2] = ( temp1 | temp2 );
// }
// }
}
/*
************************************************************************************************************
*
* function
*
* name :
*
* parmeters :
*
* return :
*
* note : 返回hash值
*
*
************************************************************************************************************
*/
unsigned int HashString( unsigned char *str, unsigned int dwHashType, unsigned int length )
{
// unsigned char *key = (unsigned char *)str;
// int ch;
//
// while( length > 0 )
// {
// ch = *key++;
// seed1 = cryptTable[(dwHashType << 8) + ch] ^ (seed1 + seed2);
// seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
// length --;
// }
//
// return seed1;
key += add_sum((void *)str, length);
return (unsigned int)key;
}
void HashString_init(void)
{
key = 0;
}
#define HASH_BUFFER_BYTES (32 * 1024)
#define HASH_BUFFER_SECTORS (HASH_BUFFER_BYTES/512)
//static void change_boot_signature(int partition_index)
//{
// unsigned int summary = 0;
// uint boot_start ;
// uchar buffer[HASH_BUFFER_BYTES];
// uint read_bytes;
// unsigned int s_value[4], h_value[4];
//
// memset(buffer,0,HASH_BUFFER_BYTES);
// prepareCryptTable();
// boot_start = sunxi_partition_get_offset(partition_index);
// if(boot_start == 0)
// {
// printf("get the boot partition offest error!!\n");
// return ;
// }
// HashString_init();
// read_bytes = sizeof(struct fastboot_boot_img_hdr);
// if(!sunxi_flash_read(boot_start, (read_bytes + 511)/512, buffer))
// {
// printf("signature0 read flash sig1 err\n");
//
// return ;
// }
// summary = HashString(buffer, 1, read_bytes); //1类hash
// printf("the summary is 0x%x\n",summary);
// read_bytes = sizeof(struct image_header);
// if(!sunxi_flash_read(boot_start+ CFG_FASTBOOT_MKBOOTIMAGE_PAGE_SIZE/512, (read_bytes + 511)/512, buffer))
// {
// printf("signature0 read flash sig2 err\n");
//
// return ;
// }
// summary = HashString(buffer, 1, read_bytes); //1类hash
// printf("the summary is 0x%x\n",summary);
// rsa_init();
// h_value[3] = (summary>>24)&0xff;
// h_value[2] = (summary>>16)&0xff;
// h_value[1] = (summary>>8)&0xff;
// h_value[0] = (summary>>0)&0xff;
//
// rsa_encrypt(h_value,4,s_value);
//
// if(!sunxi_flash_read(boot_start, 2, buffer))
// {
// printf("signature0 read flash sig3 err\n");
// return;
// }
//
// *(unsigned int *)(buffer + 608) = s_value[0];
// *(unsigned int *)(buffer + 612) = s_value[1];
// *(unsigned int *)(buffer + 616) = s_value[2];
// *(unsigned int *)(buffer + 620) = s_value[3];
// debug("change_boot_signature!!!!\n");
// debug("s_value[0] = %d\n",s_value[0]);
// debug("s_value[1] = %d\n",s_value[1]);
// debug("s_value[2] = %d\n",s_value[2]);
// debug("s_value[3] = %d\n",s_value[3]);
// if(!sunxi_flash_write(boot_start,2, buffer))
// {
// printf("cant write the signature into flash!!\n");
// return ;
// }
//
// return ;
//}
//
//static void change_system_signature(int partition_index)
//{
// unsigned int summary = 0;
// unsigned int system_start;
// unsigned int s_value[4], h_value[4];
// unsigned char buffer[HASH_BUFFER_BYTES];
// unsigned int read_bytes;
// struct ext4_super_block *sblock;
// system_start = sunxi_partition_get_offset(partition_index);
//
// HashString_init();
// read_bytes = sizeof(struct ext4_super_block);
// if(!sunxi_flash_read(system_start + CFG_SUPER_BLOCK_SECTOR, (read_bytes + 511)/512, buffer))
// {
// printf("read the system fail!!!\n");
// return ;
// }
// sblock = (struct ext4_super_block *)buffer;
// sblock->s_mtime = CFG_SUPER_BLOCK_STAMP_VALUE;
// sblock->s_mnt_count = CFG_SUPER_BLOCK_STAMP_VALUE & 0xffff;
// memset(sblock->s_last_mounted, 0, 64);
//
// summary = HashString(buffer, 1, (unsigned int)&(((struct ext4_super_block *)0)->s_snapshot_list)); //1类hash
// printf("the summary is 0x%x\n",summary);
// rsa_init();
//
// h_value[3] = (summary>>24)&0xff;
// h_value[2] = (summary>>16)&0xff;
// h_value[1] = (summary>>8)&0xff;
// h_value[0] = (summary>>0)&0xff;
//
// rsa_encrypt(h_value,4,s_value);
//
// if(!sunxi_flash_read(system_start, 2, buffer))
// {
// printf("fail to read the system signature!!!\n");
// return;
// }
//
// *(unsigned int *)(buffer + 1000 - 10 * 4 + 0) = s_value[0];
// *(unsigned int *)(buffer + 1000 - 10 * 4 + 4) = s_value[1];
// *(unsigned int *)(buffer + 1000 - 10 * 4 + 8 ) = s_value[2];
// *(unsigned int *)(buffer + 1000 - 10 * 4 + 12 ) = s_value[3] ;
//
// debug("change_system_signature!!!!\n");
// debug("s_value[0] = %d\n",s_value[0]);
// debug("s_value[1] = %d\n",s_value[1]);
// debug("s_value[2] = %d\n",s_value[2]);
// debug("s_value[3] = %d\n",s_value[3]);
//
// if(!sunxi_flash_write(system_start,2, buffer))
// {
// printf("write the system signature fail!!\n");
// return ;
// }
// return ;
//}
//static void change_signature(void)
//{
// int partition_num = 0;
// int i;
// char partition_name[16];
// partition_num = sunxi_partition_get_total_num();
// if((partition_num <= 0) || (partition_num > SUNXI_MBR_MAX_PART_COUNT))
// {
// printf("mbr not exist\n");
// return;
// }
// for(i=0;i<partition_num;i++)
// {
// sunxi_partition_get_name(i,partition_name);
// if(!strcmp("boot",partition_name))
// {
// printf("find the boot partition!!\n");
// change_boot_signature(i);
// }
// if(!strcmp("system",partition_name))
// {
// printf("find the system partition!!\n");
// change_system_signature(i);
// }
// }
// return ;
//}
static int __signature_add_for_boot_format(uint start, uint *sig_value)
{
unsigned char buffer[4096];
unsigned int h_value[4], s_value[4];
uint hash_value;
HashString_init();
if(sunxi_flash_read(start, 4096/512, buffer) != (4096/512))
{
puts("sunxi add signature fail: read flash err\n");
return -1;
}
hash_value = HashString(buffer, 1, sizeof(struct fastboot_boot_img_hdr)); //1类hash
hash_value = HashString(buffer + CFG_FASTBOOT_MKBOOTIMAGE_PAGE_SIZE, 1, sizeof(struct image_header)); //1类hash
rsa_init();
h_value[0] = (hash_value>>0) & 0xff;
h_value[1] = (hash_value>>8) & 0xff;
h_value[2] = (hash_value>>16) & 0xff;
h_value[3] = (hash_value>>24) & 0xff;
rsa_encrypt( h_value, 4, s_value);
sig_value[0] = s_value[0];
sig_value[1] = s_value[1];
sig_value[2] = s_value[2];
sig_value[3] = s_value[3];
return 0;
}
static int __signature_add_for_ext4_format(uint start, uint *sig_value)
{
unsigned char buffer[4096];
unsigned int h_value[4], s_value[4];
struct ext4_super_block *sblock;
uint hash_value;
HashString_init();
if(sunxi_flash_read(start + CFG_SUPER_BLOCK_SECTOR, 4096/512, buffer) != (4096/512))
{
puts("sunxi add signature fail: read flash err\n");
return -1;
}
sblock = (struct ext4_super_block *)buffer;
sblock->s_mtime = CFG_SUPER_BLOCK_STAMP_VALUE;
sblock->s_mnt_count = CFG_SUPER_BLOCK_STAMP_VALUE & 0xffff;
memset(sblock->s_last_mounted, 0, 64);
hash_value = HashString(buffer, 1, (unsigned int)&(((struct ext4_super_block *)0)->s_snapshot_list)); //1类hash
rsa_init();
h_value[0] = (hash_value>>0) & 0xff;
h_value[1] = (hash_value>>8) & 0xff;
h_value[2] = (hash_value>>16) & 0xff;
h_value[3] = (hash_value>>24) & 0xff;
rsa_encrypt( h_value, 4, s_value);
sig_value[0] = s_value[0];
sig_value[1] = s_value[1];
sig_value[2] = s_value[2];
sig_value[3] = s_value[3];
return 0;
}
static int __signature_add(sunxi_partition *partition)
{
int ret;
if(partition->sig_verify == 0x8000)
{
ret = __signature_add_for_boot_format(partition->addrlo, partition->sig_value);
}
else if(partition->sig_verify == 0x8001)
{
ret = __signature_add_for_ext4_format(partition->addrlo, partition->sig_value);
}
else
{
printf("the part is not need to add signature\n");
ret = 0;
}
if(ret < 0)
{
printf("sunxi add signature for part %s failed\n", partition->name);
return -1;
}
return 0;
}
static int __signature_verify_for_boot_format(uint start, uint *sig_value)
{
unsigned char buffer[4096];
unsigned int h_value[4], s_value[4];
uint summary1, summary2;
HashString_init();
if(sunxi_flash_read(start, 4096/512, buffer) != (4096/512))
{
puts("sunxi add signature fail: read flash err\n");
return -1;
}
summary1 = HashString(buffer, 1, sizeof(struct fastboot_boot_img_hdr)); //1类hash
summary1 = HashString(buffer + CFG_FASTBOOT_MKBOOTIMAGE_PAGE_SIZE, 1, sizeof(struct image_header)); //1类hash
s_value[0] = sig_value[0];
s_value[1] = sig_value[1];
s_value[2] = sig_value[2];
s_value[3] = sig_value[3];
rsa_init();
rsa_decrypt( s_value, 4, h_value );
summary2 = (h_value[0]<<0) | (h_value[1]<<8) | (h_value[2]<<16) | (h_value[3]<<24);
if(summary1 != summary2)
{
printf("summary by hash 0x%x\n", summary1);
printf("summary by key 0x%x\n", summary2);
printf("boot signature invalid\n");
return -1;
}
return 0;
}
static int __signature_verify_for_ext4_format(uint start, uint *sig_value)
{
unsigned char buffer[4096];
unsigned int h_value[4], s_value[4];
struct ext4_super_block *sblock;
uint summary1, summary2;
HashString_init();
if(sunxi_flash_read(start + CFG_SUPER_BLOCK_SECTOR, 4096/512, buffer) != (4096/512))
{
puts("sunxi add signature fail: read flash err\n");
return -1;
}
sblock = (struct ext4_super_block *)buffer;
sblock->s_mtime = CFG_SUPER_BLOCK_STAMP_VALUE;
sblock->s_mnt_count = CFG_SUPER_BLOCK_STAMP_VALUE & 0xffff;
memset(sblock->s_last_mounted, 0, 64);
summary1 = HashString(buffer, 1, (unsigned int)&(((struct ext4_super_block *)0)->s_snapshot_list)); //1类hash
s_value[0] = sig_value[0];
s_value[1] = sig_value[1];
s_value[2] = sig_value[2];
s_value[3] = sig_value[3];
rsa_init();
rsa_decrypt( s_value, 4, h_value );
summary2 = (h_value[0]<<0) | (h_value[1]<<8) | (h_value[2]<<16) | (h_value[3]<<24);
if(summary1 != summary2)
{
printf("summary by hash 0x%x\n", summary1);
printf("summary by key 0x%x\n", summary2);
printf("system signature invalid\n");
return -1;
}
return 0;
}
static int __signature_verify(sunxi_partition *partition)
{
int ret;
if(partition->sig_verify == 0x8000)
{
ret = __signature_verify_for_boot_format(partition->addrlo, partition->sig_value);
}
else if(partition->sig_verify == 0x8001)
{
ret = __signature_verify_for_ext4_format(partition->addrlo, partition->sig_value);
}
else
{
printf("the part is not need to verify signature\n");
ret = 0;
}
if(ret < 0)
{
printf("sunxi verify signature for part %s failed\n", partition->name);
return -1;
}
return 0;
}
//static int __signature_verify(char *part_name)
//{
// unsigned int tmp_start;
// unsigned int summary1, summary2;
// unsigned int s_value[4], h_value[4];
// unsigned char buffer[HASH_BUFFER_BYTES];
// unsigned int read_bytes;
//
// memset(buffer, 0, HASH_BUFFER_BYTES);
// //计算hash值
// prepareCryptTable(); //准备hash表
// //获取签名
// printf("ras init\n");
// rsa_init();
// printf("ras start\n");
//
// if(!strcmp("boot", part_name))
// {
// tmp_start = sunxi_partition_get_offset_byname(part_name);
//
// printf("find part %s\n", part_name);
// HashString_init();
// read_bytes = sizeof(struct fastboot_boot_img_hdr);
// if(!sunxi_flash_read(tmp_start, (read_bytes + 511)/512, buffer))
// {
// printf("signature0 read flash sig1 err\n");
//
// return -1;
// }
// summary1 = HashString(buffer, 1, read_bytes); //1类hash
// read_bytes = sizeof(struct image_header);
// if(!sunxi_flash_read(tmp_start + CFG_FASTBOOT_MKBOOTIMAGE_PAGE_SIZE/512, (read_bytes + 511)/512, buffer))
// {
// printf("signature0 read flash sig2 err\n");
//
// return -1;
// }
// summary1 = HashString(buffer, 1, read_bytes); //1类hash
//
// //获取保存的签名
// if(!sunxi_flash_read(tmp_start, 2, buffer))
// {
// printf("signature0 read flash sig3 err\n");
//
// return -1;
// }
// s_value[0] = *(unsigned int *)(buffer + 608);
// s_value[1] = *(unsigned int *)(buffer + 612);
// s_value[2] = *(unsigned int *)(buffer + 616);
// s_value[3] = *(unsigned int *)(buffer + 620);
//
// rsa_decrypt( s_value, 4, h_value );
//
// summary2 = (h_value[0]<<0) | (h_value[1]<<8) | (h_value[2]<<16) | (h_value[3]<<24);
//#if 0
// for(j=0;j<4;j++)
// {
// printf("s_value[%d] = %x\n", j, s_value[j]);
// }
// for(j=0;j<4;j++)
// {
// printf("h_value[%d] = %x\n", j, h_value[j]);
// }
//#endif
// printf("summary by hash 0x%x\n", summary1);
// printf("summary by rsa 0x%x\n", summary2);
// if(summary1 != summary2)
// {
// printf("boot signature invalid\n");
//
// return -1;
// }
// }
// else if(!strcmp("system", part_name))
// {
// struct ext4_super_block *sblock;
//
// tmp_start = sunxi_partition_get_offset_byname(part_name);
// printf("find part %s\n", part_name);
//
// HashString_init();
//
// read_bytes = sizeof(struct ext4_super_block);
// if(!sunxi_flash_read(tmp_start + CFG_SUPER_BLOCK_SECTOR, (read_bytes + 511)/512, buffer))
// {
// printf("signature1 read flash sig1 err\n");
//
// return -1;
// }
// sblock = (struct ext4_super_block *)buffer;
//#if 0
// {
// int k;
// printf("s_inodes_count = %x\n", sblock->s_inodes_count);
// printf("s_blocks_count_lo = %x\n", sblock->s_blocks_count_lo);
// printf("s_r_blocks_count_lo = %x\n", sblock->s_r_blocks_count_lo);
// printf("s_free_blocks_count_lo= %x\n", sblock->s_free_blocks_count_lo);
// printf("s_free_inodes_count = %x\n", sblock->s_free_inodes_count);
// printf("s_first_data_block = %x\n", sblock->s_first_data_block);
// printf("s_log_block_size = %x\n", sblock->s_log_block_size);
// printf("s_log_cluster_size = %x\n", sblock->s_log_cluster_size);
// printf("s_blocks_per_group = %x\n", sblock->s_blocks_per_group);
// printf("s_clusters_per_group = %x\n", sblock->s_clusters_per_group);
// printf("s_inodes_per_group = %x\n", sblock->s_inodes_per_group);
// printf("s_mtime = %x\n", sblock->s_mtime);
// printf("s_wtime = %x\n", sblock->s_wtime);
// printf("s_mnt_count = %x\n", sblock->s_mnt_count);
// printf("s_max_mnt_count = %x\n", sblock->s_max_mnt_count);
// printf("s_magic = %x\n", sblock->s_magic);
// printf("s_state = %x\n", sblock->s_state);
// printf("s_errors = %x\n", sblock->s_errors);
// printf("s_minor_rev_level = %x\n", sblock->s_minor_rev_level);
// printf("s_lastcheck = %x\n", sblock->s_lastcheck);
// printf("s_checkinterval = %x\n", sblock->s_checkinterval);
// printf("s_creator_os = %x\n", sblock->s_creator_os);
// printf("s_rev_level = %x\n", sblock->s_rev_level);
// printf("s_def_resuid = %x\n", sblock->s_def_resuid);
// printf("s_def_resgid = %x\n", sblock->s_def_resgid);
//
// printf("s_first_ino = %x\n", sblock->s_first_ino);
// printf("s_inode_size = %x\n", sblock->s_inode_size);
// printf("s_block_group_nr = %x\n", sblock->s_block_group_nr);
// printf("s_feature_compat = %x\n", sblock->s_feature_compat);
// printf("s_feature_incompat = %x\n", sblock->s_feature_incompat);
// printf("s_feature_ro_compat = %x\n", sblock->s_feature_ro_compat);
// for(k=0;k<16;k++)
// {
// printf("s_uuid[%d] = %x\n", k, sblock->s_uuid[k]);
// }
// for(k=0;k<16;k++)
// {
// printf("s_volume_name[%d] = %x\n", k, sblock->s_volume_name[k]);
// }
// for(k=0;k<64;k++)
// {
// printf("s_last_mounted[%d]= %x\n", k, sblock->s_last_mounted[k]);
// }
// printf("s_algorithm_usage_bitmap= %x\n", sblock->s_algorithm_usage_bitmap);
//
// printf("s_prealloc_blocks = %x\n", sblock->s_prealloc_blocks);
// printf("s_prealloc_dir_blocks = %x\n", sblock->s_prealloc_dir_blocks);
// printf("s_reserved_gdt_blocks = %x\n", sblock->s_reserved_gdt_blocks);
//
// for(k=0;k<16;k++)
// {
// printf("s_journal_uuid[%d]= %x\n", k, sblock->s_journal_uuid[k]);
// }
// printf("s_journal_inum = %x\n", sblock->s_journal_inum);
// printf("s_journal_dev = %x\n", sblock->s_journal_dev);
// printf("s_last_orphan = %x\n", sblock->s_last_orphan);
// for(k=0;k<16;k++)
// {
// printf("s_hash_seed[%d] = %x\n", k, sblock->s_hash_seed[k]);
// }
// printf("s_def_hash_version = %x\n", sblock->s_def_hash_version);
// printf("s_jnl_backup_type = %x\n", sblock->s_jnl_backup_type);
// printf("s_desc_size = %x\n", sblock->s_desc_size);
// printf("s_default_mount_opts = %x\n", sblock->s_default_mount_opts);
// printf("s_first_meta_bg = %x\n", sblock->s_first_meta_bg);
// printf("s_mkfs_time = %x\n", sblock->s_mkfs_time);
// for(k=0;k<17;k++)
// {
// printf("s_jnl_blocks[%d] = %x\n", k, sblock->s_jnl_blocks[k]);
// }
//
// printf("s_blocks_count_hi = %x\n", sblock->s_blocks_count_hi);
// printf("s_r_blocks_count_hi = %x\n", sblock->s_r_blocks_count_hi);
// printf("s_free_blocks_count_hi= %x\n", sblock->s_free_blocks_count_hi);
// printf("s_min_extra_isize = %x\n", sblock->s_min_extra_isize);
// printf("s_want_extra_isize = %x\n", sblock->s_want_extra_isize);
// printf("s_flags = %x\n", sblock->s_flags);
//
// printf("s_raid_stride = %x\n", sblock->s_raid_stride);
// printf("s_mmp_update_interval = %x\n", sblock->s_mmp_update_interval);
// printf("s_mmp_block = %x\n", sblock->s_mmp_block);
// printf("s_raid_stripe_width = %x\n", sblock->s_raid_stripe_width);
// printf("s_log_groups_per_flex = %x\n", sblock->s_log_groups_per_flex);
// printf("s_reserved_char_pad = %x\n", sblock->s_reserved_char_pad);
//
// printf("s_reserved_pad = %x\n", sblock->s_reserved_pad);
// printf("s_kbytes_written = %x\n", sblock->s_kbytes_written);
// printf("s_snapshot_inum = %x\n", sblock->s_snapshot_inum);
// printf("s_snapshot_id = %x\n", sblock->s_snapshot_id);
// printf("s_snapshot_r_blocks_count= %x\n", sblock->s_snapshot_r_blocks_count);
// printf("s_snapshot_list = %x\n", sblock->s_snapshot_list);
// }
//#endif
// sblock->s_mtime = CFG_SUPER_BLOCK_STAMP_VALUE;
// sblock->s_mnt_count = CFG_SUPER_BLOCK_STAMP_VALUE & 0xffff;
// memset(sblock->s_last_mounted, 0, 64);
// summary1 = HashString(buffer, 1, (unsigned int)&(((struct ext4_super_block *)0)->s_snapshot_list)); //1类hash
//
// //获取保存的签名
// if(!sunxi_flash_read(tmp_start, 2, buffer))
// {
// printf("signature1 read flash sig3 err\n");
//
// return -1;
// }
// s_value[0] = *(unsigned int *)(buffer + 1000 - 10 * 4 + 0);
// s_value[1] = *(unsigned int *)(buffer + 1000 - 10 * 4 + 4);
// s_value[2] = *(unsigned int *)(buffer + 1000 - 10 * 4 + 8);
// s_value[3] = *(unsigned int *)(buffer + 1000 - 10 * 4 + 12);
//
// rsa_decrypt( s_value, 4, h_value );
// summary2 = (h_value[0]<<0) | (h_value[1]<<8) | (h_value[2]<<16) | (h_value[3]<<24);
//#if 0
// for(j=0;j<4;j++)
// {
// printf("s_value[%d] = %x\n", j, s_value[j]);
// }
// for(j=0;j<4;j++)
// {
// printf("h_value[%d] = %x\n", j, h_value[j]);
// }
//#endif
// printf("summary by hash %x\n", summary1);
// printf("summary by rsa %x\n", summary2);
// if(summary1 != summary2)
// {
// printf("system signature invalid\n");
//
// return -1;
// }
// }
//
// return 0;
//}
/*
************************************************************************************************************
*
* function
*
* name :
*
* parmeters :
*
* return :
*
* note :
*
*
************************************************************************************************************
*/
int do_sunxi_boot_signature(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
int ret;
int i;
sunxi_mbr_t *mbr = (sunxi_mbr_t *)sunxi_partition_fetch_mbr();
if(mbr == NULL)
{
puts("sunxi signature fail: unable to get the signature table\n");
return -1;
}
if(gd->lockflag == SUNXI_NOLOCK)
{
puts("no signature\n");
return 0;
}
if(gd->lockflag == SUNXI_UNLOCK)
{
puts("signature abandon\n");
setenv("signature", "abandon");
return 0;
}
for(i=0;i<mbr->PartCount;i++)
{
if((mbr->array[i].sig_verify & 0x8000) == 0x8000)
{
ret = __signature_verify(&mbr->array[i]);
if(ret < 0)
{
printf("sunxi signature fail: the part %s signature is not passed\n", mbr->array[i].name);
ret = signature_erase_all(mbr);
if(ret < 0)
{
printf("sunxi signature fail: erase part fail\n");
return -1;
}
if(gd->lockflag == SUNXI_LOCKING)
{
puts("signature failed\n");
setenv("signature", "failed");
}
else if(gd->lockflag == SUNXI_RELOCKING)
{
puts("signature relock_failed\n");
setenv("signature", "relock_failed");
}
return 0;
}
}
}
if(gd->lockflag == SUNXI_LOCKING)
{
puts("signature pass\n");
setenv("signature", "pass");
}
else if(gd->lockflag == SUNXI_RELOCKING)
{
puts("signature relock_pass\n");
setenv("signature", "relock_pass");
}
return 0;
}
U_BOOT_CMD(
sunxi_boot_signature, CONFIG_SYS_MAXARGS, 1, do_sunxi_boot_signature,
"sunxi_boot_signature sub-system",
"no parmeters : \n"
);
static int sunxi_resignature(sunxi_mbr_t *mbr)
{
int ret;
int i;
for(i=0;i<mbr->PartCount;i++)
{
if((mbr->array[i].sig_verify & 0x8000) == 0x8000)
{
printf("resignature for part %s\n", mbr->array[i].name);
ret = __signature_add(&mbr->array[i]);
if(ret < 0)
{
setenv("signature", "failed");
printf("sunxi signature fail: the part %s signature is not passed\n", mbr->array[i].name);
return -1;
}
}
}
return 0;
}
int sunxi_oem_op_lock(int request_flag, char *info, int force)
{
char buffer[SUNXI_MBR_COPY_NUM * SUNXI_MBR_SIZE];
char *tmp_buffer;
sunxi_mbr_t *mbr, *tmp_mbr;
char local_info[64];
char *info_p;
uint store_flag;
int i;
uint crc_cal;
if(info == NULL)
{
memset(local_info, 0, 64);
info_p = local_info;
}
else
{
info_p = info;
}
if(sunxi_flash_read(0, SUNXI_MBR_COPY_NUM * SUNXI_MBR_SIZE/512, buffer) != (SUNXI_MBR_COPY_NUM * SUNXI_MBR_SIZE/512))
{
strcpy(info_p, "sunxi oem operation fail, cant get oem flag");
printf("%s\n", info_p);
return -1;
}
mbr = (sunxi_mbr_t *)buffer;
store_flag = mbr->lockflag;
if( (request_flag == SUNXI_RELOCKING) || (request_flag == SUNXI_LOCKING) ) //要求加锁
{
if( ((store_flag == SUNXI_UNLOCK) || (store_flag == SUNXI_NOLOCK)) || (force == 1) ) //如果没有锁上
{
if(!sunxi_resignature(mbr)) //执行加锁操作
{
if(!force)
{
mbr->lockflag = SUNXI_RELOCKING;
}
else
{
mbr->lockflag = SUNXI_LOCKING;
}
tmp_mbr = mbr + 1;
for(i=1;i<SUNXI_MBR_COPY_NUM;i++)
{
tmp_mbr->array[i].sig_value[0] = mbr->array[i].sig_value[0];
tmp_mbr->array[i].sig_value[1] = mbr->array[i].sig_value[1];
tmp_mbr->array[i].sig_value[2] = mbr->array[i].sig_value[2];
tmp_mbr->array[i].sig_value[3] = mbr->array[i].sig_value[3];
tmp_mbr ++;
}
}
else //如果加锁失败
{
strcpy(info_p, "the lock flag is invalid");
printf("%s\n", info_p);
return -2;
}
}
//else if(lockflag == SUNXI_LOCKING) //如果已经锁上
else //默认都是锁上
{
strcpy(info_p, "system is already locked");
printf("%s\n", info_p);
return -3;
}
}
else if(request_flag == SUNXI_UNLOCK) //要求解锁
{
if( ((store_flag == SUNXI_UNLOCK) || (store_flag == SUNXI_NOLOCK)) && (force != 1) )//
{
strcpy(info_p, "system is not locked");
printf("%s\n", info_p);
return -4;
}
//else if(store_flag == SUNXI_LOCKING) //如果已经锁上
else //默认都是锁上
{
puts("ready to erase all dedicate parts\n");
if(!signature_erase_all(mbr))//开始擦除数据
{
if(!force)
{
mbr->lockflag = SUNXI_UNLOCK;
}
else
{
mbr->lockflag = SUNXI_NOLOCK;
}
}
else
{
strcpy(info_p, "system cant erase parts");
printf("%s\n", info_p);
return -5;
}
}
}
else
{
strcpy(info_p, "the requst is invalid");
printf("%s\n", info_p);
return -6;
}
tmp_mbr = mbr;
tmp_buffer = buffer;
for(i=0;i<SUNXI_MBR_COPY_NUM;i++)
{
tmp_mbr->lockflag = mbr->lockflag;
crc_cal = crc32(0, (const unsigned char *)tmp_buffer + 4, SUNXI_MBR_SIZE-4);
*(unsigned int *)tmp_buffer = crc_cal;
tmp_buffer += SUNXI_MBR_SIZE;
tmp_mbr ++;
}
if(sunxi_flash_write(0, SUNXI_MBR_COPY_NUM * SUNXI_MBR_SIZE/512, buffer) != (SUNXI_MBR_COPY_NUM * SUNXI_MBR_SIZE/512))
{
strcpy(info_p, "sunxi oem operation fail, cant set oem flag");
printf("%s\n", info_p);
return -7;
}
sunxi_partition_refresh(buffer, SUNXI_MBR_SIZE);
gd->lockflag = mbr->lockflag;
return 0;
}
#else /* CONFIG_OPENSSL */
#define SUNXI_SIGN_READ_MAX (1024 * 1024)
#include <sunxi_openssl.h>
#include <sunxi_debug.h>
#include <sunxi_board.h>
#include "../fs/aw_fs/ff.h"
#include <openssl/sha.h>
#include <openssl/rsa.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/bn.h>
#include <openssl/pem.h>
static FILE sign_file;
#define SUNXI_SIGN_READ_MAX (1024 * 1024)
/*
************************************************************************************************************
*
* function
*
* name :
*
* parmeters :
*
* return :
*
* note :
*
*
************************************************************************************************************
*/
int __probe_sign_file(unsigned char *partition_name, char *sign_buffer)
{
unsigned char file_name[32];
int ret;
int index;
uint rbytes;
memset(file_name, 0, 32);
strcpy((char *)file_name, (char *)partition_name);
index = strlen((const char *)file_name);
file_name[index++] = '.';
file_name[index++] = 's';
file_name[index++] = 'i';
file_name[index++] = 'g';
ret = f_open (&sign_file, (const TCHAR *)file_name, FA_OPEN_EXISTING | FA_READ );
if(ret)
{
printf("validata err: open sign file %s error\n", file_name);
return -1;
}
f_read(&sign_file, sign_buffer, 256, &rbytes);
//公钥解密rsa
f_close(&sign_file);
//sunxi_dump(sign_buffer, 256);
return 0;
}
/*
************************************************************************************************************
*
* function
*
* name :
*
* parmeters :
*
* return :
*
* note :
*
*
************************************************************************************************************
*/
static int __calculate_for_bootimg_format(char *data_buffer, char *hash_buffer)
{
SHA256_CTX ctx;
memset(hash_buffer, 0, SHA256_DIGEST_LENGTH);
//计算sha256
SHA256_Init(&ctx);
SHA256_Update(&ctx, (u_int8_t *)data_buffer, sizeof(struct fastboot_boot_img_hdr));
//sunxi_dump(data_buffer, sizeof(struct fastboot_boot_img_hdr));
SHA256_Update(&ctx, (u_int8_t *)(data_buffer + CFG_FASTBOOT_MKBOOTIMAGE_PAGE_SIZE), sizeof(struct image_header) + 512);
//sunxi_dump(data_buffer + CFG_FASTBOOT_MKBOOTIMAGE_PAGE_SIZE, sizeof(struct image_header) + 512);
SHA256_Final((unsigned char *)hash_buffer, &ctx);
if(hash_buffer[0] >= 0xe0)
hash_buffer[0] = 0xcc;
//sunxi_dump(hash_buffer, 256);
return 0;
}
/*
************************************************************************************************************
*
* function
*
* name :
*
* parmeters :
*
* return :
*
* note :
*
*
************************************************************************************************************
*/
static int __calculate_for_sparse_format(char *data_buffer, char *hash_buffer)
{
char *tmp_buffer = data_buffer + CFG_SUPER_BLOCK_SECTOR * 512;
struct ext4_super_block *sblock;
SHA256_CTX ctx;
unsigned int data_len;
sblock = (struct ext4_super_block *)tmp_buffer;
sblock->s_mtime = CFG_SUPER_BLOCK_STAMP_VALUE;
sblock->s_mnt_count = CFG_SUPER_BLOCK_STAMP_VALUE & 0xffff;
memset(sblock->s_last_mounted, 0, 64);
//计算sha256
data_len = (unsigned int)&(((struct ext4_super_block *)0)->s_snapshot_list);
SHA256_Init(&ctx);
SHA256_Update(&ctx, (u_int8_t *)tmp_buffer, data_len);
SHA256_Final((unsigned char *)hash_buffer, &ctx);
if(hash_buffer[0] >= 0xe0)
hash_buffer[0] = 0xcc;
//sunxi_dump(hash_buffer, 256);
return 0;
}
/*
************************************************************************************************************
*
* function
*
* name :
*
* parmeters :
*
* return :
*
* note :
*
*
************************************************************************************************************
*/
static int __validata_verify(sunxi_partition *partition)
{
int ret;
char *data_buffer;
char sign_buffer[256];
char hash1_buffer[512];
char hash2_buffer[512];
if( (partition->sig_verify != 0x8000) && (partition->sig_verify != 0x8001) )
{
printf("the part is not need to verify signature\n");
return 0;
}
data_buffer = malloc(SUNXI_SIGN_READ_MAX);
memset(data_buffer, 0, SUNXI_SIGN_READ_MAX);
if(!sunxi_flash_read(partition->addrlo, SUNXI_SIGN_READ_MAX/512, data_buffer))
{
printf("validata err: read partition %s err\n", partition->name);
free(data_buffer);
return -1;
}
memset(hash1_buffer, 0, 512);
if(partition->sig_verify == 0x8000)
{
ret = __calculate_for_bootimg_format(data_buffer, hash1_buffer);
}
else
{
ret = __calculate_for_sparse_format(data_buffer, hash1_buffer);
}
//获取分区对应的签名文件
memset(sign_buffer, 0, SHA256_DIGEST_LENGTH);
memset(hash2_buffer, 0, 512);
if(__probe_sign_file(partition->name, sign_buffer))
{
free(data_buffer);
return -1;
}
ret = sunxi_rsa_publickey_decrypt(sign_buffer, hash2_buffer, 256, "0:public.pem");
if(ret < 0)
{
free(data_buffer);
printf("validata err: when public decrypt %s\n", partition->name);
return -1;
}
if(hash2_buffer[0] >= 0xe0)
hash2_buffer[0] = 0xcc;
//printf("\n\n");
//sunxi_dump(hash2_buffer, 256);
//比较两个值
if(memcmp(hash1_buffer, hash2_buffer, 256))
{
free(data_buffer);
printf("validate err: when compare the signature on %s\n", partition->name);
return -1;
}
free(data_buffer);
printf("validate ok: validate the signature on %s\n", partition->name);
return 0;
}
/*
************************************************************************************************************
*
* function
*
* name :
*
* parmeters :
*
* return :
*
* note :
*
*
************************************************************************************************************
*/
int sunxi_oem_op_lock(int request_flag, char *info, int force)
{
return -1;
}
/*
************************************************************************************************************
*
* function
*
* name :
*
* parmeters :
*
* return :
*
* note :
*
*
************************************************************************************************************
*/
int do_sunxi_boot_signature(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
int ret;
int i;
sunxi_mbr_t *mbr = (sunxi_mbr_t *)sunxi_partition_fetch_mbr();
FATFS openssl_mount;
if(mbr == NULL)
{
puts("sunxi signature fail: unable to get the signature table\n");
return -1;
}
if(gd->lockflag == SUNXI_NOLOCK)
{
puts("sunxi validata: no signature\n");
return 0;
}
if(gd->lockflag == SUNXI_UNLOCK)
{
puts("sunxi validata: signature abandon\n");
setenv("signature", "abandon");
return 0;
}
arm_neon_init();
f_mount_ex(0, &openssl_mount, 0);
for(i=0;i<mbr->PartCount;i++)
{
if((mbr->array[i].sig_verify & 0x8000) == 0x8000)
{
ret = __validata_verify(&mbr->array[i]);
if(ret < 0)
{
printf("sunxi signature fail: the part %s signature is not passed\n", mbr->array[i].name);
ret = signature_erase_all(mbr);
if(ret < 0)
{
printf("sunxi signature fail: erase part fail\n");
f_mount(0, NULL, NULL);
return -1;
}
if(gd->lockflag == SUNXI_LOCKING)
{
puts("signature failed\n");
setenv("signature", "failed");
}
else if(gd->lockflag == SUNXI_RELOCKING)
{
puts("signature relock_failed\n");
setenv("signature", "relock_failed");
}
f_mount(0, NULL, NULL);
return 0;
}
}
}
if(gd->lockflag == SUNXI_LOCKING)
{
puts("signature pass\n");
setenv("signature", "pass");
}
else if(gd->lockflag == SUNXI_RELOCKING)
{
puts("signature relock_pass\n");
setenv("signature", "relock_pass");
}
f_mount(0, NULL, NULL);
return 0;
}
U_BOOT_CMD(
sunxi_boot_signature, 16, 0, do_sunxi_boot_signature,
"do validata",
"[public key name]"
);
#endif /* CONFIG_OPENSSL */
/*
************************************************************************************************************
*
* function
*
* name :
*
* parmeters :
*
* return :
*
* note :
*
*
************************************************************************************************************
*/
static int __signature_erase_part(uint sector_start, uint nsector, void *erase_buffer, uint buffer_sectors)
{
uint tmp_nsectors, tmp_start;
tmp_start = sector_start;
tmp_nsectors = nsector;
while(tmp_nsectors>=buffer_sectors)
{
if(sunxi_flash_write(tmp_start, buffer_sectors, erase_buffer) != buffer_sectors)
{
printf("signature err: unable to erase part when signature fail\n");
return -1;
}
tmp_start += buffer_sectors;
tmp_nsectors -= buffer_sectors;
}
if(tmp_nsectors)
{
if(sunxi_flash_write(tmp_start, tmp_nsectors, erase_buffer) != tmp_nsectors)
{
printf("signature err: unable to erase part when signature fail\n");
return -1;
}
}
return 0;
}
/*
************************************************************************************************************
*
* function
*
* name :
*
* parmeters :
*
* return :
*
* note : 4 steps: 1, erase cache; 2 erase data; 3 erase private; 4 erase drm; 5 erase UDISK
*
*
************************************************************************************************************
*/
int signature_erase_all(sunxi_mbr_t *mbr)
{
int i;
uint part_start, part_sectors;
void *buffer;
buffer = malloc(4 * 1024 * 1024);
if(!buffer)
{
puts("sunxi signature fail: unable to malloc memory to erase parts\n");
return -1;
}
puts("ready to erase dedicated parts\n");
memset(buffer, 0xff, 4 * 1024 * 1024);
for(i=0;i<mbr->PartCount;i++)
{
printf("try part %s\n", mbr->array[i].name);
if(mbr->array[i].sig_erase == 0x8000)
{
if(!uboot_spare_head.boot_data.storage_type)
{
NAND_build_all_partition();
}
part_start = mbr->array[i].addrlo;
//part_sectors = mbr->array[i].lenlo;
part_sectors = 16 * 1024 * 1024/512;
printf("erase part %s ...\n", mbr->array[i].name);
if(__signature_erase_part(part_start, part_sectors, buffer, 4 * 1024 * 1024/512))
{
printf("erase part %s fail\n", mbr->array[i].name);
free(buffer);
return -1;
}
printf("erase part %s ok\n", mbr->array[i].name);
}
}
free(buffer);
return 0;
}