tools: rockchip: support hostprogs for pack tools

- include: boot_merge/trust_merge/loaderimage/resource_tool/checksum;
- porting from rkdevelop and base on commit 8fd1d8f
  (resource: get resource primary from boot partition);
- clean generated binary file when execute clean command;

Change-Id: I41c1893c2da0a0f25c2d39dbbd933f89fbb04948
Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
This commit is contained in:
Joseph Chen 2018-09-26 18:30:20 +08:00 committed by Jianhong Chen
parent bbef4bcaa1
commit 23ba6841cc
15 changed files with 5303 additions and 7 deletions

15
make.sh
View File

@ -34,14 +34,16 @@ TOOLCHAIN_ARM32=../prebuilts/gcc/linux-x86/arm/gcc-linaro-6.3.1-2017.05-x86_64_a
TOOLCHAIN_ARM64=../prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin
########################################### User not touch #############################################
BIN_PATH_FIXUP="--replace tools/rk_tools/ ./"
RKTOOLS=./tools
# Declare global INI file searching index name for every chip, update in select_chip_info()
RKCHIP=
RKCHIP_LABEL=
RKCHIP_LOADER=
RKCHIP_TRUST=
# Declare global rkbin RKTOOLS and rkbin repository path, updated in prepare()
RKTOOLS=
# Declare rkbin repository path, updated in prepare()
RKBIN=
# Declare global toolchain path for CROSS_COMPILE, updated in select_toolchain()
@ -170,11 +172,10 @@ prepare()
;;
esac
# Initialize RKBIN and RKTOOLS
# Initialize RKBIN
if [ -d ${RKBIN_TOOLS} ]; then
absolute_path=$(cd `dirname ${RKBIN_TOOLS}`; pwd)
RKBIN=${absolute_path}
RKTOOLS=${absolute_path}/tools
else
echo
echo "Can't find '../rkbin/' repository, please download it before pack image!"
@ -415,12 +416,12 @@ pack_loader_image()
for ini in $files
do
if [ -f "$ini" ]; then
${RKTOOLS}/boot_merger --replace tools/rk_tools/ ./ $ini
${RKTOOLS}/boot_merger ${BIN_PATH_FIXUP} $ini
echo "pack loader okay! Input: $ini"
fi
done
else
${RKTOOLS}/boot_merger --replace tools/rk_tools/ ./ ${RKBIN}/RKBOOT/${RKCHIP_LOADER}MINIALL.ini
${RKTOOLS}/boot_merger ${BIN_PATH_FIXUP} ${RKBIN}/RKBOOT/${RKCHIP_LOADER}MINIALL.ini
echo "pack loader okay! Input: ${RKBIN}/RKBOOT/${RKCHIP_LOADER}MINIALL.ini"
fi
@ -439,7 +440,7 @@ pack_trust_image()
fi
cd ${RKBIN}
${RKTOOLS}/trust_merger ${PLATFORM_SHA} ${PLATFORM_RSA} ${PLATFORM_TRUST_IMG_SIZE} --replace tools/rk_tools/ ./ ${RKBIN}/RKTRUST/${RKCHIP_TRUST}${PLATFORM_AARCH32}TRUST.ini
${RKTOOLS}/trust_merger ${PLATFORM_SHA} ${PLATFORM_RSA} ${PLATFORM_TRUST_IMG_SIZE} ${BIN_PATH_FIXUP} ${RKBIN}/RKTRUST/${RKCHIP_TRUST}${PLATFORM_AARCH32}TRUST.ini
cd - && mv ${RKBIN}/trust.img ./trust.img
echo "pack trust okay! Input: ${RKBIN}/RKTRUST/${RKCHIP_TRUST}${PLATFORM_AARCH32}TRUST.ini"

5
tools/.gitignore vendored
View File

@ -28,3 +28,8 @@
/sunxi-spl-image-builder
/ubsha1
/xway-swap-bytes
/trust_merger
/boot_merger
/loaderimage
/checksum
/resource_tool

View File

@ -57,6 +57,21 @@ mkenvimage-objs := mkenvimage.o os_support.o lib/crc32.o
hostprogs-y += dumpimage mkimage
hostprogs-$(CONFIG_FIT_SIGNATURE) += fit_info fit_check_sign
# Rockchip pack tools
ifdef CONFIG_ARCH_ROCKCHIP
hostprogs-y += boot_merger
hostprogs-y += trust_merger
hostprogs-y += loaderimage
hostprogs-y += resource_tool
hostprogs-y += checksum
boot_merger-objs := rockchip/boot_merger.o rockchip/sha2.o lib/sha256.o
trust_merger-objs := rockchip/trust_merger.o rockchip/sha2.o lib/sha256.o
loaderimage-objs := rockchip/loaderimage.o rockchip/sha.o lib/sha256.o rockchip/crc32_rk.o
resource_tool-objs := rockchip/resource_tool.o
checksum-objs := rockchip/checksum.o rockchip/crc32_rk.o
endif
FIT_SIG_OBJS-$(CONFIG_FIT_SIGNATURE) := common/image-sig.o
# The following files are synced with upstream DTC.

1061
tools/rockchip/boot_merger.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,201 @@
/*
* (C) Copyright 2008-2015 Fuzhou Rockchip Electronics Co., Ltd
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef BOOT_MERGER_H
#define BOOT_MERGER_H
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <stdbool.h>
/* #define DEBUG */
extern bool gDebug;
#define LOGE(fmt, args...) fprintf(stderr, "E: [%s] "fmt, __func__, ##args)
#define LOGD(fmt, args...) do {\
if (gDebug) \
fprintf(stderr, "W: [%s] "fmt, __func__, ##args); \
} while (0)
#define SCANF_EAT(in) fscanf(in, "%*[ \r\n\t/]")//, gEat)
#define MAX_LINE_LEN 256
extern char gEat[MAX_LINE_LEN];
typedef char line_t[MAX_LINE_LEN];
#define DEF_CONFIG_FILE "CONFIG.ini"
#define DEF_MAJOR 0
#define DEF_MINOR 3
#define DEF_CHIP "RK30"
#define DEF_CODE471_NUM 1
#define DEF_CODE472_NUM 1
#define DEF_CODE471_SLEEP 0
#define DEF_CODE472_SLEEP 0
#define DEF_CODE471_PATH "30_LPDDR2_300MHz_DDR3_300MHz.bin"
#define DEF_CODE472_PATH "rk30usbplug.bin"
#define DEF_LOADER_NUM 2
#define DEF_LOADER0 "FlashData"
#define DEF_LOADER0_PATH "30_LPDDR2_300MHz_DDR3_300MHz.bin"
#define DEF_LOADER1 "FlashBoot"
#define DEF_LOADER1_PATH "../../u-boot.bin"
#define DEF_OUT_PATH "../../RK30xxLoader_uboot.bin"
#define OUT_SUBFIX ".bin"
#define SEC_CHIP "[CHIP_NAME]"
#define SEC_VERSION "[VERSION]"
#define SEC_471 "[CODE471_OPTION]"
#define SEC_472 "[CODE472_OPTION]"
#define SEC_LOADER "[LOADER_OPTION]"
#define SEC_OUT "[OUTPUT]"
#define OPT_NAME "NAME"
#define OPT_MAJOR "MAJOR"
#define OPT_MINOR "MINOR"
#define OPT_NUM "NUM"
#define OPT_LOADER_NUM "LOADERCOUNT"
#define OPT_PATH "Path"
#define OPT_SLEEP "Sleep"
#define OPT_LOADER_NAME "LOADER"
#define OPT_OUT_PATH "PATH"
typedef struct {
char name[MAX_LINE_LEN];
char path[MAX_LINE_LEN];
} name_entry;
typedef struct {
int major;
int minor;
char chip[MAX_LINE_LEN];
int code471Sleep;
int code472Sleep;
int code471Num;
int code472Num;
line_t* code471Path;
line_t* code472Path;
int loaderNum;
name_entry* loader;
char outPath[MAX_LINE_LEN];
} options;
#define TAG 0x544F4F42
#define MERGER_VERSION 0x01030000
#define SMALL_PACKET 512
#define MAX_NAME_LEN 20
#define MAX_MERGE_SIZE (512 << 10)
#define SEC_CHIP_TYPES "[CHIP_TYPES]"
#define CHIP_RK28 "RK28"
#define CHIP_RK281X "RK281X"
#define CHIP_RKPANDA "RKPANDA"
#define CHIP_RK27 "RK27"
#define CHIP_RKNANO "RKNANO"
#define CHIP_RKSMART "RKSMART"
#define CHIP_RKCROWN "RKCROWN"
#define CHIP_RKCAYMAN "RKCAYMAN"
#define CHIP_RK29 "RK29"
#define CHIP_RK292X "RK292X"
#define CHIP_RK30 "RK30"
#define CHIP_RK30B "RK30B"
#define CHIP_RK31 "RK31"
#define CHIP_RK32 "RK32"
typedef enum {
RKNONE_DEVICE =0,
RK27_DEVICE =0x10,
RKCAYMAN_DEVICE =0x11,
RK28_DEVICE =0x20,
RK281X_DEVICE =0x21,
RKPANDA_DEVICE =0x22,
RKNANO_DEVICE =0x30,
RKSMART_DEVICE =0x31,
RKCROWN_DEVICE =0x40,
RK29_DEVICE =0x50,
RK292X_DEVICE =0x51,
RK30_DEVICE =0x60,
RK30B_DEVICE =0x61,
RK31_DEVICE =0x70,
RK32_DEVICE =0x80
} rk_chip_type;
typedef enum {
ENTRY_471 =1,
ENTRY_472 =2,
ENTRY_LOADER =4,
} rk_entry_type;
#pragma pack(1)
typedef struct {
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t minute;
uint8_t second;
} rk_time;
#define BOOT_RESERVED_SIZE 57
typedef struct {
uint32_t tag;
uint16_t size;
uint32_t version;
uint32_t mergerVersion;
rk_time releaseTime;
uint32_t chipType;
uint8_t code471Num;
uint32_t code471Offset;
uint8_t code471Size;
uint8_t code472Num;
uint32_t code472Offset;
uint8_t code472Size;
uint8_t loaderNum;
uint32_t loaderOffset;
uint8_t loaderSize;
uint8_t signFlag;
uint8_t rc4Flag;
uint8_t reserved[BOOT_RESERVED_SIZE];
} rk_boot_header;
typedef struct {
uint8_t size;
rk_entry_type type;
uint16_t name[MAX_NAME_LEN];
uint32_t dataOffset;
uint32_t dataSize;
uint32_t dataDelay;
} rk_boot_entry;
#pragma pack()
#define OPT_VERBOSE "--verbose"
#define OPT_HELP "--help"
#define OPT_VERSION "--version"
#define OPT_MERGE "--pack"
#define OPT_UNPACK "--unpack"
#define OPT_SUBFIX "--subfix"
#define OPT_REPLACE "--replace"
#define OPT_SIZE "--size"
#define OPT_CHIP "-c"
#define OPT_471 "-1"
#define OPT_472 "-2"
#define OPT_DATA "-d"
#define OPT_BOOT "-b"
#define OPT_OUT "-o"
#define VERSION "2013-8-12 14:27:23"
#endif/* BOOT_MERGER_H */

118
tools/rockchip/checksum.c Normal file
View File

@ -0,0 +1,118 @@
/*
* (C) Copyright 2008-2015 Fuzhou Rockchip Electronics Co., Ltd
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <sys/stat.h>
#include <stdio.h>
#include <stdint.h>
#include <u-boot/crc.h>
extern uint32_t crc32_rk(uint32_t, const unsigned char *, uint32_t);
#define SZ_4M 0x00400000
#define SZ_16M 0x01000000
#define SZ_32M 0x02000000
#define RK_BLK_SIZE 512
void usage(const char *prog)
{
fprintf(stderr, "Usage: %s <image>\n", prog);
}
/*
* Neutralize little endians.
*/
uint32_t le_uint32(uint32_t x)
{
uint32_t val;
uint8_t *p = (uint8_t *)(&x);
val = (*p++ & 0xff) << 0;
val |= (*p++ & 0xff) << 8;
val |= (*p++ & 0xff) << 16;
val |= (*p & 0xff) << 24;
return val;
}
int main(int argc, char *argv[])
{
FILE *fp;
uint32_t blocks = 0;
fp = fopen(argv[1], "rb");
if (!fp) {
perror(argv[1]);
return -1;
}
struct stat sb;
int ret = stat(argv[1], &sb);
if (!fp || ret) {
perror(argv[1]);
return -1;
}
blocks = sb.st_size / RK_BLK_SIZE;
if (sb.st_size % RK_BLK_SIZE) {
printf("size should align %d", RK_BLK_SIZE);
return -1;
}
printf("totle blocks:0x%08x\n", blocks);
#ifdef CONFIG_FASTBOOT_TRANSFER_BUFFER_SIZE_EACH
uint32_t buf_size = CONFIG_FASTBOOT_TRANSFER_BUFFER_SIZE_EACH;
#else
uint32_t buf_size = 16 * 1024 * 1024;
#endif
void *buf = malloc(buf_size);
uint16_t buf_blocks = buf_size / RK_BLK_SIZE;
uint32_t offset = 0;
#ifndef CONFIG_QUICK_CHECKSUM
uint32_t *crc_array = (uint32_t *)malloc(buf_size);
uint16_t crc_counts = 0;
uint32_t checksum = 0;
#else
long long unsigned int checksum = 0;
#endif
while (blocks > 0) {
uint16_t read_blocks = blocks > buf_blocks ? buf_blocks : blocks;
if (fread(buf, read_blocks * RK_BLK_SIZE, 1, fp) != 1) {
printf("read failed, offset:0x%08x, blocks:0x%08x\n", offset,
read_blocks);
return -1;
}
offset += read_blocks;
blocks -= read_blocks;
#ifndef CONFIG_QUICK_CHECKSUM
crc_array[crc_counts] = crc32_rk(0, buf, read_blocks * RK_BLK_SIZE);
printf("offset:0x%08x, blocks:0x%08x, crc:0x%08x\n", offset, read_blocks,
crc_array[crc_counts]);
crc_counts++;
#else
int i = 0;
uint32_t *data = (uint32_t *)buf;
for (i = 0; i<read_blocks *RK_BLK_SIZE>> 2; i++)
checksum += le_uint32(data[i]);
printf("offset:0x%08x, blocks:0x%08x, checksum:0x%016llx\n", offset,
read_blocks, checksum);
#endif
}
#ifndef CONFIG_QUICK_CHECKSUM
/* 3:compute whole checksum */
checksum = (crc_counts == 1) ? crc_array[0]
: crc32_rk(0, (unsigned char *)crc_array,
sizeof(uint32_t) * crc_counts);
printf("whole checksum:0x%08x\n", checksum);
free(crc_array);
#else
printf("whole checksum:0x%016llx\n", checksum);
#endif
free(buf);
fclose(fp);
return 0;
}

