ardupilot/Tools/scripts/signing
Andrew Tridgell 792fdc2fb8 Tools: specify pymonocypher version in more places
and confirm version when running tools
2024-05-19 10:07:54 +10:00
..
ArduPilotKeys
README.md
generate_keys.py
make_secure_bl.py
make_secure_fw.py

README.md

Secure Boot Support

To assist with vendors needing high levels of tamper resistance with RemoteID, you can optionally use secure boot with ArduPilot. This involves installing a bootloader with up to 10 public keys included and signing the ArduPilot vehicle firmware with one secret key. The bootloader will refuse to boot the firmware if the signature on the firmware doesn't match any of the public keys in the bootloader.

Generating Keys

To generate a public/private key pair, run the following command:

  python3 -m pip install pymonocypher==3.1.3.2
  Tools/scripts/signing/generate_keys.py NAME

That will create two files:

  • NAME_private_key.dat
  • NAME_public_key.dat

NAME can be any string, but would usually be your vendor name. It is only used for the local filenames.

The generated private key should be kept in a secure location. The public key will be used to create a secure bootloader that will only accept firmwares signed with one of the public keys in the bootloader.

Building secure bootloader

To build a secure bootloader run this command:

 Tools/scripts/build_bootloaders.py BOARDNAME --signing-key=NAME_public_key.dat

That will update the bootloader in Tools/bootloaders/BOARDNAME_bl.bin to enable secure boot with the specified public key. Next time you build a firmware for this board then that bootloader will be included in ROMFS.

Note that this will include the 3 ArduPilot signing keys by default as well as your key. This is done so that your users can update to a standard ArduPilot firmware release and also prevents issues with vendors who can no longer provide firmware updates to users. If you have a very good reason for not including the ArduPilot signing keys then you can pass the option --omit-ardupilot-keys to the make_secure_bl.py script.

Building Signed Firmware

To build a signed firmware run this command (example is for a copter build):

 ./waf configure --board BOARDNAME --signed-fw
 ./waf copter
 ./Tools/scripts/signing/make_secure_fw.py build/BOARDNAME/bin/arducopter.apj NAME_private_key.dat

The final step signs the apj firmware with your private key. You can then load that secure firmware as usual with your ground station, for example using load custom firmware in MissionPlanner or Tools/scripts/uploader.py on Linux.

Alternatively you can set the private key in the configure step, which allows for build and upload in one step for faster development:

 ./waf configure --board BOARDNAME --signed-fw --private-key NAME_private_key.dat
 ./waf copter --upload

Flashing the secure bootloader

There are two methods of getting the secure bootloader onto the board. The simplest is to follow the above steps and then follow the usual method of updating the bootloader, which involves sending a MAVLink command to ask the firmware to flash the embedded bootloader from ROMFS. The firmware generated using the above steps will have your secure bootloader included in ROMFS, so when the users asks for the bootloader to update it will flash the secure bootloader.

The second method is to put the board into DFU mode. If your hwdef.dat and hwdef-bl.dat include the ENABLE_DFU_BOOT options and your board is based on a STM32H7 then your ground station should be able to put the board into DFU mode. You can then flash the bootloader bin file to address 0x08000000 using any DFU capable client.

Note that the flight controller will refuse a switch to DFU mode if it is running a secure bootloader already.

How to tell you are using secure boot

When using a secure bootloader the USB ID presented by the bootloader will have a "Secure" string added. For example, you would see this in "dmesg" in Linux:

  Product: BOARDNAME-Secure-BL-v10

On Windows you can look at the device properties in device manager when the bootloader is running and look for the "Bus reported device description". It will have the above "Secure" string. Note that this string only appears when in the bootloader. To ensure the board stays in the bootloader for long enough to see this string just flash a normal unsigned firmware. With a secure bootloader and an unsigned firmware the board will stay in the bootloader forever as it will be failing the secure boot checks.

Reverting to normal boot

If you have installed secure boot on a board then to revert to normal boot you would need to flash a new bootloader that does not have secure boot enabled. To do that you should replace Tools/bootloaders/BOARDNAME_bl.bin with the normal bootloader for your board .

Then using MAVproxy connect to the autopilot and execute the following commands to remove all public keys from the signed bootloader:

  module load SecureCommand
  securecommand set private_keyfile my_private_key.dat
  securecommand getsessionkey

This opens a secure command session using your private_key.dat file to allow the removal of all public keys from the bootloader using these commands:

  securecommand getpublickeys        will return the number of public keys...you will need this next
  securecommand removepublickeys 0 X   where X is the number of public keys...this removes them

For example, if you have a standard firmware with the 3 ArduPilot public keys and one of your own public keys then X will be 4 in the above command.

Re-run the 'getpublickeys' command again to verify that all keys have been removed.

Now exit MAVProxy and build a firmware using the normal bootloader but still using the --signed-fw option:

   ./waf configure --board BOARDNAME --signed-fw
   ./waf copter --upload   (or whatever vehicle you desire)

After loading the new firmware, connect to MAVProxy and run the command to flash, the new, non signing checking bootloader:

  flashbootloader

You may now use and run normal unsigned firmware, including the firmware just loaded.

Supported Boards

Secure boot is only supported on boards with at least 32k of flash space for the bootloader. This includes all boards based on the STM32H7 and STM32F7. You can use secure boot on older other boards if you change the hwdef.dat and hwdef-bl.dat to add more space for the bootloader.

If you have a private key corresponding to one of the public keys in the bootloader on a board then you can use the MAVLink2 SECURE_COMMAND messages to change the public keys, or even remove all public keys to allow the use of unsigned firmwares.

MAVProxy version 1.8.55 and later has a "securecommand" module which gives you commands for:

  • generating a session key for remote update
  • fetching the current public keys
  • setting new public keys as additonal or replacement keys
  • removing all public keys

It is expected that future versions of MissionPlanner will include a plugin with the same functionality.

Using SECURE_COMMAND in combination with MAVLink forwarding you can hand over management of a vehicle between vendors.