<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.19 (Ruby 3.3.3) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-kohbrok-mls-associated-parties-00" category="info" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.23.2 -->
  <front>
    <title abbrev="MLSAP">MLS Associated parties</title>
    <seriesInfo name="Internet-Draft" value="draft-kohbrok-mls-associated-parties-00"/>
    <author fullname="Konrad Kohbrok">
      <organization>Phoenix R&amp;D</organization>
      <address>
        <email>konrad.kohbrok@datashrine.de</email>
      </address>
    </author>
    <author fullname="Raphael Robert">
      <organization>Phoenix R&amp;D</organization>
      <address>
        <email>ietf@raphaelrobert.com</email>
      </address>
    </author>
    <date year="2024" month="October" day="21"/>
    <area>Security</area>
    <workgroup>Messaging Layer Security</workgroup>
    <keyword>security</keyword>
    <keyword>messaging layer security</keyword>
    <abstract>
      <?line 40?>

<t>The Messaging Layer Security (MLS) protocol allows a group of clients to
exchange symmetric keys, agree on group state and send application messages.</t>
      <t>The main purpose of an MLS group is thus to facilitate agreement on group state
and key material between the members of the group. In some cases, however, it is
useful to share agreement on the (public) group state, as well as key material
with another party that is not a full member of the group.</t>
      <t>This document describes a safe extension to do just that.</t>
    </abstract>
    <note removeInRFC="true">
      <name>About This Document</name>
      <t>
        The latest revision of this draft can be found at <eref target="https://kkohbrok.github.io/mls-associated-parties/draft-kohbrok-mls-associated-parties.html"/>.
        Status information for this document may be found at <eref target="https://datatracker.ietf.org/doc/draft-kohbrok-mls-associated-parties/"/>.
      </t>
      <t>
        Discussion of this document takes place on the
        Messaging Layer Security Working Group mailing list (<eref target="mailto:mls@ietf.org"/>),
        which is archived at <eref target="https://mailarchive.ietf.org/arch/browse/mls/"/>.
        Subscribe at <eref target="https://www.ietf.org/mailman/listinfo/mls/"/>.
      </t>
      <t>Source for this draft and an issue tracker can be found at
        <eref target="https://github.com/kkohbrok/mls-associated-parties"/>.</t>
    </note>
  </front>
  <middle>
    <?line 52?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>This document outlines a mechanism that allows an MLS group (i.e. the members
thereof) to share key material with one or more associated parties such as a
server acting as the delivery service.</t>
      <t>The mechanism provides the following properties:</t>
      <ul spacing="normal">
        <li>
          <t>All members of the group agree on the associated parties and their public key
material</t>
        </li>
        <li>
          <t>All members of the group agree on the key material shared with the associated
parties</t>
        </li>
      </ul>
      <t>The mechanism makes the following assumptions:</t>
      <ul spacing="normal">
        <li>
          <t>All associated parties keep track of the group state on a per-commit basis
including the group’s RatchetTree and GroupInfo</t>
        </li>
        <li>
          <t>All external parties publish AssociatedPartyEntries that can be retrieved by
group members to add the owner to a group as an associated party</t>
        </li>
      </ul>
    </section>
    <section anchor="overview">
      <name>Overview</name>
      <t>The mechanism sketched in this document is essentially a copy of the MLS key
schedule shared with an individual external party (with a distinct key schedule
for each such party).</t>
      <t>The key material of each epoch carries over to the previous epoch, where new key
material is injected into the key schedule with each commit.</t>
    </section>
    <section anchor="associated-party-entries">
      <name>Associated party entries</name>
      <t>Any party that wants to be eligible as an associated party to an MLS group must
publish the key material required.</t>
      <sourcecode type="tls"><![CDATA[
enum {
  reserved(0),
  published(1),
  update(2),
  (255)
} AssociatedPartyEntrySource;

struct {
  HPKEPublicKey encryption_key;
  SignaturePublicKey signature_key;
  Credential credential;
  AssociatedPartyEntrySource source;
  select (AssociatedPartyEntry.source) {
    case published:
        Lifetime lifetime;

    case update:
        struct{};
  };
} AssociatedPartyEntry

struct {
    HPKEPublicKey encryption_key;
    SignaturePublicKey signature_key;
    Credential credential;

    AssociatedPartyEntrySource source;
    select (AssociatedPartyEntryTBS.source) {
        case published:
            Lifetime lifetime;
        case update:
            struct{};
    };

    select (AssociatedPartyEntryTBS.source) {
        case published:
            struct{};

        case update:
            opaque group_id<V>;
            uint32 leaf_index;
    };
} AssociatedPartyEntryTBS
]]></sourcecode>
      <t>All published AssociatedPartyEntries MUST have their <tt>source</tt> set to
