I think it says something about the ambiguity that I'm not entirely sure
which interpretation you are saying is clearly the correct one, so I'm
going to discuss both. :-)

Like many extensions, RFC 8879 changes the messages that are sent over the
handshake stream, both in contents (new extensions added to ClientHello and
CertificateRequest) and in type (CompressedCertificate is sent instead of
Certificate). While it is rare that we change the message types, it's not
unheard of. For example, RFC 6066 introduced the CertificateStatus message.
When that happens, such changes are reflected in the handshake transcript.
The handshake transcript is all the messages that are sent or received over
the handshake stream, and RFC 8879 replaces the Certificate message with
the CompressedCertificate message. Thus, by the sent/received
interpretation, the transcript should include CompressedCertificate and not
Certificate.

This matches how every TLS stack I'm aware of is structured. Indeed some
handle the transcript automatically under the handshake layer and would
*only* be able to implement this version. (Ours used to be like that. We've
since gotten more flexible as a consequence of some work to control the
timing a bit better, but I suspect other stacks of our lineage are still
architectured this way.) It's also what was interoperably implemented by
multiple stacks, so practically speaking, it is the interpretation we need
to settle on.

Yes, it happens that RFC 8879's CompressedCertificate message contains a
compressed string, which uncompresses to another string formatted like a
Certificate structure (without the Handshake header[*[). And it happens
that other TLS handshake mechanisms interact with the result of that
decompression as if they saw a vanilla Certificate message, but that's all
within the handshake proper and about the handshake stream that we
transcribe. Extensions change what goes on in the handshake. RFC 8879 is
defined as a handshake-level mechanism, not a filter over the handshake
stream. (It has to be, because it needs to add an extension to CH and CR,
and correlate that to its new message.)

But then the problem is the transcript in RFC 8446 is not actually defined
in terms of what's actually sent/received over the handshake stream. It is
defined in reference to particular messages, albeit with some "..."s in
between. It also says this:

   For concreteness, the transcript hash is always taken from the
   following sequence of handshake messages, starting at the first
   ClientHello and including only those messages that were sent:
   ClientHello, HelloRetryRequest, ClientHello, ServerHello,
   EncryptedExtensions, server CertificateRequest, server Certificate,
   server CertificateVerify, server Finished, EndOfEarlyData, client
   Certificate, client CertificateVerify, client Finished.

https://www.rfc-editor.org/rfc/rfc8446#section-4.4.1:~:text=For%20concreteness%2C%20the,CertificateVerify%2C%20client%20Finished
.

Taken literally, this text would suggest that, if an extension adds or
modifies handshake messages, it's not reflected in the transcript, unless
it says otherwise. That's not what we want, both by how real
implementations work, or by the security goals of the transcript. We
*want* message
modifications to show up in the transcript by default, but the formal text
does not say this. And thus the ambiguity.

David

[*] Actually, this seems to also be a point of ambiguity. The spec says you
compress a Certificate, and the Certificate structure indeed does not have
the four-byte header. Looking at our implementation, we indeed only
compress that portion and not the header. I assume (but haven't checked)
that's what other implementations do because we'd probably have heard of an
interop issue by now. But in TLS we're sloppy enough about messages with
and without the header that it's worth being explicit.

On Wed, Feb 4, 2026 at 1:17 AM Nico Williams <[email protected]> wrote:

> On Fri, Jan 30, 2026 at 12:46:40PM +0900, Kazu Yamamoto (山本和彦) wrote:
> > But RFC 8879 says:
> >
> >    After decompression, the Certificate message MUST be processed as
> >    if it were encoded without being compressed.
>
> In my opinion the quoted text is not ambiguous, and no errata is
> necessary.
>
> First, RFC 8879 does not change how TLS 1.3 computes its transcripts.
> More on this below.
>
> Second, the quoted sentence is superfluous and unnecessary.  What
> "processing" does one do with the Certificate message?  One validates
> the certificate.  But RFC 8879 does not provide a way to validate
> compressed certificates apart from decompressing them and then
> validating them as usual.  And what other validation method could one
> design other than decompress then validate as usual?  Therefore the
> quoted sentence was never necessary: because it's obvious.
>
> Third, the next sentence in the RFC says:
>
>                                       [...].  This way, the parsing and
>    the verification have the same security properties as they would have
>    in TLS normally.
>
> but one does use "parsed" messages to compute the TLS handshake
> transcript hash.  So clearly the first sentence would not be consistent
> with any intent to change the way the transcript hash is computed.  More
> below.
>
> > I think the following original interpretation is possible for the
> > content:
> >
> >    Transcript-Hash(Handshake Context, Certificate)
>
> RFC 8879 does not change how TLS 1.3 computes its transcripts.  Nor
> should it.  And if it did it would have to be explicit about it.
>
> The point of the transcript being
>
>     Transcript-Hash(M1, M2, ... Mn) = Hash(M1 || M2 || ... || Mn)
>
> is that M1, M2, .., Mn are the N messages sent / received _as they are
> sent or received_ without any alterations.  The whole point of the
> transcript hash is to _detect alterations_.  Therefore no compression of
> any part of the handshake should alter the Transcript-Hash() function.
>
> The handshake transacript is such a critical and core design point of
> TLS that, had the Internet-Draft preceding RFC 8879 meant to alter the
> Transcript-Hash() function then surely it would never have managed WG
> consensus.
>
> Nico
> --
>
> _______________________________________________
> TLS mailing list -- [email protected]
> To unsubscribe send an email to [email protected]
>
_______________________________________________
TLS mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to