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
Add Trusted Platform Module 2.0 (TPM2) pin support #17
Conversation
8c9a7ca
to
9206ae0
Compare
4eeef7f
to
ba152b2
Compare
ba152b2
to
c5333b8
Compare
c5333b8
to
e247e38
Compare
@npmccallum one thing pointing out is that the default algorithm used for the primary key is ECC (TPM_ALG_ECC). A better option would be to use a symmetric algorithm (TPM_ALG_SYMCIPHER) instead. But unfortunately only asymmetric algorithms were supported for primary keys in previous version of the TCG TPM specification so using symcipher as default may not work on all TPM2 chips (please refer to this tpm2-tools project issue). The TPM chips have properties that specify the implemented version of the spec, so you can query them, i.e:
So we could query the specification version but as @webmeister mentioned, I also didn't find where exactly in the specification is mentioned which algorithms are supported for primary keys on each version of the spec. So I'm not sure if we can rely on something like that to choose which key algorithm use by default. I also didn't have access to a TPM2 that implements a 01.38 revision to test if symmetric parent keys were working. That's why I left ECC as the default for now, which should work on all TPM2 chips. |
Any ideas? |
@npmccallum yes, the tpm2-tools support different TCTI modules (transport layers). By default it attempts to use the D-Bus based resource manager (tpm2-abrmd) but you can also access the TPM device directly. Could you please try the following command instead:
|
This is on a 6mo Dell XPS 13:
Thoughts? |
I question whether or not we can predict algorithm support from TPM_PT_REVISION. I suspect vendors will implement the algorithms and forget to bump the revision. Is there a way to test for symcipher directly? What precisely are the drawbacks for using EC? |
@npmccallum right, that's what I questioned too. I don't think there's a way to explicitly query the algorithms that are supported by a given TPM2 chip. AFAICT, the spec only defines the set of mandatory algorithms on each spec version. But even there, it doesn't specify if these are only for created objects or also for primary keys. But even older versions of the spec mentions that asymmetric algorithms can be used for primary keys, and RSA and ECC are listed as mandatory asymmetric algorithms. The reason I mentioned symcipher as possibly a better default option was performance. But since ECDH is used, I guess is less of a concern? |
What is the current performance impact of ECC? Can you help define this for me? Is there any way we can mitigate the performance hit? |
@npmccallum the problem is that I didn't have access to many TPMs to have a conclusive answer. But a colleague tested the clevis tpm2 pin (which defaults to ECC) on his system and said that encryption/decryption took several seconds. Now, I don't know if the performance on those chips are really bad regardless of the used algorithm since I don't have access to test. On my test system (Intel PTT firmware based TPM2) I get much faster times:
I've also tested on a system with a hardware TPM2 and the times were similar than my test system. Neither system supports using symmetric primary keys so I couldn't compare the performance. So more than the default algorithm used, I'm worried about the performance variability between different TPM2 chips. One optimization that I did compared with the previous PR is that the primary key isn't recalculated on each operation (which may be slow specially for RSA). But instead the pin only calculates the PK the first time and make it persistent in the TPM, so future operations don't have to. |
This seems reasonable. Can you defined "make it persistent in the TPM" for me? At the Linux Security Summit two weeks ago, I sat in a talk on TPM where the recommended advice was to export the primary key and load it during decryption. Are you persisting the PK on the NVRAM? |
Yes, the objects in the TPM2 can either be transient or persistent. Transient objects are the ones that are only in the TPM RAM and can be removed by either a TPM2_FlushContext() command or a TPM2 reset. Persistent objects are stored in the TPM NVRAM and there's a TPM2_EvictControl() command to either make a transient object persistent or to evict a persistent object. I also read the same recommendation than you, and that's why the previous implementation didn't store the primary keys in the TPM and was recalculated on decryption (since the PK derivation function is deterministic). But then someone found this TPM2 chip that's very slow and also I noticed that RSA primary key creation time took several seconds even on my test system. Notice how the first operation takes a lot because the RSA PK is created and the second one is fast due the PK already being in the TPM2:
For ECC is faster, but still creating the PK increases the operation time:
|
I'd be pretty certain that if your TPM claims to implement 01.38 (or newer), you can also rely on it supporting symmetric storage keys. But this version of the specification is just a year old now, so it will probably take a long time before the majority of TPMs implements it.
You can query the supported algorithms, but only in a generic "is this algorithm supported at all" kind of way (TPM_CAP_ALGS). You cannot determine whether a specific command will accept a certain parameter. Of course, if symmetric keys are fast enough to create, you could just always start with one, and only when your command fails, fall back to slower keys. Or another wild idea: Why do you need a storage key at all in your scenario? Can't you just use a symmetric primary key and do all your operations with it? There is no need for you to be able to move keys between TPMs, is there?
Exporting the primary key sounds like TPM2_ContextSave, right? This should indeed be a fast operation, but your exported copy is only valid for that power cycle, so you need to recreate it after each reboot (or store it in NVM using TPM2_EvictControl). |
Then Anaconda needs to know that PCR7 is connected to the secure boot state. If it is only Anaconda that needs this knowledge, this is fine. But if you expect other applications to have the same need, then it would make sense to encode this TPM-specific knowledge somewhere on a lower layer (clevis in this case?), so that not every application author has to read the obscure TPM specifications (or blindly copy the algorithm from another application).
No, my assumption was that the attacker can access the sealed object that is stored on the disk (encrypted with a TPM-internal secret). Because if your assumption is that an attacker cannot access that data, there would be no need for you to use a TPM at all, you could just store your key in plain at the same location. From the "the disk alone cannot be decrypted" scenario I guess that what you really assume is that the attacker can access the sealed object (e.g. because they have physical access to the disk) or perhaps the TPM (e.g. because they can execute code as a non-root user on the machine), but never both. But that scenario would also work with an inexpensive USB flash drive as key storage, no need for a fancy TPM. So to really get an advantage from the TPM, you need to use it for more than just a very complicated data storage ;-)
Correct.
This is not so much about attacks, but again rather about cooperation between multiple applications. You are probably the first/only application at the moment, so there is nobody else to cooperate with. But that only means that you will not notice now, if you violate the expectations of other authors (that might be encoded in some specification). Do you know whether there is a specification that describes what you can and cannot do with PCR7? I'll be on vacation for the rest of the week, so further discussion probably has to be moved to next week. |
TPM-specific knowledge somewhere on a lower layer (clevis in this case?), so that not every application author has to read the obscure TPM specifications (or blindly copy the algorithm from another application). Yes, I get your point and I don't say that I disagree with you. I'm just not sure if clevis is supposed to only provide mechanisms and let users define the policies or also have some built-in policies, like your "seal-against-current-secure-boot-state" example. I'll let @npmccallum comment on this.
I was talking about the "user with access to both the disk and TPM2 after boot" case. One option I can think of is to extend the PCR7 with a pre-defined hash (i.e: all 0) after the LUKS volume is unlocked. That way someone who gets access to both the sealed data and the TPM2, won't be able to unseal the secret after the system was booted. But users will still be able to seal other data against that current PCR state, since the PCR7 digest will always be extended with the same value (hash on boot + 0s).
Well, the point of having the key sealed against the TPM2 and not in plain text is to bind the disk to the machine. If it was in plain text, then someone that steals the disk (or VM image) could just unlock it.
Correct, I assume that either one can access the TPM2 (because not only root can execute commands) or the sealed key (because the disk is stolen) but never both.
That's true. But the advantage of the TPM2 is that it will already be present in most machines and also users don't have to plug it on boot. If a security mechanism depends on user to plug a device each time they need to boot a machine, most likely will fail due being hard to use. I think the TPM2 is a good trade off between security and easy of use.
I see, you are making a very good point and I've to admit that I haven't given a lot of thinking to this yet. But I think that the TPM2 being a sensitive shared resource, most applications using it should be trusted. be encoded in some specification). Do you know whether there is a specification that describes what you can and cannot do with PCR7? The most official documentation that I know of is this from Microsoft and is what follows shim.
No worries, enjoy your vacation. This is blocked on a new release of the tpm2-tools anyways, so we have time to discuss these issues and further refine the implementation if needed. I should also go on paternity leave soon (depending on when the baby decides to arrive), so I may become less active for a couple of weeks. Thanks, again! |
One thing we need to do in this patch is clearly define the threat model and what attacks we cannot protect against. This needs to be meticulously documented in the man page. |
@npmccallum yes, I've been thinking about this. I was wrongly focused on the LUKS volume unlock case, but that's just a particular case of a more general one. Basically, what clevis assumes is that the attacker doesn't have access to the TPM2. On encryption, a JWK is created, the data is encrypted with the JWK and the JWK is encrypted with the TPM2. Both the ciphertext and the wrapped JWK are stored in the JWE. On decryption, both the ciphertext and the wrapped JWK are taken from the JWE and the TPM2 is used to decrypt the JWK which in turn is used to decrypt the ciphertext. So the assumption is that the attacker won't have access to both the JWE and the TPM2. This assumption is not only true for the clevis tpm2 pin but for all pins AFAICT. For example, in the tang and HTTP pins an attacker only needs access to both the JWE and the network service to decrypt the ciphertext. The assumption is that it won't have access to both. The only difference between these pins and the tpm2 one, is that the {en,de}cryption backend is local to the machine. So it must be protected from the attackers. And additional protection that the TPM2 has, is that the encrypted data could be "sealed" to a specific TPM2 PCR state. So if the current PCR state doesn't match the one specified on encryption, the data can't de decrypted even if the attacker has access to the TPM2. |
This is correct so far. The question for me is clearly delineating if/how the TPM2 can be protected. For network services this is pretty obvious (firewall, authentication, etc.). But it is much less clear for TPM. Binding against PCRs only helps if the PCRs are extended with the relevant measurements. On Linux, they aren't (yet). Further, if the measurements are all stock executables (kernel, initramfs, init, etc.) then an attacker can reproduce these measurements by booting an alternate stock OS that has different root credentials. Thus, for example, this might be useful for a root volume in initramfs since, after initramfs, recovery would be impossible. But this can't be used for non-root volumes which are unlocked after boot because an attacker would then always have access to the TPM. We need to think carefully about these cases and document the possible attacks. |
851d7a0
to
3959e1b
Compare
I think that rather than documenting all the possible attacks, what we should explain clearly is the fact that the Clevis security model relies on the fact that an attacker would not get access to both the encrypted secret and the decryption key. And that in the case of the tpm2 pin, the key es encrypted using a TPM2 chip that's always present in the machine. While for other pins, the decryption key is located externally (a remove server, a pluggable authentication device, etc). That way people can understand the limitations of the tpm2 pin an assess the risk and how to protect the TPM2 depending on their particular use case. I've rebased the commit on top of latest master and also added some comments on this line to the clevis-encrypt-tpm2 man page:
@npmccallum please let me know what you think. |
3959e1b
to
10d8a4c
Compare
I think that is good. Perhaps we should also have a separate man page that discusses the security implications of automated decryption at a high level and then overviews the unlocking methods and their specific security properties? |
@npmccallum agreed. That will be a more general man page so I think that will belong to a separate pull request as a follow-up. |
62c0294
to
a2916a9
Compare
Hi @martinezjavier, I like the idea of extending PCR7 once you've got the secret from the TPM. Have you read this article?
Do you have any idea on when the tpm2-tools release might come out? |
@RashmicaG great, thanks for your interest.
Yes, I read Matthew's article. In fact, that's from where I got the idea of extending PCR7.
The second release candidate (-rc1) of the tpm2-tools 3.0.0 was released yesterday. Hopefully the final version should be in a week or so. |
@martinezjavier Can we land -rc1 in rawhide ASAP? |
a2916a9
to
33ad317
Compare
@npmccallum the release candidates for tpm2-tss and tpm2-tools landed today in rawhide: https://src.fedoraproject.org/fork/javierm/rpms/tpm2-tss/c/f27ddf803d9962ad6ef4869e2fd5169e3e68459f |
This adds support for a Trusted Platform Module 2.0 (TPM2) clevis pin. It encrypts the JWK using a TPM2 chip, and then at decryption time the JWK is decrypted using the same TPM2 chip to allow clevis to decrypt the secret stored in the JWE. That way the ciphertext is bound to a TPM so it can only be decripted in a particular machine. Encrypting data using the tpm2 pin works the same than with other pins: $ clevis encrypt tpm2 '{}' < PT > JWE The pin has reasonable defaults for its configuration, but a different hierarchy, hash, and key algorithms can be choosen if the defaults are not suitable. Decryption also works the same than with other pins, only needs the JWE: $ clevis decrypt tpm2 < JWE > PT The public and private key pair of the encrypted JWK are stored in the JWE object, so those can be fetched at decryption time to unseal the JWK using the TPM2 chip. Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
33ad317
to
958ca83
Compare
Excellent! I will try to get this tested next week. |
@npmccallum perfect, thanks a lot for your help! Please let me know if have any issues or something isn't clear to you. |
@npmccallum did you have time to test this? |
Not yet. I'm out of the office until Jan 8th. I'll make it a priority when I get back. |
@npmccallum great, thanks a lot! And also happy new year 😃 |
@npmccallum another gentle ping on this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am testing this now.
curl \ | ||
jose \ | ||
nc | ||
|
||
dracut_need_initqueue | ||
} | ||
|
||
installkernel() { | ||
hostonly='' instmods =drivers/char/tpm |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The space after instmods
looks strange. Is it correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is.
From dracut's man page:
instmods installs one or more kernel modules in the initramfs.
can also be a whole subsystem, if prefixed with a
"="
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@npmccallum yes, as @circhioz said I took that from dracut's man page.
You can also look that other dracut modules are using it, i.e: $ grep "instmods =" /usr/lib/dracut/modules.d/ -R
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perfect! Thanks!
I tested this in the boot and non-root cases. Both work. The code looks clean. It is merged. Congratulations to everyone! Also, I've release v9, which contains primarily this change along with some minor other fixes. |
@npmccallum great, thanks a lot for your help! |
This adds support for a Trusted Platform Module 2.0 (TPM2) clevis pin.
It encrypts the JWK using a TPM2 chip, and then at decryption time the
JWK is decrypted using the same TPM2 chip to allow clevis to decrypt
the secret stored in the JWE. That way the ciphertext is bound to a TPM
so it can only be decripted in a particular machine.
Encrypting data using the tpm2 pin works the same than with other pins:
$ clevis encrypt tpm2 '{}' < PT > JWE
The pin has reasonable defaults for its configuration, but a different
hierarchy, hash, and key algorithms can be choosen if the defaults are
not suitable.
Decryption also works the same than with other pins, only needs the JWE:
$ clevis decrypt tpm2 < JWE > PT
The public and private key pair of the encrypted JWK are stored in the
JWE object, so those can be fetched at decryption time to unseal the
JWK using the TPM2 chip.
Signed-off-by: Javier Martinez Canillas javierm@redhat.com