xref: /rk3399_ARM-atf/tools/marvell/doimage/doimage.c (revision 0c9b38b61b023b6a040f717d1c23420ccbf0e71c)
16414dc6dSKonstantin Porotchkin /*
26414dc6dSKonstantin Porotchkin  * Copyright (C) 2018 Marvell International Ltd.
36414dc6dSKonstantin Porotchkin  *
46414dc6dSKonstantin Porotchkin  * SPDX-License-Identifier:     BSD-3-Clause
56414dc6dSKonstantin Porotchkin  * https://spdx.org/licenses
66414dc6dSKonstantin Porotchkin  */
76414dc6dSKonstantin Porotchkin 
86414dc6dSKonstantin Porotchkin #include <stdlib.h>
96414dc6dSKonstantin Porotchkin #include <stdio.h>
106414dc6dSKonstantin Porotchkin #include <stdint.h>
116414dc6dSKonstantin Porotchkin #include <stddef.h>
126414dc6dSKonstantin Porotchkin #include <string.h>
136414dc6dSKonstantin Porotchkin #include <unistd.h>
146414dc6dSKonstantin Porotchkin #include <sys/stat.h>
156414dc6dSKonstantin Porotchkin #include <sys/time.h>
166414dc6dSKonstantin Porotchkin 
176414dc6dSKonstantin Porotchkin #ifdef CONFIG_MVEBU_SECURE_BOOT
186414dc6dSKonstantin Porotchkin #include <libconfig.h>	/* for parsing config file */
196414dc6dSKonstantin Porotchkin 
206414dc6dSKonstantin Porotchkin /* mbedTLS stuff */
218eb4efe7SHenrik Nordstrom #include <mbedtls/version.h>
226414dc6dSKonstantin Porotchkin #if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ENTROPY_C) && \
236414dc6dSKonstantin Porotchkin 	defined(MBEDTLS_SHA256_C) && \
246414dc6dSKonstantin Porotchkin 	defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_FS_IO) && \
256414dc6dSKonstantin Porotchkin 	defined(MBEDTLS_CTR_DRBG_C)
266414dc6dSKonstantin Porotchkin #include <mbedtls/error.h>
276414dc6dSKonstantin Porotchkin #include <mbedtls/entropy.h>
286414dc6dSKonstantin Porotchkin #include <mbedtls/ctr_drbg.h>
296414dc6dSKonstantin Porotchkin #include <mbedtls/md.h>
306414dc6dSKonstantin Porotchkin #include <mbedtls/pk.h>
316414dc6dSKonstantin Porotchkin #include <mbedtls/sha256.h>
326414dc6dSKonstantin Porotchkin #include <mbedtls/x509.h>
336414dc6dSKonstantin Porotchkin #else
346414dc6dSKonstantin Porotchkin #error "Bad mbedTLS configuration!"
356414dc6dSKonstantin Porotchkin #endif
366414dc6dSKonstantin Porotchkin #endif /* CONFIG_MVEBU_SECURE_BOOT */
376414dc6dSKonstantin Porotchkin 
386414dc6dSKonstantin Porotchkin #define MAX_FILENAME		256
396414dc6dSKonstantin Porotchkin #define CSK_ARR_SZ		16
406414dc6dSKonstantin Porotchkin #define CSK_ARR_EMPTY_FILE	"*"
416414dc6dSKonstantin Porotchkin #define AES_KEY_BIT_LEN		256
426414dc6dSKonstantin Porotchkin #define AES_KEY_BYTE_LEN	(AES_KEY_BIT_LEN >> 3)
436414dc6dSKonstantin Porotchkin #define AES_BLOCK_SZ		16
446414dc6dSKonstantin Porotchkin #define RSA_SIGN_BYTE_LEN	256
456414dc6dSKonstantin Porotchkin #define MAX_RSA_DER_BYTE_LEN	524
466414dc6dSKonstantin Porotchkin /* Number of address pairs in control array */
476414dc6dSKonstantin Porotchkin #define CP_CTRL_EL_ARRAY_SZ	32
486414dc6dSKonstantin Porotchkin 
49a79df348SKonstantin Porotchkin #define VERSION_STRING		"Marvell(C) doimage utility version 3.3"
506414dc6dSKonstantin Porotchkin 
516414dc6dSKonstantin Porotchkin /* A8K definitions */
526414dc6dSKonstantin Porotchkin 
536414dc6dSKonstantin Porotchkin /* Extension header types */
546414dc6dSKonstantin Porotchkin #define EXT_TYPE_SECURITY	0x1
556414dc6dSKonstantin Porotchkin #define EXT_TYPE_BINARY		0x2
566414dc6dSKonstantin Porotchkin 
576414dc6dSKonstantin Porotchkin #define MAIN_HDR_MAGIC		0xB105B002
586414dc6dSKonstantin Porotchkin 
596414dc6dSKonstantin Porotchkin /* PROLOG alignment considerations:
606414dc6dSKonstantin Porotchkin  *  128B: To allow supporting XMODEM protocol.
616414dc6dSKonstantin Porotchkin  *  8KB: To align the boot image to the largest NAND page size, and simplify
626414dc6dSKonstantin Porotchkin  *  the read operations from NAND.
636414dc6dSKonstantin Porotchkin  *  We choose the largest page size, in order to use a single image for all
646414dc6dSKonstantin Porotchkin  *  NAND page sizes.
656414dc6dSKonstantin Porotchkin  */
666414dc6dSKonstantin Porotchkin #define PROLOG_ALIGNMENT	(8 << 10)
676414dc6dSKonstantin Porotchkin 
686414dc6dSKonstantin Porotchkin /* UART argument bitfield */
696414dc6dSKonstantin Porotchkin #define UART_MODE_UNMODIFIED	0x0
706414dc6dSKonstantin Porotchkin #define UART_MODE_DISABLE	0x1
716414dc6dSKonstantin Porotchkin #define UART_MODE_UPDATE	0x2
726414dc6dSKonstantin Porotchkin 
736414dc6dSKonstantin Porotchkin typedef struct _main_header {
746414dc6dSKonstantin Porotchkin 	uint32_t	magic;			/*  0-3  */
756414dc6dSKonstantin Porotchkin 	uint32_t	prolog_size;		/*  4-7  */
766414dc6dSKonstantin Porotchkin 	uint32_t	prolog_checksum;	/*  8-11 */
776414dc6dSKonstantin Porotchkin 	uint32_t	boot_image_size;	/* 12-15 */
786414dc6dSKonstantin Porotchkin 	uint32_t	boot_image_checksum;	/* 16-19 */
796414dc6dSKonstantin Porotchkin 	uint32_t	rsrvd0;			/* 20-23 */
806414dc6dSKonstantin Porotchkin 	uint32_t	load_addr;		/* 24-27 */
816414dc6dSKonstantin Porotchkin 	uint32_t	exec_addr;		/* 28-31 */
826414dc6dSKonstantin Porotchkin 	uint8_t		uart_cfg;		/*  32   */
836414dc6dSKonstantin Porotchkin 	uint8_t		baudrate;		/*  33   */
846414dc6dSKonstantin Porotchkin 	uint8_t		ext_count;		/*  34   */
856414dc6dSKonstantin Porotchkin 	uint8_t		aux_flags;		/*  35   */
866414dc6dSKonstantin Porotchkin 	uint32_t	io_arg_0;		/* 36-39 */
876414dc6dSKonstantin Porotchkin 	uint32_t	io_arg_1;		/* 40-43 */
886414dc6dSKonstantin Porotchkin 	uint32_t	io_arg_2;		/* 43-47 */
896414dc6dSKonstantin Porotchkin 	uint32_t	io_arg_3;		/* 48-51 */
906414dc6dSKonstantin Porotchkin 	uint32_t	rsrvd1;			/* 52-55 */
916414dc6dSKonstantin Porotchkin 	uint32_t	rsrvd2;			/* 56-59 */
926414dc6dSKonstantin Porotchkin 	uint32_t	rsrvd3;			/* 60-63 */
936414dc6dSKonstantin Porotchkin } header_t;
946414dc6dSKonstantin Porotchkin 
956414dc6dSKonstantin Porotchkin typedef struct _ext_header {
966414dc6dSKonstantin Porotchkin 	uint8_t		type;
976414dc6dSKonstantin Porotchkin 	uint8_t		offset;
986414dc6dSKonstantin Porotchkin 	uint16_t	reserved;
996414dc6dSKonstantin Porotchkin 	uint32_t	size;
1006414dc6dSKonstantin Porotchkin } ext_header_t;
1016414dc6dSKonstantin Porotchkin 
1026414dc6dSKonstantin Porotchkin typedef struct _sec_entry {
1036414dc6dSKonstantin Porotchkin 	uint8_t		kak_key[MAX_RSA_DER_BYTE_LEN];
1046414dc6dSKonstantin Porotchkin 	uint32_t	jtag_delay;
1056414dc6dSKonstantin Porotchkin 	uint32_t	box_id;
1066414dc6dSKonstantin Porotchkin 	uint32_t	flash_id;
1076414dc6dSKonstantin Porotchkin 	uint32_t	jtag_en;
1086414dc6dSKonstantin Porotchkin 	uint32_t	encrypt_en;
1096414dc6dSKonstantin Porotchkin 	uint32_t	efuse_dis;
1106414dc6dSKonstantin Porotchkin 	uint8_t		header_sign[RSA_SIGN_BYTE_LEN];
1116414dc6dSKonstantin Porotchkin 	uint8_t		image_sign[RSA_SIGN_BYTE_LEN];
1126414dc6dSKonstantin Porotchkin 	uint8_t		csk_keys[CSK_ARR_SZ][MAX_RSA_DER_BYTE_LEN];
1136414dc6dSKonstantin Porotchkin 	uint8_t		csk_sign[RSA_SIGN_BYTE_LEN];
1146414dc6dSKonstantin Porotchkin 	uint32_t	cp_ctrl_arr[CP_CTRL_EL_ARRAY_SZ];
1156414dc6dSKonstantin Porotchkin 	uint32_t	cp_efuse_arr[CP_CTRL_EL_ARRAY_SZ];
1166414dc6dSKonstantin Porotchkin } sec_entry_t;
1176414dc6dSKonstantin Porotchkin 
1186414dc6dSKonstantin Porotchkin /* A8K definitions end */
1196414dc6dSKonstantin Porotchkin 
1206414dc6dSKonstantin Porotchkin /* UART argument bitfield */
1216414dc6dSKonstantin Porotchkin #define UART_MODE_UNMODIFIED	0x0
1226414dc6dSKonstantin Porotchkin #define UART_MODE_DISABLE	0x1
1236414dc6dSKonstantin Porotchkin #define UART_MODE_UPDATE	0x2
1246414dc6dSKonstantin Porotchkin 
1256414dc6dSKonstantin Porotchkin #define uart_set_mode(arg, mode)	(arg |= (mode & 0x3))
1266414dc6dSKonstantin Porotchkin 
1276414dc6dSKonstantin Porotchkin typedef struct _sec_options {
1286414dc6dSKonstantin Porotchkin #ifdef CONFIG_MVEBU_SECURE_BOOT
1296414dc6dSKonstantin Porotchkin 	char aes_key_file[MAX_FILENAME+1];
1306414dc6dSKonstantin Porotchkin 	char kak_key_file[MAX_FILENAME+1];
1316414dc6dSKonstantin Porotchkin 	char csk_key_file[CSK_ARR_SZ][MAX_FILENAME+1];
1326414dc6dSKonstantin Porotchkin 	uint32_t	box_id;
1336414dc6dSKonstantin Porotchkin 	uint32_t	flash_id;
1346414dc6dSKonstantin Porotchkin 	uint32_t	jtag_delay;
1356414dc6dSKonstantin Porotchkin 	uint8_t		csk_index;
1366414dc6dSKonstantin Porotchkin 	uint8_t		jtag_enable;
1376414dc6dSKonstantin Porotchkin 	uint8_t		efuse_disable;
1386414dc6dSKonstantin Porotchkin 	uint32_t	cp_ctrl_arr[CP_CTRL_EL_ARRAY_SZ];
1396414dc6dSKonstantin Porotchkin 	uint32_t	cp_efuse_arr[CP_CTRL_EL_ARRAY_SZ];
1406414dc6dSKonstantin Porotchkin 	mbedtls_pk_context	kak_pk;
1416414dc6dSKonstantin Porotchkin 	mbedtls_pk_context	csk_pk[CSK_ARR_SZ];
1426414dc6dSKonstantin Porotchkin 	uint8_t		aes_key[AES_KEY_BYTE_LEN];
1436414dc6dSKonstantin Porotchkin 	uint8_t		*encrypted_image;
1446414dc6dSKonstantin Porotchkin 	uint32_t	enc_image_sz;
1456414dc6dSKonstantin Porotchkin #endif
1466414dc6dSKonstantin Porotchkin } sec_options;
1476414dc6dSKonstantin Porotchkin 
1486414dc6dSKonstantin Porotchkin typedef struct _options {
1496414dc6dSKonstantin Porotchkin 	char bin_ext_file[MAX_FILENAME+1];
1506414dc6dSKonstantin Porotchkin 	char sec_cfg_file[MAX_FILENAME+1];
1516414dc6dSKonstantin Porotchkin 	sec_options *sec_opts;
1526414dc6dSKonstantin Porotchkin 	uint32_t  load_addr;
1536414dc6dSKonstantin Porotchkin 	uint32_t  exec_addr;
1546414dc6dSKonstantin Porotchkin 	uint32_t  baudrate;
1556414dc6dSKonstantin Porotchkin 	uint8_t	  disable_print;
1566414dc6dSKonstantin Porotchkin 	int8_t    key_index; /* For header signatures verification only */
1576414dc6dSKonstantin Porotchkin 	uint32_t  nfc_io_args;
1586414dc6dSKonstantin Porotchkin } options_t;
1596414dc6dSKonstantin Porotchkin 
usage_err(char * msg)1606414dc6dSKonstantin Porotchkin void usage_err(char *msg)
1616414dc6dSKonstantin Porotchkin {
1626414dc6dSKonstantin Porotchkin 	fprintf(stderr, "Error: %s\n", msg);
1636414dc6dSKonstantin Porotchkin 	fprintf(stderr, "run 'doimage -h' to get usage information\n");
1646414dc6dSKonstantin Porotchkin 	exit(-1);
1656414dc6dSKonstantin Porotchkin }
1666414dc6dSKonstantin Porotchkin 
usage(void)1676414dc6dSKonstantin Porotchkin void usage(void)
1686414dc6dSKonstantin Porotchkin {
1696414dc6dSKonstantin Porotchkin 	printf("\n\n%s\n\n", VERSION_STRING);
1706414dc6dSKonstantin Porotchkin 	printf("Usage: doimage [options] <input_file> [output_file]\n");
1716414dc6dSKonstantin Porotchkin 	printf("create bootrom image from u-boot and boot extensions\n\n");
1726414dc6dSKonstantin Porotchkin 
1736414dc6dSKonstantin Porotchkin 	printf("Arguments\n");
1746414dc6dSKonstantin Porotchkin 	printf("  input_file   name of boot image file.\n");
1756414dc6dSKonstantin Porotchkin 	printf("               if -p is used, name of the bootrom image file");
1766414dc6dSKonstantin Porotchkin 	printf("               to parse.\n");
1776414dc6dSKonstantin Porotchkin 	printf("  output_file  name of output bootrom image file\n");
1786414dc6dSKonstantin Porotchkin 
1796414dc6dSKonstantin Porotchkin 	printf("\nOptions\n");
1806414dc6dSKonstantin Porotchkin 	printf("  -s        target SOC name. supports a8020,a7020\n");
1816414dc6dSKonstantin Porotchkin 	printf("            different SOCs may have different boot image\n");
1826414dc6dSKonstantin Porotchkin 	printf("            format so it's mandatory to know the target SOC\n");
1836414dc6dSKonstantin Porotchkin 	printf("  -i        boot I/F name. supports nand, spi, nor\n");
1846414dc6dSKonstantin Porotchkin 	printf("            This affects certain parameters coded in the\n");
1856414dc6dSKonstantin Porotchkin 	printf("            image header\n");
1866414dc6dSKonstantin Porotchkin 	printf("  -l        boot image load address. default is 0x0\n");
1876414dc6dSKonstantin Porotchkin 	printf("  -e        boot image entry address. default is 0x0\n");
1886414dc6dSKonstantin Porotchkin 	printf("  -b        binary extension image file.\n");
1896414dc6dSKonstantin Porotchkin 	printf("            This image is executed before the boot image.\n");
1906414dc6dSKonstantin Porotchkin 	printf("            This is typically used to initialize the memory ");
1916414dc6dSKonstantin Porotchkin 	printf("            controller.\n");
1926414dc6dSKonstantin Porotchkin 	printf("            Currently supports only a single file.\n");
1936414dc6dSKonstantin Porotchkin #ifdef CONFIG_MVEBU_SECURE_BOOT
1946414dc6dSKonstantin Porotchkin 	printf("  -c        Make trusted boot image using parameters\n");
1956414dc6dSKonstantin Porotchkin 	printf("            from the configuration file.\n");
1966414dc6dSKonstantin Porotchkin #endif
1976414dc6dSKonstantin Porotchkin 	printf("  -p        Parse and display a pre-built boot image\n");
1986414dc6dSKonstantin Porotchkin #ifdef CONFIG_MVEBU_SECURE_BOOT
1996414dc6dSKonstantin Porotchkin 	printf("  -k        Key index for RSA signatures verification\n");
2006414dc6dSKonstantin Porotchkin 	printf("            when parsing the boot image\n");
2016414dc6dSKonstantin Porotchkin #endif
2026414dc6dSKonstantin Porotchkin 	printf("  -m        Disable prints of bootrom and binary extension\n");
2036414dc6dSKonstantin Porotchkin 	printf("  -u        UART baudrate used for bootrom prints.\n");
2046414dc6dSKonstantin Porotchkin 	printf("            Must be multiple of 1200\n");
2056414dc6dSKonstantin Porotchkin 	printf("  -h        Show this help message\n");
2066414dc6dSKonstantin Porotchkin 	printf(" IO-ROM NFC-NAND boot parameters:\n");
2076414dc6dSKonstantin Porotchkin 	printf("  -n        NAND device block size in KB [Default is 64KB].\n");
2086414dc6dSKonstantin Porotchkin 	printf("  -t        NAND cell technology (SLC [Default] or MLC)\n");
2096414dc6dSKonstantin Porotchkin 
2106414dc6dSKonstantin Porotchkin 	exit(-1);
2116414dc6dSKonstantin Porotchkin }
2126414dc6dSKonstantin Porotchkin 
2136414dc6dSKonstantin Porotchkin /* globals */
2146414dc6dSKonstantin Porotchkin static options_t opts = {
2156414dc6dSKonstantin Porotchkin 	.bin_ext_file = "NA",
2166414dc6dSKonstantin Porotchkin 	.sec_cfg_file = "NA",
2176414dc6dSKonstantin Porotchkin 	.sec_opts = 0,
2186414dc6dSKonstantin Porotchkin 	.load_addr = 0x0,
2196414dc6dSKonstantin Porotchkin 	.exec_addr = 0x0,
2206414dc6dSKonstantin Porotchkin 	.disable_print = 0,
2216414dc6dSKonstantin Porotchkin 	.baudrate = 0,
2226414dc6dSKonstantin Porotchkin 	.key_index = -1,
2236414dc6dSKonstantin Porotchkin };
2246414dc6dSKonstantin Porotchkin 
get_file_size(char * filename)2256414dc6dSKonstantin Porotchkin int get_file_size(char *filename)
2266414dc6dSKonstantin Porotchkin {
2276414dc6dSKonstantin Porotchkin 	struct stat st;
2286414dc6dSKonstantin Porotchkin 
2296414dc6dSKonstantin Porotchkin 	if (stat(filename, &st) == 0)
2306414dc6dSKonstantin Porotchkin 		return st.st_size;
2316414dc6dSKonstantin Porotchkin 
2326414dc6dSKonstantin Porotchkin 	return -1;
2336414dc6dSKonstantin Porotchkin }
2346414dc6dSKonstantin Porotchkin 
checksum32(uint32_t * start,int len)2356414dc6dSKonstantin Porotchkin uint32_t checksum32(uint32_t *start, int len)
2366414dc6dSKonstantin Porotchkin {
2376414dc6dSKonstantin Porotchkin 	uint32_t sum = 0;
2386414dc6dSKonstantin Porotchkin 	uint32_t *startp = start;
2396414dc6dSKonstantin Porotchkin 
2406414dc6dSKonstantin Porotchkin 	do {
2416414dc6dSKonstantin Porotchkin 		sum += *startp;
2426414dc6dSKonstantin Porotchkin 		startp++;
2436414dc6dSKonstantin Porotchkin 		len -= 4;
2446414dc6dSKonstantin Porotchkin 	} while (len > 0);
2456414dc6dSKonstantin Porotchkin 
2466414dc6dSKonstantin Porotchkin 	return sum;
2476414dc6dSKonstantin Porotchkin }
2486414dc6dSKonstantin Porotchkin 
2496414dc6dSKonstantin Porotchkin /*******************************************************************************
2506414dc6dSKonstantin Porotchkin  *    create_rsa_signature (memory buffer content)
2516414dc6dSKonstantin Porotchkin  *          Create RSASSA-PSS/SHA-256 signature for memory buffer
2526414dc6dSKonstantin Porotchkin  *          using RSA Private Key
2536414dc6dSKonstantin Porotchkin  *    INPUT:
2546414dc6dSKonstantin Porotchkin  *          pk_ctx     Private Key context
2556414dc6dSKonstantin Porotchkin  *          input      memory buffer
2566414dc6dSKonstantin Porotchkin  *          ilen       buffer length
2576414dc6dSKonstantin Porotchkin  *          pers       personalization string for seeding the RNG.
2586414dc6dSKonstantin Porotchkin  *                     For instance a private key file name.
2596414dc6dSKonstantin Porotchkin  *    OUTPUT:
2606414dc6dSKonstantin Porotchkin  *          signature  RSA-2048 signature
2616414dc6dSKonstantin Porotchkin  *    RETURN:
2626414dc6dSKonstantin Porotchkin  *          0 on success
2636414dc6dSKonstantin Porotchkin  */
2646414dc6dSKonstantin Porotchkin #ifdef CONFIG_MVEBU_SECURE_BOOT
create_rsa_signature(mbedtls_pk_context * pk_ctx,const unsigned char * input,size_t ilen,const char * pers,uint8_t * signature)2656414dc6dSKonstantin Porotchkin int create_rsa_signature(mbedtls_pk_context	*pk_ctx,
2666414dc6dSKonstantin Porotchkin 			 const unsigned char	*input,
2676414dc6dSKonstantin Porotchkin 			 size_t			ilen,
2686414dc6dSKonstantin Porotchkin 			 const char		*pers,
2696414dc6dSKonstantin Porotchkin 			 uint8_t		*signature)
2706414dc6dSKonstantin Porotchkin {
2716414dc6dSKonstantin Porotchkin 	mbedtls_entropy_context		entropy;
2726414dc6dSKonstantin Porotchkin 	mbedtls_ctr_drbg_context	ctr_drbg;
2736414dc6dSKonstantin Porotchkin 	unsigned char			hash[32];
2746414dc6dSKonstantin Porotchkin 	unsigned char			buf[MBEDTLS_MPI_MAX_SIZE];
2756414dc6dSKonstantin Porotchkin 	int				rval;
2766414dc6dSKonstantin Porotchkin 
2776414dc6dSKonstantin Porotchkin 	/* Not sure this is required,
2786414dc6dSKonstantin Porotchkin 	 * but it's safer to start with empty buffers
2796414dc6dSKonstantin Porotchkin 	 */
2806414dc6dSKonstantin Porotchkin 	memset(hash, 0, sizeof(hash));
2816414dc6dSKonstantin Porotchkin 	memset(buf, 0, sizeof(buf));
2826414dc6dSKonstantin Porotchkin 
2836414dc6dSKonstantin Porotchkin 	mbedtls_ctr_drbg_init(&ctr_drbg);
2846414dc6dSKonstantin Porotchkin 	mbedtls_entropy_init(&entropy);
2856414dc6dSKonstantin Porotchkin 
2866414dc6dSKonstantin Porotchkin 	/* Seed the random number generator */
2876414dc6dSKonstantin Porotchkin 	rval = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
2886414dc6dSKonstantin Porotchkin 				(const unsigned char *)pers, strlen(pers));
2896414dc6dSKonstantin Porotchkin 	if (rval != 0) {
2906414dc6dSKonstantin Porotchkin 		fprintf(stderr, " Failed in ctr_drbg_init call (%d)!\n", rval);
2916414dc6dSKonstantin Porotchkin 		goto sign_exit;
2926414dc6dSKonstantin Porotchkin 	}
2936414dc6dSKonstantin Porotchkin 
2946414dc6dSKonstantin Porotchkin 	/* The PK context should be already initialized.
2956414dc6dSKonstantin Porotchkin 	 * Set the padding type for this PK context
2966414dc6dSKonstantin Porotchkin 	 */
2976414dc6dSKonstantin Porotchkin 	mbedtls_rsa_set_padding(mbedtls_pk_rsa(*pk_ctx),
2986414dc6dSKonstantin Porotchkin 				MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
2996414dc6dSKonstantin Porotchkin 
3006414dc6dSKonstantin Porotchkin 	/* First compute the SHA256 hash for the input blob */
301a79df348SKonstantin Porotchkin 	mbedtls_sha256_ret(input, ilen, hash, 0);
3026414dc6dSKonstantin Porotchkin 
3036414dc6dSKonstantin Porotchkin 	/* Then calculate the hash signature */
3046414dc6dSKonstantin Porotchkin 	rval = mbedtls_rsa_rsassa_pss_sign(mbedtls_pk_rsa(*pk_ctx),
3056414dc6dSKonstantin Porotchkin 					   mbedtls_ctr_drbg_random,
3066414dc6dSKonstantin Porotchkin 					   &ctr_drbg,
3076414dc6dSKonstantin Porotchkin 					   MBEDTLS_RSA_PRIVATE,
3086414dc6dSKonstantin Porotchkin 					   MBEDTLS_MD_SHA256, 0, hash, buf);
3096414dc6dSKonstantin Porotchkin 	if (rval != 0) {
3106414dc6dSKonstantin Porotchkin 		fprintf(stderr,
3116414dc6dSKonstantin Porotchkin 			"Failed to create RSA signature for %s. Error %d\n",
3126414dc6dSKonstantin Porotchkin 			pers, rval);
3136414dc6dSKonstantin Porotchkin 		goto sign_exit;
3146414dc6dSKonstantin Porotchkin 	}
3156414dc6dSKonstantin Porotchkin 	memcpy(signature, buf, 256);
3166414dc6dSKonstantin Porotchkin 
3176414dc6dSKonstantin Porotchkin sign_exit:
3186414dc6dSKonstantin Porotchkin 	mbedtls_ctr_drbg_free(&ctr_drbg);
3196414dc6dSKonstantin Porotchkin 	mbedtls_entropy_free(&entropy);
3206414dc6dSKonstantin Porotchkin 
3216414dc6dSKonstantin Porotchkin 	return rval;
3226414dc6dSKonstantin Porotchkin } /* end of create_rsa_signature */
3236414dc6dSKonstantin Porotchkin 
3246414dc6dSKonstantin Porotchkin /*******************************************************************************
3256414dc6dSKonstantin Porotchkin  *    verify_rsa_signature (memory buffer content)
3266414dc6dSKonstantin Porotchkin  *          Verify RSASSA-PSS/SHA-256 signature for memory buffer
3276414dc6dSKonstantin Porotchkin  *          using RSA Public Key
3286414dc6dSKonstantin Porotchkin  *    INPUT:
3296414dc6dSKonstantin Porotchkin  *          pub_key    Public Key buffer
3306414dc6dSKonstantin Porotchkin  *          ilen       Public Key buffer length
3316414dc6dSKonstantin Porotchkin  *          input      memory buffer
3326414dc6dSKonstantin Porotchkin  *          ilen       buffer length
3336414dc6dSKonstantin Porotchkin  *          pers       personalization string for seeding the RNG.
3346414dc6dSKonstantin Porotchkin  *          signature  RSA-2048 signature
3356414dc6dSKonstantin Porotchkin  *    OUTPUT:
3366414dc6dSKonstantin Porotchkin  *          none
3376414dc6dSKonstantin Porotchkin  *    RETURN:
3386414dc6dSKonstantin Porotchkin  *          0 on success
3396414dc6dSKonstantin Porotchkin  */
verify_rsa_signature(const unsigned char * pub_key,size_t klen,const unsigned char * input,size_t ilen,const char * pers,uint8_t * signature)3406414dc6dSKonstantin Porotchkin int verify_rsa_signature(const unsigned char	*pub_key,
3416414dc6dSKonstantin Porotchkin 			 size_t			klen,
3426414dc6dSKonstantin Porotchkin 			 const unsigned char	*input,
3436414dc6dSKonstantin Porotchkin 			 size_t			ilen,
3446414dc6dSKonstantin Porotchkin 			 const char		*pers,
3456414dc6dSKonstantin Porotchkin 			 uint8_t		*signature)
3466414dc6dSKonstantin Porotchkin {
3476414dc6dSKonstantin Porotchkin 	mbedtls_entropy_context		entropy;
3486414dc6dSKonstantin Porotchkin 	mbedtls_ctr_drbg_context	ctr_drbg;
3496414dc6dSKonstantin Porotchkin 	mbedtls_pk_context		pk_ctx;
3506414dc6dSKonstantin Porotchkin 	unsigned char			hash[32];
3516414dc6dSKonstantin Porotchkin 	int				rval;
352a79df348SKonstantin Porotchkin 	unsigned char			*pkey = (unsigned char *)pub_key;
3536414dc6dSKonstantin Porotchkin 
3546414dc6dSKonstantin Porotchkin 	/* Not sure this is required,
3556414dc6dSKonstantin Porotchkin 	 * but it's safer to start with empty buffer
3566414dc6dSKonstantin Porotchkin 	 */
3576414dc6dSKonstantin Porotchkin 	memset(hash, 0, sizeof(hash));
3586414dc6dSKonstantin Porotchkin 
3596414dc6dSKonstantin Porotchkin 	mbedtls_pk_init(&pk_ctx);
3606414dc6dSKonstantin Porotchkin 	mbedtls_ctr_drbg_init(&ctr_drbg);
3616414dc6dSKonstantin Porotchkin 	mbedtls_entropy_init(&entropy);
3626414dc6dSKonstantin Porotchkin 
3636414dc6dSKonstantin Porotchkin 	/* Seed the random number generator */
3646414dc6dSKonstantin Porotchkin 	rval = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
3656414dc6dSKonstantin Porotchkin 				(const unsigned char *)pers, strlen(pers));
3666414dc6dSKonstantin Porotchkin 	if (rval != 0) {
3676414dc6dSKonstantin Porotchkin 		fprintf(stderr, " Failed in ctr_drbg_init call (%d)!\n", rval);
3686414dc6dSKonstantin Porotchkin 		goto verify_exit;
3696414dc6dSKonstantin Porotchkin 	}
3706414dc6dSKonstantin Porotchkin 
3716414dc6dSKonstantin Porotchkin 	/* Check ability to read the public key */
372a79df348SKonstantin Porotchkin 	rval = mbedtls_pk_parse_subpubkey(&pkey, pub_key + klen, &pk_ctx);
3736414dc6dSKonstantin Porotchkin 	if (rval != 0) {
3746414dc6dSKonstantin Porotchkin 		fprintf(stderr, " Failed in pk_parse_public_key (%#x)!\n",
3756414dc6dSKonstantin Porotchkin 			rval);
3766414dc6dSKonstantin Porotchkin 		goto verify_exit;
3776414dc6dSKonstantin Porotchkin 	}
3786414dc6dSKonstantin Porotchkin 
3796414dc6dSKonstantin Porotchkin 	/* Set the padding type for the new PK context */
3806414dc6dSKonstantin Porotchkin 	mbedtls_rsa_set_padding(mbedtls_pk_rsa(pk_ctx),
3816414dc6dSKonstantin Porotchkin 				MBEDTLS_RSA_PKCS_V21,
3826414dc6dSKonstantin Porotchkin 				MBEDTLS_MD_SHA256);
3836414dc6dSKonstantin Porotchkin 
3846414dc6dSKonstantin Porotchkin 	/* Compute the SHA256 hash for the input buffer */
385a79df348SKonstantin Porotchkin 	mbedtls_sha256_ret(input, ilen, hash, 0);
3866414dc6dSKonstantin Porotchkin 
3876414dc6dSKonstantin Porotchkin 	rval = mbedtls_rsa_rsassa_pss_verify(mbedtls_pk_rsa(pk_ctx),
3886414dc6dSKonstantin Porotchkin 					     mbedtls_ctr_drbg_random,
3896414dc6dSKonstantin Porotchkin 					     &ctr_drbg,
3906414dc6dSKonstantin Porotchkin 					     MBEDTLS_RSA_PUBLIC,
3916414dc6dSKonstantin Porotchkin 					     MBEDTLS_MD_SHA256, 0,
3926414dc6dSKonstantin Porotchkin 					     hash, signature);
3936414dc6dSKonstantin Porotchkin 	if (rval != 0)
3946414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Failed to verify signature (%d)!\n", rval);
3956414dc6dSKonstantin Porotchkin 
3966414dc6dSKonstantin Porotchkin verify_exit:
3976414dc6dSKonstantin Porotchkin 
3986414dc6dSKonstantin Porotchkin 	mbedtls_pk_free(&pk_ctx);
3996414dc6dSKonstantin Porotchkin 	mbedtls_ctr_drbg_free(&ctr_drbg);
4006414dc6dSKonstantin Porotchkin 	mbedtls_entropy_free(&entropy);
4016414dc6dSKonstantin Porotchkin 	return rval;
4026414dc6dSKonstantin Porotchkin } /* end of verify_rsa_signature */
4036414dc6dSKonstantin Porotchkin 
4046414dc6dSKonstantin Porotchkin /*******************************************************************************
4056414dc6dSKonstantin Porotchkin  *    image_encrypt
4066414dc6dSKonstantin Porotchkin  *           Encrypt image buffer using AES-256-CBC scheme.
4076414dc6dSKonstantin Porotchkin  *           The resulting image is saved into opts.sec_opts->encrypted_image
4086414dc6dSKonstantin Porotchkin  *           and the adjusted image size into opts.sec_opts->enc_image_sz
4096414dc6dSKonstantin Porotchkin  *           First AES_BLOCK_SZ bytes of the output image contain IV
4106414dc6dSKonstantin Porotchkin  *    INPUT:
4116414dc6dSKonstantin Porotchkin  *          buf        Source buffer to encrypt
4126414dc6dSKonstantin Porotchkin  *          blen       Source buffer length
4136414dc6dSKonstantin Porotchkin  *    OUTPUT:
4146414dc6dSKonstantin Porotchkin  *          none
4156414dc6dSKonstantin Porotchkin  *    RETURN:
4166414dc6dSKonstantin Porotchkin  *          0 on success
4176414dc6dSKonstantin Porotchkin  */
image_encrypt(uint8_t * buf,uint32_t blen)4186414dc6dSKonstantin Porotchkin int image_encrypt(uint8_t *buf, uint32_t blen)
4196414dc6dSKonstantin Porotchkin {
4206414dc6dSKonstantin Porotchkin 	struct timeval		tv;
4216414dc6dSKonstantin Porotchkin 	char			*ptmp = (char *)&tv;
4226414dc6dSKonstantin Porotchkin 	unsigned char		digest[32];
4236414dc6dSKonstantin Porotchkin 	unsigned char		IV[AES_BLOCK_SZ];
424*fbf65557SJaiprakash Singh 	size_t			i, k;
4256414dc6dSKonstantin Porotchkin 	mbedtls_aes_context	aes_ctx;
4266414dc6dSKonstantin Porotchkin 	int			rval = -1;
4276414dc6dSKonstantin Porotchkin 	uint8_t			*test_img = 0;
4286414dc6dSKonstantin Porotchkin 
4296414dc6dSKonstantin Porotchkin 	if (AES_BLOCK_SZ > 32) {
4306414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Unsupported AES block size %d\n",
4316414dc6dSKonstantin Porotchkin 			AES_BLOCK_SZ);
4326414dc6dSKonstantin Porotchkin 		return rval;
4336414dc6dSKonstantin Porotchkin 	}
4346414dc6dSKonstantin Porotchkin 
4356414dc6dSKonstantin Porotchkin 	mbedtls_aes_init(&aes_ctx);
4366414dc6dSKonstantin Porotchkin 	memset(IV, 0, AES_BLOCK_SZ);
4376414dc6dSKonstantin Porotchkin 	memset(digest, 0, 32);
4386414dc6dSKonstantin Porotchkin 
4396414dc6dSKonstantin Porotchkin 	/* Generate initialization vector and init the AES engine
4406414dc6dSKonstantin Porotchkin 	 * Use file name XOR current time and finally SHA-256
4416414dc6dSKonstantin Porotchkin 	 * [0...AES_BLOCK_SZ-1]
4426414dc6dSKonstantin Porotchkin 	 */
4436414dc6dSKonstantin Porotchkin 	k = strlen(opts.sec_opts->aes_key_file);
4446414dc6dSKonstantin Porotchkin 	if (k > AES_BLOCK_SZ)
4456414dc6dSKonstantin Porotchkin 		k = AES_BLOCK_SZ;
4466414dc6dSKonstantin Porotchkin 	memcpy(IV, opts.sec_opts->aes_key_file, k);
4476414dc6dSKonstantin Porotchkin 	gettimeofday(&tv, 0);
4486414dc6dSKonstantin Porotchkin 
4496414dc6dSKonstantin Porotchkin 	for (i = 0, k = 0; i < AES_BLOCK_SZ; i++,
4506414dc6dSKonstantin Porotchkin 	     k = (k+1) % sizeof(struct timeval))
4516414dc6dSKonstantin Porotchkin 		IV[i] ^= ptmp[k];
4526414dc6dSKonstantin Porotchkin 
4536414dc6dSKonstantin Porotchkin 	/* compute SHA-256 digest of the results
4546414dc6dSKonstantin Porotchkin 	 * and use it as the init vector (IV)
4556414dc6dSKonstantin Porotchkin 	 */
456a79df348SKonstantin Porotchkin 	mbedtls_sha256_ret(IV, AES_BLOCK_SZ, digest, 0);
4576414dc6dSKonstantin Porotchkin 	memcpy(IV, digest, AES_BLOCK_SZ);
4586414dc6dSKonstantin Porotchkin 	mbedtls_aes_setkey_enc(&aes_ctx, opts.sec_opts->aes_key,
4596414dc6dSKonstantin Porotchkin 			       AES_KEY_BIT_LEN);
4606414dc6dSKonstantin Porotchkin 
4616414dc6dSKonstantin Porotchkin 	/* The output image has to include extra space for IV
4626414dc6dSKonstantin Porotchkin 	 * and to be aligned to the AES block size.
4636414dc6dSKonstantin Porotchkin 	 * The input image buffer has to be already aligned to AES_BLOCK_SZ
4646414dc6dSKonstantin Porotchkin 	 * and padded with zeroes
4656414dc6dSKonstantin Porotchkin 	 */
4666414dc6dSKonstantin Porotchkin 	opts.sec_opts->enc_image_sz = (blen + 2 * AES_BLOCK_SZ - 1) &
4676414dc6dSKonstantin Porotchkin 				      ~(AES_BLOCK_SZ - 1);
4686414dc6dSKonstantin Porotchkin 	opts.sec_opts->encrypted_image = calloc(opts.sec_opts->enc_image_sz, 1);
4696414dc6dSKonstantin Porotchkin 	if (opts.sec_opts->encrypted_image == 0) {
4706414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Failed to allocate encrypted image!\n");
4716414dc6dSKonstantin Porotchkin 		goto encrypt_exit;
4726414dc6dSKonstantin Porotchkin 	}
4736414dc6dSKonstantin Porotchkin 
4746414dc6dSKonstantin Porotchkin 	/* Put IV into the output buffer next to the encrypted image
4756414dc6dSKonstantin Porotchkin 	 * Since the IV is modified by the encryption function,
4766414dc6dSKonstantin Porotchkin 	 * this should be done now
4776414dc6dSKonstantin Porotchkin 	 */
4786414dc6dSKonstantin Porotchkin 	memcpy(opts.sec_opts->encrypted_image +
4796414dc6dSKonstantin Porotchkin 		   opts.sec_opts->enc_image_sz - AES_BLOCK_SZ,
4806414dc6dSKonstantin Porotchkin 		   IV, AES_BLOCK_SZ);
4816414dc6dSKonstantin Porotchkin 	rval = mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_ENCRYPT,
4826414dc6dSKonstantin Porotchkin 			     opts.sec_opts->enc_image_sz - AES_BLOCK_SZ,
4836414dc6dSKonstantin Porotchkin 			     IV, buf, opts.sec_opts->encrypted_image);
4846414dc6dSKonstantin Porotchkin 	if (rval != 0) {
4856414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Failed to encrypt the image! Error %d\n",
4866414dc6dSKonstantin Porotchkin 			rval);
4876414dc6dSKonstantin Porotchkin 		goto encrypt_exit;
4886414dc6dSKonstantin Porotchkin 	}
4896414dc6dSKonstantin Porotchkin 
4906414dc6dSKonstantin Porotchkin 	mbedtls_aes_free(&aes_ctx);
4916414dc6dSKonstantin Porotchkin 
4926414dc6dSKonstantin Porotchkin 	/* Try to decrypt the image and compare it with the original data */
4936414dc6dSKonstantin Porotchkin 	mbedtls_aes_init(&aes_ctx);
4946414dc6dSKonstantin Porotchkin 	mbedtls_aes_setkey_dec(&aes_ctx, opts.sec_opts->aes_key,
4956414dc6dSKonstantin Porotchkin 			       AES_KEY_BIT_LEN);
4966414dc6dSKonstantin Porotchkin 
4976414dc6dSKonstantin Porotchkin 	test_img = calloc(opts.sec_opts->enc_image_sz - AES_BLOCK_SZ, 1);
4986414dc6dSKonstantin Porotchkin 	if (test_img == 0) {
4996414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Failed to allocate test image!d\n");
5006414dc6dSKonstantin Porotchkin 		rval = -1;
5016414dc6dSKonstantin Porotchkin 		goto encrypt_exit;
5026414dc6dSKonstantin Porotchkin 	}
5036414dc6dSKonstantin Porotchkin 
5046414dc6dSKonstantin Porotchkin 	memcpy(IV, opts.sec_opts->encrypted_image +
5056414dc6dSKonstantin Porotchkin 		   opts.sec_opts->enc_image_sz - AES_BLOCK_SZ,
5066414dc6dSKonstantin Porotchkin 		   AES_BLOCK_SZ);
5076414dc6dSKonstantin Porotchkin 	rval = mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT,
5086414dc6dSKonstantin Porotchkin 			     opts.sec_opts->enc_image_sz - AES_BLOCK_SZ,
5096414dc6dSKonstantin Porotchkin 			     IV, opts.sec_opts->encrypted_image, test_img);
5106414dc6dSKonstantin Porotchkin 	if (rval != 0) {
5116414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Failed to decrypt the image! Error %d\n",
5126414dc6dSKonstantin Porotchkin 			rval);
5136414dc6dSKonstantin Porotchkin 		goto encrypt_exit;
5146414dc6dSKonstantin Porotchkin 	}
5156414dc6dSKonstantin Porotchkin 
5166414dc6dSKonstantin Porotchkin 	for (i = 0; i < blen; i++) {
5176414dc6dSKonstantin Porotchkin 		if (buf[i] != test_img[i]) {
5186414dc6dSKonstantin Porotchkin 			fprintf(stderr, "Failed to compare the image after");
519*fbf65557SJaiprakash Singh 			fprintf(stderr, " decryption! Byte count is %lu\n",
520*fbf65557SJaiprakash Singh 				(unsigned long)i);
5216414dc6dSKonstantin Porotchkin 			rval = -1;
5226414dc6dSKonstantin Porotchkin 			goto encrypt_exit;
5236414dc6dSKonstantin Porotchkin 		}
5246414dc6dSKonstantin Porotchkin 	}
5256414dc6dSKonstantin Porotchkin 
5266414dc6dSKonstantin Porotchkin encrypt_exit:
5276414dc6dSKonstantin Porotchkin 
5286414dc6dSKonstantin Porotchkin 	mbedtls_aes_free(&aes_ctx);
5296414dc6dSKonstantin Porotchkin 	if (test_img)
5306414dc6dSKonstantin Porotchkin 		free(test_img);
5316414dc6dSKonstantin Porotchkin 
5326414dc6dSKonstantin Porotchkin 	return rval;
5336414dc6dSKonstantin Porotchkin } /* end of image_encrypt */
5346414dc6dSKonstantin Porotchkin 
5356414dc6dSKonstantin Porotchkin /*******************************************************************************
5366414dc6dSKonstantin Porotchkin  *    verify_secure_header_signatures
5376414dc6dSKonstantin Porotchkin  *          Verify CSK array, header and image signatures and print results
5386414dc6dSKonstantin Porotchkin  *    INPUT:
5396414dc6dSKonstantin Porotchkin  *          main_hdr       Main header
5406414dc6dSKonstantin Porotchkin  *          sec_ext        Secure extension
5416414dc6dSKonstantin Porotchkin  *    OUTPUT:
5426414dc6dSKonstantin Porotchkin  *          none
5436414dc6dSKonstantin Porotchkin  *    RETURN:
5446414dc6dSKonstantin Porotchkin  *          0 on success
5456414dc6dSKonstantin Porotchkin  */
verify_secure_header_signatures(header_t * main_hdr,sec_entry_t * sec_ext)5466414dc6dSKonstantin Porotchkin int verify_secure_header_signatures(header_t *main_hdr, sec_entry_t *sec_ext)
5476414dc6dSKonstantin Porotchkin {
5486414dc6dSKonstantin Porotchkin 	uint8_t	*image = (uint8_t *)main_hdr + main_hdr->prolog_size;
5496414dc6dSKonstantin Porotchkin 	uint8_t	signature[RSA_SIGN_BYTE_LEN];
5506414dc6dSKonstantin Porotchkin 	int		rval = -1;
5516414dc6dSKonstantin Porotchkin 
5526414dc6dSKonstantin Porotchkin 	/* Save headers signature and reset it in the secure header */
5536414dc6dSKonstantin Porotchkin 	memcpy(signature, sec_ext->header_sign, RSA_SIGN_BYTE_LEN);
5546414dc6dSKonstantin Porotchkin 	memset(sec_ext->header_sign, 0, RSA_SIGN_BYTE_LEN);
5556414dc6dSKonstantin Porotchkin 
5566414dc6dSKonstantin Porotchkin 	fprintf(stdout, "\nCheck RSA Signatures\n");
5576414dc6dSKonstantin Porotchkin 	fprintf(stdout, "#########################\n");
5586414dc6dSKonstantin Porotchkin 	fprintf(stdout, "CSK Block Signature: ");
5596414dc6dSKonstantin Porotchkin 	if (verify_rsa_signature(sec_ext->kak_key,
5606414dc6dSKonstantin Porotchkin 				 MAX_RSA_DER_BYTE_LEN,
5616414dc6dSKonstantin Porotchkin 				 &sec_ext->csk_keys[0][0],
5626414dc6dSKonstantin Porotchkin 				 sizeof(sec_ext->csk_keys),
5636414dc6dSKonstantin Porotchkin 				 "CSK Block Signature: ",
5646414dc6dSKonstantin Porotchkin 				 sec_ext->csk_sign) != 0) {
5656414dc6dSKonstantin Porotchkin 		fprintf(stdout, "ERROR\n");
5666414dc6dSKonstantin Porotchkin 		goto ver_error;
5676414dc6dSKonstantin Porotchkin 	}
5686414dc6dSKonstantin Porotchkin 	fprintf(stdout, "OK\n");
5696414dc6dSKonstantin Porotchkin 
5706414dc6dSKonstantin Porotchkin 	if (opts.key_index != -1) {
5716414dc6dSKonstantin Porotchkin 		fprintf(stdout, "Image Signature:     ");
5726414dc6dSKonstantin Porotchkin 		if (verify_rsa_signature(sec_ext->csk_keys[opts.key_index],
5736414dc6dSKonstantin Porotchkin 					 MAX_RSA_DER_BYTE_LEN,
5746414dc6dSKonstantin Porotchkin 					 image, main_hdr->boot_image_size,
5756414dc6dSKonstantin Porotchkin 					 "Image Signature: ",
5766414dc6dSKonstantin Porotchkin 					 sec_ext->image_sign) != 0) {
5776414dc6dSKonstantin Porotchkin 			fprintf(stdout, "ERROR\n");
5786414dc6dSKonstantin Porotchkin 			goto ver_error;
5796414dc6dSKonstantin Porotchkin 		}
5806414dc6dSKonstantin Porotchkin 		fprintf(stdout, "OK\n");
5816414dc6dSKonstantin Porotchkin 
5826414dc6dSKonstantin Porotchkin 		fprintf(stdout, "Header Signature:    ");
5836414dc6dSKonstantin Porotchkin 		if (verify_rsa_signature(sec_ext->csk_keys[opts.key_index],
5846414dc6dSKonstantin Porotchkin 					 MAX_RSA_DER_BYTE_LEN,
5856414dc6dSKonstantin Porotchkin 					 (uint8_t *)main_hdr,
5866414dc6dSKonstantin Porotchkin 					 main_hdr->prolog_size,
5876414dc6dSKonstantin Porotchkin 					 "Header Signature: ",
5886414dc6dSKonstantin Porotchkin 					 signature) != 0) {
5896414dc6dSKonstantin Porotchkin 			fprintf(stdout, "ERROR\n");
5906414dc6dSKonstantin Porotchkin 			goto ver_error;
5916414dc6dSKonstantin Porotchkin 		}
5926414dc6dSKonstantin Porotchkin 		fprintf(stdout, "OK\n");
5936414dc6dSKonstantin Porotchkin 	} else {
5946414dc6dSKonstantin Porotchkin 		fprintf(stdout, "SKIP Image and Header Signatures");
5956414dc6dSKonstantin Porotchkin 		fprintf(stdout, " check (undefined key index)\n");
5966414dc6dSKonstantin Porotchkin 	}
5976414dc6dSKonstantin Porotchkin 
5986414dc6dSKonstantin Porotchkin 	rval = 0;
5996414dc6dSKonstantin Porotchkin 
6006414dc6dSKonstantin Porotchkin ver_error:
6016414dc6dSKonstantin Porotchkin 	memcpy(sec_ext->header_sign, signature, RSA_SIGN_BYTE_LEN);
6026414dc6dSKonstantin Porotchkin 	return rval;
6036414dc6dSKonstantin Porotchkin }
6046414dc6dSKonstantin Porotchkin 
6056414dc6dSKonstantin Porotchkin /*******************************************************************************
6066414dc6dSKonstantin Porotchkin  *    verify_and_copy_file_name_entry
6076414dc6dSKonstantin Porotchkin  *    INPUT:
6086414dc6dSKonstantin Porotchkin  *          element_name
6096414dc6dSKonstantin Porotchkin  *          element
6106414dc6dSKonstantin Porotchkin  *    OUTPUT:
6116414dc6dSKonstantin Porotchkin  *          copy_to
6126414dc6dSKonstantin Porotchkin  *    RETURN:
6136414dc6dSKonstantin Porotchkin  *          0 on success
6146414dc6dSKonstantin Porotchkin  */
verify_and_copy_file_name_entry(const char * element_name,const char * element,char * copy_to)6156414dc6dSKonstantin Porotchkin int verify_and_copy_file_name_entry(const char *element_name,
6166414dc6dSKonstantin Porotchkin 				    const char *element, char *copy_to)
6176414dc6dSKonstantin Porotchkin {
618*fbf65557SJaiprakash Singh 	size_t element_length = strlen(element);
6196414dc6dSKonstantin Porotchkin 
6206414dc6dSKonstantin Porotchkin 	if (element_length >= MAX_FILENAME) {
621*fbf65557SJaiprakash Singh 		fprintf(stderr, "The file name %s for %s is too long (%lu). ",
622*fbf65557SJaiprakash Singh 			element, element_name, (unsigned long)element_length);
6236414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Maximum allowed %d characters!\n",
6246414dc6dSKonstantin Porotchkin 			MAX_FILENAME);
6256414dc6dSKonstantin Porotchkin 		return -1;
6266414dc6dSKonstantin Porotchkin 	} else if (element_length == 0) {
6276414dc6dSKonstantin Porotchkin 		fprintf(stderr, "The file name for %s is empty!\n",
6286414dc6dSKonstantin Porotchkin 			element_name);
6296414dc6dSKonstantin Porotchkin 		return -1;
6306414dc6dSKonstantin Porotchkin 	}
6316414dc6dSKonstantin Porotchkin 	memcpy(copy_to, element, element_length);
6326414dc6dSKonstantin Porotchkin 
6336414dc6dSKonstantin Porotchkin 	return 0;
6346414dc6dSKonstantin Porotchkin }
6356414dc6dSKonstantin Porotchkin 
6366414dc6dSKonstantin Porotchkin /*******************************************************************************
6376414dc6dSKonstantin Porotchkin  *    parse_sec_config_file
6386414dc6dSKonstantin Porotchkin  *          Read the secure boot configuration from a file
6396414dc6dSKonstantin Porotchkin  *          into internal structures
6406414dc6dSKonstantin Porotchkin  *    INPUT:
6416414dc6dSKonstantin Porotchkin  *          filename      File name
6426414dc6dSKonstantin Porotchkin  *    OUTPUT:
6436414dc6dSKonstantin Porotchkin  *          none
6446414dc6dSKonstantin Porotchkin  *    RETURN:
6456414dc6dSKonstantin Porotchkin  *          0 on success
6466414dc6dSKonstantin Porotchkin  */
parse_sec_config_file(char * filename)6476414dc6dSKonstantin Porotchkin int parse_sec_config_file(char *filename)
6486414dc6dSKonstantin Porotchkin {
6496414dc6dSKonstantin Porotchkin 	config_t		sec_cfg;
6506414dc6dSKonstantin Porotchkin 	int			array_sz, element, rval = -1;
6516414dc6dSKonstantin Porotchkin 	const char		*cfg_string;
6526414dc6dSKonstantin Porotchkin 	int32_t			cfg_int32;
6536414dc6dSKonstantin Porotchkin 	const config_setting_t	*csk_array, *control_array;
6546414dc6dSKonstantin Porotchkin 	sec_options		*sec_opt = 0;
6556414dc6dSKonstantin Porotchkin 
6566414dc6dSKonstantin Porotchkin 	config_init(&sec_cfg);
6576414dc6dSKonstantin Porotchkin 
6586414dc6dSKonstantin Porotchkin 	if (config_read_file(&sec_cfg, filename) != CONFIG_TRUE) {
6596414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Failed to read data from config file ");
6606414dc6dSKonstantin Porotchkin 		fprintf(stderr, "%s\n\t%s at line %d\n",
6616414dc6dSKonstantin Porotchkin 			filename, config_error_text(&sec_cfg),
6626414dc6dSKonstantin Porotchkin 			config_error_line(&sec_cfg));
6636414dc6dSKonstantin Porotchkin 		goto exit_parse;
6646414dc6dSKonstantin Porotchkin 	}
6656414dc6dSKonstantin Porotchkin 
6666414dc6dSKonstantin Porotchkin 	sec_opt = (sec_options *)calloc(sizeof(sec_options), 1);
6676414dc6dSKonstantin Porotchkin 	if (sec_opt == 0) {
6686414dc6dSKonstantin Porotchkin 		fprintf(stderr,
6696414dc6dSKonstantin Porotchkin 			"Cannot allocate memory for secure boot options!\n");
6706414dc6dSKonstantin Porotchkin 		goto exit_parse;
6716414dc6dSKonstantin Porotchkin 	}
6726414dc6dSKonstantin Porotchkin 
6736414dc6dSKonstantin Porotchkin 	/* KAK file name */
6746414dc6dSKonstantin Porotchkin 	if (config_lookup_string(&sec_cfg, "kak_key_file",
6756414dc6dSKonstantin Porotchkin 				 &cfg_string) != CONFIG_TRUE) {
6766414dc6dSKonstantin Porotchkin 		fprintf(stderr, "The \"kak_key_file\" undefined!\n");
6776414dc6dSKonstantin Porotchkin 		goto exit_parse;
6786414dc6dSKonstantin Porotchkin 	}
6796414dc6dSKonstantin Porotchkin 	if (verify_and_copy_file_name_entry("kak_key_file",
6806414dc6dSKonstantin Porotchkin 					    cfg_string, sec_opt->kak_key_file))
6816414dc6dSKonstantin Porotchkin 		goto exit_parse;
6826414dc6dSKonstantin Porotchkin 
6836414dc6dSKonstantin Porotchkin 
6846414dc6dSKonstantin Porotchkin 	/* AES file name - can be empty/undefined */
6856414dc6dSKonstantin Porotchkin 	if (config_lookup_string(&sec_cfg, "aes_key_file",
6866414dc6dSKonstantin Porotchkin 				 &cfg_string) == CONFIG_TRUE) {
6876414dc6dSKonstantin Porotchkin 		if (verify_and_copy_file_name_entry("aes_key_file",
6886414dc6dSKonstantin Porotchkin 						    cfg_string,
6896414dc6dSKonstantin Porotchkin 						    sec_opt->aes_key_file))
6906414dc6dSKonstantin Porotchkin 			goto exit_parse;
6916414dc6dSKonstantin Porotchkin 	}
6926414dc6dSKonstantin Porotchkin 
6936414dc6dSKonstantin Porotchkin 	/* CSK file names array */
6946414dc6dSKonstantin Porotchkin 	csk_array = config_lookup(&sec_cfg, "csk_key_file");
6956414dc6dSKonstantin Porotchkin 	if (csk_array == NULL) {
6966414dc6dSKonstantin Porotchkin 		fprintf(stderr, "The \"csk_key_file\" undefined!\n");
6976414dc6dSKonstantin Porotchkin 		goto exit_parse;
6986414dc6dSKonstantin Porotchkin 	}
6996414dc6dSKonstantin Porotchkin 	array_sz = config_setting_length(csk_array);
7006414dc6dSKonstantin Porotchkin 	if (array_sz > CSK_ARR_SZ) {
7016414dc6dSKonstantin Porotchkin 		fprintf(stderr, "The \"csk_key_file\" array is too big! ");
7026414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Only first %d elements will be used\n",
7036414dc6dSKonstantin Porotchkin 			CSK_ARR_SZ);
7046414dc6dSKonstantin Porotchkin 		array_sz = CSK_ARR_SZ;
7056414dc6dSKonstantin Porotchkin 	} else if (array_sz == 0) {
7066414dc6dSKonstantin Porotchkin 		fprintf(stderr, "The \"csk_key_file\" array is empty!\n");
7076414dc6dSKonstantin Porotchkin 		goto exit_parse;
7086414dc6dSKonstantin Porotchkin 	}
7096414dc6dSKonstantin Porotchkin 
7106414dc6dSKonstantin Porotchkin 	for (element = 0; element < array_sz; element++) {
7116414dc6dSKonstantin Porotchkin 		cfg_string = config_setting_get_string_elem(csk_array, element);
7126414dc6dSKonstantin Porotchkin 		if (verify_and_copy_file_name_entry(
7136414dc6dSKonstantin Porotchkin 				"csk_key_file", cfg_string,
7146414dc6dSKonstantin Porotchkin 				sec_opt->csk_key_file[element])) {
7156414dc6dSKonstantin Porotchkin 			fprintf(stderr, "Bad csk_key_file[%d] entry!\n",
7166414dc6dSKonstantin Porotchkin 				element);
7176414dc6dSKonstantin Porotchkin 			goto exit_parse;
7186414dc6dSKonstantin Porotchkin 		}
7196414dc6dSKonstantin Porotchkin 	}
7206414dc6dSKonstantin Porotchkin 
7216414dc6dSKonstantin Porotchkin 	/* JTAG options */
7226414dc6dSKonstantin Porotchkin 	if (config_lookup_bool(&sec_cfg, "jtag.enable",
7236414dc6dSKonstantin Porotchkin 			       &cfg_int32) != CONFIG_TRUE) {
7246414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Error obtaining \"jtag.enable\" element. ");
7256414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Using default - FALSE\n");
7266414dc6dSKonstantin Porotchkin 		cfg_int32 = 0;
7276414dc6dSKonstantin Porotchkin 	}
7286414dc6dSKonstantin Porotchkin 	sec_opt->jtag_enable = cfg_int32;
7296414dc6dSKonstantin Porotchkin 
7306414dc6dSKonstantin Porotchkin 	if (config_lookup_int(&sec_cfg, "jtag.delay",
7316414dc6dSKonstantin Porotchkin 			      &cfg_int32) != CONFIG_TRUE) {
7326414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Error obtaining \"jtag.delay\" element. ");
7336414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Using default - 0us\n");
7346414dc6dSKonstantin Porotchkin 		cfg_int32 = 0;
7356414dc6dSKonstantin Porotchkin 	}
7366414dc6dSKonstantin Porotchkin 	sec_opt->jtag_delay = cfg_int32;
7376414dc6dSKonstantin Porotchkin 
7386414dc6dSKonstantin Porotchkin 	/* eFUSE option */
7396414dc6dSKonstantin Porotchkin 	if (config_lookup_bool(&sec_cfg, "efuse_disable",
7406414dc6dSKonstantin Porotchkin 			       &cfg_int32) != CONFIG_TRUE) {
7416414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Error obtaining \"efuse_disable\" element. ");
7426414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Using default - TRUE\n");
7436414dc6dSKonstantin Porotchkin 		cfg_int32 = 1;
7446414dc6dSKonstantin Porotchkin 	}
7456414dc6dSKonstantin Porotchkin 	sec_opt->efuse_disable = cfg_int32;
7466414dc6dSKonstantin Porotchkin 
7476414dc6dSKonstantin Porotchkin 	/* Box ID option */
7486414dc6dSKonstantin Porotchkin 	if (config_lookup_int(&sec_cfg, "box_id", &cfg_int32) != CONFIG_TRUE) {
7496414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Error obtaining \"box_id\" element. ");
7506414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Using default - 0x0\n");
7516414dc6dSKonstantin Porotchkin 		cfg_int32 = 0;
7526414dc6dSKonstantin Porotchkin 	}
7536414dc6dSKonstantin Porotchkin 	sec_opt->box_id = cfg_int32;
7546414dc6dSKonstantin Porotchkin 
7556414dc6dSKonstantin Porotchkin 	/* Flash ID option */
7566414dc6dSKonstantin Porotchkin 	if (config_lookup_int(&sec_cfg, "flash_id",
7576414dc6dSKonstantin Porotchkin 			      &cfg_int32) != CONFIG_TRUE) {
7586414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Error obtaining \"flash_id\" element. ");
7596414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Using default - 0x0\n");
7606414dc6dSKonstantin Porotchkin 		cfg_int32 = 0;
7616414dc6dSKonstantin Porotchkin 	}
7626414dc6dSKonstantin Porotchkin 	sec_opt->flash_id = cfg_int32;
7636414dc6dSKonstantin Porotchkin 
7646414dc6dSKonstantin Porotchkin 	/* CSK index option */
7656414dc6dSKonstantin Porotchkin 	if (config_lookup_int(&sec_cfg, "csk_key_index",
7666414dc6dSKonstantin Porotchkin 			      &cfg_int32) != CONFIG_TRUE) {
7676414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Error obtaining \"flash_id\" element. ");
7686414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Using default - 0x0\n");
7696414dc6dSKonstantin Porotchkin 		cfg_int32 = 0;
7706414dc6dSKonstantin Porotchkin 	}
7716414dc6dSKonstantin Porotchkin 	sec_opt->csk_index = cfg_int32;
7726414dc6dSKonstantin Porotchkin 
7736414dc6dSKonstantin Porotchkin 	/* Secure boot control array */
7746414dc6dSKonstantin Porotchkin 	control_array = config_lookup(&sec_cfg, "control");
7756414dc6dSKonstantin Porotchkin 	if (control_array != NULL) {
7766414dc6dSKonstantin Porotchkin 		array_sz = config_setting_length(control_array);
7776414dc6dSKonstantin Porotchkin 		if (array_sz == 0)
7786414dc6dSKonstantin Porotchkin 			fprintf(stderr, "The \"control\" array is empty!\n");
7796414dc6dSKonstantin Porotchkin 	} else {
7806414dc6dSKonstantin Porotchkin 		fprintf(stderr, "The \"control\" is undefined!\n");
7816414dc6dSKonstantin Porotchkin 		array_sz = 0;
7826414dc6dSKonstantin Porotchkin 	}
7836414dc6dSKonstantin Porotchkin 
7846414dc6dSKonstantin Porotchkin 	for (element = 0; element < CP_CTRL_EL_ARRAY_SZ; element++) {
7856414dc6dSKonstantin Porotchkin 		sec_opt->cp_ctrl_arr[element] =
7866414dc6dSKonstantin Porotchkin 			config_setting_get_int_elem(control_array, element * 2);
7876414dc6dSKonstantin Porotchkin 		sec_opt->cp_efuse_arr[element] =
7886414dc6dSKonstantin Porotchkin 			config_setting_get_int_elem(control_array,
7896414dc6dSKonstantin Porotchkin 						    element * 2 + 1);
7906414dc6dSKonstantin Porotchkin 	}
7916414dc6dSKonstantin Porotchkin 
7926414dc6dSKonstantin Porotchkin 	opts.sec_opts = sec_opt;
7936414dc6dSKonstantin Porotchkin 	rval = 0;
7946414dc6dSKonstantin Porotchkin 
7956414dc6dSKonstantin Porotchkin exit_parse:
7966414dc6dSKonstantin Porotchkin 	config_destroy(&sec_cfg);
7976414dc6dSKonstantin Porotchkin 	if (sec_opt && (rval != 0))
7986414dc6dSKonstantin Porotchkin 		free(sec_opt);
7996414dc6dSKonstantin Porotchkin 	return rval;
8006414dc6dSKonstantin Porotchkin } /* end of parse_sec_config_file */
8016414dc6dSKonstantin Porotchkin 
format_sec_ext(char * filename,FILE * out_fd)8026414dc6dSKonstantin Porotchkin int format_sec_ext(char *filename, FILE *out_fd)
8036414dc6dSKonstantin Porotchkin {
8046414dc6dSKonstantin Porotchkin 	ext_header_t	header;
8056414dc6dSKonstantin Porotchkin 	sec_entry_t	sec_ext;
8066414dc6dSKonstantin Porotchkin 	int		index;
8076414dc6dSKonstantin Porotchkin 	int		written;
8086414dc6dSKonstantin Porotchkin 
8096414dc6dSKonstantin Porotchkin #define DER_BUF_SZ	1600
8106414dc6dSKonstantin Porotchkin 
8116414dc6dSKonstantin Porotchkin 	/* First, parse the configuration file */
8126414dc6dSKonstantin Porotchkin 	if (parse_sec_config_file(filename)) {
8136414dc6dSKonstantin Porotchkin 		fprintf(stderr,
8146414dc6dSKonstantin Porotchkin 			"failed parsing configuration file %s\n", filename);
8156414dc6dSKonstantin Porotchkin 		return 1;
8166414dc6dSKonstantin Porotchkin 	}
8176414dc6dSKonstantin Porotchkin 
8186414dc6dSKonstantin Porotchkin 	/* Everything except signatures can be created at this stage */
8196414dc6dSKonstantin Porotchkin 	header.type = EXT_TYPE_SECURITY;
8206414dc6dSKonstantin Porotchkin 	header.offset = 0;
8216414dc6dSKonstantin Porotchkin 	header.size = sizeof(sec_entry_t);
8226414dc6dSKonstantin Porotchkin 	header.reserved = 0;
8236414dc6dSKonstantin Porotchkin 
8246414dc6dSKonstantin Porotchkin 	/* Bring up RSA context and read private keys from their files */
8256414dc6dSKonstantin Porotchkin 	for (index = 0; index < (CSK_ARR_SZ + 1); index++) {
8266414dc6dSKonstantin Porotchkin 		/* for every private key file */
8276414dc6dSKonstantin Porotchkin 		mbedtls_pk_context	*pk_ctx = (index == CSK_ARR_SZ) ?
8286414dc6dSKonstantin Porotchkin 					&opts.sec_opts->kak_pk :
8296414dc6dSKonstantin Porotchkin 					&opts.sec_opts->csk_pk[index];
8306414dc6dSKonstantin Porotchkin 		char		*fname = (index == CSK_ARR_SZ) ?
8316414dc6dSKonstantin Porotchkin 					opts.sec_opts->kak_key_file :
8326414dc6dSKonstantin Porotchkin 					opts.sec_opts->csk_key_file[index];
8336414dc6dSKonstantin Porotchkin 		uint8_t		*out_der_key = (index == CSK_ARR_SZ) ?
8346414dc6dSKonstantin Porotchkin 					sec_ext.kak_key :
8356414dc6dSKonstantin Porotchkin 					sec_ext.csk_keys[index];
8366414dc6dSKonstantin Porotchkin 		size_t		output_len;
8376414dc6dSKonstantin Porotchkin 		unsigned char	output_buf[DER_BUF_SZ];
8386414dc6dSKonstantin Porotchkin 		unsigned char	*der_buf_start;
8396414dc6dSKonstantin Porotchkin 
8406414dc6dSKonstantin Porotchkin 		/* Handle invalid/reserved file names */
8416414dc6dSKonstantin Porotchkin 		if (strncmp(CSK_ARR_EMPTY_FILE, fname,
8426414dc6dSKonstantin Porotchkin 			    strlen(CSK_ARR_EMPTY_FILE)) == 0) {
8436414dc6dSKonstantin Porotchkin 			if (opts.sec_opts->csk_index == index) {
8446414dc6dSKonstantin Porotchkin 				fprintf(stderr,
8456414dc6dSKonstantin Porotchkin 					"CSK file with index %d cannot be %s\n",
8466414dc6dSKonstantin Porotchkin 					index, CSK_ARR_EMPTY_FILE);
8476414dc6dSKonstantin Porotchkin 				return 1;
8486414dc6dSKonstantin Porotchkin 			} else if (index == CSK_ARR_SZ) {
8496414dc6dSKonstantin Porotchkin 				fprintf(stderr, "KAK file name cannot be %s\n",
8506414dc6dSKonstantin Porotchkin 					CSK_ARR_EMPTY_FILE);
8516414dc6dSKonstantin Porotchkin 				return 1;
8526414dc6dSKonstantin Porotchkin 			}
8536414dc6dSKonstantin Porotchkin 			/* this key will be empty in CSK array */
8546414dc6dSKonstantin Porotchkin 			continue;
8556414dc6dSKonstantin Porotchkin 		}
8566414dc6dSKonstantin Porotchkin 
8576414dc6dSKonstantin Porotchkin 		mbedtls_pk_init(pk_ctx);
8586414dc6dSKonstantin Porotchkin 		/* Read the private RSA key into the context
8596414dc6dSKonstantin Porotchkin 		 * and verify it (no password)
8606414dc6dSKonstantin Porotchkin 		 */
8616414dc6dSKonstantin Porotchkin 		if (mbedtls_pk_parse_keyfile(pk_ctx, fname, "") != 0) {
8626414dc6dSKonstantin Porotchkin 			fprintf(stderr,
8636414dc6dSKonstantin Porotchkin 				"Cannot read RSA private key file %s\n", fname);
8646414dc6dSKonstantin Porotchkin 			return 1;
8656414dc6dSKonstantin Porotchkin 		}
8666414dc6dSKonstantin Porotchkin 
8676414dc6dSKonstantin Porotchkin 		/* Create a public key out of private one
8686414dc6dSKonstantin Porotchkin 		 * and store it in DER format
8696414dc6dSKonstantin Porotchkin 		 */
8706414dc6dSKonstantin Porotchkin 		output_len = mbedtls_pk_write_pubkey_der(pk_ctx,
8716414dc6dSKonstantin Porotchkin 							 output_buf,
8726414dc6dSKonstantin Porotchkin 							 DER_BUF_SZ);
8736414dc6dSKonstantin Porotchkin 		if (output_len < 0) {
8746414dc6dSKonstantin Porotchkin 			fprintf(stderr,
8756414dc6dSKonstantin Porotchkin 				"Failed to create DER coded PUB key (%s)\n",
8766414dc6dSKonstantin Porotchkin 				fname);
8776414dc6dSKonstantin Porotchkin 			return 1;
8786414dc6dSKonstantin Porotchkin 		}
879a79df348SKonstantin Porotchkin 
8806414dc6dSKonstantin Porotchkin 		/* Data in the output buffer is aligned to the buffer end */
8816414dc6dSKonstantin Porotchkin 		der_buf_start = output_buf + sizeof(output_buf) - output_len;
8826414dc6dSKonstantin Porotchkin 		/* In the header DER data is aligned
8836414dc6dSKonstantin Porotchkin 		 * to the start of appropriate field
8846414dc6dSKonstantin Porotchkin 		 */
885a79df348SKonstantin Porotchkin 		bzero(out_der_key, MAX_RSA_DER_BYTE_LEN);
8866414dc6dSKonstantin Porotchkin 		memcpy(out_der_key, der_buf_start, output_len);
8876414dc6dSKonstantin Porotchkin 
8886414dc6dSKonstantin Porotchkin 	} /* for every private key file */
8896414dc6dSKonstantin Porotchkin 
8906414dc6dSKonstantin Porotchkin 	/* The CSK block signature can be created here */
8916414dc6dSKonstantin Porotchkin 	if (create_rsa_signature(&opts.sec_opts->kak_pk,
8926414dc6dSKonstantin Porotchkin 				 &sec_ext.csk_keys[0][0],
8936414dc6dSKonstantin Porotchkin 				 sizeof(sec_ext.csk_keys),
8946414dc6dSKonstantin Porotchkin 				 opts.sec_opts->csk_key_file[
8956414dc6dSKonstantin Porotchkin 					 opts.sec_opts->csk_index],
8966414dc6dSKonstantin Porotchkin 				 sec_ext.csk_sign) != 0) {
8976414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Failed to sign CSK keys block!\n");
8986414dc6dSKonstantin Porotchkin 		return 1;
8996414dc6dSKonstantin Porotchkin 	}
900a79df348SKonstantin Porotchkin 
9016414dc6dSKonstantin Porotchkin 	/* Check that everything is correct */
902a79df348SKonstantin Porotchkin 	if (verify_rsa_signature(sec_ext.kak_key,
903a79df348SKonstantin Porotchkin 				 MAX_RSA_DER_BYTE_LEN,
9046414dc6dSKonstantin Porotchkin 				 &sec_ext.csk_keys[0][0],
9056414dc6dSKonstantin Porotchkin 				 sizeof(sec_ext.csk_keys),
9066414dc6dSKonstantin Porotchkin 				 opts.sec_opts->kak_key_file,
9076414dc6dSKonstantin Porotchkin 				 sec_ext.csk_sign) != 0) {
9086414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Failed to verify CSK keys block signature!\n");
9096414dc6dSKonstantin Porotchkin 		return 1;
9106414dc6dSKonstantin Porotchkin 	}
9116414dc6dSKonstantin Porotchkin 
9126414dc6dSKonstantin Porotchkin 	/* AES encryption stuff */
9136414dc6dSKonstantin Porotchkin 	if (strlen(opts.sec_opts->aes_key_file) != 0) {
9146414dc6dSKonstantin Porotchkin 		FILE		*in_fd;
9156414dc6dSKonstantin Porotchkin 
9166414dc6dSKonstantin Porotchkin 		in_fd = fopen(opts.sec_opts->aes_key_file, "rb");
9176414dc6dSKonstantin Porotchkin 		if (in_fd == NULL) {
9186414dc6dSKonstantin Porotchkin 			fprintf(stderr, "Failed to open AES key file %s\n",
9196414dc6dSKonstantin Porotchkin 				opts.sec_opts->aes_key_file);
9206414dc6dSKonstantin Porotchkin 			return 1;
9216414dc6dSKonstantin Porotchkin 		}
9226414dc6dSKonstantin Porotchkin 
9236414dc6dSKonstantin Porotchkin 		/* Read the AES key in ASCII format byte by byte */
9246414dc6dSKonstantin Porotchkin 		for (index = 0; index < AES_KEY_BYTE_LEN; index++) {
9256414dc6dSKonstantin Porotchkin 			if (fscanf(in_fd, "%02hhx",
9266414dc6dSKonstantin Porotchkin 			    opts.sec_opts->aes_key + index) != 1) {
9276414dc6dSKonstantin Porotchkin 				fprintf(stderr,
9286414dc6dSKonstantin Porotchkin 					"Failed to read AES key byte %d ",
9296414dc6dSKonstantin Porotchkin 					index);
9306414dc6dSKonstantin Porotchkin 				fprintf(stderr,
9316414dc6dSKonstantin Porotchkin 					"from file %s\n",
9326414dc6dSKonstantin Porotchkin 					opts.sec_opts->aes_key_file);
9336414dc6dSKonstantin Porotchkin 				fclose(in_fd);
9346414dc6dSKonstantin Porotchkin 				return 1;
9356414dc6dSKonstantin Porotchkin 			}
9366414dc6dSKonstantin Porotchkin 		}
9376414dc6dSKonstantin Porotchkin 		fclose(in_fd);
9386414dc6dSKonstantin Porotchkin 		sec_ext.encrypt_en = 1;
9396414dc6dSKonstantin Porotchkin 	} else {
9406414dc6dSKonstantin Porotchkin 		sec_ext.encrypt_en = 0;
9416414dc6dSKonstantin Porotchkin 	}
9426414dc6dSKonstantin Porotchkin 
9436414dc6dSKonstantin Porotchkin 	/* Fill the rest of the trusted boot extension fields */
9446414dc6dSKonstantin Porotchkin 	sec_ext.box_id		= opts.sec_opts->box_id;
9456414dc6dSKonstantin Porotchkin 	sec_ext.flash_id	= opts.sec_opts->flash_id;
9466414dc6dSKonstantin Porotchkin 	sec_ext.efuse_dis	= opts.sec_opts->efuse_disable;
9476414dc6dSKonstantin Porotchkin 	sec_ext.jtag_delay	= opts.sec_opts->jtag_delay;
9486414dc6dSKonstantin Porotchkin 	sec_ext.jtag_en		= opts.sec_opts->jtag_enable;
9496414dc6dSKonstantin Porotchkin 
9506414dc6dSKonstantin Porotchkin 	memcpy(sec_ext.cp_ctrl_arr,
9516414dc6dSKonstantin Porotchkin 	       opts.sec_opts->cp_ctrl_arr,
9526414dc6dSKonstantin Porotchkin 	       sizeof(uint32_t) * CP_CTRL_EL_ARRAY_SZ);
9536414dc6dSKonstantin Porotchkin 	memcpy(sec_ext.cp_efuse_arr,
9546414dc6dSKonstantin Porotchkin 	       opts.sec_opts->cp_efuse_arr,
9556414dc6dSKonstantin Porotchkin 	       sizeof(uint32_t) * CP_CTRL_EL_ARRAY_SZ);
9566414dc6dSKonstantin Porotchkin 
9576414dc6dSKonstantin Porotchkin 	/* Write the resulting extension to file
9586414dc6dSKonstantin Porotchkin 	 * (image and header signature fields are still empty)
9596414dc6dSKonstantin Porotchkin 	 */
9606414dc6dSKonstantin Porotchkin 
9616414dc6dSKonstantin Porotchkin 	/* Write extension header */
9626414dc6dSKonstantin Porotchkin 	written = fwrite(&header, sizeof(ext_header_t), 1, out_fd);
9636414dc6dSKonstantin Porotchkin 	if (written != 1) {
9646414dc6dSKonstantin Porotchkin 		fprintf(stderr,
9656414dc6dSKonstantin Porotchkin 			"Failed to write SEC extension header to the file\n");
9666414dc6dSKonstantin Porotchkin 		return 1;
9676414dc6dSKonstantin Porotchkin 	}
9686414dc6dSKonstantin Porotchkin 	/* Write extension body */
9696414dc6dSKonstantin Porotchkin 	written = fwrite(&sec_ext, sizeof(sec_entry_t), 1, out_fd);
9706414dc6dSKonstantin Porotchkin 	if (written != 1) {
9716414dc6dSKonstantin Porotchkin 		fprintf(stderr,
9726414dc6dSKonstantin Porotchkin 			"Failed to write SEC extension body to the file\n");
9736414dc6dSKonstantin Porotchkin 		return 1;
9746414dc6dSKonstantin Porotchkin 	}
9756414dc6dSKonstantin Porotchkin 
9766414dc6dSKonstantin Porotchkin 	return 0;
9776414dc6dSKonstantin Porotchkin }
9786414dc6dSKonstantin Porotchkin 
9796414dc6dSKonstantin Porotchkin /*******************************************************************************
9806414dc6dSKonstantin Porotchkin  *    finalize_secure_ext
9816414dc6dSKonstantin Porotchkin  *          Make final changes to secure extension - calculate image and header
9826414dc6dSKonstantin Porotchkin  *          signatures and encrypt the image if needed.
9836414dc6dSKonstantin Porotchkin  *          The main header checksum and image size fields updated accordingly
9846414dc6dSKonstantin Porotchkin  *    INPUT:
9856414dc6dSKonstantin Porotchkin  *          header       Main header
9866414dc6dSKonstantin Porotchkin  *          prolog_buf   the entire prolog buffer
9876414dc6dSKonstantin Porotchkin  *          prolog_size  prolog buffer length
9886414dc6dSKonstantin Porotchkin  *          image_buf    buffer containing the input binary image
9896414dc6dSKonstantin Porotchkin  *          image_size   image buffer size.
9906414dc6dSKonstantin Porotchkin  *    OUTPUT:
9916414dc6dSKonstantin Porotchkin  *          none
9926414dc6dSKonstantin Porotchkin  *    RETURN:
9936414dc6dSKonstantin Porotchkin  *          0 on success
9946414dc6dSKonstantin Porotchkin  */
finalize_secure_ext(header_t * header,uint8_t * prolog_buf,uint32_t prolog_size,uint8_t * image_buf,int image_size)9956414dc6dSKonstantin Porotchkin int finalize_secure_ext(header_t *header,
9966414dc6dSKonstantin Porotchkin 			uint8_t *prolog_buf, uint32_t prolog_size,
9976414dc6dSKonstantin Porotchkin 			uint8_t *image_buf, int image_size)
9986414dc6dSKonstantin Porotchkin {
9996414dc6dSKonstantin Porotchkin 	int		cur_ext, offset;
10006414dc6dSKonstantin Porotchkin 	uint8_t		*final_image = image_buf;
10016414dc6dSKonstantin Porotchkin 	uint32_t	final_image_sz = image_size;
10026414dc6dSKonstantin Porotchkin 	uint8_t		hdr_sign[RSA_SIGN_BYTE_LEN];
10036414dc6dSKonstantin Porotchkin 	sec_entry_t	*sec_ext = 0;
10046414dc6dSKonstantin Porotchkin 
10056414dc6dSKonstantin Porotchkin 	/* Find the Trusted Boot Header between available extensions */
10066414dc6dSKonstantin Porotchkin 	for (cur_ext = 0, offset = sizeof(header_t);
10076414dc6dSKonstantin Porotchkin 	     cur_ext < header->ext_count; cur_ext++) {
10086414dc6dSKonstantin Porotchkin 		ext_header_t *ext_hdr = (ext_header_t *)(prolog_buf + offset);
10096414dc6dSKonstantin Porotchkin 
10106414dc6dSKonstantin Porotchkin 		if (ext_hdr->type == EXT_TYPE_SECURITY) {
10116414dc6dSKonstantin Porotchkin 			sec_ext = (sec_entry_t *)(prolog_buf + offset +
10126414dc6dSKonstantin Porotchkin 				   sizeof(ext_header_t) + ext_hdr->offset);
10136414dc6dSKonstantin Porotchkin 			break;
10146414dc6dSKonstantin Porotchkin 		}
10156414dc6dSKonstantin Porotchkin 
10166414dc6dSKonstantin Porotchkin 		offset += sizeof(ext_header_t);
10176414dc6dSKonstantin Porotchkin 		/* If offset is Zero, the extension follows its header */
10186414dc6dSKonstantin Porotchkin 		if (ext_hdr->offset == 0)
10196414dc6dSKonstantin Porotchkin 			offset += ext_hdr->size;
10206414dc6dSKonstantin Porotchkin 	}
10216414dc6dSKonstantin Porotchkin 
10226414dc6dSKonstantin Porotchkin 	if (sec_ext == 0) {
10236414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Error: No Trusted Boot extension found!\n");
10246414dc6dSKonstantin Porotchkin 		return -1;
10256414dc6dSKonstantin Porotchkin 	}
10266414dc6dSKonstantin Porotchkin 
10276414dc6dSKonstantin Porotchkin 	if (sec_ext->encrypt_en) {
10286414dc6dSKonstantin Porotchkin 		/* Encrypt the image if needed */
10296414dc6dSKonstantin Porotchkin 		fprintf(stdout, "Encrypting the image...\n");
10306414dc6dSKonstantin Porotchkin 
10316414dc6dSKonstantin Porotchkin 		if (image_encrypt(image_buf, image_size) != 0) {
10326414dc6dSKonstantin Porotchkin 			fprintf(stderr, "Failed to encrypt the image!\n");
10336414dc6dSKonstantin Porotchkin 			return -1;
10346414dc6dSKonstantin Porotchkin 		}
10356414dc6dSKonstantin Porotchkin 
10366414dc6dSKonstantin Porotchkin 		/* Image size and checksum should be updated after encryption.
10376414dc6dSKonstantin Porotchkin 		 * This way the image could be verified by the BootROM
10386414dc6dSKonstantin Porotchkin 		 * before decryption.
10396414dc6dSKonstantin Porotchkin 		 */
10406414dc6dSKonstantin Porotchkin 		final_image = opts.sec_opts->encrypted_image;
10416414dc6dSKonstantin Porotchkin 		final_image_sz = opts.sec_opts->enc_image_sz;
10426414dc6dSKonstantin Porotchkin 
10436414dc6dSKonstantin Porotchkin 		header->boot_image_size = final_image_sz;
10446414dc6dSKonstantin Porotchkin 		header->boot_image_checksum =
10456414dc6dSKonstantin Porotchkin 			checksum32((uint32_t *)final_image, final_image_sz);
10466414dc6dSKonstantin Porotchkin 	} /* AES encryption */
10476414dc6dSKonstantin Porotchkin 
10486414dc6dSKonstantin Porotchkin 	/* Create the image signature first, since it will be later
10496414dc6dSKonstantin Porotchkin 	 * signed along with the header signature
10506414dc6dSKonstantin Porotchkin 	 */
10516414dc6dSKonstantin Porotchkin 	if (create_rsa_signature(&opts.sec_opts->csk_pk[
10526414dc6dSKonstantin Porotchkin 					opts.sec_opts->csk_index],
10536414dc6dSKonstantin Porotchkin 				 final_image, final_image_sz,
10546414dc6dSKonstantin Porotchkin 				 opts.sec_opts->csk_key_file[
10556414dc6dSKonstantin Porotchkin 					opts.sec_opts->csk_index],
10566414dc6dSKonstantin Porotchkin 				 sec_ext->image_sign) != 0) {
10576414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Failed to sign image!\n");
10586414dc6dSKonstantin Porotchkin 		return -1;
10596414dc6dSKonstantin Porotchkin 	}
10606414dc6dSKonstantin Porotchkin 	/* Check that the image signature is correct */
10616414dc6dSKonstantin Porotchkin 	if (verify_rsa_signature(sec_ext->csk_keys[opts.sec_opts->csk_index],
10626414dc6dSKonstantin Porotchkin 				 MAX_RSA_DER_BYTE_LEN,
10636414dc6dSKonstantin Porotchkin 				 final_image, final_image_sz,
10646414dc6dSKonstantin Porotchkin 				 opts.sec_opts->csk_key_file[
10656414dc6dSKonstantin Porotchkin 					 opts.sec_opts->csk_index],
10666414dc6dSKonstantin Porotchkin 				 sec_ext->image_sign) != 0) {
10676414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Failed to verify image signature!\n");
10686414dc6dSKonstantin Porotchkin 		return -1;
10696414dc6dSKonstantin Porotchkin 	}
10706414dc6dSKonstantin Porotchkin 
10716414dc6dSKonstantin Porotchkin 	/* Sign the headers and all the extensions block
10726414dc6dSKonstantin Porotchkin 	 * when the header signature field is empty
10736414dc6dSKonstantin Porotchkin 	 */
10746414dc6dSKonstantin Porotchkin 	if (create_rsa_signature(&opts.sec_opts->csk_pk[
10756414dc6dSKonstantin Porotchkin 					 opts.sec_opts->csk_index],
10766414dc6dSKonstantin Porotchkin 				 prolog_buf, prolog_size,
10776414dc6dSKonstantin Porotchkin 				 opts.sec_opts->csk_key_file[
10786414dc6dSKonstantin Porotchkin 					 opts.sec_opts->csk_index],
10796414dc6dSKonstantin Porotchkin 				 hdr_sign) != 0) {
10806414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Failed to sign header!\n");
10816414dc6dSKonstantin Porotchkin 		return -1;
10826414dc6dSKonstantin Porotchkin 	}
10836414dc6dSKonstantin Porotchkin 	/* Check that the header signature is correct */
10846414dc6dSKonstantin Porotchkin 	if (verify_rsa_signature(sec_ext->csk_keys[opts.sec_opts->csk_index],
10856414dc6dSKonstantin Porotchkin 				 MAX_RSA_DER_BYTE_LEN,
10866414dc6dSKonstantin Porotchkin 				 prolog_buf, prolog_size,
10876414dc6dSKonstantin Porotchkin 				 opts.sec_opts->csk_key_file[
10886414dc6dSKonstantin Porotchkin 					 opts.sec_opts->csk_index],
10896414dc6dSKonstantin Porotchkin 				 hdr_sign) != 0) {
10906414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Failed to verify header signature!\n");
10916414dc6dSKonstantin Porotchkin 		return -1;
10926414dc6dSKonstantin Porotchkin 	}
10936414dc6dSKonstantin Porotchkin 
10946414dc6dSKonstantin Porotchkin 	/* Finally, copy the header signature into the trusted boot extension */
10956414dc6dSKonstantin Porotchkin 	memcpy(sec_ext->header_sign, hdr_sign, RSA_SIGN_BYTE_LEN);
10966414dc6dSKonstantin Porotchkin 
10976414dc6dSKonstantin Porotchkin 	return 0;
10986414dc6dSKonstantin Porotchkin }
10996414dc6dSKonstantin Porotchkin 
11006414dc6dSKonstantin Porotchkin #endif /* CONFIG_MVEBU_SECURE_BOOT */
11016414dc6dSKonstantin Porotchkin 
11026414dc6dSKonstantin Porotchkin 
11036414dc6dSKonstantin Porotchkin #define FMT_HEX		0
11046414dc6dSKonstantin Porotchkin #define FMT_DEC		1
11056414dc6dSKonstantin Porotchkin #define FMT_BIN		2
11066414dc6dSKonstantin Porotchkin #define FMT_NONE	3
11076414dc6dSKonstantin Porotchkin 
do_print_field(unsigned int value,char * name,int start,int size,int format)11086414dc6dSKonstantin Porotchkin void do_print_field(unsigned int value, char *name,
11096414dc6dSKonstantin Porotchkin 		    int start, int size, int format)
11106414dc6dSKonstantin Porotchkin {
11116414dc6dSKonstantin Porotchkin 	fprintf(stdout, "[0x%05x : 0x%05x]  %-26s",
11126414dc6dSKonstantin Porotchkin 		start, start + size - 1, name);
11136414dc6dSKonstantin Porotchkin 
11146414dc6dSKonstantin Porotchkin 	switch (format) {
11156414dc6dSKonstantin Porotchkin 	case FMT_HEX:
11166414dc6dSKonstantin Porotchkin 		printf("0x%x\n", value);
11176414dc6dSKonstantin Porotchkin 		break;
11186414dc6dSKonstantin Porotchkin 	case FMT_DEC:
11196414dc6dSKonstantin Porotchkin 		printf("%d\n", value);
11206414dc6dSKonstantin Porotchkin 		break;
11216414dc6dSKonstantin Porotchkin 	default:
11226414dc6dSKonstantin Porotchkin 		printf("\n");
11236414dc6dSKonstantin Porotchkin 		break;
11246414dc6dSKonstantin Porotchkin 	}
11256414dc6dSKonstantin Porotchkin }
11266414dc6dSKonstantin Porotchkin 
11276414dc6dSKonstantin Porotchkin #define print_field(st, type, field, hex, base) \
11286414dc6dSKonstantin Porotchkin 			do_print_field((int)st->field, #field, \
11296414dc6dSKonstantin Porotchkin 			base + offsetof(type, field), sizeof(st->field), hex)
11306414dc6dSKonstantin Porotchkin 
print_header(uint8_t * buf,int base)11316414dc6dSKonstantin Porotchkin int print_header(uint8_t *buf, int base)
11326414dc6dSKonstantin Porotchkin {
11336414dc6dSKonstantin Porotchkin 	header_t *main_hdr;
11346414dc6dSKonstantin Porotchkin 
11356414dc6dSKonstantin Porotchkin 	main_hdr = (header_t *)buf;
11366414dc6dSKonstantin Porotchkin 
11376414dc6dSKonstantin Porotchkin 	fprintf(stdout, "########### Header ##############\n");
11386414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, magic, FMT_HEX, base);
11396414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, prolog_size, FMT_DEC, base);
11406414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, prolog_checksum, FMT_HEX, base);
11416414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, boot_image_size, FMT_DEC, base);
11426414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, boot_image_checksum, FMT_HEX, base);
11436414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, rsrvd0, FMT_HEX, base);
11446414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, load_addr, FMT_HEX, base);
11456414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, exec_addr, FMT_HEX, base);
11466414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, uart_cfg, FMT_HEX, base);
11476414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, baudrate, FMT_HEX, base);
11486414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, ext_count, FMT_DEC, base);
11496414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, aux_flags, FMT_HEX, base);
11506414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, io_arg_0, FMT_HEX, base);
11516414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, io_arg_1, FMT_HEX, base);
11526414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, io_arg_2, FMT_HEX, base);
11536414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, io_arg_3, FMT_HEX, base);
11546414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, rsrvd1, FMT_HEX, base);
11556414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, rsrvd2, FMT_HEX, base);
11566414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, rsrvd3, FMT_HEX, base);
11576414dc6dSKonstantin Porotchkin 
11586414dc6dSKonstantin Porotchkin 	return sizeof(header_t);
11596414dc6dSKonstantin Porotchkin }
11606414dc6dSKonstantin Porotchkin 
print_ext_hdr(ext_header_t * ext_hdr,int base)11616414dc6dSKonstantin Porotchkin int print_ext_hdr(ext_header_t *ext_hdr, int base)
11626414dc6dSKonstantin Porotchkin {
11636414dc6dSKonstantin Porotchkin 	print_field(ext_hdr, ext_header_t, type, FMT_HEX, base);
11646414dc6dSKonstantin Porotchkin 	print_field(ext_hdr, ext_header_t, offset, FMT_HEX, base);
11656414dc6dSKonstantin Porotchkin 	print_field(ext_hdr, ext_header_t, reserved, FMT_HEX, base);
11666414dc6dSKonstantin Porotchkin 	print_field(ext_hdr, ext_header_t, size, FMT_DEC, base);
11676414dc6dSKonstantin Porotchkin 
11686414dc6dSKonstantin Porotchkin 	return base + sizeof(ext_header_t);
11696414dc6dSKonstantin Porotchkin }
11706414dc6dSKonstantin Porotchkin 
print_sec_ext(ext_header_t * ext_hdr,int base)11716414dc6dSKonstantin Porotchkin void print_sec_ext(ext_header_t *ext_hdr, int base)
11726414dc6dSKonstantin Porotchkin {
11736414dc6dSKonstantin Porotchkin 	sec_entry_t	*sec_entry;
11746414dc6dSKonstantin Porotchkin 	uint32_t	new_base;
11756414dc6dSKonstantin Porotchkin 
11766414dc6dSKonstantin Porotchkin 	fprintf(stdout, "\n########### Secure extension ###########\n");
11776414dc6dSKonstantin Porotchkin 
11786414dc6dSKonstantin Porotchkin 	new_base = print_ext_hdr(ext_hdr, base);
11796414dc6dSKonstantin Porotchkin 
11806414dc6dSKonstantin Porotchkin 	sec_entry = (sec_entry_t *)(ext_hdr + 1);
11816414dc6dSKonstantin Porotchkin 
11826414dc6dSKonstantin Porotchkin 	do_print_field(0, "KAK key", new_base, MAX_RSA_DER_BYTE_LEN, FMT_NONE);
11836414dc6dSKonstantin Porotchkin 	new_base += MAX_RSA_DER_BYTE_LEN;
11846414dc6dSKonstantin Porotchkin 	print_field(sec_entry, sec_entry_t, jtag_delay, FMT_DEC, base);
11856414dc6dSKonstantin Porotchkin 	print_field(sec_entry, sec_entry_t, box_id, FMT_HEX, base);
11866414dc6dSKonstantin Porotchkin 	print_field(sec_entry, sec_entry_t, flash_id, FMT_HEX, base);
11876414dc6dSKonstantin Porotchkin 	print_field(sec_entry, sec_entry_t, encrypt_en, FMT_DEC, base);
11886414dc6dSKonstantin Porotchkin 	print_field(sec_entry, sec_entry_t, efuse_dis, FMT_DEC, base);
11896414dc6dSKonstantin Porotchkin 	new_base += 6 * sizeof(uint32_t);
11906414dc6dSKonstantin Porotchkin 	do_print_field(0, "header signature",
11916414dc6dSKonstantin Porotchkin 		       new_base, RSA_SIGN_BYTE_LEN, FMT_NONE);
11926414dc6dSKonstantin Porotchkin 	new_base += RSA_SIGN_BYTE_LEN;
11936414dc6dSKonstantin Porotchkin 	do_print_field(0, "image signature",
11946414dc6dSKonstantin Porotchkin 		       new_base, RSA_SIGN_BYTE_LEN, FMT_NONE);
11956414dc6dSKonstantin Porotchkin 	new_base += RSA_SIGN_BYTE_LEN;
11966414dc6dSKonstantin Porotchkin 	do_print_field(0, "CSK keys", new_base,
11976414dc6dSKonstantin Porotchkin 		       CSK_ARR_SZ * MAX_RSA_DER_BYTE_LEN, FMT_NONE);
11986414dc6dSKonstantin Porotchkin 	new_base += CSK_ARR_SZ * MAX_RSA_DER_BYTE_LEN;
11996414dc6dSKonstantin Porotchkin 	do_print_field(0, "CSK block signature",
12006414dc6dSKonstantin Porotchkin 		       new_base, RSA_SIGN_BYTE_LEN, FMT_NONE);
12016414dc6dSKonstantin Porotchkin 	new_base += RSA_SIGN_BYTE_LEN;
12026414dc6dSKonstantin Porotchkin 	do_print_field(0, "control", new_base,
12036414dc6dSKonstantin Porotchkin 		       CP_CTRL_EL_ARRAY_SZ * 2, FMT_NONE);
12046414dc6dSKonstantin Porotchkin 
12056414dc6dSKonstantin Porotchkin }
12066414dc6dSKonstantin Porotchkin 
print_bin_ext(ext_header_t * ext_hdr,int base)12076414dc6dSKonstantin Porotchkin void print_bin_ext(ext_header_t *ext_hdr, int base)
12086414dc6dSKonstantin Porotchkin {
12096414dc6dSKonstantin Porotchkin 	fprintf(stdout, "\n########### Binary extension ###########\n");
12106414dc6dSKonstantin Porotchkin 	base = print_ext_hdr(ext_hdr, base);
12116414dc6dSKonstantin Porotchkin 	do_print_field(0, "binary image", base, ext_hdr->size, FMT_NONE);
12126414dc6dSKonstantin Porotchkin }
12136414dc6dSKonstantin Porotchkin 
print_extension(void * buf,int base,int count,int ext_size)12146414dc6dSKonstantin Porotchkin int print_extension(void *buf, int base, int count, int ext_size)
12156414dc6dSKonstantin Porotchkin {
12166414dc6dSKonstantin Porotchkin 	ext_header_t *ext_hdr = buf;
12176414dc6dSKonstantin Porotchkin 	int pad = ext_size;
12186414dc6dSKonstantin Porotchkin 	int curr_size;
12196414dc6dSKonstantin Porotchkin 
12206414dc6dSKonstantin Porotchkin 	while (count--) {
12216414dc6dSKonstantin Porotchkin 		if (ext_hdr->type == EXT_TYPE_BINARY)
12226414dc6dSKonstantin Porotchkin 			print_bin_ext(ext_hdr, base);
12236414dc6dSKonstantin Porotchkin 		else if (ext_hdr->type == EXT_TYPE_SECURITY)
12246414dc6dSKonstantin Porotchkin 			print_sec_ext(ext_hdr, base);
12256414dc6dSKonstantin Porotchkin 
12266414dc6dSKonstantin Porotchkin 		curr_size = sizeof(ext_header_t) + ext_hdr->size;
12276414dc6dSKonstantin Porotchkin 		base += curr_size;
12286414dc6dSKonstantin Porotchkin 		pad  -= curr_size;
12296414dc6dSKonstantin Porotchkin 		ext_hdr = (ext_header_t *)((uintptr_t)ext_hdr + curr_size);
12306414dc6dSKonstantin Porotchkin 	}
12316414dc6dSKonstantin Porotchkin 
12326414dc6dSKonstantin Porotchkin 	if (pad)
12336414dc6dSKonstantin Porotchkin 		do_print_field(0, "padding", base, pad, FMT_NONE);
12346414dc6dSKonstantin Porotchkin 
12356414dc6dSKonstantin Porotchkin 	return ext_size;
12366414dc6dSKonstantin Porotchkin }
12376414dc6dSKonstantin Porotchkin 
parse_image(uint8_t * buf,int size)12386414dc6dSKonstantin Porotchkin int parse_image(uint8_t *buf, int size)
12396414dc6dSKonstantin Porotchkin {
12406414dc6dSKonstantin Porotchkin 	int base = 0;
12416414dc6dSKonstantin Porotchkin 	int ret = 1;
12426414dc6dSKonstantin Porotchkin 	header_t *main_hdr;
12436414dc6dSKonstantin Porotchkin 	uint32_t checksum, prolog_checksum;
12446414dc6dSKonstantin Porotchkin 
12456414dc6dSKonstantin Porotchkin 
12466414dc6dSKonstantin Porotchkin 	fprintf(stdout,
12476414dc6dSKonstantin Porotchkin 		"################### Prolog Start ######################\n\n");
12486414dc6dSKonstantin Porotchkin 	main_hdr = (header_t *)buf;
12496414dc6dSKonstantin Porotchkin 	base += print_header(buf, base);
12506414dc6dSKonstantin Porotchkin 
12516414dc6dSKonstantin Porotchkin 	if (main_hdr->ext_count)
12526414dc6dSKonstantin Porotchkin 		base += print_extension(buf + base, base,
12536414dc6dSKonstantin Porotchkin 					main_hdr->ext_count,
12546414dc6dSKonstantin Porotchkin 					main_hdr->prolog_size -
12556414dc6dSKonstantin Porotchkin 					sizeof(header_t));
12566414dc6dSKonstantin Porotchkin 
12576414dc6dSKonstantin Porotchkin 	if (base < main_hdr->prolog_size) {
12586414dc6dSKonstantin Porotchkin 		fprintf(stdout, "\n########### Padding ##############\n");
12596414dc6dSKonstantin Porotchkin 		do_print_field(0, "prolog padding",
12606414dc6dSKonstantin Porotchkin 			       base, main_hdr->prolog_size - base, FMT_HEX);
12616414dc6dSKonstantin Porotchkin 		base = main_hdr->prolog_size;
12626414dc6dSKonstantin Porotchkin 	}
12636414dc6dSKonstantin Porotchkin 	fprintf(stdout,
12646414dc6dSKonstantin Porotchkin 		"\n################### Prolog End ######################\n");
12656414dc6dSKonstantin Porotchkin 
12666414dc6dSKonstantin Porotchkin 	fprintf(stdout,
12676414dc6dSKonstantin Porotchkin 		"\n################### Boot image ######################\n");
12686414dc6dSKonstantin Porotchkin 
12696414dc6dSKonstantin Porotchkin 	do_print_field(0, "boot image", base, size - base - 4, FMT_NONE);
12706414dc6dSKonstantin Porotchkin 
12716414dc6dSKonstantin Porotchkin 	fprintf(stdout,
12726414dc6dSKonstantin Porotchkin 		"################### Image end ########################\n");
12736414dc6dSKonstantin Porotchkin 
12746414dc6dSKonstantin Porotchkin 	/* Check sanity for certain values */
12756414dc6dSKonstantin Porotchkin 	printf("\nChecking values:\n");
12766414dc6dSKonstantin Porotchkin 
12776414dc6dSKonstantin Porotchkin 	if (main_hdr->magic == MAIN_HDR_MAGIC) {
12786414dc6dSKonstantin Porotchkin 		fprintf(stdout, "Headers magic:    OK!\n");
12796414dc6dSKonstantin Porotchkin 	} else {
12806414dc6dSKonstantin Porotchkin 		fprintf(stderr,
12816414dc6dSKonstantin Porotchkin 			"\n****** ERROR: HEADER MAGIC 0x%08x != 0x%08x\n",
12826414dc6dSKonstantin Porotchkin 			main_hdr->magic, MAIN_HDR_MAGIC);
12836414dc6dSKonstantin Porotchkin 		goto error;
12846414dc6dSKonstantin Porotchkin 	}
12856414dc6dSKonstantin Porotchkin 
12866414dc6dSKonstantin Porotchkin 	/* headers checksum */
12876414dc6dSKonstantin Porotchkin 	/* clear the checksum field in header to calculate checksum */
12886414dc6dSKonstantin Porotchkin 	prolog_checksum = main_hdr->prolog_checksum;
12896414dc6dSKonstantin Porotchkin 	main_hdr->prolog_checksum = 0;
12906414dc6dSKonstantin Porotchkin 	checksum = checksum32((uint32_t *)buf, main_hdr->prolog_size);
12916414dc6dSKonstantin Porotchkin 
12926414dc6dSKonstantin Porotchkin 	if (checksum == prolog_checksum) {
12936414dc6dSKonstantin Porotchkin 		fprintf(stdout, "Headers checksum: OK!\n");
12946414dc6dSKonstantin Porotchkin 	} else {
12956414dc6dSKonstantin Porotchkin 		fprintf(stderr,
12966414dc6dSKonstantin Porotchkin 			"\n***** ERROR: BAD HEADER CHECKSUM 0x%08x != 0x%08x\n",
12976414dc6dSKonstantin Porotchkin 			checksum, prolog_checksum);
12986414dc6dSKonstantin Porotchkin 		goto error;
12996414dc6dSKonstantin Porotchkin 	}
13006414dc6dSKonstantin Porotchkin 
13016414dc6dSKonstantin Porotchkin 	/* boot image checksum */
13026414dc6dSKonstantin Porotchkin 	checksum = checksum32((uint32_t *)(buf + main_hdr->prolog_size),
13036414dc6dSKonstantin Porotchkin 			      main_hdr->boot_image_size);
13046414dc6dSKonstantin Porotchkin 	if (checksum == main_hdr->boot_image_checksum) {
13056414dc6dSKonstantin Porotchkin 		fprintf(stdout, "Image checksum:   OK!\n");
13066414dc6dSKonstantin Porotchkin 	} else {
13076414dc6dSKonstantin Porotchkin 		fprintf(stderr,
13086414dc6dSKonstantin Porotchkin 			"\n****** ERROR: BAD IMAGE CHECKSUM 0x%08x != 0x%08x\n",
13096414dc6dSKonstantin Porotchkin 			checksum, main_hdr->boot_image_checksum);
13106414dc6dSKonstantin Porotchkin 		goto error;
13116414dc6dSKonstantin Porotchkin 	}
13126414dc6dSKonstantin Porotchkin 
13136414dc6dSKonstantin Porotchkin #ifdef CONFIG_MVEBU_SECURE_BOOT
13146414dc6dSKonstantin Porotchkin 	/* RSA signatures */
13156414dc6dSKonstantin Porotchkin 	if (main_hdr->ext_count) {
13166414dc6dSKonstantin Porotchkin 		uint8_t		ext_num = main_hdr->ext_count;
13176414dc6dSKonstantin Porotchkin 		ext_header_t	*ext_hdr = (ext_header_t *)(main_hdr + 1);
13186414dc6dSKonstantin Porotchkin 		unsigned char	hash[32];
13196414dc6dSKonstantin Porotchkin 		int		i;
13206414dc6dSKonstantin Porotchkin 
13216414dc6dSKonstantin Porotchkin 		while (ext_num--) {
13226414dc6dSKonstantin Porotchkin 			if (ext_hdr->type == EXT_TYPE_SECURITY) {
13236414dc6dSKonstantin Porotchkin 				sec_entry_t  *sec_entry =
13246414dc6dSKonstantin Porotchkin 						(sec_entry_t *)(ext_hdr + 1);
13256414dc6dSKonstantin Porotchkin 
13266414dc6dSKonstantin Porotchkin 				ret = verify_secure_header_signatures(
13276414dc6dSKonstantin Porotchkin 							main_hdr, sec_entry);
13286414dc6dSKonstantin Porotchkin 				if (ret != 0) {
13296414dc6dSKonstantin Porotchkin 					fprintf(stderr,
13306414dc6dSKonstantin Porotchkin 						"\n****** FAILED TO VERIFY ");
13316414dc6dSKonstantin Porotchkin 					fprintf(stderr,
13326414dc6dSKonstantin Porotchkin 						"RSA SIGNATURES ********\n");
13336414dc6dSKonstantin Porotchkin 					goto error;
13346414dc6dSKonstantin Porotchkin 				}
13356414dc6dSKonstantin Porotchkin 
1336a79df348SKonstantin Porotchkin 				mbedtls_sha256_ret(sec_entry->kak_key,
13376414dc6dSKonstantin Porotchkin 					       MAX_RSA_DER_BYTE_LEN, hash, 0);
13386414dc6dSKonstantin Porotchkin 				fprintf(stdout,
13396414dc6dSKonstantin Porotchkin 					">>>>>>>>>> KAK KEY HASH >>>>>>>>>>\n");
13406414dc6dSKonstantin Porotchkin 				fprintf(stdout, "SHA256: ");
13416414dc6dSKonstantin Porotchkin 				for (i = 0; i < 32; i++)
13426414dc6dSKonstantin Porotchkin 					fprintf(stdout, "%02X", hash[i]);
13436414dc6dSKonstantin Porotchkin 
13446414dc6dSKonstantin Porotchkin 				fprintf(stdout,
13456414dc6dSKonstantin Porotchkin 					"\n<<<<<<<<< KAK KEY HASH <<<<<<<<<\n");
13466414dc6dSKonstantin Porotchkin 
13476414dc6dSKonstantin Porotchkin 				break;
13486414dc6dSKonstantin Porotchkin 			}
13496414dc6dSKonstantin Porotchkin 			ext_hdr =
13506414dc6dSKonstantin Porotchkin 				(ext_header_t *)((uint8_t *)(ext_hdr + 1) +
13516414dc6dSKonstantin Porotchkin 				 ext_hdr->size);
13526414dc6dSKonstantin Porotchkin 		}
13536414dc6dSKonstantin Porotchkin 	}
13546414dc6dSKonstantin Porotchkin #endif
13556414dc6dSKonstantin Porotchkin 
13566414dc6dSKonstantin Porotchkin 	ret = 0;
13576414dc6dSKonstantin Porotchkin error:
13586414dc6dSKonstantin Porotchkin 	return ret;
13596414dc6dSKonstantin Porotchkin }
13606414dc6dSKonstantin Porotchkin 
format_bin_ext(char * filename,FILE * out_fd)13616414dc6dSKonstantin Porotchkin int format_bin_ext(char *filename, FILE *out_fd)
13626414dc6dSKonstantin Porotchkin {
13636414dc6dSKonstantin Porotchkin 	ext_header_t header;
13646414dc6dSKonstantin Porotchkin 	FILE *in_fd;
13656414dc6dSKonstantin Porotchkin 	int size, written;
13666414dc6dSKonstantin Porotchkin 	int aligned_size, pad_bytes;
13676414dc6dSKonstantin Porotchkin 	char c;
13686414dc6dSKonstantin Porotchkin 
13696414dc6dSKonstantin Porotchkin 	in_fd = fopen(filename, "rb");
13706414dc6dSKonstantin Porotchkin 	if (in_fd == NULL) {
13716414dc6dSKonstantin Porotchkin 		fprintf(stderr, "failed to open bin extension file %s\n",
13726414dc6dSKonstantin Porotchkin 			filename);
13736414dc6dSKonstantin Porotchkin 		return 1;
13746414dc6dSKonstantin Porotchkin 	}
13756414dc6dSKonstantin Porotchkin 
13766414dc6dSKonstantin Porotchkin 	size = get_file_size(filename);
13776414dc6dSKonstantin Porotchkin 	if (size <= 0) {
13786414dc6dSKonstantin Porotchkin 		fprintf(stderr, "bin extension file size is bad\n");
13796414dc6dSKonstantin Porotchkin 		return 1;
13806414dc6dSKonstantin Porotchkin 	}
13816414dc6dSKonstantin Porotchkin 
13826414dc6dSKonstantin Porotchkin 	/* Align extension size to 8 bytes */
13836414dc6dSKonstantin Porotchkin 	aligned_size = (size + 7) & (~7);
13846414dc6dSKonstantin Porotchkin 	pad_bytes    = aligned_size - size;
13856414dc6dSKonstantin Porotchkin 
13866414dc6dSKonstantin Porotchkin 	header.type = EXT_TYPE_BINARY;
13876414dc6dSKonstantin Porotchkin 	header.offset = 0;
13886414dc6dSKonstantin Porotchkin 	header.size = aligned_size;
13896414dc6dSKonstantin Porotchkin 	header.reserved = 0;
13906414dc6dSKonstantin Porotchkin 
13916414dc6dSKonstantin Porotchkin 	/* Write header */
13926414dc6dSKonstantin Porotchkin 	written = fwrite(&header, sizeof(ext_header_t), 1, out_fd);
13936414dc6dSKonstantin Porotchkin 	if (written != 1) {
13946414dc6dSKonstantin Porotchkin 		fprintf(stderr, "failed writing header to extension file\n");
13956414dc6dSKonstantin Porotchkin 		return 1;
13966414dc6dSKonstantin Porotchkin 	}
13976414dc6dSKonstantin Porotchkin 
13986414dc6dSKonstantin Porotchkin 	/* Write image */
13996414dc6dSKonstantin Porotchkin 	while (size--) {
14006414dc6dSKonstantin Porotchkin 		c = getc(in_fd);
14016414dc6dSKonstantin Porotchkin 		fputc(c, out_fd);
14026414dc6dSKonstantin Porotchkin 	}
14036414dc6dSKonstantin Porotchkin 
14046414dc6dSKonstantin Porotchkin 	while (pad_bytes--)
14056414dc6dSKonstantin Porotchkin 		fputc(0, out_fd);
14066414dc6dSKonstantin Porotchkin 
14076414dc6dSKonstantin Porotchkin 	fclose(in_fd);
14086414dc6dSKonstantin Porotchkin 
14096414dc6dSKonstantin Porotchkin 	return 0;
14106414dc6dSKonstantin Porotchkin }
14116414dc6dSKonstantin Porotchkin 
14126414dc6dSKonstantin Porotchkin /* ****************************************
14136414dc6dSKonstantin Porotchkin  *
14146414dc6dSKonstantin Porotchkin  * Write all extensions (binary, secure
14156414dc6dSKonstantin Porotchkin  * extensions) to file
14166414dc6dSKonstantin Porotchkin  *
14176414dc6dSKonstantin Porotchkin  * ****************************************/
14186414dc6dSKonstantin Porotchkin 
format_extensions(char * ext_filename)14196414dc6dSKonstantin Porotchkin int format_extensions(char *ext_filename)
14206414dc6dSKonstantin Porotchkin {
14216414dc6dSKonstantin Porotchkin 	FILE *out_fd;
14226414dc6dSKonstantin Porotchkin 	int ret = 0;
14236414dc6dSKonstantin Porotchkin 
14246414dc6dSKonstantin Porotchkin 	out_fd = fopen(ext_filename, "wb");
14256414dc6dSKonstantin Porotchkin 	if (out_fd == NULL) {
14266414dc6dSKonstantin Porotchkin 		fprintf(stderr, "failed to open extension output file %s",
14276414dc6dSKonstantin Porotchkin 			ext_filename);
14286414dc6dSKonstantin Porotchkin 		return 1;
14296414dc6dSKonstantin Porotchkin 	}
14306414dc6dSKonstantin Porotchkin 
14316414dc6dSKonstantin Porotchkin 	if (strncmp(opts.bin_ext_file, "NA", MAX_FILENAME)) {
14326414dc6dSKonstantin Porotchkin 		if (format_bin_ext(opts.bin_ext_file, out_fd)) {
14336414dc6dSKonstantin Porotchkin 			ret = 1;
14346414dc6dSKonstantin Porotchkin 			goto error;
14356414dc6dSKonstantin Porotchkin 		}
14366414dc6dSKonstantin Porotchkin 	}
14376414dc6dSKonstantin Porotchkin #ifdef CONFIG_MVEBU_SECURE_BOOT
14386414dc6dSKonstantin Porotchkin 	if (strncmp(opts.sec_cfg_file, "NA", MAX_FILENAME)) {
14396414dc6dSKonstantin Porotchkin 		if (format_sec_ext(opts.sec_cfg_file, out_fd)) {
14406414dc6dSKonstantin Porotchkin 			ret = 1;
14416414dc6dSKonstantin Porotchkin 			goto error;
14426414dc6dSKonstantin Porotchkin 		}
14436414dc6dSKonstantin Porotchkin 	}
14446414dc6dSKonstantin Porotchkin #endif
14456414dc6dSKonstantin Porotchkin 
14466414dc6dSKonstantin Porotchkin error:
14476414dc6dSKonstantin Porotchkin 	fflush(out_fd);
14486414dc6dSKonstantin Porotchkin 	fclose(out_fd);
14496414dc6dSKonstantin Porotchkin 	return ret;
14506414dc6dSKonstantin Porotchkin }
14516414dc6dSKonstantin Porotchkin 
update_uart(header_t * header)14526414dc6dSKonstantin Porotchkin void update_uart(header_t *header)
14536414dc6dSKonstantin Porotchkin {
14546414dc6dSKonstantin Porotchkin 	header->uart_cfg = 0;
14556414dc6dSKonstantin Porotchkin 	header->baudrate = 0;
14566414dc6dSKonstantin Porotchkin 
14576414dc6dSKonstantin Porotchkin 	if (opts.disable_print)
14586414dc6dSKonstantin Porotchkin 		uart_set_mode(header->uart_cfg, UART_MODE_DISABLE);
14596414dc6dSKonstantin Porotchkin 
14606414dc6dSKonstantin Porotchkin 	if (opts.baudrate)
14616414dc6dSKonstantin Porotchkin 		header->baudrate = (opts.baudrate / 1200);
14626414dc6dSKonstantin Porotchkin }
14636414dc6dSKonstantin Porotchkin 
14646414dc6dSKonstantin Porotchkin /* ****************************************
14656414dc6dSKonstantin Porotchkin  *
14666414dc6dSKonstantin Porotchkin  * Write the image prolog, i.e.
14676414dc6dSKonstantin Porotchkin  * main header and extensions, to file
14686414dc6dSKonstantin Porotchkin  *
14696414dc6dSKonstantin Porotchkin  * ****************************************/
14706414dc6dSKonstantin Porotchkin 
write_prolog(int ext_cnt,char * ext_filename,uint8_t * image_buf,int image_size,FILE * out_fd)14716414dc6dSKonstantin Porotchkin int write_prolog(int ext_cnt, char *ext_filename,
14726414dc6dSKonstantin Porotchkin 		 uint8_t *image_buf, int image_size, FILE *out_fd)
14736414dc6dSKonstantin Porotchkin {
14746414dc6dSKonstantin Porotchkin 	header_t		*header;
14756414dc6dSKonstantin Porotchkin 	int main_hdr_size = sizeof(header_t);
14766414dc6dSKonstantin Porotchkin 	int prolog_size = main_hdr_size;
14776414dc6dSKonstantin Porotchkin 	FILE *ext_fd;
14786414dc6dSKonstantin Porotchkin 	char *buf;
14796414dc6dSKonstantin Porotchkin 	int written, read;
14806414dc6dSKonstantin Porotchkin 	int ret = 1;
14816414dc6dSKonstantin Porotchkin 
14826414dc6dSKonstantin Porotchkin 
14836414dc6dSKonstantin Porotchkin 	if (ext_cnt)
14846414dc6dSKonstantin Porotchkin 		prolog_size +=  get_file_size(ext_filename);
14856414dc6dSKonstantin Porotchkin 
14866414dc6dSKonstantin Porotchkin 	prolog_size = ((prolog_size + PROLOG_ALIGNMENT) &
14876414dc6dSKonstantin Porotchkin 		     (~(PROLOG_ALIGNMENT-1)));
14886414dc6dSKonstantin Porotchkin 
14896414dc6dSKonstantin Porotchkin 	/* Allocate a zeroed buffer to zero the padding bytes */
14906414dc6dSKonstantin Porotchkin 	buf = calloc(prolog_size, 1);
14916414dc6dSKonstantin Porotchkin 	if (buf == NULL) {
14926414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Error: failed allocating checksum buffer\n");
14936414dc6dSKonstantin Porotchkin 		return 1;
14946414dc6dSKonstantin Porotchkin 	}
14956414dc6dSKonstantin Porotchkin 
14966414dc6dSKonstantin Porotchkin 	header = (header_t *)buf;
14976414dc6dSKonstantin Porotchkin 	header->magic       = MAIN_HDR_MAGIC;
14986414dc6dSKonstantin Porotchkin 	header->prolog_size = prolog_size;
14996414dc6dSKonstantin Porotchkin 	header->load_addr   = opts.load_addr;
15006414dc6dSKonstantin Porotchkin 	header->exec_addr   = opts.exec_addr;
15016414dc6dSKonstantin Porotchkin 	header->io_arg_0    = opts.nfc_io_args;
15026414dc6dSKonstantin Porotchkin 	header->ext_count   = ext_cnt;
15036414dc6dSKonstantin Porotchkin 	header->aux_flags   = 0;
15046414dc6dSKonstantin Porotchkin 	header->boot_image_size = (image_size + 3) & (~0x3);
15056414dc6dSKonstantin Porotchkin 	header->boot_image_checksum = checksum32((uint32_t *)image_buf,
15066414dc6dSKonstantin Porotchkin 						 image_size);
15076414dc6dSKonstantin Porotchkin 
15086414dc6dSKonstantin Porotchkin 	update_uart(header);
15096414dc6dSKonstantin Porotchkin 
15106414dc6dSKonstantin Porotchkin 	/* Populate buffer with main header and extensions */
15116414dc6dSKonstantin Porotchkin 	if (ext_cnt) {
15126414dc6dSKonstantin Porotchkin 		ext_fd = fopen(ext_filename, "rb");
15136414dc6dSKonstantin Porotchkin 		if (ext_fd == NULL) {
15146414dc6dSKonstantin Porotchkin 			fprintf(stderr,
15156414dc6dSKonstantin Porotchkin 				"Error: failed to open extensions file\n");
15166414dc6dSKonstantin Porotchkin 			goto error;
15176414dc6dSKonstantin Porotchkin 		}
15186414dc6dSKonstantin Porotchkin 
15196414dc6dSKonstantin Porotchkin 		read = fread(&buf[main_hdr_size],
15206414dc6dSKonstantin Porotchkin 			     get_file_size(ext_filename), 1, ext_fd);
15216414dc6dSKonstantin Porotchkin 		if (read != 1) {
15226414dc6dSKonstantin Porotchkin 			fprintf(stderr,
15236414dc6dSKonstantin Porotchkin 				"Error: failed to open extensions file\n");
15246414dc6dSKonstantin Porotchkin 			goto error;
15256414dc6dSKonstantin Porotchkin 		}
15266414dc6dSKonstantin Porotchkin 
15276414dc6dSKonstantin Porotchkin #ifdef CONFIG_MVEBU_SECURE_BOOT
15286414dc6dSKonstantin Porotchkin 		/* Secure boot mode? */
15296414dc6dSKonstantin Porotchkin 		if (opts.sec_opts != 0) {
15306414dc6dSKonstantin Porotchkin 			ret = finalize_secure_ext(header, (uint8_t *)buf,
15316414dc6dSKonstantin Porotchkin 						  prolog_size, image_buf,
15326414dc6dSKonstantin Porotchkin 						  image_size);
15336414dc6dSKonstantin Porotchkin 			if (ret != 0) {
15346414dc6dSKonstantin Porotchkin 				fprintf(stderr, "Error: failed to handle ");
15356414dc6dSKonstantin Porotchkin 				fprintf(stderr, "secure extension!\n");
15366414dc6dSKonstantin Porotchkin 				goto error;
15376414dc6dSKonstantin Porotchkin 			}
15386414dc6dSKonstantin Porotchkin 		} /* secure boot mode */
15396414dc6dSKonstantin Porotchkin #endif
15406414dc6dSKonstantin Porotchkin 	}
15416414dc6dSKonstantin Porotchkin 
15426414dc6dSKonstantin Porotchkin 	/* Update the total prolog checksum */
15436414dc6dSKonstantin Porotchkin 	header->prolog_checksum = checksum32((uint32_t *)buf, prolog_size);
15446414dc6dSKonstantin Porotchkin 
15456414dc6dSKonstantin Porotchkin 	/* Now spill everything to output file */
15466414dc6dSKonstantin Porotchkin 	written = fwrite(buf, prolog_size, 1, out_fd);
15476414dc6dSKonstantin Porotchkin 	if (written != 1) {
15486414dc6dSKonstantin Porotchkin 		fprintf(stderr,
15496414dc6dSKonstantin Porotchkin 			"Error: failed to write prolog to output file\n");
15506414dc6dSKonstantin Porotchkin 		goto error;
15516414dc6dSKonstantin Porotchkin 	}
15526414dc6dSKonstantin Porotchkin 
15536414dc6dSKonstantin Porotchkin 	ret = 0;
15546414dc6dSKonstantin Porotchkin 
15556414dc6dSKonstantin Porotchkin error:
15566414dc6dSKonstantin Porotchkin 	free(buf);
15576414dc6dSKonstantin Porotchkin 	return ret;
15586414dc6dSKonstantin Porotchkin }
15596414dc6dSKonstantin Porotchkin 
write_boot_image(uint8_t * buf,uint32_t image_size,FILE * out_fd)15606414dc6dSKonstantin Porotchkin int write_boot_image(uint8_t *buf, uint32_t image_size, FILE *out_fd)
15616414dc6dSKonstantin Porotchkin {
15626414dc6dSKonstantin Porotchkin 	int written;
15636414dc6dSKonstantin Porotchkin 
15645985a1e4SKonstantin Porotchkin 	written = fwrite(buf, image_size, 1, out_fd);
15656414dc6dSKonstantin Porotchkin 	if (written != 1) {
15666414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Error: Failed to write boot image\n");
15676414dc6dSKonstantin Porotchkin 		goto error;
15686414dc6dSKonstantin Porotchkin 	}
15696414dc6dSKonstantin Porotchkin 
15706414dc6dSKonstantin Porotchkin 	return 0;
15716414dc6dSKonstantin Porotchkin error:
15726414dc6dSKonstantin Porotchkin 	return 1;
15736414dc6dSKonstantin Porotchkin }
15746414dc6dSKonstantin Porotchkin 
main(int argc,char * argv[])15756414dc6dSKonstantin Porotchkin int main(int argc, char *argv[])
15766414dc6dSKonstantin Porotchkin {
15776414dc6dSKonstantin Porotchkin 	char in_file[MAX_FILENAME+1] = { 0 };
15786414dc6dSKonstantin Porotchkin 	char out_file[MAX_FILENAME+1] = { 0 };
15796414dc6dSKonstantin Porotchkin 	char ext_file[MAX_FILENAME+1] = { 0 };
15806414dc6dSKonstantin Porotchkin 	FILE *in_fd = NULL;
15816414dc6dSKonstantin Porotchkin 	FILE *out_fd = NULL;
15826414dc6dSKonstantin Porotchkin 	int parse = 0;
15836414dc6dSKonstantin Porotchkin 	int ext_cnt = 0;
15846414dc6dSKonstantin Porotchkin 	int opt;
15856414dc6dSKonstantin Porotchkin 	int ret = 0;
15865985a1e4SKonstantin Porotchkin 	int image_size, file_size;
15876414dc6dSKonstantin Porotchkin 	uint8_t *image_buf = NULL;
15886414dc6dSKonstantin Porotchkin 	int read;
15896414dc6dSKonstantin Porotchkin 	size_t len;
15906414dc6dSKonstantin Porotchkin 	uint32_t nand_block_size_kb, mlc_nand;
15916414dc6dSKonstantin Porotchkin 
15926414dc6dSKonstantin Porotchkin 	/* Create temporary file for building extensions
15936414dc6dSKonstantin Porotchkin 	 * Use process ID for allowing multiple parallel runs
15946414dc6dSKonstantin Porotchkin 	 */
15956414dc6dSKonstantin Porotchkin 	snprintf(ext_file, MAX_FILENAME, "/tmp/ext_file-%x", getpid());
15966414dc6dSKonstantin Porotchkin 
15976414dc6dSKonstantin Porotchkin 	while ((opt = getopt(argc, argv, "hpms:i:l:e:a:b:u:n:t:c:k:")) != -1) {
15986414dc6dSKonstantin Porotchkin 		switch (opt) {
15996414dc6dSKonstantin Porotchkin 		case 'h':
16006414dc6dSKonstantin Porotchkin 			usage();
16016414dc6dSKonstantin Porotchkin 			break;
16026414dc6dSKonstantin Porotchkin 		case 'l':
16036414dc6dSKonstantin Porotchkin 			opts.load_addr = strtoul(optarg, NULL, 0);
16046414dc6dSKonstantin Porotchkin 			break;
16056414dc6dSKonstantin Porotchkin 		case 'e':
16066414dc6dSKonstantin Porotchkin 			opts.exec_addr = strtoul(optarg, NULL, 0);
16076414dc6dSKonstantin Porotchkin 			break;
16086414dc6dSKonstantin Porotchkin 		case 'm':
16096414dc6dSKonstantin Porotchkin 			opts.disable_print = 1;
16106414dc6dSKonstantin Porotchkin 			break;
16116414dc6dSKonstantin Porotchkin 		case 'u':
16126414dc6dSKonstantin Porotchkin 			opts.baudrate = strtoul(optarg, NULL, 0);
16136414dc6dSKonstantin Porotchkin 			break;
16146414dc6dSKonstantin Porotchkin 		case 'b':
16156414dc6dSKonstantin Porotchkin 			strncpy(opts.bin_ext_file, optarg, MAX_FILENAME);
16166414dc6dSKonstantin Porotchkin 			ext_cnt++;
16176414dc6dSKonstantin Porotchkin 			break;
16186414dc6dSKonstantin Porotchkin 		case 'p':
16196414dc6dSKonstantin Porotchkin 			parse = 1;
16206414dc6dSKonstantin Porotchkin 			break;
16216414dc6dSKonstantin Porotchkin 		case 'n':
16226414dc6dSKonstantin Porotchkin 			nand_block_size_kb = strtoul(optarg, NULL, 0);
16236414dc6dSKonstantin Porotchkin 			opts.nfc_io_args |= (nand_block_size_kb / 64);
16246414dc6dSKonstantin Porotchkin 			break;
16256414dc6dSKonstantin Porotchkin 		case 't':
16266414dc6dSKonstantin Porotchkin 			mlc_nand = 0;
16276414dc6dSKonstantin Porotchkin 			if (!strncmp("MLC", optarg, 3))
16286414dc6dSKonstantin Porotchkin 				mlc_nand = 1;
16296414dc6dSKonstantin Porotchkin 			opts.nfc_io_args |= (mlc_nand << 8);
16306414dc6dSKonstantin Porotchkin 			break;
16316414dc6dSKonstantin Porotchkin #ifdef CONFIG_MVEBU_SECURE_BOOT
16326414dc6dSKonstantin Porotchkin 		case 'c': /* SEC extension */
16336414dc6dSKonstantin Porotchkin 			strncpy(opts.sec_cfg_file, optarg, MAX_FILENAME);
16346414dc6dSKonstantin Porotchkin 			ext_cnt++;
16356414dc6dSKonstantin Porotchkin 			break;
16366414dc6dSKonstantin Porotchkin 		case 'k':
16376414dc6dSKonstantin Porotchkin 			opts.key_index = strtoul(optarg, NULL, 0);
16386414dc6dSKonstantin Porotchkin 			break;
16396414dc6dSKonstantin Porotchkin #endif
16406414dc6dSKonstantin Porotchkin 		default: /* '?' */
16416414dc6dSKonstantin Porotchkin 			usage_err("Unknown argument");
16426414dc6dSKonstantin Porotchkin 			exit(EXIT_FAILURE);
16436414dc6dSKonstantin Porotchkin 		}
16446414dc6dSKonstantin Porotchkin 	}
16456414dc6dSKonstantin Porotchkin 
16466414dc6dSKonstantin Porotchkin 	/* Check validity of inputes */
16476414dc6dSKonstantin Porotchkin 	if (opts.load_addr % 8)
16486414dc6dSKonstantin Porotchkin 		usage_err("Load address must be 8 bytes aligned");
16496414dc6dSKonstantin Porotchkin 
16506414dc6dSKonstantin Porotchkin 	if (opts.baudrate % 1200)
16516414dc6dSKonstantin Porotchkin 		usage_err("Baudrate must be a multiple of 1200");
16526414dc6dSKonstantin Porotchkin 
16536414dc6dSKonstantin Porotchkin 	/* The remaining arguments are the input
16546414dc6dSKonstantin Porotchkin 	 * and potentially output file
16556414dc6dSKonstantin Porotchkin 	 */
16566414dc6dSKonstantin Porotchkin 	/* Input file must exist so exit if not */
16576414dc6dSKonstantin Porotchkin 	if (optind >= argc)
16586414dc6dSKonstantin Porotchkin 		usage_err("missing input file name");
16596414dc6dSKonstantin Porotchkin 
16606414dc6dSKonstantin Porotchkin 	len = strlen(argv[optind]);
16616414dc6dSKonstantin Porotchkin 	if (len > MAX_FILENAME)
16626414dc6dSKonstantin Porotchkin 		usage_err("file name too long");
16636414dc6dSKonstantin Porotchkin 	memcpy(in_file, argv[optind], len);
16646414dc6dSKonstantin Porotchkin 	optind++;
16656414dc6dSKonstantin Porotchkin 
16666414dc6dSKonstantin Porotchkin 	/* Output file must exist in non parse mode */
16676414dc6dSKonstantin Porotchkin 	if (optind < argc) {
16686414dc6dSKonstantin Porotchkin 		len = strlen(argv[optind]);
16696414dc6dSKonstantin Porotchkin 		if (len > MAX_FILENAME)
16706414dc6dSKonstantin Porotchkin 			usage_err("file name too long");
16716414dc6dSKonstantin Porotchkin 		memcpy(out_file, argv[optind], len);
16726414dc6dSKonstantin Porotchkin 	} else if (!parse)
16736414dc6dSKonstantin Porotchkin 		usage_err("missing output file name");
16746414dc6dSKonstantin Porotchkin 
16756414dc6dSKonstantin Porotchkin 	/* open the input file */
16766414dc6dSKonstantin Porotchkin 	in_fd = fopen(in_file, "rb");
16776414dc6dSKonstantin Porotchkin 	if (in_fd == NULL) {
16786414dc6dSKonstantin Porotchkin 		printf("Error: Failed to open input file %s\n", in_file);
16796414dc6dSKonstantin Porotchkin 		goto main_exit;
16806414dc6dSKonstantin Porotchkin 	}
16816414dc6dSKonstantin Porotchkin 
16825985a1e4SKonstantin Porotchkin 	/* Read the input file to buffer
16835985a1e4SKonstantin Porotchkin 	 * Always align the image to 16 byte boundary
16845985a1e4SKonstantin Porotchkin 	 */
16855985a1e4SKonstantin Porotchkin 	file_size  = get_file_size(in_file);
16865985a1e4SKonstantin Porotchkin 	image_size = (file_size + AES_BLOCK_SZ - 1) & ~(AES_BLOCK_SZ - 1);
16875985a1e4SKonstantin Porotchkin 	image_buf  = calloc(image_size, 1);
16886414dc6dSKonstantin Porotchkin 	if (image_buf == NULL) {
16896414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Error: failed allocating input buffer\n");
16906414dc6dSKonstantin Porotchkin 		return 1;
16916414dc6dSKonstantin Porotchkin 	}
16926414dc6dSKonstantin Porotchkin 
16935985a1e4SKonstantin Porotchkin 	read = fread(image_buf, file_size, 1, in_fd);
16946414dc6dSKonstantin Porotchkin 	if (read != 1) {
16956414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Error: failed to read input file\n");
16966414dc6dSKonstantin Porotchkin 		goto main_exit;
16976414dc6dSKonstantin Porotchkin 	}
16986414dc6dSKonstantin Porotchkin 
16996414dc6dSKonstantin Porotchkin 	/* Parse the input image and leave */
17006414dc6dSKonstantin Porotchkin 	if (parse) {
17016414dc6dSKonstantin Porotchkin 		if (opts.key_index >= CSK_ARR_SZ) {
17026414dc6dSKonstantin Porotchkin 			fprintf(stderr,
17036414dc6dSKonstantin Porotchkin 				"Wrong key IDX value. Valid values 0 - %d\n",
17046414dc6dSKonstantin Porotchkin 				CSK_ARR_SZ - 1);
17056414dc6dSKonstantin Porotchkin 			goto main_exit;
17066414dc6dSKonstantin Porotchkin 		}
17076414dc6dSKonstantin Porotchkin 		ret = parse_image(image_buf, image_size);
17086414dc6dSKonstantin Porotchkin 		goto main_exit;
17096414dc6dSKonstantin Porotchkin 	}
17106414dc6dSKonstantin Porotchkin 
17116414dc6dSKonstantin Porotchkin 	/* Create a blob file from all extensions */
17126414dc6dSKonstantin Porotchkin 	if (ext_cnt) {
17136414dc6dSKonstantin Porotchkin 		ret = format_extensions(ext_file);
17146414dc6dSKonstantin Porotchkin 		if (ret)
17156414dc6dSKonstantin Porotchkin 			goto main_exit;
17166414dc6dSKonstantin Porotchkin 	}
17176414dc6dSKonstantin Porotchkin 
17186414dc6dSKonstantin Porotchkin 	out_fd = fopen(out_file, "wb");
17196414dc6dSKonstantin Porotchkin 	if (out_fd == NULL) {
17206414dc6dSKonstantin Porotchkin 		fprintf(stderr,
17216414dc6dSKonstantin Porotchkin 			"Error: Failed to open output file %s\n", out_file);
17226414dc6dSKonstantin Porotchkin 		goto main_exit;
17236414dc6dSKonstantin Porotchkin 	}
17246414dc6dSKonstantin Porotchkin 
17256414dc6dSKonstantin Porotchkin 	ret = write_prolog(ext_cnt, ext_file, image_buf, image_size, out_fd);
17266414dc6dSKonstantin Porotchkin 	if (ret)
17276414dc6dSKonstantin Porotchkin 		goto main_exit;
17286414dc6dSKonstantin Porotchkin 
17296414dc6dSKonstantin Porotchkin #ifdef CONFIG_MVEBU_SECURE_BOOT
17306414dc6dSKonstantin Porotchkin 	if (opts.sec_opts && (opts.sec_opts->encrypted_image != 0) &&
17316414dc6dSKonstantin Porotchkin 	    (opts.sec_opts->enc_image_sz != 0)) {
17326414dc6dSKonstantin Porotchkin 		ret = write_boot_image(opts.sec_opts->encrypted_image,
17336414dc6dSKonstantin Porotchkin 				       opts.sec_opts->enc_image_sz, out_fd);
17346414dc6dSKonstantin Porotchkin 	} else
17356414dc6dSKonstantin Porotchkin #endif
17366414dc6dSKonstantin Porotchkin 		ret = write_boot_image(image_buf, image_size, out_fd);
17376414dc6dSKonstantin Porotchkin 	if (ret)
17386414dc6dSKonstantin Porotchkin 		goto main_exit;
17396414dc6dSKonstantin Porotchkin 
17406414dc6dSKonstantin Porotchkin main_exit:
17416414dc6dSKonstantin Porotchkin 	if (in_fd)
17426414dc6dSKonstantin Porotchkin 		fclose(in_fd);
17436414dc6dSKonstantin Porotchkin 
17446414dc6dSKonstantin Porotchkin 	if (out_fd)
17456414dc6dSKonstantin Porotchkin 		fclose(out_fd);
17466414dc6dSKonstantin Porotchkin 
17476414dc6dSKonstantin Porotchkin 	if (image_buf)
17486414dc6dSKonstantin Porotchkin 		free(image_buf);
17496414dc6dSKonstantin Porotchkin 
17506414dc6dSKonstantin Porotchkin 	unlink(ext_file);
17516414dc6dSKonstantin Porotchkin 
17526414dc6dSKonstantin Porotchkin #ifdef CONFIG_MVEBU_SECURE_BOOT
17536414dc6dSKonstantin Porotchkin 	if (opts.sec_opts) {
17546414dc6dSKonstantin Porotchkin 		if (opts.sec_opts->encrypted_image)
17556414dc6dSKonstantin Porotchkin 			free(opts.sec_opts->encrypted_image);
17566414dc6dSKonstantin Porotchkin 		free(opts.sec_opts);
17576414dc6dSKonstantin Porotchkin 	}
17586414dc6dSKonstantin Porotchkin #endif
17596414dc6dSKonstantin Porotchkin 	exit(ret);
17606414dc6dSKonstantin Porotchkin }
1761