diff --git a/maintainers.rst b/maintainers.rst index 5fb4494..1c88726 100644 --- a/maintainers.rst +++ b/maintainers.rst @@ -81,7 +81,7 @@ :F: docs/plat/marvell/ :F: plat/marvell/ :F: drivers/marvell/ -:F: tools/doimage/ +:F: tools/marvell/ NVidia platform ports --------------------- diff --git a/plat/marvell/a8k/common/a8k_common.mk b/plat/marvell/a8k/common/a8k_common.mk index a42481f..a589004 100644 --- a/plat/marvell/a8k/common/a8k_common.mk +++ b/plat/marvell/a8k/common/a8k_common.mk @@ -4,7 +4,7 @@ # SPDX-License-Identifier: BSD-3-Clause # https://spdx.org/licenses -include tools/doimage/doimage.mk +include tools/marvell/doimage/doimage.mk PLAT_FAMILY := a8k PLAT_FAMILY_BASE := plat/marvell/$(PLAT_FAMILY) @@ -29,7 +29,7 @@ AP_NUM := 1 $(eval $(call add_define,AP_NUM)) -DOIMAGEPATH ?= tools/doimage +DOIMAGEPATH ?= tools/marvell/doimage DOIMAGETOOL ?= ${DOIMAGEPATH}/doimage ROM_BIN_EXT ?= $(BUILD_PLAT)/ble.bin diff --git a/tools/doimage/Makefile b/tools/doimage/Makefile deleted file mode 100644 index 9f0d89d..0000000 --- a/tools/doimage/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -# -# Copyright (C) 2018 Marvell International Ltd. -# -# SPDX-License-Identifier: BSD-3-Clause -# https://spdx.org/licenses - -PROJECT = doimage -OBJECTS = doimage.o - -HOSTCCFLAGS = -Wall -Werror -ifeq (${DEBUG},1) - HOSTCCFLAGS += -g -O0 -DDEBUG -else - HOSTCCFLAGS += -O2 -endif - -ifeq (${MARVELL_SECURE_BOOT},1) -DOIMAGE_CC_FLAGS := -DCONFIG_MVEBU_SECURE_BOOT -DOIMAGE_LD_FLAGS := -lconfig -lmbedtls -lmbedcrypto -lmbedx509 -endif - -HOSTCCFLAGS += ${DOIMAGE_CC_FLAGS} - -# Make soft links and include from local directory otherwise wrong headers -# could get pulled in from firmware tree. -INCLUDE_PATHS = -I. - -HOSTCC ?= gcc -RM := rm -rf - -.PHONY: all clean - -all: ${PROJECT} - -${PROJECT}: ${OBJECTS} Makefile - @echo " HOSTLD $@" - ${Q}${HOSTCC} ${OBJECTS} ${DOIMAGE_LD_FLAGS} -o $@ - @echo - @echo "Built $@ successfully" - @echo - -%.o: %.c Makefile - @echo " HOSTCC $<" - ${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INCLUDE_PATHS} $< -o $@ - -clean: - ${Q}${RM} ${PROJECT} - ${Q}${RM} ${OBJECTS} diff --git a/tools/doimage/doimage.c b/tools/doimage/doimage.c deleted file mode 100644 index 82fd375..0000000 --- a/tools/doimage/doimage.c +++ /dev/null @@ -1,1762 +0,0 @@ -/* - * Copyright (C) 2018 Marvell International Ltd. - * - * SPDX-License-Identifier: BSD-3-Clause - * https://spdx.org/licenses - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_MVEBU_SECURE_BOOT -#include /* for parsing config file */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -/* mbedTLS stuff */ -#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ENTROPY_C) && \ - defined(MBEDTLS_SHA256_C) && \ - defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_FS_IO) && \ - defined(MBEDTLS_CTR_DRBG_C) -#include -#include -#include -#include -#include -#include -#include -#else -#error "Bad mbedTLS configuration!" -#endif -#endif /* CONFIG_MVEBU_SECURE_BOOT */ - -#define MAX_FILENAME 256 -#define CSK_ARR_SZ 16 -#define CSK_ARR_EMPTY_FILE "*" -#define AES_KEY_BIT_LEN 256 -#define AES_KEY_BYTE_LEN (AES_KEY_BIT_LEN >> 3) -#define AES_BLOCK_SZ 16 -#define RSA_SIGN_BYTE_LEN 256 -#define MAX_RSA_DER_BYTE_LEN 524 -/* Number of address pairs in control array */ -#define CP_CTRL_EL_ARRAY_SZ 32 - -#define VERSION_STRING "Marvell(C) doimage utility version 3.2" - -/* A8K definitions */ - -/* Extension header types */ -#define EXT_TYPE_SECURITY 0x1 -#define EXT_TYPE_BINARY 0x2 - -#define MAIN_HDR_MAGIC 0xB105B002 - -/* PROLOG alignment considerations: - * 128B: To allow supporting XMODEM protocol. - * 8KB: To align the boot image to the largest NAND page size, and simplify - * the read operations from NAND. - * We choose the largest page size, in order to use a single image for all - * NAND page sizes. - */ -#define PROLOG_ALIGNMENT (8 << 10) - -/* UART argument bitfield */ -#define UART_MODE_UNMODIFIED 0x0 -#define UART_MODE_DISABLE 0x1 -#define UART_MODE_UPDATE 0x2 - -typedef struct _main_header { - uint32_t magic; /* 0-3 */ - uint32_t prolog_size; /* 4-7 */ - uint32_t prolog_checksum; /* 8-11 */ - uint32_t boot_image_size; /* 12-15 */ - uint32_t boot_image_checksum; /* 16-19 */ - uint32_t rsrvd0; /* 20-23 */ - uint32_t load_addr; /* 24-27 */ - uint32_t exec_addr; /* 28-31 */ - uint8_t uart_cfg; /* 32 */ - uint8_t baudrate; /* 33 */ - uint8_t ext_count; /* 34 */ - uint8_t aux_flags; /* 35 */ - uint32_t io_arg_0; /* 36-39 */ - uint32_t io_arg_1; /* 40-43 */ - uint32_t io_arg_2; /* 43-47 */ - uint32_t io_arg_3; /* 48-51 */ - uint32_t rsrvd1; /* 52-55 */ - uint32_t rsrvd2; /* 56-59 */ - uint32_t rsrvd3; /* 60-63 */ -} header_t; - -typedef struct _ext_header { - uint8_t type; - uint8_t offset; - uint16_t reserved; - uint32_t size; -} ext_header_t; - -typedef struct _sec_entry { - uint8_t kak_key[MAX_RSA_DER_BYTE_LEN]; - uint32_t jtag_delay; - uint32_t box_id; - uint32_t flash_id; - uint32_t jtag_en; - uint32_t encrypt_en; - uint32_t efuse_dis; - uint8_t header_sign[RSA_SIGN_BYTE_LEN]; - uint8_t image_sign[RSA_SIGN_BYTE_LEN]; - uint8_t csk_keys[CSK_ARR_SZ][MAX_RSA_DER_BYTE_LEN]; - uint8_t csk_sign[RSA_SIGN_BYTE_LEN]; - uint32_t cp_ctrl_arr[CP_CTRL_EL_ARRAY_SZ]; - uint32_t cp_efuse_arr[CP_CTRL_EL_ARRAY_SZ]; -} sec_entry_t; - -/* A8K definitions end */ - -/* UART argument bitfield */ -#define UART_MODE_UNMODIFIED 0x0 -#define UART_MODE_DISABLE 0x1 -#define UART_MODE_UPDATE 0x2 - -#define uart_set_mode(arg, mode) (arg |= (mode & 0x3)) - -typedef struct _sec_options { -#ifdef CONFIG_MVEBU_SECURE_BOOT - char aes_key_file[MAX_FILENAME+1]; - char kak_key_file[MAX_FILENAME+1]; - char csk_key_file[CSK_ARR_SZ][MAX_FILENAME+1]; - uint32_t box_id; - uint32_t flash_id; - uint32_t jtag_delay; - uint8_t csk_index; - uint8_t jtag_enable; - uint8_t efuse_disable; - uint32_t cp_ctrl_arr[CP_CTRL_EL_ARRAY_SZ]; - uint32_t cp_efuse_arr[CP_CTRL_EL_ARRAY_SZ]; - mbedtls_pk_context kak_pk; - mbedtls_pk_context csk_pk[CSK_ARR_SZ]; - uint8_t aes_key[AES_KEY_BYTE_LEN]; - uint8_t *encrypted_image; - uint32_t enc_image_sz; -#endif -} sec_options; - -typedef struct _options { - char bin_ext_file[MAX_FILENAME+1]; - char sec_cfg_file[MAX_FILENAME+1]; - sec_options *sec_opts; - uint32_t load_addr; - uint32_t exec_addr; - uint32_t baudrate; - uint8_t disable_print; - int8_t key_index; /* For header signatures verification only */ - uint32_t nfc_io_args; -} options_t; - -void usage_err(char *msg) -{ - fprintf(stderr, "Error: %s\n", msg); - fprintf(stderr, "run 'doimage -h' to get usage information\n"); - exit(-1); -} - -void usage(void) -{ - printf("\n\n%s\n\n", VERSION_STRING); - printf("Usage: doimage [options] [output_file]\n"); - printf("create bootrom image from u-boot and boot extensions\n\n"); - - printf("Arguments\n"); - printf(" input_file name of boot image file.\n"); - printf(" if -p is used, name of the bootrom image file"); - printf(" to parse.\n"); - printf(" output_file name of output bootrom image file\n"); - - printf("\nOptions\n"); - printf(" -s target SOC name. supports a8020,a7020\n"); - printf(" different SOCs may have different boot image\n"); - printf(" format so it's mandatory to know the target SOC\n"); - printf(" -i boot I/F name. supports nand, spi, nor\n"); - printf(" This affects certain parameters coded in the\n"); - printf(" image header\n"); - printf(" -l boot image load address. default is 0x0\n"); - printf(" -e boot image entry address. default is 0x0\n"); - printf(" -b binary extension image file.\n"); - printf(" This image is executed before the boot image.\n"); - printf(" This is typically used to initialize the memory "); - printf(" controller.\n"); - printf(" Currently supports only a single file.\n"); -#ifdef CONFIG_MVEBU_SECURE_BOOT - printf(" -c Make trusted boot image using parameters\n"); - printf(" from the configuration file.\n"); -#endif - printf(" -p Parse and display a pre-built boot image\n"); -#ifdef CONFIG_MVEBU_SECURE_BOOT - printf(" -k Key index for RSA signatures verification\n"); - printf(" when parsing the boot image\n"); -#endif - printf(" -m Disable prints of bootrom and binary extension\n"); - printf(" -u UART baudrate used for bootrom prints.\n"); - printf(" Must be multiple of 1200\n"); - printf(" -h Show this help message\n"); - printf(" IO-ROM NFC-NAND boot parameters:\n"); - printf(" -n NAND device block size in KB [Default is 64KB].\n"); - printf(" -t NAND cell technology (SLC [Default] or MLC)\n"); - - exit(-1); -} - -/* globals */ -static options_t opts = { - .bin_ext_file = "NA", - .sec_cfg_file = "NA", - .sec_opts = 0, - .load_addr = 0x0, - .exec_addr = 0x0, - .disable_print = 0, - .baudrate = 0, - .key_index = -1, -}; - -int get_file_size(char *filename) -{ - struct stat st; - - if (stat(filename, &st) == 0) - return st.st_size; - - return -1; -} - -uint32_t checksum32(uint32_t *start, int len) -{ - uint32_t sum = 0; - uint32_t *startp = start; - - do { - sum += *startp; - startp++; - len -= 4; - } while (len > 0); - - return sum; -} - -/******************************************************************************* - * create_rsa_signature (memory buffer content) - * Create RSASSA-PSS/SHA-256 signature for memory buffer - * using RSA Private Key - * INPUT: - * pk_ctx Private Key context - * input memory buffer - * ilen buffer length - * pers personalization string for seeding the RNG. - * For instance a private key file name. - * OUTPUT: - * signature RSA-2048 signature - * RETURN: - * 0 on success - */ -#ifdef CONFIG_MVEBU_SECURE_BOOT -int create_rsa_signature(mbedtls_pk_context *pk_ctx, - const unsigned char *input, - size_t ilen, - const char *pers, - uint8_t *signature) -{ - mbedtls_entropy_context entropy; - mbedtls_ctr_drbg_context ctr_drbg; - unsigned char hash[32]; - unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; - int rval; - - /* Not sure this is required, - * but it's safer to start with empty buffers - */ - memset(hash, 0, sizeof(hash)); - memset(buf, 0, sizeof(buf)); - - mbedtls_ctr_drbg_init(&ctr_drbg); - mbedtls_entropy_init(&entropy); - - /* Seed the random number generator */ - rval = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, - (const unsigned char *)pers, strlen(pers)); - if (rval != 0) { - fprintf(stderr, " Failed in ctr_drbg_init call (%d)!\n", rval); - goto sign_exit; - } - - /* The PK context should be already initialized. - * Set the padding type for this PK context - */ - mbedtls_rsa_set_padding(mbedtls_pk_rsa(*pk_ctx), - MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256); - - /* First compute the SHA256 hash for the input blob */ - mbedtls_sha256(input, ilen, hash, 0); - - /* Then calculate the hash signature */ - rval = mbedtls_rsa_rsassa_pss_sign(mbedtls_pk_rsa(*pk_ctx), - mbedtls_ctr_drbg_random, - &ctr_drbg, - MBEDTLS_RSA_PRIVATE, - MBEDTLS_MD_SHA256, 0, hash, buf); - if (rval != 0) { - fprintf(stderr, - "Failed to create RSA signature for %s. Error %d\n", - pers, rval); - goto sign_exit; - } - memcpy(signature, buf, 256); - -sign_exit: - mbedtls_ctr_drbg_free(&ctr_drbg); - mbedtls_entropy_free(&entropy); - - return rval; -} /* end of create_rsa_signature */ - -/******************************************************************************* - * verify_rsa_signature (memory buffer content) - * Verify RSASSA-PSS/SHA-256 signature for memory buffer - * using RSA Public Key - * INPUT: - * pub_key Public Key buffer - * ilen Public Key buffer length - * input memory buffer - * ilen buffer length - * pers personalization string for seeding the RNG. - * signature RSA-2048 signature - * OUTPUT: - * none - * RETURN: - * 0 on success - */ -int verify_rsa_signature(const unsigned char *pub_key, - size_t klen, - const unsigned char *input, - size_t ilen, - const char *pers, - uint8_t *signature) -{ - mbedtls_entropy_context entropy; - mbedtls_ctr_drbg_context ctr_drbg; - mbedtls_pk_context pk_ctx; - unsigned char hash[32]; - int rval; - - /* Not sure this is required, - * but it's safer to start with empty buffer - */ - memset(hash, 0, sizeof(hash)); - - mbedtls_pk_init(&pk_ctx); - mbedtls_ctr_drbg_init(&ctr_drbg); - mbedtls_entropy_init(&entropy); - - /* Seed the random number generator */ - rval = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, - (const unsigned char *)pers, strlen(pers)); - if (rval != 0) { - fprintf(stderr, " Failed in ctr_drbg_init call (%d)!\n", rval); - goto verify_exit; - } - - /* Check ability to read the public key */ - rval = mbedtls_pk_parse_public_key(&pk_ctx, pub_key, - MAX_RSA_DER_BYTE_LEN); - if (rval != 0) { - fprintf(stderr, " Failed in pk_parse_public_key (%#x)!\n", - rval); - goto verify_exit; - } - - /* Set the padding type for the new PK context */ - mbedtls_rsa_set_padding(mbedtls_pk_rsa(pk_ctx), - MBEDTLS_RSA_PKCS_V21, - MBEDTLS_MD_SHA256); - - /* Compute the SHA256 hash for the input buffer */ - mbedtls_sha256(input, ilen, hash, 0); - - rval = mbedtls_rsa_rsassa_pss_verify(mbedtls_pk_rsa(pk_ctx), - mbedtls_ctr_drbg_random, - &ctr_drbg, - MBEDTLS_RSA_PUBLIC, - MBEDTLS_MD_SHA256, 0, - hash, signature); - if (rval != 0) - fprintf(stderr, "Failed to verify signature (%d)!\n", rval); - -verify_exit: - - mbedtls_pk_free(&pk_ctx); - mbedtls_ctr_drbg_free(&ctr_drbg); - mbedtls_entropy_free(&entropy); - return rval; -} /* end of verify_rsa_signature */ - -/******************************************************************************* - * image_encrypt - * Encrypt image buffer using AES-256-CBC scheme. - * The resulting image is saved into opts.sec_opts->encrypted_image - * and the adjusted image size into opts.sec_opts->enc_image_sz - * First AES_BLOCK_SZ bytes of the output image contain IV - * INPUT: - * buf Source buffer to encrypt - * blen Source buffer length - * OUTPUT: - * none - * RETURN: - * 0 on success - */ -int image_encrypt(uint8_t *buf, uint32_t blen) -{ - struct timeval tv; - char *ptmp = (char *)&tv; - unsigned char digest[32]; - unsigned char IV[AES_BLOCK_SZ]; - int i, k; - mbedtls_aes_context aes_ctx; - int rval = -1; - uint8_t *test_img = 0; - - if (AES_BLOCK_SZ > 32) { - fprintf(stderr, "Unsupported AES block size %d\n", - AES_BLOCK_SZ); - return rval; - } - - mbedtls_aes_init(&aes_ctx); - memset(IV, 0, AES_BLOCK_SZ); - memset(digest, 0, 32); - - /* Generate initialization vector and init the AES engine - * Use file name XOR current time and finally SHA-256 - * [0...AES_BLOCK_SZ-1] - */ - k = strlen(opts.sec_opts->aes_key_file); - if (k > AES_BLOCK_SZ) - k = AES_BLOCK_SZ; - memcpy(IV, opts.sec_opts->aes_key_file, k); - gettimeofday(&tv, 0); - - for (i = 0, k = 0; i < AES_BLOCK_SZ; i++, - k = (k+1) % sizeof(struct timeval)) - IV[i] ^= ptmp[k]; - - /* compute SHA-256 digest of the results - * and use it as the init vector (IV) - */ - mbedtls_sha256(IV, AES_BLOCK_SZ, digest, 0); - memcpy(IV, digest, AES_BLOCK_SZ); - mbedtls_aes_setkey_enc(&aes_ctx, opts.sec_opts->aes_key, - AES_KEY_BIT_LEN); - - /* The output image has to include extra space for IV - * and to be aligned to the AES block size. - * The input image buffer has to be already aligned to AES_BLOCK_SZ - * and padded with zeroes - */ - opts.sec_opts->enc_image_sz = (blen + 2 * AES_BLOCK_SZ - 1) & - ~(AES_BLOCK_SZ - 1); - opts.sec_opts->encrypted_image = calloc(opts.sec_opts->enc_image_sz, 1); - if (opts.sec_opts->encrypted_image == 0) { - fprintf(stderr, "Failed to allocate encrypted image!\n"); - goto encrypt_exit; - } - - /* Put IV into the output buffer next to the encrypted image - * Since the IV is modified by the encryption function, - * this should be done now - */ - memcpy(opts.sec_opts->encrypted_image + - opts.sec_opts->enc_image_sz - AES_BLOCK_SZ, - IV, AES_BLOCK_SZ); - rval = mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_ENCRYPT, - opts.sec_opts->enc_image_sz - AES_BLOCK_SZ, - IV, buf, opts.sec_opts->encrypted_image); - if (rval != 0) { - fprintf(stderr, "Failed to encrypt the image! Error %d\n", - rval); - goto encrypt_exit; - } - - mbedtls_aes_free(&aes_ctx); - - /* Try to decrypt the image and compare it with the original data */ - mbedtls_aes_init(&aes_ctx); - mbedtls_aes_setkey_dec(&aes_ctx, opts.sec_opts->aes_key, - AES_KEY_BIT_LEN); - - test_img = calloc(opts.sec_opts->enc_image_sz - AES_BLOCK_SZ, 1); - if (test_img == 0) { - fprintf(stderr, "Failed to allocate test image!d\n"); - rval = -1; - goto encrypt_exit; - } - - memcpy(IV, opts.sec_opts->encrypted_image + - opts.sec_opts->enc_image_sz - AES_BLOCK_SZ, - AES_BLOCK_SZ); - rval = mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, - opts.sec_opts->enc_image_sz - AES_BLOCK_SZ, - IV, opts.sec_opts->encrypted_image, test_img); - if (rval != 0) { - fprintf(stderr, "Failed to decrypt the image! Error %d\n", - rval); - goto encrypt_exit; - } - - for (i = 0; i < blen; i++) { - if (buf[i] != test_img[i]) { - fprintf(stderr, "Failed to compare the image after"); - fprintf(stderr, " decryption! Byte count is %d\n", i); - rval = -1; - goto encrypt_exit; - } - } - -encrypt_exit: - - mbedtls_aes_free(&aes_ctx); - if (test_img) - free(test_img); - - return rval; -} /* end of image_encrypt */ - -/******************************************************************************* - * verify_secure_header_signatures - * Verify CSK array, header and image signatures and print results - * INPUT: - * main_hdr Main header - * sec_ext Secure extension - * OUTPUT: - * none - * RETURN: - * 0 on success - */ -int verify_secure_header_signatures(header_t *main_hdr, sec_entry_t *sec_ext) -{ - uint8_t *image = (uint8_t *)main_hdr + main_hdr->prolog_size; - uint8_t signature[RSA_SIGN_BYTE_LEN]; - int rval = -1; - - /* Save headers signature and reset it in the secure header */ - memcpy(signature, sec_ext->header_sign, RSA_SIGN_BYTE_LEN); - memset(sec_ext->header_sign, 0, RSA_SIGN_BYTE_LEN); - - fprintf(stdout, "\nCheck RSA Signatures\n"); - fprintf(stdout, "#########################\n"); - fprintf(stdout, "CSK Block Signature: "); - if (verify_rsa_signature(sec_ext->kak_key, - MAX_RSA_DER_BYTE_LEN, - &sec_ext->csk_keys[0][0], - sizeof(sec_ext->csk_keys), - "CSK Block Signature: ", - sec_ext->csk_sign) != 0) { - fprintf(stdout, "ERROR\n"); - goto ver_error; - } - fprintf(stdout, "OK\n"); - - if (opts.key_index != -1) { - fprintf(stdout, "Image Signature: "); - if (verify_rsa_signature(sec_ext->csk_keys[opts.key_index], - MAX_RSA_DER_BYTE_LEN, - image, main_hdr->boot_image_size, - "Image Signature: ", - sec_ext->image_sign) != 0) { - fprintf(stdout, "ERROR\n"); - goto ver_error; - } - fprintf(stdout, "OK\n"); - - fprintf(stdout, "Header Signature: "); - if (verify_rsa_signature(sec_ext->csk_keys[opts.key_index], - MAX_RSA_DER_BYTE_LEN, - (uint8_t *)main_hdr, - main_hdr->prolog_size, - "Header Signature: ", - signature) != 0) { - fprintf(stdout, "ERROR\n"); - goto ver_error; - } - fprintf(stdout, "OK\n"); - } else { - fprintf(stdout, "SKIP Image and Header Signatures"); - fprintf(stdout, " check (undefined key index)\n"); - } - - rval = 0; - -ver_error: - memcpy(sec_ext->header_sign, signature, RSA_SIGN_BYTE_LEN); - return rval; -} - -/******************************************************************************* - * verify_and_copy_file_name_entry - * INPUT: - * element_name - * element - * OUTPUT: - * copy_to - * RETURN: - * 0 on success - */ -int verify_and_copy_file_name_entry(const char *element_name, - const char *element, char *copy_to) -{ - int element_length = strlen(element); - - if (element_length >= MAX_FILENAME) { - fprintf(stderr, "The file name %s for %s is too long (%d). ", - element, element_name, element_length); - fprintf(stderr, "Maximum allowed %d characters!\n", - MAX_FILENAME); - return -1; - } else if (element_length == 0) { - fprintf(stderr, "The file name for %s is empty!\n", - element_name); - return -1; - } - memcpy(copy_to, element, element_length); - - return 0; -} - -/******************************************************************************* - * parse_sec_config_file - * Read the secure boot configuration from a file - * into internal structures - * INPUT: - * filename File name - * OUTPUT: - * none - * RETURN: - * 0 on success - */ -int parse_sec_config_file(char *filename) -{ - config_t sec_cfg; - int array_sz, element, rval = -1; - const char *cfg_string; - int32_t cfg_int32; - const config_setting_t *csk_array, *control_array; - sec_options *sec_opt = 0; - - config_init(&sec_cfg); - - if (config_read_file(&sec_cfg, filename) != CONFIG_TRUE) { - fprintf(stderr, "Failed to read data from config file "); - fprintf(stderr, "%s\n\t%s at line %d\n", - filename, config_error_text(&sec_cfg), - config_error_line(&sec_cfg)); - goto exit_parse; - } - - sec_opt = (sec_options *)calloc(sizeof(sec_options), 1); - if (sec_opt == 0) { - fprintf(stderr, - "Cannot allocate memory for secure boot options!\n"); - goto exit_parse; - } - - /* KAK file name */ - if (config_lookup_string(&sec_cfg, "kak_key_file", - &cfg_string) != CONFIG_TRUE) { - fprintf(stderr, "The \"kak_key_file\" undefined!\n"); - goto exit_parse; - } - if (verify_and_copy_file_name_entry("kak_key_file", - cfg_string, sec_opt->kak_key_file)) - goto exit_parse; - - - /* AES file name - can be empty/undefined */ - if (config_lookup_string(&sec_cfg, "aes_key_file", - &cfg_string) == CONFIG_TRUE) { - if (verify_and_copy_file_name_entry("aes_key_file", - cfg_string, - sec_opt->aes_key_file)) - goto exit_parse; - } - - /* CSK file names array */ - csk_array = config_lookup(&sec_cfg, "csk_key_file"); - if (csk_array == NULL) { - fprintf(stderr, "The \"csk_key_file\" undefined!\n"); - goto exit_parse; - } - array_sz = config_setting_length(csk_array); - if (array_sz > CSK_ARR_SZ) { - fprintf(stderr, "The \"csk_key_file\" array is too big! "); - fprintf(stderr, "Only first %d elements will be used\n", - CSK_ARR_SZ); - array_sz = CSK_ARR_SZ; - } else if (array_sz == 0) { - fprintf(stderr, "The \"csk_key_file\" array is empty!\n"); - goto exit_parse; - } - - for (element = 0; element < array_sz; element++) { - cfg_string = config_setting_get_string_elem(csk_array, element); - if (verify_and_copy_file_name_entry( - "csk_key_file", cfg_string, - sec_opt->csk_key_file[element])) { - fprintf(stderr, "Bad csk_key_file[%d] entry!\n", - element); - goto exit_parse; - } - } - - /* JTAG options */ - if (config_lookup_bool(&sec_cfg, "jtag.enable", - &cfg_int32) != CONFIG_TRUE) { - fprintf(stderr, "Error obtaining \"jtag.enable\" element. "); - fprintf(stderr, "Using default - FALSE\n"); - cfg_int32 = 0; - } - sec_opt->jtag_enable = cfg_int32; - - if (config_lookup_int(&sec_cfg, "jtag.delay", - &cfg_int32) != CONFIG_TRUE) { - fprintf(stderr, "Error obtaining \"jtag.delay\" element. "); - fprintf(stderr, "Using default - 0us\n"); - cfg_int32 = 0; - } - sec_opt->jtag_delay = cfg_int32; - - /* eFUSE option */ - if (config_lookup_bool(&sec_cfg, "efuse_disable", - &cfg_int32) != CONFIG_TRUE) { - fprintf(stderr, "Error obtaining \"efuse_disable\" element. "); - fprintf(stderr, "Using default - TRUE\n"); - cfg_int32 = 1; - } - sec_opt->efuse_disable = cfg_int32; - - /* Box ID option */ - if (config_lookup_int(&sec_cfg, "box_id", &cfg_int32) != CONFIG_TRUE) { - fprintf(stderr, "Error obtaining \"box_id\" element. "); - fprintf(stderr, "Using default - 0x0\n"); - cfg_int32 = 0; - } - sec_opt->box_id = cfg_int32; - - /* Flash ID option */ - if (config_lookup_int(&sec_cfg, "flash_id", - &cfg_int32) != CONFIG_TRUE) { - fprintf(stderr, "Error obtaining \"flash_id\" element. "); - fprintf(stderr, "Using default - 0x0\n"); - cfg_int32 = 0; - } - sec_opt->flash_id = cfg_int32; - - /* CSK index option */ - if (config_lookup_int(&sec_cfg, "csk_key_index", - &cfg_int32) != CONFIG_TRUE) { - fprintf(stderr, "Error obtaining \"flash_id\" element. "); - fprintf(stderr, "Using default - 0x0\n"); - cfg_int32 = 0; - } - sec_opt->csk_index = cfg_int32; - - /* Secure boot control array */ - control_array = config_lookup(&sec_cfg, "control"); - if (control_array != NULL) { - array_sz = config_setting_length(control_array); - if (array_sz == 0) - fprintf(stderr, "The \"control\" array is empty!\n"); - } else { - fprintf(stderr, "The \"control\" is undefined!\n"); - array_sz = 0; - } - - for (element = 0; element < CP_CTRL_EL_ARRAY_SZ; element++) { - sec_opt->cp_ctrl_arr[element] = - config_setting_get_int_elem(control_array, element * 2); - sec_opt->cp_efuse_arr[element] = - config_setting_get_int_elem(control_array, - element * 2 + 1); - } - - opts.sec_opts = sec_opt; - rval = 0; - -exit_parse: - config_destroy(&sec_cfg); - if (sec_opt && (rval != 0)) - free(sec_opt); - return rval; -} /* end of parse_sec_config_file */ - -int format_sec_ext(char *filename, FILE *out_fd) -{ - ext_header_t header; - sec_entry_t sec_ext; - int index; - int written; - -#define DER_BUF_SZ 1600 - - /* First, parse the configuration file */ - if (parse_sec_config_file(filename)) { - fprintf(stderr, - "failed parsing configuration file %s\n", filename); - return 1; - } - - /* Everything except signatures can be created at this stage */ - header.type = EXT_TYPE_SECURITY; - header.offset = 0; - header.size = sizeof(sec_entry_t); - header.reserved = 0; - - /* Bring up RSA context and read private keys from their files */ - for (index = 0; index < (CSK_ARR_SZ + 1); index++) { - /* for every private key file */ - mbedtls_pk_context *pk_ctx = (index == CSK_ARR_SZ) ? - &opts.sec_opts->kak_pk : - &opts.sec_opts->csk_pk[index]; - char *fname = (index == CSK_ARR_SZ) ? - opts.sec_opts->kak_key_file : - opts.sec_opts->csk_key_file[index]; - uint8_t *out_der_key = (index == CSK_ARR_SZ) ? - sec_ext.kak_key : - sec_ext.csk_keys[index]; - size_t output_len; - unsigned char output_buf[DER_BUF_SZ]; - unsigned char *der_buf_start; - - /* Handle invalid/reserved file names */ - if (strncmp(CSK_ARR_EMPTY_FILE, fname, - strlen(CSK_ARR_EMPTY_FILE)) == 0) { - if (opts.sec_opts->csk_index == index) { - fprintf(stderr, - "CSK file with index %d cannot be %s\n", - index, CSK_ARR_EMPTY_FILE); - return 1; - } else if (index == CSK_ARR_SZ) { - fprintf(stderr, "KAK file name cannot be %s\n", - CSK_ARR_EMPTY_FILE); - return 1; - } - /* this key will be empty in CSK array */ - continue; - } - - mbedtls_pk_init(pk_ctx); - /* Read the private RSA key into the context - * and verify it (no password) - */ - if (mbedtls_pk_parse_keyfile(pk_ctx, fname, "") != 0) { - fprintf(stderr, - "Cannot read RSA private key file %s\n", fname); - return 1; - } - - /* Create a public key out of private one - * and store it in DER format - */ - output_len = mbedtls_pk_write_pubkey_der(pk_ctx, - output_buf, - DER_BUF_SZ); - if (output_len < 0) { - fprintf(stderr, - "Failed to create DER coded PUB key (%s)\n", - fname); - return 1; - } - /* Data in the output buffer is aligned to the buffer end */ - der_buf_start = output_buf + sizeof(output_buf) - output_len; - /* In the header DER data is aligned - * to the start of appropriate field - */ - memcpy(out_der_key, der_buf_start, output_len); - - } /* for every private key file */ - - /* The CSK block signature can be created here */ - if (create_rsa_signature(&opts.sec_opts->kak_pk, - &sec_ext.csk_keys[0][0], - sizeof(sec_ext.csk_keys), - opts.sec_opts->csk_key_file[ - opts.sec_opts->csk_index], - sec_ext.csk_sign) != 0) { - fprintf(stderr, "Failed to sign CSK keys block!\n"); - return 1; - } - /* Check that everything is correct */ - if (verify_rsa_signature(sec_ext.kak_key, MAX_RSA_DER_BYTE_LEN, - &sec_ext.csk_keys[0][0], - sizeof(sec_ext.csk_keys), - opts.sec_opts->kak_key_file, - sec_ext.csk_sign) != 0) { - fprintf(stderr, "Failed to verify CSK keys block signature!\n"); - return 1; - } - - /* AES encryption stuff */ - if (strlen(opts.sec_opts->aes_key_file) != 0) { - FILE *in_fd; - - in_fd = fopen(opts.sec_opts->aes_key_file, "rb"); - if (in_fd == NULL) { - fprintf(stderr, "Failed to open AES key file %s\n", - opts.sec_opts->aes_key_file); - return 1; - } - - /* Read the AES key in ASCII format byte by byte */ - for (index = 0; index < AES_KEY_BYTE_LEN; index++) { - if (fscanf(in_fd, "%02hhx", - opts.sec_opts->aes_key + index) != 1) { - fprintf(stderr, - "Failed to read AES key byte %d ", - index); - fprintf(stderr, - "from file %s\n", - opts.sec_opts->aes_key_file); - fclose(in_fd); - return 1; - } - } - fclose(in_fd); - sec_ext.encrypt_en = 1; - } else { - sec_ext.encrypt_en = 0; - } - - /* Fill the rest of the trusted boot extension fields */ - sec_ext.box_id = opts.sec_opts->box_id; - sec_ext.flash_id = opts.sec_opts->flash_id; - sec_ext.efuse_dis = opts.sec_opts->efuse_disable; - sec_ext.jtag_delay = opts.sec_opts->jtag_delay; - sec_ext.jtag_en = opts.sec_opts->jtag_enable; - - memcpy(sec_ext.cp_ctrl_arr, - opts.sec_opts->cp_ctrl_arr, - sizeof(uint32_t) * CP_CTRL_EL_ARRAY_SZ); - memcpy(sec_ext.cp_efuse_arr, - opts.sec_opts->cp_efuse_arr, - sizeof(uint32_t) * CP_CTRL_EL_ARRAY_SZ); - - /* Write the resulting extension to file - * (image and header signature fields are still empty) - */ - - /* Write extension header */ - written = fwrite(&header, sizeof(ext_header_t), 1, out_fd); - if (written != 1) { - fprintf(stderr, - "Failed to write SEC extension header to the file\n"); - return 1; - } - /* Write extension body */ - written = fwrite(&sec_ext, sizeof(sec_entry_t), 1, out_fd); - if (written != 1) { - fprintf(stderr, - "Failed to write SEC extension body to the file\n"); - return 1; - } - - return 0; -} - -/******************************************************************************* - * finalize_secure_ext - * Make final changes to secure extension - calculate image and header - * signatures and encrypt the image if needed. - * The main header checksum and image size fields updated accordingly - * INPUT: - * header Main header - * prolog_buf the entire prolog buffer - * prolog_size prolog buffer length - * image_buf buffer containing the input binary image - * image_size image buffer size. - * OUTPUT: - * none - * RETURN: - * 0 on success - */ -int finalize_secure_ext(header_t *header, - uint8_t *prolog_buf, uint32_t prolog_size, - uint8_t *image_buf, int image_size) -{ - int cur_ext, offset; - uint8_t *final_image = image_buf; - uint32_t final_image_sz = image_size; - uint8_t hdr_sign[RSA_SIGN_BYTE_LEN]; - sec_entry_t *sec_ext = 0; - - /* Find the Trusted Boot Header between available extensions */ - for (cur_ext = 0, offset = sizeof(header_t); - cur_ext < header->ext_count; cur_ext++) { - ext_header_t *ext_hdr = (ext_header_t *)(prolog_buf + offset); - - if (ext_hdr->type == EXT_TYPE_SECURITY) { - sec_ext = (sec_entry_t *)(prolog_buf + offset + - sizeof(ext_header_t) + ext_hdr->offset); - break; - } - - offset += sizeof(ext_header_t); - /* If offset is Zero, the extension follows its header */ - if (ext_hdr->offset == 0) - offset += ext_hdr->size; - } - - if (sec_ext == 0) { - fprintf(stderr, "Error: No Trusted Boot extension found!\n"); - return -1; - } - - if (sec_ext->encrypt_en) { - /* Encrypt the image if needed */ - fprintf(stdout, "Encrypting the image...\n"); - - if (image_encrypt(image_buf, image_size) != 0) { - fprintf(stderr, "Failed to encrypt the image!\n"); - return -1; - } - - /* Image size and checksum should be updated after encryption. - * This way the image could be verified by the BootROM - * before decryption. - */ - final_image = opts.sec_opts->encrypted_image; - final_image_sz = opts.sec_opts->enc_image_sz; - - header->boot_image_size = final_image_sz; - header->boot_image_checksum = - checksum32((uint32_t *)final_image, final_image_sz); - } /* AES encryption */ - - /* Create the image signature first, since it will be later - * signed along with the header signature - */ - if (create_rsa_signature(&opts.sec_opts->csk_pk[ - opts.sec_opts->csk_index], - final_image, final_image_sz, - opts.sec_opts->csk_key_file[ - opts.sec_opts->csk_index], - sec_ext->image_sign) != 0) { - fprintf(stderr, "Failed to sign image!\n"); - return -1; - } - /* Check that the image signature is correct */ - if (verify_rsa_signature(sec_ext->csk_keys[opts.sec_opts->csk_index], - MAX_RSA_DER_BYTE_LEN, - final_image, final_image_sz, - opts.sec_opts->csk_key_file[ - opts.sec_opts->csk_index], - sec_ext->image_sign) != 0) { - fprintf(stderr, "Failed to verify image signature!\n"); - return -1; - } - - /* Sign the headers and all the extensions block - * when the header signature field is empty - */ - if (create_rsa_signature(&opts.sec_opts->csk_pk[ - opts.sec_opts->csk_index], - prolog_buf, prolog_size, - opts.sec_opts->csk_key_file[ - opts.sec_opts->csk_index], - hdr_sign) != 0) { - fprintf(stderr, "Failed to sign header!\n"); - return -1; - } - /* Check that the header signature is correct */ - if (verify_rsa_signature(sec_ext->csk_keys[opts.sec_opts->csk_index], - MAX_RSA_DER_BYTE_LEN, - prolog_buf, prolog_size, - opts.sec_opts->csk_key_file[ - opts.sec_opts->csk_index], - hdr_sign) != 0) { - fprintf(stderr, "Failed to verify header signature!\n"); - return -1; - } - - /* Finally, copy the header signature into the trusted boot extension */ - memcpy(sec_ext->header_sign, hdr_sign, RSA_SIGN_BYTE_LEN); - - return 0; -} - -#endif /* CONFIG_MVEBU_SECURE_BOOT */ - - -#define FMT_HEX 0 -#define FMT_DEC 1 -#define FMT_BIN 2 -#define FMT_NONE 3 - -void do_print_field(unsigned int value, char *name, - int start, int size, int format) -{ - fprintf(stdout, "[0x%05x : 0x%05x] %-26s", - start, start + size - 1, name); - - switch (format) { - case FMT_HEX: - printf("0x%x\n", value); - break; - case FMT_DEC: - printf("%d\n", value); - break; - default: - printf("\n"); - break; - } -} - -#define print_field(st, type, field, hex, base) \ - do_print_field((int)st->field, #field, \ - base + offsetof(type, field), sizeof(st->field), hex) - -int print_header(uint8_t *buf, int base) -{ - header_t *main_hdr; - - main_hdr = (header_t *)buf; - - fprintf(stdout, "########### Header ##############\n"); - print_field(main_hdr, header_t, magic, FMT_HEX, base); - print_field(main_hdr, header_t, prolog_size, FMT_DEC, base); - print_field(main_hdr, header_t, prolog_checksum, FMT_HEX, base); - print_field(main_hdr, header_t, boot_image_size, FMT_DEC, base); - print_field(main_hdr, header_t, boot_image_checksum, FMT_HEX, base); - print_field(main_hdr, header_t, rsrvd0, FMT_HEX, base); - print_field(main_hdr, header_t, load_addr, FMT_HEX, base); - print_field(main_hdr, header_t, exec_addr, FMT_HEX, base); - print_field(main_hdr, header_t, uart_cfg, FMT_HEX, base); - print_field(main_hdr, header_t, baudrate, FMT_HEX, base); - print_field(main_hdr, header_t, ext_count, FMT_DEC, base); - print_field(main_hdr, header_t, aux_flags, FMT_HEX, base); - print_field(main_hdr, header_t, io_arg_0, FMT_HEX, base); - print_field(main_hdr, header_t, io_arg_1, FMT_HEX, base); - print_field(main_hdr, header_t, io_arg_2, FMT_HEX, base); - print_field(main_hdr, header_t, io_arg_3, FMT_HEX, base); - print_field(main_hdr, header_t, rsrvd1, FMT_HEX, base); - print_field(main_hdr, header_t, rsrvd2, FMT_HEX, base); - print_field(main_hdr, header_t, rsrvd3, FMT_HEX, base); - - return sizeof(header_t); -} - -int print_ext_hdr(ext_header_t *ext_hdr, int base) -{ - print_field(ext_hdr, ext_header_t, type, FMT_HEX, base); - print_field(ext_hdr, ext_header_t, offset, FMT_HEX, base); - print_field(ext_hdr, ext_header_t, reserved, FMT_HEX, base); - print_field(ext_hdr, ext_header_t, size, FMT_DEC, base); - - return base + sizeof(ext_header_t); -} - -void print_sec_ext(ext_header_t *ext_hdr, int base) -{ - sec_entry_t *sec_entry; - uint32_t new_base; - - fprintf(stdout, "\n########### Secure extension ###########\n"); - - new_base = print_ext_hdr(ext_hdr, base); - - sec_entry = (sec_entry_t *)(ext_hdr + 1); - - do_print_field(0, "KAK key", new_base, MAX_RSA_DER_BYTE_LEN, FMT_NONE); - new_base += MAX_RSA_DER_BYTE_LEN; - print_field(sec_entry, sec_entry_t, jtag_delay, FMT_DEC, base); - print_field(sec_entry, sec_entry_t, box_id, FMT_HEX, base); - print_field(sec_entry, sec_entry_t, flash_id, FMT_HEX, base); - print_field(sec_entry, sec_entry_t, encrypt_en, FMT_DEC, base); - print_field(sec_entry, sec_entry_t, efuse_dis, FMT_DEC, base); - new_base += 6 * sizeof(uint32_t); - do_print_field(0, "header signature", - new_base, RSA_SIGN_BYTE_LEN, FMT_NONE); - new_base += RSA_SIGN_BYTE_LEN; - do_print_field(0, "image signature", - new_base, RSA_SIGN_BYTE_LEN, FMT_NONE); - new_base += RSA_SIGN_BYTE_LEN; - do_print_field(0, "CSK keys", new_base, - CSK_ARR_SZ * MAX_RSA_DER_BYTE_LEN, FMT_NONE); - new_base += CSK_ARR_SZ * MAX_RSA_DER_BYTE_LEN; - do_print_field(0, "CSK block signature", - new_base, RSA_SIGN_BYTE_LEN, FMT_NONE); - new_base += RSA_SIGN_BYTE_LEN; - do_print_field(0, "control", new_base, - CP_CTRL_EL_ARRAY_SZ * 2, FMT_NONE); - -} - -void print_bin_ext(ext_header_t *ext_hdr, int base) -{ - fprintf(stdout, "\n########### Binary extension ###########\n"); - base = print_ext_hdr(ext_hdr, base); - do_print_field(0, "binary image", base, ext_hdr->size, FMT_NONE); -} - -int print_extension(void *buf, int base, int count, int ext_size) -{ - ext_header_t *ext_hdr = buf; - int pad = ext_size; - int curr_size; - - while (count--) { - if (ext_hdr->type == EXT_TYPE_BINARY) - print_bin_ext(ext_hdr, base); - else if (ext_hdr->type == EXT_TYPE_SECURITY) - print_sec_ext(ext_hdr, base); - - curr_size = sizeof(ext_header_t) + ext_hdr->size; - base += curr_size; - pad -= curr_size; - ext_hdr = (ext_header_t *)((uintptr_t)ext_hdr + curr_size); - } - - if (pad) - do_print_field(0, "padding", base, pad, FMT_NONE); - - return ext_size; -} - -int parse_image(uint8_t *buf, int size) -{ - int base = 0; - int ret = 1; - header_t *main_hdr; - uint32_t checksum, prolog_checksum; - - - fprintf(stdout, - "################### Prolog Start ######################\n\n"); - main_hdr = (header_t *)buf; - base += print_header(buf, base); - - if (main_hdr->ext_count) - base += print_extension(buf + base, base, - main_hdr->ext_count, - main_hdr->prolog_size - - sizeof(header_t)); - - if (base < main_hdr->prolog_size) { - fprintf(stdout, "\n########### Padding ##############\n"); - do_print_field(0, "prolog padding", - base, main_hdr->prolog_size - base, FMT_HEX); - base = main_hdr->prolog_size; - } - fprintf(stdout, - "\n################### Prolog End ######################\n"); - - fprintf(stdout, - "\n################### Boot image ######################\n"); - - do_print_field(0, "boot image", base, size - base - 4, FMT_NONE); - - fprintf(stdout, - "################### Image end ########################\n"); - - /* Check sanity for certain values */ - printf("\nChecking values:\n"); - - if (main_hdr->magic == MAIN_HDR_MAGIC) { - fprintf(stdout, "Headers magic: OK!\n"); - } else { - fprintf(stderr, - "\n****** ERROR: HEADER MAGIC 0x%08x != 0x%08x\n", - main_hdr->magic, MAIN_HDR_MAGIC); - goto error; - } - - /* headers checksum */ - /* clear the checksum field in header to calculate checksum */ - prolog_checksum = main_hdr->prolog_checksum; - main_hdr->prolog_checksum = 0; - checksum = checksum32((uint32_t *)buf, main_hdr->prolog_size); - - if (checksum == prolog_checksum) { - fprintf(stdout, "Headers checksum: OK!\n"); - } else { - fprintf(stderr, - "\n***** ERROR: BAD HEADER CHECKSUM 0x%08x != 0x%08x\n", - checksum, prolog_checksum); - goto error; - } - - /* boot image checksum */ - checksum = checksum32((uint32_t *)(buf + main_hdr->prolog_size), - main_hdr->boot_image_size); - if (checksum == main_hdr->boot_image_checksum) { - fprintf(stdout, "Image checksum: OK!\n"); - } else { - fprintf(stderr, - "\n****** ERROR: BAD IMAGE CHECKSUM 0x%08x != 0x%08x\n", - checksum, main_hdr->boot_image_checksum); - goto error; - } - -#ifdef CONFIG_MVEBU_SECURE_BOOT - /* RSA signatures */ - if (main_hdr->ext_count) { - uint8_t ext_num = main_hdr->ext_count; - ext_header_t *ext_hdr = (ext_header_t *)(main_hdr + 1); - unsigned char hash[32]; - int i; - - while (ext_num--) { - if (ext_hdr->type == EXT_TYPE_SECURITY) { - sec_entry_t *sec_entry = - (sec_entry_t *)(ext_hdr + 1); - - ret = verify_secure_header_signatures( - main_hdr, sec_entry); - if (ret != 0) { - fprintf(stderr, - "\n****** FAILED TO VERIFY "); - fprintf(stderr, - "RSA SIGNATURES ********\n"); - goto error; - } - - mbedtls_sha256(sec_entry->kak_key, - MAX_RSA_DER_BYTE_LEN, hash, 0); - fprintf(stdout, - ">>>>>>>>>> KAK KEY HASH >>>>>>>>>>\n"); - fprintf(stdout, "SHA256: "); - for (i = 0; i < 32; i++) - fprintf(stdout, "%02X", hash[i]); - - fprintf(stdout, - "\n<<<<<<<<< KAK KEY HASH <<<<<<<<<\n"); - - break; - } - ext_hdr = - (ext_header_t *)((uint8_t *)(ext_hdr + 1) + - ext_hdr->size); - } - } -#endif - - ret = 0; -error: - return ret; -} - -int format_bin_ext(char *filename, FILE *out_fd) -{ - ext_header_t header; - FILE *in_fd; - int size, written; - int aligned_size, pad_bytes; - char c; - - in_fd = fopen(filename, "rb"); - if (in_fd == NULL) { - fprintf(stderr, "failed to open bin extension file %s\n", - filename); - return 1; - } - - size = get_file_size(filename); - if (size <= 0) { - fprintf(stderr, "bin extension file size is bad\n"); - return 1; - } - - /* Align extension size to 8 bytes */ - aligned_size = (size + 7) & (~7); - pad_bytes = aligned_size - size; - - header.type = EXT_TYPE_BINARY; - header.offset = 0; - header.size = aligned_size; - header.reserved = 0; - - /* Write header */ - written = fwrite(&header, sizeof(ext_header_t), 1, out_fd); - if (written != 1) { - fprintf(stderr, "failed writing header to extension file\n"); - return 1; - } - - /* Write image */ - while (size--) { - c = getc(in_fd); - fputc(c, out_fd); - } - - while (pad_bytes--) - fputc(0, out_fd); - - fclose(in_fd); - - return 0; -} - -/* **************************************** - * - * Write all extensions (binary, secure - * extensions) to file - * - * ****************************************/ - -int format_extensions(char *ext_filename) -{ - FILE *out_fd; - int ret = 0; - - out_fd = fopen(ext_filename, "wb"); - if (out_fd == NULL) { - fprintf(stderr, "failed to open extension output file %s", - ext_filename); - return 1; - } - - if (strncmp(opts.bin_ext_file, "NA", MAX_FILENAME)) { - if (format_bin_ext(opts.bin_ext_file, out_fd)) { - ret = 1; - goto error; - } - } -#ifdef CONFIG_MVEBU_SECURE_BOOT - if (strncmp(opts.sec_cfg_file, "NA", MAX_FILENAME)) { - if (format_sec_ext(opts.sec_cfg_file, out_fd)) { - ret = 1; - goto error; - } - } -#endif - -error: - fflush(out_fd); - fclose(out_fd); - return ret; -} - -void update_uart(header_t *header) -{ - header->uart_cfg = 0; - header->baudrate = 0; - - if (opts.disable_print) - uart_set_mode(header->uart_cfg, UART_MODE_DISABLE); - - if (opts.baudrate) - header->baudrate = (opts.baudrate / 1200); -} - -/* **************************************** - * - * Write the image prolog, i.e. - * main header and extensions, to file - * - * ****************************************/ - -int write_prolog(int ext_cnt, char *ext_filename, - uint8_t *image_buf, int image_size, FILE *out_fd) -{ - header_t *header; - int main_hdr_size = sizeof(header_t); - int prolog_size = main_hdr_size; - FILE *ext_fd; - char *buf; - int written, read; - int ret = 1; - - - if (ext_cnt) - prolog_size += get_file_size(ext_filename); - - prolog_size = ((prolog_size + PROLOG_ALIGNMENT) & - (~(PROLOG_ALIGNMENT-1))); - - /* Allocate a zeroed buffer to zero the padding bytes */ - buf = calloc(prolog_size, 1); - if (buf == NULL) { - fprintf(stderr, "Error: failed allocating checksum buffer\n"); - return 1; - } - - header = (header_t *)buf; - header->magic = MAIN_HDR_MAGIC; - header->prolog_size = prolog_size; - header->load_addr = opts.load_addr; - header->exec_addr = opts.exec_addr; - header->io_arg_0 = opts.nfc_io_args; - header->ext_count = ext_cnt; - header->aux_flags = 0; - header->boot_image_size = (image_size + 3) & (~0x3); - header->boot_image_checksum = checksum32((uint32_t *)image_buf, - image_size); - - update_uart(header); - - /* Populate buffer with main header and extensions */ - if (ext_cnt) { - ext_fd = fopen(ext_filename, "rb"); - if (ext_fd == NULL) { - fprintf(stderr, - "Error: failed to open extensions file\n"); - goto error; - } - - read = fread(&buf[main_hdr_size], - get_file_size(ext_filename), 1, ext_fd); - if (read != 1) { - fprintf(stderr, - "Error: failed to open extensions file\n"); - goto error; - } - -#ifdef CONFIG_MVEBU_SECURE_BOOT - /* Secure boot mode? */ - if (opts.sec_opts != 0) { - ret = finalize_secure_ext(header, (uint8_t *)buf, - prolog_size, image_buf, - image_size); - if (ret != 0) { - fprintf(stderr, "Error: failed to handle "); - fprintf(stderr, "secure extension!\n"); - goto error; - } - } /* secure boot mode */ -#endif - } - - /* Update the total prolog checksum */ - header->prolog_checksum = checksum32((uint32_t *)buf, prolog_size); - - /* Now spill everything to output file */ - written = fwrite(buf, prolog_size, 1, out_fd); - if (written != 1) { - fprintf(stderr, - "Error: failed to write prolog to output file\n"); - goto error; - } - - ret = 0; - -error: - free(buf); - return ret; -} - -int write_boot_image(uint8_t *buf, uint32_t image_size, FILE *out_fd) -{ - int aligned_size; - int written; - - /* Image size must be aligned to 4 bytes */ - aligned_size = (image_size + 3) & (~0x3); - - written = fwrite(buf, aligned_size, 1, out_fd); - if (written != 1) { - fprintf(stderr, "Error: Failed to write boot image\n"); - goto error; - } - - return 0; -error: - return 1; -} - -int main(int argc, char *argv[]) -{ - char in_file[MAX_FILENAME+1] = { 0 }; - char out_file[MAX_FILENAME+1] = { 0 }; - char ext_file[MAX_FILENAME+1] = { 0 }; - FILE *in_fd = NULL; - FILE *out_fd = NULL; - int parse = 0; - int ext_cnt = 0; - int opt; - int ret = 0; - int image_size; - uint8_t *image_buf = NULL; - int read; - size_t len; - uint32_t nand_block_size_kb, mlc_nand; - - /* Create temporary file for building extensions - * Use process ID for allowing multiple parallel runs - */ - snprintf(ext_file, MAX_FILENAME, "/tmp/ext_file-%x", getpid()); - - while ((opt = getopt(argc, argv, "hpms:i:l:e:a:b:u:n:t:c:k:")) != -1) { - switch (opt) { - case 'h': - usage(); - break; - case 'l': - opts.load_addr = strtoul(optarg, NULL, 0); - break; - case 'e': - opts.exec_addr = strtoul(optarg, NULL, 0); - break; - case 'm': - opts.disable_print = 1; - break; - case 'u': - opts.baudrate = strtoul(optarg, NULL, 0); - break; - case 'b': - strncpy(opts.bin_ext_file, optarg, MAX_FILENAME); - ext_cnt++; - break; - case 'p': - parse = 1; - break; - case 'n': - nand_block_size_kb = strtoul(optarg, NULL, 0); - opts.nfc_io_args |= (nand_block_size_kb / 64); - break; - case 't': - mlc_nand = 0; - if (!strncmp("MLC", optarg, 3)) - mlc_nand = 1; - opts.nfc_io_args |= (mlc_nand << 8); - break; -#ifdef CONFIG_MVEBU_SECURE_BOOT - case 'c': /* SEC extension */ - strncpy(opts.sec_cfg_file, optarg, MAX_FILENAME); - ext_cnt++; - break; - case 'k': - opts.key_index = strtoul(optarg, NULL, 0); - break; -#endif - default: /* '?' */ - usage_err("Unknown argument"); - exit(EXIT_FAILURE); - } - } - - /* Check validity of inputes */ - if (opts.load_addr % 8) - usage_err("Load address must be 8 bytes aligned"); - - if (opts.baudrate % 1200) - usage_err("Baudrate must be a multiple of 1200"); - - /* The remaining arguments are the input - * and potentially output file - */ - /* Input file must exist so exit if not */ - if (optind >= argc) - usage_err("missing input file name"); - - len = strlen(argv[optind]); - if (len > MAX_FILENAME) - usage_err("file name too long"); - memcpy(in_file, argv[optind], len); - optind++; - - /* Output file must exist in non parse mode */ - if (optind < argc) { - len = strlen(argv[optind]); - if (len > MAX_FILENAME) - usage_err("file name too long"); - memcpy(out_file, argv[optind], len); - } else if (!parse) - usage_err("missing output file name"); - - /* open the input file */ - in_fd = fopen(in_file, "rb"); - if (in_fd == NULL) { - printf("Error: Failed to open input file %s\n", in_file); - goto main_exit; - } - - /* Read the input file to buffer */ - image_size = get_file_size(in_file); - image_buf = calloc((image_size + AES_BLOCK_SZ - 1) & - ~(AES_BLOCK_SZ - 1), 1); - if (image_buf == NULL) { - fprintf(stderr, "Error: failed allocating input buffer\n"); - return 1; - } - - read = fread(image_buf, image_size, 1, in_fd); - if (read != 1) { - fprintf(stderr, "Error: failed to read input file\n"); - goto main_exit; - } - - /* Parse the input image and leave */ - if (parse) { - if (opts.key_index >= CSK_ARR_SZ) { - fprintf(stderr, - "Wrong key IDX value. Valid values 0 - %d\n", - CSK_ARR_SZ - 1); - goto main_exit; - } - ret = parse_image(image_buf, image_size); - goto main_exit; - } - - /* Create a blob file from all extensions */ - if (ext_cnt) { - ret = format_extensions(ext_file); - if (ret) - goto main_exit; - } - - out_fd = fopen(out_file, "wb"); - if (out_fd == NULL) { - fprintf(stderr, - "Error: Failed to open output file %s\n", out_file); - goto main_exit; - } - - ret = write_prolog(ext_cnt, ext_file, image_buf, image_size, out_fd); - if (ret) - goto main_exit; - -#ifdef CONFIG_MVEBU_SECURE_BOOT - if (opts.sec_opts && (opts.sec_opts->encrypted_image != 0) && - (opts.sec_opts->enc_image_sz != 0)) { - ret = write_boot_image(opts.sec_opts->encrypted_image, - opts.sec_opts->enc_image_sz, out_fd); - } else -#endif - ret = write_boot_image(image_buf, image_size, out_fd); - if (ret) - goto main_exit; - -main_exit: - if (in_fd) - fclose(in_fd); - - if (out_fd) - fclose(out_fd); - - if (image_buf) - free(image_buf); - - unlink(ext_file); - -#ifdef CONFIG_MVEBU_SECURE_BOOT - if (opts.sec_opts) { - if (opts.sec_opts->encrypted_image) - free(opts.sec_opts->encrypted_image); - free(opts.sec_opts); - } -#endif - exit(ret); -} diff --git a/tools/doimage/doimage.mk b/tools/doimage/doimage.mk deleted file mode 100644 index 2b751d4..0000000 --- a/tools/doimage/doimage.mk +++ /dev/null @@ -1,15 +0,0 @@ -# -# Copyright (C) 2018 Marvell International Ltd. -# -# SPDX-License-Identifier: BSD-3-Clause -# https://spdx.org/licenses - -DOIMAGE_FLAGS ?= -l 0x4100000 -e 0x4100000 - - -#NAND params -#Open and update the below when using NAND as a boot device. - -CONFIG_MVEBU_NAND_BLOCK_SIZE := 256 -CONFIG_MVEBU_NAND_CELL_TYPE := SLC -NAND_DOIMAGE_FLAGS := -t $(CONFIG_MVEBU_NAND_CELL_TYPE) -n $(CONFIG_MVEBU_NAND_BLOCK_SIZE) diff --git a/tools/doimage/secure/aes_key.txt b/tools/doimage/secure/aes_key.txt deleted file mode 100644 index 3e8a888..0000000 --- a/tools/doimage/secure/aes_key.txt +++ /dev/null @@ -1 +0,0 @@ -ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890 diff --git a/tools/doimage/secure/csk_priv_pem0.key b/tools/doimage/secure/csk_priv_pem0.key deleted file mode 100644 index 0840c2a..0000000 --- a/tools/doimage/secure/csk_priv_pem0.key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEogIBAAKCAQEAm6jN6o2zQmtyUlvfkfDbSjPJ7Vlpp/KgK/eznoVBBsDIZakX -cIgf8TSLpNVkc+ZE0f/n8X7mEZIyjuSBObLOm9vbkoZcR7DlKUL7RNNOUCv55Ozl -hQwrzpH/uIyIJTvmek29G5wroi0wGbPoxzhelIRTjVCibleBWhYCmZQ6SIRmTY8L -JT8VkX8I/Mhu62DjvxF3BnV6pXuh/FdgDN7MbldzM8Y+GOxVGi5Kcm5WHY7eyMxl -4Y0Yko31Xv7T1PcXahVBIciT+11w+fLc4wQuCJ6GUf9JbzQ0ZllY/FdRG0AhuRMH -zN0jAc/sKrIFoAErED6qlcoQg0vl7gmWN5x+2wIDAQABAoIBACtnPFOkw1FH6I6y -c3qcMGlWW33FKsLb0nGwFfOjsGgTpU1Dgver3UxCnJWPsvzmPlZYBvK9saVAoLxb -VvUhuJ6ZBXar5FtRJfUFak7cpL+SI5IDxFP++tAUwbtR5DyNoUyFFK/4Mep8sybX -lZbHTwgWhb2nuEMQP09BR+RPAplpcitkIoPkhmbGfbt9Hsd25I3bb5Z9R4S/2Rcf -7tmaxndQamij7/pUI7xtd8L6cMESJGIWrgEt/MaT2z8nNPE3EDctDSlH9yKqA2O7 -/LTfrxNDnw5gGRtOgahloThKljVM6pQa4mi91FufD67pHwnKn8urNbt8/3AWg6uU -x4FzZdECgYEA0k2UYzBM+dU6T1bZZ176YI0cZrP1tbf/JwnZGHicQYS7lPLAqgfO -u5oRQzuDimOXaV4xCPBO2nadd6aBxbZTXaglR7GG2uCHX6w2DnOr8/d66YTErTVV -u7/Bf8gMKT9mM4rWPrOEXfXfF0fvcpkBQ+QDynIB37tx/mj2lXRkLx0CgYEAvXuX -Dbe2QgSK0ajrcH7YJyx3RVx9RonOqL4yjCVCELmaDQd307Ef3j+gkd59XIewm+HA -mPyeWEUd8EzH+UvjckfKFuF2I4lEUUWtVZTa7me7mvsFqeEOu5KusD4+Hs+B9Kqd -3Evqcpj2lcMBI519Hvr9BTKfDBcH1EUos6A9rFcCgYAxsyPeTQvj/wBIv72hMFD7 -gF2159GpoFIsZ6dmoRpMYZHzIWtmw3GX5FEwEmCD1AV0YU41TpVUC7QrEq6Yiv4o -pBQrXUkBcQ6NDaW4xJ1eip4Bkd7pEDGyrR6NlDlLhjAg/i6joskla3XNirKL4pzp -7nj23vqSZToLZcLgjyEeAQKBgD5EvDo80j9VwMzvpxecB6qv+S4pG94vcWOQxYm6 -wMBATjjT6HP/9EoUPM9S/32F9er0QFfGRL8bT6Blix4I62Dl6KqmQy2gcXwH2tOS -DHRmUIe40H6oQDAyHwg6HC4B4WInI6N+qzgnvnku0VQD8FdbAgVQQmY1t1PxulN1 -aG8XAoGAPWAr4i8KkVAx4wLlMF8E/ecKcsX1J0+UuKket7Dvk7xJfwtkSLPeV8Bp -HuoHXMM3KYoZ93Hlto5rAT1VQhYuj7heU10v+9UtYTFHgaitptYmxovoCKKiZICl -48aPUI377e5jQ6RhhGYy8ltKsJ80K1T9DIkThJPSS+9NAI+jrmg= ------END RSA PRIVATE KEY----- diff --git a/tools/doimage/secure/csk_priv_pem1.key b/tools/doimage/secure/csk_priv_pem1.key deleted file mode 100644 index 91d1aeb..0000000 --- a/tools/doimage/secure/csk_priv_pem1.key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEogIBAAKCAQEAgwHXB0AaIhT15Z9lHpQ2YT1W8i4oMvvRiLGQCrba5l7BJ03E -ct0x3zagNKZEnpNndT4EAy98ihkhwVlUhxZCparJ2L3JsTs5RgV0wyQkQzwMLM8g -QI5EMmJCgFAVRHmVICOsisGGfNVUHjGdGwPOipyQCsX2MAm3E139VpB7NYj+Q4IR -4kvcb+59LZxKuRJTFKRDIqMGJu98P/ga70+YLXPCBPKSfnZnUppuaI86jF1E6xt8 -o7YtfEPCHDd2LXxKPZ670OapVqwo0t7ZSzEG63NkLp56FXc1OpfC69C8VPiZ8JqW -wxvS/vL8MMCxsBnjSuqnmOAbcNR2GFtUwJOGwwIDAQABAoIBAFcfoiDwQHDp/531 -ownzBzcj0+67Q4Ckd3SwoVp+wJTz7wB0d3DsKX6IlYJuELRk0yjlVUXJDsnIbOpo -vg4Yf7otGo9JqBh1imFGv6AHKRaNmIs0M/66nh/juNYcbAhd0w7MqrKcgRQDyy1J -UXHl1jXYaPLBNDg+PcJjf1dSPp4axzmW2Pk2rXnJCsPcZXL/0YmEvqhfOze0GdjR -hOkbbr6MPPVM66tA00xSwg9XEYJvHtwH6oB0rnANM8ieNK1mtcWkTU5di17CCrjS -ohIhXQrdVpxt549EJoUqEFSgo8OOMm2npDbFrjlukb5euakvMacwoT1te79blSKf -hrTvjgECgYEA0VqoFL0Vqe1qleikYDJ7S5xcv1oruEV31TeuBhDuf0c4PADCnBrV -/RnCEYuXs6wCk60chHg5s0jxg+nGbiY6jRTHkJLRU3ZhDtrtfidEZ78GRzFF3shl -Uzt7dHkKK1ZdiMH4sWzyRLom91TKWMrNKC1AD7v4/zjEXy6phall3ZcCgYEAoDJa -0dIKvVCS6dM2E2kMqi/45mJqsJzFvYL1s4mbma/BAC47bBju/YEse90x+iIi3Gg/ -NoXmNfGPrtgdl+/J/Y6Pohxf/e7gGN71tYVETzgc2Jv09wqmzmTjCmo3wyepyWf+ -pIAE39kdhwnqXVw5xwOG1N3xrQ9TomOO+1QiXbUCgYAF84TJqiJehUA9aLKbhXPZ -z2UXj3GkuFzSs9V/mKWe+qBPnFnr5BtnKX9JzmUOl3ovRoGEBoLlZNJwxIl+ghmx -/wA5TOMkcz4JFRIhPu6D4HtGNNFepuWyewNkaThvyPG5vIHcUVOFvqDy8PcblRBF -7xteFyLZ5nw2lHX/NbSOmwKBgFxLZqPIPcPArkPlGhyow1Ex/lbNkOZcDFkZIHHl -8C3lYm62NCodW2PWjkh2shqInEkcDn9dObsOh1eWz8X/swJQplQhwPROMfJiUnHY -a/iwPX5WrBXAn0X+Pgh8FdBsA5g0QDOKRkSplCd/APX08pzEXWQ60siAMhE3BuOq -H3qZAoGAVnzFidlXuyn+fbNaNVepK9hbuoxHHbzYYWSkpi+73EchN8kXktC+AdEf -owr9TPILbwWWJyisa3wW4xdbMifCgVLTedWZpZ09BENVqC+7g7ksX0pNMGYuFLOh -Td7mFAgmclxG5UiKexajOLjjdnAsJyrDaNKhHn8NQNN6L93N0sE= ------END RSA PRIVATE KEY----- diff --git a/tools/doimage/secure/csk_priv_pem2.key b/tools/doimage/secure/csk_priv_pem2.key deleted file mode 100644 index ea47ac5..0000000 --- a/tools/doimage/secure/csk_priv_pem2.key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEogIBAAKCAQEAjxTSTh57/5njUpE200+Qb3ySAn8lKeufgaa0K2Xc6Ri7lDZR -ZJ2BPuQZV4lYGqgWUf0IOzNf2WnE2lPfVnLMx08h7NhBqJ83yJVajpr+itnOmW+r -M7h76TFyuna1xz2kw1uhgI5Y4FRnJ4Cg4AexCSyViXSzEN/7LQwxa5z5WGDiNX5N -3/tgjGu+dzSMOiIQhXwIcK/XaiQNm3WHqqnAhPb5Q9IBuuqBfpZoFfH4XmbFWrC8 -neSMMMxX5Ti9pKhLd1EsiaP0aUNQlF8gNWuC/tNaf+OCtwVelVa3sGSRjRFe06VQ -sAE9oyXKri11yD5Dwp1xXivbpOrf7xjUe5gILwIDAQABAoIBABTr94CCxqDucKYP -I9QsSzNyJKuGyfliQdWkea3q3C2ddzhJ5QbwXQjEM8xwAdkMAQ+GD2EQtxBEfgtq -vjqW2MjAEnbefGNavL5w0GgP0+6bwLEA+ii67iuAFoWbfCMhKWmDiY8RwX8z+E13 -ao63sTRlN4x86v4pskG5CbTxpCg+8m7KklLns4SwRGf5gGQcgKRtNSR5nE4g2UNl -dghbDdNlvUncm4zxUcTh0kquhF5Tef5w+6L7W8Hv9Pky3b1c2OK1BMhJlxYrtt69 -/zhIJs89CLx5ACfam+DT/xs0uUiuRQq/e1CCQLCnUO02JqpeN/schtDCd0ZWhbtB -nT7fwTECgYEAx+COhys+7AZI0U+PeuTkI86GUsWHoBislXThxbxyGvMFjgyADZD+ -q/XEGAcxd4eTA1fr0Q9cLuuHZubjGQ7+OIXMZ6arXUsrmMrjRu3kHO+y6K6r4s8j -5bxN/iQ0bymUtJRfJSLI172plszusiPWhCL5+yhYlNoh4mNZJuJnzXkCgYEAt0Gz -07P19YPsxk5ow7ZnSNOMOkkEPP0SuHHWekMIK9KMjiRUSygOAk07zTL7MUoFn9Gy -Prfi0ybFArNhIa4Xio3Fbjfig7rGgaApK4Y3d9A/CGPv/Nj7C2OTepqlEzRLmU9e -Xw5yhbccCydXLyAYFAET2XHsmbewpvHyeYUSoOcCgYBRMJEUrOdhPmhDxZqVo/Zb -6R887gnaaUtpZlHzXUnIUqEWA1PcruIT/b/KttlMIWEBQayDfkbGtFuK3AyxeBqh -4Q+XpucC/W7XIMrTW/yGGIPG6nTdq6B8SFIyAojeArjp5T8Eua11nRAPNm1bJR2V -DRQYBlp9FGIhMJPdLKhXmQKBgGeywSyR0COfBHPu2K+u3uFB/D7bJI/ScS54FHLY -zZ3mpeylOCHTR6IbzDRAng31Ihue0KtW6P6tGJx/nv4tAltAADFvZDlAjqW5WLKt -X2PoLlL0IlBFBEIclc6yBalJVWIqnG9TwJBT3oWdPGOJWLaxKWdJZSZS4J6HmLsV -B0aPAoGAduLsOt8C5z48jPqmJxyPwsmT0Q424FccPMcvGOJ13yxq3xNsfAsbmg9l -L2i/ktE0wCMA+Pm7cuFgxwD7xTr67POZgt9022KsOSonjPsIn24UQeP46vAX/Qtx -Qf3sfvzf57vNy2Hybe38T8RsVOZla+v/QctfSfmb8Y95XL/SZzA= ------END RSA PRIVATE KEY----- diff --git a/tools/doimage/secure/csk_priv_pem3.key b/tools/doimage/secure/csk_priv_pem3.key deleted file mode 100644 index e40a864..0000000 --- a/tools/doimage/secure/csk_priv_pem3.key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAlA/T/5IMTPTu+k5PeesB2oeP80Y6nq0ls8vXLul0TVEJoJ+O -InbPYNqYPu4dbQQg/u8qp8BeXm2ujtJbBTcdn0jKIiDTKYEnlsGfUt9GHnuuzvFh -rORSKuAolUqvo/zcSCo1uykaFvSuyTovSPlwllzSixD9XBbHfn3kXneiIUa45vsJ -AyjTn2qCJt0WgvX42NTxH6Q/OWLeOuKTyRHf25eabucIv77KYy0mlEPq5jjiV5AJ -gl5F1h5G8n07JCIWjkZ2QV4wr+Hv9uGNaSb0WGppBp4CbdQa0eUI75cKzz4WXqds -HZaYiX/a8YC+EUfvqDD02vKREIKFL/1zL53P/wIDAQABAoIBAGzBj5w7oBNrGpr7 -qL9KEyt8xg0Q+gAR+Q6vXRlVXBtquiKk8Jd6I+vlxUz8RNsN3FrGPNPJpse/0yeP -dlJHYNfedLNK3zCucPD4uln6LRw5B3d0sKV5dK2Px9+ZY5iWJQxRDPS0RTi1dCnV -NmRo7P1Vo0WJLkFVbiYIvRVy1MGRfF9ejN41G6U4MoBAQ9WqLp+JasUMTspZI49a -z8tOiJPT94MHBwbKnz8Mcq8sy02LR7U5h82+0T7JoRVix/OXiOoiQExNjZ9yGar0 -wBnl0SL1UW5UUaYzbyNH0mlMXLD+qowbDZM2pBWPfqXK+CMOsL6STIwnns7lY+ZJ -ILbaVmECgYEA2kQXE1PZ25A87a81wCEld402WJ2KegrZC719EWv+xeoS72Ji8uv7 -V0PxVGJQOcG1N+dzJ5tN59SQ/NvVTrjwqNUxQqsygmWq/TcfGb9ONZRmyzcehYLb -m4xTjqJKQ6Kwm5SoaCYmzEb/xaeLwLS9HmR9MdB1dxtDOLpjaK/8qPECgYEArait -QhgaknlxG8pcAimPsEUrLHYWSFRE/MUk4+YvZg/5+YJ8csvY0SO2h0tF/ARwUrdI -DaLEifHm4vqgN03K/0gqj7TKxcNlV16PvVx7Vz97xejdqdHZLDfAo4lcotsgvFQW -zIqoQGGPLf6WhFixZ8mEYj8xnmzLGPvHQmf1h+8CgYEA0LDl917nIN4qw4ARPqDy -t/pXCienrcUNfgIxwSSnNwj2DdjejzI+4VNfPbW6y16BLPCp1CbUOGOwNXTj4R9H -S8Z8ESirZK5c7Tt1CyM1XlmEZ61OC43w+CsWAXz+0OiPQFLFKr+/vPXtvEjUgO7P -HG4sniKZDccNYQIl5oTOaaECgYAPU4u3AZmWw9EPutRT/IcJ75DX47Qjvgw4os2W -r4IPZ+mP88w39XW1P4mkdyg+DcY8BqD9Uxg1dHwEHEp3lw4LabsX48Thn1UaWOYm -uDrKgHfUB7FIg5S/Kkx+ImliliRVerZoZvRiejnAvW9bTtiZaFeetCUU7lUeZ1o2 -qiYpUQKBgHQDfdDhguBGPKpkJ7pVwHkJA/lyRWaN1hwplw4TvX2oH14NsHg5Q5Fd -lHqHFs2Ry/6X3bKgF0E6q4cx0V1Xnnj9sGsemlrHdiSxplDYRQql7X5OeYPGF/Bg -ZTTG8rDwy+ey6EP9BZUb03hISx/LyMynOzjGl6uOcdAcy2d9Vno0 ------END RSA PRIVATE KEY----- diff --git a/tools/doimage/secure/kak_priv_pem.key b/tools/doimage/secure/kak_priv_pem.key deleted file mode 100644 index dfceaba..0000000 --- a/tools/doimage/secure/kak_priv_pem.key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAsj2cHcrE2pdyCqNr+oVcQULiRx6RivkrhLl2DTqWXpP33BPm -MP0W0X0z98X7E3kZO+JIGRZ8q+6AWmUpL+53aOGItNeUgT7jQKViPJIo9ZcEnv/n -PJqdgDd4xFhnwYMgq8uVYN9IPfaKDwB3EoOqjNox2JholUVxvLw6W8DAC8La3zwb -0hiqtIlirQOQ/KaTHxC6dPYkrai+jSK5uAX7Vt8RKYg5qfDxSdZckmC2xVKYURhV -bZAlyKki4h6f8CwYCJMQDpHL6mVYCuJ1Ju/OJEXvthDKD0CD2hwILhksdey3qMOC -I5lHSO1b+sTvnVHGs65wI7A+ZYwnadMNvS9e2QIDAQABAoIBAH2uu9q2FEEe8SdX -PNiWGQtbojsL7wzTzj/0lq2VVlqyc+AXmAWLMP/fDTn1vKlqhsSXNseZ96c0sgUL -uBM4T7MA9WivauQH+C6pb6/OUFt8daG4SNGPJOg4NUweGmt1jyAUmeyJBWPL6GXT -qiK//Q78/JECRxyaryyqfWwdak3flzfwONBJ03tQ9EO+L7hf9gAP7OYnAsuNp+Bz -tj1xzNMumYYYiHvsEXx8UTe8HGrmYuO53ZY5fBLGB6Jj7hRlAHNfcdVDvvoBU5cI -Zwi+5YsBuSP2Hr9Gt2Odu+KitH3gFdS0HIiDh44AT+Trj29NMANFDfkDbVHUmE0q -YBL75NECgYEA2E+fJzdaYyyPIcvQgVM8g52hltR5IRgJICND3NOdB/Zb2teBGZh+ -1XJ6ZqQMDcOQZo0CMbX9UNRnf3NU55k48/EEITxCgUJTx/WdfJeTVlWGspt5+U/r -hDnQmkePdU1en63+u9eqsla9+VhLwU3fl/pIOpsBAnoEzs3hMQZ1G0cCgYEA0vHH -ilm3AztIoZlH3wgDAl2Gu5/YopqEofKA8G4Jp89rlkk919P/GNjEc6575wjgztDB -0Xab+H7Nqxjs3HqQX/DTTuAxzAggBg3j/ijpHnmjrCHLeMT5ciyH+EH5Bg///cLq -+Cwn7aOWuSK1hGdDYxUycHylAYZXXFJzmEIEhN8CgYEA1qTrwPZkctTckyS0GiCG -g/P/TLQ6HmTDaWiVBqPVxvjn3RjLuqJf+V5Hp2JRs7bDq39xFfMJExQyP34qWkbp -BOe8uV4agDlY+ar4Q5IFWj40EzfEqWhsxCC6pt0rtbK4mqsFg1BWyfDZQnwjcAXe -QejRk5YMQnDiJHSXaRaHTjECgYAv6ecvD624ODEJM63VhRZZ5TCDUY19caeKuXB8 -LCJZUY3Ydw5rBaY92I7Wz90o3yVhFJ3RnCVVTkgdAu5aLiS5BhSZJ+dntri/Z0xQ -IK7C01JP+OUkq2kVe/Pued28eMnms+13LWBsY+oKZ03foyz1Ro1Ma6N3MzKIr9m9 -zdEE9QKBgECfoh0xE2T/cbJrtH0mwMCUM6eMVGq+yQBKNvuuPg6kaQUsah1n1rp6 -OyvjwRAXdhshszEzNTX1WTT6/i+vZX277Ax50pPo9UhQ9kVteVt1frN6+u5sy07V -fg1f2+m0iFx4BD/irU0fzSyfGE+QkBnmXFBUNSYjp2PSqYIdufmW ------END RSA PRIVATE KEY----- diff --git a/tools/doimage/secure/sec_img_7K.cfg b/tools/doimage/secure/sec_img_7K.cfg deleted file mode 100644 index 459f731..0000000 --- a/tools/doimage/secure/sec_img_7K.cfg +++ /dev/null @@ -1,29 +0,0 @@ -# Trusted boot image extension definitions - -kak_key_file = "tools/doimage/secure/kak_priv_pem.key"; - -# CSK keys array - 16 entries total. -# Only a key with csk_key_index will be used for signing the image -# use "*" string instead of file name for specifying an empty key -csk_key_file = ["tools/doimage/secure/csk_priv_pem0.key", - "tools/doimage/secure/csk_priv_pem1.key", - "tools/doimage/secure/csk_priv_pem2.key", - "tools/doimage/secure/csk_priv_pem3.key", - "*", "*", "*", "*", "*", "*", "*", "*", "*", "*", "*", "*"]; - -# index of CSK key in the array. Valid range is 0 to 15 -csk_key_index = 3; - -# AES-256 symmetric key for image encryption -aes_key_file = "tools/doimage/secure/aes_key.txt"; - -efuse_disable = false; -jtag = { enable = true; delay = 20; }; - -box_id = 0xdeadbeef; -flash_id = 0xbaddf00d; - -# SecureBootControl and EfuseBurnControl registers array -# Two register addresses for each connected CP -# A7K - one CP, two register values -control = [0xF2441920, 0xF2441940]; diff --git a/tools/doimage/secure/sec_img_8K.cfg b/tools/doimage/secure/sec_img_8K.cfg deleted file mode 100644 index a849dff..0000000 --- a/tools/doimage/secure/sec_img_8K.cfg +++ /dev/null @@ -1,29 +0,0 @@ -# Trusted boot image extension definitions - -kak_key_file = "tools/doimage/secure/kak_priv_pem.key"; - -# CSK keys array - 16 entries total. -# Only a key with csk_key_index will be used for signing the image -# use "*" string instead of file name for specifying an empty key -csk_key_file = ["tools/doimage/secure/csk_priv_pem0.key", - "tools/doimage/secure/csk_priv_pem1.key", - "tools/doimage/secure/csk_priv_pem2.key", - "tools/doimage/secure/csk_priv_pem3.key", - "*", "*", "*", "*", "*", "*", "*", "*", "*", "*", "*", "*"]; - -# index of CSK key in the array. Valid range is 0 to 15 -csk_key_index = 3; - -# AES-256 symmetric key for image encryption -aes_key_file = "tools/doimage/secure/aes_key.txt"; - -efuse_disable = false; -jtag = { enable = true; delay = 20; }; - -box_id = 0xdeadbeef; -flash_id = 0xbaddf00d; - -# SecureBootControl and EfuseBurnControl registers array -# Two register addresses for each connected CP -# A8K - two CP, four register values -control = [0xF2441920, 0xF2441940, 0xF4441920, 0xF4441940]; diff --git a/tools/marvell/doimage/Makefile b/tools/marvell/doimage/Makefile new file mode 100644 index 0000000..9f0d89d --- /dev/null +++ b/tools/marvell/doimage/Makefile @@ -0,0 +1,48 @@ +# +# Copyright (C) 2018 Marvell International Ltd. +# +# SPDX-License-Identifier: BSD-3-Clause +# https://spdx.org/licenses + +PROJECT = doimage +OBJECTS = doimage.o + +HOSTCCFLAGS = -Wall -Werror +ifeq (${DEBUG},1) + HOSTCCFLAGS += -g -O0 -DDEBUG +else + HOSTCCFLAGS += -O2 +endif + +ifeq (${MARVELL_SECURE_BOOT},1) +DOIMAGE_CC_FLAGS := -DCONFIG_MVEBU_SECURE_BOOT +DOIMAGE_LD_FLAGS := -lconfig -lmbedtls -lmbedcrypto -lmbedx509 +endif + +HOSTCCFLAGS += ${DOIMAGE_CC_FLAGS} + +# Make soft links and include from local directory otherwise wrong headers +# could get pulled in from firmware tree. +INCLUDE_PATHS = -I. + +HOSTCC ?= gcc +RM := rm -rf + +.PHONY: all clean + +all: ${PROJECT} + +${PROJECT}: ${OBJECTS} Makefile + @echo " HOSTLD $@" + ${Q}${HOSTCC} ${OBJECTS} ${DOIMAGE_LD_FLAGS} -o $@ + @echo + @echo "Built $@ successfully" + @echo + +%.o: %.c Makefile + @echo " HOSTCC $<" + ${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INCLUDE_PATHS} $< -o $@ + +clean: + ${Q}${RM} ${PROJECT} + ${Q}${RM} ${OBJECTS} diff --git a/tools/marvell/doimage/doimage.c b/tools/marvell/doimage/doimage.c new file mode 100644 index 0000000..82fd375 --- /dev/null +++ b/tools/marvell/doimage/doimage.c @@ -0,0 +1,1762 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_MVEBU_SECURE_BOOT +#include /* for parsing config file */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +/* mbedTLS stuff */ +#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_SHA256_C) && \ + defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_FS_IO) && \ + defined(MBEDTLS_CTR_DRBG_C) +#include +#include +#include +#include +#include +#include +#include +#else +#error "Bad mbedTLS configuration!" +#endif +#endif /* CONFIG_MVEBU_SECURE_BOOT */ + +#define MAX_FILENAME 256 +#define CSK_ARR_SZ 16 +#define CSK_ARR_EMPTY_FILE "*" +#define AES_KEY_BIT_LEN 256 +#define AES_KEY_BYTE_LEN (AES_KEY_BIT_LEN >> 3) +#define AES_BLOCK_SZ 16 +#define RSA_SIGN_BYTE_LEN 256 +#define MAX_RSA_DER_BYTE_LEN 524 +/* Number of address pairs in control array */ +#define CP_CTRL_EL_ARRAY_SZ 32 + +#define VERSION_STRING "Marvell(C) doimage utility version 3.2" + +/* A8K definitions */ + +/* Extension header types */ +#define EXT_TYPE_SECURITY 0x1 +#define EXT_TYPE_BINARY 0x2 + +#define MAIN_HDR_MAGIC 0xB105B002 + +/* PROLOG alignment considerations: + * 128B: To allow supporting XMODEM protocol. + * 8KB: To align the boot image to the largest NAND page size, and simplify + * the read operations from NAND. + * We choose the largest page size, in order to use a single image for all + * NAND page sizes. + */ +#define PROLOG_ALIGNMENT (8 << 10) + +/* UART argument bitfield */ +#define UART_MODE_UNMODIFIED 0x0 +#define UART_MODE_DISABLE 0x1 +#define UART_MODE_UPDATE 0x2 + +typedef struct _main_header { + uint32_t magic; /* 0-3 */ + uint32_t prolog_size; /* 4-7 */ + uint32_t prolog_checksum; /* 8-11 */ + uint32_t boot_image_size; /* 12-15 */ + uint32_t boot_image_checksum; /* 16-19 */ + uint32_t rsrvd0; /* 20-23 */ + uint32_t load_addr; /* 24-27 */ + uint32_t exec_addr; /* 28-31 */ + uint8_t uart_cfg; /* 32 */ + uint8_t baudrate; /* 33 */ + uint8_t ext_count; /* 34 */ + uint8_t aux_flags; /* 35 */ + uint32_t io_arg_0; /* 36-39 */ + uint32_t io_arg_1; /* 40-43 */ + uint32_t io_arg_2; /* 43-47 */ + uint32_t io_arg_3; /* 48-51 */ + uint32_t rsrvd1; /* 52-55 */ + uint32_t rsrvd2; /* 56-59 */ + uint32_t rsrvd3; /* 60-63 */ +} header_t; + +typedef struct _ext_header { + uint8_t type; + uint8_t offset; + uint16_t reserved; + uint32_t size; +} ext_header_t; + +typedef struct _sec_entry { + uint8_t kak_key[MAX_RSA_DER_BYTE_LEN]; + uint32_t jtag_delay; + uint32_t box_id; + uint32_t flash_id; + uint32_t jtag_en; + uint32_t encrypt_en; + uint32_t efuse_dis; + uint8_t header_sign[RSA_SIGN_BYTE_LEN]; + uint8_t image_sign[RSA_SIGN_BYTE_LEN]; + uint8_t csk_keys[CSK_ARR_SZ][MAX_RSA_DER_BYTE_LEN]; + uint8_t csk_sign[RSA_SIGN_BYTE_LEN]; + uint32_t cp_ctrl_arr[CP_CTRL_EL_ARRAY_SZ]; + uint32_t cp_efuse_arr[CP_CTRL_EL_ARRAY_SZ]; +} sec_entry_t; + +/* A8K definitions end */ + +/* UART argument bitfield */ +#define UART_MODE_UNMODIFIED 0x0 +#define UART_MODE_DISABLE 0x1 +#define UART_MODE_UPDATE 0x2 + +#define uart_set_mode(arg, mode) (arg |= (mode & 0x3)) + +typedef struct _sec_options { +#ifdef CONFIG_MVEBU_SECURE_BOOT + char aes_key_file[MAX_FILENAME+1]; + char kak_key_file[MAX_FILENAME+1]; + char csk_key_file[CSK_ARR_SZ][MAX_FILENAME+1]; + uint32_t box_id; + uint32_t flash_id; + uint32_t jtag_delay; + uint8_t csk_index; + uint8_t jtag_enable; + uint8_t efuse_disable; + uint32_t cp_ctrl_arr[CP_CTRL_EL_ARRAY_SZ]; + uint32_t cp_efuse_arr[CP_CTRL_EL_ARRAY_SZ]; + mbedtls_pk_context kak_pk; + mbedtls_pk_context csk_pk[CSK_ARR_SZ]; + uint8_t aes_key[AES_KEY_BYTE_LEN]; + uint8_t *encrypted_image; + uint32_t enc_image_sz; +#endif +} sec_options; + +typedef struct _options { + char bin_ext_file[MAX_FILENAME+1]; + char sec_cfg_file[MAX_FILENAME+1]; + sec_options *sec_opts; + uint32_t load_addr; + uint32_t exec_addr; + uint32_t baudrate; + uint8_t disable_print; + int8_t key_index; /* For header signatures verification only */ + uint32_t nfc_io_args; +} options_t; + +void usage_err(char *msg) +{ + fprintf(stderr, "Error: %s\n", msg); + fprintf(stderr, "run 'doimage -h' to get usage information\n"); + exit(-1); +} + +void usage(void) +{ + printf("\n\n%s\n\n", VERSION_STRING); + printf("Usage: doimage [options] [output_file]\n"); + printf("create bootrom image from u-boot and boot extensions\n\n"); + + printf("Arguments\n"); + printf(" input_file name of boot image file.\n"); + printf(" if -p is used, name of the bootrom image file"); + printf(" to parse.\n"); + printf(" output_file name of output bootrom image file\n"); + + printf("\nOptions\n"); + printf(" -s target SOC name. supports a8020,a7020\n"); + printf(" different SOCs may have different boot image\n"); + printf(" format so it's mandatory to know the target SOC\n"); + printf(" -i boot I/F name. supports nand, spi, nor\n"); + printf(" This affects certain parameters coded in the\n"); + printf(" image header\n"); + printf(" -l boot image load address. default is 0x0\n"); + printf(" -e boot image entry address. default is 0x0\n"); + printf(" -b binary extension image file.\n"); + printf(" This image is executed before the boot image.\n"); + printf(" This is typically used to initialize the memory "); + printf(" controller.\n"); + printf(" Currently supports only a single file.\n"); +#ifdef CONFIG_MVEBU_SECURE_BOOT + printf(" -c Make trusted boot image using parameters\n"); + printf(" from the configuration file.\n"); +#endif + printf(" -p Parse and display a pre-built boot image\n"); +#ifdef CONFIG_MVEBU_SECURE_BOOT + printf(" -k Key index for RSA signatures verification\n"); + printf(" when parsing the boot image\n"); +#endif + printf(" -m Disable prints of bootrom and binary extension\n"); + printf(" -u UART baudrate used for bootrom prints.\n"); + printf(" Must be multiple of 1200\n"); + printf(" -h Show this help message\n"); + printf(" IO-ROM NFC-NAND boot parameters:\n"); + printf(" -n NAND device block size in KB [Default is 64KB].\n"); + printf(" -t NAND cell technology (SLC [Default] or MLC)\n"); + + exit(-1); +} + +/* globals */ +static options_t opts = { + .bin_ext_file = "NA", + .sec_cfg_file = "NA", + .sec_opts = 0, + .load_addr = 0x0, + .exec_addr = 0x0, + .disable_print = 0, + .baudrate = 0, + .key_index = -1, +}; + +int get_file_size(char *filename) +{ + struct stat st; + + if (stat(filename, &st) == 0) + return st.st_size; + + return -1; +} + +uint32_t checksum32(uint32_t *start, int len) +{ + uint32_t sum = 0; + uint32_t *startp = start; + + do { + sum += *startp; + startp++; + len -= 4; + } while (len > 0); + + return sum; +} + +/******************************************************************************* + * create_rsa_signature (memory buffer content) + * Create RSASSA-PSS/SHA-256 signature for memory buffer + * using RSA Private Key + * INPUT: + * pk_ctx Private Key context + * input memory buffer + * ilen buffer length + * pers personalization string for seeding the RNG. + * For instance a private key file name. + * OUTPUT: + * signature RSA-2048 signature + * RETURN: + * 0 on success + */ +#ifdef CONFIG_MVEBU_SECURE_BOOT +int create_rsa_signature(mbedtls_pk_context *pk_ctx, + const unsigned char *input, + size_t ilen, + const char *pers, + uint8_t *signature) +{ + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + unsigned char hash[32]; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + int rval; + + /* Not sure this is required, + * but it's safer to start with empty buffers + */ + memset(hash, 0, sizeof(hash)); + memset(buf, 0, sizeof(buf)); + + mbedtls_ctr_drbg_init(&ctr_drbg); + mbedtls_entropy_init(&entropy); + + /* Seed the random number generator */ + rval = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *)pers, strlen(pers)); + if (rval != 0) { + fprintf(stderr, " Failed in ctr_drbg_init call (%d)!\n", rval); + goto sign_exit; + } + + /* The PK context should be already initialized. + * Set the padding type for this PK context + */ + mbedtls_rsa_set_padding(mbedtls_pk_rsa(*pk_ctx), + MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256); + + /* First compute the SHA256 hash for the input blob */ + mbedtls_sha256(input, ilen, hash, 0); + + /* Then calculate the hash signature */ + rval = mbedtls_rsa_rsassa_pss_sign(mbedtls_pk_rsa(*pk_ctx), + mbedtls_ctr_drbg_random, + &ctr_drbg, + MBEDTLS_RSA_PRIVATE, + MBEDTLS_MD_SHA256, 0, hash, buf); + if (rval != 0) { + fprintf(stderr, + "Failed to create RSA signature for %s. Error %d\n", + pers, rval); + goto sign_exit; + } + memcpy(signature, buf, 256); + +sign_exit: + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); + + return rval; +} /* end of create_rsa_signature */ + +/******************************************************************************* + * verify_rsa_signature (memory buffer content) + * Verify RSASSA-PSS/SHA-256 signature for memory buffer + * using RSA Public Key + * INPUT: + * pub_key Public Key buffer + * ilen Public Key buffer length + * input memory buffer + * ilen buffer length + * pers personalization string for seeding the RNG. + * signature RSA-2048 signature + * OUTPUT: + * none + * RETURN: + * 0 on success + */ +int verify_rsa_signature(const unsigned char *pub_key, + size_t klen, + const unsigned char *input, + size_t ilen, + const char *pers, + uint8_t *signature) +{ + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_pk_context pk_ctx; + unsigned char hash[32]; + int rval; + + /* Not sure this is required, + * but it's safer to start with empty buffer + */ + memset(hash, 0, sizeof(hash)); + + mbedtls_pk_init(&pk_ctx); + mbedtls_ctr_drbg_init(&ctr_drbg); + mbedtls_entropy_init(&entropy); + + /* Seed the random number generator */ + rval = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *)pers, strlen(pers)); + if (rval != 0) { + fprintf(stderr, " Failed in ctr_drbg_init call (%d)!\n", rval); + goto verify_exit; + } + + /* Check ability to read the public key */ + rval = mbedtls_pk_parse_public_key(&pk_ctx, pub_key, + MAX_RSA_DER_BYTE_LEN); + if (rval != 0) { + fprintf(stderr, " Failed in pk_parse_public_key (%#x)!\n", + rval); + goto verify_exit; + } + + /* Set the padding type for the new PK context */ + mbedtls_rsa_set_padding(mbedtls_pk_rsa(pk_ctx), + MBEDTLS_RSA_PKCS_V21, + MBEDTLS_MD_SHA256); + + /* Compute the SHA256 hash for the input buffer */ + mbedtls_sha256(input, ilen, hash, 0); + + rval = mbedtls_rsa_rsassa_pss_verify(mbedtls_pk_rsa(pk_ctx), + mbedtls_ctr_drbg_random, + &ctr_drbg, + MBEDTLS_RSA_PUBLIC, + MBEDTLS_MD_SHA256, 0, + hash, signature); + if (rval != 0) + fprintf(stderr, "Failed to verify signature (%d)!\n", rval); + +verify_exit: + + mbedtls_pk_free(&pk_ctx); + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); + return rval; +} /* end of verify_rsa_signature */ + +/******************************************************************************* + * image_encrypt + * Encrypt image buffer using AES-256-CBC scheme. + * The resulting image is saved into opts.sec_opts->encrypted_image + * and the adjusted image size into opts.sec_opts->enc_image_sz + * First AES_BLOCK_SZ bytes of the output image contain IV + * INPUT: + * buf Source buffer to encrypt + * blen Source buffer length + * OUTPUT: + * none + * RETURN: + * 0 on success + */ +int image_encrypt(uint8_t *buf, uint32_t blen) +{ + struct timeval tv; + char *ptmp = (char *)&tv; + unsigned char digest[32]; + unsigned char IV[AES_BLOCK_SZ]; + int i, k; + mbedtls_aes_context aes_ctx; + int rval = -1; + uint8_t *test_img = 0; + + if (AES_BLOCK_SZ > 32) { + fprintf(stderr, "Unsupported AES block size %d\n", + AES_BLOCK_SZ); + return rval; + } + + mbedtls_aes_init(&aes_ctx); + memset(IV, 0, AES_BLOCK_SZ); + memset(digest, 0, 32); + + /* Generate initialization vector and init the AES engine + * Use file name XOR current time and finally SHA-256 + * [0...AES_BLOCK_SZ-1] + */ + k = strlen(opts.sec_opts->aes_key_file); + if (k > AES_BLOCK_SZ) + k = AES_BLOCK_SZ; + memcpy(IV, opts.sec_opts->aes_key_file, k); + gettimeofday(&tv, 0); + + for (i = 0, k = 0; i < AES_BLOCK_SZ; i++, + k = (k+1) % sizeof(struct timeval)) + IV[i] ^= ptmp[k]; + + /* compute SHA-256 digest of the results + * and use it as the init vector (IV) + */ + mbedtls_sha256(IV, AES_BLOCK_SZ, digest, 0); + memcpy(IV, digest, AES_BLOCK_SZ); + mbedtls_aes_setkey_enc(&aes_ctx, opts.sec_opts->aes_key, + AES_KEY_BIT_LEN); + + /* The output image has to include extra space for IV + * and to be aligned to the AES block size. + * The input image buffer has to be already aligned to AES_BLOCK_SZ + * and padded with zeroes + */ + opts.sec_opts->enc_image_sz = (blen + 2 * AES_BLOCK_SZ - 1) & + ~(AES_BLOCK_SZ - 1); + opts.sec_opts->encrypted_image = calloc(opts.sec_opts->enc_image_sz, 1); + if (opts.sec_opts->encrypted_image == 0) { + fprintf(stderr, "Failed to allocate encrypted image!\n"); + goto encrypt_exit; + } + + /* Put IV into the output buffer next to the encrypted image + * Since the IV is modified by the encryption function, + * this should be done now + */ + memcpy(opts.sec_opts->encrypted_image + + opts.sec_opts->enc_image_sz - AES_BLOCK_SZ, + IV, AES_BLOCK_SZ); + rval = mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_ENCRYPT, + opts.sec_opts->enc_image_sz - AES_BLOCK_SZ, + IV, buf, opts.sec_opts->encrypted_image); + if (rval != 0) { + fprintf(stderr, "Failed to encrypt the image! Error %d\n", + rval); + goto encrypt_exit; + } + + mbedtls_aes_free(&aes_ctx); + + /* Try to decrypt the image and compare it with the original data */ + mbedtls_aes_init(&aes_ctx); + mbedtls_aes_setkey_dec(&aes_ctx, opts.sec_opts->aes_key, + AES_KEY_BIT_LEN); + + test_img = calloc(opts.sec_opts->enc_image_sz - AES_BLOCK_SZ, 1); + if (test_img == 0) { + fprintf(stderr, "Failed to allocate test image!d\n"); + rval = -1; + goto encrypt_exit; + } + + memcpy(IV, opts.sec_opts->encrypted_image + + opts.sec_opts->enc_image_sz - AES_BLOCK_SZ, + AES_BLOCK_SZ); + rval = mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, + opts.sec_opts->enc_image_sz - AES_BLOCK_SZ, + IV, opts.sec_opts->encrypted_image, test_img); + if (rval != 0) { + fprintf(stderr, "Failed to decrypt the image! Error %d\n", + rval); + goto encrypt_exit; + } + + for (i = 0; i < blen; i++) { + if (buf[i] != test_img[i]) { + fprintf(stderr, "Failed to compare the image after"); + fprintf(stderr, " decryption! Byte count is %d\n", i); + rval = -1; + goto encrypt_exit; + } + } + +encrypt_exit: + + mbedtls_aes_free(&aes_ctx); + if (test_img) + free(test_img); + + return rval; +} /* end of image_encrypt */ + +/******************************************************************************* + * verify_secure_header_signatures + * Verify CSK array, header and image signatures and print results + * INPUT: + * main_hdr Main header + * sec_ext Secure extension + * OUTPUT: + * none + * RETURN: + * 0 on success + */ +int verify_secure_header_signatures(header_t *main_hdr, sec_entry_t *sec_ext) +{ + uint8_t *image = (uint8_t *)main_hdr + main_hdr->prolog_size; + uint8_t signature[RSA_SIGN_BYTE_LEN]; + int rval = -1; + + /* Save headers signature and reset it in the secure header */ + memcpy(signature, sec_ext->header_sign, RSA_SIGN_BYTE_LEN); + memset(sec_ext->header_sign, 0, RSA_SIGN_BYTE_LEN); + + fprintf(stdout, "\nCheck RSA Signatures\n"); + fprintf(stdout, "#########################\n"); + fprintf(stdout, "CSK Block Signature: "); + if (verify_rsa_signature(sec_ext->kak_key, + MAX_RSA_DER_BYTE_LEN, + &sec_ext->csk_keys[0][0], + sizeof(sec_ext->csk_keys), + "CSK Block Signature: ", + sec_ext->csk_sign) != 0) { + fprintf(stdout, "ERROR\n"); + goto ver_error; + } + fprintf(stdout, "OK\n"); + + if (opts.key_index != -1) { + fprintf(stdout, "Image Signature: "); + if (verify_rsa_signature(sec_ext->csk_keys[opts.key_index], + MAX_RSA_DER_BYTE_LEN, + image, main_hdr->boot_image_size, + "Image Signature: ", + sec_ext->image_sign) != 0) { + fprintf(stdout, "ERROR\n"); + goto ver_error; + } + fprintf(stdout, "OK\n"); + + fprintf(stdout, "Header Signature: "); + if (verify_rsa_signature(sec_ext->csk_keys[opts.key_index], + MAX_RSA_DER_BYTE_LEN, + (uint8_t *)main_hdr, + main_hdr->prolog_size, + "Header Signature: ", + signature) != 0) { + fprintf(stdout, "ERROR\n"); + goto ver_error; + } + fprintf(stdout, "OK\n"); + } else { + fprintf(stdout, "SKIP Image and Header Signatures"); + fprintf(stdout, " check (undefined key index)\n"); + } + + rval = 0; + +ver_error: + memcpy(sec_ext->header_sign, signature, RSA_SIGN_BYTE_LEN); + return rval; +} + +/******************************************************************************* + * verify_and_copy_file_name_entry + * INPUT: + * element_name + * element + * OUTPUT: + * copy_to + * RETURN: + * 0 on success + */ +int verify_and_copy_file_name_entry(const char *element_name, + const char *element, char *copy_to) +{ + int element_length = strlen(element); + + if (element_length >= MAX_FILENAME) { + fprintf(stderr, "The file name %s for %s is too long (%d). ", + element, element_name, element_length); + fprintf(stderr, "Maximum allowed %d characters!\n", + MAX_FILENAME); + return -1; + } else if (element_length == 0) { + fprintf(stderr, "The file name for %s is empty!\n", + element_name); + return -1; + } + memcpy(copy_to, element, element_length); + + return 0; +} + +/******************************************************************************* + * parse_sec_config_file + * Read the secure boot configuration from a file + * into internal structures + * INPUT: + * filename File name + * OUTPUT: + * none + * RETURN: + * 0 on success + */ +int parse_sec_config_file(char *filename) +{ + config_t sec_cfg; + int array_sz, element, rval = -1; + const char *cfg_string; + int32_t cfg_int32; + const config_setting_t *csk_array, *control_array; + sec_options *sec_opt = 0; + + config_init(&sec_cfg); + + if (config_read_file(&sec_cfg, filename) != CONFIG_TRUE) { + fprintf(stderr, "Failed to read data from config file "); + fprintf(stderr, "%s\n\t%s at line %d\n", + filename, config_error_text(&sec_cfg), + config_error_line(&sec_cfg)); + goto exit_parse; + } + + sec_opt = (sec_options *)calloc(sizeof(sec_options), 1); + if (sec_opt == 0) { + fprintf(stderr, + "Cannot allocate memory for secure boot options!\n"); + goto exit_parse; + } + + /* KAK file name */ + if (config_lookup_string(&sec_cfg, "kak_key_file", + &cfg_string) != CONFIG_TRUE) { + fprintf(stderr, "The \"kak_key_file\" undefined!\n"); + goto exit_parse; + } + if (verify_and_copy_file_name_entry("kak_key_file", + cfg_string, sec_opt->kak_key_file)) + goto exit_parse; + + + /* AES file name - can be empty/undefined */ + if (config_lookup_string(&sec_cfg, "aes_key_file", + &cfg_string) == CONFIG_TRUE) { + if (verify_and_copy_file_name_entry("aes_key_file", + cfg_string, + sec_opt->aes_key_file)) + goto exit_parse; + } + + /* CSK file names array */ + csk_array = config_lookup(&sec_cfg, "csk_key_file"); + if (csk_array == NULL) { + fprintf(stderr, "The \"csk_key_file\" undefined!\n"); + goto exit_parse; + } + array_sz = config_setting_length(csk_array); + if (array_sz > CSK_ARR_SZ) { + fprintf(stderr, "The \"csk_key_file\" array is too big! "); + fprintf(stderr, "Only first %d elements will be used\n", + CSK_ARR_SZ); + array_sz = CSK_ARR_SZ; + } else if (array_sz == 0) { + fprintf(stderr, "The \"csk_key_file\" array is empty!\n"); + goto exit_parse; + } + + for (element = 0; element < array_sz; element++) { + cfg_string = config_setting_get_string_elem(csk_array, element); + if (verify_and_copy_file_name_entry( + "csk_key_file", cfg_string, + sec_opt->csk_key_file[element])) { + fprintf(stderr, "Bad csk_key_file[%d] entry!\n", + element); + goto exit_parse; + } + } + + /* JTAG options */ + if (config_lookup_bool(&sec_cfg, "jtag.enable", + &cfg_int32) != CONFIG_TRUE) { + fprintf(stderr, "Error obtaining \"jtag.enable\" element. "); + fprintf(stderr, "Using default - FALSE\n"); + cfg_int32 = 0; + } + sec_opt->jtag_enable = cfg_int32; + + if (config_lookup_int(&sec_cfg, "jtag.delay", + &cfg_int32) != CONFIG_TRUE) { + fprintf(stderr, "Error obtaining \"jtag.delay\" element. "); + fprintf(stderr, "Using default - 0us\n"); + cfg_int32 = 0; + } + sec_opt->jtag_delay = cfg_int32; + + /* eFUSE option */ + if (config_lookup_bool(&sec_cfg, "efuse_disable", + &cfg_int32) != CONFIG_TRUE) { + fprintf(stderr, "Error obtaining \"efuse_disable\" element. "); + fprintf(stderr, "Using default - TRUE\n"); + cfg_int32 = 1; + } + sec_opt->efuse_disable = cfg_int32; + + /* Box ID option */ + if (config_lookup_int(&sec_cfg, "box_id", &cfg_int32) != CONFIG_TRUE) { + fprintf(stderr, "Error obtaining \"box_id\" element. "); + fprintf(stderr, "Using default - 0x0\n"); + cfg_int32 = 0; + } + sec_opt->box_id = cfg_int32; + + /* Flash ID option */ + if (config_lookup_int(&sec_cfg, "flash_id", + &cfg_int32) != CONFIG_TRUE) { + fprintf(stderr, "Error obtaining \"flash_id\" element. "); + fprintf(stderr, "Using default - 0x0\n"); + cfg_int32 = 0; + } + sec_opt->flash_id = cfg_int32; + + /* CSK index option */ + if (config_lookup_int(&sec_cfg, "csk_key_index", + &cfg_int32) != CONFIG_TRUE) { + fprintf(stderr, "Error obtaining \"flash_id\" element. "); + fprintf(stderr, "Using default - 0x0\n"); + cfg_int32 = 0; + } + sec_opt->csk_index = cfg_int32; + + /* Secure boot control array */ + control_array = config_lookup(&sec_cfg, "control"); + if (control_array != NULL) { + array_sz = config_setting_length(control_array); + if (array_sz == 0) + fprintf(stderr, "The \"control\" array is empty!\n"); + } else { + fprintf(stderr, "The \"control\" is undefined!\n"); + array_sz = 0; + } + + for (element = 0; element < CP_CTRL_EL_ARRAY_SZ; element++) { + sec_opt->cp_ctrl_arr[element] = + config_setting_get_int_elem(control_array, element * 2); + sec_opt->cp_efuse_arr[element] = + config_setting_get_int_elem(control_array, + element * 2 + 1); + } + + opts.sec_opts = sec_opt; + rval = 0; + +exit_parse: + config_destroy(&sec_cfg); + if (sec_opt && (rval != 0)) + free(sec_opt); + return rval; +} /* end of parse_sec_config_file */ + +int format_sec_ext(char *filename, FILE *out_fd) +{ + ext_header_t header; + sec_entry_t sec_ext; + int index; + int written; + +#define DER_BUF_SZ 1600 + + /* First, parse the configuration file */ + if (parse_sec_config_file(filename)) { + fprintf(stderr, + "failed parsing configuration file %s\n", filename); + return 1; + } + + /* Everything except signatures can be created at this stage */ + header.type = EXT_TYPE_SECURITY; + header.offset = 0; + header.size = sizeof(sec_entry_t); + header.reserved = 0; + + /* Bring up RSA context and read private keys from their files */ + for (index = 0; index < (CSK_ARR_SZ + 1); index++) { + /* for every private key file */ + mbedtls_pk_context *pk_ctx = (index == CSK_ARR_SZ) ? + &opts.sec_opts->kak_pk : + &opts.sec_opts->csk_pk[index]; + char *fname = (index == CSK_ARR_SZ) ? + opts.sec_opts->kak_key_file : + opts.sec_opts->csk_key_file[index]; + uint8_t *out_der_key = (index == CSK_ARR_SZ) ? + sec_ext.kak_key : + sec_ext.csk_keys[index]; + size_t output_len; + unsigned char output_buf[DER_BUF_SZ]; + unsigned char *der_buf_start; + + /* Handle invalid/reserved file names */ + if (strncmp(CSK_ARR_EMPTY_FILE, fname, + strlen(CSK_ARR_EMPTY_FILE)) == 0) { + if (opts.sec_opts->csk_index == index) { + fprintf(stderr, + "CSK file with index %d cannot be %s\n", + index, CSK_ARR_EMPTY_FILE); + return 1; + } else if (index == CSK_ARR_SZ) { + fprintf(stderr, "KAK file name cannot be %s\n", + CSK_ARR_EMPTY_FILE); + return 1; + } + /* this key will be empty in CSK array */ + continue; + } + + mbedtls_pk_init(pk_ctx); + /* Read the private RSA key into the context + * and verify it (no password) + */ + if (mbedtls_pk_parse_keyfile(pk_ctx, fname, "") != 0) { + fprintf(stderr, + "Cannot read RSA private key file %s\n", fname); + return 1; + } + + /* Create a public key out of private one + * and store it in DER format + */ + output_len = mbedtls_pk_write_pubkey_der(pk_ctx, + output_buf, + DER_BUF_SZ); + if (output_len < 0) { + fprintf(stderr, + "Failed to create DER coded PUB key (%s)\n", + fname); + return 1; + } + /* Data in the output buffer is aligned to the buffer end */ + der_buf_start = output_buf + sizeof(output_buf) - output_len; + /* In the header DER data is aligned + * to the start of appropriate field + */ + memcpy(out_der_key, der_buf_start, output_len); + + } /* for every private key file */ + + /* The CSK block signature can be created here */ + if (create_rsa_signature(&opts.sec_opts->kak_pk, + &sec_ext.csk_keys[0][0], + sizeof(sec_ext.csk_keys), + opts.sec_opts->csk_key_file[ + opts.sec_opts->csk_index], + sec_ext.csk_sign) != 0) { + fprintf(stderr, "Failed to sign CSK keys block!\n"); + return 1; + } + /* Check that everything is correct */ + if (verify_rsa_signature(sec_ext.kak_key, MAX_RSA_DER_BYTE_LEN, + &sec_ext.csk_keys[0][0], + sizeof(sec_ext.csk_keys), + opts.sec_opts->kak_key_file, + sec_ext.csk_sign) != 0) { + fprintf(stderr, "Failed to verify CSK keys block signature!\n"); + return 1; + } + + /* AES encryption stuff */ + if (strlen(opts.sec_opts->aes_key_file) != 0) { + FILE *in_fd; + + in_fd = fopen(opts.sec_opts->aes_key_file, "rb"); + if (in_fd == NULL) { + fprintf(stderr, "Failed to open AES key file %s\n", + opts.sec_opts->aes_key_file); + return 1; + } + + /* Read the AES key in ASCII format byte by byte */ + for (index = 0; index < AES_KEY_BYTE_LEN; index++) { + if (fscanf(in_fd, "%02hhx", + opts.sec_opts->aes_key + index) != 1) { + fprintf(stderr, + "Failed to read AES key byte %d ", + index); + fprintf(stderr, + "from file %s\n", + opts.sec_opts->aes_key_file); + fclose(in_fd); + return 1; + } + } + fclose(in_fd); + sec_ext.encrypt_en = 1; + } else { + sec_ext.encrypt_en = 0; + } + + /* Fill the rest of the trusted boot extension fields */ + sec_ext.box_id = opts.sec_opts->box_id; + sec_ext.flash_id = opts.sec_opts->flash_id; + sec_ext.efuse_dis = opts.sec_opts->efuse_disable; + sec_ext.jtag_delay = opts.sec_opts->jtag_delay; + sec_ext.jtag_en = opts.sec_opts->jtag_enable; + + memcpy(sec_ext.cp_ctrl_arr, + opts.sec_opts->cp_ctrl_arr, + sizeof(uint32_t) * CP_CTRL_EL_ARRAY_SZ); + memcpy(sec_ext.cp_efuse_arr, + opts.sec_opts->cp_efuse_arr, + sizeof(uint32_t) * CP_CTRL_EL_ARRAY_SZ); + + /* Write the resulting extension to file + * (image and header signature fields are still empty) + */ + + /* Write extension header */ + written = fwrite(&header, sizeof(ext_header_t), 1, out_fd); + if (written != 1) { + fprintf(stderr, + "Failed to write SEC extension header to the file\n"); + return 1; + } + /* Write extension body */ + written = fwrite(&sec_ext, sizeof(sec_entry_t), 1, out_fd); + if (written != 1) { + fprintf(stderr, + "Failed to write SEC extension body to the file\n"); + return 1; + } + + return 0; +} + +/******************************************************************************* + * finalize_secure_ext + * Make final changes to secure extension - calculate image and header + * signatures and encrypt the image if needed. + * The main header checksum and image size fields updated accordingly + * INPUT: + * header Main header + * prolog_buf the entire prolog buffer + * prolog_size prolog buffer length + * image_buf buffer containing the input binary image + * image_size image buffer size. + * OUTPUT: + * none + * RETURN: + * 0 on success + */ +int finalize_secure_ext(header_t *header, + uint8_t *prolog_buf, uint32_t prolog_size, + uint8_t *image_buf, int image_size) +{ + int cur_ext, offset; + uint8_t *final_image = image_buf; + uint32_t final_image_sz = image_size; + uint8_t hdr_sign[RSA_SIGN_BYTE_LEN]; + sec_entry_t *sec_ext = 0; + + /* Find the Trusted Boot Header between available extensions */ + for (cur_ext = 0, offset = sizeof(header_t); + cur_ext < header->ext_count; cur_ext++) { + ext_header_t *ext_hdr = (ext_header_t *)(prolog_buf + offset); + + if (ext_hdr->type == EXT_TYPE_SECURITY) { + sec_ext = (sec_entry_t *)(prolog_buf + offset + + sizeof(ext_header_t) + ext_hdr->offset); + break; + } + + offset += sizeof(ext_header_t); + /* If offset is Zero, the extension follows its header */ + if (ext_hdr->offset == 0) + offset += ext_hdr->size; + } + + if (sec_ext == 0) { + fprintf(stderr, "Error: No Trusted Boot extension found!\n"); + return -1; + } + + if (sec_ext->encrypt_en) { + /* Encrypt the image if needed */ + fprintf(stdout, "Encrypting the image...\n"); + + if (image_encrypt(image_buf, image_size) != 0) { + fprintf(stderr, "Failed to encrypt the image!\n"); + return -1; + } + + /* Image size and checksum should be updated after encryption. + * This way the image could be verified by the BootROM + * before decryption. + */ + final_image = opts.sec_opts->encrypted_image; + final_image_sz = opts.sec_opts->enc_image_sz; + + header->boot_image_size = final_image_sz; + header->boot_image_checksum = + checksum32((uint32_t *)final_image, final_image_sz); + } /* AES encryption */ + + /* Create the image signature first, since it will be later + * signed along with the header signature + */ + if (create_rsa_signature(&opts.sec_opts->csk_pk[ + opts.sec_opts->csk_index], + final_image, final_image_sz, + opts.sec_opts->csk_key_file[ + opts.sec_opts->csk_index], + sec_ext->image_sign) != 0) { + fprintf(stderr, "Failed to sign image!\n"); + return -1; + } + /* Check that the image signature is correct */ + if (verify_rsa_signature(sec_ext->csk_keys[opts.sec_opts->csk_index], + MAX_RSA_DER_BYTE_LEN, + final_image, final_image_sz, + opts.sec_opts->csk_key_file[ + opts.sec_opts->csk_index], + sec_ext->image_sign) != 0) { + fprintf(stderr, "Failed to verify image signature!\n"); + return -1; + } + + /* Sign the headers and all the extensions block + * when the header signature field is empty + */ + if (create_rsa_signature(&opts.sec_opts->csk_pk[ + opts.sec_opts->csk_index], + prolog_buf, prolog_size, + opts.sec_opts->csk_key_file[ + opts.sec_opts->csk_index], + hdr_sign) != 0) { + fprintf(stderr, "Failed to sign header!\n"); + return -1; + } + /* Check that the header signature is correct */ + if (verify_rsa_signature(sec_ext->csk_keys[opts.sec_opts->csk_index], + MAX_RSA_DER_BYTE_LEN, + prolog_buf, prolog_size, + opts.sec_opts->csk_key_file[ + opts.sec_opts->csk_index], + hdr_sign) != 0) { + fprintf(stderr, "Failed to verify header signature!\n"); + return -1; + } + + /* Finally, copy the header signature into the trusted boot extension */ + memcpy(sec_ext->header_sign, hdr_sign, RSA_SIGN_BYTE_LEN); + + return 0; +} + +#endif /* CONFIG_MVEBU_SECURE_BOOT */ + + +#define FMT_HEX 0 +#define FMT_DEC 1 +#define FMT_BIN 2 +#define FMT_NONE 3 + +void do_print_field(unsigned int value, char *name, + int start, int size, int format) +{ + fprintf(stdout, "[0x%05x : 0x%05x] %-26s", + start, start + size - 1, name); + + switch (format) { + case FMT_HEX: + printf("0x%x\n", value); + break; + case FMT_DEC: + printf("%d\n", value); + break; + default: + printf("\n"); + break; + } +} + +#define print_field(st, type, field, hex, base) \ + do_print_field((int)st->field, #field, \ + base + offsetof(type, field), sizeof(st->field), hex) + +int print_header(uint8_t *buf, int base) +{ + header_t *main_hdr; + + main_hdr = (header_t *)buf; + + fprintf(stdout, "########### Header ##############\n"); + print_field(main_hdr, header_t, magic, FMT_HEX, base); + print_field(main_hdr, header_t, prolog_size, FMT_DEC, base); + print_field(main_hdr, header_t, prolog_checksum, FMT_HEX, base); + print_field(main_hdr, header_t, boot_image_size, FMT_DEC, base); + print_field(main_hdr, header_t, boot_image_checksum, FMT_HEX, base); + print_field(main_hdr, header_t, rsrvd0, FMT_HEX, base); + print_field(main_hdr, header_t, load_addr, FMT_HEX, base); + print_field(main_hdr, header_t, exec_addr, FMT_HEX, base); + print_field(main_hdr, header_t, uart_cfg, FMT_HEX, base); + print_field(main_hdr, header_t, baudrate, FMT_HEX, base); + print_field(main_hdr, header_t, ext_count, FMT_DEC, base); + print_field(main_hdr, header_t, aux_flags, FMT_HEX, base); + print_field(main_hdr, header_t, io_arg_0, FMT_HEX, base); + print_field(main_hdr, header_t, io_arg_1, FMT_HEX, base); + print_field(main_hdr, header_t, io_arg_2, FMT_HEX, base); + print_field(main_hdr, header_t, io_arg_3, FMT_HEX, base); + print_field(main_hdr, header_t, rsrvd1, FMT_HEX, base); + print_field(main_hdr, header_t, rsrvd2, FMT_HEX, base); + print_field(main_hdr, header_t, rsrvd3, FMT_HEX, base); + + return sizeof(header_t); +} + +int print_ext_hdr(ext_header_t *ext_hdr, int base) +{ + print_field(ext_hdr, ext_header_t, type, FMT_HEX, base); + print_field(ext_hdr, ext_header_t, offset, FMT_HEX, base); + print_field(ext_hdr, ext_header_t, reserved, FMT_HEX, base); + print_field(ext_hdr, ext_header_t, size, FMT_DEC, base); + + return base + sizeof(ext_header_t); +} + +void print_sec_ext(ext_header_t *ext_hdr, int base) +{ + sec_entry_t *sec_entry; + uint32_t new_base; + + fprintf(stdout, "\n########### Secure extension ###########\n"); + + new_base = print_ext_hdr(ext_hdr, base); + + sec_entry = (sec_entry_t *)(ext_hdr + 1); + + do_print_field(0, "KAK key", new_base, MAX_RSA_DER_BYTE_LEN, FMT_NONE); + new_base += MAX_RSA_DER_BYTE_LEN; + print_field(sec_entry, sec_entry_t, jtag_delay, FMT_DEC, base); + print_field(sec_entry, sec_entry_t, box_id, FMT_HEX, base); + print_field(sec_entry, sec_entry_t, flash_id, FMT_HEX, base); + print_field(sec_entry, sec_entry_t, encrypt_en, FMT_DEC, base); + print_field(sec_entry, sec_entry_t, efuse_dis, FMT_DEC, base); + new_base += 6 * sizeof(uint32_t); + do_print_field(0, "header signature", + new_base, RSA_SIGN_BYTE_LEN, FMT_NONE); + new_base += RSA_SIGN_BYTE_LEN; + do_print_field(0, "image signature", + new_base, RSA_SIGN_BYTE_LEN, FMT_NONE); + new_base += RSA_SIGN_BYTE_LEN; + do_print_field(0, "CSK keys", new_base, + CSK_ARR_SZ * MAX_RSA_DER_BYTE_LEN, FMT_NONE); + new_base += CSK_ARR_SZ * MAX_RSA_DER_BYTE_LEN; + do_print_field(0, "CSK block signature", + new_base, RSA_SIGN_BYTE_LEN, FMT_NONE); + new_base += RSA_SIGN_BYTE_LEN; + do_print_field(0, "control", new_base, + CP_CTRL_EL_ARRAY_SZ * 2, FMT_NONE); + +} + +void print_bin_ext(ext_header_t *ext_hdr, int base) +{ + fprintf(stdout, "\n########### Binary extension ###########\n"); + base = print_ext_hdr(ext_hdr, base); + do_print_field(0, "binary image", base, ext_hdr->size, FMT_NONE); +} + +int print_extension(void *buf, int base, int count, int ext_size) +{ + ext_header_t *ext_hdr = buf; + int pad = ext_size; + int curr_size; + + while (count--) { + if (ext_hdr->type == EXT_TYPE_BINARY) + print_bin_ext(ext_hdr, base); + else if (ext_hdr->type == EXT_TYPE_SECURITY) + print_sec_ext(ext_hdr, base); + + curr_size = sizeof(ext_header_t) + ext_hdr->size; + base += curr_size; + pad -= curr_size; + ext_hdr = (ext_header_t *)((uintptr_t)ext_hdr + curr_size); + } + + if (pad) + do_print_field(0, "padding", base, pad, FMT_NONE); + + return ext_size; +} + +int parse_image(uint8_t *buf, int size) +{ + int base = 0; + int ret = 1; + header_t *main_hdr; + uint32_t checksum, prolog_checksum; + + + fprintf(stdout, + "################### Prolog Start ######################\n\n"); + main_hdr = (header_t *)buf; + base += print_header(buf, base); + + if (main_hdr->ext_count) + base += print_extension(buf + base, base, + main_hdr->ext_count, + main_hdr->prolog_size - + sizeof(header_t)); + + if (base < main_hdr->prolog_size) { + fprintf(stdout, "\n########### Padding ##############\n"); + do_print_field(0, "prolog padding", + base, main_hdr->prolog_size - base, FMT_HEX); + base = main_hdr->prolog_size; + } + fprintf(stdout, + "\n################### Prolog End ######################\n"); + + fprintf(stdout, + "\n################### Boot image ######################\n"); + + do_print_field(0, "boot image", base, size - base - 4, FMT_NONE); + + fprintf(stdout, + "################### Image end ########################\n"); + + /* Check sanity for certain values */ + printf("\nChecking values:\n"); + + if (main_hdr->magic == MAIN_HDR_MAGIC) { + fprintf(stdout, "Headers magic: OK!\n"); + } else { + fprintf(stderr, + "\n****** ERROR: HEADER MAGIC 0x%08x != 0x%08x\n", + main_hdr->magic, MAIN_HDR_MAGIC); + goto error; + } + + /* headers checksum */ + /* clear the checksum field in header to calculate checksum */ + prolog_checksum = main_hdr->prolog_checksum; + main_hdr->prolog_checksum = 0; + checksum = checksum32((uint32_t *)buf, main_hdr->prolog_size); + + if (checksum == prolog_checksum) { + fprintf(stdout, "Headers checksum: OK!\n"); + } else { + fprintf(stderr, + "\n***** ERROR: BAD HEADER CHECKSUM 0x%08x != 0x%08x\n", + checksum, prolog_checksum); + goto error; + } + + /* boot image checksum */ + checksum = checksum32((uint32_t *)(buf + main_hdr->prolog_size), + main_hdr->boot_image_size); + if (checksum == main_hdr->boot_image_checksum) { + fprintf(stdout, "Image checksum: OK!\n"); + } else { + fprintf(stderr, + "\n****** ERROR: BAD IMAGE CHECKSUM 0x%08x != 0x%08x\n", + checksum, main_hdr->boot_image_checksum); + goto error; + } + +#ifdef CONFIG_MVEBU_SECURE_BOOT + /* RSA signatures */ + if (main_hdr->ext_count) { + uint8_t ext_num = main_hdr->ext_count; + ext_header_t *ext_hdr = (ext_header_t *)(main_hdr + 1); + unsigned char hash[32]; + int i; + + while (ext_num--) { + if (ext_hdr->type == EXT_TYPE_SECURITY) { + sec_entry_t *sec_entry = + (sec_entry_t *)(ext_hdr + 1); + + ret = verify_secure_header_signatures( + main_hdr, sec_entry); + if (ret != 0) { + fprintf(stderr, + "\n****** FAILED TO VERIFY "); + fprintf(stderr, + "RSA SIGNATURES ********\n"); + goto error; + } + + mbedtls_sha256(sec_entry->kak_key, + MAX_RSA_DER_BYTE_LEN, hash, 0); + fprintf(stdout, + ">>>>>>>>>> KAK KEY HASH >>>>>>>>>>\n"); + fprintf(stdout, "SHA256: "); + for (i = 0; i < 32; i++) + fprintf(stdout, "%02X", hash[i]); + + fprintf(stdout, + "\n<<<<<<<<< KAK KEY HASH <<<<<<<<<\n"); + + break; + } + ext_hdr = + (ext_header_t *)((uint8_t *)(ext_hdr + 1) + + ext_hdr->size); + } + } +#endif + + ret = 0; +error: + return ret; +} + +int format_bin_ext(char *filename, FILE *out_fd) +{ + ext_header_t header; + FILE *in_fd; + int size, written; + int aligned_size, pad_bytes; + char c; + + in_fd = fopen(filename, "rb"); + if (in_fd == NULL) { + fprintf(stderr, "failed to open bin extension file %s\n", + filename); + return 1; + } + + size = get_file_size(filename); + if (size <= 0) { + fprintf(stderr, "bin extension file size is bad\n"); + return 1; + } + + /* Align extension size to 8 bytes */ + aligned_size = (size + 7) & (~7); + pad_bytes = aligned_size - size; + + header.type = EXT_TYPE_BINARY; + header.offset = 0; + header.size = aligned_size; + header.reserved = 0; + + /* Write header */ + written = fwrite(&header, sizeof(ext_header_t), 1, out_fd); + if (written != 1) { + fprintf(stderr, "failed writing header to extension file\n"); + return 1; + } + + /* Write image */ + while (size--) { + c = getc(in_fd); + fputc(c, out_fd); + } + + while (pad_bytes--) + fputc(0, out_fd); + + fclose(in_fd); + + return 0; +} + +/* **************************************** + * + * Write all extensions (binary, secure + * extensions) to file + * + * ****************************************/ + +int format_extensions(char *ext_filename) +{ + FILE *out_fd; + int ret = 0; + + out_fd = fopen(ext_filename, "wb"); + if (out_fd == NULL) { + fprintf(stderr, "failed to open extension output file %s", + ext_filename); + return 1; + } + + if (strncmp(opts.bin_ext_file, "NA", MAX_FILENAME)) { + if (format_bin_ext(opts.bin_ext_file, out_fd)) { + ret = 1; + goto error; + } + } +#ifdef CONFIG_MVEBU_SECURE_BOOT + if (strncmp(opts.sec_cfg_file, "NA", MAX_FILENAME)) { + if (format_sec_ext(opts.sec_cfg_file, out_fd)) { + ret = 1; + goto error; + } + } +#endif + +error: + fflush(out_fd); + fclose(out_fd); + return ret; +} + +void update_uart(header_t *header) +{ + header->uart_cfg = 0; + header->baudrate = 0; + + if (opts.disable_print) + uart_set_mode(header->uart_cfg, UART_MODE_DISABLE); + + if (opts.baudrate) + header->baudrate = (opts.baudrate / 1200); +} + +/* **************************************** + * + * Write the image prolog, i.e. + * main header and extensions, to file + * + * ****************************************/ + +int write_prolog(int ext_cnt, char *ext_filename, + uint8_t *image_buf, int image_size, FILE *out_fd) +{ + header_t *header; + int main_hdr_size = sizeof(header_t); + int prolog_size = main_hdr_size; + FILE *ext_fd; + char *buf; + int written, read; + int ret = 1; + + + if (ext_cnt) + prolog_size += get_file_size(ext_filename); + + prolog_size = ((prolog_size + PROLOG_ALIGNMENT) & + (~(PROLOG_ALIGNMENT-1))); + + /* Allocate a zeroed buffer to zero the padding bytes */ + buf = calloc(prolog_size, 1); + if (buf == NULL) { + fprintf(stderr, "Error: failed allocating checksum buffer\n"); + return 1; + } + + header = (header_t *)buf; + header->magic = MAIN_HDR_MAGIC; + header->prolog_size = prolog_size; + header->load_addr = opts.load_addr; + header->exec_addr = opts.exec_addr; + header->io_arg_0 = opts.nfc_io_args; + header->ext_count = ext_cnt; + header->aux_flags = 0; + header->boot_image_size = (image_size + 3) & (~0x3); + header->boot_image_checksum = checksum32((uint32_t *)image_buf, + image_size); + + update_uart(header); + + /* Populate buffer with main header and extensions */ + if (ext_cnt) { + ext_fd = fopen(ext_filename, "rb"); + if (ext_fd == NULL) { + fprintf(stderr, + "Error: failed to open extensions file\n"); + goto error; + } + + read = fread(&buf[main_hdr_size], + get_file_size(ext_filename), 1, ext_fd); + if (read != 1) { + fprintf(stderr, + "Error: failed to open extensions file\n"); + goto error; + } + +#ifdef CONFIG_MVEBU_SECURE_BOOT + /* Secure boot mode? */ + if (opts.sec_opts != 0) { + ret = finalize_secure_ext(header, (uint8_t *)buf, + prolog_size, image_buf, + image_size); + if (ret != 0) { + fprintf(stderr, "Error: failed to handle "); + fprintf(stderr, "secure extension!\n"); + goto error; + } + } /* secure boot mode */ +#endif + } + + /* Update the total prolog checksum */ + header->prolog_checksum = checksum32((uint32_t *)buf, prolog_size); + + /* Now spill everything to output file */ + written = fwrite(buf, prolog_size, 1, out_fd); + if (written != 1) { + fprintf(stderr, + "Error: failed to write prolog to output file\n"); + goto error; + } + + ret = 0; + +error: + free(buf); + return ret; +} + +int write_boot_image(uint8_t *buf, uint32_t image_size, FILE *out_fd) +{ + int aligned_size; + int written; + + /* Image size must be aligned to 4 bytes */ + aligned_size = (image_size + 3) & (~0x3); + + written = fwrite(buf, aligned_size, 1, out_fd); + if (written != 1) { + fprintf(stderr, "Error: Failed to write boot image\n"); + goto error; + } + + return 0; +error: + return 1; +} + +int main(int argc, char *argv[]) +{ + char in_file[MAX_FILENAME+1] = { 0 }; + char out_file[MAX_FILENAME+1] = { 0 }; + char ext_file[MAX_FILENAME+1] = { 0 }; + FILE *in_fd = NULL; + FILE *out_fd = NULL; + int parse = 0; + int ext_cnt = 0; + int opt; + int ret = 0; + int image_size; + uint8_t *image_buf = NULL; + int read; + size_t len; + uint32_t nand_block_size_kb, mlc_nand; + + /* Create temporary file for building extensions + * Use process ID for allowing multiple parallel runs + */ + snprintf(ext_file, MAX_FILENAME, "/tmp/ext_file-%x", getpid()); + + while ((opt = getopt(argc, argv, "hpms:i:l:e:a:b:u:n:t:c:k:")) != -1) { + switch (opt) { + case 'h': + usage(); + break; + case 'l': + opts.load_addr = strtoul(optarg, NULL, 0); + break; + case 'e': + opts.exec_addr = strtoul(optarg, NULL, 0); + break; + case 'm': + opts.disable_print = 1; + break; + case 'u': + opts.baudrate = strtoul(optarg, NULL, 0); + break; + case 'b': + strncpy(opts.bin_ext_file, optarg, MAX_FILENAME); + ext_cnt++; + break; + case 'p': + parse = 1; + break; + case 'n': + nand_block_size_kb = strtoul(optarg, NULL, 0); + opts.nfc_io_args |= (nand_block_size_kb / 64); + break; + case 't': + mlc_nand = 0; + if (!strncmp("MLC", optarg, 3)) + mlc_nand = 1; + opts.nfc_io_args |= (mlc_nand << 8); + break; +#ifdef CONFIG_MVEBU_SECURE_BOOT + case 'c': /* SEC extension */ + strncpy(opts.sec_cfg_file, optarg, MAX_FILENAME); + ext_cnt++; + break; + case 'k': + opts.key_index = strtoul(optarg, NULL, 0); + break; +#endif + default: /* '?' */ + usage_err("Unknown argument"); + exit(EXIT_FAILURE); + } + } + + /* Check validity of inputes */ + if (opts.load_addr % 8) + usage_err("Load address must be 8 bytes aligned"); + + if (opts.baudrate % 1200) + usage_err("Baudrate must be a multiple of 1200"); + + /* The remaining arguments are the input + * and potentially output file + */ + /* Input file must exist so exit if not */ + if (optind >= argc) + usage_err("missing input file name"); + + len = strlen(argv[optind]); + if (len > MAX_FILENAME) + usage_err("file name too long"); + memcpy(in_file, argv[optind], len); + optind++; + + /* Output file must exist in non parse mode */ + if (optind < argc) { + len = strlen(argv[optind]); + if (len > MAX_FILENAME) + usage_err("file name too long"); + memcpy(out_file, argv[optind], len); + } else if (!parse) + usage_err("missing output file name"); + + /* open the input file */ + in_fd = fopen(in_file, "rb"); + if (in_fd == NULL) { + printf("Error: Failed to open input file %s\n", in_file); + goto main_exit; + } + + /* Read the input file to buffer */ + image_size = get_file_size(in_file); + image_buf = calloc((image_size + AES_BLOCK_SZ - 1) & + ~(AES_BLOCK_SZ - 1), 1); + if (image_buf == NULL) { + fprintf(stderr, "Error: failed allocating input buffer\n"); + return 1; + } + + read = fread(image_buf, image_size, 1, in_fd); + if (read != 1) { + fprintf(stderr, "Error: failed to read input file\n"); + goto main_exit; + } + + /* Parse the input image and leave */ + if (parse) { + if (opts.key_index >= CSK_ARR_SZ) { + fprintf(stderr, + "Wrong key IDX value. Valid values 0 - %d\n", + CSK_ARR_SZ - 1); + goto main_exit; + } + ret = parse_image(image_buf, image_size); + goto main_exit; + } + + /* Create a blob file from all extensions */ + if (ext_cnt) { + ret = format_extensions(ext_file); + if (ret) + goto main_exit; + } + + out_fd = fopen(out_file, "wb"); + if (out_fd == NULL) { + fprintf(stderr, + "Error: Failed to open output file %s\n", out_file); + goto main_exit; + } + + ret = write_prolog(ext_cnt, ext_file, image_buf, image_size, out_fd); + if (ret) + goto main_exit; + +#ifdef CONFIG_MVEBU_SECURE_BOOT + if (opts.sec_opts && (opts.sec_opts->encrypted_image != 0) && + (opts.sec_opts->enc_image_sz != 0)) { + ret = write_boot_image(opts.sec_opts->encrypted_image, + opts.sec_opts->enc_image_sz, out_fd); + } else +#endif + ret = write_boot_image(image_buf, image_size, out_fd); + if (ret) + goto main_exit; + +main_exit: + if (in_fd) + fclose(in_fd); + + if (out_fd) + fclose(out_fd); + + if (image_buf) + free(image_buf); + + unlink(ext_file); + +#ifdef CONFIG_MVEBU_SECURE_BOOT + if (opts.sec_opts) { + if (opts.sec_opts->encrypted_image) + free(opts.sec_opts->encrypted_image); + free(opts.sec_opts); + } +#endif + exit(ret); +} diff --git a/tools/marvell/doimage/doimage.mk b/tools/marvell/doimage/doimage.mk new file mode 100644 index 0000000..2b751d4 --- /dev/null +++ b/tools/marvell/doimage/doimage.mk @@ -0,0 +1,15 @@ +# +# Copyright (C) 2018 Marvell International Ltd. +# +# SPDX-License-Identifier: BSD-3-Clause +# https://spdx.org/licenses + +DOIMAGE_FLAGS ?= -l 0x4100000 -e 0x4100000 + + +#NAND params +#Open and update the below when using NAND as a boot device. + +CONFIG_MVEBU_NAND_BLOCK_SIZE := 256 +CONFIG_MVEBU_NAND_CELL_TYPE := SLC +NAND_DOIMAGE_FLAGS := -t $(CONFIG_MVEBU_NAND_CELL_TYPE) -n $(CONFIG_MVEBU_NAND_BLOCK_SIZE) diff --git a/tools/marvell/doimage/secure/aes_key.txt b/tools/marvell/doimage/secure/aes_key.txt new file mode 100644 index 0000000..3e8a888 --- /dev/null +++ b/tools/marvell/doimage/secure/aes_key.txt @@ -0,0 +1 @@ +ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890 diff --git a/tools/marvell/doimage/secure/csk_priv_pem0.key b/tools/marvell/doimage/secure/csk_priv_pem0.key new file mode 100644 index 0000000..0840c2a --- /dev/null +++ b/tools/marvell/doimage/secure/csk_priv_pem0.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAm6jN6o2zQmtyUlvfkfDbSjPJ7Vlpp/KgK/eznoVBBsDIZakX +cIgf8TSLpNVkc+ZE0f/n8X7mEZIyjuSBObLOm9vbkoZcR7DlKUL7RNNOUCv55Ozl +hQwrzpH/uIyIJTvmek29G5wroi0wGbPoxzhelIRTjVCibleBWhYCmZQ6SIRmTY8L +JT8VkX8I/Mhu62DjvxF3BnV6pXuh/FdgDN7MbldzM8Y+GOxVGi5Kcm5WHY7eyMxl +4Y0Yko31Xv7T1PcXahVBIciT+11w+fLc4wQuCJ6GUf9JbzQ0ZllY/FdRG0AhuRMH +zN0jAc/sKrIFoAErED6qlcoQg0vl7gmWN5x+2wIDAQABAoIBACtnPFOkw1FH6I6y +c3qcMGlWW33FKsLb0nGwFfOjsGgTpU1Dgver3UxCnJWPsvzmPlZYBvK9saVAoLxb +VvUhuJ6ZBXar5FtRJfUFak7cpL+SI5IDxFP++tAUwbtR5DyNoUyFFK/4Mep8sybX +lZbHTwgWhb2nuEMQP09BR+RPAplpcitkIoPkhmbGfbt9Hsd25I3bb5Z9R4S/2Rcf +7tmaxndQamij7/pUI7xtd8L6cMESJGIWrgEt/MaT2z8nNPE3EDctDSlH9yKqA2O7 +/LTfrxNDnw5gGRtOgahloThKljVM6pQa4mi91FufD67pHwnKn8urNbt8/3AWg6uU +x4FzZdECgYEA0k2UYzBM+dU6T1bZZ176YI0cZrP1tbf/JwnZGHicQYS7lPLAqgfO +u5oRQzuDimOXaV4xCPBO2nadd6aBxbZTXaglR7GG2uCHX6w2DnOr8/d66YTErTVV +u7/Bf8gMKT9mM4rWPrOEXfXfF0fvcpkBQ+QDynIB37tx/mj2lXRkLx0CgYEAvXuX +Dbe2QgSK0ajrcH7YJyx3RVx9RonOqL4yjCVCELmaDQd307Ef3j+gkd59XIewm+HA +mPyeWEUd8EzH+UvjckfKFuF2I4lEUUWtVZTa7me7mvsFqeEOu5KusD4+Hs+B9Kqd +3Evqcpj2lcMBI519Hvr9BTKfDBcH1EUos6A9rFcCgYAxsyPeTQvj/wBIv72hMFD7 +gF2159GpoFIsZ6dmoRpMYZHzIWtmw3GX5FEwEmCD1AV0YU41TpVUC7QrEq6Yiv4o +pBQrXUkBcQ6NDaW4xJ1eip4Bkd7pEDGyrR6NlDlLhjAg/i6joskla3XNirKL4pzp +7nj23vqSZToLZcLgjyEeAQKBgD5EvDo80j9VwMzvpxecB6qv+S4pG94vcWOQxYm6 +wMBATjjT6HP/9EoUPM9S/32F9er0QFfGRL8bT6Blix4I62Dl6KqmQy2gcXwH2tOS +DHRmUIe40H6oQDAyHwg6HC4B4WInI6N+qzgnvnku0VQD8FdbAgVQQmY1t1PxulN1 +aG8XAoGAPWAr4i8KkVAx4wLlMF8E/ecKcsX1J0+UuKket7Dvk7xJfwtkSLPeV8Bp +HuoHXMM3KYoZ93Hlto5rAT1VQhYuj7heU10v+9UtYTFHgaitptYmxovoCKKiZICl +48aPUI377e5jQ6RhhGYy8ltKsJ80K1T9DIkThJPSS+9NAI+jrmg= +-----END RSA PRIVATE KEY----- diff --git a/tools/marvell/doimage/secure/csk_priv_pem1.key b/tools/marvell/doimage/secure/csk_priv_pem1.key new file mode 100644 index 0000000..91d1aeb --- /dev/null +++ b/tools/marvell/doimage/secure/csk_priv_pem1.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAgwHXB0AaIhT15Z9lHpQ2YT1W8i4oMvvRiLGQCrba5l7BJ03E +ct0x3zagNKZEnpNndT4EAy98ihkhwVlUhxZCparJ2L3JsTs5RgV0wyQkQzwMLM8g +QI5EMmJCgFAVRHmVICOsisGGfNVUHjGdGwPOipyQCsX2MAm3E139VpB7NYj+Q4IR +4kvcb+59LZxKuRJTFKRDIqMGJu98P/ga70+YLXPCBPKSfnZnUppuaI86jF1E6xt8 +o7YtfEPCHDd2LXxKPZ670OapVqwo0t7ZSzEG63NkLp56FXc1OpfC69C8VPiZ8JqW +wxvS/vL8MMCxsBnjSuqnmOAbcNR2GFtUwJOGwwIDAQABAoIBAFcfoiDwQHDp/531 +ownzBzcj0+67Q4Ckd3SwoVp+wJTz7wB0d3DsKX6IlYJuELRk0yjlVUXJDsnIbOpo +vg4Yf7otGo9JqBh1imFGv6AHKRaNmIs0M/66nh/juNYcbAhd0w7MqrKcgRQDyy1J +UXHl1jXYaPLBNDg+PcJjf1dSPp4axzmW2Pk2rXnJCsPcZXL/0YmEvqhfOze0GdjR +hOkbbr6MPPVM66tA00xSwg9XEYJvHtwH6oB0rnANM8ieNK1mtcWkTU5di17CCrjS +ohIhXQrdVpxt549EJoUqEFSgo8OOMm2npDbFrjlukb5euakvMacwoT1te79blSKf +hrTvjgECgYEA0VqoFL0Vqe1qleikYDJ7S5xcv1oruEV31TeuBhDuf0c4PADCnBrV +/RnCEYuXs6wCk60chHg5s0jxg+nGbiY6jRTHkJLRU3ZhDtrtfidEZ78GRzFF3shl +Uzt7dHkKK1ZdiMH4sWzyRLom91TKWMrNKC1AD7v4/zjEXy6phall3ZcCgYEAoDJa +0dIKvVCS6dM2E2kMqi/45mJqsJzFvYL1s4mbma/BAC47bBju/YEse90x+iIi3Gg/ +NoXmNfGPrtgdl+/J/Y6Pohxf/e7gGN71tYVETzgc2Jv09wqmzmTjCmo3wyepyWf+ +pIAE39kdhwnqXVw5xwOG1N3xrQ9TomOO+1QiXbUCgYAF84TJqiJehUA9aLKbhXPZ +z2UXj3GkuFzSs9V/mKWe+qBPnFnr5BtnKX9JzmUOl3ovRoGEBoLlZNJwxIl+ghmx +/wA5TOMkcz4JFRIhPu6D4HtGNNFepuWyewNkaThvyPG5vIHcUVOFvqDy8PcblRBF +7xteFyLZ5nw2lHX/NbSOmwKBgFxLZqPIPcPArkPlGhyow1Ex/lbNkOZcDFkZIHHl +8C3lYm62NCodW2PWjkh2shqInEkcDn9dObsOh1eWz8X/swJQplQhwPROMfJiUnHY +a/iwPX5WrBXAn0X+Pgh8FdBsA5g0QDOKRkSplCd/APX08pzEXWQ60siAMhE3BuOq +H3qZAoGAVnzFidlXuyn+fbNaNVepK9hbuoxHHbzYYWSkpi+73EchN8kXktC+AdEf +owr9TPILbwWWJyisa3wW4xdbMifCgVLTedWZpZ09BENVqC+7g7ksX0pNMGYuFLOh +Td7mFAgmclxG5UiKexajOLjjdnAsJyrDaNKhHn8NQNN6L93N0sE= +-----END RSA PRIVATE KEY----- diff --git a/tools/marvell/doimage/secure/csk_priv_pem2.key b/tools/marvell/doimage/secure/csk_priv_pem2.key new file mode 100644 index 0000000..ea47ac5 --- /dev/null +++ b/tools/marvell/doimage/secure/csk_priv_pem2.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAjxTSTh57/5njUpE200+Qb3ySAn8lKeufgaa0K2Xc6Ri7lDZR +ZJ2BPuQZV4lYGqgWUf0IOzNf2WnE2lPfVnLMx08h7NhBqJ83yJVajpr+itnOmW+r +M7h76TFyuna1xz2kw1uhgI5Y4FRnJ4Cg4AexCSyViXSzEN/7LQwxa5z5WGDiNX5N +3/tgjGu+dzSMOiIQhXwIcK/XaiQNm3WHqqnAhPb5Q9IBuuqBfpZoFfH4XmbFWrC8 +neSMMMxX5Ti9pKhLd1EsiaP0aUNQlF8gNWuC/tNaf+OCtwVelVa3sGSRjRFe06VQ +sAE9oyXKri11yD5Dwp1xXivbpOrf7xjUe5gILwIDAQABAoIBABTr94CCxqDucKYP +I9QsSzNyJKuGyfliQdWkea3q3C2ddzhJ5QbwXQjEM8xwAdkMAQ+GD2EQtxBEfgtq +vjqW2MjAEnbefGNavL5w0GgP0+6bwLEA+ii67iuAFoWbfCMhKWmDiY8RwX8z+E13 +ao63sTRlN4x86v4pskG5CbTxpCg+8m7KklLns4SwRGf5gGQcgKRtNSR5nE4g2UNl +dghbDdNlvUncm4zxUcTh0kquhF5Tef5w+6L7W8Hv9Pky3b1c2OK1BMhJlxYrtt69 +/zhIJs89CLx5ACfam+DT/xs0uUiuRQq/e1CCQLCnUO02JqpeN/schtDCd0ZWhbtB +nT7fwTECgYEAx+COhys+7AZI0U+PeuTkI86GUsWHoBislXThxbxyGvMFjgyADZD+ +q/XEGAcxd4eTA1fr0Q9cLuuHZubjGQ7+OIXMZ6arXUsrmMrjRu3kHO+y6K6r4s8j +5bxN/iQ0bymUtJRfJSLI172plszusiPWhCL5+yhYlNoh4mNZJuJnzXkCgYEAt0Gz +07P19YPsxk5ow7ZnSNOMOkkEPP0SuHHWekMIK9KMjiRUSygOAk07zTL7MUoFn9Gy +Prfi0ybFArNhIa4Xio3Fbjfig7rGgaApK4Y3d9A/CGPv/Nj7C2OTepqlEzRLmU9e +Xw5yhbccCydXLyAYFAET2XHsmbewpvHyeYUSoOcCgYBRMJEUrOdhPmhDxZqVo/Zb +6R887gnaaUtpZlHzXUnIUqEWA1PcruIT/b/KttlMIWEBQayDfkbGtFuK3AyxeBqh +4Q+XpucC/W7XIMrTW/yGGIPG6nTdq6B8SFIyAojeArjp5T8Eua11nRAPNm1bJR2V +DRQYBlp9FGIhMJPdLKhXmQKBgGeywSyR0COfBHPu2K+u3uFB/D7bJI/ScS54FHLY +zZ3mpeylOCHTR6IbzDRAng31Ihue0KtW6P6tGJx/nv4tAltAADFvZDlAjqW5WLKt +X2PoLlL0IlBFBEIclc6yBalJVWIqnG9TwJBT3oWdPGOJWLaxKWdJZSZS4J6HmLsV +B0aPAoGAduLsOt8C5z48jPqmJxyPwsmT0Q424FccPMcvGOJ13yxq3xNsfAsbmg9l +L2i/ktE0wCMA+Pm7cuFgxwD7xTr67POZgt9022KsOSonjPsIn24UQeP46vAX/Qtx +Qf3sfvzf57vNy2Hybe38T8RsVOZla+v/QctfSfmb8Y95XL/SZzA= +-----END RSA PRIVATE KEY----- diff --git a/tools/marvell/doimage/secure/csk_priv_pem3.key b/tools/marvell/doimage/secure/csk_priv_pem3.key new file mode 100644 index 0000000..e40a864 --- /dev/null +++ b/tools/marvell/doimage/secure/csk_priv_pem3.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAlA/T/5IMTPTu+k5PeesB2oeP80Y6nq0ls8vXLul0TVEJoJ+O +InbPYNqYPu4dbQQg/u8qp8BeXm2ujtJbBTcdn0jKIiDTKYEnlsGfUt9GHnuuzvFh +rORSKuAolUqvo/zcSCo1uykaFvSuyTovSPlwllzSixD9XBbHfn3kXneiIUa45vsJ +AyjTn2qCJt0WgvX42NTxH6Q/OWLeOuKTyRHf25eabucIv77KYy0mlEPq5jjiV5AJ +gl5F1h5G8n07JCIWjkZ2QV4wr+Hv9uGNaSb0WGppBp4CbdQa0eUI75cKzz4WXqds +HZaYiX/a8YC+EUfvqDD02vKREIKFL/1zL53P/wIDAQABAoIBAGzBj5w7oBNrGpr7 +qL9KEyt8xg0Q+gAR+Q6vXRlVXBtquiKk8Jd6I+vlxUz8RNsN3FrGPNPJpse/0yeP +dlJHYNfedLNK3zCucPD4uln6LRw5B3d0sKV5dK2Px9+ZY5iWJQxRDPS0RTi1dCnV +NmRo7P1Vo0WJLkFVbiYIvRVy1MGRfF9ejN41G6U4MoBAQ9WqLp+JasUMTspZI49a +z8tOiJPT94MHBwbKnz8Mcq8sy02LR7U5h82+0T7JoRVix/OXiOoiQExNjZ9yGar0 +wBnl0SL1UW5UUaYzbyNH0mlMXLD+qowbDZM2pBWPfqXK+CMOsL6STIwnns7lY+ZJ +ILbaVmECgYEA2kQXE1PZ25A87a81wCEld402WJ2KegrZC719EWv+xeoS72Ji8uv7 +V0PxVGJQOcG1N+dzJ5tN59SQ/NvVTrjwqNUxQqsygmWq/TcfGb9ONZRmyzcehYLb +m4xTjqJKQ6Kwm5SoaCYmzEb/xaeLwLS9HmR9MdB1dxtDOLpjaK/8qPECgYEArait +QhgaknlxG8pcAimPsEUrLHYWSFRE/MUk4+YvZg/5+YJ8csvY0SO2h0tF/ARwUrdI +DaLEifHm4vqgN03K/0gqj7TKxcNlV16PvVx7Vz97xejdqdHZLDfAo4lcotsgvFQW +zIqoQGGPLf6WhFixZ8mEYj8xnmzLGPvHQmf1h+8CgYEA0LDl917nIN4qw4ARPqDy +t/pXCienrcUNfgIxwSSnNwj2DdjejzI+4VNfPbW6y16BLPCp1CbUOGOwNXTj4R9H +S8Z8ESirZK5c7Tt1CyM1XlmEZ61OC43w+CsWAXz+0OiPQFLFKr+/vPXtvEjUgO7P +HG4sniKZDccNYQIl5oTOaaECgYAPU4u3AZmWw9EPutRT/IcJ75DX47Qjvgw4os2W +r4IPZ+mP88w39XW1P4mkdyg+DcY8BqD9Uxg1dHwEHEp3lw4LabsX48Thn1UaWOYm +uDrKgHfUB7FIg5S/Kkx+ImliliRVerZoZvRiejnAvW9bTtiZaFeetCUU7lUeZ1o2 +qiYpUQKBgHQDfdDhguBGPKpkJ7pVwHkJA/lyRWaN1hwplw4TvX2oH14NsHg5Q5Fd +lHqHFs2Ry/6X3bKgF0E6q4cx0V1Xnnj9sGsemlrHdiSxplDYRQql7X5OeYPGF/Bg +ZTTG8rDwy+ey6EP9BZUb03hISx/LyMynOzjGl6uOcdAcy2d9Vno0 +-----END RSA PRIVATE KEY----- diff --git a/tools/marvell/doimage/secure/kak_priv_pem.key b/tools/marvell/doimage/secure/kak_priv_pem.key new file mode 100644 index 0000000..dfceaba --- /dev/null +++ b/tools/marvell/doimage/secure/kak_priv_pem.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAsj2cHcrE2pdyCqNr+oVcQULiRx6RivkrhLl2DTqWXpP33BPm +MP0W0X0z98X7E3kZO+JIGRZ8q+6AWmUpL+53aOGItNeUgT7jQKViPJIo9ZcEnv/n +PJqdgDd4xFhnwYMgq8uVYN9IPfaKDwB3EoOqjNox2JholUVxvLw6W8DAC8La3zwb +0hiqtIlirQOQ/KaTHxC6dPYkrai+jSK5uAX7Vt8RKYg5qfDxSdZckmC2xVKYURhV +bZAlyKki4h6f8CwYCJMQDpHL6mVYCuJ1Ju/OJEXvthDKD0CD2hwILhksdey3qMOC +I5lHSO1b+sTvnVHGs65wI7A+ZYwnadMNvS9e2QIDAQABAoIBAH2uu9q2FEEe8SdX +PNiWGQtbojsL7wzTzj/0lq2VVlqyc+AXmAWLMP/fDTn1vKlqhsSXNseZ96c0sgUL +uBM4T7MA9WivauQH+C6pb6/OUFt8daG4SNGPJOg4NUweGmt1jyAUmeyJBWPL6GXT +qiK//Q78/JECRxyaryyqfWwdak3flzfwONBJ03tQ9EO+L7hf9gAP7OYnAsuNp+Bz +tj1xzNMumYYYiHvsEXx8UTe8HGrmYuO53ZY5fBLGB6Jj7hRlAHNfcdVDvvoBU5cI +Zwi+5YsBuSP2Hr9Gt2Odu+KitH3gFdS0HIiDh44AT+Trj29NMANFDfkDbVHUmE0q +YBL75NECgYEA2E+fJzdaYyyPIcvQgVM8g52hltR5IRgJICND3NOdB/Zb2teBGZh+ +1XJ6ZqQMDcOQZo0CMbX9UNRnf3NU55k48/EEITxCgUJTx/WdfJeTVlWGspt5+U/r +hDnQmkePdU1en63+u9eqsla9+VhLwU3fl/pIOpsBAnoEzs3hMQZ1G0cCgYEA0vHH +ilm3AztIoZlH3wgDAl2Gu5/YopqEofKA8G4Jp89rlkk919P/GNjEc6575wjgztDB +0Xab+H7Nqxjs3HqQX/DTTuAxzAggBg3j/ijpHnmjrCHLeMT5ciyH+EH5Bg///cLq ++Cwn7aOWuSK1hGdDYxUycHylAYZXXFJzmEIEhN8CgYEA1qTrwPZkctTckyS0GiCG +g/P/TLQ6HmTDaWiVBqPVxvjn3RjLuqJf+V5Hp2JRs7bDq39xFfMJExQyP34qWkbp +BOe8uV4agDlY+ar4Q5IFWj40EzfEqWhsxCC6pt0rtbK4mqsFg1BWyfDZQnwjcAXe +QejRk5YMQnDiJHSXaRaHTjECgYAv6ecvD624ODEJM63VhRZZ5TCDUY19caeKuXB8 +LCJZUY3Ydw5rBaY92I7Wz90o3yVhFJ3RnCVVTkgdAu5aLiS5BhSZJ+dntri/Z0xQ +IK7C01JP+OUkq2kVe/Pued28eMnms+13LWBsY+oKZ03foyz1Ro1Ma6N3MzKIr9m9 +zdEE9QKBgECfoh0xE2T/cbJrtH0mwMCUM6eMVGq+yQBKNvuuPg6kaQUsah1n1rp6 +OyvjwRAXdhshszEzNTX1WTT6/i+vZX277Ax50pPo9UhQ9kVteVt1frN6+u5sy07V +fg1f2+m0iFx4BD/irU0fzSyfGE+QkBnmXFBUNSYjp2PSqYIdufmW +-----END RSA PRIVATE KEY----- diff --git a/tools/marvell/doimage/secure/sec_img_7K.cfg b/tools/marvell/doimage/secure/sec_img_7K.cfg new file mode 100644 index 0000000..459f731 --- /dev/null +++ b/tools/marvell/doimage/secure/sec_img_7K.cfg @@ -0,0 +1,29 @@ +# Trusted boot image extension definitions + +kak_key_file = "tools/doimage/secure/kak_priv_pem.key"; + +# CSK keys array - 16 entries total. +# Only a key with csk_key_index will be used for signing the image +# use "*" string instead of file name for specifying an empty key +csk_key_file = ["tools/doimage/secure/csk_priv_pem0.key", + "tools/doimage/secure/csk_priv_pem1.key", + "tools/doimage/secure/csk_priv_pem2.key", + "tools/doimage/secure/csk_priv_pem3.key", + "*", "*", "*", "*", "*", "*", "*", "*", "*", "*", "*", "*"]; + +# index of CSK key in the array. Valid range is 0 to 15 +csk_key_index = 3; + +# AES-256 symmetric key for image encryption +aes_key_file = "tools/doimage/secure/aes_key.txt"; + +efuse_disable = false; +jtag = { enable = true; delay = 20; }; + +box_id = 0xdeadbeef; +flash_id = 0xbaddf00d; + +# SecureBootControl and EfuseBurnControl registers array +# Two register addresses for each connected CP +# A7K - one CP, two register values +control = [0xF2441920, 0xF2441940]; diff --git a/tools/marvell/doimage/secure/sec_img_8K.cfg b/tools/marvell/doimage/secure/sec_img_8K.cfg new file mode 100644 index 0000000..a849dff --- /dev/null +++ b/tools/marvell/doimage/secure/sec_img_8K.cfg @@ -0,0 +1,29 @@ +# Trusted boot image extension definitions + +kak_key_file = "tools/doimage/secure/kak_priv_pem.key"; + +# CSK keys array - 16 entries total. +# Only a key with csk_key_index will be used for signing the image +# use "*" string instead of file name for specifying an empty key +csk_key_file = ["tools/doimage/secure/csk_priv_pem0.key", + "tools/doimage/secure/csk_priv_pem1.key", + "tools/doimage/secure/csk_priv_pem2.key", + "tools/doimage/secure/csk_priv_pem3.key", + "*", "*", "*", "*", "*", "*", "*", "*", "*", "*", "*", "*"]; + +# index of CSK key in the array. Valid range is 0 to 15 +csk_key_index = 3; + +# AES-256 symmetric key for image encryption +aes_key_file = "tools/doimage/secure/aes_key.txt"; + +efuse_disable = false; +jtag = { enable = true; delay = 20; }; + +box_id = 0xdeadbeef; +flash_id = 0xbaddf00d; + +# SecureBootControl and EfuseBurnControl registers array +# Two register addresses for each connected CP +# A8K - two CP, four register values +control = [0xF2441920, 0xF2441940, 0xF4441920, 0xF4441940];