<tt>published</tt>.</t>
      <t>Published AssociatedPartyEntries can be retrieved by MLS group members for use
in AddAssociatedParty proposals as described in <xref target="managing-associated-parties"/>.</t>
      <t>Open Question: Do we want an extension version in these structs?</t>
      <t>Open Question: Do we want to support AP capabilities? That would allow us to
support AP extensions as well.</t>
    </section>
    <section anchor="managing-associated-parties">
      <name>Managing associated parties</name>
      <t>AssociatedParties of a group are listed in the AssociatedParties GroupContext
extension.</t>
      <sourcecode type="tls"><![CDATA[
struct {
  AssociatedPartyEntry associated_parties<V>;
} AssociatedParties
]]></sourcecode>
      <t>A group member can add or remove associated parties in the context of a group by
sending Add- or RemoveAssociatedParty proposals.</t>
      <sourcecode type="tls"><![CDATA[
struct {
  AssociatedPartyEntry new_party;
} AddAssociatedParty

struct {
  u32 removed_party_index;
} RemoveAssociatedParty
]]></sourcecode>
      <t>Any AssociatedPartyEntry in an AddAssociatedParty proposal MUST have <tt>source</tt>
set to <tt>published</tt>.</t>
      <t>Associated parties act as external senders and can additionally send
UpdateAssociatedParty proposals to update their own key material.</t>
      <sourcecode type="tls"><![CDATA[
struct {
  AssociatedPartyEntry updated_party;
} UpdateAssociatedParty
]]></sourcecode>
      <t>Any AssociatedPartyEntry in an UpdateAssociatedParty proposal MUST have <tt>source</tt>
set to <tt>update</tt>.</t>
      <t>When a group member commits one or more of theses proposals, the
AssociatedParties extension is updated accordingly.</t>
      <ul spacing="normal">
        <li>
          <t>The associated parties in the <tt>removed_party_index</tt>es of all
RemoveAssociatedParty proposals are removed from the <tt>associated_parties</tt> vector.</t>
        </li>
        <li>
          <t>The <tt>new_party</tt> AssociatedPartyEntry in all AddAssociatedParty proposals are
apended to the <tt>associated_parties</tt> vector.</t>
        </li>
        <li>
          <t>The AssociatedPartyEntries in the <tt>associated_parties</tt> vector of the senders
of all UpdateAssociatedParty proposals are replaced by the <tt>update_party</tt> in
the respective proposal.</t>
        </li>
      </ul>
    </section>
    <section anchor="associated-party-key-schedule">
      <name>Associated party key schedule</name>
      <t>An associated party key schedule is a key schedule that group members share with
