Subject: Re: [Trans] Mutability of Certificate Signatures

From: Eran Messeri <[email-masked]>
Date: Mon, 5 Jun 2017 22:42:08 +0300

That's a known concern we've tried to address: https://trac.ietf.org
/trac/trans/ticket/92

I agree this is a sub-optimal aspect of the protocol design, and would
welcome better solutions than what we have right now. As you point out,
Andrew, this is clumsy (at best) to solve for precertificates, which is
what I expect most entries to be in a world where CT is mandatory.

I think that the suggestion to fix this by defining as misbehaviour the
presentation of an incorrectly-signed certificate chain in get-entries is
the right one.
Reasoning:
- An SCT is useless to an attacker without a valid signature over the
certificate/precertificate: The collusion described above is only harmful
if a CA an a log are compromised, and even then, all it enables is for the
CA to wash its hands of a particular certificate (which wouldn't be
accepted by TLS clients without a valid signature).
- It is pretty straightforward for a monitor to validate that all chains
presented in get-entries are valid chains.
- If we can't solve it properly for precertificates, then having different
security guarantees for different kinds of entries  would be confusing, at
best.

The upside of the change to only use the TBSCertificate + Issuer key hash
in the log entry is that it's much easier to reconstruct the input for SCT
signature validation: The same code is used for certs and precertificates.
It's also easier to reason about the two entry types since they are treated
identically.

What do you think?
Eran

On Mon, May 29, 2017 at 5:10 AM, Andrew Ayer <[email-masked]> wrote:

> In RFC6962-bis, the input to the Merkle Tree leaf hash
> includes the TBSCertificate and the hash of the issuer key.
> The certificate signature is not included in the leaf hash.
> Consequentially, it is possible for a log to alter or remove
> the signature without violating the append-only property of the log.
> The tree's root hash would remain the same, and the log could still
> produce valid inclusion proofs for the corresponding SCT.
>
> This enables the following attack: if a misissued certificate is
> included in a log, an attacker could compromise or collude with the log
> operator to alter or remove the certificate's signature. Then the log
> no longer contains cryptographic proof that the CA misissued the
> certificate.  The CA indicated by issuer_key_hash could plausibly claim
> that it didn't issue the certificate.  Meanwhile, the log operator
> could claim the invalid signature came from a submitter, and blame its
> presence on a bug in the log's certificate acceptance code, something
> which has already happened with two RFC6962 logs and was not considered
> sufficiently bad by Chrome to warrant distrust[1].
>
> Note that this problem also exists in RFC6962 with pre-certificates,
> but not with certificates as the Merkle Tree leaf hash includes the full
> certificate.
>
> This could be fixed without changing the protocol by adding language
> that says that if a log cannot produce a full (pre-)certificate with a
> valid signature that matches the TBSCertificate and issuer_key_hash in
> the Merkle Tree leaf, then it must be considered misbehavior equivalent
> to violating the append-only property.
>
> However, it seems unfortunate that we can't simply rely on the Merkle
> Tree to ensure the immutability of crucial data - that is the whole
> point of a Merkle Tree, after all.  Auditors would need to perform
> an additional, complicated step.  Furthermore, if a log has a
> legitimate bug that causes certificates with invalid signatures to be
> accepted by accident, the log would have to be distrusted.
>
> Unfortunately, we can't simply include a whole pre-certificate in
> the Merkle Tree leaf hash, as it is impossible to reconstruct from
> the final certificate.  (We could put the pre-certificate signature in
> an extension in the final certificate, but that seems undesirable.)
>
> Any thoughts?  Since this is a correctness issue, I think it needs a
> resolution before RFC6962-bis is finalized.
>
> Regards,
> Andrew
>
> [1] https://groups.google.com/a/chromium.org/forum/#!topic/ct-
> policy/Itoq0YUZTlA
>
> _______________________________________________
> Trans mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/trans
>

---

From: Andrew Ayer <[email-masked]>
Date: Tue, 6 Jun 2017 10:00:22 -0700

On Mon, 5 Jun 2017 22:42:08 +0300
Eran Messeri <[email-masked]> wrote:

