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