Skip to content

Commit 1aa28fa

Browse files
committed
Add notRetired filter
1 parent 02f0529 commit 1aa28fa

File tree

2 files changed

+102
-2
lines changed

2 files changed

+102
-2
lines changed

webauthn-server-attestation/src/main/java/com/yubico/fido/metadata/FidoMetadataService.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,10 @@ public FidoMetadataServiceBuilder useBlob(@NonNull MetadataBLOBPayload blobPaylo
263263
*
264264
* <p>The default is {@link Filters#notRevoked() Filters.notRevoked()}. Setting a different
265265
* filter overrides this default; to preserve the "not revoked" condition in addition to the new
266-
* filter, you must explicitly include the condition in the few filter. For example, by using
267-
* {@link Filters#allOf(Predicate[]) Filters.allOf(Predicate...)}.
266+
* filter, you must explicitly include the condition in the new filter, for example by using
267+
* {@link Filters#allOf(Predicate[]) Filters.allOf(Predicate...)}. To add the {@link
268+
* Filters#notRetired() Filters.notRetired()} filter, use: <code>
269+
* .prefilter(Filters.allOf(Filters.notRevoked(), Filters.notRetired()))</code>.
268270
*
269271
* @param prefilter a {@link Predicate} which returns <code>true</code> for metadata entries to
270272
* include in the data source.
@@ -378,6 +380,20 @@ public static Predicate<MetadataBLOBPayloadEntry> notRevoked() {
378380
statusReport -> AuthenticatorStatus.REVOKED.equals(statusReport.getStatus()));
379381
}
380382

383+
/**
384+
* Include any metadata entry whose {@link MetadataBLOBPayloadEntry#getStatusReports()
385+
* statusReports} array contains no entry with {@link AuthenticatorStatus#RETIRED RETIRED}
386+
* status.
387+
*
388+
* @see AuthenticatorStatus#RETIRED
389+
*/
390+
public static Predicate<MetadataBLOBPayloadEntry> notRetired() {
391+
return (entry) ->
392+
entry.getStatusReports().stream()
393+
.noneMatch(
394+
statusReport -> AuthenticatorStatus.RETIRED.equals(statusReport.getStatus()));
395+
}
396+
381397
/**
382398
* Accept any authenticator whose matched metadata entry does NOT indicate a compromised
383399
* attestation key.

webauthn-server-attestation/src/test/scala/com/yubico/fido/metadata/FidoMds3Spec.scala

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,4 +1037,88 @@ class FidoMds3Spec extends AnyFunSpec with Matchers {
10371037

10381038
}
10391039

1040+
describe("The notRetired filter") {
1041+
val attestationRoot = TestAuthenticator.generateAttestationCaCertificate()
1042+
val rootCertBase64 = new ByteArray(attestationRoot._1.getEncoded).getBase64
1043+
1044+
val (goodCert, _) = TestAuthenticator.generateAttestationCertificate(
1045+
name = new X500Name("CN=Good cert"),
1046+
caCertAndKey = Some(attestationRoot),
1047+
)
1048+
1049+
val goodCertKeyIdentifier = new ByteArray(
1050+
CertificateParser.computeSubjectKeyIdentifier(goodCert)
1051+
).getHex
1052+
1053+
val aaguidRetired =
1054+
new AAGUID(ByteArray.fromHex("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
1055+
1056+
val blob: MetadataBLOBPayload =
1057+
JacksonCodecs.jsonWithDefaultEnums.readValue(
1058+
s"""{
1059+
"legalHeader" : "Kom ihåg att du aldrig får snyta dig i mattan!",
1060+
"nextUpdate" : "2022-12-01",
1061+
"no" : 0,
1062+
"entries": [
1063+
{
1064+
"aaguid": "${aaguidRetired.asGuidString()}",
1065+
"attestationCertificateKeyIdentifiers": ["${goodCertKeyIdentifier}"],
1066+
"metadataStatement": {
1067+
"aaguid": "${aaguidRetired.asGuidString()}",
1068+
"attestationCertificateKeyIdentifiers": ["${goodCertKeyIdentifier}"],
1069+
"authenticatorVersion": 1,
1070+
"attachmentHint" : ["internal"],
1071+
"attestationRootCertificates": ["${rootCertBase64}"],
1072+
"attestationTypes" : ["basic_full"],
1073+
"authenticationAlgorithms" : ["secp256r1_ecdsa_sha256_raw"],
1074+
"description" : "Test authenticator",
1075+
"keyProtection" : ["software"],
1076+
"matcherProtection" : ["software"],
1077+
"protocolFamily" : "u2f",
1078+
"publicKeyAlgAndEncodings" : ["ecc_x962_raw"],
1079+
"schema" : 3,
1080+
"tcDisplay" : [],
1081+
"upv" : [{ "major" : 1, "minor" : 1 }],
1082+
"userVerificationDetails" : [[{ "userVerificationMethod" : "presence_internal" }]]
1083+
},
1084+
"statusReports": [
1085+
{ "status": "RETIRED", "effectiveDate": "2022-02-01" }
1086+
],
1087+
"timeOfLastStatusChange": "2022-02-15"
1088+
}
1089+
]
1090+
}""".stripMargin,
1091+
classOf[MetadataBLOBPayload],
1092+
)
1093+
1094+
it("is not enabled by default.") {
1095+
val mds = FidoMetadataService.builder().useBlob(blob).build()
1096+
1097+
mds
1098+
.findTrustRoots(
1099+
List(goodCert).asJava,
1100+
Some(aaguidRetired.asBytes).toJava,
1101+
)
1102+
.getTrustRoots
1103+
.asScala should not be empty
1104+
}
1105+
1106+
it("can be enabled explicitly as a prefilter.") {
1107+
val mds = FidoMetadataService
1108+
.builder()
1109+
.useBlob(blob)
1110+
.prefilter(FidoMetadataService.Filters.notRetired())
1111+
.build()
1112+
1113+
mds
1114+
.findTrustRoots(
1115+
List(goodCert).asJava,
1116+
Some(aaguidRetired.asBytes).toJava,
1117+
)
1118+
.getTrustRoots
1119+
.asScala shouldBe empty
1120+
}
1121+
1122+
}
1123+
10401124
}

0 commit comments

Comments
 (0)