xref: /rk3399_ARM-atf/tools/marvell/doimage/doimage.c (revision 6414dc6d978097dd035de3dc2f17851dc70eed68)
1*6414dc6dSKonstantin Porotchkin /*
2*6414dc6dSKonstantin Porotchkin  * Copyright (C) 2018 Marvell International Ltd.
3*6414dc6dSKonstantin Porotchkin  *
4*6414dc6dSKonstantin Porotchkin  * SPDX-License-Identifier:     BSD-3-Clause
5*6414dc6dSKonstantin Porotchkin  * https://spdx.org/licenses
6*6414dc6dSKonstantin Porotchkin  */
7*6414dc6dSKonstantin Porotchkin 
8*6414dc6dSKonstantin Porotchkin #include <stdlib.h>
9*6414dc6dSKonstantin Porotchkin #include <stdio.h>
10*6414dc6dSKonstantin Porotchkin #include <stdint.h>
11*6414dc6dSKonstantin Porotchkin #include <stddef.h>
12*6414dc6dSKonstantin Porotchkin #include <string.h>
13*6414dc6dSKonstantin Porotchkin #include <unistd.h>
14*6414dc6dSKonstantin Porotchkin #include <sys/stat.h>
15*6414dc6dSKonstantin Porotchkin #include <sys/time.h>
16*6414dc6dSKonstantin Porotchkin 
17*6414dc6dSKonstantin Porotchkin #ifdef CONFIG_MVEBU_SECURE_BOOT
18*6414dc6dSKonstantin Porotchkin #include <libconfig.h>	/* for parsing config file */
19*6414dc6dSKonstantin Porotchkin 
20*6414dc6dSKonstantin Porotchkin #if !defined(MBEDTLS_CONFIG_FILE)
21*6414dc6dSKonstantin Porotchkin #include "mbedtls/config.h"
22*6414dc6dSKonstantin Porotchkin #else
23*6414dc6dSKonstantin Porotchkin #include MBEDTLS_CONFIG_FILE
24*6414dc6dSKonstantin Porotchkin #endif
25*6414dc6dSKonstantin Porotchkin 
26*6414dc6dSKonstantin Porotchkin /* mbedTLS stuff */
27*6414dc6dSKonstantin Porotchkin #if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ENTROPY_C) && \
28*6414dc6dSKonstantin Porotchkin 	defined(MBEDTLS_SHA256_C) && \
29*6414dc6dSKonstantin Porotchkin 	defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_FS_IO) && \
30*6414dc6dSKonstantin Porotchkin 	defined(MBEDTLS_CTR_DRBG_C)
31*6414dc6dSKonstantin Porotchkin #include <mbedtls/error.h>
32*6414dc6dSKonstantin Porotchkin #include <mbedtls/entropy.h>
33*6414dc6dSKonstantin Porotchkin #include <mbedtls/ctr_drbg.h>
34*6414dc6dSKonstantin Porotchkin #include <mbedtls/md.h>
35*6414dc6dSKonstantin Porotchkin #include <mbedtls/pk.h>
36*6414dc6dSKonstantin Porotchkin #include <mbedtls/sha256.h>
37*6414dc6dSKonstantin Porotchkin #include <mbedtls/x509.h>
38*6414dc6dSKonstantin Porotchkin #else
39*6414dc6dSKonstantin Porotchkin #error "Bad mbedTLS configuration!"
40*6414dc6dSKonstantin Porotchkin #endif
41*6414dc6dSKonstantin Porotchkin #endif /* CONFIG_MVEBU_SECURE_BOOT */
42*6414dc6dSKonstantin Porotchkin 
43*6414dc6dSKonstantin Porotchkin #define MAX_FILENAME		256
44*6414dc6dSKonstantin Porotchkin #define CSK_ARR_SZ		16
45*6414dc6dSKonstantin Porotchkin #define CSK_ARR_EMPTY_FILE	"*"
46*6414dc6dSKonstantin Porotchkin #define AES_KEY_BIT_LEN		256
47*6414dc6dSKonstantin Porotchkin #define AES_KEY_BYTE_LEN	(AES_KEY_BIT_LEN >> 3)
48*6414dc6dSKonstantin Porotchkin #define AES_BLOCK_SZ		16
49*6414dc6dSKonstantin Porotchkin #define RSA_SIGN_BYTE_LEN	256
50*6414dc6dSKonstantin Porotchkin #define MAX_RSA_DER_BYTE_LEN	524
51*6414dc6dSKonstantin Porotchkin /* Number of address pairs in control array */
52*6414dc6dSKonstantin Porotchkin #define CP_CTRL_EL_ARRAY_SZ	32
53*6414dc6dSKonstantin Porotchkin 
54*6414dc6dSKonstantin Porotchkin #define VERSION_STRING		"Marvell(C) doimage utility version 3.2"
55*6414dc6dSKonstantin Porotchkin 
56*6414dc6dSKonstantin Porotchkin /* A8K definitions */
57*6414dc6dSKonstantin Porotchkin 
58*6414dc6dSKonstantin Porotchkin /* Extension header types */
59*6414dc6dSKonstantin Porotchkin #define EXT_TYPE_SECURITY	0x1
60*6414dc6dSKonstantin Porotchkin #define EXT_TYPE_BINARY		0x2
61*6414dc6dSKonstantin Porotchkin 
62*6414dc6dSKonstantin Porotchkin #define MAIN_HDR_MAGIC		0xB105B002
63*6414dc6dSKonstantin Porotchkin 
64*6414dc6dSKonstantin Porotchkin /* PROLOG alignment considerations:
65*6414dc6dSKonstantin Porotchkin  *  128B: To allow supporting XMODEM protocol.
66*6414dc6dSKonstantin Porotchkin  *  8KB: To align the boot image to the largest NAND page size, and simplify
67*6414dc6dSKonstantin Porotchkin  *  the read operations from NAND.
68*6414dc6dSKonstantin Porotchkin  *  We choose the largest page size, in order to use a single image for all
69*6414dc6dSKonstantin Porotchkin  *  NAND page sizes.
70*6414dc6dSKonstantin Porotchkin  */
71*6414dc6dSKonstantin Porotchkin #define PROLOG_ALIGNMENT	(8 << 10)
72*6414dc6dSKonstantin Porotchkin 
73*6414dc6dSKonstantin Porotchkin /* UART argument bitfield */
74*6414dc6dSKonstantin Porotchkin #define UART_MODE_UNMODIFIED	0x0
75*6414dc6dSKonstantin Porotchkin #define UART_MODE_DISABLE	0x1
76*6414dc6dSKonstantin Porotchkin #define UART_MODE_UPDATE	0x2
77*6414dc6dSKonstantin Porotchkin 
78*6414dc6dSKonstantin Porotchkin typedef struct _main_header {
79*6414dc6dSKonstantin Porotchkin 	uint32_t	magic;			/*  0-3  */
80*6414dc6dSKonstantin Porotchkin 	uint32_t	prolog_size;		/*  4-7  */
81*6414dc6dSKonstantin Porotchkin 	uint32_t	prolog_checksum;	/*  8-11 */
82*6414dc6dSKonstantin Porotchkin 	uint32_t	boot_image_size;	/* 12-15 */
83*6414dc6dSKonstantin Porotchkin 	uint32_t	boot_image_checksum;	/* 16-19 */
84*6414dc6dSKonstantin Porotchkin 	uint32_t	rsrvd0;			/* 20-23 */
85*6414dc6dSKonstantin Porotchkin 	uint32_t	load_addr;		/* 24-27 */
86*6414dc6dSKonstantin Porotchkin 	uint32_t	exec_addr;		/* 28-31 */
87*6414dc6dSKonstantin Porotchkin 	uint8_t		uart_cfg;		/*  32   */
88*6414dc6dSKonstantin Porotchkin 	uint8_t		baudrate;		/*  33   */
89*6414dc6dSKonstantin Porotchkin 	uint8_t		ext_count;		/*  34   */
90*6414dc6dSKonstantin Porotchkin 	uint8_t		aux_flags;		/*  35   */
91*6414dc6dSKonstantin Porotchkin 	uint32_t	io_arg_0;		/* 36-39 */
92*6414dc6dSKonstantin Porotchkin 	uint32_t	io_arg_1;		/* 40-43 */
93*6414dc6dSKonstantin Porotchkin 	uint32_t	io_arg_2;		/* 43-47 */
94*6414dc6dSKonstantin Porotchkin 	uint32_t	io_arg_3;		/* 48-51 */
95*6414dc6dSKonstantin Porotchkin 	uint32_t	rsrvd1;			/* 52-55 */
96*6414dc6dSKonstantin Porotchkin 	uint32_t	rsrvd2;			/* 56-59 */
97*6414dc6dSKonstantin Porotchkin 	uint32_t	rsrvd3;			/* 60-63 */
98*6414dc6dSKonstantin Porotchkin } header_t;
99*6414dc6dSKonstantin Porotchkin 
100*6414dc6dSKonstantin Porotchkin typedef struct _ext_header {
101*6414dc6dSKonstantin Porotchkin 	uint8_t		type;
102*6414dc6dSKonstantin Porotchkin 	uint8_t		offset;
103*6414dc6dSKonstantin Porotchkin 	uint16_t	reserved;
104*6414dc6dSKonstantin Porotchkin 	uint32_t	size;
105*6414dc6dSKonstantin Porotchkin } ext_header_t;
106*6414dc6dSKonstantin Porotchkin 
107*6414dc6dSKonstantin Porotchkin typedef struct _sec_entry {
108*6414dc6dSKonstantin Porotchkin 	uint8_t		kak_key[MAX_RSA_DER_BYTE_LEN];
109*6414dc6dSKonstantin Porotchkin 	uint32_t	jtag_delay;
110*6414dc6dSKonstantin Porotchkin 	uint32_t	box_id;
111*6414dc6dSKonstantin Porotchkin 	uint32_t	flash_id;
112*6414dc6dSKonstantin Porotchkin 	uint32_t	jtag_en;
113*6414dc6dSKonstantin Porotchkin 	uint32_t	encrypt_en;
114*6414dc6dSKonstantin Porotchkin 	uint32_t	efuse_dis;
115*6414dc6dSKonstantin Porotchkin 	uint8_t		header_sign[RSA_SIGN_BYTE_LEN];
116*6414dc6dSKonstantin Porotchkin 	uint8_t		image_sign[RSA_SIGN_BYTE_LEN];
117*6414dc6dSKonstantin Porotchkin 	uint8_t		csk_keys[CSK_ARR_SZ][MAX_RSA_DER_BYTE_LEN];
118*6414dc6dSKonstantin Porotchkin 	uint8_t		csk_sign[RSA_SIGN_BYTE_LEN];
119*6414dc6dSKonstantin Porotchkin 	uint32_t	cp_ctrl_arr[CP_CTRL_EL_ARRAY_SZ];
120*6414dc6dSKonstantin Porotchkin 	uint32_t	cp_efuse_arr[CP_CTRL_EL_ARRAY_SZ];
121*6414dc6dSKonstantin Porotchkin } sec_entry_t;
122*6414dc6dSKonstantin Porotchkin 
123*6414dc6dSKonstantin Porotchkin /* A8K definitions end */
124*6414dc6dSKonstantin Porotchkin 
125*6414dc6dSKonstantin Porotchkin /* UART argument bitfield */
126*6414dc6dSKonstantin Porotchkin #define UART_MODE_UNMODIFIED	0x0
127*6414dc6dSKonstantin Porotchkin #define UART_MODE_DISABLE	0x1
128*6414dc6dSKonstantin Porotchkin #define UART_MODE_UPDATE	0x2
129*6414dc6dSKonstantin Porotchkin 
130*6414dc6dSKonstantin Porotchkin #define uart_set_mode(arg, mode)	(arg |= (mode & 0x3))
131*6414dc6dSKonstantin Porotchkin 
132*6414dc6dSKonstantin Porotchkin typedef struct _sec_options {
133*6414dc6dSKonstantin Porotchkin #ifdef CONFIG_MVEBU_SECURE_BOOT
134*6414dc6dSKonstantin Porotchkin 	char aes_key_file[MAX_FILENAME+1];
135*6414dc6dSKonstantin Porotchkin 	char kak_key_file[MAX_FILENAME+1];
136*6414dc6dSKonstantin Porotchkin 	char csk_key_file[CSK_ARR_SZ][MAX_FILENAME+1];
137*6414dc6dSKonstantin Porotchkin 	uint32_t	box_id;
138*6414dc6dSKonstantin Porotchkin 	uint32_t	flash_id;
139*6414dc6dSKonstantin Porotchkin 	uint32_t	jtag_delay;
140*6414dc6dSKonstantin Porotchkin 	uint8_t		csk_index;
141*6414dc6dSKonstantin Porotchkin 	uint8_t		jtag_enable;
142*6414dc6dSKonstantin Porotchkin 	uint8_t		efuse_disable;
143*6414dc6dSKonstantin Porotchkin 	uint32_t	cp_ctrl_arr[CP_CTRL_EL_ARRAY_SZ];
144*6414dc6dSKonstantin Porotchkin 	uint32_t	cp_efuse_arr[CP_CTRL_EL_ARRAY_SZ];
145*6414dc6dSKonstantin Porotchkin 	mbedtls_pk_context	kak_pk;
146*6414dc6dSKonstantin Porotchkin 	mbedtls_pk_context	csk_pk[CSK_ARR_SZ];
147*6414dc6dSKonstantin Porotchkin 	uint8_t		aes_key[AES_KEY_BYTE_LEN];
148*6414dc6dSKonstantin Porotchkin 	uint8_t		*encrypted_image;
149*6414dc6dSKonstantin Porotchkin 	uint32_t	enc_image_sz;
150*6414dc6dSKonstantin Porotchkin #endif
151*6414dc6dSKonstantin Porotchkin } sec_options;
152*6414dc6dSKonstantin Porotchkin 
153*6414dc6dSKonstantin Porotchkin typedef struct _options {
154*6414dc6dSKonstantin Porotchkin 	char bin_ext_file[MAX_FILENAME+1];
155*6414dc6dSKonstantin Porotchkin 	char sec_cfg_file[MAX_FILENAME+1];
156*6414dc6dSKonstantin Porotchkin 	sec_options *sec_opts;
157*6414dc6dSKonstantin Porotchkin 	uint32_t  load_addr;
158*6414dc6dSKonstantin Porotchkin 	uint32_t  exec_addr;
159*6414dc6dSKonstantin Porotchkin 	uint32_t  baudrate;
160*6414dc6dSKonstantin Porotchkin 	uint8_t	  disable_print;
161*6414dc6dSKonstantin Porotchkin 	int8_t    key_index; /* For header signatures verification only */
162*6414dc6dSKonstantin Porotchkin 	uint32_t  nfc_io_args;
163*6414dc6dSKonstantin Porotchkin } options_t;
164*6414dc6dSKonstantin Porotchkin 
165*6414dc6dSKonstantin Porotchkin void usage_err(char *msg)
166*6414dc6dSKonstantin Porotchkin {
167*6414dc6dSKonstantin Porotchkin 	fprintf(stderr, "Error: %s\n", msg);
168*6414dc6dSKonstantin Porotchkin 	fprintf(stderr, "run 'doimage -h' to get usage information\n");
169*6414dc6dSKonstantin Porotchkin 	exit(-1);
170*6414dc6dSKonstantin Porotchkin }
171*6414dc6dSKonstantin Porotchkin 
172*6414dc6dSKonstantin Porotchkin void usage(void)
173*6414dc6dSKonstantin Porotchkin {
174*6414dc6dSKonstantin Porotchkin 	printf("\n\n%s\n\n", VERSION_STRING);
175*6414dc6dSKonstantin Porotchkin 	printf("Usage: doimage [options] <input_file> [output_file]\n");
176*6414dc6dSKonstantin Porotchkin 	printf("create bootrom image from u-boot and boot extensions\n\n");
177*6414dc6dSKonstantin Porotchkin 
178*6414dc6dSKonstantin Porotchkin 	printf("Arguments\n");
179*6414dc6dSKonstantin Porotchkin 	printf("  input_file   name of boot image file.\n");
180*6414dc6dSKonstantin Porotchkin 	printf("               if -p is used, name of the bootrom image file");
181*6414dc6dSKonstantin Porotchkin 	printf("               to parse.\n");
182*6414dc6dSKonstantin Porotchkin 	printf("  output_file  name of output bootrom image file\n");
183*6414dc6dSKonstantin Porotchkin 
184*6414dc6dSKonstantin Porotchkin 	printf("\nOptions\n");
185*6414dc6dSKonstantin Porotchkin 	printf("  -s        target SOC name. supports a8020,a7020\n");
186*6414dc6dSKonstantin Porotchkin 	printf("            different SOCs may have different boot image\n");
187*6414dc6dSKonstantin Porotchkin 	printf("            format so it's mandatory to know the target SOC\n");
188*6414dc6dSKonstantin Porotchkin 	printf("  -i        boot I/F name. supports nand, spi, nor\n");
189*6414dc6dSKonstantin Porotchkin 	printf("            This affects certain parameters coded in the\n");
190*6414dc6dSKonstantin Porotchkin 	printf("            image header\n");
191*6414dc6dSKonstantin Porotchkin 	printf("  -l        boot image load address. default is 0x0\n");
192*6414dc6dSKonstantin Porotchkin 	printf("  -e        boot image entry address. default is 0x0\n");
193*6414dc6dSKonstantin Porotchkin 	printf("  -b        binary extension image file.\n");
194*6414dc6dSKonstantin Porotchkin 	printf("            This image is executed before the boot image.\n");
195*6414dc6dSKonstantin Porotchkin 	printf("            This is typically used to initialize the memory ");
196*6414dc6dSKonstantin Porotchkin 	printf("            controller.\n");
197*6414dc6dSKonstantin Porotchkin 	printf("            Currently supports only a single file.\n");
198*6414dc6dSKonstantin Porotchkin #ifdef CONFIG_MVEBU_SECURE_BOOT
199*6414dc6dSKonstantin Porotchkin 	printf("  -c        Make trusted boot image using parameters\n");
200*6414dc6dSKonstantin Porotchkin 	printf("            from the configuration file.\n");
201*6414dc6dSKonstantin Porotchkin #endif
202*6414dc6dSKonstantin Porotchkin 	printf("  -p        Parse and display a pre-built boot image\n");
203*6414dc6dSKonstantin Porotchkin #ifdef CONFIG_MVEBU_SECURE_BOOT
204*6414dc6dSKonstantin Porotchkin 	printf("  -k        Key index for RSA signatures verification\n");
205*6414dc6dSKonstantin Porotchkin 	printf("            when parsing the boot image\n");
206*6414dc6dSKonstantin Porotchkin #endif
207*6414dc6dSKonstantin Porotchkin 	printf("  -m        Disable prints of bootrom and binary extension\n");
208*6414dc6dSKonstantin Porotchkin 	printf("  -u        UART baudrate used for bootrom prints.\n");
209*6414dc6dSKonstantin Porotchkin 	printf("            Must be multiple of 1200\n");
210*6414dc6dSKonstantin Porotchkin 	printf("  -h        Show this help message\n");
211*6414dc6dSKonstantin Porotchkin 	printf(" IO-ROM NFC-NAND boot parameters:\n");
212*6414dc6dSKonstantin Porotchkin 	printf("  -n        NAND device block size in KB [Default is 64KB].\n");
213*6414dc6dSKonstantin Porotchkin 	printf("  -t        NAND cell technology (SLC [Default] or MLC)\n");
214*6414dc6dSKonstantin Porotchkin 
215*6414dc6dSKonstantin Porotchkin 	exit(-1);
216*6414dc6dSKonstantin Porotchkin }
217*6414dc6dSKonstantin Porotchkin 
218*6414dc6dSKonstantin Porotchkin /* globals */
219*6414dc6dSKonstantin Porotchkin static options_t opts = {
220*6414dc6dSKonstantin Porotchkin 	.bin_ext_file = "NA",
221*6414dc6dSKonstantin Porotchkin 	.sec_cfg_file = "NA",
222*6414dc6dSKonstantin Porotchkin 	.sec_opts = 0,
223*6414dc6dSKonstantin Porotchkin 	.load_addr = 0x0,
224*6414dc6dSKonstantin Porotchkin 	.exec_addr = 0x0,
225*6414dc6dSKonstantin Porotchkin 	.disable_print = 0,
226*6414dc6dSKonstantin Porotchkin 	.baudrate = 0,
227*6414dc6dSKonstantin Porotchkin 	.key_index = -1,
228*6414dc6dSKonstantin Porotchkin };
229*6414dc6dSKonstantin Porotchkin 
230*6414dc6dSKonstantin Porotchkin int get_file_size(char *filename)
231*6414dc6dSKonstantin Porotchkin {
232*6414dc6dSKonstantin Porotchkin 	struct stat st;
233*6414dc6dSKonstantin Porotchkin 
234*6414dc6dSKonstantin Porotchkin 	if (stat(filename, &st) == 0)
235*6414dc6dSKonstantin Porotchkin 		return st.st_size;
236*6414dc6dSKonstantin Porotchkin 
237*6414dc6dSKonstantin Porotchkin 	return -1;
238*6414dc6dSKonstantin Porotchkin }
239*6414dc6dSKonstantin Porotchkin 
240*6414dc6dSKonstantin Porotchkin uint32_t checksum32(uint32_t *start, int len)
241*6414dc6dSKonstantin Porotchkin {
242*6414dc6dSKonstantin Porotchkin 	uint32_t sum = 0;
243*6414dc6dSKonstantin Porotchkin 	uint32_t *startp = start;
244*6414dc6dSKonstantin Porotchkin 
245*6414dc6dSKonstantin Porotchkin 	do {
246*6414dc6dSKonstantin Porotchkin 		sum += *startp;
247*6414dc6dSKonstantin Porotchkin 		startp++;
248*6414dc6dSKonstantin Porotchkin 		len -= 4;
249*6414dc6dSKonstantin Porotchkin 	} while (len > 0);
250*6414dc6dSKonstantin Porotchkin 
251*6414dc6dSKonstantin Porotchkin 	return sum;
252*6414dc6dSKonstantin Porotchkin }
253*6414dc6dSKonstantin Porotchkin 
254*6414dc6dSKonstantin Porotchkin /*******************************************************************************
255*6414dc6dSKonstantin Porotchkin  *    create_rsa_signature (memory buffer content)
256*6414dc6dSKonstantin Porotchkin  *          Create RSASSA-PSS/SHA-256 signature for memory buffer
257*6414dc6dSKonstantin Porotchkin  *          using RSA Private Key
258*6414dc6dSKonstantin Porotchkin  *    INPUT:
259*6414dc6dSKonstantin Porotchkin  *          pk_ctx     Private Key context
260*6414dc6dSKonstantin Porotchkin  *          input      memory buffer
261*6414dc6dSKonstantin Porotchkin  *          ilen       buffer length
262*6414dc6dSKonstantin Porotchkin  *          pers       personalization string for seeding the RNG.
263*6414dc6dSKonstantin Porotchkin  *                     For instance a private key file name.
264*6414dc6dSKonstantin Porotchkin  *    OUTPUT:
265*6414dc6dSKonstantin Porotchkin  *          signature  RSA-2048 signature
266*6414dc6dSKonstantin Porotchkin  *    RETURN:
267*6414dc6dSKonstantin Porotchkin  *          0 on success
268*6414dc6dSKonstantin Porotchkin  */
269*6414dc6dSKonstantin Porotchkin #ifdef CONFIG_MVEBU_SECURE_BOOT
270*6414dc6dSKonstantin Porotchkin int create_rsa_signature(mbedtls_pk_context	*pk_ctx,
271*6414dc6dSKonstantin Porotchkin 			 const unsigned char	*input,
272*6414dc6dSKonstantin Porotchkin 			 size_t			ilen,
273*6414dc6dSKonstantin Porotchkin 			 const char		*pers,
274*6414dc6dSKonstantin Porotchkin 			 uint8_t		*signature)
275*6414dc6dSKonstantin Porotchkin {
276*6414dc6dSKonstantin Porotchkin 	mbedtls_entropy_context		entropy;
277*6414dc6dSKonstantin Porotchkin 	mbedtls_ctr_drbg_context	ctr_drbg;
278*6414dc6dSKonstantin Porotchkin 	unsigned char			hash[32];
279*6414dc6dSKonstantin Porotchkin 	unsigned char			buf[MBEDTLS_MPI_MAX_SIZE];
280*6414dc6dSKonstantin Porotchkin 	int				rval;
281*6414dc6dSKonstantin Porotchkin 
282*6414dc6dSKonstantin Porotchkin 	/* Not sure this is required,
283*6414dc6dSKonstantin Porotchkin 	 * but it's safer to start with empty buffers
284*6414dc6dSKonstantin Porotchkin 	 */
285*6414dc6dSKonstantin Porotchkin 	memset(hash, 0, sizeof(hash));
286*6414dc6dSKonstantin Porotchkin 	memset(buf, 0, sizeof(buf));
287*6414dc6dSKonstantin Porotchkin 
288*6414dc6dSKonstantin Porotchkin 	mbedtls_ctr_drbg_init(&ctr_drbg);
289*6414dc6dSKonstantin Porotchkin 	mbedtls_entropy_init(&entropy);
290*6414dc6dSKonstantin Porotchkin 
291*6414dc6dSKonstantin Porotchkin 	/* Seed the random number generator */
292*6414dc6dSKonstantin Porotchkin 	rval = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
293*6414dc6dSKonstantin Porotchkin 				(const unsigned char *)pers, strlen(pers));
294*6414dc6dSKonstantin Porotchkin 	if (rval != 0) {
295*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, " Failed in ctr_drbg_init call (%d)!\n", rval);
296*6414dc6dSKonstantin Porotchkin 		goto sign_exit;
297*6414dc6dSKonstantin Porotchkin 	}
298*6414dc6dSKonstantin Porotchkin 
299*6414dc6dSKonstantin Porotchkin 	/* The PK context should be already initialized.
300*6414dc6dSKonstantin Porotchkin 	 * Set the padding type for this PK context
301*6414dc6dSKonstantin Porotchkin 	 */
302*6414dc6dSKonstantin Porotchkin 	mbedtls_rsa_set_padding(mbedtls_pk_rsa(*pk_ctx),
303*6414dc6dSKonstantin Porotchkin 				MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
304*6414dc6dSKonstantin Porotchkin 
305*6414dc6dSKonstantin Porotchkin 	/* First compute the SHA256 hash for the input blob */
306*6414dc6dSKonstantin Porotchkin 	mbedtls_sha256(input, ilen, hash, 0);
307*6414dc6dSKonstantin Porotchkin 
308*6414dc6dSKonstantin Porotchkin 	/* Then calculate the hash signature */
309*6414dc6dSKonstantin Porotchkin 	rval = mbedtls_rsa_rsassa_pss_sign(mbedtls_pk_rsa(*pk_ctx),
310*6414dc6dSKonstantin Porotchkin 					   mbedtls_ctr_drbg_random,
311*6414dc6dSKonstantin Porotchkin 					   &ctr_drbg,
312*6414dc6dSKonstantin Porotchkin 					   MBEDTLS_RSA_PRIVATE,
313*6414dc6dSKonstantin Porotchkin 					   MBEDTLS_MD_SHA256, 0, hash, buf);
314*6414dc6dSKonstantin Porotchkin 	if (rval != 0) {
315*6414dc6dSKonstantin Porotchkin 		fprintf(stderr,
316*6414dc6dSKonstantin Porotchkin 			"Failed to create RSA signature for %s. Error %d\n",
317*6414dc6dSKonstantin Porotchkin 			pers, rval);
318*6414dc6dSKonstantin Porotchkin 		goto sign_exit;
319*6414dc6dSKonstantin Porotchkin 	}
320*6414dc6dSKonstantin Porotchkin 	memcpy(signature, buf, 256);
321*6414dc6dSKonstantin Porotchkin 
322*6414dc6dSKonstantin Porotchkin sign_exit:
323*6414dc6dSKonstantin Porotchkin 	mbedtls_ctr_drbg_free(&ctr_drbg);
324*6414dc6dSKonstantin Porotchkin 	mbedtls_entropy_free(&entropy);
325*6414dc6dSKonstantin Porotchkin 
326*6414dc6dSKonstantin Porotchkin 	return rval;
327*6414dc6dSKonstantin Porotchkin } /* end of create_rsa_signature */
328*6414dc6dSKonstantin Porotchkin 
329*6414dc6dSKonstantin Porotchkin /*******************************************************************************
330*6414dc6dSKonstantin Porotchkin  *    verify_rsa_signature (memory buffer content)
331*6414dc6dSKonstantin Porotchkin  *          Verify RSASSA-PSS/SHA-256 signature for memory buffer
332*6414dc6dSKonstantin Porotchkin  *          using RSA Public Key
333*6414dc6dSKonstantin Porotchkin  *    INPUT:
334*6414dc6dSKonstantin Porotchkin  *          pub_key    Public Key buffer
335*6414dc6dSKonstantin Porotchkin  *          ilen       Public Key buffer length
336*6414dc6dSKonstantin Porotchkin  *          input      memory buffer
337*6414dc6dSKonstantin Porotchkin  *          ilen       buffer length
338*6414dc6dSKonstantin Porotchkin  *          pers       personalization string for seeding the RNG.
339*6414dc6dSKonstantin Porotchkin  *          signature  RSA-2048 signature
340*6414dc6dSKonstantin Porotchkin  *    OUTPUT:
341*6414dc6dSKonstantin Porotchkin  *          none
342*6414dc6dSKonstantin Porotchkin  *    RETURN:
343*6414dc6dSKonstantin Porotchkin  *          0 on success
344*6414dc6dSKonstantin Porotchkin  */
345*6414dc6dSKonstantin Porotchkin int verify_rsa_signature(const unsigned char	*pub_key,
346*6414dc6dSKonstantin Porotchkin 			 size_t			klen,
347*6414dc6dSKonstantin Porotchkin 			 const unsigned char	*input,
348*6414dc6dSKonstantin Porotchkin 			 size_t			ilen,
349*6414dc6dSKonstantin Porotchkin 			 const char		*pers,
350*6414dc6dSKonstantin Porotchkin 			 uint8_t		*signature)
351*6414dc6dSKonstantin Porotchkin {
352*6414dc6dSKonstantin Porotchkin 	mbedtls_entropy_context		entropy;
353*6414dc6dSKonstantin Porotchkin 	mbedtls_ctr_drbg_context	ctr_drbg;
354*6414dc6dSKonstantin Porotchkin 	mbedtls_pk_context		pk_ctx;
355*6414dc6dSKonstantin Porotchkin 	unsigned char			hash[32];
356*6414dc6dSKonstantin Porotchkin 	int				rval;
357*6414dc6dSKonstantin Porotchkin 
358*6414dc6dSKonstantin Porotchkin 	/* Not sure this is required,
359*6414dc6dSKonstantin Porotchkin 	 * but it's safer to start with empty buffer
360*6414dc6dSKonstantin Porotchkin 	 */
361*6414dc6dSKonstantin Porotchkin 	memset(hash, 0, sizeof(hash));
362*6414dc6dSKonstantin Porotchkin 
363*6414dc6dSKonstantin Porotchkin 	mbedtls_pk_init(&pk_ctx);
364*6414dc6dSKonstantin Porotchkin 	mbedtls_ctr_drbg_init(&ctr_drbg);
365*6414dc6dSKonstantin Porotchkin 	mbedtls_entropy_init(&entropy);
366*6414dc6dSKonstantin Porotchkin 
367*6414dc6dSKonstantin Porotchkin 	/* Seed the random number generator */
368*6414dc6dSKonstantin Porotchkin 	rval = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
369*6414dc6dSKonstantin Porotchkin 				(const unsigned char *)pers, strlen(pers));
370*6414dc6dSKonstantin Porotchkin 	if (rval != 0) {
371*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, " Failed in ctr_drbg_init call (%d)!\n", rval);
372*6414dc6dSKonstantin Porotchkin 		goto verify_exit;
373*6414dc6dSKonstantin Porotchkin 	}
374*6414dc6dSKonstantin Porotchkin 
375*6414dc6dSKonstantin Porotchkin 	/* Check ability to read the public key */
376*6414dc6dSKonstantin Porotchkin 	rval = mbedtls_pk_parse_public_key(&pk_ctx, pub_key,
377*6414dc6dSKonstantin Porotchkin 					   MAX_RSA_DER_BYTE_LEN);
378*6414dc6dSKonstantin Porotchkin 	if (rval != 0) {
379*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, " Failed in pk_parse_public_key (%#x)!\n",
380*6414dc6dSKonstantin Porotchkin 			rval);
381*6414dc6dSKonstantin Porotchkin 		goto verify_exit;
382*6414dc6dSKonstantin Porotchkin 	}
383*6414dc6dSKonstantin Porotchkin 
384*6414dc6dSKonstantin Porotchkin 	/* Set the padding type for the new PK context */
385*6414dc6dSKonstantin Porotchkin 	mbedtls_rsa_set_padding(mbedtls_pk_rsa(pk_ctx),
386*6414dc6dSKonstantin Porotchkin 				MBEDTLS_RSA_PKCS_V21,
387*6414dc6dSKonstantin Porotchkin 				MBEDTLS_MD_SHA256);
388*6414dc6dSKonstantin Porotchkin 
389*6414dc6dSKonstantin Porotchkin 	/* Compute the SHA256 hash for the input buffer */
390*6414dc6dSKonstantin Porotchkin 	mbedtls_sha256(input, ilen, hash, 0);
391*6414dc6dSKonstantin Porotchkin 
392*6414dc6dSKonstantin Porotchkin 	rval = mbedtls_rsa_rsassa_pss_verify(mbedtls_pk_rsa(pk_ctx),
393*6414dc6dSKonstantin Porotchkin 					     mbedtls_ctr_drbg_random,
394*6414dc6dSKonstantin Porotchkin 					     &ctr_drbg,
395*6414dc6dSKonstantin Porotchkin 					     MBEDTLS_RSA_PUBLIC,
396*6414dc6dSKonstantin Porotchkin 					     MBEDTLS_MD_SHA256, 0,
397*6414dc6dSKonstantin Porotchkin 					     hash, signature);
398*6414dc6dSKonstantin Porotchkin 	if (rval != 0)
399*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Failed to verify signature (%d)!\n", rval);
400*6414dc6dSKonstantin Porotchkin 
401*6414dc6dSKonstantin Porotchkin verify_exit:
402*6414dc6dSKonstantin Porotchkin 
403*6414dc6dSKonstantin Porotchkin 	mbedtls_pk_free(&pk_ctx);
404*6414dc6dSKonstantin Porotchkin 	mbedtls_ctr_drbg_free(&ctr_drbg);
405*6414dc6dSKonstantin Porotchkin 	mbedtls_entropy_free(&entropy);
406*6414dc6dSKonstantin Porotchkin 	return rval;
407*6414dc6dSKonstantin Porotchkin } /* end of verify_rsa_signature */
408*6414dc6dSKonstantin Porotchkin 
409*6414dc6dSKonstantin Porotchkin /*******************************************************************************
410*6414dc6dSKonstantin Porotchkin  *    image_encrypt
411*6414dc6dSKonstantin Porotchkin  *           Encrypt image buffer using AES-256-CBC scheme.
412*6414dc6dSKonstantin Porotchkin  *           The resulting image is saved into opts.sec_opts->encrypted_image
413*6414dc6dSKonstantin Porotchkin  *           and the adjusted image size into opts.sec_opts->enc_image_sz
414*6414dc6dSKonstantin Porotchkin  *           First AES_BLOCK_SZ bytes of the output image contain IV
415*6414dc6dSKonstantin Porotchkin  *    INPUT:
416*6414dc6dSKonstantin Porotchkin  *          buf        Source buffer to encrypt
417*6414dc6dSKonstantin Porotchkin  *          blen       Source buffer length
418*6414dc6dSKonstantin Porotchkin  *    OUTPUT:
419*6414dc6dSKonstantin Porotchkin  *          none
420*6414dc6dSKonstantin Porotchkin  *    RETURN:
421*6414dc6dSKonstantin Porotchkin  *          0 on success
422*6414dc6dSKonstantin Porotchkin  */
423*6414dc6dSKonstantin Porotchkin int image_encrypt(uint8_t *buf, uint32_t blen)
424*6414dc6dSKonstantin Porotchkin {
425*6414dc6dSKonstantin Porotchkin 	struct timeval		tv;
426*6414dc6dSKonstantin Porotchkin 	char			*ptmp = (char *)&tv;
427*6414dc6dSKonstantin Porotchkin 	unsigned char		digest[32];
428*6414dc6dSKonstantin Porotchkin 	unsigned char		IV[AES_BLOCK_SZ];
429*6414dc6dSKonstantin Porotchkin 	int			i, k;
430*6414dc6dSKonstantin Porotchkin 	mbedtls_aes_context	aes_ctx;
431*6414dc6dSKonstantin Porotchkin 	int			rval = -1;
432*6414dc6dSKonstantin Porotchkin 	uint8_t			*test_img = 0;
433*6414dc6dSKonstantin Porotchkin 
434*6414dc6dSKonstantin Porotchkin 	if (AES_BLOCK_SZ > 32) {
435*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Unsupported AES block size %d\n",
436*6414dc6dSKonstantin Porotchkin 			AES_BLOCK_SZ);
437*6414dc6dSKonstantin Porotchkin 		return rval;
438*6414dc6dSKonstantin Porotchkin 	}
439*6414dc6dSKonstantin Porotchkin 
440*6414dc6dSKonstantin Porotchkin 	mbedtls_aes_init(&aes_ctx);
441*6414dc6dSKonstantin Porotchkin 	memset(IV, 0, AES_BLOCK_SZ);
442*6414dc6dSKonstantin Porotchkin 	memset(digest, 0, 32);
443*6414dc6dSKonstantin Porotchkin 
444*6414dc6dSKonstantin Porotchkin 	/* Generate initialization vector and init the AES engine
445*6414dc6dSKonstantin Porotchkin 	 * Use file name XOR current time and finally SHA-256
446*6414dc6dSKonstantin Porotchkin 	 * [0...AES_BLOCK_SZ-1]
447*6414dc6dSKonstantin Porotchkin 	 */
448*6414dc6dSKonstantin Porotchkin 	k = strlen(opts.sec_opts->aes_key_file);
449*6414dc6dSKonstantin Porotchkin 	if (k > AES_BLOCK_SZ)
450*6414dc6dSKonstantin Porotchkin 		k = AES_BLOCK_SZ;
451*6414dc6dSKonstantin Porotchkin 	memcpy(IV, opts.sec_opts->aes_key_file, k);
452*6414dc6dSKonstantin Porotchkin 	gettimeofday(&tv, 0);
453*6414dc6dSKonstantin Porotchkin 
454*6414dc6dSKonstantin Porotchkin 	for (i = 0, k = 0; i < AES_BLOCK_SZ; i++,
455*6414dc6dSKonstantin Porotchkin 	     k = (k+1) % sizeof(struct timeval))
456*6414dc6dSKonstantin Porotchkin 		IV[i] ^= ptmp[k];
457*6414dc6dSKonstantin Porotchkin 
458*6414dc6dSKonstantin Porotchkin 	/* compute SHA-256 digest of the results
459*6414dc6dSKonstantin Porotchkin 	 * and use it as the init vector (IV)
460*6414dc6dSKonstantin Porotchkin 	 */
461*6414dc6dSKonstantin Porotchkin 	mbedtls_sha256(IV, AES_BLOCK_SZ, digest, 0);
462*6414dc6dSKonstantin Porotchkin 	memcpy(IV, digest, AES_BLOCK_SZ);
463*6414dc6dSKonstantin Porotchkin 	mbedtls_aes_setkey_enc(&aes_ctx, opts.sec_opts->aes_key,
464*6414dc6dSKonstantin Porotchkin 			       AES_KEY_BIT_LEN);
465*6414dc6dSKonstantin Porotchkin 
466*6414dc6dSKonstantin Porotchkin 	/* The output image has to include extra space for IV
467*6414dc6dSKonstantin Porotchkin 	 * and to be aligned to the AES block size.
468*6414dc6dSKonstantin Porotchkin 	 * The input image buffer has to be already aligned to AES_BLOCK_SZ
469*6414dc6dSKonstantin Porotchkin 	 * and padded with zeroes
470*6414dc6dSKonstantin Porotchkin 	 */
471*6414dc6dSKonstantin Porotchkin 	opts.sec_opts->enc_image_sz = (blen + 2 * AES_BLOCK_SZ - 1) &
472*6414dc6dSKonstantin Porotchkin 				      ~(AES_BLOCK_SZ - 1);
473*6414dc6dSKonstantin Porotchkin 	opts.sec_opts->encrypted_image = calloc(opts.sec_opts->enc_image_sz, 1);
474*6414dc6dSKonstantin Porotchkin 	if (opts.sec_opts->encrypted_image == 0) {
475*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Failed to allocate encrypted image!\n");
476*6414dc6dSKonstantin Porotchkin 		goto encrypt_exit;
477*6414dc6dSKonstantin Porotchkin 	}
478*6414dc6dSKonstantin Porotchkin 
479*6414dc6dSKonstantin Porotchkin 	/* Put IV into the output buffer next to the encrypted image
480*6414dc6dSKonstantin Porotchkin 	 * Since the IV is modified by the encryption function,
481*6414dc6dSKonstantin Porotchkin 	 * this should be done now
482*6414dc6dSKonstantin Porotchkin 	 */
483*6414dc6dSKonstantin Porotchkin 	memcpy(opts.sec_opts->encrypted_image +
484*6414dc6dSKonstantin Porotchkin 		   opts.sec_opts->enc_image_sz - AES_BLOCK_SZ,
485*6414dc6dSKonstantin Porotchkin 		   IV, AES_BLOCK_SZ);
486*6414dc6dSKonstantin Porotchkin 	rval = mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_ENCRYPT,
487*6414dc6dSKonstantin Porotchkin 			     opts.sec_opts->enc_image_sz - AES_BLOCK_SZ,
488*6414dc6dSKonstantin Porotchkin 			     IV, buf, opts.sec_opts->encrypted_image);
489*6414dc6dSKonstantin Porotchkin 	if (rval != 0) {
490*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Failed to encrypt the image! Error %d\n",
491*6414dc6dSKonstantin Porotchkin 			rval);
492*6414dc6dSKonstantin Porotchkin 		goto encrypt_exit;
493*6414dc6dSKonstantin Porotchkin 	}
494*6414dc6dSKonstantin Porotchkin 
495*6414dc6dSKonstantin Porotchkin 	mbedtls_aes_free(&aes_ctx);
496*6414dc6dSKonstantin Porotchkin 
497*6414dc6dSKonstantin Porotchkin 	/* Try to decrypt the image and compare it with the original data */
498*6414dc6dSKonstantin Porotchkin 	mbedtls_aes_init(&aes_ctx);
499*6414dc6dSKonstantin Porotchkin 	mbedtls_aes_setkey_dec(&aes_ctx, opts.sec_opts->aes_key,
500*6414dc6dSKonstantin Porotchkin 			       AES_KEY_BIT_LEN);
501*6414dc6dSKonstantin Porotchkin 
502*6414dc6dSKonstantin Porotchkin 	test_img = calloc(opts.sec_opts->enc_image_sz - AES_BLOCK_SZ, 1);
503*6414dc6dSKonstantin Porotchkin 	if (test_img == 0) {
504*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Failed to allocate test image!d\n");
505*6414dc6dSKonstantin Porotchkin 		rval = -1;
506*6414dc6dSKonstantin Porotchkin 		goto encrypt_exit;
507*6414dc6dSKonstantin Porotchkin 	}
508*6414dc6dSKonstantin Porotchkin 
509*6414dc6dSKonstantin Porotchkin 	memcpy(IV, opts.sec_opts->encrypted_image +
510*6414dc6dSKonstantin Porotchkin 		   opts.sec_opts->enc_image_sz - AES_BLOCK_SZ,
511*6414dc6dSKonstantin Porotchkin 		   AES_BLOCK_SZ);
512*6414dc6dSKonstantin Porotchkin 	rval = mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT,
513*6414dc6dSKonstantin Porotchkin 			     opts.sec_opts->enc_image_sz - AES_BLOCK_SZ,
514*6414dc6dSKonstantin Porotchkin 			     IV, opts.sec_opts->encrypted_image, test_img);
515*6414dc6dSKonstantin Porotchkin 	if (rval != 0) {
516*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Failed to decrypt the image! Error %d\n",
517*6414dc6dSKonstantin Porotchkin 			rval);
518*6414dc6dSKonstantin Porotchkin 		goto encrypt_exit;
519*6414dc6dSKonstantin Porotchkin 	}
520*6414dc6dSKonstantin Porotchkin 
521*6414dc6dSKonstantin Porotchkin 	for (i = 0; i < blen; i++) {
522*6414dc6dSKonstantin Porotchkin 		if (buf[i] != test_img[i]) {
523*6414dc6dSKonstantin Porotchkin 			fprintf(stderr, "Failed to compare the image after");
524*6414dc6dSKonstantin Porotchkin 			fprintf(stderr, " decryption! Byte count is %d\n", i);
525*6414dc6dSKonstantin Porotchkin 			rval = -1;
526*6414dc6dSKonstantin Porotchkin 			goto encrypt_exit;
527*6414dc6dSKonstantin Porotchkin 		}
528*6414dc6dSKonstantin Porotchkin 	}
529*6414dc6dSKonstantin Porotchkin 
530*6414dc6dSKonstantin Porotchkin encrypt_exit:
531*6414dc6dSKonstantin Porotchkin 
532*6414dc6dSKonstantin Porotchkin 	mbedtls_aes_free(&aes_ctx);
533*6414dc6dSKonstantin Porotchkin 	if (test_img)
534*6414dc6dSKonstantin Porotchkin 		free(test_img);
535*6414dc6dSKonstantin Porotchkin 
536*6414dc6dSKonstantin Porotchkin 	return rval;
537*6414dc6dSKonstantin Porotchkin } /* end of image_encrypt */
538*6414dc6dSKonstantin Porotchkin 
539*6414dc6dSKonstantin Porotchkin /*******************************************************************************
540*6414dc6dSKonstantin Porotchkin  *    verify_secure_header_signatures
541*6414dc6dSKonstantin Porotchkin  *          Verify CSK array, header and image signatures and print results
542*6414dc6dSKonstantin Porotchkin  *    INPUT:
543*6414dc6dSKonstantin Porotchkin  *          main_hdr       Main header
544*6414dc6dSKonstantin Porotchkin  *          sec_ext        Secure extension
545*6414dc6dSKonstantin Porotchkin  *    OUTPUT:
546*6414dc6dSKonstantin Porotchkin  *          none
547*6414dc6dSKonstantin Porotchkin  *    RETURN:
548*6414dc6dSKonstantin Porotchkin  *          0 on success
549*6414dc6dSKonstantin Porotchkin  */
550*6414dc6dSKonstantin Porotchkin int verify_secure_header_signatures(header_t *main_hdr, sec_entry_t *sec_ext)
551*6414dc6dSKonstantin Porotchkin {
552*6414dc6dSKonstantin Porotchkin 	uint8_t	*image = (uint8_t *)main_hdr + main_hdr->prolog_size;
553*6414dc6dSKonstantin Porotchkin 	uint8_t	signature[RSA_SIGN_BYTE_LEN];
554*6414dc6dSKonstantin Porotchkin 	int		rval = -1;
555*6414dc6dSKonstantin Porotchkin 
556*6414dc6dSKonstantin Porotchkin 	/* Save headers signature and reset it in the secure header */
557*6414dc6dSKonstantin Porotchkin 	memcpy(signature, sec_ext->header_sign, RSA_SIGN_BYTE_LEN);
558*6414dc6dSKonstantin Porotchkin 	memset(sec_ext->header_sign, 0, RSA_SIGN_BYTE_LEN);
559*6414dc6dSKonstantin Porotchkin 
560*6414dc6dSKonstantin Porotchkin 	fprintf(stdout, "\nCheck RSA Signatures\n");
561*6414dc6dSKonstantin Porotchkin 	fprintf(stdout, "#########################\n");
562*6414dc6dSKonstantin Porotchkin 	fprintf(stdout, "CSK Block Signature: ");
563*6414dc6dSKonstantin Porotchkin 	if (verify_rsa_signature(sec_ext->kak_key,
564*6414dc6dSKonstantin Porotchkin 				 MAX_RSA_DER_BYTE_LEN,
565*6414dc6dSKonstantin Porotchkin 				 &sec_ext->csk_keys[0][0],
566*6414dc6dSKonstantin Porotchkin 				 sizeof(sec_ext->csk_keys),
567*6414dc6dSKonstantin Porotchkin 				 "CSK Block Signature: ",
568*6414dc6dSKonstantin Porotchkin 				 sec_ext->csk_sign) != 0) {
569*6414dc6dSKonstantin Porotchkin 		fprintf(stdout, "ERROR\n");
570*6414dc6dSKonstantin Porotchkin 		goto ver_error;
571*6414dc6dSKonstantin Porotchkin 	}
572*6414dc6dSKonstantin Porotchkin 	fprintf(stdout, "OK\n");
573*6414dc6dSKonstantin Porotchkin 
574*6414dc6dSKonstantin Porotchkin 	if (opts.key_index != -1) {
575*6414dc6dSKonstantin Porotchkin 		fprintf(stdout, "Image Signature:     ");
576*6414dc6dSKonstantin Porotchkin 		if (verify_rsa_signature(sec_ext->csk_keys[opts.key_index],
577*6414dc6dSKonstantin Porotchkin 					 MAX_RSA_DER_BYTE_LEN,
578*6414dc6dSKonstantin Porotchkin 					 image, main_hdr->boot_image_size,
579*6414dc6dSKonstantin Porotchkin 					 "Image Signature: ",
580*6414dc6dSKonstantin Porotchkin 					 sec_ext->image_sign) != 0) {
581*6414dc6dSKonstantin Porotchkin 			fprintf(stdout, "ERROR\n");
582*6414dc6dSKonstantin Porotchkin 			goto ver_error;
583*6414dc6dSKonstantin Porotchkin 		}
584*6414dc6dSKonstantin Porotchkin 		fprintf(stdout, "OK\n");
585*6414dc6dSKonstantin Porotchkin 
586*6414dc6dSKonstantin Porotchkin 		fprintf(stdout, "Header Signature:    ");
587*6414dc6dSKonstantin Porotchkin 		if (verify_rsa_signature(sec_ext->csk_keys[opts.key_index],
588*6414dc6dSKonstantin Porotchkin 					 MAX_RSA_DER_BYTE_LEN,
589*6414dc6dSKonstantin Porotchkin 					 (uint8_t *)main_hdr,
590*6414dc6dSKonstantin Porotchkin 					 main_hdr->prolog_size,
591*6414dc6dSKonstantin Porotchkin 					 "Header Signature: ",
592*6414dc6dSKonstantin Porotchkin 					 signature) != 0) {
593*6414dc6dSKonstantin Porotchkin 			fprintf(stdout, "ERROR\n");
594*6414dc6dSKonstantin Porotchkin 			goto ver_error;
595*6414dc6dSKonstantin Porotchkin 		}
596*6414dc6dSKonstantin Porotchkin 		fprintf(stdout, "OK\n");
597*6414dc6dSKonstantin Porotchkin 	} else {
598*6414dc6dSKonstantin Porotchkin 		fprintf(stdout, "SKIP Image and Header Signatures");
599*6414dc6dSKonstantin Porotchkin 		fprintf(stdout, " check (undefined key index)\n");
600*6414dc6dSKonstantin Porotchkin 	}
601*6414dc6dSKonstantin Porotchkin 
602*6414dc6dSKonstantin Porotchkin 	rval = 0;
603*6414dc6dSKonstantin Porotchkin 
604*6414dc6dSKonstantin Porotchkin ver_error:
605*6414dc6dSKonstantin Porotchkin 	memcpy(sec_ext->header_sign, signature, RSA_SIGN_BYTE_LEN);
606*6414dc6dSKonstantin Porotchkin 	return rval;
607*6414dc6dSKonstantin Porotchkin }
608*6414dc6dSKonstantin Porotchkin 
609*6414dc6dSKonstantin Porotchkin /*******************************************************************************
610*6414dc6dSKonstantin Porotchkin  *    verify_and_copy_file_name_entry
611*6414dc6dSKonstantin Porotchkin  *    INPUT:
612*6414dc6dSKonstantin Porotchkin  *          element_name
613*6414dc6dSKonstantin Porotchkin  *          element
614*6414dc6dSKonstantin Porotchkin  *    OUTPUT:
615*6414dc6dSKonstantin Porotchkin  *          copy_to
616*6414dc6dSKonstantin Porotchkin  *    RETURN:
617*6414dc6dSKonstantin Porotchkin  *          0 on success
618*6414dc6dSKonstantin Porotchkin  */
619*6414dc6dSKonstantin Porotchkin int verify_and_copy_file_name_entry(const char *element_name,
620*6414dc6dSKonstantin Porotchkin 				    const char *element, char *copy_to)
621*6414dc6dSKonstantin Porotchkin {
622*6414dc6dSKonstantin Porotchkin 	int element_length = strlen(element);
623*6414dc6dSKonstantin Porotchkin 
624*6414dc6dSKonstantin Porotchkin 	if (element_length >= MAX_FILENAME) {
625*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "The file name %s for %s is too long (%d). ",
626*6414dc6dSKonstantin Porotchkin 			element, element_name, element_length);
627*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Maximum allowed %d characters!\n",
628*6414dc6dSKonstantin Porotchkin 			MAX_FILENAME);
629*6414dc6dSKonstantin Porotchkin 		return -1;
630*6414dc6dSKonstantin Porotchkin 	} else if (element_length == 0) {
631*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "The file name for %s is empty!\n",
632*6414dc6dSKonstantin Porotchkin 			element_name);
633*6414dc6dSKonstantin Porotchkin 		return -1;
634*6414dc6dSKonstantin Porotchkin 	}
635*6414dc6dSKonstantin Porotchkin 	memcpy(copy_to, element, element_length);
636*6414dc6dSKonstantin Porotchkin 
637*6414dc6dSKonstantin Porotchkin 	return 0;
638*6414dc6dSKonstantin Porotchkin }
639*6414dc6dSKonstantin Porotchkin 
640*6414dc6dSKonstantin Porotchkin /*******************************************************************************
641*6414dc6dSKonstantin Porotchkin  *    parse_sec_config_file
642*6414dc6dSKonstantin Porotchkin  *          Read the secure boot configuration from a file
643*6414dc6dSKonstantin Porotchkin  *          into internal structures
644*6414dc6dSKonstantin Porotchkin  *    INPUT:
645*6414dc6dSKonstantin Porotchkin  *          filename      File name
646*6414dc6dSKonstantin Porotchkin  *    OUTPUT:
647*6414dc6dSKonstantin Porotchkin  *          none
648*6414dc6dSKonstantin Porotchkin  *    RETURN:
649*6414dc6dSKonstantin Porotchkin  *          0 on success
650*6414dc6dSKonstantin Porotchkin  */
651*6414dc6dSKonstantin Porotchkin int parse_sec_config_file(char *filename)
652*6414dc6dSKonstantin Porotchkin {
653*6414dc6dSKonstantin Porotchkin 	config_t		sec_cfg;
654*6414dc6dSKonstantin Porotchkin 	int			array_sz, element, rval = -1;
655*6414dc6dSKonstantin Porotchkin 	const char		*cfg_string;
656*6414dc6dSKonstantin Porotchkin 	int32_t			cfg_int32;
657*6414dc6dSKonstantin Porotchkin 	const config_setting_t	*csk_array, *control_array;
658*6414dc6dSKonstantin Porotchkin 	sec_options		*sec_opt = 0;
659*6414dc6dSKonstantin Porotchkin 
660*6414dc6dSKonstantin Porotchkin 	config_init(&sec_cfg);
661*6414dc6dSKonstantin Porotchkin 
662*6414dc6dSKonstantin Porotchkin 	if (config_read_file(&sec_cfg, filename) != CONFIG_TRUE) {
663*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Failed to read data from config file ");
664*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "%s\n\t%s at line %d\n",
665*6414dc6dSKonstantin Porotchkin 			filename, config_error_text(&sec_cfg),
666*6414dc6dSKonstantin Porotchkin 			config_error_line(&sec_cfg));
667*6414dc6dSKonstantin Porotchkin 		goto exit_parse;
668*6414dc6dSKonstantin Porotchkin 	}
669*6414dc6dSKonstantin Porotchkin 
670*6414dc6dSKonstantin Porotchkin 	sec_opt = (sec_options *)calloc(sizeof(sec_options), 1);
671*6414dc6dSKonstantin Porotchkin 	if (sec_opt == 0) {
672*6414dc6dSKonstantin Porotchkin 		fprintf(stderr,
673*6414dc6dSKonstantin Porotchkin 			"Cannot allocate memory for secure boot options!\n");
674*6414dc6dSKonstantin Porotchkin 		goto exit_parse;
675*6414dc6dSKonstantin Porotchkin 	}
676*6414dc6dSKonstantin Porotchkin 
677*6414dc6dSKonstantin Porotchkin 	/* KAK file name */
678*6414dc6dSKonstantin Porotchkin 	if (config_lookup_string(&sec_cfg, "kak_key_file",
679*6414dc6dSKonstantin Porotchkin 				 &cfg_string) != CONFIG_TRUE) {
680*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "The \"kak_key_file\" undefined!\n");
681*6414dc6dSKonstantin Porotchkin 		goto exit_parse;
682*6414dc6dSKonstantin Porotchkin 	}
683*6414dc6dSKonstantin Porotchkin 	if (verify_and_copy_file_name_entry("kak_key_file",
684*6414dc6dSKonstantin Porotchkin 					    cfg_string, sec_opt->kak_key_file))
685*6414dc6dSKonstantin Porotchkin 		goto exit_parse;
686*6414dc6dSKonstantin Porotchkin 
687*6414dc6dSKonstantin Porotchkin 
688*6414dc6dSKonstantin Porotchkin 	/* AES file name - can be empty/undefined */
689*6414dc6dSKonstantin Porotchkin 	if (config_lookup_string(&sec_cfg, "aes_key_file",
690*6414dc6dSKonstantin Porotchkin 				 &cfg_string) == CONFIG_TRUE) {
691*6414dc6dSKonstantin Porotchkin 		if (verify_and_copy_file_name_entry("aes_key_file",
692*6414dc6dSKonstantin Porotchkin 						    cfg_string,
693*6414dc6dSKonstantin Porotchkin 						    sec_opt->aes_key_file))
694*6414dc6dSKonstantin Porotchkin 			goto exit_parse;
695*6414dc6dSKonstantin Porotchkin 	}
696*6414dc6dSKonstantin Porotchkin 
697*6414dc6dSKonstantin Porotchkin 	/* CSK file names array */
698*6414dc6dSKonstantin Porotchkin 	csk_array = config_lookup(&sec_cfg, "csk_key_file");
699*6414dc6dSKonstantin Porotchkin 	if (csk_array == NULL) {
700*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "The \"csk_key_file\" undefined!\n");
701*6414dc6dSKonstantin Porotchkin 		goto exit_parse;
702*6414dc6dSKonstantin Porotchkin 	}
703*6414dc6dSKonstantin Porotchkin 	array_sz = config_setting_length(csk_array);
704*6414dc6dSKonstantin Porotchkin 	if (array_sz > CSK_ARR_SZ) {
705*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "The \"csk_key_file\" array is too big! ");
706*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Only first %d elements will be used\n",
707*6414dc6dSKonstantin Porotchkin 			CSK_ARR_SZ);
708*6414dc6dSKonstantin Porotchkin 		array_sz = CSK_ARR_SZ;
709*6414dc6dSKonstantin Porotchkin 	} else if (array_sz == 0) {
710*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "The \"csk_key_file\" array is empty!\n");
711*6414dc6dSKonstantin Porotchkin 		goto exit_parse;
712*6414dc6dSKonstantin Porotchkin 	}
713*6414dc6dSKonstantin Porotchkin 
714*6414dc6dSKonstantin Porotchkin 	for (element = 0; element < array_sz; element++) {
715*6414dc6dSKonstantin Porotchkin 		cfg_string = config_setting_get_string_elem(csk_array, element);
716*6414dc6dSKonstantin Porotchkin 		if (verify_and_copy_file_name_entry(
717*6414dc6dSKonstantin Porotchkin 				"csk_key_file", cfg_string,
718*6414dc6dSKonstantin Porotchkin 				sec_opt->csk_key_file[element])) {
719*6414dc6dSKonstantin Porotchkin 			fprintf(stderr, "Bad csk_key_file[%d] entry!\n",
720*6414dc6dSKonstantin Porotchkin 				element);
721*6414dc6dSKonstantin Porotchkin 			goto exit_parse;
722*6414dc6dSKonstantin Porotchkin 		}
723*6414dc6dSKonstantin Porotchkin 	}
724*6414dc6dSKonstantin Porotchkin 
725*6414dc6dSKonstantin Porotchkin 	/* JTAG options */
726*6414dc6dSKonstantin Porotchkin 	if (config_lookup_bool(&sec_cfg, "jtag.enable",
727*6414dc6dSKonstantin Porotchkin 			       &cfg_int32) != CONFIG_TRUE) {
728*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Error obtaining \"jtag.enable\" element. ");
729*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Using default - FALSE\n");
730*6414dc6dSKonstantin Porotchkin 		cfg_int32 = 0;
731*6414dc6dSKonstantin Porotchkin 	}
732*6414dc6dSKonstantin Porotchkin 	sec_opt->jtag_enable = cfg_int32;
733*6414dc6dSKonstantin Porotchkin 
734*6414dc6dSKonstantin Porotchkin 	if (config_lookup_int(&sec_cfg, "jtag.delay",
735*6414dc6dSKonstantin Porotchkin 			      &cfg_int32) != CONFIG_TRUE) {
736*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Error obtaining \"jtag.delay\" element. ");
737*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Using default - 0us\n");
738*6414dc6dSKonstantin Porotchkin 		cfg_int32 = 0;
739*6414dc6dSKonstantin Porotchkin 	}
740*6414dc6dSKonstantin Porotchkin 	sec_opt->jtag_delay = cfg_int32;
741*6414dc6dSKonstantin Porotchkin 
742*6414dc6dSKonstantin Porotchkin 	/* eFUSE option */
743*6414dc6dSKonstantin Porotchkin 	if (config_lookup_bool(&sec_cfg, "efuse_disable",
744*6414dc6dSKonstantin Porotchkin 			       &cfg_int32) != CONFIG_TRUE) {
745*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Error obtaining \"efuse_disable\" element. ");
746*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Using default - TRUE\n");
747*6414dc6dSKonstantin Porotchkin 		cfg_int32 = 1;
748*6414dc6dSKonstantin Porotchkin 	}
749*6414dc6dSKonstantin Porotchkin 	sec_opt->efuse_disable = cfg_int32;
750*6414dc6dSKonstantin Porotchkin 
751*6414dc6dSKonstantin Porotchkin 	/* Box ID option */
752*6414dc6dSKonstantin Porotchkin 	if (config_lookup_int(&sec_cfg, "box_id", &cfg_int32) != CONFIG_TRUE) {
753*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Error obtaining \"box_id\" element. ");
754*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Using default - 0x0\n");
755*6414dc6dSKonstantin Porotchkin 		cfg_int32 = 0;
756*6414dc6dSKonstantin Porotchkin 	}
757*6414dc6dSKonstantin Porotchkin 	sec_opt->box_id = cfg_int32;
758*6414dc6dSKonstantin Porotchkin 
759*6414dc6dSKonstantin Porotchkin 	/* Flash ID option */
760*6414dc6dSKonstantin Porotchkin 	if (config_lookup_int(&sec_cfg, "flash_id",
761*6414dc6dSKonstantin Porotchkin 			      &cfg_int32) != CONFIG_TRUE) {
762*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Error obtaining \"flash_id\" element. ");
763*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Using default - 0x0\n");
764*6414dc6dSKonstantin Porotchkin 		cfg_int32 = 0;
765*6414dc6dSKonstantin Porotchkin 	}
766*6414dc6dSKonstantin Porotchkin 	sec_opt->flash_id = cfg_int32;
767*6414dc6dSKonstantin Porotchkin 
768*6414dc6dSKonstantin Porotchkin 	/* CSK index option */
769*6414dc6dSKonstantin Porotchkin 	if (config_lookup_int(&sec_cfg, "csk_key_index",
770*6414dc6dSKonstantin Porotchkin 			      &cfg_int32) != CONFIG_TRUE) {
771*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Error obtaining \"flash_id\" element. ");
772*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Using default - 0x0\n");
773*6414dc6dSKonstantin Porotchkin 		cfg_int32 = 0;
774*6414dc6dSKonstantin Porotchkin 	}
775*6414dc6dSKonstantin Porotchkin 	sec_opt->csk_index = cfg_int32;
776*6414dc6dSKonstantin Porotchkin 
777*6414dc6dSKonstantin Porotchkin 	/* Secure boot control array */
778*6414dc6dSKonstantin Porotchkin 	control_array = config_lookup(&sec_cfg, "control");
779*6414dc6dSKonstantin Porotchkin 	if (control_array != NULL) {
780*6414dc6dSKonstantin Porotchkin 		array_sz = config_setting_length(control_array);
781*6414dc6dSKonstantin Porotchkin 		if (array_sz == 0)
782*6414dc6dSKonstantin Porotchkin 			fprintf(stderr, "The \"control\" array is empty!\n");
783*6414dc6dSKonstantin Porotchkin 	} else {
784*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "The \"control\" is undefined!\n");
785*6414dc6dSKonstantin Porotchkin 		array_sz = 0;
786*6414dc6dSKonstantin Porotchkin 	}
787*6414dc6dSKonstantin Porotchkin 
788*6414dc6dSKonstantin Porotchkin 	for (element = 0; element < CP_CTRL_EL_ARRAY_SZ; element++) {
789*6414dc6dSKonstantin Porotchkin 		sec_opt->cp_ctrl_arr[element] =
790*6414dc6dSKonstantin Porotchkin 			config_setting_get_int_elem(control_array, element * 2);
791*6414dc6dSKonstantin Porotchkin 		sec_opt->cp_efuse_arr[element] =
792*6414dc6dSKonstantin Porotchkin 			config_setting_get_int_elem(control_array,
793*6414dc6dSKonstantin Porotchkin 						    element * 2 + 1);
794*6414dc6dSKonstantin Porotchkin 	}
795*6414dc6dSKonstantin Porotchkin 
796*6414dc6dSKonstantin Porotchkin 	opts.sec_opts = sec_opt;
797*6414dc6dSKonstantin Porotchkin 	rval = 0;
798*6414dc6dSKonstantin Porotchkin 
799*6414dc6dSKonstantin Porotchkin exit_parse:
800*6414dc6dSKonstantin Porotchkin 	config_destroy(&sec_cfg);
801*6414dc6dSKonstantin Porotchkin 	if (sec_opt && (rval != 0))
802*6414dc6dSKonstantin Porotchkin 		free(sec_opt);
803*6414dc6dSKonstantin Porotchkin 	return rval;
804*6414dc6dSKonstantin Porotchkin } /* end of parse_sec_config_file */
805*6414dc6dSKonstantin Porotchkin 
806*6414dc6dSKonstantin Porotchkin int format_sec_ext(char *filename, FILE *out_fd)
807*6414dc6dSKonstantin Porotchkin {
808*6414dc6dSKonstantin Porotchkin 	ext_header_t	header;
809*6414dc6dSKonstantin Porotchkin 	sec_entry_t	sec_ext;
810*6414dc6dSKonstantin Porotchkin 	int		index;
811*6414dc6dSKonstantin Porotchkin 	int		written;
812*6414dc6dSKonstantin Porotchkin 
813*6414dc6dSKonstantin Porotchkin #define DER_BUF_SZ	1600
814*6414dc6dSKonstantin Porotchkin 
815*6414dc6dSKonstantin Porotchkin 	/* First, parse the configuration file */
816*6414dc6dSKonstantin Porotchkin 	if (parse_sec_config_file(filename)) {
817*6414dc6dSKonstantin Porotchkin 		fprintf(stderr,
818*6414dc6dSKonstantin Porotchkin 			"failed parsing configuration file %s\n", filename);
819*6414dc6dSKonstantin Porotchkin 		return 1;
820*6414dc6dSKonstantin Porotchkin 	}
821*6414dc6dSKonstantin Porotchkin 
822*6414dc6dSKonstantin Porotchkin 	/* Everything except signatures can be created at this stage */
823*6414dc6dSKonstantin Porotchkin 	header.type = EXT_TYPE_SECURITY;
824*6414dc6dSKonstantin Porotchkin 	header.offset = 0;
825*6414dc6dSKonstantin Porotchkin 	header.size = sizeof(sec_entry_t);
826*6414dc6dSKonstantin Porotchkin 	header.reserved = 0;
827*6414dc6dSKonstantin Porotchkin 
828*6414dc6dSKonstantin Porotchkin 	/* Bring up RSA context and read private keys from their files */
829*6414dc6dSKonstantin Porotchkin 	for (index = 0; index < (CSK_ARR_SZ + 1); index++) {
830*6414dc6dSKonstantin Porotchkin 		/* for every private key file */
831*6414dc6dSKonstantin Porotchkin 		mbedtls_pk_context	*pk_ctx = (index == CSK_ARR_SZ) ?
832*6414dc6dSKonstantin Porotchkin 					&opts.sec_opts->kak_pk :
833*6414dc6dSKonstantin Porotchkin 					&opts.sec_opts->csk_pk[index];
834*6414dc6dSKonstantin Porotchkin 		char		*fname = (index == CSK_ARR_SZ) ?
835*6414dc6dSKonstantin Porotchkin 					opts.sec_opts->kak_key_file :
836*6414dc6dSKonstantin Porotchkin 					opts.sec_opts->csk_key_file[index];
837*6414dc6dSKonstantin Porotchkin 		uint8_t		*out_der_key = (index == CSK_ARR_SZ) ?
838*6414dc6dSKonstantin Porotchkin 					sec_ext.kak_key :
839*6414dc6dSKonstantin Porotchkin 					sec_ext.csk_keys[index];
840*6414dc6dSKonstantin Porotchkin 		size_t		output_len;
841*6414dc6dSKonstantin Porotchkin 		unsigned char	output_buf[DER_BUF_SZ];
842*6414dc6dSKonstantin Porotchkin 		unsigned char	*der_buf_start;
843*6414dc6dSKonstantin Porotchkin 
844*6414dc6dSKonstantin Porotchkin 		/* Handle invalid/reserved file names */
845*6414dc6dSKonstantin Porotchkin 		if (strncmp(CSK_ARR_EMPTY_FILE, fname,
846*6414dc6dSKonstantin Porotchkin 			    strlen(CSK_ARR_EMPTY_FILE)) == 0) {
847*6414dc6dSKonstantin Porotchkin 			if (opts.sec_opts->csk_index == index) {
848*6414dc6dSKonstantin Porotchkin 				fprintf(stderr,
849*6414dc6dSKonstantin Porotchkin 					"CSK file with index %d cannot be %s\n",
850*6414dc6dSKonstantin Porotchkin 					index, CSK_ARR_EMPTY_FILE);
851*6414dc6dSKonstantin Porotchkin 				return 1;
852*6414dc6dSKonstantin Porotchkin 			} else if (index == CSK_ARR_SZ) {
853*6414dc6dSKonstantin Porotchkin 				fprintf(stderr, "KAK file name cannot be %s\n",
854*6414dc6dSKonstantin Porotchkin 					CSK_ARR_EMPTY_FILE);
855*6414dc6dSKonstantin Porotchkin 				return 1;
856*6414dc6dSKonstantin Porotchkin 			}
857*6414dc6dSKonstantin Porotchkin 			/* this key will be empty in CSK array */
858*6414dc6dSKonstantin Porotchkin 			continue;
859*6414dc6dSKonstantin Porotchkin 		}
860*6414dc6dSKonstantin Porotchkin 
861*6414dc6dSKonstantin Porotchkin 		mbedtls_pk_init(pk_ctx);
862*6414dc6dSKonstantin Porotchkin 		/* Read the private RSA key into the context
863*6414dc6dSKonstantin Porotchkin 		 * and verify it (no password)
864*6414dc6dSKonstantin Porotchkin 		 */
865*6414dc6dSKonstantin Porotchkin 		if (mbedtls_pk_parse_keyfile(pk_ctx, fname, "") != 0) {
866*6414dc6dSKonstantin Porotchkin 			fprintf(stderr,
867*6414dc6dSKonstantin Porotchkin 				"Cannot read RSA private key file %s\n", fname);
868*6414dc6dSKonstantin Porotchkin 			return 1;
869*6414dc6dSKonstantin Porotchkin 		}
870*6414dc6dSKonstantin Porotchkin 
871*6414dc6dSKonstantin Porotchkin 		/* Create a public key out of private one
872*6414dc6dSKonstantin Porotchkin 		 * and store it in DER format
873*6414dc6dSKonstantin Porotchkin 		 */
874*6414dc6dSKonstantin Porotchkin 		output_len = mbedtls_pk_write_pubkey_der(pk_ctx,
875*6414dc6dSKonstantin Porotchkin 							 output_buf,
876*6414dc6dSKonstantin Porotchkin 							 DER_BUF_SZ);
877*6414dc6dSKonstantin Porotchkin 		if (output_len < 0) {
878*6414dc6dSKonstantin Porotchkin 			fprintf(stderr,
879*6414dc6dSKonstantin Porotchkin 				"Failed to create DER coded PUB key (%s)\n",
880*6414dc6dSKonstantin Porotchkin 				fname);
881*6414dc6dSKonstantin Porotchkin 			return 1;
882*6414dc6dSKonstantin Porotchkin 		}
883*6414dc6dSKonstantin Porotchkin 		/* Data in the output buffer is aligned to the buffer end */
884*6414dc6dSKonstantin Porotchkin 		der_buf_start = output_buf + sizeof(output_buf) - output_len;
885*6414dc6dSKonstantin Porotchkin 		/* In the header DER data is aligned
886*6414dc6dSKonstantin Porotchkin 		 * to the start of appropriate field
887*6414dc6dSKonstantin Porotchkin 		 */
888*6414dc6dSKonstantin Porotchkin 		memcpy(out_der_key, der_buf_start, output_len);
889*6414dc6dSKonstantin Porotchkin 
890*6414dc6dSKonstantin Porotchkin 	} /* for every private key file */
891*6414dc6dSKonstantin Porotchkin 
892*6414dc6dSKonstantin Porotchkin 	/* The CSK block signature can be created here */
893*6414dc6dSKonstantin Porotchkin 	if (create_rsa_signature(&opts.sec_opts->kak_pk,
894*6414dc6dSKonstantin Porotchkin 				 &sec_ext.csk_keys[0][0],
895*6414dc6dSKonstantin Porotchkin 				 sizeof(sec_ext.csk_keys),
896*6414dc6dSKonstantin Porotchkin 				 opts.sec_opts->csk_key_file[
897*6414dc6dSKonstantin Porotchkin 					 opts.sec_opts->csk_index],
898*6414dc6dSKonstantin Porotchkin 				 sec_ext.csk_sign) != 0) {
899*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Failed to sign CSK keys block!\n");
900*6414dc6dSKonstantin Porotchkin 		return 1;
901*6414dc6dSKonstantin Porotchkin 	}
902*6414dc6dSKonstantin Porotchkin 	/* Check that everything is correct */
903*6414dc6dSKonstantin Porotchkin 	if (verify_rsa_signature(sec_ext.kak_key, MAX_RSA_DER_BYTE_LEN,
904*6414dc6dSKonstantin Porotchkin 				 &sec_ext.csk_keys[0][0],
905*6414dc6dSKonstantin Porotchkin 				 sizeof(sec_ext.csk_keys),
906*6414dc6dSKonstantin Porotchkin 				 opts.sec_opts->kak_key_file,
907*6414dc6dSKonstantin Porotchkin 				 sec_ext.csk_sign) != 0) {
908*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Failed to verify CSK keys block signature!\n");
909*6414dc6dSKonstantin Porotchkin 		return 1;
910*6414dc6dSKonstantin Porotchkin 	}
911*6414dc6dSKonstantin Porotchkin 
912*6414dc6dSKonstantin Porotchkin 	/* AES encryption stuff */
913*6414dc6dSKonstantin Porotchkin 	if (strlen(opts.sec_opts->aes_key_file) != 0) {
914*6414dc6dSKonstantin Porotchkin 		FILE		*in_fd;
915*6414dc6dSKonstantin Porotchkin 
916*6414dc6dSKonstantin Porotchkin 		in_fd = fopen(opts.sec_opts->aes_key_file, "rb");
917*6414dc6dSKonstantin Porotchkin 		if (in_fd == NULL) {
918*6414dc6dSKonstantin Porotchkin 			fprintf(stderr, "Failed to open AES key file %s\n",
919*6414dc6dSKonstantin Porotchkin 				opts.sec_opts->aes_key_file);
920*6414dc6dSKonstantin Porotchkin 			return 1;
921*6414dc6dSKonstantin Porotchkin 		}
922*6414dc6dSKonstantin Porotchkin 
923*6414dc6dSKonstantin Porotchkin 		/* Read the AES key in ASCII format byte by byte */
924*6414dc6dSKonstantin Porotchkin 		for (index = 0; index < AES_KEY_BYTE_LEN; index++) {
925*6414dc6dSKonstantin Porotchkin 			if (fscanf(in_fd, "%02hhx",
926*6414dc6dSKonstantin Porotchkin 			    opts.sec_opts->aes_key + index) != 1) {
927*6414dc6dSKonstantin Porotchkin 				fprintf(stderr,
928*6414dc6dSKonstantin Porotchkin 					"Failed to read AES key byte %d ",
929*6414dc6dSKonstantin Porotchkin 					index);
930*6414dc6dSKonstantin Porotchkin 				fprintf(stderr,
931*6414dc6dSKonstantin Porotchkin 					"from file %s\n",
932*6414dc6dSKonstantin Porotchkin 					opts.sec_opts->aes_key_file);
933*6414dc6dSKonstantin Porotchkin 				fclose(in_fd);
934*6414dc6dSKonstantin Porotchkin 				return 1;
935*6414dc6dSKonstantin Porotchkin 			}
936*6414dc6dSKonstantin Porotchkin 		}
937*6414dc6dSKonstantin Porotchkin 		fclose(in_fd);
938*6414dc6dSKonstantin Porotchkin 		sec_ext.encrypt_en = 1;
939*6414dc6dSKonstantin Porotchkin 	} else {
940*6414dc6dSKonstantin Porotchkin 		sec_ext.encrypt_en = 0;
941*6414dc6dSKonstantin Porotchkin 	}
942*6414dc6dSKonstantin Porotchkin 
943*6414dc6dSKonstantin Porotchkin 	/* Fill the rest of the trusted boot extension fields */
944*6414dc6dSKonstantin Porotchkin 	sec_ext.box_id		= opts.sec_opts->box_id;
945*6414dc6dSKonstantin Porotchkin 	sec_ext.flash_id	= opts.sec_opts->flash_id;
946*6414dc6dSKonstantin Porotchkin 	sec_ext.efuse_dis	= opts.sec_opts->efuse_disable;
947*6414dc6dSKonstantin Porotchkin 	sec_ext.jtag_delay	= opts.sec_opts->jtag_delay;
948*6414dc6dSKonstantin Porotchkin 	sec_ext.jtag_en		= opts.sec_opts->jtag_enable;
949*6414dc6dSKonstantin Porotchkin 
950*6414dc6dSKonstantin Porotchkin 	memcpy(sec_ext.cp_ctrl_arr,
951*6414dc6dSKonstantin Porotchkin 	       opts.sec_opts->cp_ctrl_arr,
952*6414dc6dSKonstantin Porotchkin 	       sizeof(uint32_t) * CP_CTRL_EL_ARRAY_SZ);
953*6414dc6dSKonstantin Porotchkin 	memcpy(sec_ext.cp_efuse_arr,
954*6414dc6dSKonstantin Porotchkin 	       opts.sec_opts->cp_efuse_arr,
955*6414dc6dSKonstantin Porotchkin 	       sizeof(uint32_t) * CP_CTRL_EL_ARRAY_SZ);
956*6414dc6dSKonstantin Porotchkin 
957*6414dc6dSKonstantin Porotchkin 	/* Write the resulting extension to file
958*6414dc6dSKonstantin Porotchkin 	 * (image and header signature fields are still empty)
959*6414dc6dSKonstantin Porotchkin 	 */
960*6414dc6dSKonstantin Porotchkin 
961*6414dc6dSKonstantin Porotchkin 	/* Write extension header */
962*6414dc6dSKonstantin Porotchkin 	written = fwrite(&header, sizeof(ext_header_t), 1, out_fd);
963*6414dc6dSKonstantin Porotchkin 	if (written != 1) {
964*6414dc6dSKonstantin Porotchkin 		fprintf(stderr,
965*6414dc6dSKonstantin Porotchkin 			"Failed to write SEC extension header to the file\n");
966*6414dc6dSKonstantin Porotchkin 		return 1;
967*6414dc6dSKonstantin Porotchkin 	}
968*6414dc6dSKonstantin Porotchkin 	/* Write extension body */
969*6414dc6dSKonstantin Porotchkin 	written = fwrite(&sec_ext, sizeof(sec_entry_t), 1, out_fd);
970*6414dc6dSKonstantin Porotchkin 	if (written != 1) {
971*6414dc6dSKonstantin Porotchkin 		fprintf(stderr,
972*6414dc6dSKonstantin Porotchkin 			"Failed to write SEC extension body to the file\n");
973*6414dc6dSKonstantin Porotchkin 		return 1;
974*6414dc6dSKonstantin Porotchkin 	}
975*6414dc6dSKonstantin Porotchkin 
976*6414dc6dSKonstantin Porotchkin 	return 0;
977*6414dc6dSKonstantin Porotchkin }
978*6414dc6dSKonstantin Porotchkin 
979*6414dc6dSKonstantin Porotchkin /*******************************************************************************
980*6414dc6dSKonstantin Porotchkin  *    finalize_secure_ext
981*6414dc6dSKonstantin Porotchkin  *          Make final changes to secure extension - calculate image and header
982*6414dc6dSKonstantin Porotchkin  *          signatures and encrypt the image if needed.
983*6414dc6dSKonstantin Porotchkin  *          The main header checksum and image size fields updated accordingly
984*6414dc6dSKonstantin Porotchkin  *    INPUT:
985*6414dc6dSKonstantin Porotchkin  *          header       Main header
986*6414dc6dSKonstantin Porotchkin  *          prolog_buf   the entire prolog buffer
987*6414dc6dSKonstantin Porotchkin  *          prolog_size  prolog buffer length
988*6414dc6dSKonstantin Porotchkin  *          image_buf    buffer containing the input binary image
989*6414dc6dSKonstantin Porotchkin  *          image_size   image buffer size.
990*6414dc6dSKonstantin Porotchkin  *    OUTPUT:
991*6414dc6dSKonstantin Porotchkin  *          none
992*6414dc6dSKonstantin Porotchkin  *    RETURN:
993*6414dc6dSKonstantin Porotchkin  *          0 on success
994*6414dc6dSKonstantin Porotchkin  */
995*6414dc6dSKonstantin Porotchkin int finalize_secure_ext(header_t *header,
996*6414dc6dSKonstantin Porotchkin 			uint8_t *prolog_buf, uint32_t prolog_size,
997*6414dc6dSKonstantin Porotchkin 			uint8_t *image_buf, int image_size)
998*6414dc6dSKonstantin Porotchkin {
999*6414dc6dSKonstantin Porotchkin 	int		cur_ext, offset;
1000*6414dc6dSKonstantin Porotchkin 	uint8_t		*final_image = image_buf;
1001*6414dc6dSKonstantin Porotchkin 	uint32_t	final_image_sz = image_size;
1002*6414dc6dSKonstantin Porotchkin 	uint8_t		hdr_sign[RSA_SIGN_BYTE_LEN];
1003*6414dc6dSKonstantin Porotchkin 	sec_entry_t	*sec_ext = 0;
1004*6414dc6dSKonstantin Porotchkin 
1005*6414dc6dSKonstantin Porotchkin 	/* Find the Trusted Boot Header between available extensions */
1006*6414dc6dSKonstantin Porotchkin 	for (cur_ext = 0, offset = sizeof(header_t);
1007*6414dc6dSKonstantin Porotchkin 	     cur_ext < header->ext_count; cur_ext++) {
1008*6414dc6dSKonstantin Porotchkin 		ext_header_t *ext_hdr = (ext_header_t *)(prolog_buf + offset);
1009*6414dc6dSKonstantin Porotchkin 
1010*6414dc6dSKonstantin Porotchkin 		if (ext_hdr->type == EXT_TYPE_SECURITY) {
1011*6414dc6dSKonstantin Porotchkin 			sec_ext = (sec_entry_t *)(prolog_buf + offset +
1012*6414dc6dSKonstantin Porotchkin 				   sizeof(ext_header_t) + ext_hdr->offset);
1013*6414dc6dSKonstantin Porotchkin 			break;
1014*6414dc6dSKonstantin Porotchkin 		}
1015*6414dc6dSKonstantin Porotchkin 
1016*6414dc6dSKonstantin Porotchkin 		offset += sizeof(ext_header_t);
1017*6414dc6dSKonstantin Porotchkin 		/* If offset is Zero, the extension follows its header */
1018*6414dc6dSKonstantin Porotchkin 		if (ext_hdr->offset == 0)
1019*6414dc6dSKonstantin Porotchkin 			offset += ext_hdr->size;
1020*6414dc6dSKonstantin Porotchkin 	}
1021*6414dc6dSKonstantin Porotchkin 
1022*6414dc6dSKonstantin Porotchkin 	if (sec_ext == 0) {
1023*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Error: No Trusted Boot extension found!\n");
1024*6414dc6dSKonstantin Porotchkin 		return -1;
1025*6414dc6dSKonstantin Porotchkin 	}
1026*6414dc6dSKonstantin Porotchkin 
1027*6414dc6dSKonstantin Porotchkin 	if (sec_ext->encrypt_en) {
1028*6414dc6dSKonstantin Porotchkin 		/* Encrypt the image if needed */
1029*6414dc6dSKonstantin Porotchkin 		fprintf(stdout, "Encrypting the image...\n");
1030*6414dc6dSKonstantin Porotchkin 
1031*6414dc6dSKonstantin Porotchkin 		if (image_encrypt(image_buf, image_size) != 0) {
1032*6414dc6dSKonstantin Porotchkin 			fprintf(stderr, "Failed to encrypt the image!\n");
1033*6414dc6dSKonstantin Porotchkin 			return -1;
1034*6414dc6dSKonstantin Porotchkin 		}
1035*6414dc6dSKonstantin Porotchkin 
1036*6414dc6dSKonstantin Porotchkin 		/* Image size and checksum should be updated after encryption.
1037*6414dc6dSKonstantin Porotchkin 		 * This way the image could be verified by the BootROM
1038*6414dc6dSKonstantin Porotchkin 		 * before decryption.
1039*6414dc6dSKonstantin Porotchkin 		 */
1040*6414dc6dSKonstantin Porotchkin 		final_image = opts.sec_opts->encrypted_image;
1041*6414dc6dSKonstantin Porotchkin 		final_image_sz = opts.sec_opts->enc_image_sz;
1042*6414dc6dSKonstantin Porotchkin 
1043*6414dc6dSKonstantin Porotchkin 		header->boot_image_size = final_image_sz;
1044*6414dc6dSKonstantin Porotchkin 		header->boot_image_checksum =
1045*6414dc6dSKonstantin Porotchkin 			checksum32((uint32_t *)final_image, final_image_sz);
1046*6414dc6dSKonstantin Porotchkin 	} /* AES encryption */
1047*6414dc6dSKonstantin Porotchkin 
1048*6414dc6dSKonstantin Porotchkin 	/* Create the image signature first, since it will be later
1049*6414dc6dSKonstantin Porotchkin 	 * signed along with the header signature
1050*6414dc6dSKonstantin Porotchkin 	 */
1051*6414dc6dSKonstantin Porotchkin 	if (create_rsa_signature(&opts.sec_opts->csk_pk[
1052*6414dc6dSKonstantin Porotchkin 					opts.sec_opts->csk_index],
1053*6414dc6dSKonstantin Porotchkin 				 final_image, final_image_sz,
1054*6414dc6dSKonstantin Porotchkin 				 opts.sec_opts->csk_key_file[
1055*6414dc6dSKonstantin Porotchkin 					opts.sec_opts->csk_index],
1056*6414dc6dSKonstantin Porotchkin 				 sec_ext->image_sign) != 0) {
1057*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Failed to sign image!\n");
1058*6414dc6dSKonstantin Porotchkin 		return -1;
1059*6414dc6dSKonstantin Porotchkin 	}
1060*6414dc6dSKonstantin Porotchkin 	/* Check that the image signature is correct */
1061*6414dc6dSKonstantin Porotchkin 	if (verify_rsa_signature(sec_ext->csk_keys[opts.sec_opts->csk_index],
1062*6414dc6dSKonstantin Porotchkin 				 MAX_RSA_DER_BYTE_LEN,
1063*6414dc6dSKonstantin Porotchkin 				 final_image, final_image_sz,
1064*6414dc6dSKonstantin Porotchkin 				 opts.sec_opts->csk_key_file[
1065*6414dc6dSKonstantin Porotchkin 					 opts.sec_opts->csk_index],
1066*6414dc6dSKonstantin Porotchkin 				 sec_ext->image_sign) != 0) {
1067*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Failed to verify image signature!\n");
1068*6414dc6dSKonstantin Porotchkin 		return -1;
1069*6414dc6dSKonstantin Porotchkin 	}
1070*6414dc6dSKonstantin Porotchkin 
1071*6414dc6dSKonstantin Porotchkin 	/* Sign the headers and all the extensions block
1072*6414dc6dSKonstantin Porotchkin 	 * when the header signature field is empty
1073*6414dc6dSKonstantin Porotchkin 	 */
1074*6414dc6dSKonstantin Porotchkin 	if (create_rsa_signature(&opts.sec_opts->csk_pk[
1075*6414dc6dSKonstantin Porotchkin 					 opts.sec_opts->csk_index],
1076*6414dc6dSKonstantin Porotchkin 				 prolog_buf, prolog_size,
1077*6414dc6dSKonstantin Porotchkin 				 opts.sec_opts->csk_key_file[
1078*6414dc6dSKonstantin Porotchkin 					 opts.sec_opts->csk_index],
1079*6414dc6dSKonstantin Porotchkin 				 hdr_sign) != 0) {
1080*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Failed to sign header!\n");
1081*6414dc6dSKonstantin Porotchkin 		return -1;
1082*6414dc6dSKonstantin Porotchkin 	}
1083*6414dc6dSKonstantin Porotchkin 	/* Check that the header signature is correct */
1084*6414dc6dSKonstantin Porotchkin 	if (verify_rsa_signature(sec_ext->csk_keys[opts.sec_opts->csk_index],
1085*6414dc6dSKonstantin Porotchkin 				 MAX_RSA_DER_BYTE_LEN,
1086*6414dc6dSKonstantin Porotchkin 				 prolog_buf, prolog_size,
1087*6414dc6dSKonstantin Porotchkin 				 opts.sec_opts->csk_key_file[
1088*6414dc6dSKonstantin Porotchkin 					 opts.sec_opts->csk_index],
1089*6414dc6dSKonstantin Porotchkin 				 hdr_sign) != 0) {
1090*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Failed to verify header signature!\n");
1091*6414dc6dSKonstantin Porotchkin 		return -1;
1092*6414dc6dSKonstantin Porotchkin 	}
1093*6414dc6dSKonstantin Porotchkin 
1094*6414dc6dSKonstantin Porotchkin 	/* Finally, copy the header signature into the trusted boot extension */
1095*6414dc6dSKonstantin Porotchkin 	memcpy(sec_ext->header_sign, hdr_sign, RSA_SIGN_BYTE_LEN);
1096*6414dc6dSKonstantin Porotchkin 
1097*6414dc6dSKonstantin Porotchkin 	return 0;
1098*6414dc6dSKonstantin Porotchkin }
1099*6414dc6dSKonstantin Porotchkin 
1100*6414dc6dSKonstantin Porotchkin #endif /* CONFIG_MVEBU_SECURE_BOOT */
1101*6414dc6dSKonstantin Porotchkin 
1102*6414dc6dSKonstantin Porotchkin 
1103*6414dc6dSKonstantin Porotchkin #define FMT_HEX		0
1104*6414dc6dSKonstantin Porotchkin #define FMT_DEC		1
1105*6414dc6dSKonstantin Porotchkin #define FMT_BIN		2
1106*6414dc6dSKonstantin Porotchkin #define FMT_NONE	3
1107*6414dc6dSKonstantin Porotchkin 
1108*6414dc6dSKonstantin Porotchkin void do_print_field(unsigned int value, char *name,
1109*6414dc6dSKonstantin Porotchkin 		    int start, int size, int format)
1110*6414dc6dSKonstantin Porotchkin {
1111*6414dc6dSKonstantin Porotchkin 	fprintf(stdout, "[0x%05x : 0x%05x]  %-26s",
1112*6414dc6dSKonstantin Porotchkin 		start, start + size - 1, name);
1113*6414dc6dSKonstantin Porotchkin 
1114*6414dc6dSKonstantin Porotchkin 	switch (format) {
1115*6414dc6dSKonstantin Porotchkin 	case FMT_HEX:
1116*6414dc6dSKonstantin Porotchkin 		printf("0x%x\n", value);
1117*6414dc6dSKonstantin Porotchkin 		break;
1118*6414dc6dSKonstantin Porotchkin 	case FMT_DEC:
1119*6414dc6dSKonstantin Porotchkin 		printf("%d\n", value);
1120*6414dc6dSKonstantin Porotchkin 		break;
1121*6414dc6dSKonstantin Porotchkin 	default:
1122*6414dc6dSKonstantin Porotchkin 		printf("\n");
1123*6414dc6dSKonstantin Porotchkin 		break;
1124*6414dc6dSKonstantin Porotchkin 	}
1125*6414dc6dSKonstantin Porotchkin }
1126*6414dc6dSKonstantin Porotchkin 
1127*6414dc6dSKonstantin Porotchkin #define print_field(st, type, field, hex, base) \
1128*6414dc6dSKonstantin Porotchkin 			do_print_field((int)st->field, #field, \
1129*6414dc6dSKonstantin Porotchkin 			base + offsetof(type, field), sizeof(st->field), hex)
1130*6414dc6dSKonstantin Porotchkin 
1131*6414dc6dSKonstantin Porotchkin int print_header(uint8_t *buf, int base)
1132*6414dc6dSKonstantin Porotchkin {
1133*6414dc6dSKonstantin Porotchkin 	header_t *main_hdr;
1134*6414dc6dSKonstantin Porotchkin 
1135*6414dc6dSKonstantin Porotchkin 	main_hdr = (header_t *)buf;
1136*6414dc6dSKonstantin Porotchkin 
1137*6414dc6dSKonstantin Porotchkin 	fprintf(stdout, "########### Header ##############\n");
1138*6414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, magic, FMT_HEX, base);
1139*6414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, prolog_size, FMT_DEC, base);
1140*6414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, prolog_checksum, FMT_HEX, base);
1141*6414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, boot_image_size, FMT_DEC, base);
1142*6414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, boot_image_checksum, FMT_HEX, base);
1143*6414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, rsrvd0, FMT_HEX, base);
1144*6414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, load_addr, FMT_HEX, base);
1145*6414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, exec_addr, FMT_HEX, base);
1146*6414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, uart_cfg, FMT_HEX, base);
1147*6414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, baudrate, FMT_HEX, base);
1148*6414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, ext_count, FMT_DEC, base);
1149*6414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, aux_flags, FMT_HEX, base);
1150*6414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, io_arg_0, FMT_HEX, base);
1151*6414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, io_arg_1, FMT_HEX, base);
1152*6414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, io_arg_2, FMT_HEX, base);
1153*6414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, io_arg_3, FMT_HEX, base);
1154*6414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, rsrvd1, FMT_HEX, base);
1155*6414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, rsrvd2, FMT_HEX, base);
1156*6414dc6dSKonstantin Porotchkin 	print_field(main_hdr, header_t, rsrvd3, FMT_HEX, base);
1157*6414dc6dSKonstantin Porotchkin 
1158*6414dc6dSKonstantin Porotchkin 	return sizeof(header_t);
1159*6414dc6dSKonstantin Porotchkin }
1160*6414dc6dSKonstantin Porotchkin 
1161*6414dc6dSKonstantin Porotchkin int print_ext_hdr(ext_header_t *ext_hdr, int base)
1162*6414dc6dSKonstantin Porotchkin {
1163*6414dc6dSKonstantin Porotchkin 	print_field(ext_hdr, ext_header_t, type, FMT_HEX, base);
1164*6414dc6dSKonstantin Porotchkin 	print_field(ext_hdr, ext_header_t, offset, FMT_HEX, base);
1165*6414dc6dSKonstantin Porotchkin 	print_field(ext_hdr, ext_header_t, reserved, FMT_HEX, base);
1166*6414dc6dSKonstantin Porotchkin 	print_field(ext_hdr, ext_header_t, size, FMT_DEC, base);
1167*6414dc6dSKonstantin Porotchkin 
1168*6414dc6dSKonstantin Porotchkin 	return base + sizeof(ext_header_t);
1169*6414dc6dSKonstantin Porotchkin }
1170*6414dc6dSKonstantin Porotchkin 
1171*6414dc6dSKonstantin Porotchkin void print_sec_ext(ext_header_t *ext_hdr, int base)
1172*6414dc6dSKonstantin Porotchkin {
1173*6414dc6dSKonstantin Porotchkin 	sec_entry_t	*sec_entry;
1174*6414dc6dSKonstantin Porotchkin 	uint32_t	new_base;
1175*6414dc6dSKonstantin Porotchkin 
1176*6414dc6dSKonstantin Porotchkin 	fprintf(stdout, "\n########### Secure extension ###########\n");
1177*6414dc6dSKonstantin Porotchkin 
1178*6414dc6dSKonstantin Porotchkin 	new_base = print_ext_hdr(ext_hdr, base);
1179*6414dc6dSKonstantin Porotchkin 
1180*6414dc6dSKonstantin Porotchkin 	sec_entry = (sec_entry_t *)(ext_hdr + 1);
1181*6414dc6dSKonstantin Porotchkin 
1182*6414dc6dSKonstantin Porotchkin 	do_print_field(0, "KAK key", new_base, MAX_RSA_DER_BYTE_LEN, FMT_NONE);
1183*6414dc6dSKonstantin Porotchkin 	new_base += MAX_RSA_DER_BYTE_LEN;
1184*6414dc6dSKonstantin Porotchkin 	print_field(sec_entry, sec_entry_t, jtag_delay, FMT_DEC, base);
1185*6414dc6dSKonstantin Porotchkin 	print_field(sec_entry, sec_entry_t, box_id, FMT_HEX, base);
1186*6414dc6dSKonstantin Porotchkin 	print_field(sec_entry, sec_entry_t, flash_id, FMT_HEX, base);
1187*6414dc6dSKonstantin Porotchkin 	print_field(sec_entry, sec_entry_t, encrypt_en, FMT_DEC, base);
1188*6414dc6dSKonstantin Porotchkin 	print_field(sec_entry, sec_entry_t, efuse_dis, FMT_DEC, base);
1189*6414dc6dSKonstantin Porotchkin 	new_base += 6 * sizeof(uint32_t);
1190*6414dc6dSKonstantin Porotchkin 	do_print_field(0, "header signature",
1191*6414dc6dSKonstantin Porotchkin 		       new_base, RSA_SIGN_BYTE_LEN, FMT_NONE);
1192*6414dc6dSKonstantin Porotchkin 	new_base += RSA_SIGN_BYTE_LEN;
1193*6414dc6dSKonstantin Porotchkin 	do_print_field(0, "image signature",
1194*6414dc6dSKonstantin Porotchkin 		       new_base, RSA_SIGN_BYTE_LEN, FMT_NONE);
1195*6414dc6dSKonstantin Porotchkin 	new_base += RSA_SIGN_BYTE_LEN;
1196*6414dc6dSKonstantin Porotchkin 	do_print_field(0, "CSK keys", new_base,
1197*6414dc6dSKonstantin Porotchkin 		       CSK_ARR_SZ * MAX_RSA_DER_BYTE_LEN, FMT_NONE);
1198*6414dc6dSKonstantin Porotchkin 	new_base += CSK_ARR_SZ * MAX_RSA_DER_BYTE_LEN;
1199*6414dc6dSKonstantin Porotchkin 	do_print_field(0, "CSK block signature",
1200*6414dc6dSKonstantin Porotchkin 		       new_base, RSA_SIGN_BYTE_LEN, FMT_NONE);
1201*6414dc6dSKonstantin Porotchkin 	new_base += RSA_SIGN_BYTE_LEN;
1202*6414dc6dSKonstantin Porotchkin 	do_print_field(0, "control", new_base,
1203*6414dc6dSKonstantin Porotchkin 		       CP_CTRL_EL_ARRAY_SZ * 2, FMT_NONE);
1204*6414dc6dSKonstantin Porotchkin 
1205*6414dc6dSKonstantin Porotchkin }
1206*6414dc6dSKonstantin Porotchkin 
1207*6414dc6dSKonstantin Porotchkin void print_bin_ext(ext_header_t *ext_hdr, int base)
1208*6414dc6dSKonstantin Porotchkin {
1209*6414dc6dSKonstantin Porotchkin 	fprintf(stdout, "\n########### Binary extension ###########\n");
1210*6414dc6dSKonstantin Porotchkin 	base = print_ext_hdr(ext_hdr, base);
1211*6414dc6dSKonstantin Porotchkin 	do_print_field(0, "binary image", base, ext_hdr->size, FMT_NONE);
1212*6414dc6dSKonstantin Porotchkin }
1213*6414dc6dSKonstantin Porotchkin 
1214*6414dc6dSKonstantin Porotchkin int print_extension(void *buf, int base, int count, int ext_size)
1215*6414dc6dSKonstantin Porotchkin {
1216*6414dc6dSKonstantin Porotchkin 	ext_header_t *ext_hdr = buf;
1217*6414dc6dSKonstantin Porotchkin 	int pad = ext_size;
1218*6414dc6dSKonstantin Porotchkin 	int curr_size;
1219*6414dc6dSKonstantin Porotchkin 
1220*6414dc6dSKonstantin Porotchkin 	while (count--) {
1221*6414dc6dSKonstantin Porotchkin 		if (ext_hdr->type == EXT_TYPE_BINARY)
1222*6414dc6dSKonstantin Porotchkin 			print_bin_ext(ext_hdr, base);
1223*6414dc6dSKonstantin Porotchkin 		else if (ext_hdr->type == EXT_TYPE_SECURITY)
1224*6414dc6dSKonstantin Porotchkin 			print_sec_ext(ext_hdr, base);
1225*6414dc6dSKonstantin Porotchkin 
1226*6414dc6dSKonstantin Porotchkin 		curr_size = sizeof(ext_header_t) + ext_hdr->size;
1227*6414dc6dSKonstantin Porotchkin 		base += curr_size;
1228*6414dc6dSKonstantin Porotchkin 		pad  -= curr_size;
1229*6414dc6dSKonstantin Porotchkin 		ext_hdr = (ext_header_t *)((uintptr_t)ext_hdr + curr_size);
1230*6414dc6dSKonstantin Porotchkin 	}
1231*6414dc6dSKonstantin Porotchkin 
1232*6414dc6dSKonstantin Porotchkin 	if (pad)
1233*6414dc6dSKonstantin Porotchkin 		do_print_field(0, "padding", base, pad, FMT_NONE);
1234*6414dc6dSKonstantin Porotchkin 
1235*6414dc6dSKonstantin Porotchkin 	return ext_size;
1236*6414dc6dSKonstantin Porotchkin }
1237*6414dc6dSKonstantin Porotchkin 
1238*6414dc6dSKonstantin Porotchkin int parse_image(uint8_t *buf, int size)
1239*6414dc6dSKonstantin Porotchkin {
1240*6414dc6dSKonstantin Porotchkin 	int base = 0;
1241*6414dc6dSKonstantin Porotchkin 	int ret = 1;
1242*6414dc6dSKonstantin Porotchkin 	header_t *main_hdr;
1243*6414dc6dSKonstantin Porotchkin 	uint32_t checksum, prolog_checksum;
1244*6414dc6dSKonstantin Porotchkin 
1245*6414dc6dSKonstantin Porotchkin 
1246*6414dc6dSKonstantin Porotchkin 	fprintf(stdout,
1247*6414dc6dSKonstantin Porotchkin 		"################### Prolog Start ######################\n\n");
1248*6414dc6dSKonstantin Porotchkin 	main_hdr = (header_t *)buf;
1249*6414dc6dSKonstantin Porotchkin 	base += print_header(buf, base);
1250*6414dc6dSKonstantin Porotchkin 
1251*6414dc6dSKonstantin Porotchkin 	if (main_hdr->ext_count)
1252*6414dc6dSKonstantin Porotchkin 		base += print_extension(buf + base, base,
1253*6414dc6dSKonstantin Porotchkin 					main_hdr->ext_count,
1254*6414dc6dSKonstantin Porotchkin 					main_hdr->prolog_size -
1255*6414dc6dSKonstantin Porotchkin 					sizeof(header_t));
1256*6414dc6dSKonstantin Porotchkin 
1257*6414dc6dSKonstantin Porotchkin 	if (base < main_hdr->prolog_size) {
1258*6414dc6dSKonstantin Porotchkin 		fprintf(stdout, "\n########### Padding ##############\n");
1259*6414dc6dSKonstantin Porotchkin 		do_print_field(0, "prolog padding",
1260*6414dc6dSKonstantin Porotchkin 			       base, main_hdr->prolog_size - base, FMT_HEX);
1261*6414dc6dSKonstantin Porotchkin 		base = main_hdr->prolog_size;
1262*6414dc6dSKonstantin Porotchkin 	}
1263*6414dc6dSKonstantin Porotchkin 	fprintf(stdout,
1264*6414dc6dSKonstantin Porotchkin 		"\n################### Prolog End ######################\n");
1265*6414dc6dSKonstantin Porotchkin 
1266*6414dc6dSKonstantin Porotchkin 	fprintf(stdout,
1267*6414dc6dSKonstantin Porotchkin 		"\n################### Boot image ######################\n");
1268*6414dc6dSKonstantin Porotchkin 
1269*6414dc6dSKonstantin Porotchkin 	do_print_field(0, "boot image", base, size - base - 4, FMT_NONE);
1270*6414dc6dSKonstantin Porotchkin 
1271*6414dc6dSKonstantin Porotchkin 	fprintf(stdout,
1272*6414dc6dSKonstantin Porotchkin 		"################### Image end ########################\n");
1273*6414dc6dSKonstantin Porotchkin 
1274*6414dc6dSKonstantin Porotchkin 	/* Check sanity for certain values */
1275*6414dc6dSKonstantin Porotchkin 	printf("\nChecking values:\n");
1276*6414dc6dSKonstantin Porotchkin 
1277*6414dc6dSKonstantin Porotchkin 	if (main_hdr->magic == MAIN_HDR_MAGIC) {
1278*6414dc6dSKonstantin Porotchkin 		fprintf(stdout, "Headers magic:    OK!\n");
1279*6414dc6dSKonstantin Porotchkin 	} else {
1280*6414dc6dSKonstantin Porotchkin 		fprintf(stderr,
1281*6414dc6dSKonstantin Porotchkin 			"\n****** ERROR: HEADER MAGIC 0x%08x != 0x%08x\n",
1282*6414dc6dSKonstantin Porotchkin 			main_hdr->magic, MAIN_HDR_MAGIC);
1283*6414dc6dSKonstantin Porotchkin 		goto error;
1284*6414dc6dSKonstantin Porotchkin 	}
1285*6414dc6dSKonstantin Porotchkin 
1286*6414dc6dSKonstantin Porotchkin 	/* headers checksum */
1287*6414dc6dSKonstantin Porotchkin 	/* clear the checksum field in header to calculate checksum */
1288*6414dc6dSKonstantin Porotchkin 	prolog_checksum = main_hdr->prolog_checksum;
1289*6414dc6dSKonstantin Porotchkin 	main_hdr->prolog_checksum = 0;
1290*6414dc6dSKonstantin Porotchkin 	checksum = checksum32((uint32_t *)buf, main_hdr->prolog_size);
1291*6414dc6dSKonstantin Porotchkin 
1292*6414dc6dSKonstantin Porotchkin 	if (checksum == prolog_checksum) {
1293*6414dc6dSKonstantin Porotchkin 		fprintf(stdout, "Headers checksum: OK!\n");
1294*6414dc6dSKonstantin Porotchkin 	} else {
1295*6414dc6dSKonstantin Porotchkin 		fprintf(stderr,
1296*6414dc6dSKonstantin Porotchkin 			"\n***** ERROR: BAD HEADER CHECKSUM 0x%08x != 0x%08x\n",
1297*6414dc6dSKonstantin Porotchkin 			checksum, prolog_checksum);
1298*6414dc6dSKonstantin Porotchkin 		goto error;
1299*6414dc6dSKonstantin Porotchkin 	}
1300*6414dc6dSKonstantin Porotchkin 
1301*6414dc6dSKonstantin Porotchkin 	/* boot image checksum */
1302*6414dc6dSKonstantin Porotchkin 	checksum = checksum32((uint32_t *)(buf + main_hdr->prolog_size),
1303*6414dc6dSKonstantin Porotchkin 			      main_hdr->boot_image_size);
1304*6414dc6dSKonstantin Porotchkin 	if (checksum == main_hdr->boot_image_checksum) {
1305*6414dc6dSKonstantin Porotchkin 		fprintf(stdout, "Image checksum:   OK!\n");
1306*6414dc6dSKonstantin Porotchkin 	} else {
1307*6414dc6dSKonstantin Porotchkin 		fprintf(stderr,
1308*6414dc6dSKonstantin Porotchkin 			"\n****** ERROR: BAD IMAGE CHECKSUM 0x%08x != 0x%08x\n",
1309*6414dc6dSKonstantin Porotchkin 			checksum, main_hdr->boot_image_checksum);
1310*6414dc6dSKonstantin Porotchkin 		goto error;
1311*6414dc6dSKonstantin Porotchkin 	}
1312*6414dc6dSKonstantin Porotchkin 
1313*6414dc6dSKonstantin Porotchkin #ifdef CONFIG_MVEBU_SECURE_BOOT
1314*6414dc6dSKonstantin Porotchkin 	/* RSA signatures */
1315*6414dc6dSKonstantin Porotchkin 	if (main_hdr->ext_count) {
1316*6414dc6dSKonstantin Porotchkin 		uint8_t		ext_num = main_hdr->ext_count;
1317*6414dc6dSKonstantin Porotchkin 		ext_header_t	*ext_hdr = (ext_header_t *)(main_hdr + 1);
1318*6414dc6dSKonstantin Porotchkin 		unsigned char	hash[32];
1319*6414dc6dSKonstantin Porotchkin 		int		i;
1320*6414dc6dSKonstantin Porotchkin 
1321*6414dc6dSKonstantin Porotchkin 		while (ext_num--) {
1322*6414dc6dSKonstantin Porotchkin 			if (ext_hdr->type == EXT_TYPE_SECURITY) {
1323*6414dc6dSKonstantin Porotchkin 				sec_entry_t  *sec_entry =
1324*6414dc6dSKonstantin Porotchkin 						(sec_entry_t *)(ext_hdr + 1);
1325*6414dc6dSKonstantin Porotchkin 
1326*6414dc6dSKonstantin Porotchkin 				ret = verify_secure_header_signatures(
1327*6414dc6dSKonstantin Porotchkin 							main_hdr, sec_entry);
1328*6414dc6dSKonstantin Porotchkin 				if (ret != 0) {
1329*6414dc6dSKonstantin Porotchkin 					fprintf(stderr,
1330*6414dc6dSKonstantin Porotchkin 						"\n****** FAILED TO VERIFY ");
1331*6414dc6dSKonstantin Porotchkin 					fprintf(stderr,
1332*6414dc6dSKonstantin Porotchkin 						"RSA SIGNATURES ********\n");
1333*6414dc6dSKonstantin Porotchkin 					goto error;
1334*6414dc6dSKonstantin Porotchkin 				}
1335*6414dc6dSKonstantin Porotchkin 
1336*6414dc6dSKonstantin Porotchkin 				mbedtls_sha256(sec_entry->kak_key,
1337*6414dc6dSKonstantin Porotchkin 					       MAX_RSA_DER_BYTE_LEN, hash, 0);
1338*6414dc6dSKonstantin Porotchkin 				fprintf(stdout,
1339*6414dc6dSKonstantin Porotchkin 					">>>>>>>>>> KAK KEY HASH >>>>>>>>>>\n");
1340*6414dc6dSKonstantin Porotchkin 				fprintf(stdout, "SHA256: ");
1341*6414dc6dSKonstantin Porotchkin 				for (i = 0; i < 32; i++)
1342*6414dc6dSKonstantin Porotchkin 					fprintf(stdout, "%02X", hash[i]);
1343*6414dc6dSKonstantin Porotchkin 
1344*6414dc6dSKonstantin Porotchkin 				fprintf(stdout,
1345*6414dc6dSKonstantin Porotchkin 					"\n<<<<<<<<< KAK KEY HASH <<<<<<<<<\n");
1346*6414dc6dSKonstantin Porotchkin 
1347*6414dc6dSKonstantin Porotchkin 				break;
1348*6414dc6dSKonstantin Porotchkin 			}
1349*6414dc6dSKonstantin Porotchkin 			ext_hdr =
1350*6414dc6dSKonstantin Porotchkin 				(ext_header_t *)((uint8_t *)(ext_hdr + 1) +
1351*6414dc6dSKonstantin Porotchkin 				 ext_hdr->size);
1352*6414dc6dSKonstantin Porotchkin 		}
1353*6414dc6dSKonstantin Porotchkin 	}
1354*6414dc6dSKonstantin Porotchkin #endif
1355*6414dc6dSKonstantin Porotchkin 
1356*6414dc6dSKonstantin Porotchkin 	ret = 0;
1357*6414dc6dSKonstantin Porotchkin error:
1358*6414dc6dSKonstantin Porotchkin 	return ret;
1359*6414dc6dSKonstantin Porotchkin }
1360*6414dc6dSKonstantin Porotchkin 
1361*6414dc6dSKonstantin Porotchkin int format_bin_ext(char *filename, FILE *out_fd)
1362*6414dc6dSKonstantin Porotchkin {
1363*6414dc6dSKonstantin Porotchkin 	ext_header_t header;
1364*6414dc6dSKonstantin Porotchkin 	FILE *in_fd;
1365*6414dc6dSKonstantin Porotchkin 	int size, written;
1366*6414dc6dSKonstantin Porotchkin 	int aligned_size, pad_bytes;
1367*6414dc6dSKonstantin Porotchkin 	char c;
1368*6414dc6dSKonstantin Porotchkin 
1369*6414dc6dSKonstantin Porotchkin 	in_fd = fopen(filename, "rb");
1370*6414dc6dSKonstantin Porotchkin 	if (in_fd == NULL) {
1371*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "failed to open bin extension file %s\n",
1372*6414dc6dSKonstantin Porotchkin 			filename);
1373*6414dc6dSKonstantin Porotchkin 		return 1;
1374*6414dc6dSKonstantin Porotchkin 	}
1375*6414dc6dSKonstantin Porotchkin 
1376*6414dc6dSKonstantin Porotchkin 	size = get_file_size(filename);
1377*6414dc6dSKonstantin Porotchkin 	if (size <= 0) {
1378*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "bin extension file size is bad\n");
1379*6414dc6dSKonstantin Porotchkin 		return 1;
1380*6414dc6dSKonstantin Porotchkin 	}
1381*6414dc6dSKonstantin Porotchkin 
1382*6414dc6dSKonstantin Porotchkin 	/* Align extension size to 8 bytes */
1383*6414dc6dSKonstantin Porotchkin 	aligned_size = (size + 7) & (~7);
1384*6414dc6dSKonstantin Porotchkin 	pad_bytes    = aligned_size - size;
1385*6414dc6dSKonstantin Porotchkin 
1386*6414dc6dSKonstantin Porotchkin 	header.type = EXT_TYPE_BINARY;
1387*6414dc6dSKonstantin Porotchkin 	header.offset = 0;
1388*6414dc6dSKonstantin Porotchkin 	header.size = aligned_size;
1389*6414dc6dSKonstantin Porotchkin 	header.reserved = 0;
1390*6414dc6dSKonstantin Porotchkin 
1391*6414dc6dSKonstantin Porotchkin 	/* Write header */
1392*6414dc6dSKonstantin Porotchkin 	written = fwrite(&header, sizeof(ext_header_t), 1, out_fd);
1393*6414dc6dSKonstantin Porotchkin 	if (written != 1) {
1394*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "failed writing header to extension file\n");
1395*6414dc6dSKonstantin Porotchkin 		return 1;
1396*6414dc6dSKonstantin Porotchkin 	}
1397*6414dc6dSKonstantin Porotchkin 
1398*6414dc6dSKonstantin Porotchkin 	/* Write image */
1399*6414dc6dSKonstantin Porotchkin 	while (size--) {
1400*6414dc6dSKonstantin Porotchkin 		c = getc(in_fd);
1401*6414dc6dSKonstantin Porotchkin 		fputc(c, out_fd);
1402*6414dc6dSKonstantin Porotchkin 	}
1403*6414dc6dSKonstantin Porotchkin 
1404*6414dc6dSKonstantin Porotchkin 	while (pad_bytes--)
1405*6414dc6dSKonstantin Porotchkin 		fputc(0, out_fd);
1406*6414dc6dSKonstantin Porotchkin 
1407*6414dc6dSKonstantin Porotchkin 	fclose(in_fd);
1408*6414dc6dSKonstantin Porotchkin 
1409*6414dc6dSKonstantin Porotchkin 	return 0;
1410*6414dc6dSKonstantin Porotchkin }
1411*6414dc6dSKonstantin Porotchkin 
1412*6414dc6dSKonstantin Porotchkin /* ****************************************
1413*6414dc6dSKonstantin Porotchkin  *
1414*6414dc6dSKonstantin Porotchkin  * Write all extensions (binary, secure
1415*6414dc6dSKonstantin Porotchkin  * extensions) to file
1416*6414dc6dSKonstantin Porotchkin  *
1417*6414dc6dSKonstantin Porotchkin  * ****************************************/
1418*6414dc6dSKonstantin Porotchkin 
1419*6414dc6dSKonstantin Porotchkin int format_extensions(char *ext_filename)
1420*6414dc6dSKonstantin Porotchkin {
1421*6414dc6dSKonstantin Porotchkin 	FILE *out_fd;
1422*6414dc6dSKonstantin Porotchkin 	int ret = 0;
1423*6414dc6dSKonstantin Porotchkin 
1424*6414dc6dSKonstantin Porotchkin 	out_fd = fopen(ext_filename, "wb");
1425*6414dc6dSKonstantin Porotchkin 	if (out_fd == NULL) {
1426*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "failed to open extension output file %s",
1427*6414dc6dSKonstantin Porotchkin 			ext_filename);
1428*6414dc6dSKonstantin Porotchkin 		return 1;
1429*6414dc6dSKonstantin Porotchkin 	}
1430*6414dc6dSKonstantin Porotchkin 
1431*6414dc6dSKonstantin Porotchkin 	if (strncmp(opts.bin_ext_file, "NA", MAX_FILENAME)) {
1432*6414dc6dSKonstantin Porotchkin 		if (format_bin_ext(opts.bin_ext_file, out_fd)) {
1433*6414dc6dSKonstantin Porotchkin 			ret = 1;
1434*6414dc6dSKonstantin Porotchkin 			goto error;
1435*6414dc6dSKonstantin Porotchkin 		}
1436*6414dc6dSKonstantin Porotchkin 	}
1437*6414dc6dSKonstantin Porotchkin #ifdef CONFIG_MVEBU_SECURE_BOOT
1438*6414dc6dSKonstantin Porotchkin 	if (strncmp(opts.sec_cfg_file, "NA", MAX_FILENAME)) {
1439*6414dc6dSKonstantin Porotchkin 		if (format_sec_ext(opts.sec_cfg_file, out_fd)) {
1440*6414dc6dSKonstantin Porotchkin 			ret = 1;
1441*6414dc6dSKonstantin Porotchkin 			goto error;
1442*6414dc6dSKonstantin Porotchkin 		}
1443*6414dc6dSKonstantin Porotchkin 	}
1444*6414dc6dSKonstantin Porotchkin #endif
1445*6414dc6dSKonstantin Porotchkin 
1446*6414dc6dSKonstantin Porotchkin error:
1447*6414dc6dSKonstantin Porotchkin 	fflush(out_fd);
1448*6414dc6dSKonstantin Porotchkin 	fclose(out_fd);
1449*6414dc6dSKonstantin Porotchkin 	return ret;
1450*6414dc6dSKonstantin Porotchkin }
1451*6414dc6dSKonstantin Porotchkin 
1452*6414dc6dSKonstantin Porotchkin void update_uart(header_t *header)
1453*6414dc6dSKonstantin Porotchkin {
1454*6414dc6dSKonstantin Porotchkin 	header->uart_cfg = 0;
1455*6414dc6dSKonstantin Porotchkin 	header->baudrate = 0;
1456*6414dc6dSKonstantin Porotchkin 
1457*6414dc6dSKonstantin Porotchkin 	if (opts.disable_print)
1458*6414dc6dSKonstantin Porotchkin 		uart_set_mode(header->uart_cfg, UART_MODE_DISABLE);
1459*6414dc6dSKonstantin Porotchkin 
1460*6414dc6dSKonstantin Porotchkin 	if (opts.baudrate)
1461*6414dc6dSKonstantin Porotchkin 		header->baudrate = (opts.baudrate / 1200);
1462*6414dc6dSKonstantin Porotchkin }
1463*6414dc6dSKonstantin Porotchkin 
1464*6414dc6dSKonstantin Porotchkin /* ****************************************
1465*6414dc6dSKonstantin Porotchkin  *
1466*6414dc6dSKonstantin Porotchkin  * Write the image prolog, i.e.
1467*6414dc6dSKonstantin Porotchkin  * main header and extensions, to file
1468*6414dc6dSKonstantin Porotchkin  *
1469*6414dc6dSKonstantin Porotchkin  * ****************************************/
1470*6414dc6dSKonstantin Porotchkin 
1471*6414dc6dSKonstantin Porotchkin int write_prolog(int ext_cnt, char *ext_filename,
1472*6414dc6dSKonstantin Porotchkin 		 uint8_t *image_buf, int image_size, FILE *out_fd)
1473*6414dc6dSKonstantin Porotchkin {
1474*6414dc6dSKonstantin Porotchkin 	header_t		*header;
1475*6414dc6dSKonstantin Porotchkin 	int main_hdr_size = sizeof(header_t);
1476*6414dc6dSKonstantin Porotchkin 	int prolog_size = main_hdr_size;
1477*6414dc6dSKonstantin Porotchkin 	FILE *ext_fd;
1478*6414dc6dSKonstantin Porotchkin 	char *buf;
1479*6414dc6dSKonstantin Porotchkin 	int written, read;
1480*6414dc6dSKonstantin Porotchkin 	int ret = 1;
1481*6414dc6dSKonstantin Porotchkin 
1482*6414dc6dSKonstantin Porotchkin 
1483*6414dc6dSKonstantin Porotchkin 	if (ext_cnt)
1484*6414dc6dSKonstantin Porotchkin 		prolog_size +=  get_file_size(ext_filename);
1485*6414dc6dSKonstantin Porotchkin 
1486*6414dc6dSKonstantin Porotchkin 	prolog_size = ((prolog_size + PROLOG_ALIGNMENT) &
1487*6414dc6dSKonstantin Porotchkin 		     (~(PROLOG_ALIGNMENT-1)));
1488*6414dc6dSKonstantin Porotchkin 
1489*6414dc6dSKonstantin Porotchkin 	/* Allocate a zeroed buffer to zero the padding bytes */
1490*6414dc6dSKonstantin Porotchkin 	buf = calloc(prolog_size, 1);
1491*6414dc6dSKonstantin Porotchkin 	if (buf == NULL) {
1492*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Error: failed allocating checksum buffer\n");
1493*6414dc6dSKonstantin Porotchkin 		return 1;
1494*6414dc6dSKonstantin Porotchkin 	}
1495*6414dc6dSKonstantin Porotchkin 
1496*6414dc6dSKonstantin Porotchkin 	header = (header_t *)buf;
1497*6414dc6dSKonstantin Porotchkin 	header->magic       = MAIN_HDR_MAGIC;
1498*6414dc6dSKonstantin Porotchkin 	header->prolog_size = prolog_size;
1499*6414dc6dSKonstantin Porotchkin 	header->load_addr   = opts.load_addr;
1500*6414dc6dSKonstantin Porotchkin 	header->exec_addr   = opts.exec_addr;
1501*6414dc6dSKonstantin Porotchkin 	header->io_arg_0    = opts.nfc_io_args;
1502*6414dc6dSKonstantin Porotchkin 	header->ext_count   = ext_cnt;
1503*6414dc6dSKonstantin Porotchkin 	header->aux_flags   = 0;
1504*6414dc6dSKonstantin Porotchkin 	header->boot_image_size = (image_size + 3) & (~0x3);
1505*6414dc6dSKonstantin Porotchkin 	header->boot_image_checksum = checksum32((uint32_t *)image_buf,
1506*6414dc6dSKonstantin Porotchkin 						 image_size);
1507*6414dc6dSKonstantin Porotchkin 
1508*6414dc6dSKonstantin Porotchkin 	update_uart(header);
1509*6414dc6dSKonstantin Porotchkin 
1510*6414dc6dSKonstantin Porotchkin 	/* Populate buffer with main header and extensions */
1511*6414dc6dSKonstantin Porotchkin 	if (ext_cnt) {
1512*6414dc6dSKonstantin Porotchkin 		ext_fd = fopen(ext_filename, "rb");
1513*6414dc6dSKonstantin Porotchkin 		if (ext_fd == NULL) {
1514*6414dc6dSKonstantin Porotchkin 			fprintf(stderr,
1515*6414dc6dSKonstantin Porotchkin 				"Error: failed to open extensions file\n");
1516*6414dc6dSKonstantin Porotchkin 			goto error;
1517*6414dc6dSKonstantin Porotchkin 		}
1518*6414dc6dSKonstantin Porotchkin 
1519*6414dc6dSKonstantin Porotchkin 		read = fread(&buf[main_hdr_size],
1520*6414dc6dSKonstantin Porotchkin 			     get_file_size(ext_filename), 1, ext_fd);
1521*6414dc6dSKonstantin Porotchkin 		if (read != 1) {
1522*6414dc6dSKonstantin Porotchkin 			fprintf(stderr,
1523*6414dc6dSKonstantin Porotchkin 				"Error: failed to open extensions file\n");
1524*6414dc6dSKonstantin Porotchkin 			goto error;
1525*6414dc6dSKonstantin Porotchkin 		}
1526*6414dc6dSKonstantin Porotchkin 
1527*6414dc6dSKonstantin Porotchkin #ifdef CONFIG_MVEBU_SECURE_BOOT
1528*6414dc6dSKonstantin Porotchkin 		/* Secure boot mode? */
1529*6414dc6dSKonstantin Porotchkin 		if (opts.sec_opts != 0) {
1530*6414dc6dSKonstantin Porotchkin 			ret = finalize_secure_ext(header, (uint8_t *)buf,
1531*6414dc6dSKonstantin Porotchkin 						  prolog_size, image_buf,
1532*6414dc6dSKonstantin Porotchkin 						  image_size);
1533*6414dc6dSKonstantin Porotchkin 			if (ret != 0) {
1534*6414dc6dSKonstantin Porotchkin 				fprintf(stderr, "Error: failed to handle ");
1535*6414dc6dSKonstantin Porotchkin 				fprintf(stderr, "secure extension!\n");
1536*6414dc6dSKonstantin Porotchkin 				goto error;
1537*6414dc6dSKonstantin Porotchkin 			}
1538*6414dc6dSKonstantin Porotchkin 		} /* secure boot mode */
1539*6414dc6dSKonstantin Porotchkin #endif
1540*6414dc6dSKonstantin Porotchkin 	}
1541*6414dc6dSKonstantin Porotchkin 
1542*6414dc6dSKonstantin Porotchkin 	/* Update the total prolog checksum */
1543*6414dc6dSKonstantin Porotchkin 	header->prolog_checksum = checksum32((uint32_t *)buf, prolog_size);
1544*6414dc6dSKonstantin Porotchkin 
1545*6414dc6dSKonstantin Porotchkin 	/* Now spill everything to output file */
1546*6414dc6dSKonstantin Porotchkin 	written = fwrite(buf, prolog_size, 1, out_fd);
1547*6414dc6dSKonstantin Porotchkin 	if (written != 1) {
1548*6414dc6dSKonstantin Porotchkin 		fprintf(stderr,
1549*6414dc6dSKonstantin Porotchkin 			"Error: failed to write prolog to output file\n");
1550*6414dc6dSKonstantin Porotchkin 		goto error;
1551*6414dc6dSKonstantin Porotchkin 	}
1552*6414dc6dSKonstantin Porotchkin 
1553*6414dc6dSKonstantin Porotchkin 	ret = 0;
1554*6414dc6dSKonstantin Porotchkin 
1555*6414dc6dSKonstantin Porotchkin error:
1556*6414dc6dSKonstantin Porotchkin 	free(buf);
1557*6414dc6dSKonstantin Porotchkin 	return ret;
1558*6414dc6dSKonstantin Porotchkin }
1559*6414dc6dSKonstantin Porotchkin 
1560*6414dc6dSKonstantin Porotchkin int write_boot_image(uint8_t *buf, uint32_t image_size, FILE *out_fd)
1561*6414dc6dSKonstantin Porotchkin {
1562*6414dc6dSKonstantin Porotchkin 	int aligned_size;
1563*6414dc6dSKonstantin Porotchkin 	int written;
1564*6414dc6dSKonstantin Porotchkin 
1565*6414dc6dSKonstantin Porotchkin 	/* Image size must be aligned to 4 bytes */
1566*6414dc6dSKonstantin Porotchkin 	aligned_size = (image_size + 3) & (~0x3);
1567*6414dc6dSKonstantin Porotchkin 
1568*6414dc6dSKonstantin Porotchkin 	written = fwrite(buf, aligned_size, 1, out_fd);
1569*6414dc6dSKonstantin Porotchkin 	if (written != 1) {
1570*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Error: Failed to write boot image\n");
1571*6414dc6dSKonstantin Porotchkin 		goto error;
1572*6414dc6dSKonstantin Porotchkin 	}
1573*6414dc6dSKonstantin Porotchkin 
1574*6414dc6dSKonstantin Porotchkin 	return 0;
1575*6414dc6dSKonstantin Porotchkin error:
1576*6414dc6dSKonstantin Porotchkin 	return 1;
1577*6414dc6dSKonstantin Porotchkin }
1578*6414dc6dSKonstantin Porotchkin 
1579*6414dc6dSKonstantin Porotchkin int main(int argc, char *argv[])
1580*6414dc6dSKonstantin Porotchkin {
1581*6414dc6dSKonstantin Porotchkin 	char in_file[MAX_FILENAME+1] = { 0 };
1582*6414dc6dSKonstantin Porotchkin 	char out_file[MAX_FILENAME+1] = { 0 };
1583*6414dc6dSKonstantin Porotchkin 	char ext_file[MAX_FILENAME+1] = { 0 };
1584*6414dc6dSKonstantin Porotchkin 	FILE *in_fd = NULL;
1585*6414dc6dSKonstantin Porotchkin 	FILE *out_fd = NULL;
1586*6414dc6dSKonstantin Porotchkin 	int parse = 0;
1587*6414dc6dSKonstantin Porotchkin 	int ext_cnt = 0;
1588*6414dc6dSKonstantin Porotchkin 	int opt;
1589*6414dc6dSKonstantin Porotchkin 	int ret = 0;
1590*6414dc6dSKonstantin Porotchkin 	int image_size;
1591*6414dc6dSKonstantin Porotchkin 	uint8_t *image_buf = NULL;
1592*6414dc6dSKonstantin Porotchkin 	int read;
1593*6414dc6dSKonstantin Porotchkin 	size_t len;
1594*6414dc6dSKonstantin Porotchkin 	uint32_t nand_block_size_kb, mlc_nand;
1595*6414dc6dSKonstantin Porotchkin 
1596*6414dc6dSKonstantin Porotchkin 	/* Create temporary file for building extensions
1597*6414dc6dSKonstantin Porotchkin 	 * Use process ID for allowing multiple parallel runs
1598*6414dc6dSKonstantin Porotchkin 	 */
1599*6414dc6dSKonstantin Porotchkin 	snprintf(ext_file, MAX_FILENAME, "/tmp/ext_file-%x", getpid());
1600*6414dc6dSKonstantin Porotchkin 
1601*6414dc6dSKonstantin Porotchkin 	while ((opt = getopt(argc, argv, "hpms:i:l:e:a:b:u:n:t:c:k:")) != -1) {
1602*6414dc6dSKonstantin Porotchkin 		switch (opt) {
1603*6414dc6dSKonstantin Porotchkin 		case 'h':
1604*6414dc6dSKonstantin Porotchkin 			usage();
1605*6414dc6dSKonstantin Porotchkin 			break;
1606*6414dc6dSKonstantin Porotchkin 		case 'l':
1607*6414dc6dSKonstantin Porotchkin 			opts.load_addr = strtoul(optarg, NULL, 0);
1608*6414dc6dSKonstantin Porotchkin 			break;
1609*6414dc6dSKonstantin Porotchkin 		case 'e':
1610*6414dc6dSKonstantin Porotchkin 			opts.exec_addr = strtoul(optarg, NULL, 0);
1611*6414dc6dSKonstantin Porotchkin 			break;
1612*6414dc6dSKonstantin Porotchkin 		case 'm':
1613*6414dc6dSKonstantin Porotchkin 			opts.disable_print = 1;
1614*6414dc6dSKonstantin Porotchkin 			break;
1615*6414dc6dSKonstantin Porotchkin 		case 'u':
1616*6414dc6dSKonstantin Porotchkin 			opts.baudrate = strtoul(optarg, NULL, 0);
1617*6414dc6dSKonstantin Porotchkin 			break;
1618*6414dc6dSKonstantin Porotchkin 		case 'b':
1619*6414dc6dSKonstantin Porotchkin 			strncpy(opts.bin_ext_file, optarg, MAX_FILENAME);
1620*6414dc6dSKonstantin Porotchkin 			ext_cnt++;
1621*6414dc6dSKonstantin Porotchkin 			break;
1622*6414dc6dSKonstantin Porotchkin 		case 'p':
1623*6414dc6dSKonstantin Porotchkin 			parse = 1;
1624*6414dc6dSKonstantin Porotchkin 			break;
1625*6414dc6dSKonstantin Porotchkin 		case 'n':
1626*6414dc6dSKonstantin Porotchkin 			nand_block_size_kb = strtoul(optarg, NULL, 0);
1627*6414dc6dSKonstantin Porotchkin 			opts.nfc_io_args |= (nand_block_size_kb / 64);
1628*6414dc6dSKonstantin Porotchkin 			break;
1629*6414dc6dSKonstantin Porotchkin 		case 't':
1630*6414dc6dSKonstantin Porotchkin 			mlc_nand = 0;
1631*6414dc6dSKonstantin Porotchkin 			if (!strncmp("MLC", optarg, 3))
1632*6414dc6dSKonstantin Porotchkin 				mlc_nand = 1;
1633*6414dc6dSKonstantin Porotchkin 			opts.nfc_io_args |= (mlc_nand << 8);
1634*6414dc6dSKonstantin Porotchkin 			break;
1635*6414dc6dSKonstantin Porotchkin #ifdef CONFIG_MVEBU_SECURE_BOOT
1636*6414dc6dSKonstantin Porotchkin 		case 'c': /* SEC extension */
1637*6414dc6dSKonstantin Porotchkin 			strncpy(opts.sec_cfg_file, optarg, MAX_FILENAME);
1638*6414dc6dSKonstantin Porotchkin 			ext_cnt++;
1639*6414dc6dSKonstantin Porotchkin 			break;
1640*6414dc6dSKonstantin Porotchkin 		case 'k':
1641*6414dc6dSKonstantin Porotchkin 			opts.key_index = strtoul(optarg, NULL, 0);
1642*6414dc6dSKonstantin Porotchkin 			break;
1643*6414dc6dSKonstantin Porotchkin #endif
1644*6414dc6dSKonstantin Porotchkin 		default: /* '?' */
1645*6414dc6dSKonstantin Porotchkin 			usage_err("Unknown argument");
1646*6414dc6dSKonstantin Porotchkin 			exit(EXIT_FAILURE);
1647*6414dc6dSKonstantin Porotchkin 		}
1648*6414dc6dSKonstantin Porotchkin 	}
1649*6414dc6dSKonstantin Porotchkin 
1650*6414dc6dSKonstantin Porotchkin 	/* Check validity of inputes */
1651*6414dc6dSKonstantin Porotchkin 	if (opts.load_addr % 8)
1652*6414dc6dSKonstantin Porotchkin 		usage_err("Load address must be 8 bytes aligned");
1653*6414dc6dSKonstantin Porotchkin 
1654*6414dc6dSKonstantin Porotchkin 	if (opts.baudrate % 1200)
1655*6414dc6dSKonstantin Porotchkin 		usage_err("Baudrate must be a multiple of 1200");
1656*6414dc6dSKonstantin Porotchkin 
1657*6414dc6dSKonstantin Porotchkin 	/* The remaining arguments are the input
1658*6414dc6dSKonstantin Porotchkin 	 * and potentially output file
1659*6414dc6dSKonstantin Porotchkin 	 */
1660*6414dc6dSKonstantin Porotchkin 	/* Input file must exist so exit if not */
1661*6414dc6dSKonstantin Porotchkin 	if (optind >= argc)
1662*6414dc6dSKonstantin Porotchkin 		usage_err("missing input file name");
1663*6414dc6dSKonstantin Porotchkin 
1664*6414dc6dSKonstantin Porotchkin 	len = strlen(argv[optind]);
1665*6414dc6dSKonstantin Porotchkin 	if (len > MAX_FILENAME)
1666*6414dc6dSKonstantin Porotchkin 		usage_err("file name too long");
1667*6414dc6dSKonstantin Porotchkin 	memcpy(in_file, argv[optind], len);
1668*6414dc6dSKonstantin Porotchkin 	optind++;
1669*6414dc6dSKonstantin Porotchkin 
1670*6414dc6dSKonstantin Porotchkin 	/* Output file must exist in non parse mode */
1671*6414dc6dSKonstantin Porotchkin 	if (optind < argc) {
1672*6414dc6dSKonstantin Porotchkin 		len = strlen(argv[optind]);
1673*6414dc6dSKonstantin Porotchkin 		if (len > MAX_FILENAME)
1674*6414dc6dSKonstantin Porotchkin 			usage_err("file name too long");
1675*6414dc6dSKonstantin Porotchkin 		memcpy(out_file, argv[optind], len);
1676*6414dc6dSKonstantin Porotchkin 	} else if (!parse)
1677*6414dc6dSKonstantin Porotchkin 		usage_err("missing output file name");
1678*6414dc6dSKonstantin Porotchkin 
1679*6414dc6dSKonstantin Porotchkin 	/* open the input file */
1680*6414dc6dSKonstantin Porotchkin 	in_fd = fopen(in_file, "rb");
1681*6414dc6dSKonstantin Porotchkin 	if (in_fd == NULL) {
1682*6414dc6dSKonstantin Porotchkin 		printf("Error: Failed to open input file %s\n", in_file);
1683*6414dc6dSKonstantin Porotchkin 		goto main_exit;
1684*6414dc6dSKonstantin Porotchkin 	}
1685*6414dc6dSKonstantin Porotchkin 
1686*6414dc6dSKonstantin Porotchkin 	/* Read the input file to buffer */
1687*6414dc6dSKonstantin Porotchkin 	image_size = get_file_size(in_file);
1688*6414dc6dSKonstantin Porotchkin 	image_buf = calloc((image_size + AES_BLOCK_SZ - 1) &
1689*6414dc6dSKonstantin Porotchkin 			   ~(AES_BLOCK_SZ - 1), 1);
1690*6414dc6dSKonstantin Porotchkin 	if (image_buf == NULL) {
1691*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Error: failed allocating input buffer\n");
1692*6414dc6dSKonstantin Porotchkin 		return 1;
1693*6414dc6dSKonstantin Porotchkin 	}
1694*6414dc6dSKonstantin Porotchkin 
1695*6414dc6dSKonstantin Porotchkin 	read = fread(image_buf, image_size, 1, in_fd);
1696*6414dc6dSKonstantin Porotchkin 	if (read != 1) {
1697*6414dc6dSKonstantin Porotchkin 		fprintf(stderr, "Error: failed to read input file\n");
1698*6414dc6dSKonstantin Porotchkin 		goto main_exit;
1699*6414dc6dSKonstantin Porotchkin 	}
1700*6414dc6dSKonstantin Porotchkin 
1701*6414dc6dSKonstantin Porotchkin 	/* Parse the input image and leave */
1702*6414dc6dSKonstantin Porotchkin 	if (parse) {
1703*6414dc6dSKonstantin Porotchkin 		if (opts.key_index >= CSK_ARR_SZ) {
1704*6414dc6dSKonstantin Porotchkin 			fprintf(stderr,
1705*6414dc6dSKonstantin Porotchkin 				"Wrong key IDX value. Valid values 0 - %d\n",
1706*6414dc6dSKonstantin Porotchkin 				CSK_ARR_SZ - 1);
1707*6414dc6dSKonstantin Porotchkin 			goto main_exit;
1708*6414dc6dSKonstantin Porotchkin 		}
1709*6414dc6dSKonstantin Porotchkin 		ret = parse_image(image_buf, image_size);
1710*6414dc6dSKonstantin Porotchkin 		goto main_exit;
1711*6414dc6dSKonstantin Porotchkin 	}
1712*6414dc6dSKonstantin Porotchkin 
1713*6414dc6dSKonstantin Porotchkin 	/* Create a blob file from all extensions */
1714*6414dc6dSKonstantin Porotchkin 	if (ext_cnt) {
1715*6414dc6dSKonstantin Porotchkin 		ret = format_extensions(ext_file);
1716*6414dc6dSKonstantin Porotchkin 		if (ret)
1717*6414dc6dSKonstantin Porotchkin 			goto main_exit;
1718*6414dc6dSKonstantin Porotchkin 	}
1719*6414dc6dSKonstantin Porotchkin 
1720*6414dc6dSKonstantin Porotchkin 	out_fd = fopen(out_file, "wb");
1721*6414dc6dSKonstantin Porotchkin 	if (out_fd == NULL) {
1722*6414dc6dSKonstantin Porotchkin 		fprintf(stderr,
1723*6414dc6dSKonstantin Porotchkin 			"Error: Failed to open output file %s\n", out_file);
1724*6414dc6dSKonstantin Porotchkin 		goto main_exit;
1725*6414dc6dSKonstantin Porotchkin 	}
1726*6414dc6dSKonstantin Porotchkin 
1727*6414dc6dSKonstantin Porotchkin 	ret = write_prolog(ext_cnt, ext_file, image_buf, image_size, out_fd);
1728*6414dc6dSKonstantin Porotchkin 	if (ret)
1729*6414dc6dSKonstantin Porotchkin 		goto main_exit;
1730*6414dc6dSKonstantin Porotchkin 
1731*6414dc6dSKonstantin Porotchkin #ifdef CONFIG_MVEBU_SECURE_BOOT
1732*6414dc6dSKonstantin Porotchkin 	if (opts.sec_opts && (opts.sec_opts->encrypted_image != 0) &&
1733*6414dc6dSKonstantin Porotchkin 	    (opts.sec_opts->enc_image_sz != 0)) {
1734*6414dc6dSKonstantin Porotchkin 		ret = write_boot_image(opts.sec_opts->encrypted_image,
1735*6414dc6dSKonstantin Porotchkin 				       opts.sec_opts->enc_image_sz, out_fd);
1736*6414dc6dSKonstantin Porotchkin 	} else
1737*6414dc6dSKonstantin Porotchkin #endif
1738*6414dc6dSKonstantin Porotchkin 		ret = write_boot_image(image_buf, image_size, out_fd);
1739*6414dc6dSKonstantin Porotchkin 	if (ret)
1740*6414dc6dSKonstantin Porotchkin 		goto main_exit;
1741*6414dc6dSKonstantin Porotchkin 
1742*6414dc6dSKonstantin Porotchkin main_exit:
1743*6414dc6dSKonstantin Porotchkin 	if (in_fd)
1744*6414dc6dSKonstantin Porotchkin 		fclose(in_fd);
1745*6414dc6dSKonstantin Porotchkin 
1746*6414dc6dSKonstantin Porotchkin 	if (out_fd)
1747*6414dc6dSKonstantin Porotchkin 		fclose(out_fd);
1748*6414dc6dSKonstantin Porotchkin 
1749*6414dc6dSKonstantin Porotchkin 	if (image_buf)
1750*6414dc6dSKonstantin Porotchkin 		free(image_buf);
1751*6414dc6dSKonstantin Porotchkin 
1752*6414dc6dSKonstantin Porotchkin 	unlink(ext_file);
1753*6414dc6dSKonstantin Porotchkin 
1754*6414dc6dSKonstantin Porotchkin #ifdef CONFIG_MVEBU_SECURE_BOOT
1755*6414dc6dSKonstantin Porotchkin 	if (opts.sec_opts) {
1756*6414dc6dSKonstantin Porotchkin 		if (opts.sec_opts->encrypted_image)
1757*6414dc6dSKonstantin Porotchkin 			free(opts.sec_opts->encrypted_image);
1758*6414dc6dSKonstantin Porotchkin 		free(opts.sec_opts);
1759*6414dc6dSKonstantin Porotchkin 	}
1760*6414dc6dSKonstantin Porotchkin #endif
1761*6414dc6dSKonstantin Porotchkin 	exit(ret);
1762*6414dc6dSKonstantin Porotchkin }
1763