an associated party. It follows the same pattern as the main MLS key schedule,
where fresh randomness is injected with each epoch and a secret from the old
epoch is used to seed the next. Associated party key schedules are separate for
each associated party.</t>
      <figure anchor="ap-key-schedule">
        <name>The Associated Party Key Schedule</name>
        <artset>
          <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="480" width="656" viewBox="0 0 656 480" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
              <path d="M 272,40 L 272,208" fill="none" stroke="black"/>
              <path d="M 272,240 L 272,272" fill="none" stroke="black"/>
              <path d="M 272,304 L 272,384" fill="none" stroke="black"/>
              <path d="M 272,416 L 272,448" fill="none" stroke="black"/>
              <path d="M 216,96 L 232,96" fill="none" stroke="black"/>
              <path d="M 216,160 L 232,160" fill="none" stroke="black"/>
              <path d="M 272,336 L 296,336" fill="none" stroke="black"/>
              <polygon class="arrowhead" points="304,336 292,330.4 292,341.6" fill="black" transform="rotate(0,296,336)"/>
              <polygon class="arrowhead" points="280,448 268,442.4 268,453.6" fill="black" transform="rotate(90,272,448)"/>
              <polygon class="arrowhead" points="280,384 268,378.4 268,389.6" fill="black" transform="rotate(90,272,384)"/>
              <polygon class="arrowhead" points="280,272 268,266.4 268,277.6" fill="black" transform="rotate(90,272,272)"/>
              <polygon class="arrowhead" points="280,208 268,202.4 268,213.6" fill="black" transform="rotate(90,272,208)"/>
              <polygon class="arrowhead" points="280,152 268,146.4 268,157.6" fill="black" transform="rotate(90,272,152)"/>
              <polygon class="arrowhead" points="280,88 268,82.4 268,93.6" fill="black" transform="rotate(90,272,88)"/>
              <polygon class="arrowhead" points="240,160 228,154.4 228,165.6" fill="black" transform="rotate(0,232,160)"/>
              <polygon class="arrowhead" points="240,96 228,90.4 228,101.6" fill="black" transform="rotate(0,232,96)"/>
              <g class="text">
                <text x="284" y="36">ap_init_secret_[n-1]</text>
                <text x="140" y="100">ap_commit_secret</text>
                <text x="256" y="100">KDF</text>
                <text x="304" y="100">Extract</text>
                <text x="76" y="164">ap_proposal_secret</text>
                <text x="168" y="164">(or</text>
                <text x="196" y="164">0)</text>
                <text x="256" y="164">KDF</text>
                <text x="304" y="164">Extract</text>
                <text x="276" y="228">ExpandWithLabel(.,</text>
                <text x="400" y="228">"ap_epoch",</text>
                <text x="520" y="228">GroupContext_[n],</text>
                <text x="624" y="228">KDF.Nh)</text>
                <text x="280" y="292">ap_epoch_secret</text>
                <text x="368" y="340">DeriveSecret(.,</text>
                <text x="492" y="340">"ap_exporter")</text>
                <text x="312" y="356">=</text>
                <text x="396" y="356">ap_exporter_secret</text>
                <text x="280" y="404">DeriveSecret(.,</text>
                <text x="376" y="404">"init")</text>
                <text x="280" y="468">init_secret_[n]</text>
              </g>
            </svg>
          </artwork>
          <artwork type="ascii-art"><![CDATA[
                         ap_init_secret_[n-1]
                                 |
                                 |
                                 V
         ap_commit_secret --> KDF.Extract
                                 |
                                 |
                                 V
ap_proposal_secret (or 0) --> KDF.Extract
                                 |
                                 |
                                 V
                         ExpandWithLabel(., "ap_epoch", GroupContext_[n], KDF.Nh)
                                 |
                                 |
                                 V
                           ap_epoch_secret
                                 |
                                 |
                                 +--> DeriveSecret(., "ap_exporter")
                                 |    = ap_exporter_secret
                                 |
                                 V
                           DeriveSecret(., "init")
                                 |
                                 |
                                 V
                           init_secret_[n]
]]></artwork>
        </artset>
      </figure>
    </section>
    <section anchor="injecting-randomness-with-each-commit">
      <name>Injecting randomness with each commit</name>
      <t>Whenever a group member creates a commit, it exports the <tt>associated_parties_secret</tt>
from the group’s <tt>epoch_secret</tt> (of the new epoch). The <tt>ap_exporter_secret</tt> is
then used to derive the <tt>ap_commit_base_secret</tt> for each associated party, where
<tt>context</tt> is the AssociatedPartyExportContext with <tt>ap_index</tt> as the associated
party's index in the AssociatedParties extension and <tt>ap_entry</tt> as the
associated party's AssociatedPartyEntry.</t>
      <sourcecode type="tls"><![CDATA[
associated_parties_secret =
  DeriveExtensionSecret(epoch_secret, "AP Exporter Secret")

struct {
  u32 ap_index;
  AssociatedPartyEntry ap_entry;
} AssociatedPartyExportContext

ap_commit_base_secret =
  ExpandWithLabel(associated_parties_secret, "AP Commit Base Secret",
                    context, KDF.Nh)
]]></sourcecode>
      <t>From the <tt>ap_commit_base_secret</tt>, the committer derives the <tt>ap_commit_secret</tt>
and the <tt>ap_commit_secret_id</tt>.</t>
      <sourcecode type="tls"><![CDATA[
ap_commit_secret =
  DeriveSecret(ap_commit_base_secret, "AP Commit Secret")

ap_commit_secret_id =
  DeriveSecret(ap_commit_base_secret, "AP Commit Secret ID")
]]></sourcecode>
      <t>The committer then encrypts the <tt>ap_commit_base_secret</tt> with an
AssociatedPartyCommitEncryptionContext as <tt>context</tt>, where <tt>group_context</tt> is
the context of the group's new epoch.</t>
      <sourcecode type="tls"><![CDATA[
struct {
  opaque label = "AP Commit Secret";
  GroupContext group_context;
  opaque ap_commit_secret_id<V>;
} AssociatedPartyCommitEncryptionContext;

(kem_output, ciphertext) =
  SafeEncryptWithContext(0xXXXX, external_pub, context,
                          ap_commit_base_secret)
]]></sourcecode>
      <t><tt>kem_output</tt>, <tt>ciphertext</tt> and the <tt>ap_commit_secret_id</tt> are sent as a separate
