Skip to content

Commit ca5b624

Browse files
committed
Test that unknown attestation statement formats don't crash
1 parent e450626 commit ca5b624

File tree

2 files changed

+101
-14
lines changed

2 files changed

+101
-14
lines changed

webauthn-server-core/src/main/java/com/yubico/webauthn/data/AttestationType.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,5 +96,19 @@ public enum AttestationType {
9696
* @see <a href="https://www.w3.org/TR/2019/PR-webauthn-20190117/#none-attestation">§8.7 None Attestation Statement
9797
* Format</a>
9898
*/
99-
NONE
99+
NONE,
100+
101+
/**
102+
* In this case, attestation information is present but was not understood by the library.
103+
* <p>
104+
* For example, the attestation statement might be using a new attestation statement format not yet supported by the
105+
* library.
106+
* </p>
107+
*
108+
* @see <a href="https://www.w3.org/TR/2019/PR-webauthn-20190117/#sctn-attestation-types">§6.4.3. Attestation
109+
* Types</a>
110+
* @see <a href="https://www.w3.org/TR/2019/REC-webauthn-1-20190304/#defined-attestation-formats">§8. Defined
111+
* Attestation Statement Formats</a>
112+
*/
113+
UNKNOWN
100114
}

webauthn-server-core/src/test/scala/com/yubico/webauthn/RelyingPartyRegistrationSpec.scala

Lines changed: 86 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1554,15 +1554,15 @@ class RelyingPartyRegistrationSpec extends FunSpec with Matchers with ScalaCheck
15541554
step.tryNext shouldBe a [Success[_]]
15551555
}
15561556

1557-
it("Unknown attestation statement formats fail.") {
1557+
it("Unknown attestation statement formats are identified as such.") {
15581558
val steps = finishRegistration(testData = RegistrationTestData.FidoU2f.BasicAttestation.setAttestationStatementFormat("urgel"))
15591559
val step: FinishRegistrationSteps#Step14 = steps.begin.next.next.next.next.next.next.next.next.next.next.next.next.next
15601560

1561-
step.validations shouldBe a [Failure[_]]
1562-
step.validations.failed.get shouldBe an [IllegalArgumentException]
1563-
step.tryNext shouldBe a [Failure[_]]
1561+
step.validations shouldBe a [Success[_]]
1562+
step.tryNext shouldBe a [Success[_]]
1563+
step.attestationType should be (AttestationType.UNKNOWN)
1564+
step.attestationTrustPath.asScala shouldBe empty
15641565
}
1565-
15661566
}
15671567

15681568
describe("15. If validation is successful, obtain a list of acceptable trust anchors (attestation root certificates or ECDAA-Issuer public keys) for that attestation type and attestation statement format fmt, from a trusted source or from policy. For example, the FIDO Metadata Service [FIDOMetadataService] provides one way to obtain such information, using the aaguid in the attestedCredentialData in authData.") {
@@ -1619,6 +1619,17 @@ class RelyingPartyRegistrationSpec extends FunSpec with Matchers with ScalaCheck
16191619
step.tryNext shouldBe a [Success[_]]
16201620
}
16211621
}
1622+
1623+
describe("For unknown attestation statement formats") {
1624+
it("no trust anchors are returned.") {
1625+
val steps = finishRegistration(testData = RegistrationTestData.FidoU2f.BasicAttestation.setAttestationStatementFormat("urgel"))
1626+
val step: FinishRegistrationSteps#Step15 = steps.begin.next.next.next.next.next.next.next.next.next.next.next.next.next.next
1627+
1628+
step.validations shouldBe a [Success[_]]
1629+
step.trustResolver.asScala shouldBe empty
1630+
step.tryNext shouldBe a [Success[_]]
1631+
}
1632+
}
16221633
}
16231634

16241635
describe("16. Assess the attestation trustworthiness using the outputs of the verification procedure in step 14, as follows:") {
@@ -1652,6 +1663,37 @@ class RelyingPartyRegistrationSpec extends FunSpec with Matchers with ScalaCheck
16521663
}
16531664
}
16541665

