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