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