osresearch / safeboot

Scripts to slightly improve the security of the Linux boot process with UEFI Secure Boot and TPM support
https://safeboot.dev/
GNU General Public License v2.0
270 stars 28 forks source link

Document pros and cons of using single private key for Secure Boot #97

Open invidian opened 3 years ago

invidian commented 3 years ago

Hey, this issue is more of a question, but perhaps it would be nice to have answer persisted in the documentation for others.

I'm currently researching building a secure setup for reproducible OS installation for private fleet of machines and while reading about use of TPM I stumbled upon this project, which I think is incredible and largely covers my needs. However, I am still trying to understand some details to make sure I can trust what I'm going to implement.

By looking at uefi-sign-keys, as far I understand safeboot use single private key stored in 9c slot on YubiKey for PK, KEK and DB keys for Secure Boot. Please correct me if I'm wrong.

Based on understanding above I am curious about following aspects:

Thanks in advance!

osresearch commented 3 years ago

That's a good set of questions. The single key signing is a convenience for the common use case of a single machine with a single admin (who probably also the owner). For a fleet of machines, with multiple administrators, it probably does make sense to use a key hierarchy. If you already have a corporate CA, that can be the Platform Key, which is used to sign the KEK, which could be stored in a hardware token, and is used to sign individual admin keys that are in the db.

Using a TPM signed key has the drawback that the single machine could then (possibly) be coerced into signing a new OS image for itself. An attacker who can directly talk to the TPM can potentially use it to sign a new set of PCRs, for instance. Depending on your key authentication settings and threat model, this might be a bigger issue.

key-init does store the key in the filesystem, with an optional passphrase protecting it. You are free to move the private key elsewhere, or to perform that step on another machine and only transfer the public key to the client system. yubikey-init is the one that configures the key in the hardware token, which does then require that the hardware token be available for every upgrade. In a fleet where these are centrally managed and rolled out, that hopefully isn't an issue.

(Again, depending on your threat model, you might be interested in cosign (#70), which allows the signing key to be split between multiple signing authorities. If your builds are reproducible, then they can each perform a partial signature and then combine N-of-M of those signatures to produce a valid RSA signature on the actual EFI executable)

invidian commented 3 years ago

Thanks for answering @osresearch!

That's a good set of questions. The single key signing is a convenience for the common use case of a single machine with a single admin (who probably also the owner). For a fleet of machines, with multiple administrators, it probably does make sense to use a key hierarchy. If you already have a corporate CA, that can be the Platform Key, which is used to sign the KEK, which could be stored in a hardware token, and is used to sign individual admin keys that are in the db.

Just to clarify, in my case, I'm a single admin with multiple machines.

(Again, depending on your threat model, you might be interested in cosign (#70), which allows the signing key to be split between multiple signing authorities. If your builds are reproducible, then they can each perform a partial signature and then combine N-of-M of those signatures to produce a valid RSA signature on the actual EFI executable)

cosign sounds really interesting, but it's a bummer that it does not support hardware keys, it make it's use limited and I think not suitable for my case.

#

So I've spend more time (perhaps waay too much :smile:) examining UEFI specification and various sources talking about the Secure Boot and while I don't feel comfortable saying that I now understand everything, I think I can at least partially answer my questions.

What are the pros and cons between using single key pair for each key type? Usual guides for using Secure Boot tells user to generate 3 different keys.

So, I think the main difference (at least in my case) between using single key pair and multiple pairs is handling the situation when the key leaks. If 3 different keys are stored in a different way, so each of them can be stolen independently, then the following situations may occur:

Given that last 2 points require ability to execute the code, protecting key added in db is the most important thing. https://github.com/gdamjan/secure-boot/issues/5#issuecomment-353684997 also suggested, that keys other than db should ideally be stored offline.

The other feature of using multiple keys I found crucial is ability to delegate trust to other parties (key owners). E.g. Platform owner (e.g. OEM) may delegate the control over who is allowed to execute code on the platform to the OS vendor by adding OS vendor key to KEK.

KEK has also capabilities of further delegating who is allowed to execute the code on the platform, which as far as I remember might be used to allow driver developers to sign their drivers for the devices for example, though in real world, right now only Microsoft is allowed to sign drivers, they do not delegate the trust further.

I also found some sources saying, that KEK may also be used to sign code for execution, however when testing on my systems, I was not able to get it to work. But that ended up pushing me into the rabbit hole of checking which UEFI specification version my UEFI implements, which I didn't find how to perform. My UEFI author also does not say, which version it implements (security by obscurity?).

Figuring it out based on UEFI specification changelog is not easy either, I was not able to find clearly defined differences between each spec versions, only "Revision History" which is not particularly useful. I guess one could use https://github.com/tianocore/edk2-test to run different versions of test suite to check which version their UEFI implements?

So, if you are the only trusted person for your machines, using more than one key does not really bring a lot of benefit from security point of view, maybe except lifting the requirement of re-keying all devices in case your key leaks.

I hope this is not too much of a off-topic. I probably missed some details too, as overall it seems Secure Boot documentation is not great and most sources pretty much copy-paste from UEFI specification, which IMO is not the best either.

I still need to read about the TPM part...

invidian commented 3 years ago

Using a TPM signed key has the drawback that the single machine could then (possibly) be coerced into signing a new OS image for itself. An attacker who can directly talk to the TPM can potentially use it to sign a new set of PCRs, for instance. Depending on your key authentication settings and threat model, this might be a bigger issue.

key-init does store the key in the filesystem, with an optional passphrase protecting it. You are free to move the private key elsewhere, or to perform that step on another machine and only transfer the public key to the client system. yubikey-init is the one that configures the key in the hardware token, which does then require that the hardware token be available for every upgrade. In a fleet where these are centrally managed and rolled out, that hopefully isn't an issue.

So, storing key on TPM has this advantage, that the private key cannot be copied and used offline. Also if key is protected by a password, TPM prevents against brute-force attacks on the key. Note that the device like YubiKey gives the same level of protection.

It also forces you to only be able to use the key from a given AND trusted machine, as opposite to e.g. YubiKey, which can be used on any machine.

I think ideally you could combine key from TPM with key from e.g. YubiKey while signing the bootloader, as this reduces the blast radius in case your YubiKey is compromised, as then an attacker cannot execute the code on neither of your machines still. The same goes other way around, if your machine is compromised, an attacker cannot sign new code using only the TPM, as hardware module is still required.