Home | History | Annotate | Download | only in doc
      1 The trusted boot framework on Marvell Armada 38x
      2 ================================================
      3 
      4 Contents:
      5 
      6 1. Overview of the trusted boot
      7 2. Terminology
      8 3. Boot image layout
      9 4. The secured header
     10 5. The secured boot flow
     11 6. Usage example
     12 7. Work to be done
     13 8. Bibliography
     14 
     15 1. Overview of the trusted boot
     16 -------------------------------
     17 
     18 The Armada's trusted boot framework enables the SoC to cryptographically verify
     19 a specially prepared boot image. This can be used to establish a chain of trust
     20 from the boot firmware all the way to the OS.
     21 
     22 To achieve this, the Armada SoC requires a specially prepared boot image, which
     23 contains the relevant cryptographic data, as well as other information
     24 pertaining to the boot process. Furthermore, a eFuse structure (a
     25 one-time-writeable memory) need to be configured in the correct way.
     26 
     27 Roughly, the secure boot process works as follows:
     28 
     29 * Load the header block of the boot image, extract a special "root" public RSA
     30   key from it, and verify its SHA-256 hash against a SHA-256 stored in a eFuse
     31   field.
     32 * Load an array of code signing public RSA keys from the header block, and
     33   verify its RSA signature (contained in the header block as well) using the
     34   "root" RSA key.
     35 * Choose a code signing key, and use it to verify the header block (excluding
     36   the key array).
     37 * Verify the binary image's signature (contained in the header block) using the
     38   code signing key.
     39 * If all checks pass successfully, boot the image.
     40 
     41 The chain of trust is thus as follows:
     42 
     43 * The SHA-256 value in the eFuse field verifies the "root" public key.
     44 * The "root" public key verifies the code signing key array.
     45 * The selected code signing key verifies the header block and the binary image.
     46 
     47 In the special case of building a boot image containing U-Boot as the binary
     48 image, which employs this trusted boot framework, the following tasks need to
     49 be addressed:
     50 
     51 1. Creation of the needed cryptographic key material.
     52 2. Creation of a conforming boot image containing the U-Boot image as binary
     53    image.
     54 3. Burning the necessary eFuse values.
     55 
     56 (1) will be addressed later, (2) will be taken care of by U-Boot's build
     57 system (some user configuration is required, though), and for (3) the necessary
     58 data (essentially a series of U-Boot commands to be entered at the U-Boot
     59 command prompt) will be created by the build system as well.
     60 
     61 The documentation of the trusted boot mode is contained in part 1, chapter
     62 7.2.5 in the functional specification [1], and in application note [2].
     63 
     64 2. Terminology
     65 --------------
     66 
     67 	           CSK - Code Signing Key(s): An array of RSA key pairs, which
     68                          are used to sign and verify the secured header and the
     69                          boot loader image.
     70 	           KAK - Key Authentication Key: A RSA key pair, which is used
     71                          to sign and verify the array of CSKs.
     72 	  Header block - The first part of the boot image, which contains the
     73 			 image's headers (also known as "headers block", "boot
     74 			 header", and "image header")
     75                  eFuse - A one-time-writeable memory.
     76                BootROM - The Armada's built-in boot firmware, which is
     77                          responsible for verifying and starting secure images.
     78 	    Boot image - The complete image the SoC's boot firmware loads
     79 			 (contains the header block and the binary image)
     80 	   Main header - The header in the header block containing information
     81 			 and data pertaining to the boot process (used for both
     82 			 the regular and secured boot processes)
     83 	  Binary image - The binary code payload of the boot image; in this
     84 			 case the U-Boot's code (also known as "source image",
     85 			 or just "image")
     86 	Secured header - The specialized header in the header block that
     87 			 contains information and data pertaining to the
     88 			 trusted boot (also known as "security header")
     89      Secured boot mode - A special boot mode of the Armada SoC in which secured
     90                          images are verified (non-secure images won't boot);
     91                          the mode is activated by setting a eFuse field.
     92     Trusted debug mode - A special mode for the trusted boot that allows
     93 			 debugging of devices employing the trusted boot
     94 			 framework in a secure manner (untested in the current
     95 			 implementation).
     96 Trusted boot framework - The ARMADA SoC's implementation of a secure verified
     97                          boot process.
     98 
     99 3. Boot image layout
    100 --------------------
    101 
    102 +-- Boot image --------------------------------------------+
    103 |                                                          |
    104 | +-- Header block --------------------------------------+ |
    105 | | Main header                                          | |
    106 | +------------------------------------------------------+ |
    107 | | Secured header                                       | |
    108 | +------------------------------------------------------+ |
    109 | | BIN header(s)                                        | |
    110 | +------------------------------------------------------+ |
    111 | | REG header(s)                                        | |
    112 | +------------------------------------------------------+ |
    113 | | Padding                                              | |
    114 | +------------------------------------------------------+ |
    115 |                                                          |
    116 | +------------------------------------------------------+ |
    117 | | Binary image + checksum                              | |
    118 | +------------------------------------------------------+ |
    119 +----------------------------------------------------------+
    120 
    121 4. The secured header
    122 ---------------------
    123 
    124 For the trusted boot framework, a additional header is added to the boot image.
    125 The following data are relevant for the secure boot:
    126 
    127 		   KAK: The KAK is contained in the secured header in the form
    128 		        of a RSA-2048 public key in DER format with a length of
    129 			524 bytes.
    130 Header block signature: The RSA signature of the header block (excluding the
    131                         CSK array), created using the selected CSK.
    132 Binary image signature: The RSA signature of the binary image, created using
    133                         the selected CSK.
    134              CSK array: The array of the 16 CSKs as RSA-2048 public keys in DER
    135 	                format with a length of 8384 = 16 * 524 bytes.
    136    CSK block signature: The RSA signature of the CSK array, created using the
    137                         KAK.
    138 
    139 NOTE: The JTAG delay, Box ID, and Flash ID header fields do play a role in the
    140 trusted boot process to enable and configure secure debugging, but they were
    141 not tested in the current implementation of the trusted boot in U-Boot.
    142 
    143 5. The secured boot flow
    144 ------------------------
    145 
    146 The steps in the boot flow that are relevant for the trusted boot framework
    147 proceed as follows:
    148 
    149 1) Check if trusted boot is enabled, and perform regular boot if it is not.
    150 2) Load the secured header, and verify its checksum.
    151 3) Select the lowest valid CSK from CSK0 to CSK15.
    152 4) Verify the SHA-256 hash of the KAK embedded in the secured header.
    153 5) Verify the RSA signature of the CSK block from the secured header with the
    154    KAK.
    155 6) Verify the header block signature (which excludes the CSK block) from the
    156    secured header with the selected CSK.
    157 7) Load the binary image to the main memory and verify its checksum.
    158 8) Verify the binary image's RSA signature from the secured header with the
    159    selected CSK.
    160 9) Continue the boot process as in the case of the regular boot.
    161 
    162 NOTE: All RSA signatures are verified according to the PKCS #1 v2.1 standard
    163 described in [3].
    164 
    165 NOTE: The Box ID and Flash ID are checked after step 6, and the trusted debug
    166 mode may be entered there, but since this mode is untested in the current
    167 implementation, it is not described further.
    168 
    169 6. Usage example
    170 ----------------
    171 
    172 ### Create key material
    173 
    174 To employ the trusted boot framework, cryptographic key material needs to be
    175 created. In the current implementation, two keys are needed to build a valid
    176 secured boot image: The KAK private key and a CSK private key (both have to be
    177 2048 bit RSA keys in PEM format). Note that the usage of more than one CSK is
    178 currently not supported.
    179 
    180 NOTE: Since the public key can be generated from the private key, it is
    181 sufficient to store the private key for each key pair.
    182 
    183 OpenSSL can be used to generate the needed files kwb_kak.key and kwb_csk.key
    184 (the names of these files have to be configured, see the next section on
    185 kwbimage.cfg settings):
    186 
    187 openssl genrsa -out kwb_kak.key 2048
    188 openssl genrsa -out kwb_csk.key 2048
    189 
    190 The generated files have to be placed in the U-Boot root directory.
    191 
    192 Alternatively, instead of copying the files, symlinks to the private keys can
    193 be placed in the U-Boot root directory.
    194 
    195 WARNING: Knowledge of the KAK or CSK private key would enable an attacker to
    196 generate secured boot images containing arbitrary code. Hence, the private keys
    197 should be carefully guarded.
    198 
    199 ### Create/Modifiy kwbimage.cfg
    200 
    201 The Kirkwook architecture in U-Boot employs a special board-specific
    202 configuration file (kwbimage.cfg), which controls various boot image settings
    203 that are interpreted by the BootROM, such as the boot medium. The support the
    204 trusted boot framework, several new options were added to faciliate
    205 configuration of the secured boot.
    206 
    207 The configuration file's layout has been retained, only the following new
    208 options were added:
    209 
    210 		KAK - The name of the KAK RSA private key file in the U-Boot
    211                       root directory, without the trailing extension of ".key".
    212 		CSK - The name of the (active) CSK RSA private key file in the
    213 		      U-Boot root directory, without the trailing extension of
    214 		      ".key".
    215 	     BOX_ID - The BoxID to be used for trusted debugging (a integer
    216 	              value).
    217 	   FLASH_ID - The FlashID to be used for trusted debugging (a integer
    218 	              value).
    219 	 JTAG_DELAY - The JTAG delay to be used for trusted debugging (a
    220 	              integer value).
    221           CSK_INDEX - The index of the active CSK (a integer value).
    222 SEC_SPECIALIZED_IMG - Flag to indicate whether to include the BoxID and FlashID
    223 		      in the image (that is, whether to use the trusted debug
    224 		      mode or not); no parameters.
    225        SEC_BOOT_DEV - The boot device from which the trusted boot is allowed to
    226 		      proceed, identified via a numeric ID. The tested values
    227 		      are 0x34 = NOR flash, 0x31 = SDIO/MMC card; for
    228 		      additional ID values, consult the documentation in [1].
    229       SEC_FUSE_DUMP - Dump the "fuse prog" commands necessary for writing the
    230 		      correct eFuse values to a text file in the U-Boot root
    231 		      directory. The parameter is the architecture for which to
    232 		      dump the commands (currently only "a38x" is supported).
    233 
    234 The parameter values may be hardcoded into the file, but it is also possible to
    235 employ a dynamic approach of creating a Autoconf-like kwbimage.cfg.in, then
    236 reading configuration values from Kconfig options or from the board config
    237 file, and generating the actual kwbimage.cfg from this template using Makefile
    238 mechanisms (see board/gdsys/a38x/Makefile as an example for this approach).
    239 
    240 ### Set config options
    241 
    242 To enable the generation of trusted boot images, the corresponding support
    243 needs to be activated, and a index for the active CSK needs to be selected as
    244 well.
    245 
    246 Furthermore, eFuse writing support has to be activated in order to burn the
    247 eFuse structure's values (this option is just needed for programming the eFuse
    248 structure; production boot images may disable it).
    249 
    250 ARM architecture
    251  -> [*] Build image for trusted boot
    252     (0)   Index of active CSK
    253  -> [*] Enable eFuse support
    254     [ ]   Fake eFuse access (dry run)
    255 
    256 ### Build and test boot image
    257 
    258 The creation of the boot image is done via the usual invocation of make (with a
    259 suitably set CROSS_COMPILE environment variable, of course). The resulting boot
    260 image u-boot-spl.kwb can then be tested, if so desired. The hdrparser from [5]
    261 can be used for this purpose. To build the tool, invoke make in the
    262 'tools/marvell/doimage_mv' directory of [5], which builds a stand-alone
    263 hdrparser executable. A test can be conducted by calling hdrparser with the
    264 produced boot image and the following (mandatory) parameters:
    265 
    266 ./hdrparser -k 0 -t u-boot-spl.kwb
    267 
    268 Here we assume that the CSK index is 0 and the boot image file resides in the
    269 same directory (adapt accordingly if needed). The tool should report that all
    270 checksums are valid ("GOOD"), that all signature verifications succeed
    271 ("PASSED"), and, finally, that the overall test was successful
    272 ("T E S T   S U C C E E D E D" in the last line of output).
    273 
    274 ### Burn eFuse structure
    275 
    276 +----------------------------------------------------------+
    277 | WARNING: Burning the eFuse structure is a irreversible   |
    278 | operation! Should wrong or corrupted values be used, the |
    279 | board won't boot anymore, and recovery is likely         |
    280 | impossible!                                              |
    281 +----------------------------------------------------------+
    282 
    283 After the build process has finished, and the SEC_FUSE_DUMP option was set in
    284 the kwbimage.cfg was set, a text file kwb_fuses_a38x.txt should be present in
    285 the U-Boot top-level directory. It contains all the necessary commands to set
    286 the eFuse structure to the values needed for the used KAK digest, as well as
    287 the CSK index, Flash ID and Box ID that were selected in kwbimage.cfg.
    288 
    289 Sequentially executing the commands in this file at the U-Boot command prompt
    290 will write these values to the eFuse structure.
    291 
    292 If the SEC_FUSE_DUMP option was not set, the commands needed to burn the fuses
    293 have to be crafted by hand. The needed fuse lines can be looked up in [1]; a
    294 rough overview of the process is:
    295 
    296 * Burn the KAK public key hash. The hash itself can be found in the file
    297   pub_kak_hash.txt in the U-Boot top-level directory; be careful to account for
    298   the endianness!
    299 * Burn the CSK selection, BoxID, and FlashID
    300 * Enable trusted boot by burning the corresponding fuse (WARNING: this must be
    301   the last fuse line written!)
    302 * Lock the unused fuse lines
    303 
    304 The command to employ is the "fuse prog" command previously enabled by setting
    305 the corresponding configuration option.
    306 
    307 For the trusted boot, the fuse prog command has a special syntax, since the
    308 ARMADA SoC demands that whole fuse lines (64 bit values) have to be written as
    309 a whole. The fuse prog command itself allows lists of 32 bit words to be
    310 written at a time, but this is translated to a series of single 32 bit write
    311 operations to the fuse line, where the individual 32 bit words are identified
    312 by a "word" counter that is increased for each write.
    313 
    314 To work around this restriction, we interpret each line to have three "words"
    315 (0-2): The first and second words are the values to be written to the fuse
    316 line, and the third is a lock flag, which is supposed to lock the fuse line
    317 when set to 1. Writes to the first and second words are memoized between
    318 function calls, and the fuse line is only really written and locked (on writing
    319 the third word) if both words were previously set, so that "incomplete" writes
    320 are prevented. An exception to this is a single write to the third word (index
    321 2) without previously writing neither the first nor the second word, which
    322 locks the fuse line without setting any value; this is needed to lock the
    323 unused fuse lines.
    324 
    325 As an example, to write the value 0011223344556677 to fuse line 10, we would
    326 use the following command:
    327 
    328 fuse prog -y 10 0 00112233 44556677 1
    329 
    330 Here 10 is the fuse line number, 0 is the index of the first word to be
    331 written, 00112233 and 44556677 are the values to be written to the fuse line
    332 (first and second word) and the trailing 1 is the value for the third word
    333 responsible for locking the line.
    334 
    335 A "lock-only" command would look like this:
    336 
    337 fuse prog -y 11 2 1
    338 
    339 Here 11 is the fuse number, 2 is the index of the first word to be written
    340 (notice that we only write to word 2 here; the third word for fuse line
    341 locking), and the 1 is the value for the word we are writing to.
    342 
    343 WARNING: According to application note [4], the VHV pin of the SoC must be
    344 connected to a 1.8V source during eFuse programming, but *must* be disconnected
    345 for normal operation. The AN [4] describes a software-controlled circuit (based
    346 on a N-channel or P-channel FET and a free GPIO pin of the SoC) to achieve
    347 this, but a jumper-based circuit should suffice as well. Regardless of the
    348 chosen circuit, the issue needs to be addressed accordingly!
    349 
    350 7. Work to be done
    351 ------------------
    352 
    353 * Add the ability to populate more than one CSK
    354 * Test secure debug
    355 * Test on Armada XP
    356 
    357 8. Bibliography
    358 ---------------
    359 
    360 [1] ARMADA(R) 38x Family High-Performance Single/Dual CPU System on Chip
    361     Functional Specification; MV-S109094-00, Rev. C; August 2, 2015,
    362     Preliminary
    363 [2] AN-383: ARMADA(R) 38x Families Secure Boot Mode Support; MV-S302501-00
    364     Rev.  A; March 11, 2015, Preliminary
    365 [3] Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography
    366     Specifications Version 2.1; February 2003;
    367     https://www.ietf.org/rfc/rfc3447.txt
    368 [4] AN-389: ARMADA(R) VHV Power; MV-S302545-00 Rev. B; January 28, 2016,
    369     Released
    370 [5] Marvell Armada 38x U-Boot support; November 25, 2015;
    371     https://github.com/MarvellEmbeddedProcessors/u-boot-marvell
    372 
    373 2017-01-05, Mario Six <mario.six (a] gdsys.cc>
    374