-
Notifications
You must be signed in to change notification settings - Fork 53
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 example of certify #458
Conversation
Hey! I've implemented something like this in our abstraction layer for our work on attestation in TLS, it's in my fork on the One thing to note is that the docs are a bit outdated - I've modified the exact serialisation format so it's not aligned with the WebAuthn spec anymore, but it's still pretty close. The new format is described here. If you have more questions, you can find us more easily on Slack. |
Thanks @ionut-arm - I'll join later, but no guarantees I'm in a convenient same timezone (Australia, UTC+10 here). I'm working on https://github.com/kanidm/kanidm and https://github.com/openSUSE/himmelblau where we want to have machine bound and attested certificates, which is why I'm pursuing certify. It's also the reason I was looking at HMAC for TPM binding password caches on endpoints, and the duplicable keys for the servers that replicate. Generally I try to extend my work into examples to help future users of the library too, which is why I have tried to be submitting these as I go. Funny you mention Webauthn though, because I'm the author of https://crates.io/crates/webauthn-rs |
I have a few questions if that's okay.
Generally I think while this was good to read, it's probably confused me even more 🤣 would you mind reviewing the example to help me work out what I'm actually missing here? |
Oh, apologies for that, then 😅 I'll have a look at the example (and your links above) and see if I can offer some suggestions. |
Hi! It took a bit longer than hoped for, thanks for the patience! I ran your example locally and tweaked it a bit. I got the RSA example to work by using For ECC keys, though, it was an issue on our side, for which I've raised #464 - essentially the way we populated ECC parameters was wrong. One thing that helped quite a lot in tracing the issue was using To answer some of your questions from above:
For this you'll need to read about
Nope, no requirements of that sort on the object being certified I think.
Not sure I get this one - the
As mentioned above, the first auth is for the certified key, the second for the certifying key. In our case, we keep both protected by passwords. In the cases where we do use
Activate credential is not directly related to |
Thanks for the help!
So what does the second session handle do then? 🤔
Yeah, I had been forgetting that. Worth saying that printing out the errors hasn't helped me a whole lot, especially on the TPM front, they tend not to "give much detail".
I wonder if this is where I'm getting stuck on my question of "how to show the x509 chain back to the endorsement key". Which also begs the question, can you certify directly with the endorsement key? Anyway, I've update the branch with the "working" attestation with an AK, but I still don't know how to "chain this back" to the EK for an external verifier. I also put in the latest commit an attempt to certify directly with the endorsement key, because that's what I have seen in Webauthn (I've never seen a TPM Webauthn Credential with a chain, it's always against the endorsement key (?)). |
It authenticates the attesting key :D
You generally cannot, for privacy purposes. For many platforms the EK is restricted to decryption so that it can only activate credentials. Also, the whole activate credential flow can only give one party the assurance that your AK is in the same TPM as the EK (since nothing gets signed, unlike when generating an x509 cert). That's why in our use of attestation we don't bother with the EK, we simply endorse the AK to the verifier with a pinky swear that it's a TPM key. But Keylime, for example, does implement this whole activation dance. |
Which I think I did work out later :)
Is this also needed for webauthn? I think my question is "how does the ek relate to the ak so that a provider can validate the content?" In webauthn we always get the ek cert and it signs over the collected client data hash, so I'm wondering how that works? |
Ahhh turns out some tpms have EK's that can directly sign: |
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.
Apologies, forgot to submit the review.
scheme: HashScheme::new(hash_alg), | ||
}; | ||
|
||
// ⚠️ Appears to be an invalid combination. |
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.
Will you be waiting until my PR goes in to try this out, see if it works, and update the comment?
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.
Yeah, I'll wait for that so I can fix this up :)
Okay, I've been re-reading this, looking at my code and I was still confused. I took a step back to look at how webauthn-rs verifies tpm attestations and checked the specs again. So I want to "validate" my thinking about how the flow here is working. This was pieced together from a lot of places so it could be wrong still. We have a hypothetical user machine which has a TPM. We want this machine to be part of our authentication/trust CA so the machine begins by loading it's EK object and then creating a new AK under the endorsement hierachy. The EK public and AK name are now sent to our trust CA These use TPM_MakeCredential to create a new encrypted IdObject that our TPM can load. The TPM in the user machine now loads the IdObject with ActivateCredential. This allows it access to a private key that our trust servers know and can guarantee can only exist in this TPM. The private key that was issued might also have a x509 certificate associated to it's public key, which was signed by our trust CA. Now our TPM can use the issued and loaded IdObject to certify (attest) other keys that it may create. Since the IdObject is only able to be loaded by that specific TPM, and we trust it's behaviour, we can now trust attestations the TPM produces. So the point of certify isn't to bind the EK/AK to a key. It's so that when an EK/AK are used with makeCredential/ActivateCredential and we trust those are in the TPM, we can then use that to chain our trust via certify to other objects. Does that make sense? If so, should I rework the example to show the MakeCredential / ActivateCredential process at the start and then certify after? |
Closing because I cooked the git branch somehow. |
This is the foundations of an example showing how to use "certify". However, it's worth noting that today it doesn't work because of various subtleties that I don't understand :(
It's also quite messy because there appear to be some issues around the sessions in the ak/ek abstractions.
Any advice on how to fix and improve the example would be most welcome! As well, perhaps there are some opportunities here to improve the abstractions?