Re: [TLS] Fwd: Re: AD review of draft-ietf-tls-dtls-connection-id-07

Benjamin Kaduk <> Sat, 24 October 2020 02:13 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id 64C813A0C04; Fri, 23 Oct 2020 19:13:30 -0700 (PDT)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -1.898
X-Spam-Status: No, score=-1.898 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id jRGUJhCiAHlg; Fri, 23 Oct 2020 19:13:28 -0700 (PDT)
Received: from ( []) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by (Postfix) with ESMTPS id 1A8303A0C06; Fri, 23 Oct 2020 19:13:27 -0700 (PDT)
Received: from ([]) (authenticated bits=56) (User authenticated as kaduk@ATHENA.MIT.EDU) by (8.14.7/8.12.4) with ESMTP id 09O2DGtN004319 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 23 Oct 2020 22:13:21 -0400
Date: Fri, 23 Oct 2020 19:13:16 -0700
From: Benjamin Kaduk <>
To: Eric Rescorla <>
Cc: Achim Kraus <>, Watson Ladd <>, Joseph Salowey <>, "" <>,
Message-ID: <>
References: <> <> <> <> <> <> <> <> <> <>
MIME-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: inline
In-Reply-To: <>
Archived-At: <>
Subject: Re: [TLS] Fwd: Re: AD review of draft-ietf-tls-dtls-connection-id-07
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: "This is the mailing list for the Transport Layer Security working group of the IETF." <>
List-Unsubscribe: <>, <>
List-Archive: <>
List-Post: <>
List-Help: <>
List-Subscribe: <>, <>
X-List-Received-Date: Sat, 24 Oct 2020 02:13:30 -0000

Hi Ekr,

Thanks for chiming in.

On Thu, Oct 15, 2020 at 08:59:43AM -0700, Eric Rescorla wrote:
> I would like to make several points here:
> - In terms of operational practice, in order for a server to
> function correctly, the CID must either be fixed-length for all
> clients that might need to be demuxed *or*
> self-describing. Otherwise, the server will not be able to determine
> the correct CID. I believe this is clear in the specification:

I am pretty sure that we all agree on this, yes...

>    Because each party sends the value in the "connection_id" extension
>    it wants to receive as a CID in encrypted records, it is possible for
>    an endpoint to use a globally constant length for such connection
>    identifiers.  This can in turn ease parsing and connection lookup,
>    for example by having the length in question be a compile-time
>    constant.  Implementations, which want to use variable-length CIDs,
>    are responsible for constructing the CID in such a way that its
>    length can be determined on reception.  Such implementations must
>    still be able to send CIDs of different length to other parties.
>    Note that there is no CID length information included in the record
>    itself.

...and thanks for the reminder about how we say so in the text already.

> This is an important space optimization and in fact was one of the
> key points in getting us to variable CIDs in QUIC, so I would not
> want to take a regression here.
> - I agree with Ben that the current construction has some awkward
> properties and that prefixing the length field would remedy that. It's
> been quite some time since we had this discussion but as I recall the
> rationale was to protect the bits on the wire as-is rather than some
> reconstructed version of them (see a number of long discussions on
> this topic), so just prefixing the CID length is also not ideal.

I think the current scheme is unfortunately using fields put together in a
rather different order than the actual bits on the wire (more below).

> - To the best of my knowledge, the ability to just disclose the
> encryption key but not the MAC key has never been part of the
> official interface of TLS -- and of course it doesn't really

I agree.

> work with many AEADs. So, anyone who is doing that is off the
> fairway and I don't think has any security guarantees (TLS aside,
> many application protocols have surprising security properties
> in this situation) With that said, we shouldn't break such uses
> unnecessarily, and it seems like there might be other negative
> side effects of the current construction.

To be clear, I'm more concerned about the "other negative side effects";
bringing up this case was just a convenient rhetorical device to attempt to
illustrate that what seems like a local cryptographic annoyance can be
parlayed into something more significant.

> So on balance, I think we should try to fix this. I'm slightly less
> enthusiastic about just swapping the length field, because I'd
> prefer to MAC the literal bytes (though perhaps we'll just have
> to live with that). However, it might be worth bikeshedding that
> some. Here's one potential alternative, though I haven't studied

Seeing you write this has served to finally hammer home for me a point that
Achim has been making for some time.  Sorry for being so dense about this,
Achim!  That is to say, if we're making any change at all, we should change
to what is unambiguously the Right Thing, not just make a fiddling change
on the margins -- there's not much difference in implementation impact, and
we can get it actually right and not have to change it again.

> struct {
>   uint8 marker = tls12_cid;
>   uint8 cid_len;
>   uint64 seq_num;
>   uint8 cid = tls12_cid;               \
>   uint16 DTLSCiphertext.version +      |  appears on wire   | non-CID MAC input
>   opaque cid[cid_len];                 /                    |
>   uint16 length_of_DTLSInnerPlaintext;                      /
> }
> This is a little goofy but it has (I think) the properties that (1) the
> bytes appear
> in the MAC in the order they appear on the wire (2) fixed-length metadata
> appears in
> the front (the seq_num already does) (3) the duplicated tls12_cid in the
> front avoids confusion with MAC input for other records.

I like (1) and (2) and agree with (3), though I'm having a little trouble
lining up your figure with the DTLSCiphertext structure, which I'll repeat
here so I'm not flipping back and forth as much:

        struct {
            ContentType special_type = tls12_cid;
            ProtocolVersion version;
            uint16 epoch;
            uint48 sequence_number;
            opaque cid[cid_length];               // New field
            uint16 length;
            opaque enc_content[DTLSCiphertext.length];
        } DTLSCiphertext;