1666+
describe("If an unknown attestation statement format was used, check if no attestation is acceptable under Relying Party policy.") {
1667+
val testData = RegistrationTestData.FidoU2f.BasicAttestation.setAttestationStatementFormat("urgel")
1668+
1669+
describe("The default test case") {
1670+
it("is rejected if untrusted attestation is not allowed.") {
1671+
val steps = finishRegistration(
1672+
testData = testData,
1673+
allowUntrustedAttestation = false
1674+
)
1675+
val step: FinishRegistrationSteps#Step16 = steps.begin.next.next.next.next.next.next.next.next.next.next.next.next.next.next.next
1676+
1677+
step.validations shouldBe a [Failure[_]]
1678+
step.validations.failed.get shouldBe an [IllegalArgumentException]
1679+
step.attestationTrusted should be (false)
1680+
step.tryNext shouldBe a [Failure[_]]
1681+
}
1682+
1683+
it("is accepted if untrusted attestation is allowed.") {
1684+
val steps = finishRegistration(
1685+
testData = testData,
1686+
allowUntrustedAttestation = true
1687+
)
1688+
val step: FinishRegistrationSteps#Step16 = steps.begin.next.next.next.next.next.next.next.next.next.next.next.next.next.next.next
1689+
1690+
step.validations shouldBe a [Success[_]]
1691+
step.attestationTrusted should be (false)
1692+
step.tryNext shouldBe a [Success[_]]
1693+
}
1694+
}
1695+
}
1696+
16551697
describe("If self attestation was used, check if self attestation is acceptable under Relying Party policy.") {
16561698

16571699
describe("The default test case, with self attestation,") {
@@ -1833,15 +1875,32 @@ class RelyingPartyRegistrationSpec extends FunSpec with Matchers with ScalaCheck
18331875
steps.run.isAttestationTrusted should be (false)
18341876
}
18351877

1836-
it("The test case with unknown attestation fails.") {
1878+
describe("The test case with unknown attestation") {
18371879
val testData = RegistrationTestData.FidoU2f.BasicAttestation.setAttestationStatementFormat("urgel")
1838-
val steps = finishRegistration(
1839-
testData = testData,
1840-
allowUntrustedAttestation = true,
1841-
credentialRepository = Helpers.CredentialRepository.empty
1842-
)
1843-
val result = Try(steps.run)
1844-
result.failed.get shouldBe an [IllegalArgumentException]
1880+
1881+
it("passes if the RP allows untrusted attestation.") {
1882+
val steps = finishRegistration(
1883+
testData = testData,
1884+
allowUntrustedAttestation = true,
1885+
credentialRepository = Helpers.CredentialRepository.empty
1886+
)
1887+
val result = Try(steps.run)
1888+
result shouldBe a [Success[_]]
1889+
result.get.isAttestationTrusted should be (false)
1890+
result.get.getAttestationType should be (AttestationType.UNKNOWN)
1891+
result.get.getAttestationMetadata.asScala shouldBe empty
1892+
}
1893+
1894+
it("fails if the RP required trusted attestation.") {
1895+
val steps = finishRegistration(
1896+
testData = testData,
1897+
allowUntrustedAttestation = false,
1898+
credentialRepository = Helpers.CredentialRepository.empty
1899+
)
1900+
val result = Try(steps.run)
1901+
result shouldBe a [Failure[_]]
1902+
result.failed.get shouldBe an [IllegalArgumentException]
1903+
}
18451904
}
18461905

18471906
describe("NOTE: However, if permitted by policy, the Relying Party MAY register the credential ID and credential public key but treat the credential as one with self attestation (see §6.4.3 Attestation Types). If doing so, the Relying Party is asserting there is no cryptographic proof that the public key credential has been generated by a particular authenticator model. See [FIDOSecRef] and [UAFProtocol] for a more detailed discussion.") {
@@ -1907,9 +1966,23 @@ class RelyingPartyRegistrationSpec extends FunSpec with Matchers with ScalaCheck
19071966
)
19081967

19091968
result.isAttestationTrusted should be (false)
1969+
result.getAttestationType should be (AttestationType.NONE)
19101970
result.getKeyId.getId should equal (RegistrationTestData.NoneAttestation.Default.response.getId)
19111971
}
19121972

1973+
it("accept registrations with unknown attestation statement format.") {
1974+
val testData = RegistrationTestData.FidoU2f.BasicAttestation.setAttestationStatementFormat("urgel")
1975+
val result = rp.finishRegistration(FinishRegistrationOptions.builder()
1976+
.request(request)
1977+
.response(testData.response)
1978+
.build()
1979+
)
1980+
1981+
result.isAttestationTrusted should be (false)
1982+
result.getAttestationType should be (AttestationType.UNKNOWN)
1983+
result.getKeyId.getId should equal (testData.response.getId)
1984+
}
1985+
19131986
it("accept android-key attestations but report they're untrusted.") {
19141987
val result = rp.finishRegistration(FinishRegistrationOptions.builder()
19151988
.request(request)

0 commit comments

Comments
 (0)