Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
invidian opened this issue Jan 5, 2021 · 3 comments
Open
Labels
question Further information is requested

Comments

@invidian
Copy link

invidian commented Jan 5, 2021

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:

  • 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.
  • Is there any security benefit in using keys unique to the machine (e.g. in TPM) rather than re-using the same key for all owned machines? For example, if single machine private key gets compromised, it cannot be used to boot malicious software on other machines.
  • As far as I see key-init currently stores the key on the host file-system. Is it somehow better than storing it in TPM? For some systems using YubiKey might not be very convenient (having to access home server to plug YubiKey for every kernel update).

Thanks in advance!

@osresearch osresearch added the question Further information is requested label Jan 7, 2021
@osresearch
Copy link
Owner

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
Copy link
Author

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 😄) 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:

  • If only key added in db leaks, it gives an attacker ability to execute code on your platform, which is most dangerous kind of attack. If you find out that this key leaked, you should then audit/re-provision all platforms OSes where the same key has been used to ensure that attacker did not leave you a backdoor, generate new key, add it to db and blacklist old key by adding it to dbx.
  • If only key added in KEK leaks AND attacker has ability to execute the code on your platform, they can use leaked key to add their own keys to db. This is similar to just cloning your own db key. If this occurs, one must audit/re-provision all platforms OSes where the same key has been used AND blacklist old key by adding it to dbx (IIRC UEFI should reject all keys which are rooting to this key).
  • If only Platform Key leaks AND an attacker is able to execute code on your platform, they may add their own KEK and db keys to your platform.

Given that last 2 points require ability to execute the code, protecting key added in db is the most important thing. gdamjan/secure-boot#5 (comment) 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
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants