From a7b64b5508da17d6298829fb995d5f961c77a82a Mon Sep 17 00:00:00 2001 From: kostap Date: Tue, 13 Jan 2015 08:48:10 +0200 Subject: [PATCH] Add secure boot infrastructure for A3xx/ALP - Add changes to build script and image tools infrastructure allowing build images for secure boot mode on A3xx and ALP - Modify doimage and hdrparser, update bootrom header format. - Modify build script for supporting secure boot mode options. Change-Id: I46d08fd9e5f17777df41c1b89e447e83ba39c24b Signed-off-by: kostap Reviewed-on: http://vgitil04.il.marvell.com:8080/15951 Tested-by: Star_Automation Reviewed-by: Haim Boot Reviewed-by: Hanna Hawa Reviewed-by: Shadi Ammouri Reviewed-on: http://vgitil04.il.marvell.com:8080/16281 Reviewed-by: Omri Itach Tested-by: Omri Itach --- build.pl | 86 ++- .../bin_hdr/inc/common/bootstrap_def.h | 116 ++-- tools/marvell/doimage_mv/bootstrap_def.h | 50 +- tools/marvell/doimage_mv/doimage.c | 531 ++++++++---------- tools/marvell/doimage_mv/doimage.h | 84 +-- tools/marvell/doimage_mv/hdrparser.c | 231 +++++--- 6 files changed, 643 insertions(+), 455 deletions(-) diff --git a/build.pl b/build.pl index 2c92d3dc873..fe94c96e9cc 100755 --- a/build.pl +++ b/build.pl @@ -4,8 +4,10 @@ sub HELP_MESSAGE { - print "\nUsage : build -f \"Flash type\" -b \"board name\" [-v X.X.X] [-m \"DDR type\"] [-o \"Output file\"]\\\n"; - print " [-p] [-r \"UART baudrate\"] [-u \"UART port\"] [-g \"MPP configuration\"]\n\n"; + print "\nUsage : build -f \"Flash type\" -b \"board name\" [-v X.X.X] [-m \"DDR type\"] [-o \"Output file\"] \\\n"; + print " [-p] [-r \"UART baudrate\"] [-u \"UART port\"] [-g \"MPP configuration\"] \\\n"; + print " [-z \"Private RSA KAK key file\" -a \"Private RSA CSK key file\" -k \"CSK array index\" \\\n"; + print " -x \"BOX ID\" -l \"Flash ID\"] [-j \"JTAG delay\"]\n"; print "Example: ./build.pl -f spi -v 14T2 -b avanta_lp -i spi:nand -c\n"; print "\n"; print "Options:\n"; @@ -29,6 +31,18 @@ sub HELP_MESSAGE print "\t-u\tChange the default BootROM UART debug port number. Suported ports 0 - 3\n"; print "\t-g\tSelect BootROM debug port MPPs configuration value = 0-7 (BootROM-specific)\n"; print "\n"; + print "Secure boot options:\n"; + print "\tNOTE: \tAll secure options except \"j\" are mandatory once one of them is selected\n"; + print "\t\tSecure boot mode is availbale for Armada-3xx and Avanta-LP SoC families only!\n\n"; + print "\t-z\tCreate image with RSA KAK block signature for secure boot mode\n"; + print "\t\tIf the private key file name is \"@@\", the new RSA key pair will be generated and used\n"; + print "\t-a\tCreate image with RSA CSK signature for secure boot mode\n"; + print "\t\tIf the private key file name is \"@@\", the new RSA key pair will be generated and used\n"; + print "\t-k\tCSK Array Index in range of 0 to 15\n"; + print "\t-j\tEnable JTAG interface and delay boot execution by \" delay\" ms. Disabled if omitted\n"; + print "\t-x\tBox ID (hex) - in range of 0 to 0xffffffff\n"; + print "\t-l\tFlash ID (hex) - in range of to 0xffffffff\n"; + print "\n"; print "Environment Variables:\n"; print "\tCROSS_COMPILE Cross compiler to build U-BOOT\n"; print "\tCROSS_COMPILE_BH Cross compiler to build bin hdr\n"; @@ -38,7 +52,7 @@ sub HELP_MESSAGE # Main use Getopt::Std; -getopt('f:b:o:i:v:d:m:r:u:g:'); +getopt('f:b:o:i:v:d:m:r:u:g:z:a:k:j:x:l:'); if((!defined $opt_b) or (!defined $opt_f)) { @@ -198,6 +212,70 @@ sub HELP_MESSAGE exit 1; } +$bin_hdr_n = "bin_hdr.bin"; + +if (($boardID eq "a38x") or + ($boardID eq "a39x") or + ($boardID eq "a375") or + ($boardID eq "alp")) { + + # Secure boot options + if ((defined $opt_z) or + (defined $opt_a) or + (defined $opt_k) or + (defined $opt_j) or + (defined $opt_x) or + (defined $opt_l)) { + + # If defined one of secure options, all the rest except "j" become mandatory + if ((!defined $opt_z) or + (!defined $opt_a) or + (!defined $opt_k) or + (!defined $opt_x) or + (!defined $opt_l)) { + print "\n *** Error: In secure boot mode all options (except \"j\") are mandatory!\n\n"; + exit 1; + } + + # KAK RSA key + if ($opt_z eq "@@") { + print("Secure boot, generate new KAK RSA key\n"); + } else { + printf("Secure boot, Use KAK RSA key from file \"$opt_z\"\n", ); + } + + # CSK RSA key + if ($opt_a eq "@@") { + print("Secure boot, generate new CSK RSA key "); + } else { + print("Secure boot, Use CSK RSA key from file \"$opt_z\" "); + } + + # CSK array index + print("@ CSK array index $opt_k\n"); + $rsa_opts = "-Z $opt_z -A $opt_a -K $opt_k "; + + # JTAG enable/disable and delay + if(!defined $opt_j){ + $id_opts = "-B $opt_x -F $opt_l "; + } else { + $id_opts = "-B $opt_x -F $opt_l -J $opt_j "; + } + printf("Secure boot, Additional options : %s\n", $id_opts); + + $bin_hdr_n = "bin_hdr_sec.bin"; + + } else { + + print("No secure boot option selected\n"); + $rsa_opts = ""; + $id_opts = ""; + } + +} + + + # Big endian place holder if(defined $opt_e) { $endian = "be"; @@ -333,7 +411,7 @@ sub HELP_MESSAGE print "\n**** [Creating Image]\t*****\n\n"; $failUart = system("./tools/marvell/doimage -T uart -D 0 -E 0 -G ./tools/marvell/bin_hdr/bin_hdr.uart.bin u-boot.bin u-boot-$boardID-$opt_v-$flash_name$targetBoard-uart.bin"); -$fail = system("./tools/marvell/doimage -T $img_type -D 0x0 -E 0x0 $img_opts $extra_opt -G ./tools/marvell/bin_hdr/bin_hdr.bin u-boot.bin u-boot-$boardID-$opt_v-$flash_name$targetBoard.bin"); +$fail = system("./tools/marvell/doimage -T $img_type -D 0x0 -E 0x0 $img_opts $rsa_opts $id_opts $extra_opt -G ./tools/marvell/bin_hdr/$bin_hdr_n u-boot.bin u-boot-$boardID-$opt_v-$flash_name$targetBoard.bin"); if($fail){ print "\n *** Error: Doimage failed\n\n"; diff --git a/tools/marvell/bin_hdr/inc/common/bootstrap_def.h b/tools/marvell/bin_hdr/inc/common/bootstrap_def.h index ac0788422a8..f4c54675c14 100644 --- a/tools/marvell/bin_hdr/inc/common/bootstrap_def.h +++ b/tools/marvell/bin_hdr/inc/common/bootstrap_def.h @@ -73,26 +73,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define MAIN_HDR_NAND_SLC 0 #define MAIN_HDR_NAND_MLC 1 -typedef struct BHR_t -{ -/* type name byte order */ - MV_U8 blockID; /*0 */ - MV_U8 rsvd1; /*1 */ - MV_U16 nandPageSize; /*2-3 */ - MV_U32 blockSize; /*4-7 */ - MV_U8 version; /*8 */ - MV_U8 hdrSizeMsb; /*9 */ - MV_U16 hdrSizeLsb; /*10-11 */ - MV_U32 sourceAddr; /*12-15 */ - MV_U32 destinationAddr; /*16-19 */ - MV_U32 executionAddr; /*20-23 */ - MV_U8 rsvd3; /*24 */ - MV_U8 nandBlockSize; /*25 */ - MV_U8 nandTechnology; /*26 */ - MV_U8 rsvd4; /*27 */ - MV_U16 rsvd2; /*28-29 */ - MV_U8 ext; /*30 */ - MV_U8 checkSum; /*31 */ +typedef struct BHR_t { +/* type name byte order */ + MV_U8 blockID; /* 0 */ + MV_U8 flags; /* 1 */ + MV_U16 nandPageSize; /* 2-3 */ + MV_U32 blockSize; /* 4-7 */ + MV_U8 version; /* 8 */ + MV_U8 hdrSizeMsb; /* 9 */ + MV_U16 hdrSizeLsb; /* 10-11 */ + MV_U32 sourceAddr; /* 12-15 */ + MV_U32 destinationAddr; /* 16-19 */ + MV_U32 executionAddr; /* 20-23 */ + MV_U8 options; /* 24 */ + MV_U8 nandBlockSize; /* 25 */ + MV_U8 nandTechnology; /* 26 */ + MV_U8 rsvd4; /* 27 */ + MV_U16 rsvd2; /* 28-29 */ + MV_U8 ext; /* 30 */ + MV_U8 checkSum; /* 31 */ } BHR_t, * pBHR_t; @@ -103,8 +102,7 @@ typedef struct BHR_t #define EXT_HDR_TYP_BINARY 0x02 #define EXT_HDR_TYP_REGISTER 0x03 -typedef struct headExtBHR_t /* Common extention header head */ -{ +typedef struct headExtBHR_t { /* Common extension header head */ /* type name byte order */ MV_U8 type; MV_U8 lenMsb; @@ -121,8 +119,7 @@ typedef struct headExtBHR_t /* Common extention header head */ #define EXT_HDR_GET_LEN(pHead) \ (((MV_U32)((pHead)->lenMsb) << 16) | ((pHead)->lenLsb)) -typedef struct tailExtBHR_t /* Common extention header tail */ -{ +typedef struct tailExtBHR_t {/* Common extension header tail */ /* type name byte order */ MV_U8 nextHdr; MV_U8 delay; @@ -130,35 +127,46 @@ typedef struct tailExtBHR_t /* Common extention header tail */ } tailExtBHR_t; +typedef struct publicKey_t {/* public key*/ + MV_U8 Key[524]; +} publicKey_t; + #define RSA_MAX_KEY_LEN_BYTES 256 -typedef struct secExtBHR_t -{ +typedef struct secExtBHR_t { headExtBHR_t head; MV_U8 encrypt; MV_U8 rsrvd0; MV_U16 rsrvd1; - MV_U8 pubKey[524]; + publicKey_t pubKey; MV_U8 jtagEn; MV_U8 rsrvd2; MV_U16 rsrvd3; MV_U32 boxId; - MV_U16 flashId; - MV_U16 rsrvd4; + MV_U32 flashId; MV_U8 hdrSign[256]; MV_U8 imgSign[256]; + publicKey_t cskArray[16]; + MV_U8 cskBlockSign[256]; tailExtBHR_t tail; } secExtBHR_t, *pSecExtBHR_T; -#ifdef MV_TEST_PLATFORM +/***********************/ +/* SECURE PARAMS */ +/***********************/ +#define CSK_BLOCK_OFFSET 0x420 +#define PUB_KEY_SIZE 524 +#define CSK_KEY_NUM 16 +#define CSK_BLOCK_SIGN_OFFSET (CSK_BLOCK_OFFSET + (PUB_KEY_SIZE * CSK_KEY_NUM)) +/* 16 keys + 256 bytes long signature */ +#define CSK_BLOCK_SIZE ((PUB_KEY_SIZE * CSK_KEY_NUM) + 0x100) + + #define BOOTROM_SIZE (64 * 1024) -#else -#define BOOTROM_SIZE (48 * 1024) -#endif #define EXT_HDR_BASE_SIZE (sizeof(headExtBHR_t) + sizeof(tailExtBHR_t)) /* MAX size of entire headers block */ -#define MAX_HEADER_SIZE (64 * 1024) +#define MAX_HEADER_SIZE (192 * 1024) #define MAX_TWSI_HDR_SIZE (60 * 1024) /* MAX eeprom is 64K & leave 4K for image and header */ /* Boot Type - block ID */ @@ -167,8 +175,48 @@ typedef struct secExtBHR_t #define IBR_HDR_NAND_ID 0x8B #define IBR_HDR_SATA_ID 0x78 #define IBR_HDR_PEX_ID 0x9C +#define IBR_HDR_MMC_ID 0xAE #define IBR_HDR_UART_ID 0x69 #define IBR_DEF_ATTRIB 0x00 +/* ROM flags */ +#define BHR_FLAG_PRINT_EN 0x01 +#define BHR_FLAG_RESERVED1 0x02 +#define BHR_FLAG_RESERVED2 0x04 +#define BHR_FLAG_RESERVED3 0x08 +#define BHR_FLAG_RESERVED4 0x10 +#define BHR_FLAG_RESERVED5 0x20 +#define BHR_FLAG_RESERVED6 0x40 +#define BHR_FLAG_RESERVED7 0x80 + +/* ROM options */ +#define BHR_OPT_BAUDRATE_OFFS 0x0 +#define BHR_OPT_BAUDRATE_MASK (0x7 << BHR_OPT_BAUDRATE_OFFS) +#define BHR_OPT_BAUD_DEFAULT (0x0 << BHR_OPT_BAUDRATE_OFFS) +#define BHR_OPT_BAUD_2400 (0x1 << BHR_OPT_BAUDRATE_OFFS) +#define BHR_OPT_BAUD_4800 (0x2 << BHR_OPT_BAUDRATE_OFFS) +#define BHR_OPT_BAUD_9600 (0x3 << BHR_OPT_BAUDRATE_OFFS) +#define BHR_OPT_BAUD_19200 (0x4 << BHR_OPT_BAUDRATE_OFFS) +#define BHR_OPT_BAUD_38400 (0x5 << BHR_OPT_BAUDRATE_OFFS) +#define BHR_OPT_BAUD_57600 (0x6 << BHR_OPT_BAUDRATE_OFFS) +#define BHR_OPT_BAUD_115200 (0x7 << BHR_OPT_BAUDRATE_OFFS) + +#define BHR_OPT_UART_PORT_OFFS 0x3 +#define BHR_OPT_UART_PORT_MASK (0x3 << BHR_OPT_UART_PORT_OFFS) + +#define BHR_OPT_UART_MPPS_OFFS 0x5 +#define BHR_OPT_UART_MPPS_MASK (0x7 << BHR_OPT_UART_PORT_OFFS) + + + + +typedef struct _mvCpuArmClk { + MV_U32 cpuClk; /* CPU clock MHz */ + MV_U32 ddrClk; /* DDR clock MHz */ + MV_U32 l2cClk; /* L2 cache clock MHz */ +} MV_CPU_ARM_CLK; + + #endif /* MV_ASMLANGUAGE */ #endif /* _INC_BOOTSTRAP_H */ + diff --git a/tools/marvell/doimage_mv/bootstrap_def.h b/tools/marvell/doimage_mv/bootstrap_def.h index d214b1b366f..366b5a3887d 100755 --- a/tools/marvell/doimage_mv/bootstrap_def.h +++ b/tools/marvell/doimage_mv/bootstrap_def.h @@ -73,9 +73,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define MAIN_HDR_NAND_SLC 0 #define MAIN_HDR_NAND_MLC 1 -typedef struct BHR_t -{ -// type name byte order +typedef struct BHR_t { +/* type name byte order */ MV_U8 blockID; /* 0 */ MV_U8 flags; /* 1 */ MV_U16 nandPageSize; /* 2-3 */ @@ -103,8 +102,7 @@ typedef struct BHR_t #define EXT_HDR_TYP_BINARY 0x02 #define EXT_HDR_TYP_REGISTER 0x03 -typedef struct headExtBHR_t /* Common extention header head */ -{ +typedef struct headExtBHR_t { /* Common extension header head */ // type name byte order MV_U8 type; MV_U8 lenMsb; @@ -121,8 +119,7 @@ typedef struct headExtBHR_t /* Common extention header head */ #define EXT_HDR_GET_LEN(pHead) \ (((MV_U32)((pHead)->lenMsb) << 16) | ((pHead)->lenLsb)) -typedef struct tailExtBHR_t /* Common extention header tail */ -{ +typedef struct tailExtBHR_t {/* Common extension header tail */ // type name byte order MV_U8 nextHdr; MV_U8 delay; @@ -130,32 +127,43 @@ typedef struct tailExtBHR_t /* Common extention header tail */ } tailExtBHR_t; +typedef struct publicKey_t {/* public key*/ + MV_U8 Key[524]; +} publicKey_t; + #define RSA_MAX_KEY_LEN_BYTES 256 -typedef struct secExtBHR_t -{ +typedef struct secExtBHR_t { headExtBHR_t head; MV_U8 encrypt; MV_U8 rsrvd0; MV_U16 rsrvd1; - MV_U8 pubKey[524]; + publicKey_t pubKey; MV_U8 jtagEn; MV_U8 rsrvd2; MV_U16 rsrvd3; MV_U32 boxId; - MV_U16 flashId; - MV_U16 rsrvd4; + MV_U32 flashId; MV_U8 hdrSign[256]; MV_U8 imgSign[256]; + publicKey_t cskArray[16]; + MV_U8 cskBlockSign[256]; tailExtBHR_t tail; } secExtBHR_t, *pSecExtBHR_T; -#ifdef MV_TEST_PLATFORM +/***********************/ +/* SECURE PARAMS */ +/***********************/ +#define CSK_BLOCK_OFFSET 0x420 +#define PUB_KEY_SIZE 524 +#define CSK_KEY_NUM 16 +#define CSK_BLOCK_SIGN_OFFSET (CSK_BLOCK_OFFSET + (PUB_KEY_SIZE * CSK_KEY_NUM)) +/* 16 keys + 256 bytes long signature */ +#define CSK_BLOCK_SIZE ((PUB_KEY_SIZE * CSK_KEY_NUM) + 0x100) + + #define BOOTROM_SIZE (64 * 1024) -#else -#define BOOTROM_SIZE (48 * 1024) -#endif #define EXT_HDR_BASE_SIZE (sizeof(headExtBHR_t) + sizeof(tailExtBHR_t)) /* MAX size of entire headers block */ #define MAX_HEADER_SIZE (192 * 1024) @@ -199,6 +207,16 @@ typedef struct secExtBHR_t #define BHR_OPT_UART_MPPS_OFFS 0x5 #define BHR_OPT_UART_MPPS_MASK (0x7 << BHR_OPT_UART_MPPS_OFFS) + + + +typedef struct _mvCpuArmClk { + MV_U32 cpuClk; /* CPU clock MHz */ + MV_U32 ddrClk; /* DDR clock MHz */ + MV_U32 l2cClk; /* L2 cache clock MHz */ +} MV_CPU_ARM_CLK; + + #endif /* MV_ASMLANGUAGE */ #endif /* _INC_BOOTSTRAP_H */ diff --git a/tools/marvell/doimage_mv/doimage.c b/tools/marvell/doimage_mv/doimage.c index 6162dd46854..99861a9ef50 100644 --- a/tools/marvell/doimage_mv/doimage.c +++ b/tools/marvell/doimage_mv/doimage.c @@ -98,7 +98,7 @@ int f_out = -1; int f_header = -1; struct stat fs_stat; rsa_context rsa; -aes_context aes; +rsa_context rsaCsk; unsigned char IV[16] = {0}; /******************************************************************************* @@ -108,6 +108,7 @@ unsigned char IV[16] = {0}; * input memory buffer * ilen buffer length * print_val if not 0, print SHA-256 digest of the memory buffer (debug) +* kak selector between kak key or csk key * OUTPUT: * signature RSA-2048 signature * RETURN: @@ -115,15 +116,20 @@ unsigned char IV[16] = {0}; *******************************************************************************/ int create_rsa_signature ( unsigned char *input, - int ilen, + int ilen, unsigned char *signature, - char *print_val) + char *print_val, + unsigned int kak) { unsigned char sha_256[32]; int i; + rsa_context *rsaCont = &rsaCsk; memset(sha_256, 0, 32 * sizeof(unsigned char)); + if (kak != 0) + rsaCont = &rsa; + /* compute SHA-256 digest */ sha2(input, ilen, sha_256, 0); @@ -134,7 +140,7 @@ int create_rsa_signature ( printf("\n"); } - return rsa_pkcs1_sign(&rsa, RSA_PRIVATE, RSA_SHA256, 32, sha_256, signature); + return rsa_pkcs1_sign(rsaCont, RSA_PRIVATE, RSA_SHA256, 32, sha_256, signature); } /* end of create_rsa_signature() */ @@ -144,7 +150,8 @@ int create_rsa_signature ( * INPUT: * input memory buffer * ilen buffer length - signature RSA-2048 signature +* signature RSA-2048 signature +* kak selector between kak key or csk key * OUTPUT: * none * RETURN: @@ -152,17 +159,22 @@ int create_rsa_signature ( *******************************************************************************/ int verify_rsa_signature ( unsigned char *input, - int ilen, - unsigned char *signature) + int ilen, + unsigned char *signature, + unsigned int kak) { unsigned char sha_256[32]; + rsa_context *rsaCont = &rsaCsk; memset(sha_256, 0, 32 * sizeof(unsigned char)); + if (kak != 0) + rsaCont = &rsa; + /* compute SHA-256 digest */ sha2(input, ilen, sha_256, 0); - return rsa_pkcs1_verify(&rsa, RSA_PUBLIC, RSA_SHA256, 32, sha_256, signature); + return rsa_pkcs1_verify(rsaCont, RSA_PUBLIC, RSA_SHA256, 32, sha_256, signature); } /* end of create_rsa_signature() */ @@ -390,8 +402,8 @@ int build_bin_header (char *fname, MV_U8 *buffer, MV_U32 current_size) if (i >= (max_bytes_to_write / 4)) { fprintf(stderr,"Binary extention exeeds the maximum size " "of %d bytes\n", max_bytes_to_write); - return 0; -} + return 0; + } /* Include extended header head and tail sizes */ tmp_len = EXT_HDR_BASE_SIZE + i * 4; @@ -556,19 +568,6 @@ int build_headers (USER_OPTIONS *opt, char *buf_in) /* Create extension header(s) */ /* Security Header - always single and always first after the Main header */ if (opt->flags & Z_OPTION_MASK) { - if (opt->flags & A_OPTION_MASK) { - int align16 = 0; - - if (hdr->blockSize & 0xF) - align16 = 16 - hdr->blockSize & 0xF; - /* At this stage everything is 4-bytes aligned */ - /* For AES-128 the image should be aligned to 16 bytes */ - /* Additional 16 bytes are also required for IV storage */ - hdr->blockSize += align16 + 16; - opt->postpadding_size += align16; - opt->post_padding = 1; - } - /* Allocate space for security header, but do not fill in it now */ secExtHdr = (secExtBHR_t *)(tmpHeader + header_size); secExtHdr->head.type = EXT_HDR_TYP_SECURITY; @@ -661,11 +660,11 @@ int build_headers (USER_OPTIONS *opt, char *buf_in) /* Insert required header into the output buffer */ hdr_len = build_hdr_func(fname, tmpHeader, header_size); if (hdr_len <= 0) - goto header_error; + goto header_error; header_size += hdr_len; - tailExtHdr = (tailExtBHR_t *)(tmpHeader + header_size - sizeof(tailExtBHR_t)); - } + tailExtHdr = (tailExtBHR_t *)(tmpHeader + header_size - sizeof(tailExtBHR_t)); + } fclose(f_list); } /* if (fname_list) */ @@ -687,8 +686,8 @@ int build_headers (USER_OPTIONS *opt, char *buf_in) /* Setup the image source address */ if (opt->image_type == IMG_SATA) { if ((opt->image_source) && (opt->image_source > header_size)) - hdr->sourceAddr = opt->image_source; - else + hdr->sourceAddr = opt->image_source; + else hdr->sourceAddr = header_size >> 9; /* Already aligned to 512 */ } else { if ((opt->image_source) && (opt->image_source > header_size)) { @@ -765,39 +764,41 @@ int build_headers (USER_OPTIONS *opt, char *buf_in) /* Security header has a constant length */ secExtHdr->head.lenLsb = sizeof(secExtBHR_t); - rsa_exp_len = (mpi_msb(&rsa.E) + 7) >> 3; /* exponent length in bytes */ + /*CSK*/ + rsa_exp_len = (mpi_msb(&rsaCsk.E) + 7) >> 3; /* exponent length in bytes */ /* Full RSA public key lengh in DER encoding includes: - modulus (N) length - exponent (E) length - 4 bytes for each of the above components (type and length fields) Four bytes for the data block header are not included in this calculation */ - rsa_key_len = rsa.len + rsa_exp_len + 8; + rsa_key_len = rsaCsk.len + rsa_exp_len + 8; - /* First the RSA public key should be inserted into security header */ + /* First the CSK RSA public key should be inserted into security header */ /* Use DER encoding and long length field form (3 bytes) */ - secExtHdr->pubKey[0] = 0x30; /* Type field for entire block */ - secExtHdr->pubKey[1] = 0x82; /* long form, 2 bytes length field */ - secExtHdr->pubKey[2] = (rsa_key_len & 0xFF00) >> 8; - secExtHdr->pubKey[3] = rsa_key_len & 0x00FF; - secExtHdr->pubKey[4] = 0x02; /* modulus type (integer) */ - secExtHdr->pubKey[5] = 0x82; /* long form, 2 bytes length field */ - secExtHdr->pubKey[6] = (rsa.len & 0x0000FF00) >> 8; - secExtHdr->pubKey[7] = rsa.len; /*we support up to 256 bytes key length */ - secExtHdr->pubKey[8 + rsa.len] = 0x02; /* exponent type (integer) */ - secExtHdr->pubKey[9 + rsa.len] = 0x82; /* long form, 2 bytes length field */ - secExtHdr->pubKey[10 + rsa.len] = (rsa_exp_len & 0x0000FF00) >> 8; - secExtHdr->pubKey[11 + rsa.len] = rsa_exp_len; - - if ((0 != mpi_write_binary(&rsa.N, &secExtHdr->pubKey[8], rsa.len)) || - (0 != mpi_write_binary(&rsa.E, &secExtHdr->pubKey[12 + rsa.len], rsa_exp_len))) { + (((secExtHdr->cskArray)[opt->csk_index]).Key)[0] = 0x30; /*Type field for entire block */ + (((secExtHdr->cskArray)[opt->csk_index]).Key)[1] = 0x82; /*long form, 2 bytes length field */ + (((secExtHdr->cskArray)[opt->csk_index]).Key)[2] = (rsa_key_len & 0xFF00) >> 8; + (((secExtHdr->cskArray)[opt->csk_index]).Key)[3] = rsa_key_len & 0x00FF; + (((secExtHdr->cskArray)[opt->csk_index]).Key)[4] = 0x02; /*modulus type (integer) */ + (((secExtHdr->cskArray)[opt->csk_index]).Key)[5] = 0x82; /*long form, 2 bytes length field */ + (((secExtHdr->cskArray)[opt->csk_index]).Key)[6] = (rsaCsk.len & 0x0000FF00) >> 8; + (((secExtHdr->cskArray)[opt->csk_index]).Key)[7] = rsaCsk.len; /*we support up to 256 bytes key length */ + (((secExtHdr->cskArray)[opt->csk_index]).Key)[8 + rsaCsk.len] = 0x02; /* exponent type (integer) */ + (((secExtHdr->cskArray)[opt->csk_index]).Key)[9 + rsaCsk.len] = 0x82; /* long form, 2 bytes length field */ + (((secExtHdr->cskArray)[opt->csk_index]).Key)[10 + rsaCsk.len] = (rsa_exp_len & 0x0000FF00) >> 8; + (((secExtHdr->cskArray)[opt->csk_index]).Key)[11 + rsaCsk.len] = rsa_exp_len; + + if ((0 != mpi_write_binary(&rsaCsk.N, &(((secExtHdr->cskArray)[opt->csk_index]).Key)[8], rsa.len)) || + (0 != mpi_write_binary(&rsaCsk.E, &(((secExtHdr->cskArray)[opt->csk_index]).Key)[12 + rsa.len], + rsa_exp_len))) { fprintf(stderr, "Failed to write RSA key to security header\n"); goto header_error; } - sha2((unsigned char *)secExtHdr->pubKey, rsa_key_len + 4, rsa_digest, 0); - if ((f_sha = fopen("./sha2_pub.txt", "w")) == NULL) - fprintf(stderr, "Error opening SHA-256 digest file ./sha2_pub.txt\n"); + sha2((unsigned char *)(((secExtHdr->cskArray)[opt->csk_index]).Key), rsa_key_len + 4, rsa_digest, 0); + if ((f_sha = fopen("./sha2_pub_csk.txt", "w")) == NULL) + fprintf(stderr, "Error opening SHA-256 digest file ./sha2_pub_csk.txt\n"); fprintf(f_sha, "SHA256 = "); @@ -810,36 +811,72 @@ int build_headers (USER_OPTIONS *opt, char *buf_in) DB(stdout, "Box ID = 0x%08X, Flash ID = 0x%04X, JTAG %s\n", opt->boxId, opt->flashId, opt->jtagDelay == 0 ? "DISABLED" : "ENABLED"); - /* Encrypt boot image using AES-128-CBC if required */ - if (opt->flags & A_OPTION_MASK) { - MV_U32 chsum32 = 0; + /* the RSA signature is now can be created for the CSK Array using KAK */ + error = create_rsa_signature(tmpHeader + sizeof(BHR_t) + CSK_BLOCK_OFFSET, + CSK_BLOCK_SIZE, rsa_signature, "CSK ARRAY SHA256:", 1); + if (0 != error) { + fprintf(stderr, "Failed to create CSK array signature using KAK, error %d\n", error); + goto header_error; + } - secExtHdr->encrypt = 1; +#if defined MV_MEMPOOL_STAT && defined NO_HEAP + fprintf(stdout, "CSK Header signature creation\n"); + mpool_print_stat(); + mpool_reset_stat(); +#endif - if ((opt->image_dest == 0xFFFFFFFF) && - (opt->image_type == IMG_FLASH)) { - fprintf(stderr, "Wrong setup - Encrypted image with direct SPI boot!\n"); - fprintf(stderr, "The image should be downloaded into RAM for decryption.\n"); - fprintf(stderr, "Please define a valid destination address!\n"); - goto header_error; - } - /* 16 bytes at tail - IV, followed by 4 bytes of CHKSUM */ - chsum32 = checksum32((void*)(opt->image_buf), opt->image_sz - 20, 0); - fprintf(stdout, "The image (plain img. CHKSUM = %08X) is encrypted using AES-128.\n", chsum32); - - if ((opt->image_sz - 4) % 16) { - fprintf(stderr, "Total boot image size (%d) is not multiple of 16!\n", - opt->image_sz); - free(opt->image_buf); - goto header_error; - } + /* Header signature MUST be checked when it's placeholder in the heqader is zeroed */ + if (0 != verify_rsa_signature(tmpHeader + sizeof(BHR_t) + CSK_BLOCK_OFFSET, + CSK_BLOCK_SIZE, rsa_signature, 1 /* KAK*/)) { + fprintf(stderr, "Failed to verify header CSK RSA signature\n"); + goto header_error; + } + memcpy(secExtHdr->cskBlockSign, rsa_signature, rsa.len); - aes_crypt_cbc(&aes, AES_ENCRYPT, opt->image_sz - 20, IV, - opt->image_buf, opt->image_buf); - } /* AES-128 encryption */ + /*KAK*/ + rsa_exp_len = (mpi_msb(&rsa.E) + 7) >> 3; /* exponent length in bytes */ + /* Full RSA public key lengh in DER encoding includes: + - modulus (N) length + - exponent (E) length + - 4 bytes for each of the above components (type and length fields) + Four bytes for the data block header are not included in this calculation + */ + rsa_key_len = rsa.len + rsa_exp_len + 8; + + /* Next the KAK RSA public key should be inserted into security header */ + /* Use DER encoding and long length field form (3 bytes) */ + ((secExtHdr->pubKey).Key)[0] = 0x30; /* Type field for entire block */ + ((secExtHdr->pubKey).Key)[1] = 0x82; /* long form, 2 bytes length field */ + ((secExtHdr->pubKey).Key)[2] = (rsa_key_len & 0xFF00) >> 8; + ((secExtHdr->pubKey).Key)[3] = rsa_key_len & 0x00FF; + ((secExtHdr->pubKey).Key)[4] = 0x02; /* modulus type (integer) */ + ((secExtHdr->pubKey).Key)[5] = 0x82; /* long form, 2 bytes length field */ + ((secExtHdr->pubKey).Key)[6] = (rsa.len & 0x0000FF00) >> 8; + ((secExtHdr->pubKey).Key)[7] = rsa.len; /*we support up to 256 bytes key length */ + ((secExtHdr->pubKey).Key)[8 + rsa.len] = 0x02; /* exponent type (integer) */ + ((secExtHdr->pubKey).Key)[9 + rsa.len] = 0x82; /* long form, 2 bytes length field */ + ((secExtHdr->pubKey).Key)[10 + rsa.len] = (rsa_exp_len & 0x0000FF00) >> 8; + ((secExtHdr->pubKey).Key)[11 + rsa.len] = rsa_exp_len; + + if ((0 != mpi_write_binary(&rsa.N, &((secExtHdr->pubKey).Key)[8], rsa.len)) || + (0 != mpi_write_binary(&rsa.E, &((secExtHdr->pubKey).Key)[12 + rsa.len], rsa_exp_len))) { + fprintf(stderr, "Failed to write RSA key to security header\n"); + goto header_error; + } + sha2((unsigned char *)((secExtHdr->pubKey).Key), rsa_key_len + 4, rsa_digest, 0); + if ((f_sha = fopen("./sha2_pub_kak.txt", "w")) == NULL) + fprintf(stderr, "Error opening SHA-256 digest file ./sha2_pub_kak.txt\n"); + + fprintf(f_sha, "SHA256 = "); + + for (k = 0; k < 32; k++) + fprintf(f_sha, "%02X", rsa_digest[k]); + + fprintf(f_sha, "\n"); + fclose(f_sha); - /* Create RSA signature for the boot image file (checksum is not included) */ - error = create_rsa_signature(opt->image_buf, opt->image_sz - 4, secExtHdr->imgSign, "IMG SHA256: "); + /* Create RSA signature for the boot image file using CSK (checksum is not included) */ + error = create_rsa_signature(opt->image_buf, opt->image_sz - 4, secExtHdr->imgSign, "IMG SHA256:", 0 /*CSK*/); if (0 != error) { fprintf(stderr, "Failed to create boot image RSA signature, error %d\n", error); goto header_error; @@ -850,7 +887,7 @@ int build_headers (USER_OPTIONS *opt, char *buf_in) mpool_print_stat(); mpool_reset_stat(); #endif - error = verify_rsa_signature(opt->image_buf, opt->image_sz - 4, secExtHdr->imgSign); + error = verify_rsa_signature(opt->image_buf, opt->image_sz - 4, secExtHdr->imgSign, 0 /*CSK*/); if (0 != error) { fprintf(stderr, "Failed to verify boot image RSA signature, error %d\n", error); goto header_error; @@ -862,8 +899,8 @@ int build_headers (USER_OPTIONS *opt, char *buf_in) mpool_reset_stat(); #endif - /* the RSA signature is now can be created for the entire headers block */ - error = create_rsa_signature(tmpHeader, header_size, rsa_signature, "HDR SHA256: "); + /* the RSA signature is now can be created for the entire headers block using CSK */ + error = create_rsa_signature(tmpHeader, header_size, rsa_signature, "HDR SHA256:", 0 /*CSK*/); if (0 != error) { fprintf(stderr, "Failed to create header RSA signature, error %d\n", error); goto header_error; @@ -876,7 +913,7 @@ int build_headers (USER_OPTIONS *opt, char *buf_in) #endif /* Header signature MUST be checked when it's placeholder in the heqader is zeroed */ - error = verify_rsa_signature(tmpHeader, header_size, rsa_signature); + error = verify_rsa_signature(tmpHeader, header_size, rsa_signature, 0 /*CSK*/); if (0 != error) { fprintf(stderr, "Failed to verify header RSA signature, error %d\n", error); goto header_error; @@ -1250,7 +1287,7 @@ int build_bin_img (USER_OPTIONS *opt, char *buf_in) bin_image_end: - if (tmpImg) + if (tmpImg) free(tmpImg); for (i = 0; i < files_num; i++) { @@ -1273,7 +1310,7 @@ int build_bin_img (USER_OPTIONS *opt, char *buf_in) * RETURN: * 0 on success *******************************************************************************/ -int build_regular_img (USER_OPTIONS *opt, char *buf_in) +int build_regular_img (USER_OPTIONS *opt, char *buf_in) { int size_written = 0; int new_file_size = 0; @@ -1313,35 +1350,40 @@ int build_regular_img (USER_OPTIONS *opt, char *buf_in) /******************************************************************************* * read_rsa_key -* read RSA key from file +* read RSA private key from file * INPUT: * fname private key file name * rsa RSA context +* kak Type of key to use (CSK or KAK) * OUTPUT: * rsa RSA context * RETURN: * 0 on success *******************************************************************************/ -int read_rsa_key(char *fname) +int read_rsa_key(char *fname, char kak) { - FILE *f_prkey; - int ret; + FILE *f_prkey; + int ret; + rsa_context *rsaCont = &rsaCsk; if ((f_prkey = fopen(fname, "r")) == NULL) { fprintf(stderr, "Error opening RSA private key file %s\n", fname); return -1; } - rsa_init(&rsa, RSA_PKCS_V15, 0, NULL, NULL); + if (kak != 0) + rsaCont = &rsa; + + rsa_init(rsaCont, RSA_PKCS_V15, 0, NULL, NULL); - ret = mpi_read_file(&rsa.N , 16, f_prkey); - ret += mpi_read_file(&rsa.E , 16, f_prkey); - ret += mpi_read_file(&rsa.D , 16, f_prkey); - ret += mpi_read_file(&rsa.P , 16, f_prkey); - ret += mpi_read_file(&rsa.Q , 16, f_prkey); - ret += mpi_read_file(&rsa.DP, 16, f_prkey); - ret += mpi_read_file(&rsa.DQ, 16, f_prkey); - ret += mpi_read_file(&rsa.QP, 16, f_prkey); + ret = mpi_read_file(&rsaCont->N , 16, f_prkey); + ret += mpi_read_file(&rsaCont->E , 16, f_prkey); + ret += mpi_read_file(&rsaCont->D , 16, f_prkey); + ret += mpi_read_file(&rsaCont->P , 16, f_prkey); + ret += mpi_read_file(&rsaCont->Q , 16, f_prkey); + ret += mpi_read_file(&rsaCont->DP, 16, f_prkey); + ret += mpi_read_file(&rsaCont->DQ, 16, f_prkey); + ret += mpi_read_file(&rsaCont->QP, 16, f_prkey); fclose(f_prkey); @@ -1353,177 +1395,77 @@ int read_rsa_key(char *fname) * generate RSA key pair and save new keys into text files * INPUT: * rsa RSA context +* kak Type of key to use (CSK or KAK) * OUTPUT: * rsa RSA context * RETURN: * 0 on success *******************************************************************************/ -int generate_rsa_key(void) +int generate_rsa_key(char kak) { int ret; havege_state hs; FILE *fpub = NULL; FILE *fpriv = NULL; + rsa_context *rsaCont; + char fname[80]; havege_init(&hs); - rsa_init(&rsa, RSA_PKCS_V15, 0, havege_rand, &hs); + if (kak != 0) { + rsaCont = &rsa; + sprintf(fname, "rsa_pub_kak.txt"); + } else { + rsaCont = &rsaCsk; + sprintf(fname, "rsa_pub_csk.txt"); + } - if (rsa_gen_key(&rsa, RSA_KEY_SIZE, RSA_EXPONENT) != 0) { + rsa_init(rsaCont, RSA_PKCS_V15, 0, havege_rand, &hs); + + if (rsa_gen_key(rsaCont, RSA_KEY_SIZE, RSA_EXPONENT) != 0) { fprintf(stderr, "Failed to generate RSA key\n"); return -1; } - fpub = fopen("rsa_pub.txt", "w+"); + fpub = fopen(fname, "w+"); if (fpub == NULL) { - fprintf(stderr, "Could not open rsa_pub.txt file for writing\n"); + fprintf(stderr, "Could not open %s file for writing\n", fname); return -1; } - ret = mpi_write_file("N = ", &rsa.N, 16, fpub); - ret += mpi_write_file("E = ", &rsa.E, 16, fpub); + ret = mpi_write_file("N = ", &rsaCont->N, 16, fpub); + ret += mpi_write_file("E = ", &rsaCont->E, 16, fpub); fclose(fpub); if (ret != 0) { - fprintf(stderr, "Failed to write into rsa_pub.txt file!\n"); + fprintf(stderr, "Failed to write into %s file!\n", fname); return -1; } - fpriv = fopen("rsa_priv.txt", "w+"); + if (kak != 0) + sprintf(fname, "rsa_priv_kak.txt"); + else + sprintf(fname, "rsa_priv_sck.txt"); + + fpriv = fopen(fname, "w+"); if (fpriv == NULL) { - fprintf(stderr, "Could not open rsa_priv.txt file for writing\n"); + fprintf(stderr, "Could not open %s file for writing\n", fname); return -1; } - ret = mpi_write_file("N = " , &rsa.N , 16, fpriv); - ret += mpi_write_file("E = " , &rsa.E , 16, fpriv); - ret += mpi_write_file("D = " , &rsa.D , 16, fpriv); - ret += mpi_write_file("P = " , &rsa.P , 16, fpriv); - ret += mpi_write_file("Q = " , &rsa.Q , 16, fpriv); - ret += mpi_write_file("DP = ", &rsa.DP, 16, fpriv); - ret += mpi_write_file("DQ = ", &rsa.DQ, 16, fpriv); - ret += mpi_write_file("QP = ", &rsa.QP, 16, fpriv); + ret = mpi_write_file("N = " , &rsaCont->N , 16, fpriv); + ret += mpi_write_file("E = " , &rsaCont->E , 16, fpriv); + ret += mpi_write_file("D = " , &rsaCont->D , 16, fpriv); + ret += mpi_write_file("P = " , &rsaCont->P , 16, fpriv); + ret += mpi_write_file("Q = " , &rsaCont->Q , 16, fpriv); + ret += mpi_write_file("DP = ", &rsaCont->DP, 16, fpriv); + ret += mpi_write_file("DQ = ", &rsaCont->DQ, 16, fpriv); + ret += mpi_write_file("QP = ", &rsaCont->QP, 16, fpriv); if (ret != 0) fprintf(stderr, "Failed to write into rsa_priv.txt file!\n"); return ret; } -/******************************************************************************* -* read_aes_key -* read AES key from file -* INPUT: -* fname AES key file name -* aes_key AES key -* init_vect AES IV -* OUTPUT: -* aes_key AES key -* init_vect AES IV -* RETURN: -* 0 on success -*******************************************************************************/ -int read_aes_key(char *fname, unsigned char *aes_key, unsigned char *init_vect) -{ - int ret = -1; - size_t num; - FILE *fkey = NULL; - char line[120] = {0}; - unsigned char *curr_val = NULL; - char *num_str = NULL; - - fkey = fopen(fname, "r"); - if (fkey == NULL) { - fprintf(stderr, "Could not open AES key file %s\n", fname); - return -1; - } - - /* Read and parse every string in file */ - while (fgets(line, 120, fkey) != NULL) { - - if (strncmp("AES = ", line, 6) == 0) { - num_str = line + 6; - curr_val = aes_key; - } else if (strncmp("IV = ", line, 5) == 0) { - num_str = line + 5; - curr_val = init_vect; - } else - continue; - - num = strlen(num_str); - if ((num_str[num - 1] == '\n') || (num_str[num - 1] == '\r')) { - num_str[num - 1] = '\0'; - num--; - } - - /* The row should contain 2 characters per key digit */ - if (strlen(num_str) != (AES_KEY_SIZE >> 2)) { - fprintf(stderr, "Badly formed string [%s] in file %s\n", line, fname); - goto aes_read_end; - } - - for (; num > 0; num -= 2) { - if (sscanf(num_str, "%02hhx", curr_val) == EOF) { - fprintf(stderr, "Conversion error starting %s\n", num_str); - goto aes_read_end; - } - curr_val++; - num_str += 2; - } - - } /* for each line in file */ - - ret = 0; - -aes_read_end: - - fclose(fkey); - return ret; -} - -/******************************************************************************* -* generate_rsa_key -* generate AES key and IV and save them into text files -* INPUT: -* aes AES context -* OUTPUT: -* aes AES context -* RETURN: -* 0 on success -*******************************************************************************/ -int generate_aes_key(unsigned char *aes_key, unsigned char *init_vect) -{ - int ret = 0, i, k; - havege_state hs; - FILE *fkey = NULL; - unsigned char *curr_val = aes_key; - char *rname[2] = {"AES", "IV"}; - - havege_init(&hs); - - fkey = fopen("aes_key.txt", "w"); - if (fkey == NULL) { - fprintf(stderr, "Could not open AES key file aes_key.txt\n"); - return -1; - } - - /* Fill AES key and IV with random numbers generated by HAVEGE */ - for (i = 0; i < 2; i++) { - - fprintf(fkey, "%s = ", rname[i]); - - for (k = 0; k < 16; k++) { - curr_val[k] = (unsigned char)havege_rand(&hs); - fprintf(fkey, "%02X", curr_val[k]); - } - - fprintf(fkey, "\n"); - - curr_val = init_vect; - } - - fclose(fkey); - return ret; -} - /******************************************************************************* * process_image * handle input and output file options, read and verify RSA and AES keys. @@ -1558,7 +1500,7 @@ int process_image(USER_OPTIONS *opt) exit(0); } else if ((c == 'Y')||(c == 'y')) { /* additional read is needed for Enter key */ - c = getc(stdin); + c = getc(stdin); } override[i] = 1; } @@ -1609,7 +1551,7 @@ int process_image(USER_OPTIONS *opt) if (f_out == -1) { fprintf(stderr,"Error opening %s file \n", opt->fname.out); goto end; - } + } /* open the output header file */ if (opt->header_mode == HDR_IMG_TWO_FILES) { @@ -1624,18 +1566,18 @@ int process_image(USER_OPTIONS *opt) } } - /* secure boot support - read RSA private key */ + /* secure boot support - read KAK RSA private key */ if (opt->flags & Z_OPTION_MASK) { - + /* KAK */ if (strncmp(opt->fname_prkey, "@@", 2) != 0) { /* private key file supplied */ - if (read_rsa_key(opt->fname_prkey) != 0) { - fprintf(stderr, "Cannot read RSA private key file %s\n\n", opt->fname_prkey); + if (read_rsa_key(opt->fname_prkey, 1) != 0) { + fprintf(stderr, "Cannot read KAK RSA private key file %s\n\n", opt->fname_prkey); goto end; } } else { /* new key pair is required */ - DB("Generating new RSA key pair..."); - if (generate_rsa_key() != 0) { - fprintf(stderr, "Cannot generate RSA key pair\n\n"); + DB("Generating new KAK RSA key pair..."); + if (generate_rsa_key(1) != 0) { + fprintf(stderr, "Cannot generate KAK RSA key pair\n\n"); goto end; } DB("OK\n"); @@ -1649,30 +1591,33 @@ int process_image(USER_OPTIONS *opt) rsa.len, RSA_MAX_KEY_LEN_BYTES); goto end; } else - fprintf(stdout, "The RSA private key is %d bit long\n", rsa.len * 8); + fprintf(stdout, "KAK RSA private key is %d bit long\n", rsa.len * 8); - /* Use AES-128 encryption - read the key and generate IV vector */ - if (opt->flags & A_OPTION_MASK) { - unsigned char aes_key[16]; - - if (strncmp(opt->fname_aeskey, "@@", 2) != 0) { /* AES key file supplied */ - if (read_aes_key(opt->fname_aeskey, aes_key, IV) != 0) { - fprintf(stderr, "Cannot read AES key file\n\n"); - goto end; - } - } else { /* new key is required */ - DB("Generating new AES key ..."); - if (generate_aes_key(aes_key, IV) != 0) { - fprintf(stderr, "Cannot generate AES key\n\n"); - goto end; - } - DB("OK\n"); + /*CSK*/ + /* secure boot support - read CSK RSA private key */ + if (strncmp(opt->fname_prkeyCsk, "@@", 2) != 0) { /* private key file supplied */ + if (read_rsa_key(opt->fname_prkeyCsk, 0) != 0) { + fprintf(stderr, "Cannot read CSK RSA private key file %s\n\n", opt->fname_prkey); + goto end; } + } else { /* new key pair is required */ + DB("Generating new CSK RSA key pair..."); + if (generate_rsa_key(0) != 0) { + fprintf(stderr, "Cannot generate CSK RSA key pair\n\n"); + goto end; + } + DB("OK\n"); + } - aes_setkey_enc(&aes, aes_key, 128); - - } /* AES-128 encryption */ + rsaCsk.len = (mpi_msb(&rsaCsk.N) + 7) >> 3; /* key lenght in bytes */ + if (RSA_MAX_KEY_LEN_BYTES < rsaCsk.len) { + fprintf(stderr, "Wrong RSA key length - %d bytes!" + " Supported RSA keys up to %d bytes\n", + rsaCsk.len, RSA_MAX_KEY_LEN_BYTES); + goto end; + } else + fprintf(stdout, "CSK RSA private key is %d bit long\n", rsaCsk.len * 8); } /* secure boot options */ /* Image Header(s) */ @@ -1709,7 +1654,7 @@ int process_image(USER_OPTIONS *opt) if (f_header != -1) close(f_header); - if (buf_in) + if (buf_in) munmap((void*)buf_in, fs_stat.st_size); if (f_in != -1) @@ -1766,20 +1711,22 @@ void print_usage(void) printf("\nSecure boot mode options - all options are mandatory once secure mode is selected by Z switch:\n"); printf("-----------------------------------------------------------------------------------------------\n\n"); - printf("-Z [prv_key_file]: Create image with RSA signature for secure boot mode\n"); - printf(" If the private key file name is missing, a new key pair will be generated\n"); - printf(" and saved in files named rsa_prv.key and rsa_pub.key\n"); - printf(" A new file named sha2_pub.txt will be generated for a public key\n"); - printf("-J jtag_delay: Enable JTAG and delay boot execution by \"N\" ms\n"); + printf("-Z [rsa_priv_kak_file]: Create image with RSA KAK block signature for secure boot mode\n"); + printf(" If the private key file name is \"@@\", a new key pair will be generated\n"); + printf(" and saved in files named rsa_priv_kak.key and rsa_pub_kak.key\n"); + printf(" A new file named sha2_pub_kak.txt will be generated for a public key\n"); + printf("-A [rsa_priv_csk_file]: Create image with RSA CSK signature for secure boot mode\n"); + printf(" If the private key file name is \"@@\", a new key pair will be generated\n"); + printf(" and saved in files named rsa_priv_csk.key and rsa_pub_sck.key\n"); + printf(" A new file named sha2_pub_csk.txt will be generated for a public key\n"); + printf("-K csk_index: CSK Array Index in range of 0 to 15\n"); + printf("-J jtag_delay: Enable JTAG and delay boot execution by \"jtag_delay\" ms\n"); printf("-B hex_box_id: Box ID (hex) - from 0 to 0xffffffff\n"); - printf("-F hex_flash_id: Flash ID (hex) - from 0 to 0xffff \n\n"); + printf("-F hex_flash_id: Flash ID (hex) - from 0 to 0xffffffff \n\n"); printf("\n[other_options] - optional and can be one or more of the following:\n"); printf("==============================================================================================\n\n"); - printf("-A [aes_key_file]: Valid in secure mode only. Encrypt the boot image using AES-128 key\n"); - printf(" If the aes key file name is missing, a new AES-128 key will be generated\n"); - printf(" and saved in file named aes_key.txt suitable for eFuse storage\n"); printf("-G exec_file: ascii file name that contains binary routine (ARM 5TE THUMB)\n"); printf(" to run before the bootloader image execution.\n"); printf(" The routine must contain an appropriate code for saving \n"); @@ -1847,9 +1794,9 @@ MV_U8 checksum8(void* start, MV_U32 len, MV_U8 csum) sum += *(MV_U8*)startp; startp++; - } while(--len); + } while(--len); - return (sum); + return (sum); } /* end of checksum8 */ @@ -1875,9 +1822,9 @@ MV_U32 checksum32(void* start, MV_U32 len, MV_U32 csum) startp++; len -= 4; - } while(len); + } while(len); - return (sum); + return (sum); } /* *end of checksum32() */ @@ -1946,8 +1893,8 @@ MV_U32 crc32(MV_U32 crc, volatile MV_U32 *buf, MV_U32 len) if (len) { do { - DO1(buf); - } while (--len); + DO1(buf); + } while (--len); } return crc ^ 0xffffffffL; @@ -2001,8 +1948,9 @@ int main (int argc, char** argv) { USER_OPTIONS options; int optch; /* command-line option char */ - static char optstring[] = "T:D:E:X:Y:S:P:W:H:R:M:Z:J:B:F:A:G:L:N:C:b:u:m:p"; + static char optstring[] = "T:D:E:X:Y:S:P:W:H:R:M:Z:K:J:B:F:A:G:L:N:C:b:u:m:p"; int i, k; + unsigned long secureOptions; if (argc < 2) goto parse_error; @@ -2124,7 +2072,7 @@ int main (int argc, char** argv) if (options.flags & Z_OPTION_MASK) goto parse_error; options.flags |= Z_OPTION_MASK; - DB("RSA private Key file name %s\n", options.fname_prkey); + DB("KAK RSA private Key file name %s\n", options.fname_prkey); break; case 'J': /* JTAG Enabled */ @@ -2151,12 +2099,16 @@ int main (int argc, char** argv) DB("Flash ID %#x\n", options.flashId); break; - case 'A': /* secure boot - encrypt with AES-128 key */ - options.fname_aeskey = optarg; - if (options.flags & A_OPTION_MASK) - goto parse_error; + case 'A': /* secure boot - CSK key */ + options.fname_prkeyCsk = optarg; options.flags |= A_OPTION_MASK; - DB("AES file name %s\n", options.fname_aeskey); + DB("CSK RSA private Key file name %s\n", options.fname_prkeyCsk); + break; + + case 'K': /* secure boot - CSK Array Index*/ + options.csk_index = strtoul(optarg, &endptr, 10); + options.flags |= K_OPTION_MASK; + DB("CSK Array Index %d\n", options.csk_index); break; case 'L': /* NAND block size */ @@ -2247,12 +2199,6 @@ int main (int argc, char** argv) if (options.req_flags != (options.flags & options.req_flags)) goto parse_error; - if ((options.flags & F_OPTION_MASK) && - (options.flashId > 0xFFFF)) { - fprintf(stderr,"Error: Flash ID is too long!\n\n\n\n\n"); - goto parse_error; - } - if ((options.flags & L_OPTION_MASK) && ((options.nandBlkSize > 255) || ((options.nandBlkSize == 0) && (options.nandPageSize != 512)))) { @@ -2267,6 +2213,19 @@ int main (int argc, char** argv) goto parse_error; } + secureOptions = A_OPTION_MASK | Z_OPTION_MASK | K_OPTION_MASK | + B_OPTION_MASK | F_OPTION_MASK; + if (options.flags & secureOptions) { + if ((options.flags & secureOptions) != secureOptions) { + fprintf(stderr,"Error: All secure options are mandatory!\n\n\n\n\n"); + goto parse_error; + } + if((options.csk_index < 0) || (options.csk_index > 16)) { + fprintf(stderr,"Error: Bad CSK Array Index - %d!\n\n\n\n\n", options.csk_index); + goto parse_error; + } + } + return process_image(&options); parse_error: diff --git a/tools/marvell/doimage_mv/doimage.h b/tools/marvell/doimage_mv/doimage.h index ba51acc67f0..f9480f52c04 100644 --- a/tools/marvell/doimage_mv/doimage.h +++ b/tools/marvell/doimage_mv/doimage.h @@ -67,19 +67,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include /* use the same version as in "bootrom.inc" file */ -#define VERSION_NUMBER "2.10" -#define PRODUCT_SUPPORT "Marvell Armada and xCAT series" +#define VERSION_NUMBER "2.20" +#define PRODUCT_SUPPORT "Marvell Armada-3xx series" #define RSA_KEY_SIZE 2048 #define RSA_EXPONENT 65537 -#define AES_KEY_SIZE 128 - -#define T_OPTION_MASK 0x1 /* image type */ -#define D_OPTION_MASK 0x2 /* image destination */ -#define E_OPTION_MASK 0x4 /* image execution address */ -#define S_OPTION_MASK 0x8 /* starting sector */ -#define R_OPTION_MASK 0x10 /* DRAM file */ +#define T_OPTION_MASK 0x1 /* image type */ +#define D_OPTION_MASK 0x2 /* image destination */ +#define E_OPTION_MASK 0x4 /* image execution address */ +#define S_OPTION_MASK 0x8 /* starting sector */ +#define R_OPTION_MASK 0x10 /* DRAM file */ #define C_OPTION_MASK 0x20 /* headers definition file */ #define P_OPTION_MASK 0x40 /* NAND Page size */ #define M_OPTION_MASK 0x80 /* TWSI serial init file */ @@ -89,10 +87,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define Y_OPTION_MASK 0x800 /* Post padding */ #define J_OPTION_MASK 0x1000 /* JTAG Enabled */ #define B_OPTION_MASK 0x2000 /* Box ID */ -#define Z_OPTION_MASK 0x4000 /* secure boot mode - private key */ +#define Z_OPTION_MASK 0x4000 /* secure boot mode - KAK private key */ #define F_OPTION_MASK 0x8000 /* Flash ID */ -#define A_OPTION_MASK 0x10000 /* AES encryption */ +#define A_OPTION_MASK 0x10000 /* secure boot mode - CSK private key */ #define G_OPTION_MASK 0x20000 /* binary file */ +#define K_OPTION_MASK 0x40000 /* secure boot mode - CSK private key index */ #define L_OPTION_MASK 0x80000 /* NAND block size (in 64K chunks) */ #define N_OPTION_MASK 0x100000/* NAND cell technology MLC/SLC */ #define p_OPTION_MASK 0x200000 /* Print enable */ @@ -144,46 +143,47 @@ typedef enum typedef enum { - HDR_IMG_ONE_FILE = 1, /* Create one file with header and image */ - HDR_IMG_TWO_FILES = 2, /* Create seperate header and image files */ - HDR_ONLY = 3, /* Create only header */ - IMG_ONLY = 4, /* Create only image */ + HDR_IMG_ONE_FILE = 1, /* Create one file with header and image */ + HDR_IMG_TWO_FILES = 2, /* Create seperate header and image files */ + HDR_ONLY = 3, /* Create only header */ + IMG_ONLY = 4, /* Create only image */ } HEADER_MODE; typedef struct { IMG_TYPE image_type; - char *fname_dram; /* DRAM init file for "register" header */ - char *fname_twsi; /* TWSI serial init file */ - char *fname_bin; /* binary code file for "binary" header */ - char *fname_prkey;/* RSA Private key file */ - char *fname_aeskey;/* AES-128 key file */ - char *fname_list; /* headers definition file */ - u32 flags; /* user-defined flags */ - u32 req_flags; /* mandatory flags */ - u32 image_source;/* starting sector */ - u32 image_dest; /* image destination */ - u32 image_exec; /* image execution */ - unsigned int hex_width; /* HEX file width */ - unsigned int header_mode; /* Header file mode */ - int pre_padding; - int post_padding; - int prepadding_size; - int postpadding_size; + char *fname_dram; /* DRAM init file for "register" header */ + char *fname_twsi; /* TWSI serial init file */ + char *fname_bin; /* binary code file for "binary" header */ + char *fname_prkey; /* KAK RSA Private key file */ + char *fname_prkeyCsk;/* CSK RSA Private key file */ + char *fname_list; /* headers definition file */ + u32 flags; /* user-defined flags */ + u32 req_flags; /* mandatory flags */ + u32 image_source; /* starting sector */ + u32 image_dest; /* image destination */ + u32 image_exec; /* image execution */ + unsigned int hex_width; /* HEX file width */ + unsigned int header_mode;/* Header file mode */ + int csk_index; + int pre_padding; + int post_padding; + int prepadding_size; + int postpadding_size; unsigned int bytesToAlign; unsigned int nandPageSize; unsigned int nandBlkSize; - char nandCellTech; - u32 boxId; - u32 flashId; - u32 jtagDelay; - char *image_buf; /* image buffer for image pre-load */ - u32 image_sz; /* total size of pre-loaded image buffer including paddings */ - u32 img_gap; /* gap between header and image start point */ - u32 baudRate; /* debug print port baudrate */ - u32 debugPortNum; /* debug print port number */ - u32 debugPortMpp; /* debug print port MPP configuration */ + char nandCellTech; + u32 boxId; + u32 flashId; + u32 jtagDelay; + char *image_buf; /* image buffer for image pre-load */ + u32 image_sz; /* total size of pre-loaded image buffer including paddings */ + u32 img_gap; /* gap between header and image start point */ + u32 baudRate; /* debug print port baudrate */ + u32 debugPortNum; /* debug print port number */ + u32 debugPortMpp; /* debug print port MPP configuration */ union { char *fname_arr[5]; diff --git a/tools/marvell/doimage_mv/hdrparser.c b/tools/marvell/doimage_mv/hdrparser.c index fe83be5e713..b7c230fef51 100755 --- a/tools/marvell/doimage_mv/hdrparser.c +++ b/tools/marvell/doimage_mv/hdrparser.c @@ -77,15 +77,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "polarssl/sha2.h" #include "polarssl/rsa.h" -#include "polarssl/aes.h" +//#include "polarssl/aes.h" -#define VERSION_NUMBER "1.1" +#define VERSION_NUMBER "2.0" /* Security context */ -typedef struct secCtx_t -{ +typedef struct secCtx_t { rsa_context rsa; - aes_context aes; +// aes_context aes; } secCtx_t; @@ -138,7 +137,8 @@ void print_usage(char *myname) printf("Usage: \n"); printf("%s [options] \n\n", myname); printf("Options: \n"); - printf("-t Test the header and image secure signatures\n"); + printf("-t Test secure signatures\n"); + printf("-k Use \"idx\" as CSK array index. Index range: 0 - 15\n"); printf("\n"); } @@ -193,10 +193,10 @@ int parse_main_header(pBHR_t pHdr) MAIN_HDR_GET_LEN(pHdr), MAIN_HDR_GET_LEN(pHdr)); if (pHdr->blockID == IBR_HDR_SATA_ID) { fprintf(stdout, "[15:12]Source address (LBA): 0x%08X\n", - pHdr->sourceAddr, pHdr->sourceAddr); + pHdr->sourceAddr); } else { fprintf(stdout, "[15:12]Source address: 0x%08X\n", - pHdr->sourceAddr, pHdr->sourceAddr); + pHdr->sourceAddr); } fprintf(stdout, "[19:16]Destination address: 0x%08X\n", pHdr->destinationAddr); @@ -231,6 +231,9 @@ int parse_main_header(pBHR_t pHdr) *******************************************************************************/ int parse_sec_header(pSecExtBHR_T pHdr) { + + int cskKey; + fprintf(stdout, "-----------------------------------------------------\n"); fprintf(stdout, " SECURITY HEADER @ %p\n", (void*)((char*)pHdr - buf_in)); fprintf(stdout, "-----------------------------------------------------\n"); @@ -245,7 +248,7 @@ int parse_sec_header(pSecExtBHR_T pHdr) fprintf(stdout, "[0007:0006]Reserved: 0x%04X\n", pHdr->rsrvd1); fprintf(stdout, "[0531:0008]Public Key: %02X %02X %02X %02X ...\n", - pHdr->pubKey[0], pHdr->pubKey[1], pHdr->pubKey[2], pHdr->pubKey[3]); + ((pHdr->pubKey).Key)[0], ((pHdr->pubKey).Key)[1], ((pHdr->pubKey).Key)[2], ((pHdr->pubKey).Key)[3]); fprintf(stdout, "[0532:0532]JTAG enabled: %s [%d]\n", pHdr->jtagEn != 0 ? "YES" : "NOT", pHdr->jtagEn); fprintf(stdout, "[0533:0533]Reserved: 0x%02X\n", @@ -254,21 +257,25 @@ int parse_sec_header(pSecExtBHR_T pHdr) pHdr->rsrvd3); fprintf(stdout, "[0539:0536]Box ID: 0x%08X\n", pHdr->boxId); - fprintf(stdout, "[0541:0540]Flash ID: 0x%04X\n", + fprintf(stdout, "[0543:0540]Flash ID: 0x%08X\n", pHdr->flashId); - fprintf(stdout, "[0543:0542]Reserved: 0x%04X\n", - pHdr->rsrvd4); fprintf(stdout, "[0799:0544]Header signature: %02X %02X %02X %02X ...\n", pHdr->hdrSign[0], pHdr->hdrSign[1], pHdr->hdrSign[2], pHdr->hdrSign[3]); fprintf(stdout, "[1055:0800]Image signature: %02X %02X %02X %02X ...\n", pHdr->imgSign[0], pHdr->imgSign[1], pHdr->imgSign[2], pHdr->imgSign[3]); - fprintf(stdout, "[1057:1056]More headers follow: %s\n", - pHdr->tail.nextHdr != 0 ? "YES" : "NOT"); - fprintf(stdout, "[1058:1058]Reserved: 0x%02X\n", - pHdr->tail.delay); - fprintf(stdout, "[1060:1059]Reserved: 0x%04X\n", - pHdr->tail.rsvd2); - + for(cskKey = 0; cskKey < CSK_KEY_NUM; cskKey++) { + fprintf(stdout, "[%d:%d]CSK Key[%d]: %s%02X %02X %02X %02X ...\n", + (1056 + 524*(cskKey+1) - 1), (1056 + 524*cskKey), cskKey, cskKey > 9 ? "" :" ", ((pHdr->cskArray[cskKey]).Key)[0], + ((pHdr->cskArray[cskKey]).Key)[1], ((pHdr->cskArray[cskKey]).Key)[2], ((pHdr->cskArray[cskKey]).Key)[3]); + } + fprintf(stdout, "[9695:9440]CSK signature: %02X %02X %02X %02X ...\n", + pHdr->cskBlockSign[0], pHdr->cskBlockSign[1], pHdr->cskBlockSign[2], pHdr->cskBlockSign[3]); + fprintf(stdout, "[9696]More headers follow: %s\n", + pHdr->tail.nextHdr != 0 ? "YES" : "NOT"); + fprintf(stdout, "[9697]Reserved: 0x%02X\n", + pHdr->tail.delay); + fprintf(stdout, "[9699:9698]Reserved: 0x%04X\n", + pHdr->tail.rsvd2); return 0; } @@ -277,9 +284,9 @@ int parse_sec_header(pSecExtBHR_T pHdr) *******************************************************************************/ int parse_bin_header(headExtBHR_t *pHdr) { - tailExtBHR_t *pTail = (tailExtBHR_t*)((MV_U8*)pHdr + + tailExtBHR_t *pTail = (tailExtBHR_t *)((MV_U8 *)pHdr + EXT_HDR_GET_LEN(pHdr) - sizeof(tailExtBHR_t)); - MV_U8 *buf = (MV_U8*)(pHdr+1); + MV_U8 *buf = (MV_U8 *)(pHdr + 1); int code_bytes = (EXT_HDR_GET_LEN(pHdr) - EXT_HDR_BASE_SIZE - (*buf + 1)*4); fprintf(stdout, "-----------------------------------------------------\n"); @@ -293,9 +300,9 @@ int parse_bin_header(headExtBHR_t *pHdr) fprintf(stdout, "[0004:0004]Number of parameters: %d (0x%06X)\n", *buf, *buf); fprintf(stdout, "[0005:0005]Reserved: 0x%02X\n", - *(buf + 1), *(buf + 1)); + *(buf + 1)); fprintf(stdout, "[0007:0005]Reserved: 0x%04X\n", - *(MV_U16*)(buf + 2), *(MV_U16*)(buf + 2)); + *(MV_U16 *)(buf + 2)); if (*buf != 0) fprintf(stdout, "[%04d:0008]Parameters\n", (7 + (*buf)*4)); fprintf(stdout, "[%04d:%04d]ARM Code link offset: %p\n", @@ -315,19 +322,19 @@ int parse_bin_header(headExtBHR_t *pHdr) *******************************************************************************/ int parse_reg_header(headExtBHR_t *pHdr) { - tailExtBHR_t *pTail = (tailExtBHR_t*)((MV_U8*)pHdr + + tailExtBHR_t *pTail = (tailExtBHR_t *)((MV_U8 *)pHdr + EXT_HDR_GET_LEN(pHdr) - sizeof(tailExtBHR_t)); int num_elem = (EXT_HDR_GET_LEN(pHdr) - EXT_HDR_BASE_SIZE)/8; fprintf(stdout, "-----------------------------------------------------\n"); - fprintf(stdout, " REGISTER HEADER @ %p\n", (void*)((char*)pHdr - buf_in)); + fprintf(stdout, " REGISTER HEADER @ %p\n", (void *)((char *)pHdr - buf_in)); fprintf(stdout, "-----------------------------------------------------\n"); fprintf(stdout, "[0000:0000]Header type: 0x%02X\n", pHdr->type); fprintf(stdout, "[0003:0001]Header length: %d (0x%06X)\n", EXT_HDR_GET_LEN(pHdr), EXT_HDR_GET_LEN(pHdr)); fprintf(stdout, "[%04d:0004]Num of ADDR-VAL pairs: %d (0x%02X)\n", - (num_elem*8 + 3), num_elem, num_elem); + (num_elem * 8 + 3), num_elem, num_elem); num_elem = num_elem * 8 + 4; fprintf(stdout, "[%04d:%04d]More headers follow: %s\n", num_elem, num_elem, pTail->nextHdr != 0 ? "YES" : "NOT"); @@ -356,12 +363,13 @@ int verify_rsa_signature (secCtx_t *pSecCtx, MV_U8 *start, MV_U32 len, MV_U8 *si /******************************************************************************* * verify_sec_header - check the secure header fields *******************************************************************************/ -int verify_sec_header (BHR_t *pHdr) +int verify_sec_header (BHR_t *pHdr, int csk_idx) { MV_U32 rsaKeyLen = 0; - int rsaModLen, rsaExpLen; + int rsaModLen, rsaExpLen; secExtBHR_t *pSecHdr = (secExtBHR_t *)(pHdr + 1); secCtx_t secCtx; + secCtx_t secCtxCSK; unsigned char buf256[256]; unsigned char buf32[32]; int i; @@ -373,30 +381,30 @@ int verify_sec_header (BHR_t *pHdr) memset(buf32, 0, 32 * sizeof(unsigned char)); /* RSA public key should be in DER format with 2-bytes length field */ - if ((pSecHdr->pubKey[0] != 0x30) || - (pSecHdr->pubKey[1] != 0x82)) { - fprintf(stderr,"\nError: Bad RSA key!\n"); + if ((((pSecHdr->pubKey).Key)[0] != 0x30) || + (((pSecHdr->pubKey).Key)[1] != 0x82)) { + fprintf(stderr,"\nError: Bad RSA key (KAK)!\n"); return -1; } /* DER format fields verification */ - rsaModLen = (pSecHdr->pubKey[6] << 8) + pSecHdr->pubKey[7]; + rsaModLen = (((pSecHdr->pubKey).Key)[6] << 8) + ((pSecHdr->pubKey).Key)[7]; if (rsaModLen > RSA_MAX_KEY_LEN_BYTES) { - fprintf(stderr,"\nError: Bad RSA key Modulo length (%d)!\n", rsaModLen); + fprintf(stderr,"\nError: Bad RSA key Modulo length (%d) - KAK!\n", rsaModLen); return -1; } - rsaExpLen = (pSecHdr->pubKey[10 + rsaModLen] << 8) + - pSecHdr->pubKey[11 + rsaModLen]; + rsaExpLen = (((pSecHdr->pubKey).Key)[10 + rsaModLen] << 8) + + ((pSecHdr->pubKey).Key)[11 + rsaModLen]; if (rsaExpLen > RSA_MAX_KEY_LEN_BYTES) { - fprintf(stderr,"\nError: Bad RSA key Exponent length (%d)!\n", rsaExpLen); + fprintf(stderr,"\nError: Bad RSA key Exponent length (%d) - KAK!\n", rsaExpLen); return -1; } /* Load the RSA public key */ rsa_init(&secCtx.rsa, RSA_PKCS_V15, 0, NULL, NULL); - if ((0 != mpi_read_binary(&secCtx.rsa.N, &pSecHdr->pubKey[8], rsaModLen)) || - (0 != mpi_read_binary(&secCtx.rsa.E, &pSecHdr->pubKey[12 + rsaModLen], rsaExpLen))) { + if ((0 != mpi_read_binary(&secCtx.rsa.N, &((pSecHdr->pubKey).Key)[8], rsaModLen)) || + (0 != mpi_read_binary(&secCtx.rsa.E, &((pSecHdr->pubKey).Key)[12 + rsaModLen], rsaExpLen))) { fprintf(stderr,"\nError: RSA Library error!\n"); return -1; } @@ -404,9 +412,10 @@ int verify_sec_header (BHR_t *pHdr) secCtx.rsa.len = (mpi_msb(&secCtx.rsa.N) + 7) >> 3; /* key lenght in bytes */ /* Key length should include 4 bytes of the data block header */ - rsaKeyLen = (pSecHdr->pubKey[2] << 8) + pSecHdr->pubKey[3] + 4; - sha2((unsigned char *)pSecHdr->pubKey, rsaKeyLen, buf32, 0); - fprintf(stdout,"RSA key SHA256 digest for eFuse:\n BE FULL: "); + rsaKeyLen = (((pSecHdr->pubKey).Key)[2] << 8) + ((pSecHdr->pubKey).Key)[3] + 4; + sha2((unsigned char *)((pSecHdr->pubKey).Key), rsaKeyLen, buf32, 0); + fprintf(stdout, "----------------------------------------------------------\n"); + fprintf(stdout,"RSA key SHA256 digest for eFuse (KAK):\n BE FULL: "); for (i = 0; i < 32; i++) { fprintf(stdout,"%02x ", buf32[i]); if (i == 15) @@ -419,24 +428,92 @@ int verify_sec_header (BHR_t *pHdr) fprintf(stdout,"\n "); } fprintf(stdout,"\n"); + fprintf(stdout, "----------------------------------------------------------\n"); + + memset(buf32, 0, 32 * sizeof(unsigned char)); + /* CSK array signature should be cleared in the header before verification */ + memcpy(buf256, pSecHdr->cskBlockSign, 256); + memset(pSecHdr->cskBlockSign, 0, 256); + + /* Verify the CSK array signature */ + fprintf(stdout,"CSK array RSA signature verification - "); + if (verify_rsa_signature(&secCtx, (MV_U8 *)pHdr + sizeof(BHR_t) + CSK_BLOCK_OFFSET, CSK_BLOCK_SIZE, buf256) != 0) { + fprintf(stderr,"FAILED\n"); + return -1; + } + fprintf(stdout,"PASSED\n"); + +//// Work with CSK + memcpy(pSecHdr->cskBlockSign, buf256, 256); /* Restore CSK array signature */ + memset(buf256, 0, 256 * sizeof(unsigned char)); memset(buf32, 0, 32 * sizeof(unsigned char)); + /* RSA public key should be in DER format with 2-bytes length field */ + if ((((pSecHdr->cskArray[csk_idx]).Key)[0] != 0x30) || + (((pSecHdr->cskArray[csk_idx]).Key)[1] != 0x82)) { + fprintf(stderr,"\nError: Bad RSA key (CSK-%d)!\n", csk_idx); + return -1; + } + + /* DER format fields verification */ + rsaModLen = (((pSecHdr->cskArray[csk_idx]).Key)[6] << 8) + ((pSecHdr->cskArray[csk_idx]).Key)[7]; + if (rsaModLen > RSA_MAX_KEY_LEN_BYTES) { + fprintf(stderr,"\nError: Bad RSA key Modulo length (%d) - CSK-%d!\n", rsaModLen, csk_idx); + return -1; + } + + rsaExpLen = (((pSecHdr->cskArray[csk_idx]).Key)[10 + rsaModLen] << 8) + + ((pSecHdr->cskArray[csk_idx]).Key)[11 + rsaModLen]; + if (rsaExpLen > RSA_MAX_KEY_LEN_BYTES) { + fprintf(stderr,"\nError: Bad RSA key Exponent length (%d) - CSK-%d!\n", rsaExpLen, csk_idx); + return -1; + } + + /* Load the RSA public key */ + rsa_init(&secCtx.rsa, RSA_PKCS_V15, 0, NULL, NULL); + if ((0 != mpi_read_binary(&secCtx.rsa.N, &((pSecHdr->cskArray[csk_idx]).Key)[8], rsaModLen)) || + (0 != mpi_read_binary(&secCtx.rsa.E, &((pSecHdr->cskArray[csk_idx]).Key)[12 + rsaModLen], rsaExpLen))) { + fprintf(stderr,"\nError: RSA Library error!\n"); + return -1; + } + + secCtx.rsa.len = (mpi_msb(&secCtx.rsa.N) + 7) >> 3; /* key length in bytes */ + + /* Key length should include 4 bytes of the data block header */ + rsaKeyLen = (((pSecHdr->cskArray[csk_idx]).Key)[csk_idx] << 8) + ((pSecHdr->cskArray[csk_idx]).Key)[3] + 4; + sha2((unsigned char *)((pSecHdr->cskArray[csk_idx]).Key), rsaKeyLen, buf32, 0); + fprintf(stdout, "----------------------------------------------------------\n"); + fprintf(stdout,"RSA key SHA256 digest for eFuse (CSK-%d):\n BE FULL: ", csk_idx); + for (i = 0; i < 32; i++) { + fprintf(stdout,"%02x ", buf32[i]); + if (i == 15) + fprintf(stdout,"\n "); + } + fprintf(stdout,"\n LE REGS: "); + for (i = 0; i < 8; i++) { + fprintf(stdout,"[%d]%08x ", i, *(MV_U32*)(buf32 + i*4)); + if (i == 3) + fprintf(stdout,"\n "); + } + fprintf(stdout,"\n"); + fprintf(stdout, "----------------------------------------------------------\n"); + /* Header signature should be cleared in the header before verification */ memcpy(buf256, pSecHdr->hdrSign, 256); memset(pSecHdr->hdrSign, 0, 256); - /* Verify the headers block signature */ - fprintf(stdout,"Header RSA signature verification - "); + /* Verify the header block signature using CSK array key entry */ + fprintf(stdout,"Headers block RSA signature verification - "); if (verify_rsa_signature(&secCtx, (MV_U8 *)pHdr, MAIN_HDR_GET_LEN(pHdr), buf256) != 0) { fprintf(stderr,"FAILED\n"); return -1; } fprintf(stdout,"PASSED\n"); - fprintf(stdout,"Image RSA signature verification - "); - if (verify_rsa_signature(&secCtx, buf_in + pHdr->sourceAddr, - pHdr->blockSize - 4, pSecHdr->imgSign) != 0) { + /* Verify image using CSK array key entry */ + fprintf(stdout,"Boot image RSA signature verification - "); + if (verify_rsa_signature(&secCtx, buf_in + pHdr->sourceAddr, pHdr->blockSize - 4, pSecHdr->imgSign) != 0) { fprintf(stderr,"FAILED\n"); return -1; } @@ -448,30 +525,34 @@ int verify_sec_header (BHR_t *pHdr) /******************************************************************************* * main *******************************************************************************/ -int main (int argc, char** argv) +int main(int argc, char **argv) { - int i, rsa_verify = 0; + int i, csk_idx=-1, rsa_verify = 0; char *fname; - int fin; + int fin; struct stat fs_stat; - int error = 1; + int error = 1; - int optch; /* command-line option char */ - static char optstring[] = "t"; + int optch; /* command-line option char */ + static char optstring[] = "tk:"; pBHR_t pHdr = NULL; MV_U32 chksum, chksum2; while ((optch = getopt(argc, argv, optstring)) != -1) { - char *endptr = NULL; + char *endptr = NULL; switch (optch) { - case 't': /* test */ - rsa_verify = 1; - break; + case 't': /* test */ + rsa_verify = 1; + break; + + case 'k': /* CSK index */ + csk_idx = strtoul(optarg, &endptr, 10); + break; - default: - print_usage(argv[0]); - exit(EXIT_FAILURE); + default: + print_usage(argv[0]); + exit(EXIT_FAILURE); } } /* parse command-line options */ @@ -481,23 +562,23 @@ int main (int argc, char** argv) } if ((fin = open(fname, O_RDONLY)) < 0) { - fprintf(stderr,"Error opening %s file\n", fname); + fprintf(stderr,"\nError: Failed to open %s file\n", fname); goto end; } if (0 != fstat(fin, &fs_stat)) { - fprintf(stderr,"Failed to get %s status\n", fname); + fprintf(stderr,"\n Error: Failed to get %s status\n", fname); goto end; } buf_in = (char*)malloc(fs_stat.st_size); if (buf_in == NULL) { - fprintf(stderr,"Error allocting buffer for %s file\n", fname); + fprintf(stderr,"\nError: Failed to allocate buffer for %s file\n", fname); goto end; } if (read(fin, buf_in, fs_stat.st_size) != fs_stat.st_size) { - fprintf(stderr,"Error reading %s file\n", fname); + fprintf(stderr,"\nError: Failed to read %s file\n", fname); goto end; } @@ -534,7 +615,7 @@ int main (int argc, char** argv) goto end; break; default: - fprintf(stderr,"Unknown header type 0x%x\n", pHead->type); + fprintf(stderr,"\nError: Unknown header type 0x%x\n", pHead->type); goto end; } @@ -549,22 +630,26 @@ int main (int argc, char** argv) fprintf(stdout, "-----------------------------------------------------\n"); fprintf(stdout, " BOOT IMAGE @ %p\n", pHdr->blockID == IBR_HDR_SATA_ID ? - (void*)((char*)pHdr - buf_in + pHdr->sourceAddr * 512) : - (void*)((char*)pHdr - buf_in + pHdr->sourceAddr)); + (void *)((char *)pHdr - buf_in + pHdr->sourceAddr * 512) : + (void *)((char *)pHdr - buf_in + pHdr->sourceAddr)); fprintf(stdout, "-----------------------------------------------------\n"); chksum = *(MV_U32*)(buf_in + fs_stat.st_size - 4); if (pHdr->blockID == IBR_HDR_SATA_ID) - chksum2 = checksum32((void *)(buf_in + pHdr->sourceAddr * 512), pHdr->blockSize - 4, 0); + chksum2 = checksum32((void *)(buf_in + pHdr->sourceAddr * 512), pHdr->blockSize - 4, 0); else - chksum2 = checksum32((void *)(buf_in + pHdr->sourceAddr), pHdr->blockSize - 4, 0); + chksum2 = checksum32((void *)(buf_in + pHdr->sourceAddr), pHdr->blockSize - 4, 0); - fprintf(stdout, "Binary image checksum = 0x%08X (%s)\n", chksum, - chksum == chksum2 ? "GOOD" : "BAD"); + fprintf(stdout, "Binary image checksum = 0x%08X (%s)\n", chksum, chksum == chksum2 ? "GOOD" : "BAD"); - if (rsa_verify != 0) - error = verify_sec_header(pHdr); - else + if (rsa_verify != 0) { + if ((csk_idx < 0) || (csk_idx > 15)) { + fprintf(stderr,"\nError: Bad CSK array index (%d). 0 < idx < 15!\n", csk_idx); + error = 1; + goto end; + } + error = verify_sec_header(pHdr, csk_idx); + } else error = 0; end: