A cryptographically secure bootloader for RISC-V in Rust
codethink.co.uk
codethink.co.uk
With measured boot, components in the boot chain tell some trusted component (e.g. a TPM, possibly in FW) about all of their input and only if the hashes at the end match, $something is accessible (in most cases a secret key for data decryption).
1. More flexibility (with TPM e.g. you can "seal" a secret against different parts independently)
2. No need for PKI, which gets very complex once revocations are involved (have fun looking at the "Secure Boot" DBX lists and the shim SBAT mechanism)
3. More freedom: The system still boots if the measurements don't match, you just don't get access to secrets. You're free to seal your own secrets against your new measurements and whoever did the last sealing has no access anymore. (Unlike on PCs where the Microsoft trust is in most cases not removable).
I assume the TPM in this case would only have a partial decryption key? I think something similar could be accomplished with SSS, no?
2. As for this, I can say i've never used DBX with UEFI Secure boot. Instead of revoking keys, I just remake the entire PKI from the top. The PKI is only there to support independent use by OS Vendor/OEM hence the separation of PK/KEK/db.
3. Counterpoint: over-reliance on TPMs and such. Whereas the ordinary trust chain only requires signature verification at the start of boot (presumably on-chip), measured boot requires more complex trusted computing hardware (presumably off-chip).
Personally, I find that systems that are overly-reliant on complex trusted computing hardware tend to lack in other areas. For example, iphones or google-pixel devices encourage the user to use a low-entropy password like a 4-digit PIN. These systems try often to reconcile "analog" passkeys like Biometrics (FaceID, fingerprints) by using trusted computing. Of course, if the trusted computing systems are breached (https://www.404media.co/leaked-docs-show-what-phones-cellebr...), then security is very weak.
I suppose the advantage of the measured-boot method is that it is optional. So you can still boot whatever OS you want, just without some TC features.
Depends on how it's set up. Currently most setups that use measured boot (systemd-pcrlock, partially BitLocker) ask for a recovery key if unsealing fails due to measurement mismatches and offer other options.
> I assume the TPM in this case would only have a partial decryption key?
That's also possible, but so far I haven't seen that. The sealed secret is sent to the TPM which then uses its hidden internal seed to derive the master key for volume decryption and sends it back. (In the case of bitlocker with TPM < 2 that could trivially be sniffed on the LPC bus...)
> I think something similar could be accomplished with SSS, no?
If you mean Shamir's secret sharing, possibly. Question is what to do with the shares.
2. Yeah, for your local machine this is a working approach, if you make sure that really only your own key works. Another reason against PKI is also that the trusted authority can't retroactively sign a backdoored executable to gain access to devices, as the measurements are independent from authority and ideally device specific.
3. Signature verification isn't just needed at the start of boot, it's ideally from start of booting until user authentication, which is the part that can be tampered with. I'd argue that the software side for measured boot is simpler, while the hardware side may be more complex.
> For example, iphones or google-pixel devices encourage the user to use a low-entropy password like a 4-digit PIN.
Using TPM+PIN is actually not that bad: Only if measurements match it's possible to unlock with a PIN and the TPM uses a counter in nonvolatile memory to prevent brute force attacks. It's not unfathomable that some manufacturer screws that up, but it's IMO stronger than relying on multiple parties (CPU, BIOS, OEMs, OS) developing an actually secure trust chain.
If you would like to play around with measured boot and similar functionality of TCG DICE. Thats on a USB stick that open, and have a good team behind it.
UEFI updates can also be a problem if they wipe the TPM as part of the update and thus destroy the sealed secret entirely (as my PC mobo does).
Yep, this can be a pain also in regards to firmware bugs (broken TCG event log anyone?). In the worst case you need to enter the recovery key or if you know in advance, exclude some component from measurement temporarily while supervising the next boot. If something goes wrong with the trust chain like a key got revoked but the bootloader didn't update correctly, you end up with an unbootable device and can't even go back easily.
> UEFI updates can also be a problem if they wipe the TPM as part of the update and thus destroy the sealed secret entirely (as my PC mobo does).
Ouch, that's bad design. The firmware is measured into the TPM on boot so there's no reason to do that..
It might just be a warning to cover their asses; ie it doesn't actually clear the TPM but they don't want to be responsible for your un-unlockable drive in case it does. I don't actually use the TPM for measured boot or anything else so I haven't checked.
In any case, UEFI updates are relatively common right now (once every couple of months or so) because it's a relatively new mobo (AM5), and because AMD is about to release new CPUs that requires corresponding AGESA etc updates. It'll probably become less frequent in a few years.
But you don't need any fancy PKI or vendor certificates for a trust chain, local trust is good enough.
I.e. the problem of secure boot isn't that it has a secured boot chain but how it has one.
Either way measured boot is still a nice think to complement a secure boot chain.
like just doing a review and comparison of existing boot verification mechanisms would have been already good scope for a thesis. Instead they are barely even mentioned as a side-note, which puts this in a awkward position.
or if crypto was focus, then putting more work on designing and implementing the crypto scheme would have been relevant. Now they got so tangled with the nitty gritty boot details that the crypto ended up also as questionable side-note.
or if rust was focus, then just implementing clean pure-rust bootloader could have been already enough for the thesis, avoiding the stumbling over on misguided crypto bits.
or many other ways this could have been more successful. overall it now feels the author ended up biting far more than what they can chew. also they should have imho spent less time coding and more time on editing the actual thesis. the text is all over the place.
There aren't that many people in the world who write bootloader code daily for a living, an even smaller subset of those would ever have done one entirely from scratch (vs. just board-porting U-Boot), and even of those, the likelihood of someone having done a secureboot capable one wouldn't be high. Assuming you have such a person as a thesis advisor is a huge stretch ...
That said though, a thesis is (or should be) a learning exercise. Even a complete fail (to achieve the "initial" objective) can make a great thesis if new knowledge - even negative proofs, "this isn't possible because ..." - come out of it. It's just my opinion maybe, but a graduate should never be taught "fake it till you make it"; rather, describe and document failures thoroughly, explain the observations, highlight and justify the parts that work or are breakthroughs. That can make a much better readable and much more useful thesis than one that skims over one-time lucky else nonreproducible results and delivers uncommented sources that fail to compile for anyone but the original author. In that sense, I would argue that a good thesis advisor will focus on the scientific process, documentary evidence, clarity of experimental setups and tests/checks/benchmarks performed, not whether the outcome would be "great enough" to pitch as a founder to VCs.
> In that sense, I would argue that a good thesis advisor will focus on the scientific process, documentary evidence, clarity of experimental setups and tests/checks/benchmarks performed, not whether the outcome would be "great enough" to pitch as a founder to VCs.
Exactly! And in this case I feel the exact opposite happened; the advisor let the student work overly fancy project with lot of buzzwords ticked and with minimal rigor; from the result I think it's is pretty obvious that way too big part of the whole project was spent on coding, and too little on those things. That's why I blamed the advisor/supervisor in my parent comment, they should have intervened at some point in the process.
Of course I do realize that in practice these thesis supervisors might have gazillion students under them and minimal time allocated per student, so most likely they just weren't very involved at any stage. And academic institutions have pressure to get students to graduate which creates its own set of problems.
If you don't need the other features of u-boot that this doesn't have, it makes sense to count the lower binary size and runtime memory usage as an advantage.
That said, they compared it to "an example U-boot binary", which sounds like they probably didn't tweak the bajillion config options u-boot has to produce one with an equivalent feature set to theirs, which would've been a fairer comparison for sure.
Either way, do you consider this a bad thing?
So it's really hard to call it a good thing or a bad thing; it's a trade.
I think that we have been able to thwart "treachery" in the meantime by exploiting side-channels in trusted computing implementations. Ultimately it may be necessary to amend the constitution to prevent manufacturers from distributing locked-down hardware for the good of free society (competition, democracy, etc.) at large. Otherwise, computer giants will have ultimate control over the distribution of information (given that the economics of manufacturing are driven by economies of scale).
Vector crypto is very cutting edge too. I guess there isn't any hardware that has it yet...
> SentinelBoot's threat model focuses on thin client devices which do not store their own OS and over-the-air updates (e.g. how phones are updated): both of these cases involve executable code being sent over a network, usually the internet. We ignore the risk of direct hardware modification, as an attacker can just swap out the bootloader (making any potential defence implemented by SentinelBoot in vain).
The author readily acknowledges that it does not defend against hardware modification. The other comments here trying to vilify this project don't understand what it is supposed to do.
Those who sacrifice liberty for safety will receive and deserve neither.
https://techcrunch.com/2014/02/14/how-the-world-butchered-be...
https://news.ycombinator.com/item?id=5268899
https://www.npr.org/2015/03/02/390245038/ben-franklins-famou...
The author explains that it does not attempt to defend against hardware attacks or attempts to replace the bootloader:
> SentinelBoot's threat model focuses on thin client devices which do not store their own OS and over-the-air updates (e.g. how phones are updated): both of these cases involve executable code being sent over a network, usually the internet. We ignore the risk of direct hardware modification, as an attacker can just swap out the bootloader (making any potential defence implemented by SentinelBoot in vain).
You see it with phones but also with cars where OEMs require Secure Boot enabled devices when possible. This ranges from the central unit to all small ECUs.
You can kind of see it pushed for desktops as the default mode but at least there for now you usually have a way to disable it.
For embedded devices though they never really provide a way to disable it. I think you could find a compromise where you could provide a physical method to disable it. If you disable it you clear all the DRM keys and other secrets. This way you can still protect against malicious updates for most users and tinkerers can do what they want once the company stops supporting it.
If anything, it just makes me glad that RISC-V also has specs for UEFI-like interfaces.
This bootloader doesn’t actually seem to be a real secure / trusted boot implementation anyway, just a thing that verifies updates.
Where Rust (and most languages with a robust type system) can help prevent side channel issues is via typing - all cryptographic operations in a given library can be implemented with (for example), a TimingSafeU32 type that only implements constant-time operations (comparison, multiplication, addition, etc). This massively reduces the opportunity for mistakes. Traits make implementing this type of system much easier and more elegant.
`rust-timing-shield` and `subtle` are both a good example here, as well as really everything in https://github.com/dalek-cryptography .
Or maybe an early return and having an expensive destructor called as it goes out of phase with RAII
They mean a boot loader that validates cryptographic public key signatures of the loaded component. That would be a secure cryptographic bootloader. AFTER they have proven that it is, in fact, secure.
You can't just write some code and then say it must be secure because Rust was involved.
Did they say that?
Which, by the way, do not apply, since the SHA256-Code is marked unsafe.
Contrast that with C, where every line may be a source of safety issues. It's a meaningful difference.
There is another issue: Unsafe code in Rust could violate assumptions that could cause other code in Rust to be unsafe. So it needs more care to write than regular C.
But I agree that it still a huge net benefit with respect to memory safety, but let's not exaggerate.
So I agree with the point in principle, I just do not like the "spin" of "every line of C is time bomb nobody can understand" while in Rust you just have to look at some lines of "unsafe" and all is good.
unsigned int mul(unsigned int x, unsigned int y) { return x * y; }
Or there are many high level function structures as, which also has no UB (with some assumption on the called functions):
void bar() { struct foo *p = foo_alloc(); foo_do1(p); foo_do2(p); foo_delete(p); }
Such code can be easily screened and also this can be done automatically. There is a lack of open-source which can do this, but I have an experimental GCC branch which starts to do this and looks promising.
unsigned short mul(unsigned short x, unsigned short y) { return x * y; }
I don't know about you, but I wouldn't think to treat these any differently unless I put on my language lawyer hat.
But I also do not worry about signed overflow anyhow, because compilers can turn them into traps.
Language standards shouldn't rely on compiler options to save developers here. There's a lot of compilers in the world that don't support the same range of options GCC and clang have, like CompCert. Those are often the ones building safety-critical applications these days, where trapping would be inappropriate.
Whether trapping is appropriate or not depends on the context, but it surprising to hear as an argument, because Rust also has a fail hard policy...
void bar() { struct foo *p = foo_alloc(); foo_do1(p); foo_do2(p); foo_delete(p); }
Are we assuming foo_alloc always succeeds? malloc returns NULL to indicate failure to allocate, which this code wouldn't handle.> Such code can be easily screened and also this can be done automatically.
That doesn't sound right at all. Robust static analysis of C code is extremely involved. It's an area of ongoing research.
Prior efforts along these lines have not been successful. Even adopting the MISRA C ruleset doesn't guarantee absence of undefined behaviour, for instance.
Any "unsafe" block within a rust source code potentially corrupts the entire application as undefined behavior has no bound and will/may leak right out of the unsafe block.
You are arguing something else. Enumerating all unsafe code is a good feature, but when one of the fundamental building blocks of your security is marked unsafe, it raises questions about its overall benefit.
I'm emphasizing the difference between rust and C here because unlike Martin, I don't agree that it's meaningfully possible to eliminate UB in C by careful analysis. You're able to do this in Rust in large part because those issues are all concentrated in a few tightly scoped blocks with clear responsibilities.
Unsafe also gives you a massive hint where to look when you're debugging.
I have a feeling that the qualifier is there in the headline to distinguish from the potential security improvements that come from replacing a C bootloader implementation with a feature -parity Rust one.
The article doesn't claim that at all.
The cryptographically secure part comes from doing cryptographic verification of the code before running it.
The article talks about using Rust to improve memory safety.