raspberrypi / usbboot

Raspberry Pi USB booting code, moved from tools repository
Apache License 2.0
913 stars 231 forks source link

Cannot write program_pubkey=1 to OTP memory #233

Closed ertsth closed 1 month ago

ertsth commented 2 months ago

Describe the bug

I want to lock secure mode on my Raspberry Pi 4B completely, to have bootloader that ignores any recovery.bin that is not signed with my RSA private key. I followed instructions in this repo (https://github.com/raspberrypi/usbboot/blob/master/secure-boot-recovery/README.md#locking-secure-boot-mode) and general secure boot instructions (https://pip.raspberrypi.com/categories/685-whitepapers-app-notes/documents/RP-003466-WP/Boot-Security-Howto.pdf). When I'm trying to lock bootloader with program_pubkey=1, recovery fails (red screen and error in logs). Similar issue: #143

Steps to reproduce the behaviour

Changed secure-boot-recovery/config.txt to the following:

uart_2ndstage=1

eeprom_write_protect=1

program_pubkey=1

#revoke_devkey=1

#program_jtag_lock=1

cd secure-boot-recovery ../tools/update-pieeprom.sh -k ../private.pem sudo ../rpiboot -d .

Device(s)

Other

Compute Module IO board.

No response

RPIBOOT logs

RPIBOOT: build-date Jul 23 2024 version 20240422~085300 bbd60338
Loading: ./bootcode4.bin
Waiting for BCM2835/6/7/2711/2712...
Loading: ./bootcode4.bin
Sending bootcode.bin
Successful read 4 bytes 
Waiting for BCM2835/6/7/2711/2712...
Loading: ./bootcode4.bin
Second stage boot server
Loading: ./config.txt
File read: config.txt
Loading: ./pieeprom.bin
Loading: ./pieeprom.bin
Loading: ./pieeprom.sig
File read: pieeprom.sig
Loading: ./pieeprom.bin
File read: pieeprom.bin
Second stage boot server done

Kernel logs

no kernel

Device UART logs

  8.17 RPi: RECOVERY release VERSION:72caf667 DATE: 2024/05/17 TIME: 12:26:58
  8.21 BOOTMODE: 0x07 partition 0 build-ts BUILD_TIMESTAMP=1715945218 serial ec9a8c13 boardrev c03115 stc 8821279
  8.31 PM_RSTS: 0x00001000
  8.33 part 00000000 reset_info 00000000
  8.37 uSD voltage 3.3V
  9.95 OTP boardrev c03115 bootrom 8b0 8b0
  9.77 BOOT_ORDER: 0xf3
  9.77 USB-OTG disconnect
 11.89 Read config.txt bytes     1214 hnd 0x0
 11.92 pieeprom.sig
 11.92 hash: 26ec387b92a613d201ae73f0372a4eba3eaca7ae03f5b9c80b752c7e9864bb9d
 11.99 ts: 1722863417
 11.87 Reading EEPROM: 524288 bytes 0xc0b60000
 12.26 637ms
 12.80 Bootloader EEPROM is up to date
 12.80 secure_boot_provision program_pubkey 1
 12.87 bootconf.sig
 12.87 hash: d7c7f93ddb4805ddd847c358e4e4770c68a2e5dcd0448f2352128b8cf4b58957
 12.93 rsa2048: 842ce46724d5d000442be962c605e746607ce445865006c27f5f65d7adaa2ff4ddc16cc82336b04c1e4d6a7d5b02f17c34654ae61b113bdcb84c0c351dad40e7c870aa629711d7473e6f06765733a7b6b3efa4b3f2da187cba72f24306b6d320927145aa5a9471352e2e535d4149f547afdec5327bdd65764012d3439d9d1a66abfe5d1ebca9f4f72c171a88f1f840dab6dbf8a07d01b69627ac6f2a3d1026440f0bcbe985bc4357fbb22b3b6f4f7419f470a0f2252190cb36de01bbf5c1a4ab57b8d8b9e74c8c1528ed25d07ce693ecf43b0a64a08b868ac4230e6d135367de56bcb5243535b052826480f571f98b8b811c3aeb0fa9684b688008d1202e88df
 12.41 RSA verify
 12.75 rsa-verify pass (0x0)
 12.75 Failed to set RPIBOOT OTP gpio0 c600 -> 0
 12.79 USB-OTG disconnect
 12.81 BOOT ERROR: code 34 - ''
peterharperuk commented 2 months ago

Have you use gpio 6 for the nRPIBOOT gpio? If this is the case I think you might need to add "program_rpiboot_gpio=6" to config.txt as well.

ertsth commented 1 month ago

Yes, I'm using GPIO6 to boot in RPIBOOT mode, it was programmed previously. But I though that config program_rpiboot_gpio=6 enables gpio6 in OTP memory and therefore has no effect after it was programmed, at least that's what documentation says. Do I need to have this line in config.txt every time I want to change something in signed bootloader?

peterharperuk commented 1 month ago

I think you need it when enabling secure boot. It's playing safe to make sure OTP is set correctly for the GPIO you have chosen because a side effect of enabling secure-boot is that SD boot by the BOOTROM is disabled, i.e. you can only update the eeprom with rpiboot via the nRPIBOOT gpio. Hope that makes sense.

ertsth commented 1 month ago

Thanks for the quick answer! I can confirm that everything works as expected after I've added program_rpiboot_gpio=6 to my config.txt file. However, I'd like to clarify something since I haven't found anything about it in the documentation. So, the 'correct' workflow for locking secure boot is:

  1. erase EEPROM to fall into RPIBOOT mode manually
  2. program_rpiboot_gpio=N to have easy access to RPIBOOT mode
  3. enable secure boot
  4. lock secure boot by adding program_pubkey=1, revoke_devkey=1 etc., BUT program_rpiboot_gpio=N still needs to be presented in config.txt file.

Does N need to be the same? For example what if I've programmed GPIO6 but changed config to program_rpiboot_gpio=4 when locking secure boot? Is this option only required to be presented or to match currently OTP programmed nRPIBOOT?

And the most important, it should be documented somewhere, right? Because that's a very simple but not very obvious detail.

peterharperuk commented 1 month ago

Yes, the documentation could be improved. I've not tried it but I suspect steps 2 and 3 could be combined. But doing these steps separately might be safer as it's reducing the possibility of bricking a device during testing.

Does N need to be the same?

Yes it absolutely must be the same. Once OTP has been programmed it will generate an error if there's an attempt to change the GPIO again. It will however succeed in programming an OTP field to the same value.