Skip to content

Support multiple FIDO MDS trust roots - #503

Open
emlun wants to merge 2 commits into
mds-truncate-trust-pathfrom
mds-multi-trust-root
Open

Support multiple FIDO MDS trust roots#503
emlun wants to merge 2 commits into
mds-truncate-trust-pathfrom
mds-multi-trust-root

Conversation

@emlun

@emlun emlun commented Sep 4, 2026

Copy link
Copy Markdown
Member

This will help to better work around issues like #498 in the future.

@emlun
emlun requested a review from fdennis September 4, 2026 15:33
@emlun
emlun force-pushed the mds-multi-trust-root branch from 8ed9d58 to 4a24408 Compare September 4, 2026 15:34
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

Test Results

   288 files  ± 0     288 suites  ±0   6m 0s ⏱️ ±0s
 3 405 tests +12   3 393 ✅ +12  12 💤 ±0  0 ❌ ±0 
14 592 runs  +72  14 544 ✅ +72  48 💤 ±0  0 ❌ ±0 

Results for commit 4a24408. ± Comparison against base commit d1e3f64.

♻️ This comment has been updated with latest results.

return Collections.singletonList(trustRootCertificate);
return trustAnchors.stream()
.map(TrustAnchor::getTrustedCert)
.findFirst()

@georgespalding georgespalding Sep 9, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure there is a real world scenario for this
but it looks like there's a gap that should at least be documented.

Assuming an mds blob is loaded with no x5u or x5c in the header, the first cert will be picked, despite there potentially being multiple certs in the trust anchors.

Now, in a scenario where a library user parsing an mds blob (with no x5u or x5c in the header) that has a signing cert about to expire, might try to add both the new and old signing certificate to the trust anchors, but the cert returned here will always give the first cert... (meaning the second cert will never be used)

Shouldn't this method rather return an empty list in this case?
The logic in verifyBlob would have to detect this, and instead try each trust anchor, attempting to use those directly to verify the signature without an intermediate chain.

The implementation of verifyBlob would look something like:

    final MetadataBLOBHeader header = parseResult.blob.getHeader();
    final List<X509Certificate> certChain = fetchHeaderCertChain(trustAnchors, header);
    final List<X509Certificate> leafCerts;
    if(certChain.isEmpty()) {
      leafCerts = trustAnchors.stream()
          .map(TrustAnchor::getTrustedCert)
          .collect(Collectors.toList());
    } else {
      leafCerts=Collections.singletonList(certChain.get(0));
    }
    for (final X509Certificate leafCert : leafCerts) {
            ... existing leafCert processing ... 
    }
    throw new IllegalStateException(
        "Exited without finding a certification path or failing to validate any certification path. This should be impossible, please file a bug report.");

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, thanks for the call-out! I think it's unlikely to come up in practice, so I just did an ugly placeholder solution... but you're right that we can probably do this better without too much trouble by adding some kind of retry loop for this case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants