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