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