101
tools/rockchip/crc32_rk.c Normal file
View File

@ -0,0 +1,101 @@
/*
* (C) Copyright 2008-2015 Fuzhou Rockchip Electronics Co., Ltd
* Peter, Software Engineering, <superpeter.cai@gmail.com>.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifdef USE_HOSTCC
#include <arpa/inet.h>
#else
#include <common.h>
#endif
#include <compiler.h>
#include <u-boot/crc.h>
#include "u-boot/zlib.h"
#define tole(x) cpu_to_le32(x)
/* ========================================================================
* Table of CRC-32's of all single-byte values (made by make_crc_table)
*/
static const uint32_t crc_table[256] = {
tole(0x00000000L), tole(0x04c10db7L), tole(0x09821b6eL), tole(0x0d4316d9L),
tole(0x130436dcL), tole(0x17c53b6bL), tole(0x1a862db2L), tole(0x1e472005L),
tole(0x26086db8L), tole(0x22c9600fL), tole(0x2f8a76d6L), tole(0x2b4b7b61L),
tole(0x350c5b64L), tole(0x31cd56d3L), tole(0x3c8e400aL), tole(0x384f4dbdL),
tole(0x4c10db70L), tole(0x48d1d6c7L), tole(0x4592c01eL), tole(0x4153cda9L),
tole(0x5f14edacL), tole(0x5bd5e01bL), tole(0x5696f6c2L), tole(0x5257fb75L),
tole(0x6a18b6c8L), tole(0x6ed9bb7fL), tole(0x639aada6L), tole(0x675ba011L),
tole(0x791c8014L), tole(0x7ddd8da3L), tole(0x709e9b7aL), tole(0x745f96cdL),
tole(0x9821b6e0L), tole(0x9ce0bb57L), tole(0x91a3ad8eL), tole(0x9562a039L),
tole(0x8b25803cL), tole(0x8fe48d8bL), tole(0x82a79b52L), tole(0x866696e5L),
tole(0xbe29db58L), tole(0xbae8d6efL), tole(0xb7abc036L), tole(0xb36acd81L),
tole(0xad2ded84L), tole(0xa9ece033L), tole(0xa4aff6eaL), tole(0xa06efb5dL),
tole(0xd4316d90L), tole(0xd0f06027L), tole(0xddb376feL), tole(0xd9727b49L),
tole(0xc7355b4cL), tole(0xc3f456fbL), tole(0xceb74022L), tole(0xca764d95L),
tole(0xf2390028L), tole(0xf6f80d9fL), tole(0xfbbb1b46L), tole(0xff7a16f1L),
tole(0xe13d36f4L), tole(0xe5fc3b43L), tole(0xe8bf2d9aL), tole(0xec7e202dL),
tole(0x34826077L), tole(0x30436dc0L), tole(0x3d007b19L), tole(0x39c176aeL),
tole(0x278656abL), tole(0x23475b1cL), tole(0x2e044dc5L), tole(0x2ac54072L),
tole(0x128a0dcfL), tole(0x164b0078L), tole(0x1b0816a1L), tole(0x1fc91b16L),
tole(0x018e3b13L), tole(0x054f36a4L), tole(0x080c207dL), tole(0x0ccd2dcaL),
tole(0x7892bb07L), tole(0x7c53b6b0L), tole(0x7110a069L), tole(0x75d1addeL),
tole(0x6b968ddbL), tole(0x6f57806cL), tole(0x621496b5L), tole(0x66d59b02L),
tole(0x5e9ad6bfL), tole(0x5a5bdb08L), tole(0x5718cdd1L), tole(0x53d9c066L),
tole(0x4d9ee063L), tole(0x495fedd4L), tole(0x441cfb0dL), tole(0x40ddf6baL),
tole(0xaca3d697L), tole(0xa862db20L), tole(0xa521cdf9L), tole(0xa1e0c04eL),
tole(0xbfa7e04bL), tole(0xbb66edfcL), tole(0xb625fb25L), tole(0xb2e4f692L),
tole(0x8aabbb2fL), tole(0x8e6ab698L), tole(0x8329a041L), tole(0x87e8adf6L),
tole(0x99af8df3L), tole(0x9d6e8044L), tole(0x902d969dL), tole(0x94ec9b2aL),
tole(0xe0b30de7L), tole(0xe4720050L), tole(0xe9311689L), tole(0xedf01b3eL),
tole(0xf3b73b3bL), tole(0xf776368cL), tole(0xfa352055L), tole(0xfef42de2L),
tole(0xc6bb605fL), tole(0xc27a6de8L), tole(0xcf397b31L), tole(0xcbf87686L),
tole(0xd5bf5683L), tole(0xd17e5b34L), tole(0xdc3d4dedL), tole(0xd8fc405aL),
tole(0x6904c0eeL), tole(0x6dc5cd59L), tole(0x6086db80L), tole(0x6447d637L),
tole(0x7a00f632L), tole(0x7ec1fb85L), tole(0x7382ed5cL), tole(0x7743e0ebL),
tole(0x4f0cad56L), tole(0x4bcda0e1L), tole(0x468eb638L), tole(0x424fbb8fL),
tole(0x5c089b8aL), tole(0x58c9963dL), tole(0x558a80e4L), tole(0x514b8d53L),
tole(0x25141b9eL), tole(0x21d51629L), tole(0x2c9600f0L), tole(0x28570d47L),
tole(0x36102d42L), tole(0x32d120f5L), tole(0x3f92362cL), tole(0x3b533b9bL),
tole(0x031c7626L), tole(0x07dd7b91L), tole(0x0a9e6d48L), tole(0x0e5f60ffL),
tole(0x101840faL), tole(0x14d94d4dL), tole(0x199a5b94L), tole(0x1d5b5623L),
tole(0xf125760eL), tole(0xf5e47bb9L), tole(0xf8a76d60L), tole(0xfc6660d7L),
tole(0xe22140d2L), tole(0xe6e04d65L), tole(0xeba35bbcL), tole(0xef62560bL),
tole(0xd72d1bb6L), tole(0xd3ec1601L), tole(0xdeaf00d8L), tole(0xda6e0d6fL),
tole(0xc4292d6aL), tole(0xc0e820ddL), tole(0xcdab3604L), tole(0xc96a3bb3L),
tole(0xbd35ad7eL), tole(0xb9f4a0c9L), tole(0xb4b7b610L), tole(0xb076bba7L),
tole(0xae319ba2L), tole(0xaaf09615L), tole(0xa7b380ccL), tole(0xa3728d7bL),
tole(0x9b3dc0c6L), tole(0x9ffccd71L), tole(0x92bfdba8L), tole(0x967ed61fL),
tole(0x8839f61aL), tole(0x8cf8fbadL), tole(0x81bbed74L), tole(0x857ae0c3L),
tole(0x5d86a099L), tole(0x5947ad2eL), tole(0x5404bbf7L), tole(0x50c5b640L),
tole(0x4e829645L), tole(0x4a439bf2L), tole(0x47008d2bL), tole(0x43c1809cL),
tole(0x7b8ecd21L), tole(0x7f4fc096L), tole(0x720cd64fL), tole(0x76cddbf8L),
tole(0x688afbfdL), tole(0x6c4bf64aL), tole(0x6108e093L), tole(0x65c9ed24L),
tole(0x11967be9L), tole(0x1557765eL), tole(0x18146087L), tole(0x1cd56d30L),
tole(0x02924d35L), tole(0x06534082L), tole(0x0b10565bL), tole(0x0fd15becL),
tole(0x379e1651L), tole(0x335f1be6L), tole(0x3e1c0d3fL), tole(0x3add0088L),
tole(0x249a208dL), tole(0x205b2d3aL), tole(0x2d183be3L), tole(0x29d93654L),
tole(0xc5a71679L), tole(0xc1661bceL), tole(0xcc250d17L), tole(0xc8e400a0L),
tole(0xd6a320a5L), tole(0xd2622d12L), tole(0xdf213bcbL), tole(0xdbe0367cL),
tole(0xe3af7bc1L), tole(0xe76e7676L), tole(0xea2d60afL), tole(0xeeec6d18L),
tole(0xf0ab4d1dL), tole(0xf46a40aaL), tole(0xf9295673L), tole(0xfde85bc4L),
tole(0x89b7cd09L), tole(0x8d76c0beL), tole(0x8035d667L), tole(0x84f4dbd0L),
tole(0x9ab3fbd5L), tole(0x9e72f662L), tole(0x9331e0bbL), tole(0x97f0ed0cL),
tole(0xafbfa0b1L), tole(0xab7ead06L), tole(0xa63dbbdfL), tole(0xa2fcb668L),
tole(0xbcbb966dL), tole(0xb87a9bdaL), tole(0xb5398d03L), tole(0xb1f880b4L)
};
/* ========================================================================= */
#define DO_CRC(x) crc = tab[((crc >> 24) ^ (x)) & 255] ^ (crc << 8)
uint32_t crc32_rk(uint32_t crc, const unsigned char *s, uint32_t len)
{
const uint32_t *tab;
tab = crc_table;
crc = cpu_to_le32(crc);
do {
DO_CRC(*s++);
} while (--len);
return le32_to_cpu(crc);
}
#undef DO_CRC

View File

