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

Cosign doesn't accept Digicert's TSA certificate when verifying a signature #3632

Open
alt-enio opened this issue Apr 1, 2024 · 1 comment
Labels
enhancement New feature or request

Comments

@alt-enio
Copy link

alt-enio commented Apr 1, 2024

Description

I signed an image including a timestamp from Digicert (using http://timestamp.digicert.com).

To verify that signature I had to get the TSA certificate that they publish. For example here (https://knowledge.digicert.com/general-information/rfc3161-compliant-time-stamp-authority-server). Cosign requires the full certificate chain and here lies the problem.

When building the chain from the certificates provided by Digicert on that page I got the following error:
Error: no matching signatures: unable to verify RFC3161 timestamp bundle: no TSA root certificate(s) provided to verify timestamp.

It appears that Digicert's Root certificate is not root enough for cosign. After debugging a bit I got to function SplitPEMCertificateChain (utils.go) which only considers that a certificate is root if it's self-signed. This is not the case for Digicert. There is a more general certificate used to sign that alleged Root certificate. Not sure if the criteria should be revised.

In Digicert's case, "Digicert Trusted Root G4" certificate is signed by "DigiCert Assured ID Root CA".

So, I included the true Root certificate in the chain.

Consequently, I got the following error:
Error: no matching signatures: unable to verify RFC3161 timestamp bundle: failed to verify EKU on leaf certificate: failed to verify EKU on intermediate certificate: certificate has 0 extended key usages, expected only one.

More debugging. I got to function verifyLeafAndIntermediatesTimestampingEKU (...go\pkg\mod\github.com\sigstore\timestamp-authority@v1.2.2\pkg\verification\verify.go) which has this comment: "Verify the leaf and intermediate certificates (called "EKU chaining") all have the extended key usage set to only time stamping usage". So, the intermediate certificates have to be set exclusively for timestamping usage. This was no longer the case with my chain because Digicert's Trusted Root G4, now turned intermediate, has more uses. Is it reasonable to require all intermediates to be set exclusively for timestamping?

So, it appears, for now, that Digicert's TSA can't be used for signing.

In my opinion, this could be fixed in one of two ways:

  • review the criteria for what is a root certificate
  • relax the exclusivity of timestamping use in intermediate certificates, especially if they are deep in the chain (IMO, this solution is more reasonable).
@alt-enio alt-enio added the enhancement New feature or request label Apr 1, 2024
@haydentherapper
Copy link
Contributor

haydentherapper commented Apr 3, 2024

Hey, this is a great question. There's a few issues at play here:

  1. We don't have a great UI around providing trusted roots (which could be self-signed "roots" or intermediates, up to the client) and chain builders (always intermediates). Right now, for timestamping, we are automatically assuming that self-signed == root.
  2. Digicert is treating what we are currently calling an intermediate as a root, which is why they have no technical constraints on Digicert Trusted Root G4
  3. We are following the CAB Forum's Server Cert baseline requirements for Subordinate CA Technical Constraints, even though we're private PKI

To approach each of these issues, we could:

  1. Fix the UI. We've discussed this in another issue. A long-term goal is to allow users to specify a trust root and to allow the trust root to contain CA pools. This would let you specify the "Digicert Trusted Root G4" as the root.
  2. No solution here under our control. I might argue that Digicert is not following best practices by issuing a root-like CA certificate off its root "DigiCert Assured ID Root CA". Also it's weird that "DigiCert Trusted G4 RSA4096 SHA256 TimeStamping CA" expires after "Digicert Trusted Root G4"...
  3. Relax the constraint like you said. We are private PKI so we don't have to follow any baseline requirements. I would still enforce the end-entity issuing CA be constrained.

Lemme think on this. I think (1) is the route we'd want to take, though given it'll take longer to implement, maybe we can add a flag to relax (3) in the meantime. We can also fix (1) by not guessing at what's a root and instead letting you specify a chain, where the first cert in the chain is the TSA cert, the last is considered the root, and all in the middle are subordinates. This aligns with the rest of the UI too.

because Digicert's Trusted Root G4, now turned intermediate, has more uses. Is it reasonable to require all intermediates to be set exclusively for timestamping?

Actually, it looks like Trusted Root G4 has no extended key usages. I only see key usages "Digital Signature, Certificate Sign, CRL Sign". So the reason it's failing is because there are no extended key usages. You are right though that we are being too strict and should allow any additional extended key usages, but given that's not the issue here, I'll hold off on relaxing this constraint because I've only seen timestamping intermediates with exactly one EKU.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants