Skip to content

Latest commit

 

History

History

crypto_hal

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
Signing px4 firmware files and checking the signatures in bootloader

1) Bootloader with signature checking support

If the environment variable CRYPTO_HAL is defined while building the bootloader,
the bootloader will automatically include signature check support.

If the envirnoment variable CRYPTO_HAL is not defined, there is no extra code
or structures added to the bootloader.

By default the bootloader supports monocypher ed25519 signature check. In order
to add other signature/encryption methods, one must create another crypto-hal
implementation following the example in crypto_hal/monocypher

2) Using monocypher crypto-hal

To build the default signature checking support into bootloader, define the
following environment variables:

export CRYPTO_HAL=monocypher
export PUBLIC_KEY0=${PWD}/crypto_hal/test_key/key0.pub

And build the bootloader for your board, e.g:
make px4fmuv5_bl

The key file in the above example points to px4 test key. This key should be
replaced with public key from a self generated key pair

4) Structure of the expected table of contents in the px4 firmware

The format of table of contents is

magic (4 bytes)
version (4 bytes)

n \sz  4    4     4   4      1             1             1             1      4
   ----------------------------------------------------------------------------
1  |   name start end target signature_idx signature_key ecryption_key flags1 reserved
2  |   name start end target signature_idx signature_key ecryption_key flags1 reserved
.  |
.  |
N  |   name start end target signature_idx signature_key ecryption_key flags1 reserved

end (4 bytes)

Description of the fields:

magic:          always 0x00434f54, in ascii string "TOC"
version:        crypto version, reserved for vendor specific use

name:           the entry name (not used by bl)
start:          start address of the block
end:            end address of the block
target:         the block shall be copied to this address after all crypto
                actions have been taken (signature check, decrypting)
signature_idx:  entry index within the TOC to find signature block for this
signature_key:  public key number, which is used for sig check
encryption key: private key number, which is used for decrypting the block
flags1:         flags telling what to do with the block ( see chapter 5 )
reserved:       reserved/vendor specific

end:            always 0x00444e45, in ascii string "END"

The version and N entries are defined by the board for which the px4 is being
built for. The format of the each entry is:
name<4> start<4*> end<4*> signature_idx<1> signature_key<1> ecryption_key<1> flags1<1> reserved<4>

*) entry is 20 bytes on 32-bit targets. On a 64 bit targets native 64-bit build
   it would be 32 bytes

Each entry defines a block of contents for the binary. The bootloader goes
through the TOC line-by-line and performs any tasks defined by "flags".

The TOC is always contained within the first block, which is always checked for
valid signature. The exact placement of the TOC is right after the boot delay
signature "BOOT_DELAY_ADDRESS".

5) The TOC parsing in image_toc.c

The bootloader will find the TOC and parse each entry. Depending on "flags" of
the entry, it will perform actions on each entry. The currently supported flags
are:

TOC_FLAG1_BOOT:
  - This flag marks a bootable image; the bootloader will jump to this
  image after all the crypto actions have been taken. If no separate
  vector table exists in the TOC, the application's vector table is used

TOC_FLAG1_VTORS:
  - This flag marks a separate vector table block. The bootloader will
  set the interrupt vectors to this block. This will override the vector
  table from the application.

TOC_FLAG1_CHECK_SIGNATURE:
  - Any block marked with this flag in the TOC will be signature checked.
  if the check fails (for any entry marked with the flag), booting is prohibited

TOC_FLAG1_DECRYPT:
  - The block is encrypted and has to be decrypted before use. This kind of
  block can be targeted for either bootloader or px4 firmware (the TOC is also
  accessible in px4 firmware) to pass any secrets.
  An example bootloader usage is for a chipset which can execute code directly
  from an encrypted flash. The bootloader can then set up the relevant crypto
  accelerators.
  Another example is to pass new (private) keys or IP protected code to
  either bootloader or px4 firmware
  Currently this flag is ignored by the bootloader, as there is no private key
  storage implemented.

TOC_FLAG1_RDCT:
  - This flag marks that the block is an R&D certificate, unlocking some
  features for an individual device. This flag is reserved for future use,
  it is not yet implemented in bootloader.

- The "flags" don't control the signature check for the first block;
  this one contains the TOC, and it must be tamper protected as well

- Booting any image will always happen only after the whole TOC has been
  processed.

6) Notes

- A normal bootloader which doesn't do signature checking will boot also signed
  px4 binaries
- A bootloader which does the signature checking will boot only properly signed
  px4 binaries
- The public key for signature checking will be embedded in the bootloader code.
  In order to prevent booting unauthorized binaries in the device, one must
  ensure that the bootloader or the public key cannot be tampered with
  or by-passed completely. For example in STM32 hardware this requires at least
  locking the chip to RDP level 2, on other HW targets mechanisms differ.
- On STM32 platforms, remember that RDP level 2 lockdown is irreversible.
  To test the signing, the locking down is not required.
- Remember that it is a responsibility of the user of this feature to ensure
  that the chain of trust is maintained at desired level. The crypto-hal
  implementation is just a tool, one must understand how to use it.