@ -0,0 +1,366 @@
/*
* (C) Copyright 2008-2015 Fuzhou Rockchip Electronics Co., Ltd
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include "compiler.h"
#include <version.h>
#include "sha.h"
#include <u-boot/sha256.h>
#include <u-boot/crc.h>
#include <linux/sizes.h>
#include <linux/kconfig.h>
#include <config.h>
extern uint32_t crc32_rk(uint32_t, const unsigned char *, uint32_t);
#define OPT_PACK "--pack"
#define OPT_UNPACK "--unpack"
#define OPT_UBOOT "--uboot"
#define OPT_TRUSTOS "--trustos"
#define OPT_SIZE "--size"
#define OPT_VERSION "--version"
#define OPT_INFO "--info"
/* pack or unpack */
#define MODE_PACK 0
#define MODE_UNPACK 1
#define MODE_INFO 2
#define CONFIG_SECUREBOOT_SHA256
/* image type */
#define IMAGE_UBOOT 0
#define IMAGE_TRUST 1
/* magic and hash size */
#define LOADER_MAGIC_SIZE 8
#define LOADER_HASH_SIZE 32
/* uboot image config */
#define UBOOT_NAME "uboot"
#ifdef CONFIG_RK_NVME_BOOT_EN
#define UBOOT_NUM 2
#define UBOOT_MAX_SIZE 512 * 1024
#else
#define UBOOT_NUM 4
#define UBOOT_MAX_SIZE 1024 * 1024
#endif
#define UBOOT_VERSION_STRING \
U_BOOT_VERSION " (" U_BOOT_DATE " - " U_BOOT_TIME ")" CONFIG_IDENT_STRING
#define RK_UBOOT_MAGIC "LOADER "
#define RK_UBOOT_RUNNING_ADDR CONFIG_SYS_TEXT_BASE
/* trust image config */
#define TRUST_NAME "trustos"
#define TRUST_NUM 4
#define TRUST_MAX_SIZE 1024 * 1024
#define TRUST_VERSION_STRING "Trust os"
#define RK_TRUST_MAGIC "TOS "
#define RK_TRUST_RUNNING_ADDR (CONFIG_SYS_TEXT_BASE + SZ_128M + SZ_4M)
typedef struct tag_second_loader_hdr {
uint8_t magic[LOADER_MAGIC_SIZE]; /* magic */
uint32_t version;
uint32_t reserved0;
uint32_t loader_load_addr; /* physical load addr */
uint32_t loader_load_size; /* size in bytes */
uint32_t crc32; /* crc32 */
uint32_t hash_len; /* 20 or 32 , 0 is no hash */
uint8_t hash[LOADER_HASH_SIZE]; /* sha */
uint8_t reserved[1024 - 32 - 32];
uint32_t signTag; /* 0x4E474953 */
uint32_t signlen; /* maybe 128 or 256 */
uint8_t rsaHash[256]; /* maybe 128 or 256, using max size 256 */
uint8_t reserved2[2048 - 1024 - 256 - 8];
} second_loader_hdr;
void usage(const char *prog)
{
fprintf(stderr, "Usage: %s [--pack|--unpack] [--uboot|--trustos]\
file_in "
"file_out [load_addr] [--size] [size number]\
[--version] "
"[version] | [--info] [file]\n",
prog);
}
unsigned int str2hex(char *str)
{
int i = 0;
unsigned int value = 0;
if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X'))
str += 2;
if (*str == 'x' || *str == 'X')
str += 1;
for (i = 0; *str != '\0'; i++, ++str) {
if (*str >= '0' && *str <= '9')
value = value * 16 + *str - '0';
else if (*str >= 'a' && *str <= 'f')
value = value * 16 + *str - 'a' + 10;
else if (*str >= 'A' && *str <= 'F')
value = value * 16 + *str - 'A' + 10;
else
break;
}
return value;
}
int main(int argc, char *argv[])
{
int mode = -1, image = -1;
int max_size, max_num;
int size, i;
uint32_t loader_addr, in_loader_addr = -1;
char *magic, *version, *name;
FILE *fi, *fo;
second_loader_hdr hdr;
char *buf = 0;
uint32_t in_size = 0, in_num = 0;
char *file_in = NULL, *file_out = NULL;
uint32_t curr_version = 0;
if (argc < 3) {
usage(argv[0]);
exit(EXIT_FAILURE);
}
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], OPT_PACK)) {
mode = MODE_PACK;
} else if (!strcmp(argv[i], OPT_UNPACK)) {
mode = MODE_UNPACK;
} else if (!strcmp(argv[i], OPT_UBOOT)) {
image = IMAGE_UBOOT;
file_in = argv[++i];
file_out = argv[++i];
/* detect whether loader address is delivered */
if ((argv[i + 1]) && (strncmp(argv[i + 1], "--", 2)))
in_loader_addr = str2hex(argv[++i]);
} else if (!strcmp(argv[i], OPT_TRUSTOS)) {
image = IMAGE_TRUST;
file_in = argv[++i];
file_out = argv[++i];
/* detect whether loader address is delivered */
if ((argv[i + 1]) && (strncmp(argv[i + 1], "--", 2)))
in_loader_addr = str2hex(argv[++i]);
} else if (!strcmp(argv[i], OPT_SIZE)) {
in_size = strtoul(argv[++i], NULL, 10);
/*
* Usually, it must be at 512kb align due to preloader
* detects every 512kb. But some product has critial
* flash size requirement, we have to make it small than
* 512KB.
*/
if (in_size % 64) {
usage(argv[0]);
exit(EXIT_FAILURE);
}
in_size *= 1024;
in_num = strtoul(argv[++i], NULL, 10);
} else if (!strcmp(argv[i], OPT_VERSION)) {
curr_version = strtoul(argv[++i], NULL, 10);
printf("curr_version = 0x%x\n", curr_version);
} else if (!strcmp(argv[i], OPT_INFO)) {
mode = MODE_INFO;
file_in = argv[++i];
} else {
usage(argv[0]);
exit(EXIT_FAILURE);
}
}
/* config image information */
if (image == IMAGE_UBOOT) {
name = UBOOT_NAME;
magic = RK_UBOOT_MAGIC;
version = UBOOT_VERSION_STRING;
max_size = in_size ? in_size : UBOOT_MAX_SIZE;
max_num = in_num ? in_num : UBOOT_NUM;
loader_addr =
(in_loader_addr == -1) ? RK_UBOOT_RUNNING_ADDR : in_loader_addr;
} else if (image == IMAGE_TRUST) {
name = TRUST_NAME;
magic = RK_TRUST_MAGIC;
version = TRUST_VERSION_STRING;
max_size = in_size ? in_size : TRUST_MAX_SIZE;
max_num = in_num ? in_num : TRUST_NUM;
loader_addr =
(in_loader_addr == -1) ? RK_TRUST_RUNNING_ADDR : in_loader_addr;
} else if (mode == MODE_INFO) {
} else {
exit(EXIT_FAILURE);
}
if (mode == MODE_PACK) {
buf = calloc(max_size, max_num);
if (!buf) {
perror(file_out);
exit(EXIT_FAILURE);
}
printf("\n load addr is 0x%x!\n", loader_addr);
if (!file_in || !file_out) {
usage(argv[0]);
exit(EXIT_FAILURE);
}
/* file in */
fi = fopen(file_in, "rb");
if (!fi) {
perror(file_in);
exit(EXIT_FAILURE);
}
/* file out */
fo = fopen(file_out, "wb");
if (!fo) {
perror(file_out);
exit(EXIT_FAILURE);
}
printf("pack input %s \n", file_in);
fseek(fi, 0, SEEK_END);
size = ftell(fi);
fseek(fi, 0, SEEK_SET);
printf("pack file size: %d \n", size);
if (size > max_size - sizeof(second_loader_hdr)) {
perror(file_out);
exit(EXIT_FAILURE);
}
memset(&hdr, 0, sizeof(second_loader_hdr));
memcpy((char *)hdr.magic, magic, LOADER_MAGIC_SIZE);
hdr.version = curr_version;
hdr.loader_load_addr = loader_addr;
if (!fread(buf + sizeof(second_loader_hdr), size, 1, fi))
exit(EXIT_FAILURE);
/* Aligned size to 4-byte, Rockchip HW Crypto need 4-byte align */
size = (((size + 3) >> 2) << 2);
hdr.loader_load_size = size;
hdr.crc32 = crc32_rk(
0, (const unsigned char *)buf + sizeof(second_loader_hdr), size);
printf("crc = 0x%08x\n", hdr.crc32);
#ifndef CONFIG_SECUREBOOT_SHA256
SHA_CTX ctx;
uint8_t *sha;
hdr.hash_len = (SHA_DIGEST_SIZE > LOADER_HASH_SIZE) ? LOADER_HASH_SIZE
: SHA_DIGEST_SIZE;
SHA_init(&ctx);
SHA_update(&ctx, buf + sizeof(second_loader_hdr), size);
if (hdr.version > 0)
SHA_update(&ctx, (void *)&hdr.version, 8);
SHA_update(&ctx, &hdr.loader_load_addr, sizeof(hdr.loader_load_addr));
SHA_update(&ctx, &hdr.loader_load_size, sizeof(hdr.loader_load_size));
SHA_update(&ctx, &hdr.hash_len, sizeof(hdr.hash_len));
sha = (uint8_t *)SHA_final(&ctx);
memcpy(hdr.hash, sha, hdr.hash_len);
#else
sha256_context ctx;
uint8_t hash[LOADER_HASH_SIZE];
memset(hash, 0, LOADER_HASH_SIZE);
hdr.hash_len = 32; /* sha256 */
sha256_starts(&ctx);
sha256_update(&ctx, (void *)buf + sizeof(second_loader_hdr), size);
if (hdr.version > 0)
sha256_update(&ctx, (void *)&hdr.version, 8);
sha256_update(&ctx, (void *)&hdr.loader_load_addr,
sizeof(hdr.loader_load_addr));
sha256_update(&ctx, (void *)&hdr.loader_load_size,
sizeof(hdr.loader_load_size));
sha256_update(&ctx, (void *)&hdr.hash_len, sizeof(hdr.hash_len));
sha256_finish(&ctx, hash);
memcpy(hdr.hash, hash, hdr.hash_len);
#endif /* CONFIG_SECUREBOOT_SHA256 */
printf("%s version: %s\n", name, version);
memcpy(buf, &hdr, sizeof(second_loader_hdr));
for (i = 0; i < max_num; i++)
fwrite(buf, max_size, 1, fo);
printf("pack %s success! \n", file_out);
fclose(fi);
fclose(fo);
} else if (mode == MODE_UNPACK) {
buf = calloc(max_size, max_num);
if (!buf) {
perror(file_out);
exit(EXIT_FAILURE);
}
if (!file_in || !file_out) {
usage(argv[0]);
exit(EXIT_FAILURE);
}
/* file in */
fi = fopen(file_in, "rb");
if (!fi) {
perror(file_in);
exit(EXIT_FAILURE);
}
/* file out */
fo = fopen(file_out, "wb");
if (!fo) {
perror(file_out);
exit(EXIT_FAILURE);
}
printf("unpack input %s \n", file_in);
memset(&hdr, 0, sizeof(second_loader_hdr));
if (!fread(&hdr, sizeof(second_loader_hdr), 1, fi))
exit(EXIT_FAILURE);
if (!fread(buf, hdr.loader_load_size, 1, fi))
exit(EXIT_FAILURE);
fwrite(buf, hdr.loader_load_size, 1, fo);
printf("unpack %s success! \n", file_out);
fclose(fi);
fclose(fo);
} else if (mode == MODE_INFO) {
second_loader_hdr *hdr;
hdr = malloc(sizeof(struct tag_second_loader_hdr));
if (hdr == NULL) {
printf("Memory error!\n");
exit(EXIT_FAILURE);
}
/* file in */
fi = fopen(file_in, "rb");
if (!fi) {
perror(file_in);
exit(EXIT_FAILURE);
}
if (!fread(hdr, sizeof(struct tag_second_loader_hdr), 1, fi))
exit(EXIT_FAILURE);
if (!(memcmp(RK_UBOOT_MAGIC, hdr->magic, 5)) ||
!(memcmp(RK_TRUST_MAGIC, hdr->magic, 3))) {
printf("The image info:\n");
printf("Rollback index is %d\n", hdr->version);
printf("Load Addr is 0x%x\n", hdr->loader_load_addr);
} else {
printf("Please input the correct file.\n");
}
fclose(fi);
free(hdr);
}
free(buf);
return 0;
}

File diff suppressed because it is too large Load Diff

320
tools/rockchip/sha.c Normal file
View File

@ -0,0 +1,320 @@
/* sha.c
**
** Copyright 2008, The Android Open Source Project
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of Google Inc. nor the names of its contributors may
** be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "sha.h"
/*
Some machines lack byteswap.h and endian.h. These have to use the
slower code, even if they're little-endian.
*/
#if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN)
#include <byteswap.h>
#include <memory.h>
/*
This version is about 28% faster than the generic version below,
but assumes little-endianness.
*/
static inline uint32_t ror27(uint32_t val)
{
return (val >> 27) | (val << 5);
}
static inline uint32_t ror2(uint32_t val)
{
return (val >> 2) | (val << 30);
}
static inline uint32_t ror31(uint32_t val)
{
return (val >> 31) | (val << 1);
}
static void SHA1_Transform(SHA_CTX *ctx)
{
uint32_t W[80];
register uint32_t A, B, C, D, E;
int t;
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
#define SHA_F1(A, B, C, D, E, t) \
E += ror27(A) + (W[t] = bswap_32(ctx->buf.w[t])) + (D ^ (B & (C ^ D))) + \
0x5A827999; \
B = ror2(B);
for (t = 0; t < 15; t += 5) {
SHA_F1(A, B, C, D, E, t + 0);
SHA_F1(E, A, B, C, D, t + 1);
SHA_F1(D, E, A, B, C, t + 2);
SHA_F1(C, D, E, A, B, t + 3);
SHA_F1(B, C, D, E, A, t + 4);
}
SHA_F1(A, B, C, D, E, t + 0); /* 16th one, t == 15 */
#undef SHA_F1
#define SHA_F1(A, B, C, D, E, t) \
E += \
ror27(A) + (W[t] = ror31(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16])) + \
(D ^ (B & (C ^ D))) + 0x5A827999; \
B = ror2(B);
SHA_F1(E, A, B, C, D, t + 1);
SHA_F1(D, E, A, B, C, t + 2);
SHA_F1(C, D, E, A, B, t + 3);
SHA_F1(B, C, D, E, A, t + 4);
#undef SHA_F1
#define SHA_F2(A, B, C, D, E, t) \
E += \
ror27(A) + (W[t] = ror31(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16])) + \
(B ^ C ^ D) + 0x6ED9EBA1; \
B = ror2(B);
for (t = 20; t < 40; t += 5) {
SHA_F2(A, B, C, D, E, t + 0);
SHA_F2(E, A, B, C, D, t + 1);
SHA_F2(D, E, A, B, C, t + 2);
SHA_F2(C, D, E, A, B, t + 3);
SHA_F2(B, C, D, E, A, t + 4);
}
#undef SHA_F2
#define SHA_F3(A, B, C, D, E, t) \
E += \
ror27(A) + (W[t] = ror31(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16])) + \
((B & C) | (D & (B | C))) + 0x8F1BBCDC; \
B = ror2(B);
for (; t < 60; t += 5) {
SHA_F3(A, B, C, D, E, t + 0);
SHA_F3(E, A, B, C, D, t + 1);
SHA_F3(D, E, A, B, C, t + 2);
SHA_F3(C, D, E, A, B, t + 3);
SHA_F3(B, C, D, E, A, t + 4);
}
#undef SHA_F3
#define SHA_F4(A, B, C, D, E, t) \
E += \
ror27(A) + (W[t] = ror31(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16])) + \
(B ^ C ^ D) + 0xCA62C1D6; \
B = ror2(B);
for (; t < 80; t += 5) {
SHA_F4(A, B, C, D, E, t + 0);
SHA_F4(E, A, B, C, D, t + 1);
SHA_F4(D, E, A, B, C, t + 2);
SHA_F4(C, D, E, A, B, t + 3);
SHA_F4(B, C, D, E, A, t + 4);
}
#undef SHA_F4
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
}
void SHA_update(SHA_CTX *ctx, const void *data, int len)
{
int i = ctx->count % sizeof(ctx->buf);
const uint8_t *p = (const uint8_t *)data;
ctx->count += len;
while (len > sizeof(ctx->buf) - i) {
memcpy(&ctx->buf.b[i], p, sizeof(ctx->buf) - i);
len -= sizeof(ctx->buf) - i;
p += sizeof(ctx->buf) - i;
SHA1_Transform(ctx);
i = 0;
}
while (len--) {
ctx->buf.b[i++] = *p++;
if (i == sizeof(ctx->buf)) {
SHA1_Transform(ctx);
i = 0;
}
}
}
const uint8_t *SHA_final(SHA_CTX *ctx)
{
uint64_t cnt = ctx->count * 8;
int i;
SHA_update(ctx, (uint8_t *)"\x80", 1);
while ((ctx->count % sizeof(ctx->buf)) != (sizeof(ctx->buf) - 8)) {
SHA_update(ctx, (uint8_t *)"\0", 1);
}
for (i = 0; i < 8; ++i) {
uint8_t tmp = cnt >> ((7 - i) * 8);
SHA_update(ctx, &tmp, 1);
}
for (i = 0; i < 5; i++) {
ctx->buf.w[i] = bswap_32(ctx->state[i]);
}
return ctx->buf.b;
}
#else /* #if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN)*/
#define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits))))
static void SHA1_transform(SHA_CTX *ctx)
{
uint32_t W[80];
uint32_t A, B, C, D, E;
uint8_t *p = ctx->buf;
int t;
for (t = 0; t < 16; ++t) {
uint32_t tmp = *p++ << 24;
tmp |= *p++ << 16;
tmp |= *p++ << 8;
tmp |= *p++;
W[t] = tmp;
}
for (; t < 80; t++) {
W[t] = rol(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]);
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
for (t = 0; t < 80; t++) {
uint32_t tmp = rol(5, A) + E + W[t];
if (t < 20)
tmp += (D ^ (B & (C ^ D))) + 0x5A827999;
else if (t < 40)
tmp += (B ^ C ^ D) + 0x6ED9EBA1;
else if (t < 60)
tmp += ((B & C) | (D & (B | C))) + 0x8F1BBCDC;
else
tmp += (B ^ C ^ D) + 0xCA62C1D6;
E = D;
D = C;
C = rol(30, B);
B = A;
A = tmp;
}
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
}
void SHA_update(SHA_CTX *ctx, const void *data, int len)
{
int i = ctx->count % sizeof(ctx->buf);
const uint8_t *p = (const uint8_t *)data;
ctx->count += len;
while (len--) {
ctx->buf[i++] = *p++;
if (i == sizeof(ctx->buf)) {
SHA1_transform(ctx);
i = 0;
}
}
}
const uint8_t *SHA_final(SHA_CTX *ctx)
{
uint8_t *p = ctx->buf;
uint64_t cnt = ctx->count * 8;
int i;
SHA_update(ctx, (uint8_t *)"\x80", 1);
while ((ctx->count % sizeof(ctx->buf)) != (sizeof(ctx->buf) - 8)) {
SHA_update(ctx, (uint8_t *)"\0", 1);
}
for (i = 0; i < 8; ++i) {
uint8_t tmp = cnt >> ((7 - i) * 8);
SHA_update(ctx, &tmp, 1);
}
for (i = 0; i < 5; i++) {
uint32_t tmp = ctx->state[i];
*p++ = tmp >> 24;
*p++ = tmp >> 16;
*p++ = tmp >> 8;
*p++ = tmp >> 0;
}
return ctx->buf;
}
#endif /* endianness */
void SHA_init(SHA_CTX *ctx)
{
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
ctx->state[4] = 0xC3D2E1F0;
ctx->count = 0;
}
/* Convenience function */
const uint8_t *SHA(const void *data, int len, uint8_t *digest)
{
const uint8_t *p;
int i;
SHA_CTX ctx;
SHA_init(&ctx);
SHA_update(&ctx, data, len);
p = SHA_final(&ctx);
for (i = 0; i < SHA_DIGEST_SIZE; ++i) {
digest[i] = *p++;
}
return digest;
}

63
tools/rockchip/sha.h Normal file
View File

@ -0,0 +1,63 @@
/* sha.h
**
** Copyright 2008, The Android Open Source Project
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** * Neither the name of Google Inc. nor the names of its contributors may
** be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _EMBEDDED_SHA_H_
#define _EMBEDDED_SHA_H_
#include <inttypes.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct SHA_CTX {
uint64_t count;
uint32_t state[5];
#if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN)
union {
uint8_t b[64];
uint32_t w[16];
} buf;
#else
uint8_t buf[64];
#endif
} SHA_CTX;
void SHA_init(SHA_CTX* ctx);
void SHA_update(SHA_CTX* ctx, const void* data, int len);
const uint8_t* SHA_final(SHA_CTX* ctx);
/* Convenience method. Returns digest parameter value. */
const uint8_t* SHA(const void* data, int len, uint8_t* digest);
#define SHA_DIGEST_SIZE 20
#ifdef __cplusplus
}
#endif
#endif

760
tools/rockchip/sha2.c Normal file
View File

@ -0,0 +1,760 @@
/*
---------------------------------------------------------------------------
Copyright (c) 2002, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 30/11/2002
This is a byte oriented version of SHA2 that operates on arrays of bytes
stored in memory. This code implements sha256, sha384 and sha512 but the
latter two functions rely on efficient 64-bit integer operations that
may not be very efficient on 32-bit machines
The sha256 functions use a type 'sha256_ctx' to hold details of the
current hash state and uses the following three calls:
void sha256_begin(sha256_ctx ctx[1])
void sha256_hash(sha256_ctx ctx[1], const unsigned char data[],
unsigned long len)
void sha256_end(sha256_ctx ctx[1], unsigned char hval[])
The first subroutine initialises a hash computation by setting up the
context in the sha256_ctx context. The second subroutine hashes 8-bit
bytes from array data[] into the hash state withinh sha256_ctx context,
the number of bytes to be hashed being given by the the unsigned long
integer len. The third subroutine completes the hash calculation and
places the resulting digest value in the array of 8-bit bytes hval[].
The sha384 and sha512 functions are similar and use the interfaces:
void sha384_begin(sha384_ctx ctx[1]);
void sha384_hash(sha384_ctx ctx[1], const unsigned char data[],
unsigned long len);
void sha384_end(sha384_ctx ctx[1], unsigned char hval[]);
void sha512_begin(sha512_ctx ctx[1]);
void sha512_hash(sha512_ctx ctx[1], const unsigned char data[],
unsigned long len);
void sha512_end(sha512_ctx ctx[1], unsigned char hval[]);
In addition there is a function sha2 that can be used to call all these
functions using a call with a hash length parameter as follows:
int sha2_begin(sha2_ctx ctx[1], unsigned long len);
void sha2_hash(sha2_ctx ctx[1], const unsigned char data[],
unsigned long len);
void sha2_end(sha2_ctx ctx[1], unsigned char hval[]);
My thanks to Erik Andersen <andersen@codepoet.org> for testing this code
on big-endian systems and for his assistance with corrections
*/
/* define the hash functions that you need */
#define SHA_2 /* for dynamic hash length */
#define SHA_256
#define SHA_384
#define SHA_512
#ifdef USE_HOSTCC
#include <string.h> /* for memcpy() etc. */
#include <stdlib.h> /* for _lrotr with VC++ */
#endif
#include "sha2.h"
/* rockchip crypto byte order */
#define PLATFORM_BYTE_ORDER SHA_BIG_ENDIAN
/* 1. PLATFORM SPECIFIC INCLUDES */
// #if defined(__GNU_LIBRARY__)
// # include <byteswap.h>
// # include <endian.h>
// #elif defined(__CRYPTLIB__)
// # if defined( INC_ALL )
// # include "crypt.h"
// # elif defined( INC_CHILD )
// # include "../crypt.h"
// # else
// # include "crypt.h"
// # endif
// # if defined(DATA_LITTLEENDIAN)
// # define PLATFORM_BYTE_ORDER SHA_LITTLE_ENDIAN
// # else
// # define PLATFORM_BYTE_ORDER SHA_BIG_ENDIAN
// # endif
// #if defined(_MSC_VER)
// # include <stdlib.h>
// #elif !defined(WIN32)
// # include <stdlib.h>
// # if !defined (_ENDIAN_H)
// # include <sys/param.h>
// # else
// # include _ENDIAN_H
// # endif
// #endif
/* 2. BYTE ORDER IN 32-BIT WORDS
To obtain the highest speed on processors with 32-bit words, this code
needs to determine the order in which bytes are packed into such words.
The following block of code is an attempt to capture the most obvious
ways in which various environments specify their endian definitions.
It may well fail, in which case the definitions will need to be set by
editing at the points marked **** EDIT HERE IF NECESSARY **** below.
*/
#define SHA_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */
#define SHA_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */
#if !defined(PLATFORM_BYTE_ORDER)
#if defined(LITTLE_ENDIAN) || defined(BIG_ENDIAN)
#if defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
#if defined(BYTE_ORDER)
#if (BYTE_ORDER == LITTLE_ENDIAN)
#define PLATFORM_BYTE_ORDER SHA_LITTLE_ENDIAN
#elif(BYTE_ORDER == BIG_ENDIAN)
#define PLATFORM_BYTE_ORDER SHA_BIG_ENDIAN
#endif
#endif
#elif defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN)
#define PLATFORM_BYTE_ORDER SHA_LITTLE_ENDIAN
#elif !defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
#define PLATFORM_BYTE_ORDER SHA_BIG_ENDIAN
#endif
#elif defined(_LITTLE_ENDIAN) || defined(_BIG_ENDIAN)
#if defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN)
#if defined(_BYTE_ORDER)
#if (_BYTE_ORDER == _LITTLE_ENDIAN)
#define PLATFORM_BYTE_ORDER SHA_LITTLE_ENDIAN
#elif(_BYTE_ORDER == _BIG_ENDIAN)
#define PLATFORM_BYTE_ORDER SHA_BIG_ENDIAN
#endif
#endif
#elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
#define PLATFORM_BYTE_ORDER SHA_LITTLE_ENDIAN
#elif !defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN)
#define PLATFORM_BYTE_ORDER SHA_BIG_ENDIAN
#endif
#elif 0 /* **** EDIT HERE IF NECESSARY **** */
#define PLATFORM_BYTE_ORDER SHA_LITTLE_ENDIAN
#elif 0 /* **** EDIT HERE IF NECESSARY **** */
#define PLATFORM_BYTE_ORDER SHA_BIG_ENDIAN
#elif(('1234' >> 24) == '1')
#define PLATFORM_BYTE_ORDER SHA_LITTLE_ENDIAN
#elif(('4321' >> 24) == '1')
#define PLATFORM_BYTE_ORDER SHA_BIG_ENDIAN
#endif
#endif
#if !defined(PLATFORM_BYTE_ORDER)
#error Please set undetermined byte order (lines 159 or 161 of sha2.c).
#endif
#ifdef _MSC_VER
#pragma intrinsic(memcpy)
#endif
#define rotr32(x, n) (((x) >> n) | ((x) << (32 - n)))
#if !defined(bswap_32)
#define bswap_32(x) \
((rotr32((x), 24) & 0x00ff00ff) | (rotr32((x), 8) & 0xff00ff00))
#endif
#if (PLATFORM_BYTE_ORDER == SHA_LITTLE_ENDIAN)
#define SWAP_BYTES
#else
#undef SWAP_BYTES
#endif
#if defined(SHA_2) || defined(SHA_256)
#define SHA256_MASK (SHA256_BLOCK_SIZE - 1)
#if defined(SWAP_BYTES)
#define bsw_32(p, n) \
{ \
int _i = (n); \
while (_i--) \
p[_i] = bswap_32(p[_i]); \
}
#else
#define bsw_32(p, n)
#endif
/* SHA256 mixing function definitions */
#define ch(x, y, z) (((x) & (y)) ^ (~(x) & (z)))
#define maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#define s256_0(x) (rotr32((x), 2) ^ rotr32((x), 13) ^ rotr32((x), 22))
#define s256_1(x) (rotr32((x), 6) ^ rotr32((x), 11) ^ rotr32((x), 25))
#define g256_0(x) (rotr32((x), 7) ^ rotr32((x), 18) ^ ((x) >> 3))
#define g256_1(x) (rotr32((x), 17) ^ rotr32((x), 19) ^ ((x) >> 10))
/* rotated SHA256 round definition. Rather than swapping variables as in */
/* FIPS-180, different variables are 'rotated' on each round, returning */
/* to their starting positions every eight rounds */
#define h2(i) \
ctx->wbuf[i & 15] += \
g256_1(ctx->wbuf[(i + 14) & 15]) + ctx->wbuf[(i + 9) & 15] + \
g256_0(ctx->wbuf[(i + 1) & 15])
#define h2_cycle(i, j) \
v[(7 - i) & 7] += \
(j ? h2(i) : ctx->wbuf[i & 15]) + k256[i + j] + s256_1(v[(4 - i) & 7]) + \
ch(v[(4 - i) & 7], v[(5 - i) & 7], v[(6 - i) & 7]); \
v[(3 - i) & 7] += v[(7 - i) & 7]; \
v[(7 - i) & 7] += s256_0(v[(0 - i) & 7]) + \
maj(v[(0 - i) & 7], v[(1 - i) & 7], v[(2 - i) & 7])
/* SHA256 mixing data */
const sha2_32t k256[64] = {
n_u32(428a2f98), n_u32(71374491), n_u32(b5c0fbcf), n_u32(e9b5dba5),
n_u32(3956c25b), n_u32(59f111f1), n_u32(923f82a4), n_u32(ab1c5ed5),
n_u32(d807aa98), n_u32(12835b01), n_u32(243185be), n_u32(550c7dc3),
n_u32(72be5d74), n_u32(80deb1fe), n_u32(9bdc06a7), n_u32(c19bf174),
n_u32(e49b69c1), n_u32(efbe4786), n_u32(0fc19dc6), n_u32(240ca1cc),
n_u32(2de92c6f), n_u32(4a7484aa), n_u32(5cb0a9dc), n_u32(76f988da),
n_u32(983e5152), n_u32(a831c66d), n_u32(b00327c8), n_u32(bf597fc7),
n_u32(c6e00bf3), n_u32(d5a79147), n_u32(06ca6351), n_u32(14292967),
n_u32(27b70a85), n_u32(2e1b2138), n_u32(4d2c6dfc), n_u32(53380d13),
n_u32(650a7354), n_u32(766a0abb), n_u32(81c2c92e), n_u32(92722c85),
n_u32(a2bfe8a1), n_u32(a81a664b), n_u32(c24b8b70), n_u32(c76c51a3),
n_u32(d192e819), n_u32(d6990624), n_u32(f40e3585), n_u32(106aa070),
n_u32(19a4c116), n_u32(1e376c08), n_u32(2748774c), n_u32(34b0bcb5),
n_u32(391c0cb3), n_u32(4ed8aa4a), n_u32(5b9cca4f), n_u32(682e6ff3),
n_u32(748f82ee), n_u32(78a5636f), n_u32(84c87814), n_u32(8cc70208),
n_u32(90befffa), n_u32(a4506ceb), n_u32(bef9a3f7), n_u32(c67178f2),
};
/* SHA256 initialisation data */
const sha2_32t i256[8] = { n_u32(6a09e667), n_u32(bb67ae85), n_u32(3c6ef372),
n_u32(a54ff53a), n_u32(510e527f), n_u32(9b05688c),
n_u32(1f83d9ab), n_u32(5be0cd19)
};
void sha256_begin(sha256_ctx ctx[1])
{
ctx->count[0] = ctx->count[1] = 0;
memcpy(ctx->hash, i256, 8 * sizeof(sha2_32t));
}
/* Compile 64 bytes of hash data into SHA256 digest value */
/* NOTE: this routine assumes that the byte order in the */
/* ctx->wbuf[] at this point is in such an order that low */
/* address bytes in the ORIGINAL byte stream placed in this */
/* buffer will now go to the high end of words on BOTH big */
/* and little endian systems */
void sha256_compile(sha256_ctx ctx[1])
{
sha2_32t v[8], j;
memcpy(v, ctx->hash, 8 * sizeof(sha2_32t));
for (j = 0; j < 64; j += 16) {
h2_cycle(0, j);
h2_cycle(1, j);
h2_cycle(2, j);
h2_cycle(3, j);
h2_cycle(4, j);
h2_cycle(5, j);
h2_cycle(6, j);
h2_cycle(7, j);
h2_cycle(8, j);
h2_cycle(9, j);
h2_cycle(10, j);
h2_cycle(11, j);
h2_cycle(12, j);
h2_cycle(13, j);
h2_cycle(14, j);
h2_cycle(15, j);
}
ctx->hash[0] += v[0];
ctx->hash[1] += v[1];
ctx->hash[2] += v[2];
ctx->hash[3] += v[3];
ctx->hash[4] += v[4];
ctx->hash[5] += v[5];
ctx->hash[6] += v[6];
ctx->hash[7] += v[7];
}
/* SHA256 hash data in an array of bytes into hash buffer */
/* and call the hash_compile function as required. */
void sha256_hash(sha256_ctx ctx[1], const unsigned char data[],
unsigned long len)
{
sha2_32t pos = (sha2_32t)(ctx->count[0] & SHA256_MASK),
space = SHA256_BLOCK_SIZE - pos;
const unsigned char *sp = data;
if ((ctx->count[0] += len) < len)
++(ctx->count[1]);
while (len >= space) { /* tranfer whole blocks while possible */
memcpy(((unsigned char *)ctx->wbuf) + pos, sp, space);
sp += space;
len -= space;
space = SHA256_BLOCK_SIZE;
pos = 0;
bsw_32(ctx->wbuf, SHA256_BLOCK_SIZE >> 2);
sha256_compile(ctx);
}
memcpy(((unsigned char *)ctx->wbuf) + pos, sp, len);
}
/* SHA256 Final padding and digest calculation */
static sha2_32t m1[4] = { n_u32(00000000), n_u32(ff000000), n_u32(ffff0000),
n_u32(ffffff00)
};
static sha2_32t b1[4] = { n_u32(80000000), n_u32(00800000), n_u32(00008000),
n_u32(00000080)
};
void sha256_end(sha256_ctx ctx[1], unsigned char hval[])
{
sha2_32t i = (sha2_32t)(ctx->count[0] & SHA256_MASK);
bsw_32(ctx->wbuf, (i + 3) >> 2)
/* bytes in the buffer are now in an order in which references */
/* to 32-bit words will put bytes with lower addresses into the */
/* top of 32 bit words on BOTH big and little endian machines */
/* we now need to mask valid bytes and add the padding which is */
/* a single 1 bit and as many zero bits as necessary. */
ctx->wbuf[i >> 2] = (ctx->wbuf[i >> 2] & m1[i & 3]) | b1[i & 3];
/* we need 9 or more empty positions, one for the padding byte */
/* (above) and eight for the length count. If there is not */
/* enough space pad and empty the buffer */
if (i > SHA256_BLOCK_SIZE - 9) {
if (i < 60)
ctx->wbuf[15] = 0;
sha256_compile(ctx);
i = 0;
} else /* compute a word index for the empty buffer positions */
i = (i >> 2) + 1;
while (i < 14) /* and zero pad all but last two positions */
ctx->wbuf[i++] = 0;
/* the following 32-bit length fields are assembled in the */
/* wrong byte order on little endian machines but this is */
/* corrected later since they are only ever used as 32-bit */
/* word values. */
ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 29);
ctx->wbuf[15] = ctx->count[0] << 3;
sha256_compile(ctx);
/* extract the hash value as bytes in case the hash buffer is */
/* mislaigned for 32-bit words */
for (i = 0; i < SHA256_DIGEST_SIZE; ++i)
hval[i] = (unsigned char)(ctx->hash[i >> 2] >> 8 * (~i & 3));
}
void sha256(unsigned char hval[], const unsigned char data[],
unsigned long len)
{
sha256_ctx cx[1];
sha256_begin(cx);
sha256_hash(cx, data, len);
sha256_end(cx, hval);
}
#endif
#if defined(SHA_2) || defined(SHA_384) || defined(SHA_512)
#define SHA512_MASK (SHA512_BLOCK_SIZE - 1)
#define rotr64(x, n) (((x) >> n) | ((x) << (64 - n)))
#if !defined(bswap_64)
#define bswap_64(x) \
(((sha2_64t)(bswap_32((sha2_32t)(x)))) << 32 | \
bswap_32((sha2_32t)((x) >> 32)))
#endif
#if defined(SWAP_BYTES)
#define bsw_64(p, n) \
{ \
int _i = (n); \
while (_i--) \
p[_i] = bswap_64(p[_i]); \
}
#else
#define bsw_64(p, n)
#endif
/* SHA512 mixing function definitions */
#define s512_0(x) (rotr64((x), 28) ^ rotr64((x), 34) ^ rotr64((x), 39))
#define s512_1(x) (rotr64((x), 14) ^ rotr64((x), 18) ^ rotr64((x), 41))
#define g512_0(x) (rotr64((x), 1) ^ rotr64((x), 8) ^ ((x) >> 7))
#define g512_1(x) (rotr64((x), 19) ^ rotr64((x), 61) ^ ((x) >> 6))
/* rotated SHA512 round definition. Rather than swapping variables as in */
/* FIPS-180, different variables are 'rotated' on each round, returning */
/* to their starting positions every eight rounds */
#define h5(i) \
ctx->wbuf[i & 15] += \
g512_1(ctx->wbuf[(i + 14) & 15]) + ctx->wbuf[(i + 9) & 15] + \
g512_0(ctx->wbuf[(i + 1) & 15])
#define h5_cycle(i, j) \
v[(7 - i) & 7] += \
(j ? h5(i) : ctx->wbuf[i & 15]) + k512[i + j] + s512_1(v[(4 - i) & 7]) + \
ch(v[(4 - i) & 7], v[(5 - i) & 7], v[(6 - i) & 7]); \
v[(3 - i) & 7] += v[(7 - i) & 7]; \
v[(7 - i) & 7] += s512_0(v[(0 - i) & 7]) + \
maj(v[(0 - i) & 7], v[(1 - i) & 7], v[(2 - i) & 7])
/* SHA384/SHA512 mixing data */
const sha2_64t k512[80] = {
n_u64(428a2f98d728ae22), n_u64(7137449123ef65cd), n_u64(b5c0fbcfec4d3b2f),
n_u64(e9b5dba58189dbbc), n_u64(3956c25bf348b538), n_u64(59f111f1b605d019),
n_u64(923f82a4af194f9b), n_u64(ab1c5ed5da6d8118), n_u64(d807aa98a3030242),
n_u64(12835b0145706fbe), n_u64(243185be4ee4b28c), n_u64(550c7dc3d5ffb4e2),
n_u64(72be5d74f27b896f), n_u64(80deb1fe3b1696b1), n_u64(9bdc06a725c71235),
n_u64(c19bf174cf692694), n_u64(e49b69c19ef14ad2), n_u64(efbe4786384f25e3),
n_u64(0fc19dc68b8cd5b5), n_u64(240ca1cc77ac9c65), n_u64(2de92c6f592b0275),
n_u64(4a7484aa6ea6e483), n_u64(5cb0a9dcbd41fbd4), n_u64(76f988da831153b5),
n_u64(983e5152ee66dfab), n_u64(a831c66d2db43210), n_u64(b00327c898fb213f),
n_u64(bf597fc7beef0ee4), n_u64(c6e00bf33da88fc2), n_u64(d5a79147930aa725),
n_u64(06ca6351e003826f), n_u64(142929670a0e6e70), n_u64(27b70a8546d22ffc),
n_u64(2e1b21385c26c926), n_u64(4d2c6dfc5ac42aed), n_u64(53380d139d95b3df),
n_u64(650a73548baf63de), n_u64(766a0abb3c77b2a8), n_u64(81c2c92e47edaee6),
n_u64(92722c851482353b), n_u64(a2bfe8a14cf10364), n_u64(a81a664bbc423001),
n_u64(c24b8b70d0f89791), n_u64(c76c51a30654be30), n_u64(d192e819d6ef5218),
n_u64(d69906245565a910), n_u64(f40e35855771202a), n_u64(106aa07032bbd1b8),
n_u64(19a4c116b8d2d0c8), n_u64(1e376c085141ab53), n_u64(2748774cdf8eeb99),
n_u64(34b0bcb5e19b48a8), n_u64(391c0cb3c5c95a63), n_u64(4ed8aa4ae3418acb),
n_u64(5b9cca4f7763e373), n_u64(682e6ff3d6b2b8a3), n_u64(748f82ee5defb2fc),
n_u64(78a5636f43172f60), n_u64(84c87814a1f0ab72), n_u64(8cc702081a6439ec),
n_u64(90befffa23631e28), n_u64(a4506cebde82bde9), n_u64(bef9a3f7b2c67915),
n_u64(c67178f2e372532b), n_u64(ca273eceea26619c), n_u64(d186b8c721c0c207),
n_u64(eada7dd6cde0eb1e), n_u64(f57d4f7fee6ed178), n_u64(06f067aa72176fba),
n_u64(0a637dc5a2c898a6), n_u64(113f9804bef90dae), n_u64(1b710b35131c471b),
n_u64(28db77f523047d84), n_u64(32caab7b40c72493), n_u64(3c9ebe0a15c9bebc),
n_u64(431d67c49c100d4c), n_u64(4cc5d4becb3e42b6), n_u64(597f299cfc657e2a),
n_u64(5fcb6fab3ad6faec), n_u64(6c44198c4a475817)
};
/* Compile 64 bytes of hash data into SHA384/SHA512 digest value */
void sha512_compile(sha512_ctx ctx[1])
{
sha2_64t v[8];
sha2_32t j;
memcpy(v, ctx->hash, 8 * sizeof(sha2_64t));
for (j = 0; j < 80; j += 16) {
h5_cycle(0, j);
h5_cycle(1, j);
h5_cycle(2, j);
h5_cycle(3, j);
h5_cycle(4, j);
h5_cycle(5, j);
h5_cycle(6, j);
h5_cycle(7, j);
h5_cycle(8, j);
h5_cycle(9, j);
h5_cycle(10, j);
h5_cycle(11, j);
h5_cycle(12, j);
h5_cycle(13, j);
h5_cycle(14, j);
h5_cycle(15, j);
}
ctx->hash[0] += v[0];
ctx->hash[1] += v[1];
ctx->hash[2] += v[2];
ctx->hash[3] += v[3];
ctx->hash[4] += v[4];
ctx->hash[5] += v[5];
ctx->hash[6] += v[6];
ctx->hash[7] += v[7];
}
/* Compile 128 bytes of hash data into SHA256 digest value */
/* NOTE: this routine assumes that the byte order in the */
/* ctx->wbuf[] at this point is in such an order that low */
/* address bytes in the ORIGINAL byte stream placed in this */
/* buffer will now go to the high end of words on BOTH big */
/* and little endian systems */
void sha512_hash(sha512_ctx ctx[1], const unsigned char data[],
unsigned long len)
{
sha2_32t pos = (sha2_32t)(ctx->count[0] & SHA512_MASK),
space = SHA512_BLOCK_SIZE - pos;
const unsigned char *sp = data;
if ((ctx->count[0] += len) < len)
++(ctx->count[1]);
while (len >= space) { /* tranfer whole blocks while possible */
memcpy(((unsigned char *)ctx->wbuf) + pos, sp, space);
sp += space;
len -= space;
space = SHA512_BLOCK_SIZE;
pos = 0;
bsw_64(ctx->wbuf, SHA512_BLOCK_SIZE >> 3);
sha512_compile(ctx);
}
memcpy(((unsigned char *)ctx->wbuf) + pos, sp, len);
}
/* SHA384/512 Final padding and digest calculation */
static sha2_64t m2[8] = { n_u64(0000000000000000), n_u64(ff00000000000000),
n_u64(ffff000000000000), n_u64(ffffff0000000000),
n_u64(ffffffff00000000), n_u64(ffffffffff000000),
n_u64(ffffffffffff0000), n_u64(ffffffffffffff00)
};
static sha2_64t b2[8] = { n_u64(8000000000000000), n_u64(0080000000000000),
n_u64(0000800000000000), n_u64(0000008000000000),
n_u64(0000000080000000), n_u64(0000000000800000),
n_u64(0000000000008000), n_u64(0000000000000080)
};
static void sha_end(sha512_ctx ctx[1], unsigned char hval[],
const unsigned int hlen)
{
sha2_32t i = (sha2_32t)(ctx->count[0] & SHA512_MASK);
bsw_64(ctx->wbuf, (i + 7) >> 3);
/* bytes in the buffer are now in an order in which references */
/* to 64-bit words will put bytes with lower addresses into the */
/* top of 64 bit words on BOTH big and little endian machines */
/* we now need to mask valid bytes and add the padding which is */
/* a single 1 bit and as many zero bits as necessary. */
ctx->wbuf[i >> 3] = (ctx->wbuf[i >> 3] & m2[i & 7]) | b2[i & 7];
/* we need 17 or more empty byte positions, one for the padding */
/* byte (above) and sixteen for the length count. If there is */
/* not enough space pad and empty the buffer */
if (i > SHA512_BLOCK_SIZE - 17) {
if (i < 120)
ctx->wbuf[15] = 0;
sha512_compile(ctx);
i = 0;
} else
i = (i >> 3) + 1;
while (i < 14)
ctx->wbuf[i++] = 0;
/* the following 64-bit length fields are assembled in the */
/* wrong byte order on little endian machines but this is */
/* corrected later since they are only ever used as 64-bit */
/* word values. */
ctx->wbuf[14] = (ctx->count[1] << 3) | (ctx->count[0] >> 61);
ctx->wbuf[15] = ctx->count[0] << 3;
sha512_compile(ctx);
/* extract the hash value as bytes in case the hash buffer is */
/* misaligned for 32-bit words */
for (i = 0; i < hlen; ++i)
hval[i] = (unsigned char)(ctx->hash[i >> 3] >> 8 * (~i & 7));
}
#endif
#if defined(SHA_2) || defined(SHA_384)
/* SHA384 initialisation data */
const sha2_64t i384[80] = { n_u64(cbbb9d5dc1059ed8), n_u64(629a292a367cd507),
n_u64(9159015a3070dd17), n_u64(152fecd8f70e5939),
n_u64(67332667ffc00b31), n_u64(8eb44a8768581511),
n_u64(db0c2e0d64f98fa7), n_u64(47b5481dbefa4fa4)
};
void sha384_begin(sha384_ctx ctx[1])
{
ctx->count[0] = ctx->count[1] = 0;
memcpy(ctx->hash, i384, 8 * sizeof(sha2_64t));
}
void sha384_end(sha384_ctx ctx[1], unsigned char hval[])
{
sha_end(ctx, hval, SHA384_DIGEST_SIZE);
}
void sha384(unsigned char hval[], const unsigned char data[],
unsigned long len)
{
sha384_ctx cx[1];
sha384_begin(cx);
sha384_hash(cx, data, len);
sha384_end(cx, hval);
}
#endif
#if defined(SHA_2) || defined(SHA_512)
/* SHA512 initialisation data */
const sha2_64t i512[80] = { n_u64(6a09e667f3bcc908), n_u64(bb67ae8584caa73b),
n_u64(3c6ef372fe94f82b), n_u64(a54ff53a5f1d36f1),
n_u64(510e527fade682d1), n_u64(9b05688c2b3e6c1f),
n_u64(1f83d9abfb41bd6b), n_u64(5be0cd19137e2179)
};
void sha512_begin(sha512_ctx ctx[1])
{
ctx->count[0] = ctx->count[1] = 0;
memcpy(ctx->hash, i512, 8 * sizeof(sha2_64t));
}
void sha512_end(sha512_ctx ctx[1], unsigned char hval[])
{
sha_end(ctx, hval, SHA512_DIGEST_SIZE);
}
void sha512(unsigned char hval[], const unsigned char data[],
unsigned long len)
{
sha512_ctx cx[1];
sha512_begin(cx);
sha512_hash(cx, data, len);
sha512_end(cx, hval);
}
#endif
#if defined(SHA_2)
#define CTX_256(x) ((x)->uu->ctx256)
#define CTX_384(x) ((x)->uu->ctx512)
#define CTX_512(x) ((x)->uu->ctx512)
/* SHA2 initialisation */
int sha2_begin(sha2_ctx ctx[1], unsigned long len)
{
unsigned long l = len;
switch (len) {
case 256:
l = len >> 3;
case 32:
CTX_256(ctx)->count[0] = CTX_256(ctx)->count[1] = 0;
memcpy(CTX_256(ctx)->hash, i256, 32);
break;
case 384:
l = len >> 3;
case 48:
CTX_384(ctx)->count[0] = CTX_384(ctx)->count[1] = 0;
memcpy(CTX_384(ctx)->hash, i384, 64);
break;
case 512:
l = len >> 3;
case 64:
CTX_512(ctx)->count[0] = CTX_512(ctx)->count[1] = 0;
memcpy(CTX_512(ctx)->hash, i512, 64);
break;
default:
return SHA2_BAD;
}
ctx->sha2_len = l;
return SHA2_GOOD;
}
void sha2_hash(sha2_ctx ctx[1], const unsigned char data[], unsigned long len)
{
switch (ctx->sha2_len) {
case 32:
sha256_hash(CTX_256(ctx), data, len);
return;
case 48:
sha384_hash(CTX_384(ctx), data, len);
return;
case 64:
sha512_hash(CTX_512(ctx), data, len);
return;
}
}
void sha2_end(sha2_ctx ctx[1], unsigned char hval[])
{
switch (ctx->sha2_len) {
case 32:
sha256_end(CTX_256(ctx), hval);
return;
case 48:
sha_end(CTX_384(ctx), hval, SHA384_DIGEST_SIZE);
return;
case 64:
sha_end(CTX_512(ctx), hval, SHA512_DIGEST_SIZE);
return;
}
}
int sha2(unsigned char hval[], unsigned long size, const unsigned char data[],
unsigned long len)
{
sha2_ctx cx[1];
if (sha2_begin(cx, size) == SHA2_GOOD) {
sha2_hash(cx, data, len);
sha2_end(cx, hval);
return SHA2_GOOD;
} else
return SHA2_BAD;
}
#endif

