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

Attestation verification through trust anchor #77

Open
rbroggi opened this issue Dec 3, 2022 · 14 comments · May be fixed by #154
Open

Attestation verification through trust anchor #77

rbroggi opened this issue Dec 3, 2022 · 14 comments · May be fixed by #154
Labels
priority/3/medium Medium Prioirty status/design In Design or Needs Design type/feature-request Feature Requests

Comments

@rbroggi
Copy link

rbroggi commented Dec 3, 2022

Description

Hello all.

After studying a bit the library and stumbling in this piece of comment, I would like to open a discussion on how could be an interesting way of supporting a trust verification using the library.
My understanding is that up to this point, the library does not export any facility for doing trust assessments on the embedded attestation certificates. I couldn't also find a convenient way through a public method to extract the embedded certificates without having to copy the whole procedure of attestation-object protocol decoding.
I'm opening this feature-request to trigger a discussion around how that could be accomplished. Here are some options that come to my mind, any others would be welcomed:

  1. Implement in the library the possibility to provide a list of trusted root certificates against which the attestation certificate could be verified.
  2. Implement in the library something like ExportAttestationCertificates method that would delegate to the client the responsibility to implement the chain-of-trust verification.
  3. Document if there is an existing mechanism to achieve that.

What are your thoughts on that? I would be happy to try to help wherever possible with some code-contributions. 😃

Thank you in advance for your work and support,
Rodrigo

Use Case

Some types of webauthn attestation verification would require verification against an RP policy. This verification is done by verifying the embedded attestation certificate against an RP-trusted set of root certificates (otherwise called a trust store).
Use cases:

  • Allow RP to filter which kinds/types of authenticators to allow. Some RPs might only want to support apple devices. Others only Yubico, and so on and so forth.
  • Check the validity and trustworthiness of the provided attestation-certificate

Documentation

No response

@rbroggi rbroggi added status/needs-triage Issues that need to be triaged. type/feature-request Feature Requests labels Dec 3, 2022
@rbroggi
Copy link
Author

rbroggi commented Dec 3, 2022

Reference for a chain-of-trust verification in go:

https://gist.github.com/devtdeng/4f6adcb5a306f2ae035a2e7d9f724d17

@james-d-elliott
Copy link
Member

Thanks for posting the FR. I think this is most likely a good move. I will take a deeper look at this area of the library to see if there is an obvious way to handle this. I believe the github.com/go-webauthn/revoke module will be useful here, and performing the chain verification is relatively straight forward.

I suspect we can just add two or three optional fields to the webauthn configuration element that are injected into the relevant areas as needed. A list of trusted device signing certificates, a list of AAGUID's, and a func used to override the default verification method.

@james-d-elliott james-d-elliott added priority/3/medium Medium Prioirty status/design In Design or Needs Design and removed status/needs-triage Issues that need to be triaged. labels Dec 5, 2022
@rbroggi
Copy link
Author

rbroggi commented Dec 5, 2022

Hey @james-d-elliott , I'm glad to hear your thoughts - my intuition was exactly the same (optional field in the Webauthn config.

@james-d-elliott
Copy link
Member

james-d-elliott commented Feb 12, 2023

Okay @rbroggi I believe that this is nearly already possible. I'll put together an example and the necessary changes to the library.

I believe we do everything needed in this section (except performing the checking against the anchor itself): https://github.com/go-webauthn/webauthn/blob/master/protocol/attestation.go#L111

@james-d-elliott
Copy link
Member

james-d-elliott commented Feb 13, 2023

