trezor-firmware icon indicating copy to clipboard operation
trezor-firmware copied to clipboard

Jump from firmware to bootloader initiated by Host on TT

Open tsusanka opened this issue 4 years ago • 15 comments
trafficstars

For TTs with new boardloader (~July 2021) we can provide the "Go to bootloader" feature such as we did for T1 in #1047.

We need to:

  • Support the new "go to bootloader" protobuf message, see #1461.
  • Check whether the new boardloader is present.
  • If no, abort and inform the host.
  • If yes, show a confirmation dialog.
  • Restart into bootloader.

tsusanka avatar Apr 15 '21 12:04 tsusanka

We should do this along with #1049 to minimize the number of bootloader updates.

tsusanka avatar Apr 15 '21 12:04 tsusanka

We have agreed with @prusnak, he will do the needed modification in boardloader. After that's done we can discuss who will do the rest.

tsusanka avatar Apr 28 '21 12:04 tsusanka

To recap: this is indeed not done yet. The problem is that the boardloader deletes all RAM so we can't use the same trick as for T1.

I am assigning @mmilata and moving back to backlog as this needs to be planned with #1049 as already mentioned.

tsusanka avatar Oct 25 '21 07:10 tsusanka

I was just looking at this and saw that the soft reset check was removed from the boardloader by https://github.com/trezor/trezor-firmware/commit/3294a49cec25901f57d825ef0a7ba02bd7c3169e#diff-732ec3c652ad70179ea1d45a0736327ef215644155d9a4443e76c3efef1a8e4d. That was the main hurdle and I was hesitant to remove that from the boardloader, but since that bridge was crossed a while ago, maybe just carry through the fact that it was a soft reset (by not clearing the reset flags) and then look at those flags for the soft reset event in the bootloader as a way to know to stay in the bootloader that doesn't require user interaction. As far as I remember, that's all you really need since nothing else that I recall soft resets the system, and you just need a way to know to not leave the bootloader that doesn't require user interaction. My recollection from when I put that reset flag checking stuff in the boardloader was that I was trying to provide as consistent a system state as I could (and avoiding system states that were not strictly full power-on removed a lot of unknowns) and also make it harder to perform glitching attacks that target the post-bootROM code.

mcudev avatar Nov 09 '21 02:11 mcudev

but since that bridge was crossed a while ago

The main challenge is how to implement this feature so it works with the older boardloader (that still halts when reset_flags_check tells it to). The commit you are linking to hasn't been deployed yet.

prusnak avatar Nov 09 '21 07:11 prusnak

ah, not being deployed yet changes things. i don't like the approach of changing the reset flag check in the boardloader. iirc, the reason that this feature is not implemented naturally by jumping from the firmware back to the bootloader is that the firmware runs with reduced privileges. maybe another way to backdoor into a solution is to ponder, "how do we get privileged execution back to the bootloader and in a way that makes sure it's a running an authentic prod bootloader?". it might be a dead end, but i'll think on it.

mcudev avatar Nov 09 '21 20:11 mcudev

the best idea that i've had so far, and i haven't tried it because i don't have the cycles right now, is to make a handler in the firmware that you can trigger to get into handler mode (and thus privileged execution) and then disable the mpu. that might be a dead end if the mpu can't be disabled. at the moment, i forget if there is a catch that disallows that. there might be, but maybe there's a way around it once you have privileged execution.

mcudev avatar Nov 16 '21 15:11 mcudev

ok, i finally have a promising idea on how to do this safely. i have not tried this yet, but the docs look very promising. basically, in the bootloader, check to see if the real-time clock has been configured. if not, configure it and continue as normal. however, if it has been setup already, stay in the bootloader for the update process. we're not relying on the value of the RTC, just that it has been configured (or, if that is not good enough, that it has been been running for longer than, for example, a second). RM0090 section 26.1 says, "As long as the supply voltage remains in the operating range, the RTC never stops, regardless of the device status (Run mode, low-power mode or under reset)." there are some other supporting docs that indicate that a warm reset won't clobber the RTC peripheral's registers too.

mcudev avatar Jan 07 '22 12:01 mcudev

@mcudev haha, that's a genial idea! :-)

prusnak avatar Jan 07 '22 12:01 prusnak

doh, wait, the rtc registers survive reset, but that still relies on reset which will be caught be the old boardloaders. that's not good enough. my next idea would be to add to the firmware svc call handler a service call that disables the mpu, goes back into privileged thread mode, and branches to the beginning of the boardloader code in flash. that code needs to be in a handler so that it runs with the privileges necessary to disable the mpu. that should get past the boardloader reset check and also verify integrity of the bootloader before running it. i haven't tried this yet, so, i might be missing something that will cause this approach to not work. it seems plausible that it could work though as long as the boardloader re-initing everything doesn't fail.

mcudev avatar Jan 08 '22 09:01 mcudev

Current boardloader code defines version, but it is not included in the resulting binary.

Thus for boardloader that will support this we will need a way for firmware to know whether given boardloader supports "jump to bootloader" and can respond to the call with "OK" or "sorry not supported".

I can think of two ways of doing it:

  1. add some magic bytes and boardloader version at some fixed flash address
  2. put some more advanced structure like a feature bitmap (could be used if we need to add something later), again at some fixed flash offset preceded with magic bytes

Option 2 seems cleaner, though we would need to decide how many features we want to support in future theoretically.

Both can be combined, it probably won't hurt saving the version as it's just a few bytes.

hiviah avatar Mar 08 '22 15:03 hiviah

MPU config for the firmware currently uses all the 8 regions (there are only 8 available), so normally boardloader would not be readable from running firmware. Though it seems there is a workaround of temporarily turning off MPU at beginning of firmware's main and read the feature/version bytes of boardloader into RAM. The mpu_config_firmware will configure it right away later.

hiviah avatar Mar 08 '22 15:03 hiviah

We need a testable bootloader before QA can test it...

hynek-jina avatar Jun 09 '22 12:06 hynek-jina

What can be done here from our (QA) side?

STew790 avatar Aug 01 '22 14:08 STew790

nothing for now, see https://github.com/trezor/trezor-firmware/issues/1571#issuecomment-1151047017

matejcik avatar Aug 01 '22 14:08 matejcik