message stapled to the commit. The associated party can decrypt the ciphertext
to get the <tt>ap_commit_base_secret</tt>. Other group members receiving the commit
export the <tt>ap_commit_base_secret</tt> from the key schedule of the new epoch.</t>
      <t>Both associated party and all other group members finally derive the
<tt>ap_commit_secret_id</tt> and the <tt>ap_commit_secret</tt>. They compare the
<tt>ap_commit_secret_id</tt> to the one they received along with the ciphertext to
ensure that everyone got the same base secret. The <tt>ap_commit_secret</tt> is later
used to compute the new epoch of the associated party key schedule.</t>
      <t>TODO: We probably want a distinct WireFormat for the message with <tt>kem_output</tt>,
<tt>ciphertext and </tt>ap_commit_secret_id`. That message should also be authenticated
using a signature.</t>
      <section anchor="randomness-contributions-from-associated-parties">
        <name>Randomness contributions from associated parties</name>
        <t>Associated parties can also contribute secret key material to the shared key
schedule. An associated party can do so by sampling fresh randomness and
HPKE-encrypting it to the public key in the group’s ExternalPub GroupInfo
extension (if present). The associated party then includes the resulting HPKE
ciphertext in an AssociatedPartySecret proposal and sends it to the group. That
secret is injected into the associated party key schedule in the epoch in which
it is committed.</t>
        <sourcecode type="tls"><![CDATA[
struct {
  opaque associated_party_proposal_secret<V>;
} AssociatedPartySecret;
]]></sourcecode>
        <t>TODO: Since the <tt>ap_commit_secret</tt>s come from the MLS key schedule and any
AssociatedPartySecret proposals are included in the transcript, the group should
always be in agreement on what the AP key schedule looks like. Is additional
binding necessary by injecting something from the AP key schedule back into the
MLS key schedule?</t>
      </section>
      <section anchor="computing-a-new-key-schedule-epoch-and-exporting-secrets">
        <name>Computing a new key schedule epoch and exporting secrets</name>
        <t>In each epoch, the <tt>ap_init_secret</tt> of the previous epoch, the
<tt>ap_commit_secret</tt> of this epoch, as well as any secrets from
AssociatedPartySecret proposals are used to derive this epoch’s
<tt>ap_epoch_secret</tt> as shown in <xref target="ap-key-schedule"/>. If the associated party was
added in this epoch, the <tt>ap_init_secret</tt> of the past epoch is 0. Just like in
the MLS key schedule, the GroupContext is used as context in the operation to
derive the <tt>ap_epoch_secret</tt>.</t>
        <t>The <tt>ap_epoch_secret</tt> is used to derive two secrets: The <tt>ap_init_secret</tt> of
this epoch and the <tt>ap_exporter_secret</tt>. The former is stored until the next
epoch starts. The latter is used to seed a PPRF from which the application or
other extensions can sample further secrets, domain-separated by an
application-provided string or the extension ID.</t>
        <t>All <tt>ap_</tt>-secrets are deleted after use.</t>
      </section>
    </section>
    <section anchor="sharing-associated-party-secrets-with-new-group-members">
      <name>Sharing associated party secrets with new group members</name>
      <t>When adding new group members via Welcome messages, the current
<tt>ap_init_secret</tt>s of all associated parties are included in an
AssociatedPartySecrets GroupInfo extension, ordered per associated party
according to the <tt>associated_parties</tt> vector in the group's AssociatedParties
extension.</t>
      <sourcecode type="tls"><![CDATA[
struct {
  opaque associated_party_init_secret<V>;
} AssociatedPartySecrets
]]></sourcecode>
      <t>When a new member joins via external commit, it creates the HPKE ciphertext and
key id in the same way as a normal committer would. When deriving the secrets
for the new epoch of the associated party key schedule, the
<tt>ap_init_secret</tt> is set to 0.</t>
    </section>
    <section anchor="security-considerations">
      <name>Security Considerations</name>
      <t>TODO Security</t>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>This document registers the AssociatedParties extension with ID 0xXXXX.</t>
    </section>
  </middle>
  <back>
    <?line 370?>

<section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>TODO acknowledge.</t>
    </section>
  </back>
  <!-- ##markdown-source:
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

-->

</rfc>
