Secure Binary 2.1

Version 2.1 added support for digital signatures.

The SB 2.0 and 2.1 file format also uses AES encryption for confidentiality and HMAC for extending trust from the signed part of the SB file to the command and data part of the SB file. These two keys (AES decrypt key and HMAC key) are wrapped in the RFC3394 key blob, for which the key wrapping key is the SBKEK key

SB2 generation using BD file

The tool uses an input command file to control the sequence of bootloader commands present in the output file. This command file is called a “boot descriptor file” or BD file for short. The image location is stated in the “sources” section of the .bd file. The SB key in the text file is used for encryption with the nxpimage command line tool.

It is possible to use NXP elftosb tool user guide located here.

Note

Please note that some functionality described in the UG may not be supported in SPSDK SB2 parser.

For more information about the Secure boot setup for LPC55Sxx family follow the AN12283.

Supported Commands

Supported commands for SB2.1

Command

Description

Example

load

The load statement is used to store data into the memory. The load command is also used to write to the flash memory. When loading to the flash memory, the region being loaded to must be erased before to the load operation. The most common form of a load statement is loading a source file by name.

Example:
section (0) {
// load an entire binary file to an address
load myBinFile > 0x70000000;
// load an eight byte blob
load {{ ff 2e 90 07 77 5f 1d 20 }} > 0xa0000000;
// 4 byte load IFR statement
load ifr 0x1234567 > 0x30;
// Program fuse statement
load fuse {{00 00 00 01}} > 0x01000188;
// load to sdcard
load sdcard {{aa bb cc dd}} > 0x08000188;
load @288 {{aa bb cc dd}} > 0x08000188;
}

fill

Fill is a type of load command used for filling a region of memory with pattern.

Example:
section(0) {
// pattern fill
load 0x55.b > 0x2000..0x3000;
// load two bytes at an address
load 0x1122.h > 0xf00;
}

erase

The erase statement inserts a bootloader command to erase the flash memory. There are two forms of the erase statement. The simplest form (erase all) creates a command that erases the available flash memory. The actual effect of this command depends on the runtime settings of the bootloader and whether the bootloader resides in the flash, ROM, or RAM.

Example:
section (0){
// Erase all
erase all;
// Erase unsecure all
erase unsecure all;
// erase statements specifying memory ID and range
erase @8 all;
erase @288 0x8001000..0x80074A4;
erase sdcard 0x8001000..0x80074A4;
erase mmccard 0x8001000..0x80074A4;
}

enable

Enable statement is used for initialization of external memories using a parameter block that was previously loaded to RAM.

Example:
section (0){
# Load quadspi config block bin file to RAM, use it to enable QSPI.
load myBinFile > 0x20001000;
enable qspi 0x20001000;
}

encrypt

Encrypt holds an ID, which is a reference to keyblob to be used for encryption. So the encrypt command requires a list of keyblobs, the keyblob ID and load command.

e.g.
encrypt (0){
load myImage > 0x0810000;
}

keywrap

Keywrap holds keyblob ID to be encoded by a value stored in load command and stored to address defined in the load command.

Example:
keywrap (0) {
load {{ 00000000 }} > 0x08000000;
}

keystore_to_nv

The keystore_to_nv statement instructs the bootloader to load the backed up keystore values back into keystore memory region on non-volatile memory.

