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

TPM2 AK activation/validation seems unnecessarily complicated #98

Open
mdempsky opened this issue Sep 9, 2019 · 9 comments
Open

TPM2 AK activation/validation seems unnecessarily complicated #98

mdempsky opened this issue Sep 9, 2019 · 9 comments

Comments

@mdempsky
Copy link

mdempsky commented Sep 9, 2019

Currently TPM2 clients generate an AK and then self-certify using TPM2_Certify.

But I don't think the self-certification is currently serving any purpose:

  • TPM2_MakeCredential already guarantees that the reported TPM2_PUBLIC must correctly describes the AK, otherwise TPM2_ActivateCredential won't allow the EK to decrypt the sealed credential.
  • For the AK's self-certification to be meaningful, we have to trust that the AK is good, which is kinda begging the question.
  • TPM2_Certify could be useful if go-attestation checked any of the TPMS_ATTEST fields (e.g., clockInfo or firmwareVersion) or TPMS_CREATION_DATA fields (e.g., it could check that the AK was recently generated), but go-attestation doesn't seem to pay attention to these.

As far as I can tell, if att.AttestedCreationInfo.Name.Digest in generateChallengeTPM20 was replaced with tpm2.DecodePublic(p.AIK.Public).Name().Digest, then p.AIK.CreateData and p.AIK.CreateAttestation can be removed entirely without losing any security properties.

