Re: [MLS] MLSPlaintext packets aren't authenticated using symmetric key schedule

Richard Barnes <rlb@ipv.sx> Tue, 25 August 2020 19:04 UTC

Return-Path: <rlb@ipv.sx>
X-Original-To: mls@ietfa.amsl.com
Delivered-To: mls@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id 8EF3A3A0840 for <mls@ietfa.amsl.com>; Tue, 25 Aug 2020 12:04:34 -0700 (PDT)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: 0.004
X-Spam-Level:
X-Spam-Status: No, score=0.004 tagged_above=-999 required=5 tests=[DKIM_SIGNED=0.1, DKIM_VALID=-0.1, HTML_MESSAGE=0.001, SPF_HELO_NONE=0.001, SPF_NONE=0.001, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=ipv-sx.20150623.gappssmtp.com
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 6Dh3Z0qEByjR for <mls@ietfa.amsl.com>; Tue, 25 Aug 2020 12:04:30 -0700 (PDT)
Received: from mail-qk1-x72e.google.com (mail-qk1-x72e.google.com [IPv6:2607:f8b0:4864:20::72e]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 781A23A083F for <mls@ietf.org>; Tue, 25 Aug 2020 12:04:30 -0700 (PDT)
Received: by mail-qk1-x72e.google.com with SMTP id z3so7755277qkz.7 for <mls@ietf.org>; Tue, 25 Aug 2020 12:04:30 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ipv-sx.20150623.gappssmtp.com; s=20150623; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=ES7FkKmTb1zeBgbtPaX9gam5c1ubG4T/UGzvfbU/WtQ=; b=YMT3IGP+uQCsxQZYo9WNSAyyMGTEoRcI3xFeBG61nsyZY+r8BCyZpsd52S9ctMs3Px Njh11ubQZAj4N4Xsy1bmv548VPd/aEzJ8VZA4LGcpVECbPEtlZiOqtywLAwIrofUYKef /4GcARn/rYSHXm5W2MBYRT7Nwvd7JCCQ6UNZmGOOkJSzdPoaL+zqdgQgWnPAE8t768L+ 5XDgjTle3HJVxnwFIu3YD+dyHttRma4lXhusNAj7phXq8nWiTib81d8SkTKkrUR23vKo FsV3rAlXFTDirEb61XQGZygKQWV/I6AKuitRNAUpx9TucS/z4zXyi86cQStVC16y/wmh +KuQ==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=ES7FkKmTb1zeBgbtPaX9gam5c1ubG4T/UGzvfbU/WtQ=; b=bVdh2F7nZghixV9kcF7kKPx1gZxAX4kbs4yAT8z/LdkgxdPqtQtUS33wLAJUyyeLKl aarR2Co5NSbyvZIKAsf55fp2O/9RvwzdwgKOEXjdPIHjKS/NJagF1QYtful5hq/4BzCo 8wWrTgZmeQYIIYoKGbNA2KkndQEdb1xzJIMkJFTjoAb9IXEm7gelfDOKJRhgda5Hek4a Apl9ZIYGW8wGmXnJ3HqpEF/dehkaQ/7Z/WBkXu9hGVIY1E9V6iKt+0+3foox/XVBRzh3 754S/feEaQUcGlw7y2NTt6whEqoI2TNRvz1+TABmsBxhh2UXXGigJP5eu5EWAomIPej5 5pZA==
X-Gm-Message-State: AOAM531s5zaeJavGZoPyO2k4AJOTkM+9+Lhaas2O1GUT5Okx5IcWh7nc soirgoWEeV8UA8q7s0ItHGnLiR+vSpDyQBwkt2hdMA==
X-Google-Smtp-Source: ABdhPJwt/6MXfmg/LbXhF1l3KkNhBECqI0Qdewjcxwwx9ehGcizZvs+N7IRtF8tHVAY5MgFQMp5oMxQqam6oKa2Ecmg=
X-Received: by 2002:a37:84d:: with SMTP id 74mr10608907qki.490.1598382268890; Tue, 25 Aug 2020 12:04:28 -0700 (PDT)
MIME-Version: 1.0
References: <7d7283b6-8c70-d045-81c2-f552219869ad@wickr.com> <F5B1E029-D8B4-4BEA-BF7A-CDD531D662BD@wire.com> <CAL02cgRTtZp+gHKA0hXxxEn_L6SWRRTJa-U+bhQUhpvM8qZ+Cg@mail.gmail.com> <87d72ad5-dce9-18f7-f1c4-7a8317fd0739@wickr.com> <30DD617C-A8A8-4801-A62A-43A722B1B597@wire.com> <CAL02cgTo8CXNt26XKGrMo1vU-n6M88YtoJ4cqdxrvpyWaX1VNA@mail.gmail.com> <f4e7ea74-d368-154c-72ee-8d70b30235d2@wickr.com> <CAL02cgTbQ+cirgAGdpH4=c=Yv4X=vHqik1NQ3hHxeRC=L2Uc4Q@mail.gmail.com> <26970E9E-6EED-46D5-BD5D-8E1ADB40A93F@wire.com> <1bd2268c-7f27-e24a-bcd7-3192afae13c9@wickr.com> <CAL02cgQg3spXsDfAhfrXpQ8Bd3L0Z3k0QKRwdEKp7=66dbVz-A@mail.gmail.com> <5E549D21-1DE7-4F55-9EC6-A64128957950@wire.com>
In-Reply-To: <5E549D21-1DE7-4F55-9EC6-A64128957950@wire.com>
From: Richard Barnes <rlb@ipv.sx>
Date: Tue, 25 Aug 2020 15:03:58 -0400
Message-ID: <CAL02cgQm2i5db6cQFHjV33vpqOBCk0TE3NCr-n7benryjUFdBQ@mail.gmail.com>
To: Raphael Robert <raphael@wire.com>
Cc: Joel Alwen <jalwen@wickr.com>, Messaging Layer Security WG <mls@ietf.org>
Content-Type: multipart/alternative; boundary="0000000000005a626a05adb85fc1"
Archived-At: <https://mailarchive.ietf.org/arch/msg/mls/Ugf1K4GSjel3B1pFqdapZ6OjcEs>
Subject: Re: [MLS] MLSPlaintext packets aren't authenticated using symmetric key schedule
X-BeenThere: mls@ietf.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: Messaging Layer Security <mls.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/mls>, <mailto:mls-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/mls/>
List-Post: <mailto:mls@ietf.org>
List-Help: <mailto:mls-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/mls>, <mailto:mls-request@ietf.org?subject=subscribe>
X-List-Received-Date: Tue, 25 Aug 2020 19:04:35 -0000

To close the loop on context: As mentioned on the call, the content of the
GroupContext is public, so it shouldn't interfere with the DS verifying
signatures.

After the discussion on the interim call today, I made two updates to this
PR:
1. Use an explicit MAC and separate keys
https://github.com/mlswg/mls-protocol/pull/396/commits/10e1ba799e44a7e858d7832ec5c6c39bd214010a
2. Have the membership MAC cover the signature
https://github.com/mlswg/mls-protocol/pull/396/commits/52a06e4021d654c60afea85681f4cb2c91bd05f1

We didn't really close on the latter change on the call, but it seems like
it adds a bit more rigidity than the parallel MAC-and-Sign construction we
had before, and makes things more parallel to MLSCiphertext.  (Puts me in
mind of the encrypt-then-MAC / MAC-then-encrypt / encrypt-and-MAC
discussions of yore.)

On Fri, Aug 21, 2020 at 5:49 AM Raphael Robert <raphael@wire.com> wrote:

> Thanks Richard, I think this now meets all requirements as such. However,
> I stumbled upon the (group) context field that is already in
> MLSPlaintextTBS. Wouldn’t this
>
> a) mean that the server cannot verify a signature of a member, since the
> group context is not known outside of the group?
> b) address Joel’s concerns in the first place?
>
> I’m a bit confused as to what the intention was initially when we
> introduced that. Right now it doesn’t seem to serve any extra purpose and I
> think we could remove it.
>
> Raphael
>
> On 20 Aug 2020, at 20:55, Richard Barnes <rlb@ipv.sx> wrote:
>
> On Thu, Aug 20, 2020 at 10:20 AM Joel Alwen <jalwen@wickr.com> wrote:
>
>> Yeah, good point. While I'm not sure every case of server inspection would
>> require checking sigs on packets I am sure it would be useful for some
>> cases.
>>
>> > The obvious fix is to include the membership_token in MLSPlaintext as
>> well.
>>
>> Yup, I'm all for it. (Or at least for making it an optional field in that
>> struct.)
>>
>
> The PR has been updated.  There is now a member_token field before the
> signature, which non-member senders set to zero length.
>
> https://github.com/mlswg/mls-protocol/pull/396/files
>
> Note that this allows the server to verify the signature, but the
> membership_token is opaque to it; the server can't authenticate the
> sender's membership.
>
> --Richard
>
>
>>
>> - Joël
>>
>> On 19/08/2020 09:24, Raphael Robert wrote:
>> > I thought about this some more and now I’m not sure that the
>> membership_token
>> > should only be implicit:
>> >
>> > The whole reason for HS messages to not be encrypted is that they can be
>> > inspected along the way by an external party (e.g. the Delivery
>> Service). If
>> > this is not a requirement, MLSCiphertext should really be used instead.
>> > Hiding the membership_token from external inspector means the inspector
>> can not
>> > verify the signature anymore. I think that defies the point of HS
>> messages being
>> > inspectable.
>> >
>> > The obvious fix is to include the membership_token in MLSPlaintext as
>> well.
>> >
>> > Raphael
>> >
>> >> On 18 Aug 2020, at 21:01, Richard Barnes <rlb@ipv.sx <mailto:
>> rlb@ipv.sx>> wrote:
>> >>
>> >> Here ya go: https://github.com/mlswg/mls-protocol/pull/396
>> >>
>> >> On Tue, Aug 18, 2020 at 1:30 PM Joel Alwen <jalwen@wickr.com
>> >> <mailto:jalwen@wickr.com>> wrote:
>> >>
>> >>     > Joël, do you want to write a PR?  If not, I could probably get
>> to it in the
>> >>     > next couple days.
>> >>
>> >>     Thanks. :-) If you could that would be really nice.
>> >>
>> >>     - Joël
>> >>
>> >>     On 18/08/2020 19:20, Richard Barnes wrote:
>> >>     > Sounds like we're converging here.  The only question in my mind
>> is what
>> >>     goes in
>> >>     > the MAC -- seems like the easy option is probably "the remainder
>> of the
>> >>     > MLSPlaintextTBS", i.e., everything from group_id to the end.
>> That seems
>> >>     like it
>> >>     > minimizes multiple serialization:
>> >>     >
>> >>     > tbs_content = serialize(group_id, ...)
>> >>     > membership_token = KDF.Extract(confirmation_key, tbs_content)
>> >>     > tbs = group_context || membership_token || tbs_content
>> >>     >
>> >>     > So the PR would be to basically pop the context off of
>> MLSPlaintextTBS
>> >>     and add
>> >>     > the three lines above (with the switch for internal/external in
>> prose).
>> >>     >
>> >>     > Joël, do you want to write a PR?  If not, I could probably get
>> to it in
>> >>     the next
>> >>     > couple days.
>> >>     >
>> >>     > --Richard
>> >>     >
>> >>     > On Tue, Aug 18, 2020 at 12:24 PM Raphael Robert <
>> raphael@wire.com
>> >>     <mailto:raphael@wire.com>
>> >>     > <mailto:raphael@wire.com <mailto:raphael@wire.com>>> wrote:
>> >>     >
>> >>     >     I think what you just described is indeed a combination of
>> option 1 & 2.
>> >>     >     It’s a MAC over the payload we want to authenticate, but it’s
>> >>     implicit and
>> >>     >     we only include it in the MLSPlaintextTBS. Or in other
>> words, we
>> >>     stripped it
>> >>     >     from MLSPlaintext because it is implicitly known to any
>> valid member
>> >>     of the
>> >>     >     group.
>> >>     >
>> >>     >     Raphael
>> >>     >
>> >>     >>     On 18 Aug 2020, at 18:16, Joel Alwen <jalwen@wickr.com
>> >>     <mailto:jalwen@wickr.com>
>> >>     >>     <mailto:jalwen@wickr.com <mailto:jalwen@wickr.com>>> wrote:
>> >>     >>
>> >>     >>     Yeah, I like Option 2 here. I like that it avoids growing
>> packet size.
>> >>     >>
>> >>     >>     One caveat though: I'd go for the MAC(...) version rather
>> than the
>> >>     >>     confirmation_key. For starters thing including
>> confirmation_key doesnt
>> >>     >>     authenticate the contents of the packet. But even if it did,
>> >>     signatures aren't
>> >>     >>     meant to hide the contents of what was signed. (Amend you
>> favorite sig
>> >>     >>     scheme to
>> >>     >>     tack on the message at the end a signature and you've still
>> got a
>> >>     secure
>> >>     >>     signature scheme. But clearly not a message hiding one.)
>> That means
>> >>     that AFAIK
>> >>     >>     neither ECDSA nor EdDSA etc. were designed or analyzed for
>> such a
>> >>     property. So
>> >>     >>     this would amount to a very non-standard use of a signature
>> schemes by
>> >>     >>     MLS. Not
>> >>     >>     saying it doesn't work for the particular sig schemes in our
>> >>     ciphersuite. But
>> >>     >>     its def. not how signatures are "meant" to be used.
>> >>     >>
>> >>     >>     But that leaves Option 2 with, say, including tag =
>> MAC(conf_key,
>> >>     >>     conf_trans_hash || MLSPlaintext.content) into whats being
>> signed
>> >>     which I like
>> >>     >>     and think gets the job done. Both conf_* values are taken
>> from the
>> >>     current
>> >>     >>     epoch. By MLSPlaintext.content I mean whats now called
>> MLSPlaintextTBS.
>> >>     >>
>> >>     >>>     I would propose that we do need something additional on
>> Commit
>> >>     messages as
>> >>     >>>     well as Proposals.
>> >>     >>
>> >>     >>     @Richard: For Proopsals I think this works. Is that about
>> what you
>> >>     had in mind
>> >>     >>     for commits too?
>> >>     >>
>> >>     >>     - Joël
>> >>     >>
>> >>     >>
>> >>     >>     On 18/08/2020 17:26, Richard Barnes wrote:
>> >>     >>>     Thanks for pointing this out, Joël.  I agree that the
>> attacks you're
>> >>     >>>     describing
>> >>     >>>     should work as things are currently specified.  And
>> they're salient,
>> >>     >>>     especially
>> >>     >>>     the "replace Alice in the group" one.
>> >>     >>>
>> >>     >>>     Also agree with Raphael is correct that Commit is not
>> affected by
>> >>     this, since
>> >>     >>>     someone who is not a member won't be able to generate the
>> right
>> >>     confirmation
>> >>     >>>     value.  However, I don't think this is actually the right
>> design
>> >>     to adopt
>> >>     >>>     for a
>> >>     >>>     general solution to this problem.  Confirmation verifies
>> group
>> >>     membership
>> >>     >>>     *after* processing the handshake message; the point here
>> is that we
>> >>     >>>     should also
>> >>     >>>     have a membership check *before* processing handshake
>> messages.  In
>> >>     >>>     particular,
>> >>     >>>     I would propose that we do need something additional on
>> Commit
>> >>     messages
>> >>     >>>     as well
>> >>     >>>     as Proposals.
>> >>     >>>
>> >>     >>>     Thinking about solutions here, a couple of options come to
>> mind:
>> >>     >>>
>> >>     >>>     1. Use MLSCiphertext, but with an integrity-only
>> encapsulation
>> >>     >>>     2. Incorporate in the signature something that is only
>> known to
>> >>     the group
>> >>     >>>     (e.g.,
>> >>     >>>     confirmation_key or MAC(confirmation_key;
>> confirmed_transcript_hash ||
>> >>     >>>     Proposal/Commit))
>> >>     >>>
>> >>     >>>     Option (1) has the appeal that you would only ever send
>> >>     MLSCiphertext, though
>> >>     >>>     switching between encrypted/not could be problematic.
>> Option (2)
>> >>     seems a lot
>> >>     >>>     more appealing: It doesn't add any overhead, since the
>> >>     group-secret value
>> >>     >>>     doesn't need to be sent.  And we already switch between the
>> >>     signature context
>> >>     >>>     that is added for group members vs. external.  In fact, I
>> think option
>> >>     >>>     (2) would
>> >>     >>>     just amount to a one-line change to include an extra,
>> secret value
>> >>     in the
>> >>     >>>     context at the top of the MLSPlaintextTBS struct.
>> >>     >>>
>> >>
>> https://github.com/mlswg/mls-protocol/blob/master/draft-ietf-mls-protocol.md#content-signing-and-encryption
>> >>     >>>
>> >>     >>>     The only thing that seems odd about (2) is overloading
>> signature
>> >>     >>>     verification in
>> >>     >>>     that way, i.e., using the ability to generate a signature
>> over a
>> >>     secret
>> >>     >>>     thing to
>> >>     >>>     prove you know the secret thing.  That doesn't seem
>> obviously
>> >>     flawed to
>> >>     >>>     me, but
>> >>     >>>     worth thinking about.
>> >>     >>>
>> >>     >>>     Does that make sense to folks?
>> >>     >>>
>> >>     >>>     --Richard
>> >>     >>>
>> >>     >>>
>> >>     >>>     On Tue, Aug 18, 2020 at 10:55 AM Raphael Robert
>> >>     >>>     <raphael=40wire.com@dmarc.ietf.org <mailto:
>> 40wire.com@dmarc.ietf.org>
>> >>     >>>     <mailto:raphael <mailto:raphael>=40wire.com@dmarc.ietf.org
>> >>     <mailto:40wire.com@dmarc.ietf.org>> <mailto:
>> 40wire.com@dmarc.ietf.org
>> >>     <mailto:40wire.com@dmarc.ietf.org>>>
>> >>     >>>     wrote:
>> >>     >>>
>> >>     >>>        Hi Joel,
>> >>     >>>
>> >>     >>>        For context: this would only apply when applications
>> use cleartext
>> >>     >>>        MLSPlaintext for HS messages. The recommendation is
>> still to
>> >>     encrypt them
>> >>     >>>        and send them around as MLSCiphertext.
>> >>     >>>        That being said, we said we would like to support
>> scenarios
>> >>     where HS
>> >>     >>>        messages are not necessarily encrypted.
>> >>     >>>
>> >>     >>>        Question: would this attack work with Commit messages?
>> I’m
>> >>     thinking that
>> >>     >>>        they would be rejected because the attacker cannot
>> compute the
>> >>     >>>     confirmation_tag.
>> >>     >>>
>> >>     >>>        As you mention in the PS, the easy target would be
>> Proposal
>> >>     messages.
>> >>     >>>
>> >>     >>>        I’d be interested to see what exactly you would propose
>> as a
>> >>     mitigation
>> >>     >>>        mechanism.
>> >>     >>>
>> >>     >>>        Raphael
>> >>     >>>
>> >>     >>>>     On 18 Aug 2020, at 16:36, Joel Alwen <jalwen@wickr.com
>> >>     <mailto:jalwen@wickr.com>
>> >>     >>>>     <mailto:jalwen@wickr.com <mailto:jalwen@wickr.com>>
>> >>     >>>        <mailto:jalwen@wickr.com <mailto:jalwen@wickr.com>>>
>> wrote:
>> >>     >>>>
>> >>     >>>>     Hey everyone,
>> >>     >>>>
>> >>     >>>>     Something thats been bugging Marta Mularczyk and Daniel
>> Jost and
>> >>     me for
>> >>     >>>>     a bit
>> >>     >>>>     now is that handshake messages sent out as MLSPlaintext
>> packets
>> >>     are only
>> >>     >>>>     authenticated using signatures, but not using the group's
>> key
>> >>     schedule. For
>> >>     >>>>     non-members that makes sense but for group members that's
>> weaker than
>> >>     >>>>     need be.
>> >>     >>>>
>> >>     >>>>     Suppose Alice is in a group using signing key pair (spk,
>> ssk). I
>> >>     corrupt
>> >>     >>>        her to
>> >>     >>>>     learn ssk. Now I loose access to her device again. Later
>> she
>> >>     generates a
>> >>     >>>>     fresh
>> >>     >>>>     key package with her same spk but a new HPKE key for her
>> leaf.
>> >>     She sends
>> >>     >>>        out and
>> >>     >>>>     update proposal for her new key package and someone
>> commits to
>> >>     the update.
>> >>     >>>>
>> >>     >>>>     Expected result: she (and the group at large) has
>> achieved PCS again.
>> >>     >>>>
>> >>     >>>>     Actual result: using her stolen ssk I can still forge a
>> new
>> >>     proposal's
>> >>     >>>        (sent as
>> >>     >>>>     MLSPlaintext packets) coming from Alice. Some things I
>> could do
>> >>     with this
>> >>     >>>        power:
>> >>     >>>>     - I can generate a new key package kp for Alice using her
>> spk and
>> >>     some
>> >>     >>>        HPKE key
>> >>     >>>>     she doesn't know. Then I forge an update proposal for
>> Alice with
>> >>     kp. If it
>> >>     >>>        gets
>> >>     >>>>     committed I've effectively kicked her out of the group.
>> >>     >>>>     - I could forge Add's and Remove's coming from Alice, so
>> I could
>> >>     trick the
>> >>     >>>>     group into thinking Alice is trying to Add my account to
>> the
>> >>     group or remove
>> >>     >>>>     some other group member.
>> >>     >>>>
>> >>     >>>>     Lemme know if I've missed something here in that
>> scenario...
>> >>     >>>>
>> >>     >>>>
>> >>     >>>>     If I didn't miss anything and the attacks really work as
>> >>     advertised then IMO
>> >>     >>>>     this is kinda weak sauce and worth avoiding if possible.
>> So to
>> >>     that end, how
>> >>     >>>>     about we modify MLS such that MLSPlaintext packets coming
>> from
>> >>     group members
>> >>     >>>>     must also be authenticated using something from the
>> application key
>> >>     >>>>     schedule.
>> >>     >>>>     Now the above attacks fail. As soon as Alice's update is
>> gets
>> >>     committed I no
>> >>     >>>>     longer know the group's key schedule and so can't forged
>> packet from
>> >>     >>>        Alice. More
>> >>     >>>>     generally, this brings the PCS guarantees when using
>> MLSPlaintexts
>> >>     >>>>     frameing in
>> >>     >>>>     line with what we're getting from MLSCiphertext packets.
>> >>     >>>>
>> >>     >>>>     Any thoughts?
>> >>     >>>>
>> >>     >>>>     - Joël
>> >>     >>>>
>> >>     >>>>
>> >>     >>>>
>> >>     >>>>     PS. For concreteness, we could probably extend the current
>> >>     mechanism for
>> >>     >>>        getting
>> >>     >>>>     concistancy (the confirmation_tag) to also provide
>> symmetric key
>> >>     >>>        authentication.
>> >>     >>>>     E.g. include most of the MLSPlaintext content into whats
>> being
>> >>     tagged by
>> >>     >>>>     confirmation_tag. That would cover the case of a commit
>> packet
>> >>     and doesn't
>> >>     >>>        even
>> >>     >>>>     grow the size of MLSPlaintext packets over the current
>> design.
>> >>     >>>>
>> >>     >>>>     For a proposal packet we could also have a
>> confirmation_tag but
>> >>     this one is
>> >>     >>>>     computed using the *current* epoch's confirmation_key and
>> >>     >>>        confirmed_transcript_hash.
>> >>     >>>>
>> >>     >>>>     _______________________________________________
>> >>     >>>>     MLS mailing list
>> >>     >>>>     MLS@ietf.org <mailto:MLS@ietf.org> <mailto:MLS@ietf.org
>> >>     <mailto:MLS@ietf.org>> <mailto:MLS@ietf.org <mailto:MLS@ietf.org>>
>> >>     >>>>     https://www.ietf.org/mailman/listinfo/mls
>> >>     >>>
>> >>     >>>        _______________________________________________
>> >>     >>>        MLS mailing list
>> >>     >>>        MLS@ietf.org <mailto:MLS@ietf.org> <mailto:MLS@ietf.org
>> >>     <mailto:MLS@ietf.org>> <mailto:MLS@ietf.org <mailto:MLS@ietf.org>>
>> >>     >>>        https://www.ietf.org/mailman/listinfo/mls
>> >>     >
>> >>
>> >
>>
>
>