Example:
section (0) {
keystore_to_nv @9 0x8000800;

keystore_from_nv

The keystore_to_nv statement instructs the bootloader to load the backed up keystore values back into keystore memory region on non-volatile memory.

Example:
section (0) {
keystore_to_nv @9 0x8000800;

version_check

Validates version of secure or non-secure firmware. The command fails if version is < expected.

Example:
section (0) {
version_check sec 0x2;
version_check nsec 2;
}

jump

The “jump” command produces the ROM_JUMP_CMD. See the boot image format design document for specific details about these commands, such as the function prototypes they expect.

Example:
section (0) {
# jump to the entrypoint
jump mySRecFile;
# jump to a fixed address
jump 0xffff0000;
}

Example of SB2 generation for 4 root keys

nxpimage: nxpimage sb21 export -k "sbkek.txt" -c "commandFile.bd" -o "output.sb2" -s private_key_1_2048.pem -S certificate_1_2048.der.crt -R certificate_1_2048.der.crt -R certificate_2_2048.der.crt -R certificate_3_2048.der.crt -R certificate_4_2048.der.crt -h "RHKT.bin" "input.bin"

Created SB2 file can be loaded into the device using blhost receive-sb-file command. blhost -p COMxx receive-sb-file <path to the secured binary(.sb2)>

Description of how to use BD file is in bellow chapter.

Parser grammar

This is a user guide describing how to generate a secure binary rev. 2.1 based on a configuration file (a so called BD file or command file) and additional inputs like certificates, keys, binary files etc.

Supported Syntax

The syntax is written in EBNF (Extended Backus Naur Form), however, the elftosb application uses (namely SLY - python implementation of Lex/Yacc) only BNF. From this perspective the graphs visualize the EBNF form with the grammar and the conversion into BNF as well as remarks what is supported.

command_file:

         ::= pre_section_block* section_block*
         ::= pre_section_block section_block

no references

Comments:

The options block, constants block, sources block and keyblob block must be defined prior to the section block. There may be multiple blocks in any order, but all must precede the section blocks.

# options, sources, keyblob & constants must precede section block, but there may be
# multiple definitions in any order
options {

}

sources {

}

keyblob (0) {

}

constants {

}

options {

}

# Section blocks must be the very last blocks defined
section (1) {

}

section (2) {

}

pre_section_block:

         ::= options_block
           | constants_block
           | sources_block
           | keyblob_block
         ::= pre_section_block options_block
           | pre_section_block constants_block
           | pre_section_block sources_block
           | pre_section_block keyblob_block
           | empty

referenced by:


options_block:

         ::= OPTIONS '{' option_def* '}'
         ::= OPTIONS '{' option_def '}'

referenced by:


Comments:

Example:

options {
    opt1 = "some_string";
    opt2 = 1234;
    opt3 = 1 > 3;
    ...
}

option_def:

EBNF: option_def
         ::= IDENT '=' const_expr ';'
BNF: option_def
         ::= option_def IDENT '=' const_expr ';'
           | empty

referenced by:


constants_block:

         ::= CONSTANTS '{' constant_def* '}'
         ::= CONSTANTS '{' constant_def '}'

referenced by:


Comments: Only numbers can be assigned to identifiers in the constants block.

constant_def:

EBNF: constant_def
         ::= IDENT '=' bool_expr ';'
         ::= constant_def IDENT '=' bool_expr ';'
          | empty

referenced by:


sources_block:

         ::= SOURCES '{' source_def* '}'
         ::= SOURCES '{' source_def '}'

referenced by:


source_def:

EBNF: source_def
         ::= IDENT '=' source_value ( '(' option_list? ')' )? ';'
BNF: source_def
         ::= source_def IDENT '=' source_value ';'
           | source_def IDENT '=' source_value '(' option_list ')' ';'
           | empty

referenced by:


Comments:

option_list in source_def is not supported and raises syntax error when used! According to the grammar, identifiers defined in source block are referenced in the grammar as source_name, however, the grammar can’t be defined using this type of token, as there is no rule to distinguish between an identifier token and a source name token. So the grammar uses the IDENT token instead and documents this fact in description, that it’s a source_name identifier.

source_value:

EBNF: source_value
         ::= STRING_LITERAL
           | EXTERN '(' int_const_expr ')'
         ::= STRING_LITERAL
           | EXTERN '(' int_const_expr ')'

referenced by:


Comments:

The EXTERN keyword references source files defined on the command line as the very last arguments indexed from 0. In the example below, extern(1) would reference the “./file2” file provided on command line.

Command file example:

sources {
    my_binary_file = extern(1); # my_binary_file = file2.bin
}

Command line usage:

elf2sb -c.. -o.. "some/path/to/file1.bin" "./file2.bin"

option_list:

EBNF: option_list
         ::= IDENT '=' const_expr ( ',' IDENT '=' const_expr )*
         ::= IDENT '=' const_expr ',' option_list
         | IDENT '=' const_expr

referenced by:


keyblob_block:

         ::= KEYBLOB '(' int_const_expr ')' '{' keyblob_contents* '}'
         ::= KEYBLOB '(' int_const_expr ')' '{' keyblob_contents '}'

referenced by:


Comments:

The keyblob block grammar has been modified and it supports only single keyblob_contents definition, which must not be empty!

Example

keyblob (1) {
    (
        start = 0x0800000,
        end = 0x08001000,
        key = "12345678901234567890123456789012",
        counter = "1122334455667788",
        byteSwap = False
    )
    # No further definitions allowed, if present, syntax error will be raised!
}

keyblob_contents:

         ::= '(' option_list* ')'
         ::= keyblob_contents '(' option_list ')'
         | empty

referenced by:


Comments:

The keyblob contents must define:

start [integer] - start address 'maintained' by this keyblob
end [integer] - end address 'maintained' by this keyblob
key [string] - key used to encode data stored into address range defined by this keyblob
counter [string] - TODO
byteSwap [boolean, optional] - TODO

Anything else defined under keyblob is ignored. If definition of keywords listed above, except ‘byteSwap’ is missing, a syntax error will be raised.

section_block:

         | empty

referenced by:


Comments:

section_options is not supported and raises syntax error when used!

section_options:

         ::= ';' option_list?
         ::= ';' option_list
         | ';'
         | empty

referenced by:


section_contents:

         ::= '{' statement* '}'
           | '<=' IDENT ';'
         ::= '{' statement '}'
           | '<=' IDENT ';'

referenced by:


Comments:

<= IDENT is not supported and raises syntax error when used!

The IDENT in <= IDENT must be an identifier defined in the sources block, otherwise an error is raised.

statement:

EBNF: statement
         ::= basic_stmt ';'
           | from_stmt
           | if_stmt
BNF: statement
         ::= statement basic_stmt ';'
           | statement from_stmt
           | statement if_stmt
           | empty

referenced by:


basic_stmt:

EBNF: basic_stmt
         ::= load_stmt
           | load_ifr_stmt
           | call_stmt
           | jump_sp_stmt
           | mode_stmt
           | message_stmt
           | erase_stmt
           | enable_stmt
           | reset_stmt
           | encrypt_stmt
BNF: basic_stmt
         ::= load_stmt
           | load_ifr_stmt
           | call_stmt
           | jump_sp_stmt
           | mode_stmt
           | message_stmt
           | erase_stmt
           | enable_stmt
           | reset_stmt
           | encrypt_stmt

referenced by:


load_stmt:

EBNF: load_stmt
         ::= LOAD load_data load_target
BNF: load_stmt
         ::= LOAD load_data load_target

referenced by:


load_data:

EBNF: load_data
         ::= int_const_expr
           | STRING_LITERAL
           | IDENT
           | section_list ( FROM IDENT )?
           | BINARY_BLOB
BNF: load_data
         ::= int_const_expr
           | STRING_LITERAL
           | IDENT
           | section_list
           | section_list FROM IDENT
           | BINARY_BLOB

referenced by:


load_target:

EBNF: load_target
         ::= '>' ( '.' | address_or_range )
         ::= '>' '.'
         | '>' address_or_range
         | '>' empty

referenced by:


section_list:

EBNF: section_list
         ::= section_ref ( ',' section_ref )*
         ::= section_list ',' section_ref
         | section_ref

referenced by:


section_ref:

EBNF: section_ref
         ::= '~'? SECTION_NAME
         ::= '~' SECTION_NAME
         | SECTION_NAME

referenced by:


erase_stmt:

EBNF: erase_stmt
         ::= ERASE ( address_or_range | ALL )
BNF: erase_stmt
         ::= ERASE address_or_range
         | ALL

referenced by:


address_or_range:

         ::= int_const_expr ( '..' int_const_expr )?
         ::= int_const_expr
         | int_const_expr '..' int_const_expr

referenced by:


symbol_ref:

EBNF: symbol_ref
         ::= IDENT '?' ':' IDENT
BNF: symbol_ref
         ::= IDENT '?' ':' IDENT

referenced by:


load_ifr_stmt:

         ::= LOAD IFR int_const_expr '>' int_const_expr
         ::= LOAD IFR int_const_expr '>' int_const_expr

referenced by:


call_stmt:

EBNF: call_stmt
         ::= call_type call_target call_arg?
BNF: call_stmt
         ::= call_type call_target call_arg

referenced by:


call_type:

EBNF: call_type
         ::= CALL
           | JUMP
BNF: call_type
         ::= CALL
           | JUMP

referenced by:


call_target:

EBNF: call_target
         ::= int_const_expr
           | symbol_ref
           | IDENT
         ::= int_const_expr
           | symbol_ref
           | IDENT

referenced by:


call_arg:

EBNF: call_arg ::= '(' int_const_expr? ')'
BNF: call_arg ::= '(' ')'
           | '(' int_const_expr ')'
           | empty

referenced by:


jump_sp_stmt:

EBNF: jump_sp_stmt
         ::= JUMP_SP int_const_expr call_target call_arg?

referenced by:


from_stmt:

EBNF: from_stmt
         ::= FROM IDENT '{' in_from_stmt* '}'
BNF: from_stmt
         ::= FROM IDENT '{' in_from_stmt '}'

referenced by:


in_from_stmt:

EBNF: in_from_stmt
         ::= basic_stmt ';'
           | if_stmt
         ::= in_from_stmt basic_stmt ';'
           | in_from_stmt if_stmt
           | empty

referenced by:


mode_stmt:

EBNF: mode_stmt
         ::= MODE int_const_expr
BNF: mode_stmt
         ::= MODE int_const_expr

referenced by:


message_stmt:

EBNF: message_stmt
         ::= message_type STRING_LITERAL
         ::= message_type STRING_LITERAL

referenced by:


message_type:

EBNF: message_type
         ::= INFO
           | WARNING
           | ERROR
         ::= INFO
           | WARNING
           | ERROR

no references


if_stmt:

EBNF: if_stmt   ::= IF bool_expr '{' statement* '}' else_stmt?
BNF: if_stmt   ::= IF bool_expr '{' statement '}' else_stmt

referenced by:


else_stmt:

EBNF: else_stmt
         ::= ELSE ( '(' statement* ')' | if_stmt )
BNF: else_stmt
         ::= ELSE '(' statement ')'
         | ELSE if_stmt
         | empty

referenced by:


encrypt_stmt:

EBNF: encrypt_stmt
         ::= ENCRYPT '(' int_const_expr ')' '{' statement* '}'
         ::= ENCRYPT '(' int_const_expr ')' '{' statement '}'

referenced by:


enable_stmt:

EBNF: enable_stmt
         ::= ENABLE AT_INT_LITERAL int_const_expr
         ::= ENABLE AT_INT_LITERAL int_const_expr

referenced by:


reset_stmt:

EBNF: reset_stmt
         ::= RESET
BNF: reset_stmt
         ::= RESET

referenced by:


const_expr:

EBNF: const_expr
         ::= STRING_LITERAL
           | bool_expr
BNF: const_expr
         ::= STRING_LITERAL
           | bool_expr

referenced by:


int_const_expr:

         ::= expr
         ::= expr

referenced by:


bool_expr:

EBNF: bool_expr
         ::= ( bool_expr ( '<' | '<=' | '>' | '>=' | '==' | '!=' | '&&' | '||' ) | '!' ) bool_expr
           | ( '(' bool_expr | DEFINED '(' IDENT | IDENT '(' source_name ) ')'
           | int_const_expr
BNF: bool_expr
         ::= bool_expr'<' bool_expr
         | bool_expr'<=' bool_expr
         | bool_expr'>' bool_expr
         | bool_expr'>=' bool_expr
         | bool_expr'==' bool_expr
         | bool_expr'!=' bool_expr
         | bool_expr'&&' bool_expr
         | bool_expr'||' bool_expr
         | '(' bool_expr ')'
         | int_const_expr
         | '!' bool_expr
         | DEFINED '(' IDENT ')'
         | IDENT '(' IDENT ')'

referenced by:


expr:

EBNF: expr
           ::= expr ( ( '+' | '-' | '*' | '/' | '%' | '<<' | '>>' | '&' | '|' | '^' ) expr | '.' INT_SIZE )
           | ( '(' expr | SIZEOF '(' ( SYMBOL_REF | IDENT ) ) ')'
           | INT_LITERAL
           | IDENT
           | SYMBOL_REF
           | unary_expr
BNF: expr
     ::= expr '+' expr
     | expr '-' expr
     | expr '*' expr
     | expr '/' expr
     | expr '%' expr
     | expr '<<' expr
     | expr '>>' expr
     | expr '&' expr
     | expr '|' expr
     | expr '^' expr
     | expr '.' INT_SIZE
     | '(' expr ')'
     | INT_LITERAL
     | IDENT
     | SYMBOL_REF
     | unary_expr
     | SIZEOF '(' SYMBOL_REF ')'
     | SIZEOF '(' IDENT ')'

referenced by:


unary_expr:

EBNF: unary_expr
         ::= ( '+' | '-' ) expr
BNF: unary_expr
         ::= '+' expr
         | '-' expr

referenced by:



  ... generated by RR - Railroad Diagram Generator