Ah, your proposal looks more natural if I compare it to the current AEAD
"additional_data" from the -07:

#      additional_data = seq_num +
#                        tls12_cid +
#                        DTLSCipherText.version +
#                        cid +
#                        cid_length +
#                        length_of_DTLSInnerPlaintext;

If I could try to synthesize your key points (as I understand them), hewing
more strictly to the "bits on the wire" philosophy would suggest having us use:

struct {
  uint8 marker = tls12_cid;
  uint8 cid_len;
  uint8 content_type = tls12_cid;      \
  uint16 DTLSCiphertext.version;       |  appears on wire 
  uint64 seq_num; // includes epoch    |
  opaque cid[cid_len];                 /
  uint16 length_of_DTLSInnerPlaintext;

struct {
  uint8 marker = tls12_cid;
  uint8 cid_len;
  uint8 content_type = tls12_cid;      \
  uint16 DTLSCiphertext.version;       |  appears on wire 
  uint64 seq_num; // includes epoch    |
  opaque cid[cid_len];                 /
  uint16 length_of_DTLSInnerPlaintext;
  DTLSInnerPlaintext.content;          \
  DTLSInnerPlaintext.real_type;        |  entirety of DTLSInnerPlaintext
  DTLSInnerPlaintext.zeros;            /

struct {
  uint8 marker = tls12_cid;
  uint8 cid_len;
  uint8 content_type = tls12_cid;      \
  uint16 DTLSCiphertext.version;       |  appears on wire 
  uint64 seq_num; // includes epoch    |
  opaque cid[cid_len];                 /
  uint16 iv_length;
  opaque IV[iv_length];
  uint16 enc_content_length;
  opaque enc_content[enc_content_length];

(with apologies to Achim for using the 'struct' formulation that cannot
just be copied into the draft)

They all share a commmon prefix: the content-type marker, cid_len, and the
DTLSCiphertext header, and are self-framing (though, of course, the
Mac-then-Encrypt case is mostly "parse from front" except for the "parse
from back" that it inherits from DTLSInnerPlaintext).

Note that for the Encrypt-then-MAC case there are a few more deviations
from the formulation in the -07 -- I put separate length prefixes for IV
and enc_content whereas the -07 has a single "length of (IV +
DTLSCiphertext.enc_content)".  (Also, using DTLSCiphertext.enc_content like
that seems to be self-referential.)  I don't have a strong reasoning for
that offhand, but of course the IV length depends on the cipher in use,
which is a negotiated quantity, and we start using DTLSCiphertext before
both parties' Finished are confirmed, so I erred on the side of paranoia.

Any further thoughts?



> On Wed, Oct 14, 2020 at 11:12 PM Achim Kraus <> wrote:
> > Hi Ben,
> >
> > > The attack does not require that both are valid for the same peer at the
> > > same time -- the attack can still occur when the party producing the MAC
> > is
> > > induced to use the "wrong" (invalid CID) interpretation of the byte
> > stream
> > > but then the version with valid CID is presented to the party verifying
> > the
> > > MAC.
> >
> > Though I consider the CID mainly as lookup-key for the security context,
> > including the MAC_write_key for Block Ciphers or the write_key /
> > write_IV for AEAD Ciphers provides in almost all casses the protection,
> > not the cid in the MAC. The only exclusion would be, if two different
> > cids point to the same security context. With a injective cid encoding,
> > that is mitigated.
> >
> > As far as I understand your description:
> >
> > 1. The (server) peer 1 used cid "abcd" for it's encryption context.
> >
> > 2. An attacker modifies that cid "abcd" into a different cid (any
> > assumptions about that? Should it be "abcd12"? Or "ef3456"? Or no
> > special consideration?)
> >
> > 3. Then the other peer 2 uses the modified cid to place it into the
> > FINISH record and to calculate the MAC for that. The used security
> > context on peer 2 is NOT defined by that modified CID, it's defined by
> > peer 1's 5-tupel (according draft-ietf-tls-dtls-connection-id-07).
> >
> > 4. Now peer 1 will use the modified cid to
> > 4.a. lookup the security context. What is assumed as result here?
> > 4.b. calculated the MAC using the security context and modified cid
> >
> > In my opinion, the MAC verfication generally fails, if at least one
> > input is different. So either a different security context or a
> > different cid will fail the MAC verification.
> >
> > Though you say, that not both cids need to be valid for peer 1, the
> > consequence for me is, that peer 1 knows only the unmodified cid, but
> > not the modified cid. With that, peer 1 doesn't even have a security
> > context to calculate the MAC with.
> >
> > It's totally mystic to me, what you assume as attack.
> >
> > I guess, you adapt now your example. If so, would it be possible, that
> > you try to follow the above steps and show, where you deviate?
> >
> > > If the internal structure (including length encoding) of the CID is
> > > opaque to the party producing the MAC, that party cannot validate the
> > data
> > > used as input to the MAC.
> > >
> > > (Sorry for duplicating this previous paragraph here and on the github
> > > issue.)
> > >
> >
> >  From the github issue:
> >
> >  > In short, you asked me to show how having a cid-length (in a different
> >  > position than currently) will prevent an attack: the attack in
> >  > question occurs when the client is generating a (its first) MAC, not
> >  > at the time when the MAC is validated.
> >
> > I still fail to follow your description, even with that amend.
> > Would it be possible, to get more information about an attack applied on
> > the generation of a MAC (above in step 3)? Or does the effect occur in
> > an other step (maybe 4)? Which effect should be considered?
> >
> > Maybe, someone else has also an opinion about that attack or the
> > description.
> >
> > best regards
> > Achim Kraus
> >