Looking at the spec more closely, there are a few issues we may have to overcome:

  • ECDAA implementation (there's one in java and C that I found, none in go)
  • One of the X.509 certificates in the MDS3 blob seem to be invalid (verified in go and python, though openssl is happy with it):
    • Authentrend CA 000 (with serial number 1) for AAGUIDs (error decoding basic constraints extension CA value):
      • e1a96183-5016-4f24-b55b-e3ae23614cc6
      • d41f5a69-b817-4144-a13c-9ebd6d9254d6

@rbroggi
Copy link
Author

rbroggi commented Feb 13, 2023

Interesting findings. I will see if I can understand why that is...

@james-d-elliott
Copy link
Member

Here is the certificate in question:

-----BEGIN CERTIFICATE-----
MIIBzDCCAXGgAwIBAgIBATAKBggqhkjOPQQDAjBiMQswCQYDVQQGEwJTRTESMBAG
A1UECgwJQVRLZXlDQTAwMSIwIAYDVQQLDBlBdXRoZW50aWNhdG9yIEF0dGVzdGF0
aW9uMRswGQYDVQQDExJBdXRoZW50cmVuZCBDQSAwMDAwIBcNMTYwMjI2MDgxMTA2
WhgPMjA1MDAyMjUwODExMDZaMGIxCzAJBgNVBAYTAlNFMRIwEAYDVQQKDAlBVEtl
eUNBMDAxIjAgBgNVBAsMGUF1dGhlbnRpY2F0b3IgQXR0ZXN0YXRpb24xGzAZBgNV
BAMTEkF1dGhlbnRyZW5kIENBIDAwMDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IA
BAJcWqeCxga9KJbFO2TZdjcgrtZAgfi8TXKu+v5lcR5ceb5GJYxyoCjhueESL3dd
mMIkpGyhsEEtfFUyBwsyFVCjFjAUMBIGA1UdEwEB/wQIMAYBAQECAQAwCgYIKoZI
zj0EAwIDSQAwRgIhAMqIc/Qtr+jZbnrJB7g7W8r/DHmDe+IyFvzwpzdSrxEXAiEA
tXcixZznhcDzlnIqFqkIJRGmvL9Yr6lVoP1ZkDeqmjk=
-----END CERTIFICATE-----

@james-d-elliott
Copy link
Member

james-d-elliott commented Mar 14, 2023

Hey just touching base, I know this has taken a while (I have actually made fairly significant progress but nothing material to show). I wanted to explain why. I'm intentionally underestimating my knowledge regarding WebAuthn and FIDO2 in order to avoid issues. It's easy with such a complex spec to get things wrong. In addition and fairly unrelated I'm fairly busy with work and life, making motivation a fairly scarce resource but this will resolve itself soon or I will resolve it.

I think one of the key things I want to do here is completely rewrite this portion of the library so that users must provide a MDS3 specific interface implementation to the library, with a rudimentary implementation that satisfies basic usage (memory cached, http.Client, etc).

This would allow users to implement it in a way which has a longer life i.e. saved to disk per the FIDO Alliance recommendations or share it with auxiliary micro services relatively easily. It would also potentially allow us to provide implementers a way to have additional checks or completely replace the checking process.

@rbroggi
Copy link
Author

rbroggi commented Mar 14, 2023

Dear @james-d-elliott , your efforts and transparency are very appropriated. I also find myself in a quite busy moment and have not found the time I would like to help with this. Don't hesitate to drop some details of the rewrite intentions so I can give you feedback.

@james-d-elliott
Copy link
Member

So good news about this one @rbroggi, I made contact with the FIDO Alliance, explaining the issue and cause in detail. I did a fairly careful investigation into this and it turns out the ASN.1 DER (distinguished encoding rules) booleans were improperly encoded as ASN.1 BER (basic encoding rules) booleans instead for these particular certificates. ASN.1 DER requires booleans have a 0x00 byte when false and 0xff when true, whereas ASN.1 BER stipulates any value other than 0x00 is true (they used 0x01). From my investigation it seems this is rather common, and the error occurs in several major programming languages (Go, Rust, Python, C#).

David Turner from the FIDO Alliance has had the vendor who provided the certificate fix it and it looks like it's made it into the MDS3 blob.

@rbroggi
Copy link
Author

rbroggi commented Jul 16, 2023

So good news about this one @rbroggi, I made contact with the FIDO Alliance, explaining the issue and cause in detail. I did a fairly careful investigation into this and it turns out the ASN.1 DER (distinguished encoding rules) booleans were improperly encoded as ASN.1 BER (basic encoding rules) booleans instead for these particular certificates. ASN.1 DER requires booleans have a 0x00 byte when false and 0xff when true, whereas ASN.1 BER stipulates any value other than 0x00 is true (they used 0x01). From my investigation it seems this is rather common, and the error occurs in several major programming languages (Go, Rust, Python, C#).

David Turner from the FIDO Alliance has had the vendor who provided the certificate fix it and it looks like it's made it into the MDS3 blob.

Hey James, this sound like a deep rabbit hole! Thank you for investigating and getting to the end of it!
Since it seems to be something quite common, do you have any tips on how to easily diagnose whether a certificate could be suffering from it? This could save a huge amount of hours to many people suffering from the same issue.

@james-d-elliott
Copy link
Member

Unfortunately the only way to diagnose it is to know it's an issue and identify the field being parsed is a boolean set to a value equal to or above 0x01 and equal to or lower than 0xfe, or to figure this out. It seems OpenSSL just ignores it, many languages will show an error however which can be used to pinpoint it. Alternatively knowing that this is a seemingly common issue with ASN.1 DER due to ASN.1 BER existing is a huge help.

If I had have been more motivated I probably would have found it sooner. However this means I can probably make some progress on this particular issue.

@aseigler aseigler linked a pull request Jul 17, 2023 that will close this issue
@liuyangc3
Copy link

liuyangc3 commented Nov 12, 2023

Hi @james-d-elliott May I ask how can I transfer Credential.PublicKey(I belive it's CBOR encoded) into a DER/PEM format PublicKey? And is there any plan to implement the AuthenticatorAttestationResponse interface? thanks.

@james-d-elliott
Copy link
Member

You can use webauthncbor.Unmarshal to decode it into one of the webauthncose formats. Also AuthenticatorAttestationResponse is already implemented by the type with the same name.

If there is some element you feel is missing that would be useful then please submit a completely separate FR, or if you have questions about the library submit a discussion. This issue is for discussion related to the verification of the attestation statement via the MDS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
priority/3/medium Medium Prioirty status/design In Design or Needs Design type/feature-request Feature Requests
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants