diff --git a/webauthn-server-core/src/main/java/com/yubico/webauthn/FinishRegistrationSteps.java b/webauthn-server-core/src/main/java/com/yubico/webauthn/FinishRegistrationSteps.java index ee7cd0a0e..5a085f16d 100644 --- a/webauthn-server-core/src/main/java/com/yubico/webauthn/FinishRegistrationSteps.java +++ b/webauthn-server-core/src/main/java/com/yubico/webauthn/FinishRegistrationSteps.java @@ -487,11 +487,13 @@ public Optional trustResolver() { case SELF_ATTESTATION: return Optional.empty(); + case ATTESTATION_CA: case BASIC: switch (attestation.getFormat()) { case "android-safetynet": case "fido-u2f": case "packed": + case "tpm": return metadataService.map(KnownX509TrustAnchorsTrustResolver::new); default: throw new UnsupportedOperationException(String.format( @@ -529,6 +531,7 @@ public void validate() { assure(allowUntrustedAttestation, "Self attestation is not allowed."); break; + case ATTESTATION_CA: case BASIC: assure(allowUntrustedAttestation || attestationTrusted(), "Failed to derive trust for attestation key."); break; @@ -553,6 +556,7 @@ public boolean attestationTrusted() { case NONE: return false; + case ATTESTATION_CA: case BASIC: return attestationMetadata().filter(Attestation::isTrusted).isPresent(); default: diff --git a/webauthn-server-core/src/test/scala/com/yubico/webauthn/RegistrationTestData.scala b/webauthn-server-core/src/test/scala/com/yubico/webauthn/RegistrationTestData.scala index 6bfc8d435..c414ddabc 100644 --- a/webauthn-server-core/src/test/scala/com/yubico/webauthn/RegistrationTestData.scala +++ b/webauthn-server-core/src/test/scala/com/yubico/webauthn/RegistrationTestData.scala @@ -171,7 +171,7 @@ object RegistrationTestData { ) { override def regenerate() = TestAuthenticator.createSelfAttestedCredential(attestationStatementFormat = "packed", alg = Some(COSEAlgorithmIdentifier.RS256)) } } object Tpm { - val PrivacyCa: RegistrationTestData = Packed.SelfAttestation.editAttestationObject("fmt", "tpm") + val PrivacyCa: RegistrationTestData = Packed.BasicAttestation.editAttestationObject("fmt", "tpm") } } diff --git a/webauthn-server-core/src/test/scala/com/yubico/webauthn/RelyingPartyRegistrationSpec.scala b/webauthn-server-core/src/test/scala/com/yubico/webauthn/RelyingPartyRegistrationSpec.scala index f38062130..76fe01fdb 100644 --- a/webauthn-server-core/src/test/scala/com/yubico/webauthn/RelyingPartyRegistrationSpec.scala +++ b/webauthn-server-core/src/test/scala/com/yubico/webauthn/RelyingPartyRegistrationSpec.scala @@ -1687,19 +1687,19 @@ class RelyingPartyRegistrationSpec extends FunSpec with Matchers with GeneratorD describe("The default RelyingParty settings") { - it("accept registrations with no attestation.") { - val rp = RelyingParty.builder() - .identity(RelyingPartyIdentity.builder().id("localhost").name("Test party").build()) - .credentialRepository(emptyCredentialRepository) - .build() - - val request = rp.startRegistration(StartRegistrationOptions.builder() - .user(UserIdentity.builder().name("test").displayName("Test Testsson").id(new ByteArray(Array())).build()) - .build() - ).toBuilder() - .challenge(RegistrationTestData.NoneAttestation.Default.clientData.getChallenge) - .build() + val rp = RelyingParty.builder() + .identity(RelyingPartyIdentity.builder().id("localhost").name("Test party").build()) + .credentialRepository(emptyCredentialRepository) + .build() + + val request = rp.startRegistration(StartRegistrationOptions.builder() + .user(UserIdentity.builder().name("test").displayName("Test Testsson").id(new ByteArray(Array())).build()) + .build() + ).toBuilder() + .challenge(RegistrationTestData.NoneAttestation.Default.clientData.getChallenge) + .build() + it("accept registrations with no attestation.") { val result = rp.finishRegistration(FinishRegistrationOptions.builder() .request(request) .response(RegistrationTestData.NoneAttestation.Default.response) @@ -1710,6 +1710,17 @@ class RelyingPartyRegistrationSpec extends FunSpec with Matchers with GeneratorD result.getKeyId.getId should equal (RegistrationTestData.NoneAttestation.Default.response.getId) } + it("accept TPM attestations but reports they're untrusted.") { + val result = rp.finishRegistration(FinishRegistrationOptions.builder() + .request(request) + .response(RegistrationTestData.Tpm.PrivacyCa.response) + .build() + ) + + result.isAttestationTrusted should be (false) + result.getKeyId.getId should equal (RegistrationTestData.Tpm.PrivacyCa.response.getId) + } + } }