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:
parent
bbef4bcaa1
commit
23ba6841cc
15
make.sh
15
make.sh
|
@ -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"
|
||||
|
|
|
@ -28,3 +28,8 @@
|
|||
/sunxi-spl-image-builder
|
||||
/ubsha1
|
||||
/xway-swap-bytes
|
||||
/trust_merger
|
||||
/boot_merger
|
||||
/loaderimage
|
||||
/checksum
|
||||
/resource_tool
|
||||
|
|
|
@ -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.
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
Loading…
Reference in New Issue