161
tools/rockchip/sha2.h Normal file
View File

@ -0,0 +1,161 @@
/*
---------------------------------------------------------------------------
Copyright (c) 2002, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
All rights reserved.
LICENSE TERMS
The free distribution and use of this software in both source and binary
form is allowed (with or without changes) provided that:
1. distributions of this source code include the above copyright
notice, this list of conditions and the following disclaimer;
2. distributions in binary form include the above copyright
notice, this list of conditions and the following disclaimer
in the documentation and/or other associated materials;
3. the copyright holder's name is not used to endorse products
built using this software without specific written permission.
ALTERNATIVELY, provided that this notice is retained in full, this product
may be distributed under the terms of the GNU General Public License (GPL),
in which case the provisions of the GPL apply INSTEAD OF those given above.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 30/11/2002
*/
#ifndef _SHA2_H
#define _SHA2_H
#ifdef USE_HOSTCC
#include <limits.h>
#endif
/* Defines for suffixes to 32 and 64 bit unsigned numeric values */
#define sfx_lo(x,y) x##y
#define sfx_hi(x,y) sfx_lo(x,y)
#define n_u32(p) sfx_hi(0x##p,s_u32)
#define n_u64(p) sfx_hi(0x##p,s_u64)
#ifdef USE_HOSTCC
/* define an unsigned 32-bit type */
#if UINT_MAX == 0xffffffff
typedef unsigned int sha2_32t;
#define s_u32 u
#elif ULONG_MAX == 0xffffffff
typedef unsigned long sha2_32t;
#define s_u32 ul
#else
#error Please define sha2_32t as an unsigned 32 bit type in sha2.h
#endif
/* define an unsigned 64-bit type */
#if defined( _MSC_VER )
typedef unsigned __int64 sha2_64t;
#define s_u64 ui64
#elif ULONG_MAX == 0xffffffffffffffff
typedef unsigned long sha2_64t;
#define s_u64 ul
#elif ULONG_MAX == 0xffffffff
typedef unsigned long long sha2_64t; /* a somewhat dangerous guess */
#define s_u64 ull
#else
#error Please define sha2_64t as an unsigned 64 bit type in sha2.h
#endif
#else
#include <common.h>
typedef uint32_t sha2_32t;
#define s_u32 u
typedef uint64_t sha2_64t; /* a somewhat dangerous guess */
#define s_u64 ull
#endif /* USE_HOSTCC */
#if defined(__cplusplus)
extern "C"
{
#endif
#define SHA256_DIGEST_SIZE 32
#define SHA384_DIGEST_SIZE 48
#define SHA512_DIGEST_SIZE 64
#define SHA256_BLOCK_SIZE 64
#define SHA384_BLOCK_SIZE 128
#define SHA512_BLOCK_SIZE 128
#define SHA2_DIGEST_SIZE SHA256_DIGEST_SIZE
#define SHA2_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE
#define SHA2_GOOD 0
#define SHA2_BAD 1
/* type to hold the SHA256 context */
typedef struct {
sha2_32t count[2];
sha2_32t hash[8];
sha2_32t wbuf[16];
} sha256_ctx;
/* type to hold the SHA384/512 context */
typedef struct {
sha2_64t count[2];
sha2_64t hash[8];
sha2_64t wbuf[16];
} sha512_ctx;
typedef sha512_ctx sha384_ctx;
/* type to hold a SHA2 context (256/384/512) */
typedef struct {
union {
sha256_ctx ctx256[1];
sha512_ctx ctx512[1];
} uu[1];
sha2_32t sha2_len;
} sha2_ctx;
void sha256_compile(sha256_ctx ctx[1]);
void sha512_compile(sha512_ctx ctx[1]);
void sha256_begin(sha256_ctx ctx[1]);
void sha256_hash(sha256_ctx ctx[1], const unsigned char data[], unsigned long len);
void sha256_end(sha256_ctx ctx[1], unsigned char hval[]);
void sha256(unsigned char hval[], const unsigned char data[], unsigned long len);
void sha384_begin(sha384_ctx ctx[1]);
#define sha384_hash sha512_hash
void sha384_end(sha384_ctx ctx[1], unsigned char hval[]);
void sha384(unsigned char hval[], const unsigned char data[], unsigned long len);
void sha512_begin(sha512_ctx ctx[1]);
void sha512_hash(sha512_ctx ctx[1], const unsigned char data[], unsigned long len);
void sha512_end(sha512_ctx ctx[1], unsigned char hval[]);
void sha512(unsigned char hval[], const unsigned char data[], unsigned long len);
int sha2_begin(sha2_ctx ctx[1], unsigned long size);
void sha2_hash(sha2_ctx ctx[1], const unsigned char data[], unsigned long len);
void sha2_end(sha2_ctx ctx[1], unsigned char hval[]);
int sha2(unsigned char hval[], unsigned long size, const unsigned char data[], unsigned long len);
#if defined(__cplusplus)
}
#endif
#endif

View File

@ -0,0 +1,930 @@
/*
* Rockchip trust image generator
*
* (C) Copyright 2008-2015 Fuzhou Rockchip Electronics Co., Ltd
* Peter, Software Engineering, <superpeter.cai@gmail.com>.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <sys/stat.h>
#include <u-boot/sha256.h>
#include "trust_merger.h"
#include "sha2.h"
/* #define DEBUG */
static bool gDebug =
#ifdef DEBUG
true;
#else
false;
#endif /* DEBUG */
#define LOGE(fmt, args...) fprintf(stderr, "E: [%s] " fmt, __func__, ##args)
#define LOGD(fmt, args...) \
do { \
if (gDebug) \
fprintf(stderr, "D: [%s] " fmt, __func__, ##args); \
} while (0)
/* trust image has g_trust_max_num backups */
static uint32_t g_trust_max_num = 2;
static uint32_t g_trust_max_size = 2 * 1024 * 1024;
/* config sha and rsa */
#define SHA_SEL_256 3 /* little endian */
#define SHA_SEL_256_RK 2 /* big endian: only rk3368 need it */
#define SHA_SEL_160 1
#define SHA_SEL_NONE 0
#define RSA_SEL_2048_PSS 3 /* only RK3326, PX30, RK3308 */
#define RSA_SEL_2048 2 /* most platforms except above PSS */
#define RSA_SEL_1024 1
#define RSA_SEL_NONE 0
#define is_digit(c) ((c) >= '0' && (c) <= '9')
static char *gConfigPath;
static OPT_T gOpts;
#define BL3X_FILESIZE_MAX (512 * 1024)
static uint8_t gBuf[BL3X_FILESIZE_MAX];
static bool gSubfix;
static char *gLegacyPath;
static char *gNewPath;
static uint8_t gRSAmode = RSA_SEL_2048;
static uint8_t gSHAmode = SHA_SEL_256;
const uint8_t gBl3xID[BL_MAX_SEC][4] = { { 'B', 'L', '3', '0' },
{ 'B', 'L', '3', '1' },
{ 'B', 'L', '3', '2' },
{ 'B', 'L', '3', '3' }
};
static inline uint32_t getBCD(uint16_t value)
{
uint8_t tmp[2] = { 0 };
int i;
uint32_t ret;
if (value > 0xFFFF) {
return 0;
}
for (i = 0; i < 2; i++) {
tmp[i] = (((value / 10) % 10) << 4) | (value % 10);
value /= 100;
}
ret = ((uint16_t)(tmp[1] << 8)) | tmp[0];
LOGD("ret:%x\n", ret);
return ret & 0xFF;
}
static inline void fixPath(char *path)
{
int i, len = strlen(path);
char tmp[MAX_LINE_LEN];
char *start, *end;
for (i = 0; i < len; i++) {
if (path[i] == '\\')
path[i] = '/';
else if (path[i] == '\r' || path[i] == '\n')
path[i] = '\0';
}
if (gLegacyPath && gNewPath) {
start = strstr(path, gLegacyPath);
if (start) {
end = start + strlen(gLegacyPath);
/* Backup, so tmp can be src for strcat() */
strcpy(tmp, end);
/* Terminate, so path can be dest for strcat() */
*start = '\0';
strcat(path, tmp);
}
}
}
static bool parseVersion(FILE *file)
{
int d = 0;
if (SCANF_EAT(file) != 0) {
return false;
}
if (fscanf(file, OPT_MAJOR "=%d", &d) != 1)
return false;
gOpts.major = (uint16_t) d;
if (SCANF_EAT(file) != 0) {
return false;
}
if (fscanf(file, OPT_MINOR "=%d", &d) != 1)
return false;
gOpts.minor = (uint16_t) d;
LOGD("major:%d, minor:%d\n", gOpts.major, gOpts.minor);
return true;
}
static bool parseBL3x(FILE *file, int bl3x_id)
{
int pos;
int sec;
char buf[MAX_LINE_LEN];
bl_entry_t *pbl3x = NULL;
if (bl3x_id >= BL_MAX_SEC) {
return false;
}
pbl3x = &gOpts.bl3x[bl3x_id];
/* SEC */
if (SCANF_EAT(file) != 0) {
return false;
}
if (fscanf(file, OPT_SEC "=%d", &sec) != 1) {
return false;
}
if ((gSubfix) && (bl3x_id == BL32_SEC)) {
if (sec == 0) {
sec = 1;
printf("BL3%d adjust sec from 0 to 1\n", bl3x_id);
}
}
pbl3x->sec = sec;
LOGD("bl3%d sec: %d\n", bl3x_id, pbl3x->sec);
/* PATH */
if (SCANF_EAT(file) != 0) {
return false;
}
memset(buf, 0, MAX_LINE_LEN);
if (fscanf(file, OPT_PATH "=%s", buf) != 1) {
if (pbl3x->sec)
return false;
} else {
if (strlen(buf) != 0) {
fixPath(buf);
strcpy(pbl3x->path, buf);
LOGD("bl3%d path:%s\n", bl3x_id, pbl3x->path);
}
}
/* ADDR */
if (SCANF_EAT(file) != 0) {
return false;
}
memset(buf, 0, MAX_LINE_LEN);
if (fscanf(file, OPT_ADDR "=%s", buf) != 1) {
if (pbl3x->sec)
return false;
} else {
if (strlen(buf) != 0) {
pbl3x->addr = strtoul(buf, NULL, 16);
LOGD("bl3%d addr:0x%x\n", bl3x_id, pbl3x->addr);
}
}
pos = ftell(file);
if (pos < 0) {
return false;
}
if (SCANF_EAT(file) != 0) {
return false;
}
return true;
}
static bool parseOut(FILE *file)
{
if (SCANF_EAT(file) != 0) {
return false;
}
if (fscanf(file, OPT_OUT_PATH "=%[^\r^\n]", gOpts.outPath) != 1)
return false;
fixPath(gOpts.outPath);
printf("out:%s\n", gOpts.outPath);
return true;
}
void printOpts(FILE *out)
{
fprintf(out, SEC_BL30 "\n" OPT_SEC "=%d\n", gOpts.bl3x[BL30_SEC].sec);
if (gOpts.bl3x[BL30_SEC].sec) {
fprintf(out, OPT_PATH "=%s\n", gOpts.bl3x[BL30_SEC].path);
fprintf(out, OPT_ADDR "=0x%08x\n", gOpts.bl3x[BL30_SEC].addr);
}
fprintf(out, SEC_BL31 "\n" OPT_SEC "=%d\n", gOpts.bl3x[BL31_SEC].sec);
if (gOpts.bl3x[BL31_SEC].sec) {
fprintf(out, OPT_PATH "=%s\n", gOpts.bl3x[BL31_SEC].path);
fprintf(out, OPT_ADDR "=0x%08x\n", gOpts.bl3x[BL31_SEC].addr);
}
fprintf(out, SEC_BL32 "\n" OPT_SEC "=%d\n", gOpts.bl3x[BL32_SEC].sec);
if (gOpts.bl3x[BL32_SEC].sec) {
fprintf(out, OPT_PATH "=%s\n", gOpts.bl3x[BL32_SEC].path);
fprintf(out, OPT_ADDR "=0x%08x\n", gOpts.bl3x[BL32_SEC].addr);
}
fprintf(out, SEC_BL33 "\n" OPT_SEC "=%d\n", gOpts.bl3x[BL33_SEC].sec);
if (gOpts.bl3x[BL33_SEC].sec) {
fprintf(out, OPT_PATH "=%s\n", gOpts.bl3x[BL33_SEC].path);
fprintf(out, OPT_ADDR "=0x%08x\n", gOpts.bl3x[BL33_SEC].addr);
}
fprintf(out, SEC_OUT "\n" OPT_OUT_PATH "=%s\n", gOpts.outPath);
}
static bool parseOpts(void)
{
FILE *file = NULL;
char *configPath = (gConfigPath == NULL) ? DEF_CONFIG_FILE : gConfigPath;
bool bl30ok = false, bl31ok = false, bl32ok = false, bl33ok = false;
bool outOk = false;
bool versionOk = false;
char buf[MAX_LINE_LEN];
bool ret = false;
file = fopen(configPath, "r");
if (!file) {
fprintf(stderr, "config(%s) not found!\n", configPath);
if (configPath == (char *)DEF_CONFIG_FILE) {
file = fopen(DEF_CONFIG_FILE, "w");
if (file) {
fprintf(stderr, "create defconfig\n");
printOpts(file);
}
}
goto end;
}
LOGD("start parse\n");
if (SCANF_EAT(file) != 0) {
goto end;
}
while (fscanf(file, "%s", buf) == 1) {
if (!strcmp(buf, SEC_VERSION)) {
versionOk = parseVersion(file);
if (!versionOk) {
LOGE("parseVersion failed!\n");
goto end;
}
} else if (!strcmp(buf, SEC_BL30)) {
bl30ok = parseBL3x(file, BL30_SEC);
if (!bl30ok) {
LOGE("parseBL30 failed!\n");
goto end;
}
} else if (!strcmp(buf, SEC_BL31)) {
bl31ok = parseBL3x(file, BL31_SEC);
if (!bl31ok) {
LOGE("parseBL31 failed!\n");
goto end;
}
} else if (!strcmp(buf, SEC_BL32)) {
bl32ok = parseBL3x(file, BL32_SEC);
if (!bl32ok) {
LOGE("parseBL32 failed!\n");
goto end;
}
} else if (!strcmp(buf, SEC_BL33)) {
bl33ok = parseBL3x(file, BL33_SEC);
if (!bl33ok) {
LOGE("parseBL33 failed!\n");
goto end;
}
} else if (!strcmp(buf, SEC_OUT)) {
outOk = parseOut(file);
if (!outOk) {
LOGE("parseOut failed!\n");
goto end;
}
} else if (buf[0] == '#') {
continue;
} else {
LOGE("unknown sec: %s!\n", buf);
goto end;
}
if (SCANF_EAT(file) != 0) {
goto end;
}
}
if (bl30ok && bl31ok && bl32ok && bl33ok && outOk)
ret = true;
end:
if (file)
fclose(file);
return ret;
}
bool initOpts(void)
{
memset(&gOpts, 0, sizeof(gOpts));
gOpts.major = DEF_MAJOR;
gOpts.minor = DEF_MINOR;
memcpy(&gOpts.bl3x[BL30_SEC].id, gBl3xID[BL30_SEC], 4);
strcpy(gOpts.bl3x[BL30_SEC].path, DEF_BL30_PATH);
memcpy(&gOpts.bl3x[BL31_SEC].id, gBl3xID[BL31_SEC], 4);
strcpy(gOpts.bl3x[BL31_SEC].path, DEF_BL31_PATH);
memcpy(&gOpts.bl3x[BL32_SEC].id, gBl3xID[BL32_SEC], 4);
strcpy(gOpts.bl3x[BL32_SEC].path, DEF_BL32_PATH);
memcpy(&gOpts.bl3x[BL33_SEC].id, gBl3xID[BL33_SEC], 4);
strcpy(gOpts.bl3x[BL33_SEC].path, DEF_BL33_PATH);
strcpy(gOpts.outPath, DEF_OUT_PATH);
return parseOpts();
}
static inline bool getFileSize(const char *path, uint32_t *size)
{
struct stat st;
if (stat(path, &st) < 0)
return false;
*size = st.st_size;
LOGD("path:%s, size:%d\n", path, *size);
return true;
}
void fill_file(FILE *file, char ch, uint32_t fill_size)
{
uint8_t fill_buffer[1024];
uint32_t cur_write;
memset(fill_buffer, ch, 1024);
while (fill_size > 0) {
cur_write = (fill_size >= 1024) ? 1024 : fill_size;
fwrite(fill_buffer, 1, cur_write, file);
fill_size -= cur_write;
}
}
bool filter_elf(uint32_t index, uint8_t *pMeta, uint32_t *pMetaNum,
bool *bElf)
{
bool ret = false;
FILE *file = NULL;
uint8_t *file_buffer = NULL;
uint32_t file_size, read_size, i;
Elf32_Ehdr *pElfHeader32;
Elf32_Phdr *pElfProgram32;
Elf64_Ehdr *pElfHeader64;
Elf64_Phdr *pElfProgram64;
bl_entry_t *pEntry = (bl_entry_t *)(pMeta + sizeof(bl_entry_t) * (*pMetaNum));
LOGD("index=%d,file=%s\n", index, gOpts.bl3x[index].path);
if (!getFileSize(gOpts.bl3x[index].path, &file_size))
goto exit_fileter_elf;
file = fopen(gOpts.bl3x[index].path, "rb");
if (!file) {
LOGE("open file(%s) failed\n", gOpts.bl3x[index].path);
goto exit_fileter_elf;
}
file_buffer = malloc(file_size);
if (!file_buffer)
goto exit_fileter_elf;
read_size = fread(file_buffer, 1, file_size, file);
if (read_size != file_size)
goto exit_fileter_elf;
if (*((uint32_t *)file_buffer) != ELF_MAGIC) {
ret = true;
*bElf = false;
goto exit_fileter_elf;
}
*bElf = true;
if (file_buffer[5] != 1) { /* only support little endian */
goto exit_fileter_elf;
}
if (*((uint16_t *)(file_buffer + EI_NIDENT)) !=
2) { /* only support executable case */
goto exit_fileter_elf;
}
if (file_buffer[4] == 2) {
pElfHeader64 = (Elf64_Ehdr *)file_buffer;
for (i = 0; i < pElfHeader64->e_phnum; i++) {
pElfProgram64 = (Elf64_Phdr *)(file_buffer + pElfHeader64->e_phoff +
i * pElfHeader64->e_phentsize);
if (pElfProgram64->p_type == 1) { /* PT_LOAD */
pEntry->id = gOpts.bl3x[index].id;
strcpy(pEntry->path, gOpts.bl3x[index].path);
pEntry->size = (uint32_t) pElfProgram64->p_filesz;
pEntry->offset = (uint32_t) pElfProgram64->p_offset;
pEntry->align_size = DO_ALIGN(pEntry->size, ENTRY_ALIGN);
pEntry->addr = (uint32_t) pElfProgram64->p_vaddr;
if (pEntry->align_size > BL3X_FILESIZE_MAX) {
LOGE("elf_file %s too large,segment=%d.\n", pEntry->path, i);
goto exit_fileter_elf;
}
LOGD("bl3%d: filesize = %d, imagesize = %d, segment=%d\n", index,
pEntry->size, pEntry->align_size, i);
pEntry++;
(*pMetaNum)++;
}
}
} else {
pElfHeader32 = (Elf32_Ehdr *)file_buffer;
for (i = 0; i < pElfHeader32->e_phnum; i++) {
pElfProgram32 = (Elf32_Phdr *)(file_buffer + pElfHeader32->e_phoff +
i * pElfHeader32->e_phentsize);
if (pElfProgram32->p_type == 1) { /* PT_LOAD */
pEntry->id = gOpts.bl3x[index].id;
strcpy(pEntry->path, gOpts.bl3x[index].path);
pEntry->size = pElfProgram32->p_filesz;
pEntry->offset = pElfProgram32->p_offset;
pEntry->align_size = DO_ALIGN(pEntry->size, ENTRY_ALIGN);
pEntry->addr = pElfProgram32->p_vaddr;
if (pEntry->align_size > BL3X_FILESIZE_MAX) {
LOGE("elf_file %s too large,segment=%d.\n", pEntry->path, i);
goto exit_fileter_elf;
}
LOGD("bl3%d: filesize = %d, imagesize = %d, segment=%d\n", index,
pEntry->size, pEntry->align_size, i);
pEntry++;
(*pMetaNum)++;
}
}
}
ret = true;
exit_fileter_elf:
if (file)
fclose(file);
if (file_buffer)
free(file_buffer);
return ret;
}
#define SHA256_CHECK_SZ ((uint32_t)(256 * 1024))
static bool bl3xHash256(uint8_t *pHash, uint8_t *pData, uint32_t nDataSize)
{
uint32_t nHashSize, nHasHashSize;
if (!pHash || !pData || !nDataSize) {
return false;
}
nHasHashSize = 0;
if (gSHAmode == SHA_SEL_256_RK) {
sha256_ctx ctx;
sha256_begin(&ctx);
while (nDataSize > 0) {
nHashSize = (nDataSize >= SHA256_CHECK_SZ) ? SHA256_CHECK_SZ : nDataSize;
sha256_hash(&ctx, pData + nHasHashSize, nHashSize);
nHasHashSize += nHashSize;
nDataSize -= nHashSize;
}
sha256_end(&ctx, pHash);
} else {
sha256_context ctx;
sha256_starts(&ctx);
while (nDataSize > 0) {
nHashSize = (nDataSize >= SHA256_CHECK_SZ) ? SHA256_CHECK_SZ : nDataSize;
sha256_update(&ctx, pData + nHasHashSize, nHashSize);
nHasHashSize += nHashSize;
nDataSize -= nHashSize;
}
sha256_finish(&ctx, pHash);
}
return true;
}
static bool mergetrust(void)
{
FILE *outFile = NULL;
uint32_t OutFileSize;
uint32_t SrcFileNum, SignOffset, nComponentNum;
TRUST_HEADER *pHead = NULL;
COMPONENT_DATA *pComponentData = NULL;
TRUST_COMPONENT *pComponent = NULL;
bool ret = false, bElf;
uint32_t i, n;
uint8_t *outBuf = NULL, *pbuf = NULL, *pMetaBuf = NULL;
bl_entry_t *pEntry = NULL;
if (!initOpts())
return false;
if (gDebug) {
printf("---------------\nUSING CONFIG:\n");
printOpts(stdout);
printf("---------------\n\n");
}
pMetaBuf = malloc(sizeof(bl_entry_t) * 32);
if (!pMetaBuf) {
LOGE("Merge trust image: malloc buffer error.\n");
goto end;
}
nComponentNum = SrcFileNum = 0;
for (i = BL30_SEC; i < BL_MAX_SEC; i++) {
if (gOpts.bl3x[i].sec) {
if (!filter_elf(i, pMetaBuf, &nComponentNum, &bElf)) {
LOGE("filter_elf %s file failed\n", gOpts.bl3x[i].path);
goto end;
}
if (!bElf) {
pEntry = (bl_entry_t *)(pMetaBuf + sizeof(bl_entry_t) * nComponentNum);
pEntry->id = gOpts.bl3x[i].id;
strcpy(pEntry->path, gOpts.bl3x[i].path);
getFileSize(pEntry->path, &pEntry->size);
pEntry->offset = 0;
pEntry->align_size = DO_ALIGN(pEntry->size, ENTRY_ALIGN);
pEntry->addr = gOpts.bl3x[i].addr;
if (pEntry->align_size > BL3X_FILESIZE_MAX) {
LOGE("file %s too large.\n", gOpts.bl3x[i].path);
goto end;
}
LOGD("bl3%d: filesize = %d, imagesize = %d\n", i, pEntry->size,
pEntry->align_size);
pEntry++;
nComponentNum++;
}
}
}
LOGD("bl3x bin sec = %d\n", nComponentNum);
/* 2048bytes for head */
memset(gBuf, 0, TRUST_HEADER_SIZE);
/* Trust Head */
pHead = (TRUST_HEADER *)gBuf;
memcpy(&pHead->tag, TRUST_HEAD_TAG, 4);
pHead->version = (getBCD(gOpts.major) << 8) | getBCD(gOpts.minor);
pHead->flags = 0;
pHead->flags |= (gSHAmode << 0);
pHead->flags |= (gRSAmode << 4);
SignOffset = sizeof(TRUST_HEADER) + nComponentNum * sizeof(COMPONENT_DATA);
LOGD("trust bin sign offset = %d\n", SignOffset);
pHead->size = (nComponentNum << 16) | (SignOffset >> 2);
pComponent = (TRUST_COMPONENT *)(gBuf + SignOffset + SIGNATURE_SIZE);
pComponentData = (COMPONENT_DATA *)(gBuf + sizeof(TRUST_HEADER));
OutFileSize = TRUST_HEADER_SIZE;
pEntry = (bl_entry_t *)pMetaBuf;
for (i = 0; i < nComponentNum; i++) {
/* bl3x load and run address */
pComponentData->LoadAddr = pEntry->addr;
pComponent->ComponentID = pEntry->id;
pComponent->StorageAddr = (OutFileSize >> 9);
pComponent->ImageSize = (pEntry->align_size >> 9);
LOGD("bl3%c: LoadAddr = 0x%08x, StorageAddr = %d, ImageSize = %d\n",
(char)((pEntry->id & 0xFF000000) >> 24), pComponentData->LoadAddr,
pComponent->StorageAddr, pComponent->ImageSize);
OutFileSize += pEntry->align_size;
pComponentData++;
pComponent++;
pEntry++;
}
/* create out file */
outFile = fopen(gOpts.outPath, "wb+");
if (!outFile) {
LOGE("open out file(%s) failed\n", gOpts.outPath);
outFile = fopen(DEF_OUT_PATH, "wb");
if (!outFile) {
LOGE("open default out file:%s failed!\n", DEF_OUT_PATH);
goto end;
}
}
/* 0 for g_trust_max_num backups */
#if 0
/* save trust head to out file */
if (!fwrite(gBuf, TRUST_HEADER_SIZE, 1, outFile))
goto end;
/* save trust bl3x bin */
for (i = BL30_SEC; i < BL_MAX_SEC; i++) {
if (gOpts.bl3x[i].sec) {
FILE *inFile = fopen(gOpts.bl3x[i].path, "rb");
if (!inFile)
goto end;
memset(gBuf, 0, imagesize[i]);
if (!fread(gBuf, filesize[i], 1, inFile))
goto end;
fclose(inFile);
if (!fwrite(gBuf, imagesize[i], 1, outFile))
goto end;
}
}
#else
/* check bin size */
if (OutFileSize > g_trust_max_size) {
LOGE("Merge trust image: trust bin size overfull.\n");
goto end;
}
/* malloc buffer */
pbuf = outBuf = calloc(g_trust_max_size, g_trust_max_num);
if (!outBuf) {
LOGE("Merge trust image: calloc buffer error.\n");
goto end;
}
memset(outBuf, 0, (g_trust_max_size * g_trust_max_num));
/* save trust head data */
memcpy(pbuf, gBuf, TRUST_HEADER_SIZE);
pbuf += TRUST_HEADER_SIZE;
uint8_t *pHashData = NULL;
pComponentData = (COMPONENT_DATA *)(outBuf + sizeof(TRUST_HEADER));
/* save trust bl3x bin */
pEntry = (bl_entry_t *)pMetaBuf;
for (i = 0; i < nComponentNum; i++) {
FILE *inFile = fopen(pEntry->path, "rb");
if (!inFile)
goto end;
memset(gBuf, 0, pEntry->align_size);
fseek(inFile, pEntry->offset, SEEK_SET);
if (!fread(gBuf, pEntry->size, 1, inFile))
goto end;
fclose(inFile);
/* bl3x bin hash256 */
pHashData = (uint8_t *)&pComponentData->HashData[0];
bl3xHash256(pHashData, gBuf, pEntry->align_size);
memcpy(pbuf, gBuf, pEntry->align_size);
pComponentData++;
pbuf += pEntry->align_size;
pEntry++;
}
/* copy other (g_trust_max_num - 1) backup bin */
for (n = 1; n < g_trust_max_num; n++) {
memcpy(outBuf + g_trust_max_size * n, outBuf, g_trust_max_size);
}
/* save date to file */
if (!fwrite(outBuf, g_trust_max_size * g_trust_max_num, 1, outFile)) {
LOGE("Merge trust image: write file error.\n");
goto end;
}
#endif
ret = true;
end:
/*
for (i = BL30_SEC; i < BL_MAX_SEC; i++) {
if (gOpts.bl3x[i].sec != false) {
if (gOpts.bl3x[i].is_elf) {
if (stat(gOpts.bl3x[i].path, &st) >= 0)
remove(gOpts.bl3x[i].path);
}
}
}
*/
if (pMetaBuf)
free(pMetaBuf);
if (outBuf)
free(outBuf);
if (outFile)
fclose(outFile);
return ret;
}
static int saveDatatoFile(char *FileName, void *pBuf, uint32_t size)
{
FILE *OutFile = NULL;
int ret = -1;
OutFile = fopen(FileName, "wb");
if (!OutFile) {
printf("open OutPutFlie:%s failed!\n", FileName);
goto end;
}
if (1 != fwrite(pBuf, size, 1, OutFile)) {
printf("write output file failed!\n");
goto end;
}
ret = 0;
end:
if (OutFile)
fclose(OutFile);
return ret;
}
static bool unpacktrust(char *path)
{
FILE *FileSrc = NULL;
uint32_t FileSize;
uint8_t *pBuf = NULL;
uint32_t SrcFileNum, SignOffset;
TRUST_HEADER *pHead = NULL;
COMPONENT_DATA *pComponentData = NULL;
TRUST_COMPONENT *pComponent = NULL;
char str[MAX_LINE_LEN];
bool ret = false;
uint32_t i;
FileSrc = fopen(path, "rb");
if (FileSrc == NULL) {
printf("open %s failed!\n", path);
goto end;
}
if (getFileSize(path, &FileSize) == false) {
printf("File Size failed!\n");
goto end;
}
printf("File Size = %d\n", FileSize);
pBuf = (uint8_t *)malloc(FileSize);
if (1 != fread(pBuf, FileSize, 1, FileSrc)) {
printf("read input file failed!\n");
goto end;
}
pHead = (TRUST_HEADER *)pBuf;
memcpy(str, &pHead->tag, 4);
str[4] = '\0';
printf("Header Tag:%s\n", str);
printf("Header version:%d\n", pHead->version);
printf("Header flag:%d\n", pHead->flags);
SrcFileNum = (pHead->size >> 16) & 0xffff;
SignOffset = (pHead->size & 0xffff) << 2;
printf("SrcFileNum:%d\n", SrcFileNum);
printf("SignOffset:%d\n", SignOffset);
pComponent = (TRUST_COMPONENT *)(pBuf + SignOffset + SIGNATURE_SIZE);
pComponentData = (COMPONENT_DATA *)(pBuf + sizeof(TRUST_HEADER));
for (i = 0; i < SrcFileNum; i++) {
printf("Component %d:\n", i);
memcpy(str, &pComponent->ComponentID, 4);
str[4] = '\0';
printf("ComponentID:%s\n", str);
printf("StorageAddr:0x%x\n", pComponent->StorageAddr);
printf("ImageSize:0x%x\n", pComponent->ImageSize);
printf("LoadAddr:0x%x\n", pComponentData->LoadAddr);
saveDatatoFile(str, pBuf + (pComponent->StorageAddr << 9),
pComponent->ImageSize << 9);
pComponentData++;
pComponent++;
}
ret = true;
end:
if (FileSrc)
fclose(FileSrc);
if (pBuf)
free(pBuf);
return ret;
}
static void printHelp(void)
{
printf("Usage: trust_merger [options]... FILE\n");
printf(
"Merge or unpack Rockchip's trust image (Default action is to merge.)\n");
printf("Options:\n");
printf("\t" OPT_MERGE "\t\t\tMerge trust with specified config.\n");
printf("\t" OPT_UNPACK "\t\tUnpack specified trust to current dir.\n");
printf("\t" OPT_VERBOSE "\t\tDisplay more runtime informations.\n");
printf("\t" OPT_HELP "\t\t\tDisplay this information.\n");
printf("\t" OPT_VERSION "\t\tDisplay version information.\n");
printf("\t" OPT_SUBFIX "\t\tSpec subfix.\n");
printf("\t" OPT_REPLACE "\t\tReplace some part of binary path.\n");
printf("\t" OPT_RSA "\t\t\tRSA mode.\"--rsa [mode]\", [mode] can be: "
"0(none), 1(1024), 2(2048), 3(2048 pss).\n");
printf("\t" OPT_SHA
"\t\t\tSHA mode.\"--sha [mode]\", [mode] can be: 0(none), 1(160), "
"2(256 RK big endian), 3(256 little endian).\n");
printf("\t" OPT_SIZE "\t\t\tTrustImage size.\"--size [per image KB size] "
"[copy count]\", per image must be 64KB aligned\n");
}
int main(int argc, char **argv)
{
bool merge = true;
char *optPath = NULL;
int i;
gConfigPath = NULL;
for (i = 1; i < argc; i++) {
if (!strcmp(OPT_VERBOSE, argv[i])) {
gDebug = true;
} else if (!strcmp(OPT_HELP, argv[i])) {
printHelp();
return 0;
} else if (!strcmp(OPT_VERSION, argv[i])) {
printf("trust_merger (cwz@rock-chips.com)\t" VERSION "\n");
return 0;
} else if (!strcmp(OPT_MERGE, argv[i])) {
merge = true;
} else if (!strcmp(OPT_UNPACK, argv[i])) {
merge = false;
} else if (!strcmp(OPT_SUBFIX, argv[i])) {
gSubfix = true;
printf("trust_merger: Spec subfix!\n");
} else if (!strcmp(OPT_REPLACE, argv[i])) {
i++;
gLegacyPath = argv[i];
i++;
gNewPath = argv[i];
} else if (!strcmp(OPT_RSA, argv[i])) {
i++;
if (!is_digit(*(argv[i]))) {
printHelp();
return -1;
}
gRSAmode = *(argv[i]) - '0';
LOGD("rsa mode:%d\n", gRSAmode);
} else if (!strcmp(OPT_SHA, argv[i])) {
i++;
if (!is_digit(*(argv[i]))) {
printHelp();
return -1;
}
gSHAmode = *(argv[i]) - '0';
LOGD("sha mode:%d\n", gSHAmode);
} else if (!strcmp(OPT_SIZE, argv[i])) {
/* Per trust image size */
g_trust_max_size = strtoul(argv[++i], NULL, 10);
/*
* Usually, it must be at 512kb align due to preloader
* detects every 512kb. But some product has critial
* flash size requirement, we have to make it small than
* 512KB.
*/
if (g_trust_max_size % 64) {
printHelp();
return -1;
}
g_trust_max_size *= 1024; /* bytes */
/* Total backup numbers */
g_trust_max_num = strtoul(argv[++i], NULL, 10);
} else {
if (optPath) {
fprintf(stderr, "only need one path arg, but we have:\n%s\n%s.\n",
optPath, argv[i]);
printHelp();
return -1;
}
optPath = argv[i];
}
}
if (!merge && !optPath) {
fprintf(stderr, "need set out path to unpack!\n");
printHelp();
return -1;
}
if (merge) {
LOGD("do_merge\n");
gConfigPath = optPath;
if (!mergetrust()) {
fprintf(stderr, "merge failed!\n");
return -1;
}
printf("merge success(%s)\n", gOpts.outPath);
} else {
LOGD("do_unpack\n");
if (!unpacktrust(optPath)) {
fprintf(stderr, "unpack failed!\n");
return -1;
}
printf("unpack success\n");
}
return 0;
}

View File

@ -0,0 +1,185 @@
/*
* Rockchip trust image generator
*
* (C) Copyright 2008-2015 Fuzhou Rockchip Electronics Co., Ltd
* Peter, Software Engineering, <superpeter.cai@gmail.com>.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef TRUST_MERGER_H
#define TRUST_MERGER_H
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <stdbool.h>
#define VERSION "v1.0 (2015-06-15)"
#define DO_ALIGN(a, b) (((a) > 0) ? ((((a) - 1) / (b) + 1) * (b)) : (a))
/* config file */
#define SEC_VERSION "[VERSION]"
#define SEC_BL30 "[BL30_OPTION]"
#define SEC_BL31 "[BL31_OPTION]"
#define SEC_BL32 "[BL32_OPTION]"
#define SEC_BL33 "[BL33_OPTION]"
#define SEC_OUT "[OUTPUT]"
#define OPT_MAJOR "MAJOR"
#define OPT_MINOR "MINOR"
#define OPT_SEC "SEC"
#define OPT_PATH "PATH"
#define OPT_ADDR "ADDR"
#define OPT_OUT_PATH "PATH"
/* options */
#define OPT_VERBOSE "--verbose"
#define OPT_HELP "--help"
#define OPT_VERSION "--version"
#define OPT_MERGE "--pack"
#define OPT_UNPACK "--unpack"
#define OPT_SUBFIX "--subfix"
#define OPT_REPLACE "--replace"
#define OPT_RSA "--rsa"
#define OPT_SHA "--sha"
#define OPT_SIZE "--size"
#define DEF_MAJOR 0
#define DEF_MINOR 0
#define DEF_BL30_PATH "bl30.bin"
#define DEF_BL31_PATH "bl31.bin"
#define DEF_BL32_PATH "bl32.bin"
#define DEF_BL33_PATH "bl33.bin"
#define DEF_OUT_PATH "trust.img"
#define DEF_CONFIG_FILE "RKTRUST.ini"
#define MAX_LINE_LEN 256
#define SCANF_EAT(in) fscanf(in, "%*[ \r\n\t/]")
#define ENTRY_ALIGN (2048)
enum {
BL30_SEC = 0,
BL31_SEC,
BL32_SEC,
BL33_SEC,
BL_MAX_SEC
};
typedef struct {
bool sec;
uint32_t id;
char path[MAX_LINE_LEN];
uint32_t addr;
uint32_t offset;
uint32_t size;
uint32_t align_size;
} bl_entry_t;
typedef struct {
uint16_t major;
uint16_t minor;
bl_entry_t bl3x[BL_MAX_SEC];
char outPath[MAX_LINE_LEN];
} OPT_T;
#define TRUST_HEAD_TAG "BL3X"
#define SIGNATURE_SIZE 256
#define TRUST_HEADER_SIZE 2048
typedef struct {
uint32_t tag;
uint32_t version;
uint32_t flags;
uint32_t size;
uint32_t reserved[4];
uint32_t RSA_N[64];
uint32_t RSA_E[64];
uint32_t RSA_C[64];
} TRUST_HEADER, *PTRUST_HEADER;
typedef struct {
uint32_t HashData[8];
uint32_t LoadAddr;
uint32_t reserved[3];
} COMPONENT_DATA, *PCOMPONENT_DATA;
typedef struct {
uint32_t ComponentID;
uint32_t StorageAddr;
uint32_t ImageSize;
uint32_t reserved;
} TRUST_COMPONENT, *PTRUST_COMPONENT;
#define EI_NIDENT 16
#define ELF_MAGIC 0x464c457f
typedef struct {
uint8_t e_ident[EI_NIDENT];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
uint32_t e_entry; /* Entry point */
uint32_t e_phoff;
uint32_t e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
} Elf32_Ehdr;
typedef struct {
uint8_t e_ident[EI_NIDENT]; /* ELF "magic number" */
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
uint64_t e_entry; /* Entry point virtual address */
uint64_t e_phoff; /* Program header table file offset */
uint64_t e_shoff; /* Section header table file offset */
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
} Elf64_Ehdr;
typedef struct {
uint32_t p_type;
uint32_t p_offset;
uint32_t p_vaddr;
uint32_t p_paddr;
uint32_t p_filesz;
uint32_t p_memsz;
uint32_t p_flags;
uint32_t p_align;
} Elf32_Phdr;
typedef struct {
uint32_t p_type;
uint32_t p_flags;
uint64_t p_offset; /* Segment file offset */
uint64_t p_vaddr; /* Segment virtual address */
uint64_t p_paddr; /* Segment physical address */
uint64_t p_filesz; /* Segment size in file */
uint64_t p_memsz; /* Segment size in memory */
uint64_t p_align; /* Segment alignment, file & memory */
} Elf64_Phdr;
#endif /* TRUST_MERGER_H */