But maybe I'm missing something, or there are plans to eventually utilize more of the attestation data. E.g., maybe firmwareVersion is useful to log in case it's discovered that some TPM firmware versions had key generation vulnerabilities (e.g., ROCA for RSA keys, or Yubikey's FIPS RNG goofup affecting both RSA and ECC keys); though in that case, you probably need to re-generate (and re-certify) the EK too, so I'm not sure the AK is your biggest concern.

@twitchy-jsonp
Copy link
Contributor

I agree we could probably eliminate the self-certify and still get the security properties we want. A few things:

  • I implemented it this way at the beginning to mirror the behavior of the windows Platform Crypto Provider, which generates + ships a creation certification while bootstrapping.

  • We are using CertifyCreation rather than Certify, which demonstrates that the caller created the key in the same breath as when the certification was invoked (via ticket/creation hash data), or at least a certification was done within that context and then stored.

While we don't support it now, self-certification can include extra data, which can become a nonce to prove the AK was created for a specific purpose / CA (as opposed to re-using an existing AK).

I didnt plan on using the other data, as it would be obfuscated for keys not produced under the endorsement hierarchy.

@mdempsky
Copy link
Author

mdempsky commented Sep 9, 2019

I implemented it this way at the beginning to mirror the behavior of the windows Platform Crypto Provider, which generates + ships a creation certification while bootstrapping.

Interesting. Is this publicly documented anywhere, or just details reverse engineered through using it?

(I've tried looking at Microsoft's documentation about TPMs, but it often seems very high-level and abstract; I'd love if they had any detailed documentation explaining secure TPM usage that I could peruse.)

We are using CertifyCreation rather than Certify,

Oops, yes, I meant TPM2_CertifyCreation. (Wouldn't be able to trust the TPMS_CREATION_DATA otherwise!)

While we don't support it now, self-certification can include extra data, which can become a nonce to prove the AK was created for a specific purpose / CA (as opposed to re-using an existing AK).

Ack. I was considering that. I'm just not sure I can envision why the server would be concerned about AK reuse. Maybe I'm not being creative enough though.

If long-lived, reused RSA 2048 / NIST P-256 keys are a security risk, then EKs are probably about as compelling of a target as AKs. Admittedly, an attacker who successfully compromises an activated AK is one step ahead of an attacker who only compromises an EK, as the EK-attacker will first need to use the compromised EK to enroll a compromised AK. (Maybe I'm underestimating how hard this would be to do undetected.)

There's a privacy concern regarding AK reuse, but this is probably something the client has to be more concerned about rather than the server anyway. E.g., the server can't guarantee that its own AKs aren't mistakenly reused for some other purpose, nor can it prevent the client from intentionally correlating multiple AKs that it controls.

I didnt plan on using the other data, as it would be obfuscated for keys not produced under the endorsement hierarchy.

Fair point. I was assuming if you really did want/need that data, that you would just create the AK within the endorsement hierarchy, and then require appropriate endorsement authorization. But maybe that's not an option?

@twitchy-jsonp
Copy link
Contributor

Interesting. Is this publicly documented anywhere, or just details reverse engineered through using it?

(I've tried looking at Microsoft's documentation about TPMs, but it often seems very high-level and abstract; I'd love if they had any detailed documentation explaining secure TPM usage that I could peruse.)

The only documentation available that I've found is the pdf in a github repository: https://github.com/microsoft/TSS.MSR/blob/9fb1fac9ee6b7ee2dfe8040069ae68e09d948d0d/PCPTool.v11/Using%20the%20Windows%208%20Platform%20Crypto%20Provider%20and%20Associated%20TPM%20Functionality.pdf

Ack. I was considering that. I'm just not sure I can envision why the server would be concerned about AK reuse. Maybe I'm not being creative enough though.

I haven't cared enough to implement it, but my guess is a nice separation of concerns.

Fair point. I was assuming if you really did want/need that data, that you would just create the AK within the endorsement hierarchy, and then require appropriate endorsement authorization. But maybe that's not an option?

Yepp, but for windows we would need to implement delegate authorization and read the authorization value out of an undocumented registry key.

@brandonweeks
Copy link
Member

From what I can tell, with this change AK activation should be possible with just the EK certificate and AK public key on both TPM 1.2 and 2.0. Does that sound right?

@mdempsky
Copy link
Author

@brandonweeks I'm not really familiar with TPM 1.2, sorry.

But on TPM 2.0 at least, the server still needs the AK's TPM2B_PUBLIC structure (which contain's the AK's public key), since that's (1) how you compute the Name to use with TPM2_MakeCredential, and (2) how you verify that its attributes are appropriate (e.g., that it's restricted, non-exportable, and TPM-generated).

However, if the server wants to force the client to generate a new AK (which Microsoft at least seems to think is valuable, but I'm still unclear on), you need the TPM2_CertifyCreation data.

@twitchy-jsonp
Copy link
Contributor

Sorry for the delay, forgot to respond and realised when looking at a different change.

From what I can tell, with this change AK activation should be possible with just the EK certificate and AK public key on both TPM 1.2 and 2.0. Does that sound right?

No. We would need to know the version of the TPM, and whether to use the tcsd credential activation format.

While we could eliminate checking of the self-certify to simplify this flow, I'm not a huge fan of removing the requirement for the client to ship TPM2B_PUBLIC. We don't control the template that microsoft uses to create attestation keys, and they can change it any time. At least by shipping it, we can verify its sane, rather than breaking the library for any change.

@Radranic
Copy link

I've been trying to use go-attestation for the server side only, and the validation of the CertifyCreation values during the params.Generate() call is causing issues.

Your sample and the NewAK function creates a key in the storage hierarchy if I'm not mistaken. The example I'm working on (in TSS.Net) deals with a key in the Endorsement hierarchy (which is what I require) and is also a primary key, so I don't think it can't be used for the CertifyCreation call (or I'm new enough to TPM behavior that I'm making some fundamental mistakes).

Should I be able to use CertifyCreation in this case (and have issues in my client) or is what I'm trying to do incompatible with this implementation?

@twitchy-jsonp
Copy link
Contributor

twitchy-jsonp commented Oct 12, 2021

Correct on usage of the storage hierarchy. Two main reasons:

  1. Getting authorization for the endorsement hierarchy is particularly annoying/hard, especially on windows.
  2. We want the AK lifecycle to roughly match the lifecycle of the OS install, rather than the life of the device. So it makes sense for it to be under the storage hierarchy (which in theory gets reset every time the system is 'rebuilt').

Creating an AK under the endorsement hierarchy is valid. Im 90% sure that creating a restricted primary key under the endorsement hierachy is also valid.

As for your other questions, do you mind opening a new issue? It might be helpful if you can share the errors your encountering and possibly some blobs of the values of ActivationParameters? I'm not sure if what youre doing is incompatible with go-attestation at this stage.

@Radranic
Copy link

There's probably no need to make a new issue as I don't have anything for CreateAttestation or CreateSignature in the ActivationParameters as I haven't gotten CertifyCreation to work.

From the sounds of your comment I should be able to even with a primary endorsement key, so I've probably got issues on my client code. Example code I'm working from doesn't make the call and the "server side" code in the example doesn't do the same kind of validation.

Should be fine once I get that working then. Thanks.

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

No branches or pull requests

4 participants