> I think that the suggestion to fix this by defining as misbehaviour
> the presentation of an incorrectly-signed certificate chain in
> get-entries is the right one.
> Reasoning:
> certificate/precertificate: The collusion described above is only
> harmful if a CA an a log are compromised, and even then, all it
> enables is for the CA to wash its hands of a particular certificate
> (which wouldn't be accepted by TLS clients without a valid signature).
> - It is pretty straightforward for a monitor to validate that all
> chains presented in get-entries are valid chains.
> - If we can't solve it properly for precertificates, then having
> different security guarantees for different kinds of entries  would
> be confusing, at best.
> 
> The upside of the change to only use the TBSCertificate + Issuer key
> hash in the log entry is that it's much easier to reconstruct the
> input for SCT signature validation: The same code is used for certs
> and precertificates.

You raise a good point: since there are far more TLS clients than
monitors, it makes more sense to fix this problem by adding complexity
to monitors than to TLS clients.  So I agree that defining this as
misbehavior and having monitors check is the right solution.

Let's make sure we agree what monitors need to check for certificates
(mutatis mutandis for precertificates):

1. The tbs_certificate in the x509_entry_v2 TransItem structure returned
by get-entries must be byte-for-byte identical to the TBSCertificate
portion of the leaf_certificate in the corresponding X509ChainEntry
structure returned by get-entries.

2. The issuer_key_hash in the x509_entry_v2 TransItem structure returned
by get-entries must correspond to the public key of the issuer of the
leaf_certificate in the corresponding X509ChainEntry structure returned
by get-entries.

3. The signature of the leaf_certificate in the X509ChainEntry
structure returned by get-entries must be a valid signature from the
key of its issuer.

How should a monitor get the issuer public key to perform checks 2 and
3? The obvious way is to look at the first item in the X509ChainEntry's
certificate_chain if the certificate is not self-signed, and at the
certificate itself if it is self-signed.

Unfortunately, if the logged certificate is a non-self-signed trust
anchor accepted by the log, then certificate_chain is empty and there
is no way to get the issuer public key.  So a log could evade
responsibility by making the certificate with a mutated signature a
trust anchor.

The inability to always get the issuer public key has been an
inconvenience for me when monitoring RFC6962 logs. Sometimes I end up
with a certificate and all I know about its issuer is its subject, when
ideally I would like to know its public key as well (since a CA is
uniquely identified by its subject and public key).  (I suspect crt.sh
has the same problem, based on some weird things I've observed there.)
I previously considered this a mere inconvenience, but now I see it as a
security problem.

I think that the TimestampedCertificateEntryDataV2 structure should
contain the full public key of the issuer instead of just its hash.
That way, monitors are guaranteed access to the issuer public key, and
it's easy to get.  Step 2 above could be eliminated, and step 3 becomes
simpler (no need to parse the issuer certificate to extract the public
key).

Thoughts?

Regards,
Andrew

---

From: Eran Messeri <[email-masked]>
Date: Tue, 6 Jun 2017 18:27:51 +0100

> structure returned by get-entries.
Correct.

> leaf_certificate in the corresponding X509ChainEntry structure returned
Correct.

> structure returned by get-entries must be a valid signature from the
Correct.

> certificate itself if it is self-signed.
Yes, the chain must be valid, so the first item in the chain (after the
logged leaf) should be the issuer certificate.

> responsibility by making the certificate with a mutated signature a
Correct - but then the monitor should be able to verify it was a trust
anchor at the point it was logged (maybe the output of get-trust-anchors
should  be signed?).

> I previously considered this a mere inconvenience, but now I see it as a
Could you elaborate? Is that a security problem from a CT perspective - as
in, could enable a log to avoid responsibility for something it logged, or
from a WebPKI perspective, where some certificates can be in circulation
but their issuer unknown?
I'm trying to better understand under which circumstances such certificates
would end up in the log - when would a log add a non-self-signed
certificate as a trust anchor?

---

From: Andrew Ayer <[email-masked]>
Date: Tue, 6 Jun 2017 10:39:10 -0700

On Tue, 6 Jun 2017 18:27:51 +0100
Eran Messeri <[email-masked]> wrote:

> [...]
> > anchor accepted by the log, then certificate_chain is empty and
> > there is no way to get the issuer public key.  So a log could evade
> anchor at the point it was logged (maybe the output of
> get-trust-anchors should  be signed?).

Could you elaborate?  How does the monitor being able to verify it was
a trust anchor at time of logging help?  Regardless, the monitor is
unable to perform checks 2 and 3 if it can't get the issuer public key,
and so the attack which started this email thread can still be performed.

> > inconvenience for me when monitoring RFC6962 logs. Sometimes I end
> > up with a certificate and all I know about its issuer is its
> > subject, when ideally I would like to know its public key as well
> > (since a CA is uniquely identified by its subject and public key).
> > (I suspect crt.sh has the same problem, based on some weird things
> > I've observed there.) I previously considered this a mere
> > inconvenience, but now I see it as a security problem.
> >
> Could you elaborate? Is that a security problem from a CT perspective
> - as in, could enable a log to avoid responsibility for something it
> logged, or from a WebPKI perspective, where some certificates can be
> in circulation but their issuer unknown?

I mean from the CT perspective: that is, the log can still perform
the attack we're trying to prevent.

> I'm trying to better understand under which circumstances such
> certificates would end up in the log - when would a log add a
> non-self-signed certificate as a trust anchor?

I don't know, but I have seen such certificates added as "roots" in
existing RFC6962 logs.  It's also interesting that RFC6962-bis changed
the language from "root" to "trust anchor" which suggests this
practice was intended to be explicitly supported.  What was the motivation
behind this language change?  It would certainly fix the problem if
trust anchors were required to be roots - that is, self-signed.

Regards,
Andrew

---

From: Rob Stradling <[email-masked]>
Date: Wed, 7 Jun 2017 14:35:05 +0100

On 06/06/17 18:39, Andrew Ayer wrote:
<snip>
> behind this language change?

https://trac.ietf.org/trac/trans/ticket/102

-- 
Rob Stradling
Senior Research & Development Scientist
COMODO - Creating Trust Online