rfc9420.original | rfc9420.txt | |||
---|---|---|---|---|
Network Working Group R. Barnes | Internet Engineering Task Force (IETF) R. Barnes | |||
Internet-Draft Cisco | Request for Comments: 9420 Cisco | |||
Intended status: Standards Track B. Beurdouche | Category: Standards Track B. Beurdouche | |||
Expires: 28 September 2023 Inria & Mozilla | ISSN: 2070-1721 Inria & Mozilla | |||
R. Robert | R. Robert | |||
Phoenix R&D | Phoenix R&D | |||
J. Millican | J. Millican | |||
Meta Platforms | Meta Platforms | |||
E. Omara | E. Omara | |||
K. Cohn-Gordon | K. Cohn-Gordon | |||
University of Oxford | University of Oxford | |||
27 March 2023 | July 2023 | |||
The Messaging Layer Security (MLS) Protocol | The Messaging Layer Security (MLS) Protocol | |||
draft-ietf-mls-protocol-20 | ||||
Abstract | Abstract | |||
Messaging applications are increasingly making use of end-to-end | Messaging applications are increasingly making use of end-to-end | |||
security mechanisms to ensure that messages are only accessible to | security mechanisms to ensure that messages are only accessible to | |||
the communicating endpoints, and not to any servers involved in | the communicating endpoints, and not to any servers involved in | |||
delivering messages. Establishing keys to provide such protections | delivering messages. Establishing keys to provide such protections | |||
is challenging for group chat settings, in which more than two | is challenging for group chat settings, in which more than two | |||
clients need to agree on a key but may not be online at the same | clients need to agree on a key but may not be online at the same | |||
time. In this document, we specify a key establishment protocol that | time. In this document, we specify a key establishment protocol that | |||
provides efficient asynchronous group key establishment with forward | provides efficient asynchronous group key establishment with forward | |||
secrecy and post-compromise security for groups in size ranging from | secrecy (FS) and post-compromise security (PCS) for groups in size | |||
two to thousands. | ranging from two to thousands. | |||
Discussion Venues | ||||
This note is to be removed before publishing as an RFC. | ||||
Source for this draft and an issue tracker can be found at | ||||
https://github.com/mlswg/mls-protocol (https://github.com/mlswg/mls- | ||||
protocol). | ||||
Status of This Memo | Status of This Memo | |||
This Internet-Draft is submitted in full conformance with the | This is an Internet Standards Track document. | |||
provisions of BCP 78 and BCP 79. | ||||
Internet-Drafts are working documents of the Internet Engineering | ||||
Task Force (IETF). Note that other groups may also distribute | ||||
working documents as Internet-Drafts. The list of current Internet- | ||||
Drafts is at https://datatracker.ietf.org/drafts/current/. | ||||
Internet-Drafts are draft documents valid for a maximum of six months | This document is a product of the Internet Engineering Task Force | |||
and may be updated, replaced, or obsoleted by other documents at any | (IETF). It represents the consensus of the IETF community. It has | |||
time. It is inappropriate to use Internet-Drafts as reference | received public review and has been approved for publication by the | |||
material or to cite them other than as "work in progress." | Internet Engineering Steering Group (IESG). Further information on | |||
Internet Standards is available in Section 2 of RFC 7841. | ||||
This Internet-Draft will expire on 28 September 2023. | Information about the current status of this document, any errata, | |||
and how to provide feedback on it may be obtained at | ||||
https://www.rfc-editor.org/info/rfc9420. | ||||
Copyright Notice | Copyright Notice | |||
Copyright (c) 2023 IETF Trust and the persons identified as the | Copyright (c) 2023 IETF Trust and the persons identified as the | |||
document authors. All rights reserved. | document authors. All rights reserved. | |||
This document is subject to BCP 78 and the IETF Trust's Legal | This document is subject to BCP 78 and the IETF Trust's Legal | |||
Provisions Relating to IETF Documents (https://trustee.ietf.org/ | Provisions Relating to IETF Documents | |||
license-info) in effect on the date of publication of this document. | (https://trustee.ietf.org/license-info) in effect on the date of | |||
Please review these documents carefully, as they describe your rights | publication of this document. Please review these documents | |||
and restrictions with respect to this document. Code Components | carefully, as they describe your rights and restrictions with respect | |||
extracted from this document must include Revised BSD License text as | to this document. Code Components extracted from this document must | |||
described in Section 4.e of the Trust Legal Provisions and are | include Revised BSD License text as described in Section 4.e of the | |||
provided without warranty as described in the Revised BSD License. | Trust Legal Provisions and are provided without warranty as described | |||
in the Revised BSD License. | ||||
Table of Contents | Table of Contents | |||
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 5 | 1. Introduction | |||
1.1. Change Log . . . . . . . . . . . . . . . . . . . . . . . 6 | 2. Terminology | |||
2. Terminology . . . . . . . . . . . . . . . . . . . . . . . . . 15 | 2.1. Presentation Language | |||
2.1. Presentation Language . . . . . . . . . . . . . . . . . . 16 | 2.1.1. Optional Value | |||
2.1.1. Optional Value . . . . . . . . . . . . . . . . . . . 17 | 2.1.2. Variable-Size Vector Length Headers | |||
2.1.2. Variable-size Vector Length Headers . . . . . . . . . 17 | 3. Protocol Overview | |||
3. Protocol Overview . . . . . . . . . . . . . . . . . . . . . . 19 | 3.1. Cryptographic State and Evolution | |||
3.1. Cryptographic State and Evolution . . . . . . . . . . . . 21 | 3.2. Example Protocol Execution | |||
3.2. Example Protocol Execution . . . . . . . . . . . . . . . 22 | 3.3. External Joins | |||
3.3. External Joins . . . . . . . . . . . . . . . . . . . . . 26 | 3.4. Relationships between Epochs | |||
3.4. Relationships Between Epochs . . . . . . . . . . . . . . 27 | 4. Ratchet Tree Concepts | |||
4. Ratchet Tree Concepts . . . . . . . . . . . . . . . . . . . . 29 | 4.1. Ratchet Tree Terminology | |||
4.1. Ratchet Tree Terminology . . . . . . . . . . . . . . . . 30 | 4.1.1. Ratchet Tree Nodes | |||
4.1.1. Ratchet Tree Nodes . . . . . . . . . . . . . . . . . 30 | 4.1.2. Paths through a Ratchet Tree | |||
4.1.2. Paths through a Ratchet Tree . . . . . . . . . . . . 32 | 4.2. Views of a Ratchet Tree | |||
4.2. Views of a Ratchet Tree . . . . . . . . . . . . . . . . . 33 | 5. Cryptographic Objects | |||
5. Cryptographic Objects . . . . . . . . . . . . . . . . . . . . 35 | 5.1. Cipher Suites | |||
5.1. Ciphersuites . . . . . . . . . . . . . . . . . . . . . . 35 | 5.1.1. Public Keys | |||
5.1.1. Public Keys . . . . . . . . . . . . . . . . . . . . . 35 | 5.1.2. Signing | |||
5.1.2. Signing . . . . . . . . . . . . . . . . . . . . . . . 36 | 5.1.3. Public Key Encryption | |||
5.1.3. Public-Key Encryption . . . . . . . . . . . . . . . . 37 | 5.2. Hash-Based Identifiers | |||
5.2. Hash-Based Identifiers . . . . . . . . . . . . . . . . . 37 | 5.3. Credentials | |||
5.3. Credentials . . . . . . . . . . . . . . . . . . . . . . . 38 | 5.3.1. Credential Validation | |||
5.3.1. Credential Validation . . . . . . . . . . . . . . . . 39 | 5.3.2. Credential Expiry and Revocation | |||
5.3.2. Credential Expiry and Revocation . . . . . . . . . . 40 | 5.3.3. Uniquely Identifying Clients | |||
5.3.3. Uniquely Identifying Clients . . . . . . . . . . . . 41 | 6. Message Framing | |||
6. Message Framing . . . . . . . . . . . . . . . . . . . . . . . 42 | 6.1. Content Authentication | |||
6.1. Content Authentication . . . . . . . . . . . . . . . . . 45 | 6.2. Encoding and Decoding a Public Message | |||
6.2. Encoding and Decoding a Public Message . . . . . . . . . 47 | 6.3. Encoding and Decoding a Private Message | |||
6.3. Encoding and Decoding a Private Message . . . . . . . . . 48 | 6.3.1. Content Encryption | |||
6.3.1. Content Encryption . . . . . . . . . . . . . . . . . 48 | 6.3.2. Sender Data Encryption | |||
6.3.2. Sender Data Encryption . . . . . . . . . . . . . . . 50 | 7. Ratchet Tree Operations | |||
7. Ratchet Tree Operations . . . . . . . . . . . . . . . . . . . 51 | 7.1. Parent Node Contents | |||
7.1. Parent Node Contents . . . . . . . . . . . . . . . . . . 52 | 7.2. Leaf Node Contents | |||
7.2. Leaf Node Contents . . . . . . . . . . . . . . . . . . . 52 | 7.3. Leaf Node Validation | |||
7.3. Leaf Node Validation . . . . . . . . . . . . . . . . . . 55 | 7.4. Ratchet Tree Evolution | |||
7.4. Ratchet Tree Evolution . . . . . . . . . . . . . . . . . 57 | 7.5. Synchronizing Views of the Tree | |||
7.5. Synchronizing Views of the Tree . . . . . . . . . . . . . 59 | 7.6. Update Paths | |||
7.6. Update Paths . . . . . . . . . . . . . . . . . . . . . . 62 | 7.7. Adding and Removing Leaves | |||
7.7. Adding and Removing Leaves . . . . . . . . . . . . . . . 63 | 7.8. Tree Hashes | |||
7.8. Tree Hashes . . . . . . . . . . . . . . . . . . . . . . . 64 | 7.9. Parent Hashes | |||
7.9. Parent Hashes . . . . . . . . . . . . . . . . . . . . . . 65 | 7.9.1. Using Parent Hashes | |||
7.9.1. Using Parent Hashes . . . . . . . . . . . . . . . . . 68 | 7.9.2. Verifying Parent Hashes | |||
7.9.2. Verifying Parent Hashes . . . . . . . . . . . . . . . 69 | 8. Key Schedule | |||
8. Key Schedule . . . . . . . . . . . . . . . . . . . . . . . . 70 | 8.1. Group Context | |||
8.1. Group Context . . . . . . . . . . . . . . . . . . . . . . 72 | 8.2. Transcript Hashes | |||
8.2. Transcript Hashes . . . . . . . . . . . . . . . . . . . . 74 | 8.3. External Initialization | |||
8.3. External Initialization . . . . . . . . . . . . . . . . . 77 | 8.4. Pre-Shared Keys | |||
8.4. Pre-Shared Keys . . . . . . . . . . . . . . . . . . . . . 77 | 8.5. Exporters | |||
8.5. Exporters . . . . . . . . . . . . . . . . . . . . . . . . 80 | 8.6. Resumption PSK | |||
8.6. Resumption PSK . . . . . . . . . . . . . . . . . . . . . 81 | 8.7. Epoch Authenticators | |||
8.7. Epoch Authenticators . . . . . . . . . . . . . . . . . . 81 | 9. Secret Tree | |||
9. Secret Tree . . . . . . . . . . . . . . . . . . . . . . . . . 82 | 9.1. Encryption Keys | |||
9.1. Encryption Keys . . . . . . . . . . . . . . . . . . . . . 83 | 9.2. Deletion Schedule | |||
9.2. Deletion Schedule . . . . . . . . . . . . . . . . . . . . 84 | 10. Key Packages | |||
10. Key Packages . . . . . . . . . . . . . . . . . . . . . . . . 86 | 10.1. KeyPackage Validation | |||
10.1. KeyPackage Validation . . . . . . . . . . . . . . . . . 87 | 11. Group Creation | |||
11. Group Creation . . . . . . . . . . . . . . . . . . . . . . . 88 | 11.1. Required Capabilities | |||
11.1. Required Capabilities . . . . . . . . . . . . . . . . . 90 | 11.2. Reinitialization | |||
11.2. Reinitialization . . . . . . . . . . . . . . . . . . . . 90 | 11.3. Subgroup Branching | |||
11.3. Subgroup Branching . . . . . . . . . . . . . . . . . . . 91 | 12. Group Evolution | |||
12. Group Evolution . . . . . . . . . . . . . . . . . . . . . . . 92 | 12.1. Proposals | |||
12.1. Proposals . . . . . . . . . . . . . . . . . . . . . . . 92 | 12.1.1. Add | |||
12.1.1. Add . . . . . . . . . . . . . . . . . . . . . . . . 93 | 12.1.2. Update | |||
12.1.2. Update . . . . . . . . . . . . . . . . . . . . . . . 94 | 12.1.3. Remove | |||
12.1.3. Remove . . . . . . . . . . . . . . . . . . . . . . . 94 | 12.1.4. PreSharedKey | |||
12.1.4. PreSharedKey . . . . . . . . . . . . . . . . . . . . 95 | 12.1.5. ReInit | |||
12.1.5. ReInit . . . . . . . . . . . . . . . . . . . . . . . 95 | 12.1.6. ExternalInit | |||
12.1.6. ExternalInit . . . . . . . . . . . . . . . . . . . . 96 | 12.1.7. GroupContextExtensions | |||
12.1.7. GroupContextExtensions . . . . . . . . . . . . . . . 96 | 12.1.8. External Proposals | |||
12.1.8. External Proposals . . . . . . . . . . . . . . . . . 97 | 12.2. Proposal List Validation | |||
12.2. Proposal List Validation . . . . . . . . . . . . . . . . 98 | 12.3. Applying a Proposal List | |||
12.3. Applying a Proposal List . . . . . . . . . . . . . . . . 100 | 12.4. Commit | |||
12.4. Commit . . . . . . . . . . . . . . . . . . . . . . . . . 100 | 12.4.1. Creating a Commit | |||
12.4.1. Creating a Commit . . . . . . . . . . . . . . . . . 103 | 12.4.2. Processing a Commit | |||
12.4.2. Processing a Commit . . . . . . . . . . . . . . . . 106 | 12.4.3. Adding Members to the Group | |||
12.4.3. Adding Members to the Group . . . . . . . . . . . . 109 | 13. Extensibility | |||
13. Extensibility . . . . . . . . . . . . . . . . . . . . . . . . 118 | 13.1. Additional Cipher Suites | |||
13.1. Additional Ciphersuites . . . . . . . . . . . . . . . . 119 | 13.2. Proposals | |||
13.2. Proposals . . . . . . . . . . . . . . . . . . . . . . . 119 | 13.3. Credential Extensibility | |||
13.3. Credential Extensibility . . . . . . . . . . . . . . . . 119 | 13.4. Extensions | |||
13.4. Extensions . . . . . . . . . . . . . . . . . . . . . . . 120 | 13.5. GREASE | |||
13.5. GREASE . . . . . . . . . . . . . . . . . . . . . . . . . 122 | 14. Sequencing of State Changes | |||
14. Sequencing of State Changes . . . . . . . . . . . . . . . . . 123 | 15. Application Messages | |||
15. Application Messages . . . . . . . . . . . . . . . . . . . . 124 | 15.1. Padding | |||
15.1. Padding . . . . . . . . . . . . . . . . . . . . . . . . 124 | 15.2. Restrictions | |||
15.2. Restrictions . . . . . . . . . . . . . . . . . . . . . . 125 | 15.3. Delayed and Reordered Application Messages | |||
15.3. Delayed and Reordered Application messages . . . . . . . 125 | 16. Security Considerations | |||
16. Security Considerations . . . . . . . . . . . . . . . . . . . 126 | 16.1. Transport Security | |||
16.1. Transport Security . . . . . . . . . . . . . . . . . . . 126 | 16.2. Confidentiality of Group Secrets | |||
16.2. Confidentiality of the Group Secrets . . . . . . . . . . 126 | 16.3. Confidentiality of Sender Data | |||
16.3. Confidentiality of Sender Data . . . . . . . . . . . . . 126 | 16.4. Confidentiality of Group Metadata | |||
16.4. Confidentiality of Group Metadata . . . . . . . . . . . 127 | 16.4.1. GroupID, Epoch, and Message Frequency | |||
16.4.1. GroupID, Epoch, and Message Frequency . . . . . . . 128 | 16.4.2. Group Extensions | |||
16.4.2. Group Extensions . . . . . . . . . . . . . . . . . . 129 | 16.4.3. Group Membership | |||
16.4.3. Group Membership . . . . . . . . . . . . . . . . . . 129 | 16.5. Authentication | |||
16.5. Authentication . . . . . . . . . . . . . . . . . . . . . 130 | 16.6. Forward Secrecy and Post-Compromise Security | |||
16.6. Forward Secrecy and Post-Compromise Security . . . . . . 130 | 16.7. Uniqueness of Ratchet Tree Key Pairs | |||
16.7. Uniqueness of Ratchet Tree Key Pairs . . . . . . . . . . 132 | 16.8. KeyPackage Reuse | |||
16.8. KeyPackage Reuse . . . . . . . . . . . . . . . . . . . . 132 | 16.9. Delivery Service Compromise | |||
16.9. Delivery Service Compromise . . . . . . . . . . . . . . 132 | 16.10. Authentication Service Compromise | |||
16.10. Authentication Service Compromise . . . . . . . . . . . 133 | 16.11. Additional Policy Enforcement | |||
16.11. Additional Policy Enforcement . . . . . . . . . . . . . 133 | 16.12. Group Fragmentation by Malicious Insiders | |||
16.12. Group Fragmentation by Malicious Insiders . . . . . . . 133 | 17. IANA Considerations | |||
17. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 134 | 17.1. MLS Cipher Suites | |||
17.1. MLS Ciphersuites . . . . . . . . . . . . . . . . . . . . 135 | 17.2. MLS Wire Formats | |||
17.2. MLS Wire Formats . . . . . . . . . . . . . . . . . . . . 140 | 17.3. MLS Extension Types | |||
17.3. MLS Extension Types . . . . . . . . . . . . . . . . . . 140 | 17.4. MLS Proposal Types | |||
17.4. MLS Proposal Types . . . . . . . . . . . . . . . . . . . 142 | 17.5. MLS Credential Types | |||
17.5. MLS Credential Types . . . . . . . . . . . . . . . . . . 144 | 17.6. MLS Signature Labels | |||
17.6. MLS Signature Labels . . . . . . . . . . . . . . . . . . 146 | 17.7. MLS Public Key Encryption Labels | |||
17.7. MLS Public Key Encryption Labels . . . . . . . . . . . . 146 | 17.8. MLS Exporter Labels | |||
17.8. MLS Exporter Labels . . . . . . . . . . . . . . . . . . 147 | 17.9. MLS Designated Expert Pool | |||
17.9. MLS Designated Expert Pool . . . . . . . . . . . . . . . 148 | 17.10. The "message/mls" Media Type | |||
17.10. The "message/mls" MIME Type . . . . . . . . . . . . . . 148 | 18. References | |||
18. References . . . . . . . . . . . . . . . . . . . . . . . . . 150 | 18.1. Normative References | |||
18.1. Normative References . . . . . . . . . . . . . . . . . . 150 | 18.2. Informative References | |||
18.2. Informative References . . . . . . . . . . . . . . . . . 150 | Appendix A. Protocol Origins of Example Trees | |||
Appendix A. Protocol Origins of Example Trees . . . . . . . . . 153 | Appendix B. Evolution of Parent Hashes | |||
Appendix B. Evolution of Parent Hashes . . . . . . . . . . . . . 154 | Appendix C. Array-Based Trees | |||
Appendix C. Array-Based Trees . . . . . . . . . . . . . . . . . 156 | Appendix D. Link-Based Trees | |||
Appendix D. Link-Based Trees . . . . . . . . . . . . . . . . . . 160 | Contributors | |||
Contributors . . . . . . . . . . . . . . . . . . . . . . . . . . 162 | Authors' Addresses | |||
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 163 | ||||
1. Introduction | 1. Introduction | |||
RFC EDITOR: PLEASE REMOVE THE FOLLOWING PARAGRAPH The source for this | ||||
draft is maintained in GitHub. Suggested changes should be submitted | ||||
as pull requests at https://github.com/mlswg/mls-protocol. | ||||
Instructions are on that page as well. Editorial changes can be | ||||
managed in GitHub, but any substantive change should be discussed on | ||||
the MLS mailing list. | ||||
A group of users who want to send each other encrypted messages needs | A group of users who want to send each other encrypted messages needs | |||
a way to derive shared symmetric encryption keys. For two parties, | a way to derive shared symmetric encryption keys. For two parties, | |||
this problem has been studied thoroughly, with the Double Ratchet | this problem has been studied thoroughly, with the Double Ratchet | |||
emerging as a common solution [DoubleRatchet] [Signal]. Channels | emerging as a common solution [DoubleRatchet] [Signal]. Channels | |||
implementing the Double Ratchet enjoy fine-grained forward secrecy as | implementing the Double Ratchet enjoy fine-grained forward secrecy as | |||
well as post-compromise security, but are nonetheless efficient | well as post-compromise security, but are nonetheless efficient | |||
enough for heavy use over low-bandwidth networks. | enough for heavy use over low-bandwidth networks. | |||
For a group of size greater than two, a common strategy is to | For a group of size greater than two, a common strategy is to | |||
distribute symmetric "sender keys" over existing 1:1 secure channels, | distribute symmetric "sender keys" over existing 1:1 secure channels, | |||
skipping to change at page 5, line 42 ¶ | skipping to change at line 213 ¶ | |||
compromise security with sender keys, requiring a number of key | compromise security with sender keys, requiring a number of key | |||
update messages that scales as the square of the group size. An | update messages that scales as the square of the group size. An | |||
adversary who learns a sender key can often indefinitely and | adversary who learns a sender key can often indefinitely and | |||
passively eavesdrop on that member's messages. Generating and | passively eavesdrop on that member's messages. Generating and | |||
distributing a new sender key provides a form of post-compromise | distributing a new sender key provides a form of post-compromise | |||
security with regard to that sender. However, it requires | security with regard to that sender. However, it requires | |||
computation and communications resources that scale linearly with the | computation and communications resources that scale linearly with the | |||
size of the group. | size of the group. | |||
In this document, we describe a protocol based on tree structures | In this document, we describe a protocol based on tree structures | |||
that enable asynchronous group keying with forward secrecy and post- | that enables asynchronous group keying with forward secrecy and post- | |||
compromise security. Based on earlier work on "asynchronous | compromise security. Based on earlier work on "asynchronous | |||
ratcheting trees" [ART], the protocol presented here uses an | ratcheting trees" [ART], the protocol presented here uses an | |||
asynchronous key-encapsulation mechanism for tree structures. This | asynchronous key-encapsulation mechanism for tree structures. This | |||
mechanism allows the members of the group to derive and update shared | mechanism allows the members of the group to derive and update shared | |||
keys with costs that scale as the log of the group size. | keys with costs that scale as the log of the group size. | |||
1.1. Change Log | ||||
RFC EDITOR PLEASE DELETE THIS SECTION. | ||||
draft-18 | ||||
* Make the document standards track | ||||
* Make the ratchet tree non-malleable (*) | ||||
* Use ExpandWithLabel to derive welcome key (*) | ||||
* Change MLS-Exporter label from "exporter" to "exported" (*) | ||||
* Loosen chain requirements (*) | ||||
* Clarify transcript hash initialization | ||||
* GREASE for MLS registries | ||||
* Move pseudocode out of KDFLabel definition. | ||||
* Rename PrivateContentTBE to PrivateMessageContent | ||||
* Fix DecryptWithLabel argument order for Welcome | ||||
* Responses to IESG reviews | ||||
* Describe varint length check more clearly | ||||
draft-17 | ||||
* Rename MLSCiphertext and MLSPlaintext to PrivateMessage and | ||||
PublicMesssage respectively (*) | ||||
* Add label and context to public-key encryption (*) | ||||
* Include leaf index in LeafNodeTBS for better parent-hash | ||||
guarantees (*) | ||||
* Make ProtocolVersion two bytes (*) | ||||
* Clarify group creation (*) | ||||
* Validate additional properties of unmerged leaves (*) | ||||
* Clarify that the AS needs to vet the signature key | ||||
* Remove "MLS" prefix on structs | ||||
* Credentials should be replaced before expiring | ||||
* Add a section discussing the security of the sender data | ||||
protection | ||||
* Minor fixes in presentation language. | ||||
* Allow multiple welcomes per commit | ||||
* Remove reference to BasicCredential. | ||||
* Client aware of its own removal in group | ||||
* Create IANA registries for signature and export labels | ||||
* Complete IANA media type registration | ||||
* Make more vendor code points available | ||||
* Update Recommended column definition to match 8447bis | ||||
* Responses to early ARTART review | ||||
* Responses to early OPSDIR review | ||||
* Responses to early TSV-ART review | ||||
draft-16 | ||||
* Fix GroupInfoTBS (*) | ||||
* Make reference to h2 informative | ||||
draft-15 | ||||
* Include ciphersuite in group context (*) | ||||
* Add new new_proposal_member SenderType (*) | ||||
* Always use a full tree (*) | ||||
* Change KeyPackage identifier extension to be LeafNode identifier | ||||
(*) | ||||
* Use new tree for context in path secret encryption (*) | ||||
* Use a hash function for hash identifiers (*) | ||||
* Add a marker byte to tree hash input structs (*) | ||||
* Recommend that group ids are generated randomly (*) | ||||
* Update external senders extension to have SignaturePublicKey and | ||||
Credential (*) | ||||
* Replace LeafNodeRef with leaf index (*) | ||||
* Remove AppAck proposal (*) | ||||
* Make padding arbitrary-size and all-zero (*) | ||||
* Require that unmerged_leaves be ordered | ||||
* Derive the commit secret from the end of the UpdatePath, not the | ||||
root | ||||
* Specify the precise points in the protocol where credential | ||||
validation must be done | ||||
* Make PSK provisions more uniform, e.g., always generating a fresh | ||||
random nonce | ||||
* Improve parent hash guarantees with stricter checks on tree | ||||
correctness | ||||
* Streamline some structs, e.g., folding GroupContext into GroupInfo | ||||
* Provide clearer rules for validating and applying commits | ||||
* Clarify tree hash and parent hash, and correct examples | ||||
* Clean up struct names and references to outdated structs | ||||
* Cite AEAD limits draft | ||||
draft-14 | ||||
* Ensure that a signature public key is always intelligible (*) | ||||
* Clean up terminology of derived secrets/keys | ||||
* Fix parent hash (*) | ||||
* Specify compatibility behavior around new credentials | ||||
* Add Path Required to Proposal Type template | ||||
* Sub-group branching requires fresh key packages for each member | ||||
* Use aasvg and typed code blocks | ||||
* Require init key and leaf key to be different | ||||
* Preconfigured senders extension and removal of signature key | ||||
indirection | ||||
draft-13 | ||||
* TLS syntax updates (including variable-header-length vectors) (*) | ||||
* Stop generating redundant PKE key pairs. (*) | ||||
* Move validation of identity change to the AS | ||||
* Add message/mls MIME type registration | ||||
* Split LeafNode from KeyPackage (*) | ||||
* Remove endpoint_id (*) | ||||
* Reorganize to make section layout more sane | ||||
* Forbid proposals by reference in external commits (*) | ||||
* Domain separation for KeyPackage and Proposal references (*) | ||||
* Downgrade MUST to SHOULD for commit senders including all valid | ||||
commits | ||||
* Stronger parent hashes for authenticated identities (*) | ||||
* Move wire_format to a separate tagged-union structure MLSMessage | ||||
* Generalize tree extend/truncate algorithms | ||||
* Add algorithms for link-based trees | ||||
* Forbid self-Update entirely (*) | ||||
* Consolidate resumption PSK cases (*) | ||||
* 384 Ciphersuite Addition | ||||
* Remove explicit version pin on HPKE (*) | ||||
* Remove the requirement for Add in external commit (*) | ||||
* Use smaller, fixed-size hash-based identifiers (*) | ||||
* Be explicit that Credentials can attest to multiple identities (*) | ||||
draft-12 | ||||
* Use the GroupContext to derive the joiner_secret (*) | ||||
* Make PreSharedKeys non optional in GroupSecrets (*) | ||||
* Update name for this particular key (*) | ||||
* Truncate tree size on removal (*) | ||||
* Use HPKE draft-08 (*) | ||||
* Clarify requirements around identity in MLS groups (*) | ||||
* Signal the intended wire format for MLS messages (*) | ||||
* Inject GroupContext as HPKE info instead of AAD (*) | ||||
* Clarify extension handling and make extension updatable (*) | ||||
* Improve extensibility of Proposals (*) | ||||
* Constrain proposal in External Commit (*) | ||||
* Remove the notion of a 'leaf index' (*) | ||||
* Add group_context_extensions proposal ID (*) | ||||
* Add RequiredCapabilities extension (*) | ||||
* Use cascaded KDF instead of concatenation to consolidate PSKs (*) | ||||
* Use key package hash to index clients in message structs (*) | ||||
* Don't require PublicGroupState for external init (*) | ||||
* Make ratchet tree section clearer. | ||||
* Handle non-member sender cases in MLSPlaintextTBS | ||||
* Clarify encoding of signatures with NIST curves | ||||
* Remove OPEN ISSUEs and TODOs | ||||
* Normalize the description of the zero vector | ||||
draft-11 | ||||
* Include subtree keys in parent hash (*) | ||||
* Pin HPKE to draft-07 (*) | ||||
* Move joiner secret to the end of the first key schedule epoch (*) | ||||
* Add an AppAck proposal | ||||
* Make initializations of transcript hashes consistent | ||||
draft-10 | ||||
* Allow new members to join via an external Commit (*) | ||||
* Enable proposals to be sent inline in a Commit (*) | ||||
* Re-enable constant-time Add (*) | ||||
* Change expiration extension to lifetime extension (*) | ||||
* Make the tree in the Welcome optional (*) | ||||
* PSK injection, re-init, sub-group branching (*) | ||||
* Require the initial init_secret to be a random value (*) | ||||
* Remove explicit sender data nonce (*) | ||||
* Do not encrypt to joiners in UpdatePath generation (*) | ||||
* Move MLSPlaintext signature under the confirmation tag (*) | ||||
* Explicitly authenticate group membership with MLSPLaintext (*) | ||||
* Clarify X509Credential structure (*) | ||||
* Remove unneeded interim transcript hash from GroupInfo (*) | ||||
* IANA considerations | ||||
* Derive an authentication secret | ||||
* Use Extract/Expand from HPKE KDF | ||||
* Clarify that application messages MUST be encrypted | ||||
draft-09 | ||||
* Remove blanking of nodes on Add (*) | ||||
* Change epoch numbers to uint64 (*) | ||||
* Add PSK inputs (*) | ||||
* Add key schedule exporter (*) | ||||
* Sign the updated direct path on Commit, using "parent hashes" and | ||||
one signature per leaf (*) | ||||
* Use structured types for external senders (*) | ||||
* Redesign Welcome to include confirmation and use derived keys (*) | ||||
* Remove ignored proposals (*) | ||||
* Always include an Update with a Commit (*) | ||||
* Add per-message entropy to guard against nonce reuse (*) | ||||
* Use the same hash ratchet construct for both application and | ||||
handshake keys (*) | ||||
* Add more ciphersuites | ||||
* Use HKDF to derive key pairs (*) | ||||
* Mandate expiration of ClientInitKeys (*) | ||||
* Add extensions to GroupContext and flesh out the extensibility | ||||
story (*) | ||||
* Rename ClientInitKey to KeyPackage | ||||
draft-08 | ||||
* Change ClientInitKeys so that they only refer to one ciphersuite | ||||
(*) | ||||
* Decompose group operations into Proposals and Commits (*) | ||||
* Enable Add and Remove proposals from outside the group (*) | ||||
* Replace Init messages with multi-recipient Welcome message (*) | ||||
* Add extensions to ClientInitKeys for expiration and downgrade | ||||
resistance (*) | ||||
* Allow multiple Proposals and a single Commit in one MLSPlaintext | ||||
(*) | ||||
draft-07 | ||||
* Initial version of the Tree based Application Key Schedule (*) | ||||
* Initial definition of the Init message for group creation (*) | ||||
* Fix issue with the transcript used for newcomers (*) | ||||
* Clarifications on message framing and HPKE contexts (*) | ||||
draft-06 | ||||
* Reorder blanking and update in the Remove operation (*) | ||||
* Rename the GroupState structure to GroupContext (*) | ||||
* Rename UserInitKey to ClientInitKey | ||||
* Resolve the circular dependency that draft-05 introduced in the | ||||
confirmation MAC calculation (*) | ||||
* Cover the entire MLSPlaintext in the transcript hash (*) | ||||
draft-05 | ||||
* Common framing for handshake and application messages (*) | ||||
* Handshake message encryption (*) | ||||
* Convert from literal state to a commitment via the "tree hash" (*) | ||||
* Add credentials to the tree and remove the "roster" concept (*) | ||||
* Remove the secret field from tree node values | ||||
draft-04 | ||||
* Updating the language to be similar to the Architecture document | ||||
* ECIES is now renamed in favor of HPKE (*) | ||||
* Using a KDF instead of a Hash in TreeKEM (*) | ||||
draft-03 | ||||
* Added ciphersuites and signature schemes (*) | ||||
* Re-ordered fields in UserInitKey to make parsing easier (*) | ||||
* Fixed inconsistencies between Welcome and GroupState (*) | ||||
* Added encryption of the Welcome message (*) | ||||
draft-02 | ||||
* Removed ART (*) | ||||
* Allowed partial trees to avoid double-joins (*) | ||||
* Added explicit key confirmation (*) | ||||
draft-01 | ||||
* Initial description of the Message Protection mechanism. (*) | ||||
* Initial specification proposal for the Application Key Schedule | ||||
using the per-participant chaining of the Application Secret | ||||
design. (*) | ||||
* Initial specification proposal for an encryption mechanism to | ||||
protect Application Messages using an AEAD scheme. (*) | ||||
* Initial specification proposal for an authentication mechanism of | ||||
Application Messages using signatures. (*) | ||||
* Initial specification proposal for a padding mechanism to | ||||
improving protection of Application Messages against traffic | ||||
analysis. (*) | ||||
* Inversion of the Group Init Add and Application Secret derivations | ||||
in the Handshake Key Schedule to be ease chaining in case we | ||||
switch design. (*) | ||||
* Removal of the UserAdd construct and split of GroupAdd into Add | ||||
and Welcome messages (*) | ||||
* Initial proposal for authenticating handshake messages by signing | ||||
over group state and including group state in the key schedule (*) | ||||
* Added an appendix with example code for tree math | ||||
* Changed the ECIES mechanism used by TreeKEM so that it uses nonces | ||||
generated from the shared secret | ||||
draft-00 | ||||
* Initial adoption of draft-barnes-mls-protocol-01 as a WG item. | ||||
2. Terminology | 2. Terminology | |||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", | |||
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and | "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and | |||
"OPTIONAL" in this document are to be interpreted as described in BCP | "OPTIONAL" in this document are to be interpreted as described in BCP | |||
14 [RFC2119] [RFC8174] when, and only when, they appear in all | 14 [RFC2119] [RFC8174] when, and only when, they appear in all | |||
capitals, as shown here. | capitals, as shown here. | |||
Client: An agent that uses this protocol to establish shared | Client: An agent that uses this protocol to establish shared | |||
cryptographic state with other clients. A client is defined by | cryptographic state with other clients. A client is defined by | |||
the cryptographic keys it holds. | the cryptographic keys it holds. | |||
Group: A group represents a logical collection of clients that share | Group: A group represents a logical collection of clients that share | |||
a common secret value at any given time. Its state is represented | a common secret value at any given time. Its state is represented | |||
as a linear sequence of epochs in which each epoch depends on its | as a linear sequence of epochs in which each epoch depends on its | |||
predecessor. | predecessor. | |||
Epoch: A state of a group in which a specific set of authenticated | Epoch: A state of a group in which a specific set of authenticated | |||
clients hold shared cryptographic state. | clients hold shared cryptographic state. | |||
Member: A client that is included in the shared state of a group, | Member: A client that is included in the shared state of a group and | |||
hence has access to the group's secrets. | hence has access to the group's secrets. | |||
Key Package: A signed object describing a client's identity and | Key Package: A signed object describing a client's identity and | |||
capabilities, and including a hybrid public-key encryption (HPKE | capabilities, including a hybrid public key encryption (HPKE) | |||
[RFC9180]) public key that can be used to encrypt to that client, | [RFC9180] public key that can be used to encrypt to that client. | |||
and which other clients can use to introduce the client to a new | Other clients can use a client's KeyPackage to introduce the | |||
group. | client to a new group. | |||
Group Context: An object that summarizes the shared, public state of | Group Context: An object that summarizes the shared, public state of | |||
the group. The group context is typically distributed in a signed | the group. The group context is typically distributed in a signed | |||
GroupInfo message, which is provided to new members to help them | GroupInfo message, which is provided to new members to help them | |||
join a group. | join a group. | |||
Signature Key: A signing key pair used to authenticate the sender of | Signature Key: A signing key pair used to authenticate the sender of | |||
a message. | a message. | |||
Proposal: A message that proposes a change to the group, e.g., | Proposal: A message that proposes a change to the group, e.g., | |||
adding or removing a member. | adding or removing a member. | |||
Commit: A message that implements the changes to the group proposed | Commit: A message that implements the changes to the group proposed | |||
in a set of Proposals. | in a set of Proposals. | |||
PublicMessage: An MLS protocol message that is signed by its sender | PublicMessage: An MLS protocol message that is signed by its sender | |||
and authenticated as coming from a member of the group in a | and authenticated as coming from a member of the group in a | |||
particular epoch, but not encrypted. | particular epoch, but not encrypted. | |||
PrivateMessage: An MLS protocol message that is both signed by its | PrivateMessage: An MLS protocol message that is signed by its | |||
sender, authenticated as coming from a member of the group in a | sender, authenticated as coming from a member of the group in a | |||
particular epoch, and encrypted so that it is confidential to the | particular epoch, and encrypted so that it is confidential to the | |||
members of the group in that epoch. | members of the group in that epoch. | |||
Handshake Message: A PublicMessage or PrivateMessage carrying an MLS | Handshake Message: A PublicMessage or PrivateMessage carrying an MLS | |||
Proposal or Commit object, as opposed to application data. | Proposal or Commit object, as opposed to application data. | |||
Application Message: A PrivateMessage carrying application data. | Application Message: A PrivateMessage carrying application data. | |||
Terminology specific to tree computations is described in | Terminology specific to tree computations is described in | |||
Section 4.1. | Section 4.1. | |||
In general, symmetric values are referred to as "keys" or "secrets" | In general, symmetric values are referred to as "keys" or "secrets" | |||
interchangeably. Either term denotes a value that MUST be kept | interchangeably. Either term denotes a value that MUST be kept | |||
confidential to a Client. When labeling individual values, we | confidential to a client. When labeling individual values, we | |||
typically use "secret" to refer to a value that is used derive | typically use "secret" to refer to a value that is used to derive | |||
further secret values, and "key" to refer to a value that is used | further secret values and "key" to refer to a value that is used with | |||
with an algorithm such as HMAC or an AEAD algorithm. | an algorithm such as Hashed Message Authentication Code (HMAC) or an | |||
Authenticated Encryption with Associated Data (AEAD) algorithm. | ||||
The PublicMessage and PrivateMessage formats are defined in | The PublicMessage and PrivateMessage formats are defined in | |||
Section 6. Security notions such as forward secrecy and post- | Section 6. Security notions such as forward secrecy and post- | |||
compromise security are defined in Section 16. | compromise security are defined in Section 16. | |||
As detailed in Section 13.5, MLS uses the "Generate Random Extensions | As detailed in Section 13.5, MLS uses the "Generate Random Extensions | |||
And Sustain Extensibility" (GREASE) approach to maintaining | And Sustain Extensibility" (GREASE) approach to maintaining | |||
extensibility, where senders insert random values into fields in | extensibility, where senders insert random values into fields in | |||
which receivers are required to ignore unknown values. Specific | which receivers are required to ignore unknown values. Specific | |||
"GREASE values" for this purpose are registered in the appropriate | "GREASE values" for this purpose are registered in the appropriate | |||
IANA registries. | IANA registries. | |||
2.1. Presentation Language | 2.1. Presentation Language | |||
We use the TLS presentation language [RFC8446] to describe the | We use the TLS presentation language [RFC8446] to describe the | |||
structure of protocol messages. In addition to the base syntax, we | structure of protocol messages. In addition to the base syntax, we | |||
add two additional features, the ability for fields to be optional | add two additional features: the ability for fields to be optional | |||
and the ability for vectors to have variable-size length headers. | and the ability for vectors to have variable-size length headers. | |||
2.1.1. Optional Value | 2.1.1. Optional Value | |||
An optional value is encoded with a presence-signaling octet, | An optional value is encoded with a presence-signaling octet, | |||
followed by the value itself if present. When decoding, a presence | followed by the value itself if present. When decoding, a presence | |||
octet with a value other than 0 or 1 MUST be rejected as malformed. | octet with a value other than 0 or 1 MUST be rejected as malformed. | |||
struct { | struct { | |||
uint8 present; | uint8 present; | |||
select (present) { | select (present) { | |||
case 0: struct{}; | case 0: struct{}; | |||
case 1: T value; | case 1: T value; | |||
}; | }; | |||
} optional<T>; | } optional<T>; | |||
2.1.2. Variable-size Vector Length Headers | 2.1.2. Variable-Size Vector Length Headers | |||
In the TLS presentation language, vectors are encoded as a sequence | In the TLS presentation language, vectors are encoded as a sequence | |||
of encoded elements prefixed with a length. The length field has a | of encoded elements prefixed with a length. The length field has a | |||
fixed size set by specifying the minimum and maximum lengths of the | fixed size set by specifying the minimum and maximum lengths of the | |||
encoded sequence of elements. | encoded sequence of elements. | |||
In MLS, there are several vectors whose sizes vary over significant | In MLS, there are several vectors whose sizes vary over significant | |||
ranges. So instead of using a fixed-size length field, we use a | ranges. So instead of using a fixed-size length field, we use a | |||
variable-size length using a variable-length integer encoding based | variable-size length using a variable-length integer encoding based | |||
on the one in Section 16 of [RFC9000]. They differ only in that the | on the one described in Section 16 of [RFC9000]. They differ only in | |||
one here requires a minimum-size encoding. Instead of presenting min | that the one here requires a minimum-size encoding. Instead of | |||
and max values, the vector description simply includes a V. For | presenting min and max values, the vector description simply includes | |||
example: | a V. For example: | |||
struct { | struct { | |||
uint32 fixed<0..255>; | uint32 fixed<0..255>; | |||
opaque variable<V>; | opaque variable<V>; | |||
} StructWithVectors; | } StructWithVectors; | |||
Such a vector can represent values with length from 0 bytes to 2^30 | Such a vector can represent values with length from 0 bytes to 2^30 | |||
bytes. The variable-length integer encoding reserves the two most | bytes. The variable-length integer encoding reserves the two most | |||
significant bits of the first byte to encode the base 2 logarithm of | significant bits of the first byte to encode the base 2 logarithm of | |||
the integer encoding length in bytes. The integer value is encoded | the integer encoding length in bytes. The integer value is encoded | |||
on the remaining bits, so that the overall value is in network byte | on the remaining bits, so that the overall value is in network byte | |||
order. The encoded value MUST use the smallest number of bits | order. The encoded value MUST use the smallest number of bits | |||
required to represent the value. When decoding, values using more | required to represent the value. When decoding, values using more | |||
bits than necessary MUST be treated as malformed. | bits than necessary MUST be treated as malformed. | |||
This means that integers are encoded on 1, 2, or 4 bytes and can | This means that integers are encoded in 1, 2, or 4 bytes and can | |||
encode 6-, 14-, or 30-bit values respectively. | encode 6-, 14-, or 30-bit values, respectively. | |||
+========+=========+=============+=======+============+ | +========+=========+=============+=======+============+ | |||
| Prefix | Length | Usable Bits | Min | Max | | | Prefix | Length | Usable Bits | Min | Max | | |||
+========+=========+=============+=======+============+ | +========+=========+=============+=======+============+ | |||
| 00 | 1 | 6 | 0 | 63 | | | 00 | 1 | 6 | 0 | 63 | | |||
+--------+---------+-------------+-------+------------+ | +--------+---------+-------------+-------+------------+ | |||
| 01 | 2 | 14 | 64 | 16383 | | | 01 | 2 | 14 | 64 | 16383 | | |||
+--------+---------+-------------+-------+------------+ | +--------+---------+-------------+-------+------------+ | |||
| 10 | 4 | 30 | 16384 | 1073741823 | | | 10 | 4 | 30 | 16384 | 1073741823 | | |||
+--------+---------+-------------+-------+------------+ | +--------+---------+-------------+-------+------------+ | |||
| 11 | invalid | - | - | - | | | 11 | invalid | - | - | - | | |||
+--------+---------+-------------+-------+------------+ | +--------+---------+-------------+-------+------------+ | |||
Table 1: Summary of Integer Encodings | Table 1: Summary of Integer Encodings | |||
Vectors that start with "11" prefix are invalid and MUST be rejected. | Vectors that start with the prefix "11" are invalid and MUST be | |||
rejected. | ||||
For example: | For example: | |||
* The four byte length value 0x9d7f3e7d decodes to 494878333. | * The four-byte length value 0x9d7f3e7d decodes to 494878333. | |||
* The two byte length value 0x7bbd decodes to 15293. | * The two-byte length value 0x7bbd decodes to 15293. | |||
* The single byte length value 0x25 decodes to 37. | * The single-byte length value 0x25 decodes to 37. | |||
The following figure adapts the pseudocode provided in [RFC9000] to | The following figure adapts the pseudocode provided in [RFC9000] to | |||
add a check for minimum-length encoding: | add a check for minimum-length encoding: | |||
ReadVarint(data): | ReadVarint(data): | |||
// The length of variable-length integers is encoded in the | // The length of variable-length integers is encoded in the | |||
// first two bits of the first byte. | // first two bits of the first byte. | |||
v = data.next_byte() | v = data.next_byte() | |||
prefix = v >> 6 | prefix = v >> 6 | |||
if prefix == 3: | if prefix == 3: | |||
skipping to change at page 19, line 14 ¶ | skipping to change at line 411 ¶ | |||
The use of variable-size integers for vector lengths allows vectors | The use of variable-size integers for vector lengths allows vectors | |||
to grow very large, up to 2^30 bytes. Implementations should take | to grow very large, up to 2^30 bytes. Implementations should take | |||
care not to allow vectors to overflow available storage. To | care not to allow vectors to overflow available storage. To | |||
facilitate debugging of potential interoperability problems, | facilitate debugging of potential interoperability problems, | |||
implementations SHOULD provide a clear error when such an overflow | implementations SHOULD provide a clear error when such an overflow | |||
condition occurs. | condition occurs. | |||
3. Protocol Overview | 3. Protocol Overview | |||
MLS is designed to operate in the context described in | MLS is designed to operate in the context described in [MLS-ARCH]. | |||
[I-D.ietf-mls-architecture]. In particular, we assume that the | In particular, we assume that the following services are provided: | |||
following services are provided: | ||||
* An Authentication Service (AS) that enables group members to | * An Authentication Service (AS) that enables group members to | |||
authenticate the credentials presented by other group members. | authenticate the credentials presented by other group members. | |||
* A Delivery Service (DS) that routes MLS messages among the | * A Delivery Service (DS) that routes MLS messages among the | |||
participants in the protocol. | participants in the protocol. | |||
MLS assumes a trusted AS but a largely untrusted DS. Section 16.10 | MLS assumes a trusted AS but a largely untrusted DS. Section 16.10 | |||
describes the impact of compromise or misbehavior of an AS. MLS is | describes the impact of compromise or misbehavior of an AS. MLS is | |||
designed to protect the confidentiality and integrity of the group | designed to protect the confidentiality and integrity of the group | |||
data even in the face of a compromised DS; in general, the DS is just | data even in the face of a compromised DS; in general, the DS is only | |||
expected to reliably deliver messages. Section 16.9 describes the | expected to reliably deliver messages. Section 16.9 describes the | |||
impact of compromise or misbehavior of a DS. | impact of compromise or misbehavior of a DS. | |||
The core functionality of MLS is continuous group authenticated key | The core functionality of MLS is continuous group authenticated key | |||
exchange (AKE). As with other authenticated key exchange protocols | exchange (AKE). As with other authenticated key exchange protocols | |||
(such as TLS), the participants in the protocol agree on a common | (such as TLS), the participants in the protocol agree on a common | |||
secret value, and each participant can verify the identity of the | secret value, and each participant can verify the identity of the | |||
other participants. That secret can then be used to protect messages | other participants. That secret can then be used to protect messages | |||
sent from one participant in the group to the other participants | sent from one participant in the group to the other participants | |||
using the MLS framing layer or can be exported for use with other | using the MLS framing layer or can be exported for use with other | |||
skipping to change at page 20, line 26 ¶ | skipping to change at line 460 ¶ | |||
The creator of an MLS group creates the group's first epoch | The creator of an MLS group creates the group's first epoch | |||
unilaterally, with no protocol interactions. Thereafter, the members | unilaterally, with no protocol interactions. Thereafter, the members | |||
of the group advance their shared cryptographic state from one epoch | of the group advance their shared cryptographic state from one epoch | |||
to another by exchanging MLS messages. | to another by exchanging MLS messages. | |||
* A _KeyPackage_ object describes a client's capabilities and | * A _KeyPackage_ object describes a client's capabilities and | |||
provides keys that can be used to add the client to a group. | provides keys that can be used to add the client to a group. | |||
* A _Proposal_ message proposes a change to be made in the next | * A _Proposal_ message proposes a change to be made in the next | |||
epoch, such as adding or removing a member | epoch, such as adding or removing a member. | |||
* A _Commit_ message initiates a new epoch by instructing members of | * A _Commit_ message initiates a new epoch by instructing members of | |||
the group to implement a collection of proposals | the group to implement a collection of proposals. | |||
* A _Welcome_ message provides a new member to the group with the | * A _Welcome_ message provides a new member to the group with the | |||
information to initialize their state for the epoch in which they | information to initialize their state for the epoch in which they | |||
were added or in which they want to add themselves to the group | were added or in which they want to add themselves to the group. | |||
KeyPackage and Welcome messages are used to initiate a group or | KeyPackage and Welcome messages are used to initiate a group or | |||
introduce new members, so they are exchanged between group members | introduce new members, so they are exchanged between group members | |||
and clients not yet in the group. A client publishes a KeyPackage | and clients not yet in the group. A client publishes a KeyPackage | |||
via the DS, thus enabling other clients to add it to groups. When a | via the DS, thus enabling other clients to add it to groups. When a | |||
group member wants to add a new member to a group it uses the new | group member wants to add a new member to a group, it uses the new | |||
member's KeyPackage to add the new member to the group and construct | member's KeyPackage to add them and constructs a Welcome message with | |||
a Welcome message with which the new member can initialize its local | which the new member can initialize their local state. | |||
state. | ||||
Proposal and Commit messages are sent from one member of a group to | Proposal and Commit messages are sent from one member of a group to | |||
the others. MLS provides a common framing layer for sending messages | the others. MLS provides a common framing layer for sending messages | |||
within a group: A _PublicMessage_ provides sender authentication for | within a group: A _PublicMessage_ provides sender authentication for | |||
unencrypted Proposal and Commit messages. A _PrivateMessage_ | unencrypted Proposal and Commit messages. A _PrivateMessage_ | |||
provides encryption and authentication for both Proposal/Commit | provides encryption and authentication for both Proposal/Commit | |||
messages as well as any application data. | messages as well as any application data. | |||
3.1. Cryptographic State and Evolution | 3.1. Cryptographic State and Evolution | |||
skipping to change at page 21, line 34 ¶ | skipping to change at line 513 ¶ | |||
| / | | | \ | | | / | | | \ | | |||
|/ | | | \| | |/ | | | \| | |||
' | V | ' | ' | V | ' | |||
| epoch_secret | | | epoch_secret | | |||
| | | | | | | | |||
| | | | | | | | |||
| V | | | V | | |||
| | | | | | |||
'- ... -' | '- ... -' | |||
Figure 1: Overview of MLS group evolution | Figure 1: Overview of MLS Group Evolution | |||
* A _ratchet tree_ that represents the membership of the group, | * A _ratchet tree_ that represents the membership of the group, | |||
providing group members a way to authenticate each other and | providing group members a way to authenticate each other and | |||
efficiently encrypt messages to subsets of the group. Each epoch | efficiently encrypt messages to subsets of the group. Each epoch | |||
has a distinct ratchet tree. It seeds the _key schedule_. | has a distinct ratchet tree. It seeds the _key schedule_. | |||
* A _key schedule_ that describes the chain of key derivations used | * A _key schedule_ that describes the chain of key derivations used | |||
to progress from epoch to epoch (mainly using the _init_secret_ | to progress from epoch to epoch (mainly using the _init_secret_ | |||
and _epoch_secret_), as well as the derivation of a variety of | and _epoch_secret_), as well as the derivation of a variety of | |||
other secrets (see Table 4), for example: | other secrets (see Table 4). For example: | |||
- An _encryption secret_ that is used to initialize the secret | - An _encryption secret_ that is used to initialize the secret | |||
tree for the epoch. | tree for the epoch. | |||
- An _exporter secret_ that allows other protocols to leverage | - An _exporter secret_ that allows other protocols to leverage | |||
MLS as a generic authenticated group key exchange. | MLS as a generic authenticated group key exchange. | |||
- A _resumption secret_ that members can use to prove their | - A _resumption secret_ that members can use to prove their | |||
membership in the group, e.g., when creating a subgroup or a | membership in the group, e.g., when creating a subgroup or a | |||
successor group. | successor group. | |||
skipping to change at page 22, line 35 ¶ | skipping to change at line 561 ¶ | |||
For each Commit that adds one or more members to the group, there are | For each Commit that adds one or more members to the group, there are | |||
one or more corresponding Welcome messages. Each Welcome message | one or more corresponding Welcome messages. Each Welcome message | |||
provides new members with the information they need to initialize | provides new members with the information they need to initialize | |||
their views of the key schedule and ratchet tree, so that these views | their views of the key schedule and ratchet tree, so that these views | |||
align with the views held by other members of the group in this | align with the views held by other members of the group in this | |||
epoch. | epoch. | |||
3.2. Example Protocol Execution | 3.2. Example Protocol Execution | |||
There are three major operations in the lifecycle of a group: | There are three major operations in the life of a group: | |||
* Adding a member, initiated by a current member; | * Adding a member, initiated by a current member; | |||
* Updating the keys that represent a member in the tree; | * Updating the keys that represent a member in the tree; and | |||
* Removing a member. | * Removing a member. | |||
Each of these operations is "proposed" by sending a message of the | Each of these operations is "proposed" by sending a message of the | |||
corresponding type (Add / Update / Remove). The state of the group | corresponding type (Add / Update / Remove). The state of the group | |||
is not changed, however, until a Commit message is sent to provide | is not changed, however, until a Commit message is sent to provide | |||
the group with fresh entropy. In this section, we show each proposal | the group with fresh entropy. In this section, we show each proposal | |||
being committed immediately, but in more advanced deployment cases an | being committed immediately, but in more advanced deployment cases, | |||
application might gather several proposals before committing them all | an application might gather several proposals before committing them | |||
at once. In the illustrations below, we show the Proposal and Commit | all at once. In the illustrations below, we show the Proposal and | |||
messages directly, while in reality they would be sent encapsulated | Commit messages directly, while in reality they would be sent | |||
in PublicMessage or PrivateMessage objects. | encapsulated in PublicMessage or PrivateMessage objects. | |||
Before the initialization of a group, clients publish KeyPackages to | Before the initialization of a group, clients publish KeyPackages to | |||
a directory provided by the DS (see Figure 2). | a directory provided by the DS (see Figure 2). | |||
Delivery Service | Delivery Service | |||
| | | | |||
.--------' '--------. | .--------' '--------. | |||
| | | | | | |||
Group | Group | |||
A B C Directory Channel | A B C Directory Channel | |||
skipping to change at page 23, line 27 ¶ | skipping to change at line 601 ¶ | |||
| | | | | | | | | | | | |||
| | KeyPackageB | | | | | | KeyPackageB | | | | |||
| +-------------------------------->| | | | +-------------------------------->| | | |||
| | | | | | | | | | | | |||
| | | KeyPackageC | | | | | | KeyPackageC | | | |||
| | +--------------->| | | | | +--------------->| | | |||
| | | | | | | | | | | | |||
Figure 2: Clients A, B, and C publish KeyPackages to the directory | Figure 2: Clients A, B, and C publish KeyPackages to the directory | |||
Figure 3 shows how these prepublished KeyPackages are used to create | Figure 3 shows how these pre-published KeyPackages are used to create | |||
a group. When a client A wants to establish a group with B and C, it | a group. When client A wants to establish a group with clients B and | |||
first initializes a group state containing only itself and downloads | C, it first initializes a group state containing only itself and | |||
KeyPackages for B and C. For each member, A generates an Add and | downloads KeyPackages for B and C. For each member, A generates an | |||
Commit message adding that member, and broadcasts them to the group. | Add proposal and a Commit message to add that member and then | |||
It also generates a Welcome message and sends this directly to the | broadcasts the two messages to the group. Client A also generates a | |||
new member (there's no need to send it to the group). Only after A | Welcome message and sends it directly to the new member (there's no | |||
has received its Commit message back from the Delivery Service does | need to send it to the group). Only after A has received its Commit | |||
it update its state to reflect the new member's addition. | message back from the Delivery Service does it update its state to | |||
reflect the new member's addition. | ||||
Once A has updated its state, the new member has processed the | Once A has updated its state, the new member has processed the | |||
Welcome, and any other group members have processed the Commit, they | Welcome, and any other group members have processed the Commit, they | |||
will all have consistent representations of the group state, | will all have consistent representations of the group state, | |||
including a group secret that is known only to the members the group. | including a group secret that is known only to the members the group. | |||
The new member will be able to read and send new messages to the | The new member will be able to read and send new messages to the | |||
group, but messages sent before they were added to the group will not | group, but messages sent before they were added to the group will not | |||
be accessible. | be accessible. | |||
Group | Group | |||
skipping to change at page 24, line 39 ¶ | skipping to change at line 654 ¶ | |||
| | | | | | | | | | | | |||
| | | | Add(AB->ABC) | | | | | | Add(AB->ABC) | | |||
| | | | Commit(Add) | | | | | | Commit(Add) | | |||
|<---------------------------------------------------------------+ | |<---------------------------------------------------------------+ | |||
| |<------------------------------------------------+ | | |<------------------------------------------------+ | |||
| | | | | | | | | | | | |||
Figure 3: Client A creates a group with clients B and C | Figure 3: Client A creates a group with clients B and C | |||
Subsequent additions of group members proceed in the same way. Any | Subsequent additions of group members proceed in the same way. Any | |||
member of the group can download a KeyPackage for a new client and | member of the group can download a KeyPackage for a new client, | |||
broadcast Add and Commit messages that the current group will use to | broadcast Add and Commit messages that the current group will use to | |||
update their state, and a Welcome message that the new client can use | update their state, and send a Welcome message that the new client | |||
to initialize its state and join the group. | can use to initialize its state and join the group. | |||
To enforce the forward secrecy and post-compromise security of | To enforce the forward secrecy and post-compromise security of | |||
messages, each member periodically updates the keys that represent | messages, each member periodically updates the keys that represent | |||
them to the group. A member does this by sending a Commit (possibly | them to the group. A member does this by sending a Commit (possibly | |||
with no proposals), or by sending an Update message that is committed | with no proposals) or by sending an Update message that is committed | |||
by another member (see Figure 4). Once the other members of the | by another member (see Figure 4). Once the other members of the | |||
group have processed these messages, the group's secrets will be | group have processed these messages, the group's secrets will be | |||
unknown to an attacker that had compromised the secrets corresponding | unknown to an attacker that had compromised the secrets corresponding | |||
to the sender's leaf in the tree. | to the sender's leaf in the tree. At the end of the scenario shown | |||
in Figure 4, the group has post-compromise security with respect to | ||||
both A and B. | ||||
Update messages SHOULD be sent at regular intervals of time as long | Update messages SHOULD be sent at regular intervals of time as long | |||
as the group is active, and members that don't update SHOULD | as the group is active, and members that don't update SHOULD | |||
eventually be removed from the group. It's left to the application | eventually be removed from the group. It's left to the application | |||
to determine an appropriate amount of time between Updates. Since | to determine an appropriate amount of time between Updates. Since | |||
the purpose of sending an Update is to proactively constrain a | the purpose of sending an Update is to proactively constrain a | |||
compromise window, the right frequency is usually on the order of | compromise window, the right frequency is usually on the order of | |||
hours or days, not milliseconds. For example, an application might | hours or days, not milliseconds. For example, an application might | |||
send an Update each time a member sends an application message after | send an Update each time a member sends an application message after | |||
receiving from other members, or daily if no application messages are | receiving any message from another member, or daily if no application | |||
sent. | messages are sent. | |||
The MLS architecture recommends that MLS be operated over a secure | The MLS architecture recommends that MLS be operated over a secure | |||
transport (see Section 7.1 of [I-D.ietf-mls-architecture]). Such | transport (see Section 7.1 of [MLS-ARCH]). Such transport protocols | |||
transport protocols will typically provide functions such as | will typically provide functions such as congestion control that | |||
congestion control that manage the impact of an MLS-using application | manage the impact of an MLS-using application on other applications | |||
on other applications sharing the same network. Applications should | sharing the same network. Applications should take care that they do | |||
take care that they do not send MLS messages at a rate that will | not send MLS messages at a rate that will cause problems such as | |||
cause problems such as network congestion, especially if they are not | network congestion, especially if they are not following the above | |||
following the above recommendation (e.g., sending MLS directly over | recommendation (e.g., sending MLS directly over UDP instead). | |||
UDP instead). | ||||
Group | Group | |||
A B ... Z Directory Channel | A B ... Z Directory Channel | |||
| | | | | | | | | | | | |||
| | Update(B) | | | | | | Update(B) | | | | |||
| +------------------------------------------->| | | +------------------------------------------->| | |||
| | | | Update(B) | | | | | | Update(B) | | |||
|<----------------------------------------------------------+ | |<----------------------------------------------------------+ | |||
| |<-------------------------------------------+ | | |<-------------------------------------------+ | |||
| | |<----------------------------+ | | | |<----------------------------+ | |||
| | | | | | | | | | | | |||
| Commit(Upd) | | | | | | Commit(Upd) | | | | | |||
+---------------------------------------------------------->| | +---------------------------------------------------------->| | |||
| | | | Commit(Upd) | | | | | | Commit(Upd) | | |||
|<----------------------------------------------------------+ | |<----------------------------------------------------------+ | |||
| |<-------------------------------------------+ | | |<-------------------------------------------+ | |||
| | |<----------------------------+ | | | |<----------------------------+ | |||
| | | | | | | | | | | | |||
Figure 4: Client B proposes to update its key, and client A | Figure 4: Client B proposes to update its key, and client A | |||
commits the proposal. As a result, the keys for both B and A | commits the proposal | |||
updated, so the group has post-compromise security with respect | ||||
to both of them. | ||||
Members are removed from the group in a similar way, as shown in | Members are removed from the group in a similar way, as shown in | |||
Figure 5. Any member of the group can send a Remove proposal | Figure 5. Any member of the group can send a Remove proposal | |||
followed by a Commit message. The Commit message provides new | followed by a Commit message. The Commit message provides new | |||
entropy to all members of the group except the removed member. This | entropy to all members of the group except the removed member. This | |||
new entropy is added to the epoch secret for the new epoch so that it | new entropy is added to the epoch secret for the new epoch so that it | |||
is not known to the removed member. Note that this does not | is not known to the removed member. Note that this does not | |||
necessarily imply that any member is actually allowed to evict other | necessarily imply that any member is actually allowed to evict other | |||
members; groups can enforce access control policies on top of these | members; groups can enforce access control policies on top of these | |||
basic mechanisms. | basic mechanisms. | |||
skipping to change at page 26, line 36 ¶ | skipping to change at line 747 ¶ | |||
Note that the flows in this section are examples; applications can | Note that the flows in this section are examples; applications can | |||
arrange message flows in other ways. For example: | arrange message flows in other ways. For example: | |||
* Welcome messages don't necessarily need to be sent directly to new | * Welcome messages don't necessarily need to be sent directly to new | |||
joiners. Since they are encrypted to new joiners, they could be | joiners. Since they are encrypted to new joiners, they could be | |||
distributed more broadly, say if the application only had access | distributed more broadly, say if the application only had access | |||
to a broadcast channel for the group. | to a broadcast channel for the group. | |||
* Proposal messages don't need to be immediately sent to all group | * Proposal messages don't need to be immediately sent to all group | |||
members. They need to be available to the committer before | members. They need to be available to the committer before | |||
generating a commit, and to other members before processing the | generating a Commit, and to other members before processing the | |||
commit. | Commit. | |||
* The sender of a Commit doesn't necessarily have to wait to receive | * The sender of a Commit doesn't necessarily have to wait to receive | |||
its own Commit back before advancing its state. It only needs to | its own Commit back before advancing its state. It only needs to | |||
know that its Commit will be the next one applied by the group, | know that its Commit will be the next one applied by the group, | |||
say based on a promise from an orchestration server. | say based on a promise from an orchestration server. | |||
3.3. External Joins | 3.3. External Joins | |||
In addition to the Welcome-based flow for adding a new member to the | In addition to the Welcome-based flow for adding a new member to the | |||
group, it is also possible for a new member to join by means of an | group, it is also possible for a new member to join by means of an | |||
skipping to change at page 27, line 32 ¶ | skipping to change at line 791 ¶ | |||
| | |<-------------+ | | | | |<-------------+ | | |||
| | | | | | | | | | | | |||
| | | Commit(ExtZ) | | | | | | Commit(ExtZ) | | | |||
| | +---------------------------->| | | | +---------------------------->| | |||
| | | | Commit(ExtZ) | | | | | | Commit(ExtZ) | | |||
|<----------------------------------------------------------+ | |<----------------------------------------------------------+ | |||
| |<-------------------------------------------+ | | |<-------------------------------------------+ | |||
| | |<----------------------------+ | | | |<----------------------------+ | |||
| | | | | | | | | | | | |||
Figure 6: Client A publishes a GroupInfo object and Client Z uses | Figure 6: Client A publishes a GroupInfo object, and Client Z | |||
it to join the group | uses it to join the group | |||
3.4. Relationships Between Epochs | 3.4. Relationships between Epochs | |||
A group has a single linear sequence of epochs. Groups and epochs | A group has a single linear sequence of epochs. Groups and epochs | |||
are generally independent of one another. However, it can sometimes | are generally independent of one another. However, it can sometimes | |||
be useful to link epochs cryptographically, either within a group or | be useful to link epochs cryptographically, either within a group or | |||
across groups. MLS derives a resumption pre-shared key (PSK) from | across groups. MLS derives a resumption pre-shared key (PSK) from | |||
each epoch to allow entropy extracted from one epoch to be injected | each epoch to allow entropy extracted from one epoch to be injected | |||
into a future epoch. A group member that wishes to inject a PSK | into a future epoch. A group member that wishes to inject a PSK | |||
issues a PreSharedKey proposal (Section 12.1.4) describing the PSK to | issues a PreSharedKey proposal (Section 12.1.4) describing the PSK to | |||
be injected. When this proposal is committed, the corresponding PSK | be injected. When this proposal is committed, the corresponding PSK | |||
will be incorporated into the key schedule as described in | will be incorporated into the key schedule as described in | |||
Section 8.4. | Section 8.4. | |||
Linking epochs in this way guarantees that members entering the new | Linking epochs in this way guarantees that members entering the new | |||
epoch agree on a key if and only if they were members of the group | epoch agree on a key if and only if they were members of the group | |||
during the epoch from which the resumption key was extracted. | during the epoch from which the resumption key was extracted. | |||
MLS supports two ways to tie a new group to an existing group, | MLS supports two ways to tie a new group to an existing group, which | |||
illustrated in Figure 7 and Figure 8. Reinitialization closes one | are illustrated in Figures 7 and 8. Reinitialization closes one | |||
group and creates a new group comprising the same members with | group and creates a new group comprising the same members with | |||
different parameters. Branching starts a new group with a subset of | different parameters. Branching starts a new group with a subset of | |||
the original group's participants (with no effect on the original | the original group's participants (with no effect on the original | |||
group). In both cases, the new group is linked to the old group via | group). In both cases, the new group is linked to the old group via | |||
a resumption PSK. | a resumption PSK. | |||
epoch_A_[n-1] | epoch_A_[n-1] | |||
| | | | |||
| | | | |||
|<-- ReInit | |<-- ReInit | |||
| | | | |||
V | V | |||
epoch_A_[n] epoch_B_[0] | epoch_A_[n] epoch_B_[0] | |||
. | | . | | |||
. PSK(usage=reinit) | | . PSK(usage=reinit) | | |||
.....................>| | .....................>| | |||
| | | | |||
V | V | |||
epoch_B_[1] | epoch_B_[1] | |||
Figure 7: Reinitializing a group | Figure 7: Reinitializing a Group | |||
epoch_A_[n] epoch_B_[0] | epoch_A_[n] epoch_B_[0] | |||
| | | | | | |||
| PSK(usage=branch) | | | PSK(usage=branch) | | |||
|....................>| | |....................>| | |||
| | | | | | |||
V V | V V | |||
epoch_A_[n+1] epoch_B_[1] | epoch_A_[n+1] epoch_B_[1] | |||
Figure 8: Branching a group | Figure 8: Branching a Group | |||
Applications may also choose to use resumption PSKs to link epochs in | Applications may also choose to use resumption PSKs to link epochs in | |||
other ways. For example, Figure 9 shows a case where a resumption | other ways. For example, Figure 9 shows a case where a resumption | |||
PSK from epoch n is injected into epoch n+k. This demonstrates that | PSK from epoch n is injected into epoch n+k. This demonstrates that | |||
the members of the group at epoch n+k were also members at epoch n, | the members of the group at epoch n+k were also members at epoch n, | |||
irrespective of any changes to these members' keys due to Updates or | irrespective of any changes to these members' keys due to Updates or | |||
Commits. | Commits. | |||
epoch_A_[n] | epoch_A_[n] | |||
| | | | |||
skipping to change at page 29, line 23 ¶ | skipping to change at line 870 ¶ | |||
| . | | . | |||
V . | V . | |||
epoch_A_[n+k-1] . | epoch_A_[n+k-1] . | |||
| . | | . | |||
| . | | . | |||
|<.................... | |<.................... | |||
| | | | |||
V | V | |||
epoch_A_[n+k] | epoch_A_[n+k] | |||
Figure 9: Reinjecting entropy from an earlier epoch | Figure 9: Reinjecting Entropy from an Earlier Epoch | |||
4. Ratchet Tree Concepts | 4. Ratchet Tree Concepts | |||
The protocol uses "ratchet trees" for deriving shared secrets among a | The protocol uses "ratchet trees" for deriving shared secrets among a | |||
group of clients. A ratchet tree is an arrangement of secrets and | group of clients. A ratchet tree is an arrangement of secrets and | |||
key pairs among the members of a group in a way that allows for | key pairs among the members of a group in a way that allows for | |||
secrets to be efficiently updated to reflect changes in the group. | secrets to be efficiently updated to reflect changes in the group. | |||
Ratchet trees allow a group to efficiently remove any member by | Ratchet trees allow a group to efficiently remove any member by | |||
encrypting new entropy to a subset of the group. A ratchet tree | encrypting new entropy to a subset of the group. A ratchet tree | |||
skipping to change at page 30, line 7 ¶ | skipping to change at line 895 ¶ | |||
is the number of members in the group). | is the number of members in the group). | |||
This remove operation allows MLS to efficiently achieve post- | This remove operation allows MLS to efficiently achieve post- | |||
compromise security. In an Update proposal or a full Commit message, | compromise security. In an Update proposal or a full Commit message, | |||
an old (possibly compromised) representation of a member is | an old (possibly compromised) representation of a member is | |||
efficiently removed from the group and replaced with a freshly | efficiently removed from the group and replaced with a freshly | |||
generated instance. | generated instance. | |||
4.1. Ratchet Tree Terminology | 4.1. Ratchet Tree Terminology | |||
Trees consist of _nodes_. A node is a _leaf_ if it has no children, | Trees consist of _nodes_. A node is a _leaf_ if it has no children; | |||
and a _parent_ otherwise; note that all parents in our trees have | otherwise, it is a _parent_. All parents in our trees have precisely | |||
precisely two children, a _left_ child and a _right_ child. A node | two children, a _left_ child and a _right_ child. A node is the | |||
is the _root_ of a tree if it has no parents, and _intermediate_ if | _root_ of a tree if it has no parent, and _intermediate_ if it has | |||
it has both children and parents. The _descendants_ of a node are | both children and a parent. The _descendants_ of a node are that | |||
that node's children, and the descendants of its children, and we say | node's children, and the descendants of its children. We say a tree | |||
a tree _contains_ a node if that node is a descendant of the root of | _contains_ a node if that node is a descendant of the root of the | |||
the tree, or if the node itself is the root of the tree. Nodes are | tree, or if the node itself is the root of the tree. Nodes are | |||
_siblings_ if they share the same parent. | _siblings_ if they share the same parent. | |||
A _subtree_ of a tree is the tree given by any node (the _head_ of | A _subtree_ of a tree is the tree given by any node (the _head_ of | |||
the subtree) and its descendants. The _size_ of a tree or subtree is | the subtree) and its descendants. The _size_ of a tree or subtree is | |||
the number of leaf nodes it contains. For a given parent node, its | the number of leaf nodes it contains. For a given parent node, its | |||
_left subtree_ is the subtree with its left child as head | _left subtree_ is the subtree with its left child as head and its | |||
(respectively _right subtree_). | _right subtree_ is the subtree with its right child as head. | |||
Every tree used in this protocol is a perfect binary tree, that is, a | Every tree used in this protocol is a perfect binary tree, that is, a | |||
complete balanced binary tree with 2^d leaves all at the same depth | complete balanced binary tree with 2^d leaves all at the same depth | |||
d. This structure is unique for a given depth d. | d. This structure is unique for a given depth d. | |||
There are multiple ways that an implementation might represent a | There are multiple ways that an implementation might represent a | |||
ratchet tree in memory. A convenient property of left-balanced | ratchet tree in memory. A convenient property of left-balanced | |||
binary trees (including the complete trees used here) is that they | binary trees (including the complete trees used here) is that they | |||
can be represented as an array of nodes, with node relationships | can be represented as an array of nodes, with node relationships | |||
computed based on the nodes' indices in the array. A more | computed based on the nodes' indices in the array. A more | |||
traditional representation based on linked node objects may also be | traditional representation based on linked node objects may also be | |||
used. Appendix C and Appendix D provide some details on how to | used. Appendices C and D provide some details on how to implement | |||
implement the tree operations required for MLS in these | the tree operations required for MLS in these representations. MLS | |||
representations. MLS places no requirements on implementations' | places no requirements on implementations' internal representations | |||
internal representations of ratchet trees. An implementation may use | of ratchet trees. An implementation may use any tree representation | |||
any tree representation and associated algorithms, as long as they | and associated algorithms, as long as they produce correct protocol | |||
produce correct protocol messages. | messages. | |||
4.1.1. Ratchet Tree Nodes | 4.1.1. Ratchet Tree Nodes | |||
Each leaf node in a ratchet tree is given an _index_ (or _leaf | Each leaf node in a ratchet tree is given an _index_ (or _leaf | |||
index_), starting at 0 from the left to 2^d - 1 at the right (for a | index_), starting at 0 from the left to 2^d - 1 at the right (for a | |||
tree with 2^d leaves). A tree with 2^d leaves has 2^(d+1) - 1 nodes, | tree with 2^d leaves). A tree with 2^d leaves has 2^(d+1) - 1 nodes, | |||
including parent nodes. | including parent nodes. | |||
Each node in a ratchet tree is either _blank_ (containing no value) | Each node in a ratchet tree is either _blank_ (containing no value) | |||
or it holds an HPKE public key with some associated data: | or it holds an HPKE public key with some associated data: | |||
* A public key (for the HPKE scheme in use, see Section 5.1) | * A public key (for the HPKE scheme in use; see Section 5.1) | |||
* A credential (only for leaf nodes; see Section 5.3) | ||||
* A credential (only for leaf nodes, see Section 5.3) | ||||
* An ordered list of "unmerged" leaves (see Section 4.2) | * An ordered list of "unmerged" leaves (see Section 4.2) | |||
* A hash of certain information about the node's parent, as of the | * A hash of certain information about the node's parent, as of the | |||
last time the node was changed (see Section 7.9). | last time the node was changed (see Section 7.9). | |||
As described in Section 4.2, different members know different subsets | As described in Section 4.2, different members know different subsets | |||
of the set of private keys corresponding to the public keys in nodes | of the set of private keys corresponding to the public keys in nodes | |||
in the tree. The private key corresponding to a parent node is known | in the tree. The private key corresponding to a parent node is known | |||
only to members at leaf nodes that are descedants of that node. The | only to members at leaf nodes that are descendants of that node. The | |||
private key corresponding to a leaf node is known only to the member | private key corresponding to a leaf node is known only to the member | |||
at that leaf node. A leaf node is _unmerged_ relative to one of its | at that leaf node. A leaf node is _unmerged_ relative to one of its | |||
ancestor nodes if the member at the leaf node does not know the | ancestor nodes if the member at the leaf node does not know the | |||
private key corresponding to the ancestor node. | private key corresponding to the ancestor node. | |||
Every node, regardless of whether the node is blank or populated, has | Every node, regardless of whether the node is blank or populated, has | |||
a corresponding _hash_ that summarizes the contents of the subtree | a corresponding _hash_ that summarizes the contents of the subtree | |||
below that node. The rules for computing these hashes are described | below that node. The rules for computing these hashes are described | |||
in Section 7.8. | in Section 7.8. | |||
The _resolution_ of a node is an ordered list of non-blank nodes that | The _resolution_ of a node is an ordered list of non-blank nodes that | |||
collectively cover all non-blank descendants of the node. The | collectively cover all non-blank descendants of the node. The | |||
resolution of the root contains the set of keys which are | resolution of the root contains the set of keys that are collectively | |||
collectively necessary to encrypt to every node in the group. The | necessary to encrypt to every node in the group. The resolution of a | |||
resolution of a node is effectively a depth-first, left-first | node is effectively a depth-first, left-first enumeration of the | |||
enumeration of the nearest non-blank nodes below the node: | nearest non-blank nodes below the node: | |||
* The resolution of a non-blank node comprises the node itself, | * The resolution of a non-blank node comprises the node itself, | |||
followed by its list of unmerged leaves, if any | followed by its list of unmerged leaves, if any. | |||
* The resolution of a blank leaf node is the empty list | * The resolution of a blank leaf node is the empty list. | |||
* The resolution of a blank intermediate node is the result of | * The resolution of a blank intermediate node is the result of | |||
concatenating the resolution of its left child with the resolution | concatenating the resolution of its left child with the resolution | |||
of its right child, in that order | of its right child, in that order. | |||
For example, consider the following subtree, where the _ character | For example, consider the following subtree, where the _ character | |||
represents a blank node and unmerged leaves are indicated in square | represents a blank node and unmerged leaves are indicated in square | |||
brackets: | brackets: | |||
... | ... | |||
/ | / | |||
_ | _ | |||
______|______ | ______|______ | |||
/ \ | / \ | |||
X[B] _ | X[B] _ | |||
__|__ __|__ | __|__ __|__ | |||
/ \ / \ | / \ / \ | |||
_ _ Y _ | _ _ Y _ | |||
/ \ / \ / \ / \ | / \ / \ / \ / \ | |||
A B _ D E F _ H | A B _ D E F _ H | |||
0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 | |||
Figure 10: A tree with blanks and unmerged leaves | Figure 10: A Tree with Blanks and Unmerged Leaves | |||
In this tree, we can see all of the above rules in play: | In this tree, we can see all of the above rules in play: | |||
* The resolution of node X is the list [X, B] | * The resolution of node X is the list [X, B]. | |||
* The resolution of leaf 2 or leaf 6 is the empty list [] | * The resolution of leaf 2 or leaf 6 is the empty list []. | |||
* The resolution of top node is the list [X, B, Y, H] | * The resolution of top node is the list [X, B, Y, H]. | |||
4.1.2. Paths through a Ratchet Tree | 4.1.2. Paths through a Ratchet Tree | |||
The _direct path_ of a root is the empty list, and of any other node | The _direct path_ of a root is the empty list. The direct path of | |||
is the concatenation of that node's parent along with the parent's | any other node is the concatenation of that node's parent along with | |||
direct path. | the parent's direct path. | |||
The _copath_ of a node is the node's sibling concatenated with the | The _copath_ of a node is the node's sibling concatenated with the | |||
list of siblings of all the nodes in its direct path, excluding the | list of siblings of all the nodes in its direct path, excluding the | |||
root. | root. | |||
The _filtered direct path_ of a leaf node L is the node's direct | The _filtered direct path_ of a leaf node L is the node's direct | |||
path, with any node removed whose child on the copath of L has an | path, with any node removed whose child on the copath of L has an | |||
empty resolution (keeping in mind that any unmerged leaves of the | empty resolution (keeping in mind that any unmerged leaves of the | |||
copath child count toward its resolution). The removed nodes do not | copath child count toward its resolution). The removed nodes do not | |||
need their own key pairs because encrypting to the node's key pair | need their own key pairs because encrypting to the node's key pair | |||
skipping to change at page 33, line 19 ¶ | skipping to change at line 1039 ¶ | |||
_=U Y | _=U Y | |||
| | | | | | |||
.-+-. .-+-. | .-+-. .-+-. | |||
/ \ / \ | / \ / \ | |||
T _=V X _=Z | T _=V X _=Z | |||
/ \ / \ / \ / \ | / \ / \ / \ / \ | |||
A B _ _ E F G _=H | A B _ _ E F G _=H | |||
0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 | |||
Figure 11: A complete tree with five members, with labels for | Figure 11: A Complete Tree with Five Members, with Labels for | |||
blank parent nodes | Blank Parent Nodes | |||
In this tree, the direct paths, copaths, and filtered direct paths | In this tree, the direct paths, copaths, and filtered direct paths | |||
for the leaf nodes are as follows: | for the leaf nodes are as follows: | |||
+======+=============+=========+======================+ | +======+=============+=========+======================+ | |||
| Node | Direct path | Copath | Filtered Direct Path | | | Node | Direct path | Copath | Filtered Direct Path | | |||
+======+=============+=========+======================+ | +======+=============+=========+======================+ | |||
| A | T, U, W | B, V, Y | T, W | | | A | T, U, W | B, V, Y | T, W | | |||
+------+-------------+---------+----------------------+ | +------+-------------+---------+----------------------+ | |||
| B | T, U, W | A, V, Y | T, W | | | B | T, U, W | A, V, Y | T, W | | |||
skipping to change at page 34, line 8 ¶ | skipping to change at line 1076 ¶ | |||
associated with the leaf nodes. | associated with the leaf nodes. | |||
No participant in an MLS group knows the private key associated with | No participant in an MLS group knows the private key associated with | |||
every node in the tree. Instead, each member is assigned to a leaf | every node in the tree. Instead, each member is assigned to a leaf | |||
of the tree, which determines the subset of private keys it knows. | of the tree, which determines the subset of private keys it knows. | |||
The credential stored at that leaf is one provided by the member. | The credential stored at that leaf is one provided by the member. | |||
In particular, MLS maintains the members' views of the tree in such a | In particular, MLS maintains the members' views of the tree in such a | |||
way as to maintain the _tree invariant_: | way as to maintain the _tree invariant_: | |||
The private key for a node in the tree is known to a member of | | The private key for a node in the tree is known to a member of the | |||
the group only if the node's subtree contains that member's leaf. | | group only if the node's subtree contains that member's leaf. | |||
In other words, if a node is not blank, then it holds a public key. | In other words, if a node is not blank, then it holds a public key. | |||
The corresponding private key is known only to members occupying | The corresponding private key is known only to members occupying | |||
leaves below that node. | leaves below that node. | |||
The reverse implication is not true: A member may not know the | The reverse implication is not true: A member may not know the | |||
private key of an intermediate node above them. Such a member has an | private key of an intermediate node above them. Such a member has an | |||
_unmerged_ leaf at the intermediate node. Encrypting to an | _unmerged_ leaf at the intermediate node. Encrypting to an | |||
intermediate node requires encrypting to the node's public key, as | intermediate node requires encrypting to the node's public key, as | |||
well as the public keys of all the unmerged leaves below it. A leaf | well as the public keys of all the unmerged leaves below it. A leaf | |||
skipping to change at page 35, line 4 ¶ | skipping to change at line 1117 ¶ | |||
/ \ / \ | / \ / \ | |||
pk(A) pk(B) pk(C) pk(D) | pk(A) pk(B) pk(C) pk(D) | |||
Private @ A Private @ B Private @ C Private @ D | Private @ A Private @ B Private @ C Private @ D | |||
============= ============= ============= ============= | ============= ============= ============= ============= | |||
ABCD ABCD ABCD ABCD | ABCD ABCD ABCD ABCD | |||
/ \ / \ / \ / \ | / \ / \ / \ / \ | |||
AB _ AB _ ? _ ? _ | AB _ AB _ ? _ ? _ | |||
/ \ / \ / \ / \ / \ / \ / \ / \ | / \ / \ / \ / \ / \ / \ / \ / \ | |||
A ? ? ? ? B ? ? ? ? C ? ? ? ? D | A ? ? ? ? B ? ? ? ? C ? ? ? ? D | |||
Note how the tree invariant applies: Each member knows only their own | Note how the tree invariant applies: Each member knows only their own | |||
leaf, the private key AB is known only to A and B, and the private | leaf, the private key AB is known only to A and B, and the private | |||
key ABCD is known to all four members. This also illustrates another | key ABCD is known to all four members. This also illustrates another | |||
important point: it is possible for there to be "holes" on the path | important point: it is possible for there to be "holes" on the path | |||
from a member's leaf to the root in which the member knows the key | from a member's leaf to the root in which the member knows the key | |||
both above and below a given node, but not for that node, as in the | both above and below a given node, but not for that node, as in the | |||
case with D. | case with D. | |||
5. Cryptographic Objects | 5. Cryptographic Objects | |||
5.1. Ciphersuites | 5.1. Cipher Suites | |||
Each MLS session uses a single ciphersuite that specifies the | Each MLS session uses a single cipher suite that specifies the | |||
following primitives to be used in group key computations: | following primitives to be used in group key computations: | |||
* HPKE parameters: | * HPKE parameters: | |||
- A Key Encapsulation Mechanism (KEM) | - A Key Encapsulation Mechanism (KEM) | |||
- A Key Derivation Function (KDF) | - A Key Derivation Function (KDF) | |||
- An Authenticated Encryption with Associated Data (AEAD) | - An Authenticated Encryption with Associated Data (AEAD) | |||
encryption algorithm | encryption algorithm | |||
* A hash algorithm | * A hash algorithm | |||
* A MAC algorithm | * A Message Authentication Code (MAC) algorithm | |||
* A signature algorithm | * A signature algorithm | |||
MLS uses HPKE for public-key encryption [RFC9180]. The DeriveKeyPair | MLS uses HPKE for public key encryption [RFC9180]. The DeriveKeyPair | |||
function associated to the KEM for the ciphersuite maps octet strings | function associated to the KEM for the cipher suite maps octet | |||
to HPKE key pairs. As in HPKE, MLS assumes that an AEAD algorithm | strings to HPKE key pairs. As in HPKE, MLS assumes that an AEAD | |||
produces a single ciphertext output from AEAD encryption (aligning | algorithm produces a single ciphertext output from AEAD encryption | |||
with [RFC5116]), as opposed to a separate ciphertext and tag. | (aligning with [RFC5116]), as opposed to a separate ciphertext and | |||
tag. | ||||
Ciphersuites are represented with the CipherSuite type. The | Cipher suites are represented with the CipherSuite type. The cipher | |||
ciphersuites are defined in Section 17.1. | suites are defined in Section 17.1. | |||
5.1.1. Public Keys | 5.1.1. Public Keys | |||
HPKE public keys are opaque values in a format defined by the | HPKE public keys are opaque values in a format defined by the | |||
underlying protocol (see Section 4 of [RFC9180] for more | underlying protocol (see Section 4 of [RFC9180] for more | |||
information). | information). | |||
opaque HPKEPublicKey<V>; | opaque HPKEPublicKey<V>; | |||
Signature public keys are likewise represented as opaque values in a | Signature public keys are likewise represented as opaque values in a | |||
format defined by the ciphersuite's signature scheme. | format defined by the cipher suite's signature scheme. | |||
opaque SignaturePublicKey<V>; | opaque SignaturePublicKey<V>; | |||
For ciphersuites using Ed25519 or Ed448 signature schemes, the public | For cipher suites using the Edwards-curve Digital Signature Algorithm | |||
key is in the format specified in [RFC8032]. For ciphersuites using | (EdDSA) signature schemes (Ed25519 or Ed448), the public key is in | |||
ECDSA with the NIST curves (P-256, P-384, or P-521), the public key | the format specified in [RFC8032]. | |||
is represented as an encoded UncompressedPointRepresentation struct, | ||||
as defined in [RFC8446]. | For cipher suites using the Elliptic Curve Digital Signature | |||
Algorithm (ECDSA) with the NIST curves (P-256, P-384, or P-521), the | ||||
public key is represented as an encoded | ||||
UncompressedPointRepresentation struct, as defined in [RFC8446]. | ||||
5.1.2. Signing | 5.1.2. Signing | |||
The signature algorithm specified in a group's ciphersuite is the | The signature algorithm specified in a group's cipher suite is the | |||
mandatory algorithm to be used for signing messages within the group. | mandatory algorithm to be used for signing messages within the group. | |||
It MUST be the same as the signature algorithm specified in the | It MUST be the same as the signature algorithm specified in the | |||
credentials in the leaves of the tree (including the leaf node | credentials in the leaves of the tree (including the leaf node | |||
information in KeyPackages used to add new members). | information in KeyPackages used to add new members). | |||
The signatures used in this document are encoded as specified in | The signatures used in this document are encoded as specified in | |||
[RFC8446]. In particular, ECDSA signatures are DER-encoded and EdDSA | [RFC8446]. In particular, ECDSA signatures are DER encoded, and | |||
signatures are defined as the concatenation of r and s as specified | EdDSA signatures are defined as the concatenation of R and S, as | |||
in [RFC8032]. | specified in [RFC8032]. | |||
To disambiguate different signatures used in MLS, each signed value | To disambiguate different signatures used in MLS, each signed value | |||
is prefixed by a label as shown below: | is prefixed by a label as shown below: | |||
SignWithLabel(SignatureKey, Label, Content) = | SignWithLabel(SignatureKey, Label, Content) = | |||
Signature.Sign(SignatureKey, SignContent) | Signature.Sign(SignatureKey, SignContent) | |||
VerifyWithLabel(VerificationKey, Label, Content, SignatureValue) = | VerifyWithLabel(VerificationKey, Label, Content, SignatureValue) = | |||
Signature.Verify(VerificationKey, SignContent, SignatureValue) | Signature.Verify(VerificationKey, SignContent, SignatureValue) | |||
Where SignContent is specified as: | Where SignContent is specified as: | |||
struct { | struct { | |||
opaque label<V>; | opaque label<V>; | |||
opaque content<V>; | opaque content<V>; | |||
} SignContent; | } SignContent; | |||
And its fields set to: | And its fields are set to: | |||
label = "MLS 1.0 " + Label; | label = "MLS 1.0 " + Label; | |||
content = Content; | content = Content; | |||
Here, the functions Signature.Sign and Signature.Verify are defined | ||||
by the signature algorithm. If MLS extensions require signatures by | The functions Signature.Sign and Signature.Verify are defined by the | |||
group members, they should re-use the SignWithLabel construction, | signature algorithm. If MLS extensions require signatures by group | |||
using a distinct label. To avoid collisions in these labels, an IANA | members, they should reuse the SignWithLabel construction, using a | |||
distinct label. To avoid collisions in these labels, an IANA | ||||
registry is defined in Section 17.6. | registry is defined in Section 17.6. | |||
5.1.3. Public-Key Encryption | 5.1.3. Public Key Encryption | |||
As with signing, MLS includes a label and context in encryption | As with signing, MLS includes a label and context in encryption | |||
operations to avoid confusion between ciphertexts produced for | operations to avoid confusion between ciphertexts produced for | |||
different purposes. Encryption and decryption including this label | different purposes. Encryption and decryption including this label | |||
and context are done as follows: | and context are done as follows: | |||
EncryptWithLabel(PublicKey, Label, Context, Plaintext) = | EncryptWithLabel(PublicKey, Label, Context, Plaintext) = | |||
SealBase(PublicKey, EncryptContext, "", Plaintext) | SealBase(PublicKey, EncryptContext, "", Plaintext) | |||
DecryptWithLabel(PrivateKey, Label, Context, KEMOutput, Ciphertext) = | DecryptWithLabel(PrivateKey, Label, Context, KEMOutput, Ciphertext) = | |||
OpenBase(KEMOutput, PrivateKey, EncryptContext, "", Ciphertext) | OpenBase(KEMOutput, PrivateKey, EncryptContext, "", Ciphertext) | |||
Where EncryptContext is specified as: | Where EncryptContext is specified as: | |||
struct { | struct { | |||
opaque label<V>; | opaque label<V>; | |||
opaque context<V>; | opaque context<V>; | |||
} EncryptContext; | } EncryptContext; | |||
And its fields set to: | And its fields are set to: | |||
label = "MLS 1.0 " + Label; | label = "MLS 1.0 " + Label; | |||
context = Context; | context = Context; | |||
Here, the functions SealBase and OpenBase are defined [RFC9180], | The functions SealBase and OpenBase are defined in Section 6.1 of | |||
using the HPKE algorithms specified by the group's ciphersuite. If | [RFC9180] (with "Base" as the MODE), using the HPKE algorithms | |||
MLS extensions require HPKE encryption operations, they should re-use | specified by the group's cipher suite. If MLS extensions require | |||
the EncryptWithLabel construction, using a distinct label. To avoid | HPKE encryption operations, they should reuse the EncryptWithLabel | |||
collisions in these labels, an IANA registry is defined in | construction, using a distinct label. To avoid collisions in these | |||
Section 17.7. | labels, an IANA registry is defined in Section 17.7. | |||
5.2. Hash-Based Identifiers | 5.2. Hash-Based Identifiers | |||
Some MLS messages refer to other MLS objects by hash. For example, | Some MLS messages refer to other MLS objects by hash. For example, | |||
Welcome messages refer to KeyPackages for the members being welcomed, | Welcome messages refer to KeyPackages for the members being welcomed, | |||
and Commits refer to Proposals they cover. These identifiers are | and Commits refer to Proposals they cover. These identifiers are | |||
computed as follows: | computed as follows: | |||
opaque HashReference<V>; | opaque HashReference<V>; | |||
HashReference KeyPackageRef; | HashReference KeyPackageRef; | |||
HashReference ProposalRef; | HashReference ProposalRef; | |||
MakeKeyPackageRef(value) = RefHash("MLS 1.0 KeyPackage Reference", value) | MakeKeyPackageRef(value) | |||
MakeProposalRef(value) = RefHash("MLS 1.0 Proposal Reference", value) | = RefHash("MLS 1.0 KeyPackage Reference", value) | |||
MakeProposalRef(value) | ||||
= RefHash("MLS 1.0 Proposal Reference", value) | ||||
RefHash(label, value) = Hash(RefHashInput) | RefHash(label, value) = Hash(RefHashInput) | |||
Where RefHashInput is defined as: | Where RefHashInput is defined as: | |||
struct { | struct { | |||
opaque label<V>; | opaque label<V>; | |||
opaque value<V>; | opaque value<V>; | |||
} RefHashInput; | } RefHashInput; | |||
And its fields set to: | And its fields are set to: | |||
label = label; | label = label; | |||
value = value; | value = value; | |||
For a KeyPackageRef, the value input is the encoded KeyPackage, and | For a KeyPackageRef, the value input is the encoded KeyPackage, and | |||
the ciphersuite specified in the KeyPackage determines the KDF used. | the cipher suite specified in the KeyPackage determines the KDF used. | |||
For a ProposalRef, the value input is the AuthenticatedContent | For a ProposalRef, the value input is the AuthenticatedContent | |||
carrying the proposal. In the latter two cases, the KDF is | carrying the Proposal. In the latter two cases, the KDF is | |||
determined by the group's ciphersuite. | determined by the group's cipher suite. | |||
5.3. Credentials | 5.3. Credentials | |||
Each member of a group presents a credential that provides one or | Each member of a group presents a credential that provides one or | |||
more identities for the member, and associates them with the member's | more identities for the member and associates them with the member's | |||
signing key. The identities and signing key are verified by the | signing key. The identities and signing key are verified by the | |||
Authentication Service in use for a group. | Authentication Service in use for a group. | |||
It is up to the application to decide which identifier or identifiers | It is up to the application to decide which identifiers to use at the | |||
to use at the application level. For example, a certificate in an | application level. For example, a certificate in an X509Credential | |||
X509Credential may attest to several domain names or email addresses | may attest to several domain names or email addresses in its | |||
in its subjectAltName extension. An application may decide to | subjectAltName extension. An application may decide to present all | |||
present all of these to a user, or if it knows a "desired" domain | of these to a user, or if it knows a "desired" domain name or email | |||
name or email address, it can check that the desired identifier is | address, it can check that the desired identifier is among those | |||
among those attested. Using the terminology from [RFC6125], a | attested. Using the terminology from [RFC6125], a credential | |||
Credential provides "presented identifiers", and it is up to the | provides "presented identifiers", and it is up to the application to | |||
application to supply a "reference identifier" for the authenticated | supply a "reference identifier" for the authenticated client, if any. | |||
client, if any. | ||||
// See IANA registry for registered values | // See the "MLS Credential Types" IANA registry for values | |||
uint16 CredentialType; | uint16 CredentialType; | |||
struct { | struct { | |||
opaque cert_data<V>; | opaque cert_data<V>; | |||
} Certificate; | } Certificate; | |||
struct { | struct { | |||
CredentialType credential_type; | CredentialType credential_type; | |||
select (Credential.credential_type) { | select (Credential.credential_type) { | |||
case basic: | case basic: | |||
skipping to change at page 40, line 6 ¶ | skipping to change at line 1351 ¶ | |||
words, following the model that [RFC6125] describes for TLS, the | words, following the model that [RFC6125] describes for TLS, the | |||
application maintains a list of "reference identifiers" for the | application maintains a list of "reference identifiers" for the | |||
members of a group, and the credentials provide "presented | members of a group, and the credentials provide "presented | |||
identifiers". A member of a group is authenticated by first | identifiers". A member of a group is authenticated by first | |||
validating that the member's credential legitimately represents some | validating that the member's credential legitimately represents some | |||
presented identifiers, and then ensuring that the reference | presented identifiers, and then ensuring that the reference | |||
identifiers for the member are authenticated by those presented | identifiers for the member are authenticated by those presented | |||
identifiers. | identifiers. | |||
The parts of the system that perform these functions are collectively | The parts of the system that perform these functions are collectively | |||
referred to as the Authentication Service (AS) | referred to as the Authentication Service (AS) [MLS-ARCH]. A | |||
[I-D.ietf-mls-architecture]. A member's credential is said to be | member's credential is said to be _validated with the AS_ when the AS | |||
_validated with the AS_ when the AS verifies that the credential's | verifies that the credential's presented identifiers are correctly | |||
presented identifiers are correctly associated with the signature_key | associated with the signature_key field in the member's LeafNode, and | |||
field in the member's LeafNode, and verifies that those identifiers | that those identifiers match the reference identifiers for the | |||
match the reference identifiers for the member. | member. | |||
Whenever a new credential is introduced in the group, it MUST be | Whenever a new credential is introduced in the group, it MUST be | |||
validated with the AS. In particular, at the following events in the | validated with the AS. In particular, at the following events in the | |||
protocol: | protocol: | |||
* When a member receives a KeyPackage that it will use in an Add | * When a member receives a KeyPackage that it will use in an Add | |||
proposal to add a new member to the group. | proposal to add a new member to the group | |||
* When a member receives a GroupInfo object that it will use to join | * When a member receives a GroupInfo object that it will use to join | |||
a group, either via a Welcome or via an External Commit | a group, either via a Welcome or via an external Commit | |||
* When a member receives an Add proposal adding a member to the | * When a member receives an Add proposal adding a member to the | |||
group. | group | |||
* When a member receives an Update proposal whose LeafNode has a new | * When a member receives an Update proposal whose LeafNode has a new | |||
credential for the member. | credential for the member | |||
* When a member receives a Commit with an UpdatePath whose LeafNode | * When a member receives a Commit with an UpdatePath whose LeafNode | |||
has a new credential for the committer. | has a new credential for the committer | |||
* When an external_senders extension is added to the group, or an | * When an external_senders extension is added to the group | |||
existing external_senders extension is updated. | ||||
In cases where a member's credential is being replaced, such as | * When an existing external_senders extension is updated | |||
In cases where a member's credential is being replaced, such as the | ||||
Update and Commit cases above, the AS MUST also verify that the set | Update and Commit cases above, the AS MUST also verify that the set | |||
of presented identifiers in the new credential is valid as a | of presented identifiers in the new credential is valid as a | |||
successor to the set of presented identifiers in the old credential, | successor to the set of presented identifiers in the old credential, | |||
according to the application's policy. | according to the application's policy. | |||
5.3.2. Credential Expiry and Revocation | 5.3.2. Credential Expiry and Revocation | |||
In some credential schemes, a valid credential can "expire", or | In some credential schemes, a valid credential can "expire" or become | |||
become invalid after a certain point in time. For example, each | invalid after a certain point in time. For example, each X.509 | |||
X.509 certificate has a notAfter field, expressing a time after which | certificate has a notAfter field, expressing a time after which the | |||
the certificate is not valid. | certificate is not valid. | |||
Expired credentials can cause operational problems in light of the | Expired credentials can cause operational problems in light of the | |||
validation requirements of Section 5.3.1. Applications can apply | validation requirements of Section 5.3.1. Applications can apply | |||
some operational practices and adaptations to Authentication Service | some operational practices and adaptations to Authentication Service | |||
policies to moderate these impacts. | policies to moderate these impacts. | |||
In general, to avoid operational problems such as new joiners | In general, to avoid operational problems such as new joiners | |||
rejecting expired credentials in a group, applications that use such | rejecting expired credentials in a group, applications that use such | |||
credentials should ensure to the extent practical that all of the | credentials should ensure to the extent practical that all of the | |||
credentials in use in a group are valid at all times. | credentials in use in a group are valid at all times. | |||
skipping to change at page 41, line 30 ¶ | skipping to change at line 1424 ¶ | |||
If a member finds that another member's credential has expired, they | If a member finds that another member's credential has expired, they | |||
may issue a Remove that removes that member. For example, an | may issue a Remove that removes that member. For example, an | |||
application could require a member preparing to issue a Commit to | application could require a member preparing to issue a Commit to | |||
check the tree for expired credentials and include Remove proposals | check the tree for expired credentials and include Remove proposals | |||
for those members in its Commit. In situations where the group tree | for those members in its Commit. In situations where the group tree | |||
is known to the DS, the DS could also monitor the tree for expired | is known to the DS, the DS could also monitor the tree for expired | |||
credentials and issue external Remove proposals. | credentials and issue external Remove proposals. | |||
Some credential schemes also allow credentials to be revoked. | Some credential schemes also allow credentials to be revoked. | |||
Revocation is similar to expiry, in that a previously valid | Revocation is similar to expiry in that a previously valid credential | |||
credential becomes invalid. As such, most of the considerations | becomes invalid. As such, most of the considerations above also | |||
above also apply to revoked credentials. However, applications may | apply to revoked credentials. However, applications may want to | |||
want to treat revoked credentials differently, e.g., removing members | treat revoked credentials differently, e.g., by removing members with | |||
with revoked credentials while allowing members with expired | revoked credentials while allowing members with expired credentials | |||
credentials time to update. | time to update. | |||
5.3.3. Uniquely Identifying Clients | 5.3.3. Uniquely Identifying Clients | |||
MLS implementations will presumably provide applications with a way | MLS implementations will presumably provide applications with a way | |||
to request protocol operations with regard to other clients (e.g., | to request protocol operations with regard to other clients (e.g., | |||
removing clients). Such functions will need to refer to the other | removing clients). Such functions will need to refer to the other | |||
clients using some identifier. MLS clients have a few types of | clients using some identifier. MLS clients have a few types of | |||
identifiers, with different operational properties. | identifiers, with different operational properties. | |||
Internally to the protocol, group members are uniquely identified by | Internally to the protocol, group members are uniquely identified by | |||
skipping to change at page 42, line 31 ¶ | skipping to change at line 1474 ¶ | |||
Handshake and application messages use a common framing structure. | Handshake and application messages use a common framing structure. | |||
This framing provides encryption to ensure confidentiality within the | This framing provides encryption to ensure confidentiality within the | |||
group, as well as signing to authenticate the sender. | group, as well as signing to authenticate the sender. | |||
In most of the protocol, messages are handled in the form of | In most of the protocol, messages are handled in the form of | |||
AuthenticatedContent objects. These structures contain the content | AuthenticatedContent objects. These structures contain the content | |||
of the message itself as well as information to authenticate the | of the message itself as well as information to authenticate the | |||
sender (see Section 6.1). The additional protections required to | sender (see Section 6.1). The additional protections required to | |||
transmit these messages over an untrusted channel (group membership | transmit these messages over an untrusted channel (group membership | |||
authentication or AEAD encryption) are added by encoding the | authentication or AEAD encryption) are added by encoding the | |||
AuthenticatedContent as an PublicMessage or PrivateMessage message, | AuthenticatedContent as a PublicMessage or PrivateMessage message, | |||
which can then be sent as an MLSMessage. Likewise, these protections | which can then be sent as an MLSMessage. Likewise, these protections | |||
are enforced (via membership verification or AEAD decryption) when | are enforced (via membership verification or AEAD decryption) when | |||
decoding an PublicMessage or PrivateMessage into an | decoding a PublicMessage or PrivateMessage into an | |||
AuthenticatedContent object. | AuthenticatedContent object. | |||
PrivateMessage represents a signed and encrypted message, with | PrivateMessage represents a signed and encrypted message, with | |||
protections for both the content of the message and related metadata. | protections for both the content of the message and related metadata. | |||
PublicMessage represents a message that is only signed, and not | PublicMessage represents a message that is only signed, and not | |||
encrypted. Applications MUST use PrivateMessage to encrypt | encrypted. Applications MUST use PrivateMessage to encrypt | |||
application messages and SHOULD use PrivateMessage to encode | application messages and SHOULD use PrivateMessage to encode | |||
handshake messages, but MAY transmit handshake messages encoded as | handshake messages, but they MAY transmit handshake messages encoded | |||
PublicMessage objects in cases where it is necessary for the Delivery | as PublicMessage objects in cases where it is necessary for the | |||
Service to examine such messages. | Delivery Service to examine such messages. | |||
enum { | enum { | |||
reserved(0), | reserved(0), | |||
mls10(1), | mls10(1), | |||
(65535) | (65535) | |||
} ProtocolVersion; | } ProtocolVersion; | |||
enum { | enum { | |||
reserved(0), | reserved(0), | |||
application(1), | application(1), | |||
proposal(2), | proposal(2), | |||
commit(3), | commit(3), | |||
(255) | (255) | |||
} ContentType; | } ContentType; | |||
enum { | enum { | |||
reserved(0), | reserved(0), | |||
skipping to change at page 43, line 34 ¶ | skipping to change at line 1525 ¶ | |||
case member: | case member: | |||
uint32 leaf_index; | uint32 leaf_index; | |||
case external: | case external: | |||
uint32 sender_index; | uint32 sender_index; | |||
case new_member_commit: | case new_member_commit: | |||
case new_member_proposal: | case new_member_proposal: | |||
struct{}; | struct{}; | |||
}; | }; | |||
} Sender; | } Sender; | |||
// See IANA registry for registered values | // See the "MLS Wire Formats" IANA registry for values | |||
uint16 WireFormat; | uint16 WireFormat; | |||
struct { | struct { | |||
opaque group_id<V>; | opaque group_id<V>; | |||
uint64 epoch; | uint64 epoch; | |||
Sender sender; | Sender sender; | |||
opaque authenticated_data<V>; | opaque authenticated_data<V>; | |||
ContentType content_type; | ContentType content_type; | |||
select (FramedContent.content_type) { | select (FramedContent.content_type) { | |||
skipping to change at page 44, line 4 ¶ | skipping to change at line 1543 ¶ | |||
ContentType content_type; | ContentType content_type; | |||
select (FramedContent.content_type) { | select (FramedContent.content_type) { | |||
case application: | case application: | |||
opaque application_data<V>; | opaque application_data<V>; | |||
case proposal: | case proposal: | |||
Proposal proposal; | Proposal proposal; | |||
case commit: | case commit: | |||
Commit commit; | Commit commit; | |||
}; | }; | |||
} FramedContent; | } FramedContent; | |||
struct { | struct { | |||
ProtocolVersion version = mls10; | ProtocolVersion version = mls10; | |||
WireFormat wire_format; | WireFormat wire_format; | |||
select (MLSMessage.wire_format) { | select (MLSMessage.wire_format) { | |||
case mls_public_message: | case mls_public_message: | |||
PublicMessage public_message; | PublicMessage public_message; | |||
case mls_private_message: | case mls_private_message: | |||
PrivateMessage private_message; | PrivateMessage private_message; | |||
case mls_welcome: | case mls_welcome: | |||
Welcome welcome; | Welcome welcome; | |||
case mls_group_info: | case mls_group_info: | |||
GroupInfo group_info; | GroupInfo group_info; | |||
case mls_key_package: | case mls_key_package: | |||
KeyPackage key_package; | KeyPackage key_package; | |||
}; | }; | |||
} MLSMessage; | } MLSMessage; | |||
Messages from senders that aren't in the group are sent as | Messages from senders that aren't in the group are sent as | |||
PublicMessage. See Section 12.1.8 and Section 12.4.3.2 for more | PublicMessage. See Sections 12.1.8 and 12.4.3.2 for more details. | |||
details. | ||||
The following structure is used to fully describe the data | The following structure is used to fully describe the data | |||
transmitted in plaintexts or ciphertexts. | transmitted in plaintexts or ciphertexts. | |||
struct { | struct { | |||
WireFormat wire_format; | WireFormat wire_format; | |||
FramedContent content; | FramedContent content; | |||
FramedContentAuthData auth; | FramedContentAuthData auth; | |||
} AuthenticatedContent; | } AuthenticatedContent; | |||
The following figure illustrates how the various structures described | The following figure illustrates how the various structures described | |||
in this section relate to each other, and the high-level operations | in this section relate to each other, and the high-level operations | |||
used to produce and consume them: | used to produce and consume them: | |||
Proposal Commit Application Data | Proposal Commit Application Data | |||
| | | | | | | | |||
+--------------+--------------+ | +--------------+--------------+ | |||
| | | | |||
V | V | |||
FramedContent | FramedContent | |||
| | -. | | | -. | |||
| | | | +--------+ | | | |||
+--------+ | | | | | | | |||
| | | | V | +-- Asymmetric | |||
V | +-- Asymmetric | FramedContentAuthData | | Sign / Verify | |||
FramedContentAuthData | | Sign / Verify | | | | | |||
| | | | +--------+ | | | |||
+--------+ | | | | | | | |||
| | | | V V -' | |||
V V -' | AuthenticatedContent | |||
AuthenticatedContent | | -. | |||
| -. | +--------+--------+ | | |||
| | | | | +-- Symmetric | |||
| | | V V | Protect / Unprotect | |||
+--------+--------+ +-- Symmetric | PublicMessage PrivateMessage -' | |||
| | | Protect / Unprotect | | | | |||
V V | | | | Welcome KeyPackage GroupInfo | |||
Welcome KeyPackage GroupInfo PublicMessage PrivateMessage -' | | | | | | | |||
| | | | | | +-----------------+-----+----------+----------+ | |||
| | | | | | | | |||
+----------+----------+----+--------+-----------------+ | V | |||
| | MLSMessage | |||
V | ||||
MLSMessage | ||||
Figure 12: Relationships among MLS objects | Figure 12: Relationships among MLS Objects | |||
6.1. Content Authentication | 6.1. Content Authentication | |||
FramedContent is authenticated using the FramedContentAuthData | FramedContent is authenticated using the FramedContentAuthData | |||
structure. | structure. | |||
struct { | struct { | |||
ProtocolVersion version = mls10; | ProtocolVersion version = mls10; | |||
WireFormat wire_format; | WireFormat wire_format; | |||
FramedContent content; | FramedContent content; | |||
skipping to change at page 47, line 16 ¶ | skipping to change at line 1670 ¶ | |||
in the external_senders group context extension (see | in the external_senders group context extension (see | |||
Section 12.1.8.1). The content_type of the message MUST be | Section 12.1.8.1). The content_type of the message MUST be | |||
proposal and the proposal_type MUST be a value that is allowed for | proposal and the proposal_type MUST be a value that is allowed for | |||
external senders. | external senders. | |||
* new_member_commit: The signature key in the LeafNode in the | * new_member_commit: The signature key in the LeafNode in the | |||
Commit's path (see Section 12.4.3.2). The content_type of the | Commit's path (see Section 12.4.3.2). The content_type of the | |||
message MUST be commit. | message MUST be commit. | |||
* new_member_proposal: The signature key in the LeafNode in the | * new_member_proposal: The signature key in the LeafNode in the | |||
KeyPackage embedded in an External Add Proposal. The content_type | KeyPackage embedded in an external Add proposal. The content_type | |||
of the message MUST be proposal and the proposal_type of the | of the message MUST be proposal and the proposal_type of the | |||
Proposal MUST be add. | Proposal MUST be add. | |||
Recipients of an MLSMessage MUST verify the signature with the key | Recipients of an MLSMessage MUST verify the signature with the key | |||
depending on the sender_type of the sender as described above. | depending on the sender_type of the sender as described above. | |||
The confirmation tag value confirms that the members of the group | The confirmation tag value confirms that the members of the group | |||
have arrived at the same state of the group. A FramedContentAuthData | have arrived at the same state of the group. A FramedContentAuthData | |||
is said to be valid when both the signature and confirmation_tag | is said to be valid when both the signature and confirmation_tag | |||
fields are valid. | fields are valid. | |||
skipping to change at page 48, line 12 ¶ | skipping to change at line 1711 ¶ | |||
the sender's membership in the group. For messages sent by members, | the sender's membership in the group. For messages sent by members, | |||
it MUST be set to the following value: | it MUST be set to the following value: | |||
struct { | struct { | |||
FramedContentTBS content_tbs; | FramedContentTBS content_tbs; | |||
FramedContentAuthData auth; | FramedContentAuthData auth; | |||
} AuthenticatedContentTBM; | } AuthenticatedContentTBM; | |||
membership_tag = MAC(membership_key, AuthenticatedContentTBM) | membership_tag = MAC(membership_key, AuthenticatedContentTBM) | |||
When decoding an PublicMessage into an AuthenticatedContent, the | When decoding a PublicMessage into an AuthenticatedContent, the | |||
application MUST check membership_tag and MUST check that the | application MUST check membership_tag and MUST check that the | |||
FramedContentAuthData is valid. | FramedContentAuthData is valid. | |||
6.3. Encoding and Decoding a Private Message | 6.3. Encoding and Decoding a Private Message | |||
Authenticated and encrypted messages are encoded using the | Authenticated and encrypted messages are encoded using the | |||
PrivateMessage structure. | PrivateMessage structure. | |||
struct { | struct { | |||
opaque group_id<V>; | opaque group_id<V>; | |||
uint64 epoch; | uint64 epoch; | |||
ContentType content_type; | ContentType content_type; | |||
opaque authenticated_data<V>; | opaque authenticated_data<V>; | |||
opaque encrypted_sender_data<V>; | opaque encrypted_sender_data<V>; | |||
opaque ciphertext<V>; | opaque ciphertext<V>; | |||
} PrivateMessage; | } PrivateMessage; | |||
encrypted_sender_data and ciphertext are encrypted using the AEAD | encrypted_sender_data and ciphertext are encrypted using the AEAD | |||
function specified by the ciphersuite in use, using as input the | function specified by the cipher suite in use, using the SenderData | |||
structures SenderData and PrivateMessageContent. | and PrivateMessageContent structures as input. | |||
6.3.1. Content Encryption | 6.3.1. Content Encryption | |||
Content to be encrypted is encoded in a PrivateMessageContent | Content to be encrypted is encoded in a PrivateMessageContent | |||
structure. | structure. | |||
struct { | struct { | |||
select (PrivateMessage.content_type) { | select (PrivateMessage.content_type) { | |||
case application: | case application: | |||
opaque application_data<V>; | opaque application_data<V>; | |||
skipping to change at page 49, line 22 ¶ | skipping to change at line 1755 ¶ | |||
case commit: | case commit: | |||
Commit commit; | Commit commit; | |||
}; | }; | |||
FramedContentAuthData auth; | FramedContentAuthData auth; | |||
opaque padding[length_of_padding]; | opaque padding[length_of_padding]; | |||
} PrivateMessageContent; | } PrivateMessageContent; | |||
The padding field is set by the sender, by first encoding the content | The padding field is set by the sender, by first encoding the content | |||
(via the select) and the auth field, then appending the chosen number | (via the select) and the auth field, and then appending the chosen | |||
of zero bytes. A receiver identifies the padding field in a | number of zero bytes. A receiver identifies the padding field in a | |||
plaintext decoded from PrivateMessage.ciphertext by first decoding | plaintext decoded from PrivateMessage.ciphertext by first decoding | |||
the content and the auth field; then the padding field comprises any | the content and the auth field; then the padding field comprises any | |||
remaining octets of plaintext. The padding field MUST be filled with | remaining octets of plaintext. The padding field MUST be filled with | |||
all zero bytes. A receiver MUST verify that there are no non-zero | all zero bytes. A receiver MUST verify that there are no non-zero | |||
bytes in the padding field, and if this check fails, the enclosing | bytes in the padding field, and if this check fails, the enclosing | |||
PrivateMessage MUST be rejected as malformed. This check ensures | PrivateMessage MUST be rejected as malformed. This check ensures | |||
that the padding process is deterministic, so that, for example, | that the padding process is deterministic, so that, for example, | |||
padding cannot be used as a covert channel. | padding cannot be used as a covert channel. | |||
In the MLS key schedule, the sender creates two distinct key ratchets | In the MLS key schedule, the sender creates two distinct key ratchets | |||
for handshake and application messages for each member of the group. | for handshake and application messages for each member of the group. | |||
When encrypting a message, the sender looks at the ratchets it | When encrypting a message, the sender looks at the ratchets it | |||
derived for its own member and chooses an unused generation from | derived for its own member and chooses an unused generation from | |||
either the handshake or application ratchet depending on the content | either the handshake ratchet or the application ratchet, depending on | |||
type of the message. This generation of the ratchet is used to | the content type of the message. This generation of the ratchet is | |||
derive a provisional nonce and key. | used to derive a provisional nonce and key. | |||
Before use in the encryption operation, the nonce is XORed with a | Before use in the encryption operation, the nonce is XORed with a | |||
fresh random value to guard against reuse. Because the key schedule | fresh random value to guard against reuse. Because the key schedule | |||
generates nonces deterministically, a client MUST keep persistent | generates nonces deterministically, a client MUST keep persistent | |||
state as to where in the key schedule it is; if this persistent state | state as to where in the key schedule it is; if this persistent state | |||
is lost or corrupted, a client might reuse a generation that has | is lost or corrupted, a client might reuse a generation that has | |||
already been used, causing reuse of a key/nonce pair. | already been used, causing reuse of a key/nonce pair. | |||
To avoid this situation, the sender of a message MUST generate a | To avoid this situation, the sender of a message MUST generate a | |||
fresh random four-byte "reuse guard" value and XOR it with the first | fresh random four-byte "reuse guard" value and XOR it with the first | |||
skipping to change at page 50, line 42 ¶ | skipping to change at line 1818 ¶ | |||
ContentType content_type; | ContentType content_type; | |||
opaque authenticated_data<V>; | opaque authenticated_data<V>; | |||
} PrivateContentAAD; | } PrivateContentAAD; | |||
When decoding a PrivateMessageContent, the application MUST check | When decoding a PrivateMessageContent, the application MUST check | |||
that the FramedContentAuthData is valid. | that the FramedContentAuthData is valid. | |||
It is up to the application to decide what authenticated_data to | It is up to the application to decide what authenticated_data to | |||
provide and how much padding to add to a given message (if any). The | provide and how much padding to add to a given message (if any). The | |||
overall size of the AAD and ciphertext MUST fit within the limits | overall size of the AAD and ciphertext MUST fit within the limits | |||
established for the group's AEAD algorithm in [!I-D.irtf-cfrg-aead- | established for the group's AEAD algorithm in [CFRG-AEAD-LIMITS]. | |||
limits]. | ||||
6.3.2. Sender Data Encryption | 6.3.2. Sender Data Encryption | |||
The "sender data" used to look up the key for content encryption is | The "sender data" used to look up the key for content encryption is | |||
encrypted with the ciphersuite's AEAD with a key and nonce derived | encrypted with the cipher suite's AEAD with a key and nonce derived | |||
from both the sender_data_secret and a sample of the encrypted | from both the sender_data_secret and a sample of the encrypted | |||
content. Before being encrypted, the sender data is encoded as an | content. Before being encrypted, the sender data is encoded as an | |||
object of the following form: | object of the following form: | |||
struct { | struct { | |||
uint32 leaf_index; | uint32 leaf_index; | |||
uint32 generation; | uint32 generation; | |||
opaque reuse_guard[4]; | opaque reuse_guard[4]; | |||
} SenderData; | } SenderData; | |||
skipping to change at page 51, line 32 ¶ | skipping to change at line 1855 ¶ | |||
whole ciphertext is used. In pseudocode, the key and nonce are | whole ciphertext is used. In pseudocode, the key and nonce are | |||
derived as: | derived as: | |||
ciphertext_sample = ciphertext[0..KDF.Nh-1] | ciphertext_sample = ciphertext[0..KDF.Nh-1] | |||
sender_data_key = ExpandWithLabel(sender_data_secret, "key", | sender_data_key = ExpandWithLabel(sender_data_secret, "key", | |||
ciphertext_sample, AEAD.Nk) | ciphertext_sample, AEAD.Nk) | |||
sender_data_nonce = ExpandWithLabel(sender_data_secret, "nonce", | sender_data_nonce = ExpandWithLabel(sender_data_secret, "nonce", | |||
ciphertext_sample, AEAD.Nn) | ciphertext_sample, AEAD.Nn) | |||
The Additional Authenticated Data (AAD) for the SenderData ciphertext | The AAD for the SenderData ciphertext is the first three fields of | |||
is the first three fields of PrivateMessage: | PrivateMessage: | |||
struct { | struct { | |||
opaque group_id<V>; | opaque group_id<V>; | |||
uint64 epoch; | uint64 epoch; | |||
ContentType content_type; | ContentType content_type; | |||
} SenderDataAAD; | } SenderDataAAD; | |||
When parsing a SenderData struct as part of message decryption, the | When parsing a SenderData struct as part of message decryption, the | |||
recipient MUST verify that the leaf index indicated in the leaf_index | recipient MUST verify that the leaf index indicated in the leaf_index | |||
field identifies a non-blank node. | field identifies a non-blank node. | |||
7. Ratchet Tree Operations | 7. Ratchet Tree Operations | |||
The ratchet tree for an epoch describes the membership of a group in | The ratchet tree for an epoch describes the membership of a group in | |||
that epoch, providing public-key encryption (HPKE) keys that can be | that epoch, providing public key encryption (HPKE) keys that can be | |||
used to encrypt to subsets of the group as well as information to | used to encrypt to subsets of the group as well as information to | |||
authenticate the members. In order to reflect changes to the | authenticate the members. In order to reflect changes to the | |||
membership of the group from one epoch to the next, corresponding | membership of the group from one epoch to the next, corresponding | |||
changes are made to the ratchet tree. In this section, we describe | changes are made to the ratchet tree. In this section, we describe | |||
the content of the tree and the required operations. | the content of the tree and the required operations. | |||
7.1. Parent Node Contents | 7.1. Parent Node Contents | |||
As discussed in Section 4.1.1, the nodes of a ratchet tree contain | As discussed in Section 4.1.1, the nodes of a ratchet tree contain | |||
several types of data describing individual members (for leaf nodes) | several types of data describing individual members (for leaf nodes) | |||
skipping to change at page 52, line 44 ¶ | skipping to change at line 1916 ¶ | |||
enum { | enum { | |||
reserved(0), | reserved(0), | |||
key_package(1), | key_package(1), | |||
update(2), | update(2), | |||
commit(3), | commit(3), | |||
(255) | (255) | |||
} LeafNodeSource; | } LeafNodeSource; | |||
struct { | struct { | |||
ProtocolVersion versions<V>; | ProtocolVersion versions<V>; | |||
CipherSuite ciphersuites<V>; | CipherSuite cipher_suites<V>; | |||
ExtensionType extensions<V>; | ExtensionType extensions<V>; | |||
ProposalType proposals<V>; | ProposalType proposals<V>; | |||
CredentialType credentials<V>; | CredentialType credentials<V>; | |||
} Capabilities; | } Capabilities; | |||
struct { | struct { | |||
uint64 not_before; | uint64 not_before; | |||
uint64 not_after; | uint64 not_after; | |||
} Lifetime; | } Lifetime; | |||
// See IANA registry for registered values | // See the "MLS Extension Types" IANA registry for values | |||
uint16 ExtensionType; | uint16 ExtensionType; | |||
struct { | struct { | |||
ExtensionType extension_type; | ExtensionType extension_type; | |||
opaque extension_data<V>; | opaque extension_data<V>; | |||
} Extension; | } Extension; | |||
struct { | struct { | |||
HPKEPublicKey encryption_key; | HPKEPublicKey encryption_key; | |||
SignaturePublicKey signature_key; | SignaturePublicKey signature_key; | |||
skipping to change at page 54, line 33 ¶ | skipping to change at line 2000 ¶ | |||
} LeafNodeTBS; | } LeafNodeTBS; | |||
The encryption_key field contains an HPKE public key whose private | The encryption_key field contains an HPKE public key whose private | |||
key is held only by the member occupying this leaf (or in the case of | key is held only by the member occupying this leaf (or in the case of | |||
a LeafNode in a KeyPackage object, the issuer of the KeyPackage). | a LeafNode in a KeyPackage object, the issuer of the KeyPackage). | |||
The signature_key field contains the member's public signing key. | The signature_key field contains the member's public signing key. | |||
The credential field contains information authenticating both the | The credential field contains information authenticating both the | |||
member's identity and the provided signing key, as described in | member's identity and the provided signing key, as described in | |||
Section 5.3. | Section 5.3. | |||
The capabilities field indicates what protocol versions, | The capabilities field indicates the protocol features that the | |||
ciphersuites, extensions, credential types, and non-default proposal | client supports, including protocol versions, cipher suites, | |||
types are supported by a client. Proposal and extension types | credential types, non-default proposal types, and non-default | |||
defined in this document are considered "default" and thus need not | extension types. The following proposal and extension types are | |||
be listed, while any credential types the application wishes to use | considered "default" and MUST NOT be listed: | |||
MUST be listed. Extensions that appear in the extensions field of a | ||||
LeafNode MUST be included in the extensions field of the capabilities | * Proposal types: | |||
field, and the credential type used in the LeafNode MUST be included | ||||
in the credentials field of the capabilities field. As discussed in | - 0x0001 - add | |||
Section 13, unknown values in capabilities MUST be ignored, and the | ||||
creator of a capabilities field SHOULD include some random GREASE | - 0x0002 - update | |||
values to help ensure that other clients correctly ignore unknown | ||||
values. | - 0x0003 - remove | |||
- 0x0004 - psk | ||||
- 0x0005 - reinit | ||||
- 0x0006 - external_init | ||||
- 0x0007 - group_context_extensions | ||||
* Extension types: | ||||
- 0x0001 - application_id | ||||
- 0x0002 - ratchet_tree | ||||
- 0x0003 - required_capabilities | ||||
- 0x0004 - external_pub | ||||
- 0x0005 - external_senders | ||||
There are no default values for the other fields of a capabilities | ||||
object. The client MUST list all values for the respective | ||||
parameters that it supports. | ||||
The types of any non-default extensions that appear in the extensions | ||||
field of a LeafNode MUST be included in the extensions field of the | ||||
capabilities field, and the credential type used in the LeafNode MUST | ||||
be included in the credentials field of the capabilities field. | ||||
As discussed in Section 13, unknown values in capabilities MUST be | ||||
ignored, and the creator of a capabilities field SHOULD include some | ||||
random GREASE values to help ensure that other clients correctly | ||||
ignore unknown values. | ||||
The leaf_node_source field indicates how this LeafNode came to be | The leaf_node_source field indicates how this LeafNode came to be | |||
added to the tree. This signal tells other members of the group | added to the tree. This signal tells other members of the group | |||
whether the leaf node is required to have a lifetime or parent_hash, | whether the leaf node is required to have a lifetime or parent_hash, | |||
and whether the group_id is added as context to the signature. | and whether the group_id is added as context to the signature. These | |||
Whether these fields can be computed by the client represented by the | fields are included selectively because the client creating a | |||
LeafNode depends on when the LeafNode was created. For example, a | LeafNode is not always able to compute all of them. For example, a | |||
KeyPackage is created before the client knows which group it will be | KeyPackage is created before the client knows which group it will be | |||
used with, so its signature can't bind to a group_id. | used with, so its signature can't bind to a group_id. | |||
In the case where the leaf was added to the tree based on a pre- | In the case where the leaf was added to the tree based on a pre- | |||
published KeyPackage, the lifetime field represents the times between | published KeyPackage, the lifetime field represents the times between | |||
which clients will consider a LeafNode valid. These times are | which clients will consider a LeafNode valid. These times are | |||
represented as absolute times, measured in seconds since the Unix | represented as absolute times, measured in seconds since the Unix | |||
epoch (1970-01-01T00:00:00Z). Applications MUST define a maximum | epoch (1970-01-01T00:00:00Z). Applications MUST define a maximum | |||
total lifetime that is acceptable for a LeafNode, and reject any | total lifetime that is acceptable for a LeafNode, and reject any | |||
LeafNode where the total lifetime is longer than this duration. In | LeafNode where the total lifetime is longer than this duration. In | |||
skipping to change at page 55, line 42 ¶ | skipping to change at line 2085 ¶ | |||
group is added as context to the signature. | group is added as context to the signature. | |||
LeafNode objects stored in the group's ratchet tree are updated | LeafNode objects stored in the group's ratchet tree are updated | |||
according to the evolution of the tree. Each modification of | according to the evolution of the tree. Each modification of | |||
LeafNode content MUST be reflected by a change in its signature. | LeafNode content MUST be reflected by a change in its signature. | |||
This allows other members to verify the validity of the LeafNode at | This allows other members to verify the validity of the LeafNode at | |||
any time, particularly in the case of a newcomer joining the group. | any time, particularly in the case of a newcomer joining the group. | |||
7.3. Leaf Node Validation | 7.3. Leaf Node Validation | |||
The validity of a LeafNode needs to be verified at a few stages: | The validity of a LeafNode needs to be verified at the following | |||
stages: | ||||
* When a LeafNode is downloaded in a KeyPackage, before it is used | * When a LeafNode is downloaded in a KeyPackage, before it is used | |||
to add the client to the group | to add the client to the group | |||
* When a LeafNode is received by a group member in an Add, Update, | * When a LeafNode is received by a group member in an Add, Update, | |||
or Commit message | or Commit message | |||
* When a client validates a ratchet tree, e.g., when joining a group | * When a client validates a ratchet tree, e.g., when joining a group | |||
or after processing a commit | or after processing a Commit | |||
The client verifies the validity of a LeafNode using the following | The client verifies the validity of a LeafNode using the following | |||
steps: | steps: | |||
* Verify that the credential in the LeafNode is valid as described | * Verify that the credential in the LeafNode is valid, as described | |||
in Section 5.3.1. | in Section 5.3.1. | |||
* Verify that the signature on the LeafNode is valid using | * Verify that the signature on the LeafNode is valid using | |||
signature_key. | signature_key. | |||
* Verify that the LeafNode is compatible with the group's | * Verify that the LeafNode is compatible with the group's | |||
parameters. If the GroupContext has a required_capabilities | parameters. If the GroupContext has a required_capabilities | |||
extension, then the required extensions, proposals, and credential | extension, then the required extensions, proposals, and credential | |||
types MUST be listed in the LeafNode's capabilities field. | types MUST be listed in the LeafNode's capabilities field. | |||
* Verify that the credential type is supported by all members of the | * Verify that the credential type is supported by all members of the | |||
group, as specified by the capabilities field of each member's | group, as specified by the capabilities field of each member's | |||
LeafNode, and that the capabilities field of this LeafNode | LeafNode, and that the capabilities field of this LeafNode | |||
indicates support for all the credential types currently in use by | indicates support for all the credential types currently in use by | |||
other members. | other members. | |||
* Verify the lifetime field: | * Verify the lifetime field: | |||
- If the LeafNode appears in a message being sent by the client, | - If the LeafNode appears in a message being sent by the client, | |||
e.g., a proposal or a commit, then the client MUST verify that | e.g., a Proposal or a Commit, then the client MUST verify that | |||
the current time is within the range of the lifetime field. | the current time is within the range of the lifetime field. | |||
- If instead the LeafNode appears in a message being received by | - If instead the LeafNode appears in a message being received by | |||
the client, e.g., a proposal, a commit, or a ratchet tree of | the client, e.g., a Proposal, a Commit, or a ratchet tree of | |||
the group the client is joining, it is RECOMMENDED that the | the group the client is joining, it is RECOMMENDED that the | |||
client verifies that the current time is within the range of | client verifies that the current time is within the range of | |||
the lifetime field. (This check is not mandatory because the | the lifetime field. (This check is not mandatory because the | |||
LeafNode might have expired in the time between when the | LeafNode might have expired in the time between when the | |||
message was sent and when it was received.) | message was sent and when it was received.) | |||
* Verify that the extensions in the LeafNode are supported by | * Verify that the extensions in the LeafNode are supported by | |||
checking that the ID for each extension in the extensions field is | checking that the ID for each extension in the extensions field is | |||
listed in the capabilities.extensions field of the LeafNode. | listed in the capabilities.extensions field of the LeafNode. | |||
skipping to change at page 57, line 50 ¶ | skipping to change at line 2190 ¶ | |||
path_secret[n] = DeriveSecret(path_secret[n-1], "path") | path_secret[n] = DeriveSecret(path_secret[n-1], "path") | |||
* Compute the sequence of HPKE key pairs (node_priv,node_pub), one | * Compute the sequence of HPKE key pairs (node_priv,node_pub), one | |||
for each node on the leaf's direct path, as follows. | for each node on the leaf's direct path, as follows. | |||
node_secret[n] = DeriveSecret(path_secret[n], "node") | node_secret[n] = DeriveSecret(path_secret[n], "node") | |||
node_priv[n], node_pub[n] = KEM.DeriveKeyPair(node_secret[n]) | node_priv[n], node_pub[n] = KEM.DeriveKeyPair(node_secret[n]) | |||
The node secret is derived as a temporary intermediate secret so that | The node secret is derived as a temporary intermediate secret so that | |||
each secret is only used with one algorithm: The path secret is used | each secret is only used with one algorithm: The path secret is used | |||
as an input to DeriveSecret and the node secret is used as an input | as an input to DeriveSecret, and the node secret is used as an input | |||
to DeriveKeyPair. | to DeriveKeyPair. | |||
For example, suppose there is a group with four members, with C an | For example, suppose there is a group with four members, with C an | |||
unmerged leaf at Z: | unmerged leaf at Z: | |||
Y | Y | |||
| | | | |||
.-+-. | .-+-. | |||
/ \ | / \ | |||
X Z[C] | X Z[C] | |||
/ \ / \ | / \ / \ | |||
A B C D | A B C D | |||
0 1 2 3 | 0 1 2 3 | |||
Figure 13: A full tree with one unmerged leaf | Figure 13: A Full Tree with One Unmerged Leaf | |||
If member B subsequently generates an UpdatePath based on a secret | If member B subsequently generates an UpdatePath based on a secret | |||
"leaf_secret", then it would generate the following sequence of path | "leaf_secret", then it would generate the following sequence of path | |||
secrets: | secrets: | |||
path_secret[1] ---> node_secret[1] -------> node_priv[1], node_pub[1] | path_secret[1] ---> node_secret[1] -------> node_priv[1], node_pub[1] | |||
^ | ^ | |||
| | | | |||
| | | | |||
skipping to change at page 58, line 40 ¶ | skipping to change at line 2228 ¶ | |||
^ | ^ | |||
| | | | |||
| | | | |||
leaf_secret ------> leaf_node_secret --+--> leaf_priv, leaf_pub | leaf_secret ------> leaf_node_secret --+--> leaf_priv, leaf_pub | |||
| | | | | | |||
'-------. .-------' | '-------. .-------' | |||
| | | | |||
leaf_node | leaf_node | |||
Figure 14: Derivation of ratchet tree keys along a direct path | Figure 14: Derivation of Ratchet Tree Keys along a Direct Path | |||
After applying the UpdatePath, the tree will have the following | After applying the UpdatePath, the tree will have the following | |||
structure: | structure: | |||
node_priv[1] --------> Y' | node_priv[1] --------> Y' | |||
| | | | |||
.-+-. | .-+-. | |||
/ \ | / \ | |||
node_priv[0] ----> X' Z[C] | node_priv[0] ----> X' Z[C] | |||
/ \ / \ | / \ / \ | |||
A B C D | A B C D | |||
^ | ^ | |||
leaf_priv -----------+ | leaf_priv -----------+ | |||
0 1 2 3 | 0 1 2 3 | |||
Figure 15: Placement of keys in a ratchet tree | Figure 15: Placement of Keys in a Ratchet Tree | |||
7.5. Synchronizing Views of the Tree | 7.5. Synchronizing Views of the Tree | |||
After generating fresh key material and applying it to ratchet | After generating fresh key material and applying it to update their | |||
forward their local tree state as described in the Section 7.4, the | local tree state as described in Section 7.4, the generator | |||
generator broadcasts this update to other members of the group in a | broadcasts this update to other members of the group in a Commit | |||
Commit message, who apply it to keep their local views of the tree in | message, who apply it to keep their local views of the tree in sync | |||
sync with the sender's. More specifically, when a member commits a | with the sender's. More specifically, when a member commits a change | |||
change to the tree (e.g., to add or remove a member), it transmits an | to the tree (e.g., to add or remove a member), it transmits an | |||
UpdatePath containing a set of public keys and encrypted path secrets | UpdatePath containing a set of public keys and encrypted path secrets | |||
for intermediate nodes in the filtered direct path of its leaf. The | for intermediate nodes in the filtered direct path of its leaf. The | |||
other members of the group use these values to update their view of | other members of the group use these values to update their view of | |||
the tree, aligning their copy of the tree to the sender's. | the tree, aligning their copy of the tree to the sender's. | |||
An UpdatePath contains the following information for each node in the | An UpdatePath contains the following information for each node in the | |||
filtered direct path of the sender's leaf, including the root: | filtered direct path of the sender's leaf, including the root: | |||
* The public key for the node | * The public key for the node | |||
skipping to change at page 59, line 47 ¶ | skipping to change at line 2275 ¶ | |||
the node | the node | |||
The path secret value for a given node is encrypted to the subtree | The path secret value for a given node is encrypted to the subtree | |||
rooted at the parent's non-updated child, i.e., the child on the | rooted at the parent's non-updated child, i.e., the child on the | |||
copath of the sender's leaf node. There is one encryption of the | copath of the sender's leaf node. There is one encryption of the | |||
path secret to each public key in the resolution of the non-updated | path secret to each public key in the resolution of the non-updated | |||
child. | child. | |||
A member of the group _updates their direct path_ by computing new | A member of the group _updates their direct path_ by computing new | |||
values for their leaf node and the nodes along their filtered direct | values for their leaf node and the nodes along their filtered direct | |||
path: | path as follows: | |||
1. Blank all nodes along the direct path of the sender's leaf. | 1. Blank all nodes along the direct path of the sender's leaf. | |||
2. Compute updated path secrets and public keys for the nodes on the | 2. Compute updated path secrets and public keys for the nodes on the | |||
sender's filtered direct path. | sender's filtered direct path. | |||
* Generate a sequence of path secrets of the same length as the | * Generate a sequence of path secrets of the same length as the | |||
filtered direct path, as defined in Section 7.4 | filtered direct path, as defined in Section 7.4. | |||
* For each node in the filtered direct path, replace the node's | * For each node in the filtered direct path, replace the node's | |||
public key with the node_pub[n] value derived from the | public key with the node_pub[n] value derived from the | |||
corresponding path secret path_secret[n]. | corresponding path secret path_secret[n]. | |||
3. Compute the new parent hashes for the nodes along the filtered | 3. Compute the new parent hashes for the nodes along the filtered | |||
direct path and the sender's leaf node. | direct path and the sender's leaf node. | |||
4. Update the leaf node for the sender. | 4. Update the leaf node for the sender. | |||
* Set the leaf_node_source to commit. | * Set the leaf_node_source to commit. | |||
* Set the encryption_key to the public key of a freshly sampled | * Set the encryption_key to the public key of a freshly sampled | |||
key pair | key pair. | |||
* Set the parent hash to the parent hash for the leaf. | * Set the parent hash to the parent hash for the leaf. | |||
* Re-sign the leaf node with its new contents | * Re-sign the leaf node with its new contents. | |||
Since the new leaf node effectively updates an existing leaf node in | Since the new leaf node effectively updates an existing leaf node in | |||
the group, it MUST adhere to the same restrictions as LeafNodes used | the group, it MUST adhere to the same restrictions as LeafNodes used | |||
in Update proposals (aside from leaf_node_source). The application | in Update proposals (aside from leaf_node_source). The application | |||
MAY specify other changes to the leaf node, e.g., providing a new | MAY specify other changes to the leaf node, e.g., providing a new | |||
signature key, updated capabilities, or different extensions. | signature key, updated capabilities, or different extensions. | |||
The member then _encrypts path secrets to the group_. For each node | The member then _encrypts path secrets to the group_. For each node | |||
in the member's filtered direct path, the member takes the following | in the member's filtered direct path, the member takes the following | |||
steps: | steps: | |||
1. Compute the resolution of the node's child that is on the copath | 1. Compute the resolution of the node's child that is on the copath | |||
of the sender (the child that is not in the direct path of the | of the sender (the child that is not in the direct path of the | |||
sender). Any new member (from an Add proposal) added in the same | sender). Any new member (from an Add proposal) added in the same | |||
Commit MUST be excluded from this resolution. | Commit MUST be excluded from this resolution. | |||
2. For each node in the resolution, encrypt the path secret for the | 2. For each node in the resolution, encrypt the path secret for the | |||
direct path node using the public key of the resolution node, as | direct path node using the public key of the resolution node, as | |||
defined in Section 7.6 | defined in Section 7.6. | |||
The recipient of an UpdatePath performs the corresponding steps. | The recipient of an UpdatePath performs the corresponding steps. | |||
First, the recipient _merges UpdatePath into the tree_: | First, the recipient _merges UpdatePath into the tree_: | |||
1. Blank all nodes on the direct path of the sender's leaf. | 1. Blank all nodes on the direct path of the sender's leaf. | |||
2. For all nodes on the filtered direct path of the sender's leaf, | 2. For all nodes on the filtered direct path of the sender's leaf, | |||
* Set the public key to the public key in the UpdatePath. | * Set the public key to the public key in the UpdatePath. | |||
skipping to change at page 62, line 7 ¶ | skipping to change at line 2380 ¶ | |||
+=============+====================================================+ | +=============+====================================================+ | |||
| node_pub[1] | E(pk(Z), path_secret[1]), E(pk(C), path_secret[1]) | | | node_pub[1] | E(pk(Z), path_secret[1]), E(pk(C), path_secret[1]) | | |||
+-------------+----------------------------------------------------+ | +-------------+----------------------------------------------------+ | |||
| node_pub[0] | E(pk(A), path_secret[0]) | | | node_pub[0] | E(pk(A), path_secret[0]) | | |||
+-------------+----------------------------------------------------+ | +-------------+----------------------------------------------------+ | |||
Table 3 | Table 3 | |||
In this table, the value node_pub[i] represents the public key | In this table, the value node_pub[i] represents the public key | |||
derived from node_secret[i], pk(X) represents the current public key | derived from node_secret[i], pk(X) represents the current public key | |||
of node X, and E(K, S) represents the public-key encryption of the | of node X, and E(K, S) represents the public key encryption of the | |||
path secret S to the public key K (using HPKE). | path secret S to the public key K (using HPKE). | |||
A recipient at node A would decrypt E(pk(A), path_secret\[0\]) to | A recipient at node A would decrypt E(pk(A), path_secret\[0\]) to | |||
obtain path_secret\[0\], then use it to derive path_secret[1] and the | obtain path_secret\[0\], then use it to derive path_secret[1] and the | |||
resulting node secrets and key pairs. Thus, A would have the private | resulting node secrets and key pairs. Thus, A would have the private | |||
keys to nodes X' and Y', in accordance with the tree invariant. | keys to nodes X' and Y', in accordance with the tree invariant. | |||
Similarly, a recipient at node D would decrypt E(pk(Z), | Similarly, a recipient at node D would decrypt E(pk(Z), | |||
path_secret[1]) to obtain path_secret[1], then use it to derive the | path_secret[1]) to obtain path_secret[1], then use it to derive the | |||
node secret and key pair for the node Y'. As required to maintain | node secret and key pair for the node Y'. As required to maintain | |||
skipping to change at page 63, line 30 ¶ | skipping to change at line 2451 ¶ | |||
Here node_public_key is the public key of the node for which the path | Here node_public_key is the public key of the node for which the path | |||
secret is encrypted, group_context is the provisional GroupContext | secret is encrypted, group_context is the provisional GroupContext | |||
object for the group, and the EncryptWithLabel function is as defined | object for the group, and the EncryptWithLabel function is as defined | |||
in Section 5.1.3. | in Section 5.1.3. | |||
7.7. Adding and Removing Leaves | 7.7. Adding and Removing Leaves | |||
In addition to the path-based updates to the tree described above, it | In addition to the path-based updates to the tree described above, it | |||
is also necessary to add and remove leaves of the tree in order to | is also necessary to add and remove leaves of the tree in order to | |||
reflect changes to the membership of the group (see Section 12.1.1 | reflect changes to the membership of the group (see Sections 12.1.1 | |||
and Section 12.1.3). Since the tree is always full, adding or | and 12.1.3). Since the tree is always full, adding or removing | |||
removing leaves corresponds to increasing or decreasing the depth of | leaves corresponds to increasing or decreasing the depth of the tree, | |||
the tree, resulting in the number of leaves being doubled or halved. | resulting in the number of leaves being doubled or halved. These | |||
These operations are also known as _extending_ and _truncating_ the | operations are also known as _extending_ and _truncating_ the tree. | |||
tree. | ||||
Leaves are always added and removed at the right edge of the tree. | Leaves are always added and removed at the right edge of the tree. | |||
When the size of the tree needs to be increased, a new blank root | When the size of the tree needs to be increased, a new blank root | |||
node is added, whose left subtree is the existing tree and right | node is added, whose left subtree is the existing tree and right | |||
subtree is a new all-blank subtree. This operation is typically done | subtree is a new all-blank subtree. This operation is typically done | |||
when adding a member to the group. | when adding a member to the group. | |||
_ <-- new blank root _ | _ <-- new blank root _ | |||
__|__ __|__ | __|__ __|__ | |||
/ \ / \ | / \ / \ | |||
X ===> X _ <-- new blank subtree ===> X _ | X ===> X _ <-- new blank subtree ===> X _ | |||
/ \ / \ / \ / \ / \ | / \ / \ / \ / \ / \ | |||
A B A B _ _ A B C _ | A B A B _ _ A B C _ | |||
^ | ^ | |||
| | | | |||
+-- new member | new member --+ | |||
Figure 16: Extending the tree to make room for a third member | Figure 16: Extending the Tree to Make Room for a Third Member | |||
When the right subtree of the tree no longer has any non-blank nodes, | When the right subtree of the tree no longer has any non-blank nodes, | |||
it can be safely removed. The root of the tree and the right subtree | it can be safely removed. The root of the tree and the right subtree | |||
are discarded (whether or not the root node is blank). The left | are discarded (whether or not the root node is blank). The left | |||
child of the root becomes the new root node, and the left subtree | child of the root becomes the new root node, and the left subtree | |||
becomes the new tree. This operation is typically done after | becomes the new tree. This operation is typically done after | |||
removing a member from the group. | removing a member from the group. | |||
Y Y | Y Y | |||
__|__ __|__ | __|__ __|__ | |||
/ \ / \ | / \ / \ | |||
X _ ===> X _ ==> X <-- new root | X _ ===> X _ ==> X <-- new root | |||
/ \ / \ / \ / \ / \ | / \ / \ / \ / \ / \ | |||
A B C _ A B _ _ A B | A B C _ A B _ _ A B | |||
^ | ^ | |||
| | | | |||
removed member --+ | removed member --+ | |||
Figure 17: Cleaning up after removing member C | Figure 17: Cleaning Up after Removing Member C | |||
Concrete algorithms for these operations on array-based and link- | Concrete algorithms for these operations on array-based and link- | |||
based trees are provided in Appendix C and Appendix D. The concrete | based trees are provided in Appendices C and D. The concrete | |||
algorithms are non-normative. An implementation may use any | algorithms are non-normative. An implementation may use any | |||
algorithm that produces the correct tree in its internal | algorithm that produces the correct tree in its internal | |||
representation. | representation. | |||
7.8. Tree Hashes | 7.8. Tree Hashes | |||
MLS hashes the contents of the tree in two ways to authenticate | MLS hashes the contents of the tree in two ways to authenticate | |||
different properties of the tree. _Tree hashes_ are defined in this | different properties of the tree. _Tree hashes_ are defined in this | |||
section, and _parent hashes_ are defined in Section 7.9. | section, and _parent hashes_ are defined in Section 7.9. | |||
skipping to change at page 64, line 49 ¶ | skipping to change at line 2517 ¶ | |||
subtree below that node. The tree hash of the root is used in the | subtree below that node. The tree hash of the root is used in the | |||
GroupContext to confirm that the group agrees on the whole tree. | GroupContext to confirm that the group agrees on the whole tree. | |||
Tree hashes are computed recursively from the leaves up to the root. | Tree hashes are computed recursively from the leaves up to the root. | |||
P --> th(P) | P --> th(P) | |||
^ ^ | ^ ^ | |||
/ \ | / \ | |||
/ \ | / \ | |||
th(L) th(R) | th(L) th(R) | |||
Figure 18: Composition of the tree hash | Figure 18: Composition of the Tree Hash | |||
The tree hash of an individual node is the hash of the node's | The tree hash of an individual node is the hash of the node's | |||
TreeHashInput object, which may contain either a LeafNodeHashInput or | TreeHashInput object, which may contain either a LeafNodeHashInput or | |||
a ParentNodeHashInput depending on the type of node. | a ParentNodeHashInput depending on the type of node. | |||
LeafNodeHashInput objects contain the leaf_index and the LeafNode (if | LeafNodeHashInput objects contain the leaf_index and the LeafNode (if | |||
any). ParentNodeHashInput objects contain the ParentNode (if any) | any). ParentNodeHashInput objects contain the ParentNode (if any) | |||
and the tree hash of the node's left and right children. For both | and the tree hash of the node's left and right children. For both | |||
parent and leaf nodes, the optional node value MUST be absent if the | parent and leaf nodes, the optional node value MUST be absent if the | |||
node is blank and present if the node contains a value. | node is blank and present if the node contains a value. | |||
skipping to change at page 65, line 50 ¶ | skipping to change at line 2564 ¶ | |||
The tree hash of an entire tree corresponds to the tree hash of the | The tree hash of an entire tree corresponds to the tree hash of the | |||
root node, which is computed recursively by starting at the leaf | root node, which is computed recursively by starting at the leaf | |||
nodes and building up. | nodes and building up. | |||
7.9. Parent Hashes | 7.9. Parent Hashes | |||
While tree hashes summarize the state of a tree at point in time, | While tree hashes summarize the state of a tree at point in time, | |||
parent hashes capture information about how keys in the tree were | parent hashes capture information about how keys in the tree were | |||
populated. | populated. | |||
When a client sends a commit to change a group, it can include an | When a client sends a Commit to change a group, it can include an | |||
UpdatePath to assign new keys to the nodes along its filtered direct | UpdatePath to assign new keys to the nodes along its filtered direct | |||
path. When a client computes an UpdatePath (as defined in | path. When a client computes an UpdatePath (as defined in | |||
Section 7.5), it computes and signs a parent hash that summarizes the | Section 7.5), it computes and signs a parent hash that summarizes the | |||
state of the tree after the UpdatePath has been applied. These | state of the tree after the UpdatePath has been applied. These | |||
summaries are constructed in a chain from the root to the member's | summaries are constructed in a chain from the root to the member's | |||
leaf so that the part of the chain closer to the root can be | leaf so that the part of the chain closer to the root can be | |||
overwritten as nodes set in one UpdatePath are reset by a later | overwritten as nodes set in one UpdatePath are reset by a later | |||
UpdatePath. | UpdatePath. | |||
ph(Q) | ph(Q) | |||
/ | / | |||
/ | / | |||
V | V | |||
P.public_key --> ph(P) | P.public_key --> ph(P) | |||
/ ^ | / ^ | |||
/ \ | / \ | |||
V \ | V \ | |||
N.parent_hash th(S) | N.parent_hash th(S) | |||
Figure 19: Inputs to a parent hash | Figure 19: Inputs to a Parent Hash | |||
As a result, the signature over the parent hash in each member's leaf | As a result, the signature over the parent hash in each member's leaf | |||
effectively signs the subtree of the tree that hasn't been changed | effectively signs the subtree of the tree that hasn't been changed | |||
since that leaf was last changed in an UpdatePath. A new member | since that leaf was last changed in an UpdatePath. A new member | |||
joining the group uses these parent hashes to verify that the parent | joining the group uses these parent hashes to verify that the parent | |||
nodes in the tree were set by members of the group, not chosen by an | nodes in the tree were set by members of the group, not chosen by an | |||
external attacker. For an example of how this works, see Appendix B. | external attacker. For an example of how this works, see Appendix B. | |||
Consider a ratchet tree with a non-blank parent node P and children D | Consider a ratchet tree with a non-blank parent node P and children D | |||
and S (for "parent", "direct path", and "sibling"), with D and P in | and S (for "parent", "direct path", and "sibling"), with D and P in | |||
skipping to change at page 66, line 45 ¶ | skipping to change at line 2608 ¶ | |||
/ | / | |||
P | P | |||
__|__ | __|__ | |||
/ \ | / \ | |||
D S | D S | |||
/ \ / \ | / \ / \ | |||
... ... ... ... | ... ... ... ... | |||
/ | / | |||
L | L | |||
Figure 20: Nodes involved in a parent hash computation | Figure 20: Nodes Involved in a Parent Hash Computation | |||
The parent hash of P changes whenever an UpdatePath object is applied | The parent hash of P changes whenever an UpdatePath object is applied | |||
to the ratchet tree along a path from a leaf L traversing node D (and | to the ratchet tree along a path from a leaf L traversing node D (and | |||
hence also P). The new "Parent hash of P (with copath child S)" is | hence also P). The new "Parent hash of P (with copath child S)" is | |||
obtained by hashing P's ParentHashInput struct. | obtained by hashing P's ParentHashInput struct. | |||
struct { | struct { | |||
HPKEPublicKey encryption_key; | HPKEPublicKey encryption_key; | |||
opaque parent_hash<V>; | opaque parent_hash<V>; | |||
opaque original_sibling_tree_hash<V>; | opaque original_sibling_tree_hash<V>; | |||
} ParentHashInput; | } ParentHashInput; | |||
The field encryption_key contains the HPKE public key of P. If P is | The field encryption_key contains the HPKE public key of P. If P is | |||
the root, then the parent_hash field is set to a zero-length octet | the root, then the parent_hash field is set to a zero-length octet | |||
string. Otherwise, parent_hash is the Parent Hash of the next node | string. Otherwise, parent_hash is the parent hash of the next node | |||
after P on the filtered direct path of the leaf L. This way, P's | after P on the filtered direct path of the leaf L. This way, P's | |||
Parent Hash fixes the new HPKE public key of each non-blank node on | parent hash fixes the new HPKE public key of each non-blank node on | |||
the path from P to the root. Note that the path from P to the root | the path from P to the root. Note that the path from P to the root | |||
may contain some blank nodes that are not fixed by P's Parent Hash. | may contain some blank nodes that are not fixed by P's parent hash. | |||
However, for each node that has an HPKE key, this key is fixed by P's | However, for each node that has an HPKE key, this key is fixed by P's | |||
Parent Hash. | parent hash. | |||
Finally, original_sibling_tree_hash is the tree hash of S in the | Finally, original_sibling_tree_hash is the tree hash of S in the | |||
ratchet tree modified as follows: For each leaf L in | ratchet tree modified as follows: For each leaf L in | |||
P.unmerged_leaves, blank L and remove it from the unmerged_leaves | P.unmerged_leaves, blank L and remove it from the unmerged_leaves | |||
sets of all parent nodes. | sets of all parent nodes. | |||
Observe that original_sibling_tree_hash does not change between | Observe that original_sibling_tree_hash does not change between | |||
updates of P. This property is crucial for the correctness of the | updates of P. This property is crucial for the correctness of the | |||
protocol. | protocol. | |||
skipping to change at page 67, line 49 ¶ | skipping to change at line 2659 ¶ | |||
W [F] | W [F] | |||
______|_____ | ______|_____ | |||
/ \ | / \ | |||
U Y [F] | U Y [F] | |||
__|__ __|__ | __|__ __|__ | |||
/ \ / \ | / \ / \ | |||
T _ _ _ | T _ _ _ | |||
/ \ / \ / \ / \ | / \ / \ / \ / \ | |||
A B C D E F G _ | A B C D E F G _ | |||
Figure 21: A tree illustrating parent hash computations. | Figure 21: A Tree Illustrating Parent Hash Computations | |||
With P = W and S = Y, original_sibling_tree_hash is the tree hash of | With P = W and S = Y, original_sibling_tree_hash is the tree hash of | |||
the following tree: | the following tree: | |||
Y | Y | |||
__|__ | __|__ | |||
/ \ | / \ | |||
_ _ | _ _ | |||
/ \ / \ | / \ / \ | |||
E _ G _ | E _ G _ | |||
Because W.unmerged_leaves includes F, F is blanked and removed from | Because W.unmerged_leaves includes F, F is blanked and removed from | |||
Y.unmerged_leaves. | Y.unmerged_leaves. | |||
Note that no recomputation is needed if the tree hash of S is | Note that no recomputation is needed if the tree hash of S is | |||
unchanged since the last time P was updated. This is the case for | unchanged since the last time P was updated. This is the case for | |||
computing or processing a Commit whose UpdatePath traverses P, since | computing or processing a Commit whose UpdatePath traverses P, since | |||
the Commit itself resets P. (In other words, it is only necessary to | the Commit itself resets P. (In other words, it is only necessary to | |||
recompute the original sibling tree hash when validating a group's | recompute the original sibling tree hash when validating a group's | |||
tree on joining.) More generally, if none of the entries in | tree on joining.) More generally, if none of the entries in | |||
P.unmerged_leaves is in the subtree under S (and thus no leaves were | P.unmerged_leaves are in the subtree under S (and thus no leaves were | |||
blanked), then the original tree hash at S is the tree hash of S in | blanked), then the original tree hash at S is the tree hash of S in | |||
the current tree. | the current tree. | |||
If it is necessary to recompute the original tree hash of a node, the | If it is necessary to recompute the original tree hash of a node, the | |||
efficiency of recomputation can be improved by caching intermediate | efficiency of recomputation can be improved by caching intermediate | |||
tree hashes, to avoid recomputing over the subtree when the subtree | tree hashes, to avoid recomputing over the subtree when the subtree | |||
is included in multiple parent hashes. A subtree hash can be reused | is included in multiple parent hashes. A subtree hash can be reused | |||
as long as the intersection of the parent's unmerged leaves with the | as long as the intersection of the parent's unmerged leaves with the | |||
subtree is the same as in the earlier computation. | subtree is the same as in the earlier computation. | |||
skipping to change at page 68, line 43 ¶ | skipping to change at line 2702 ¶ | |||
In ParentNode objects and LeafNode objects with leaf_node_source set | In ParentNode objects and LeafNode objects with leaf_node_source set | |||
to commit, the value of the parent_hash field is the parent hash of | to commit, the value of the parent_hash field is the parent hash of | |||
the next non-blank parent node above the node in question (the next | the next non-blank parent node above the node in question (the next | |||
node in the filtered direct path). Using the node labels in | node in the filtered direct path). Using the node labels in | |||
Figure 20, the parent_hash field of D is equal to the parent hash of | Figure 20, the parent_hash field of D is equal to the parent hash of | |||
P with copath child S. This is the case even when the node D is a | P with copath child S. This is the case even when the node D is a | |||
leaf node. | leaf node. | |||
The parent_hash field of a LeafNode is signed by the member. The | The parent_hash field of a LeafNode is signed by the member. The | |||
signature of such a LeafNode thus also attests to which keys the | signature of such a LeafNode thus attests to which keys the group | |||
group member introduced into the ratchet tree and to whom the | member introduced into the ratchet tree and to whom the corresponding | |||
corresponding secret keys were sent. This prevents malicious | secret keys were sent, in addition to the other contents of the | |||
insiders from constructing artificial ratchet trees with a node D | LeafNode. This prevents malicious insiders from constructing | |||
whose HPKE secret key is known to the insider yet where the insider | artificial ratchet trees with a node D whose HPKE secret key is known | |||
isn't assigned a leaf in the subtree rooted at D. Indeed, such a | to the insider, yet where the insider isn't assigned a leaf in the | |||
ratchet tree would violate the tree invariant. | subtree rooted at D. Indeed, such a ratchet tree would violate the | |||
tree invariant. | ||||
7.9.2. Verifying Parent Hashes | 7.9.2. Verifying Parent Hashes | |||
Parent hashes are verified at two points in the protocol: When | Parent hashes are verified at two points in the protocol: When | |||
joining a group and when processing a Commit. | joining a group and when processing a Commit. | |||
The parent hash in a node D is valid with respect to a parent node P | The parent hash in a node D is valid with respect to a parent node P | |||
if the following criteria hold. Here C and S are the children of P | if the following criteria hold. Here C and S are the children of P | |||
(for "child" and "sibling"), with C being the child that is on the | (for "child" and "sibling"), with C being the child that is on the | |||
direct path of D (possibly D itself) and S the other child: | direct path of D (possibly D itself) and S being the other child: | |||
* D is a descendant of P in the tree. | * D is a descendant of P in the tree. | |||
* The parent_hash field of D is equal to the parent hash of P with | * The parent_hash field of D is equal to the parent hash of P with | |||
copath child S. | copath child S. | |||
* D is in the resolution of C, and the intersection of P's | * D is in the resolution of C, and the intersection of P's | |||
unmerged_leaves with the subtree under C is equal to the | unmerged_leaves with the subtree under C is equal to the | |||
resolution of C with D removed. | resolution of C with D removed. | |||
These checks verify that D and P were updated at the same time (in | These checks verify that D and P were updated at the same time (in | |||
the same UpdatePath), and that they were neighbors in the UpdatePath | the same UpdatePath), and that they were neighbors in the UpdatePath | |||
because the nodes in between them would have omitted from the | because the nodes in between them would have omitted from the | |||
filtered direct path. | filtered direct path. | |||
A parent node P is "parent-hash valid" if it can be chained back to a | A parent node P is "parent-hash valid" if it can be chained back to a | |||
leaf node in this way. That is, if there is leaf node L and a | leaf node in this way. That is, if there is leaf node L and a | |||
sequence of parent nodes P_1, ..., P_N such that P_N = P and each | sequence of parent nodes P_1, ..., P_N such that P_N = P and each | |||
step in the chain is authenticated by a parent hash: L's parent hash | step in the chain is authenticated by a parent hash, then L's parent | |||
is valid with respect to P_1, P_1's parent hash is valid with respect | hash is valid with respect to P_1, P_1's parent hash is valid with | |||
to P_2, and so on. | respect to P_2, and so on. | |||
When joining a group, the new member MUST authenticate that each non- | When joining a group, the new member MUST authenticate that each non- | |||
blank parent node P is parent-hash valid. This can be done "bottom | blank parent node P is parent-hash valid. This can be done "bottom | |||
up" by building chains up from leaves and verifying that all non- | up" by building chains up from leaves and verifying that all non- | |||
blank parent nodes are covered by exactly one such chain, or "top | blank parent nodes are covered by exactly one such chain, or "top | |||
down" by verifying that there is exactly one descendant of each non- | down" by verifying that there is exactly one descendant of each non- | |||
blank parent node for which the parent node is parent-hash valid. | blank parent node for which the parent node is parent-hash valid. | |||
When processing a Commit message that includes an UpdatePath, clients | When processing a Commit message that includes an UpdatePath, clients | |||
MUST recompute the expected value of parent_hash for the committer's | MUST recompute the expected value of parent_hash for the committer's | |||
new leaf and verify that it matches the parent_hash value in the | new leaf and verify that it matches the parent_hash value in the | |||
supplied leaf_node. After being merged into the tree, the nodes in | supplied leaf_node. After being merged into the tree, the nodes in | |||
the UpdatePath form a parent-hash chain from the committer's leaf to | the UpdatePath form a parent-hash chain from the committer's leaf to | |||
the root. | the root. | |||
8. Key Schedule | 8. Key Schedule | |||
Group keys are derived using the Extract and Expand functions from | Group keys are derived using the Extract and Expand functions from | |||
the KDF for the group's ciphersuite, as well as the functions defined | the KDF for the group's cipher suite, as well as the functions | |||
below: | defined below: | |||
ExpandWithLabel(Secret, Label, Context, Length) = | ExpandWithLabel(Secret, Label, Context, Length) = | |||
KDF.Expand(Secret, KDFLabel, Length) | KDF.Expand(Secret, KDFLabel, Length) | |||
DeriveSecret(Secret, Label) = | DeriveSecret(Secret, Label) = | |||
ExpandWithLabel(Secret, Label, "", KDF.Nh) | ExpandWithLabel(Secret, Label, "", KDF.Nh) | |||
Where KDFLabel is specified as: | Where KDFLabel is specified as: | |||
struct { | struct { | |||
uint16 length; | uint16 length; | |||
opaque label<V>; | opaque label<V>; | |||
opaque context<V>; | opaque context<V>; | |||
} KDFLabel; | } KDFLabel; | |||
And its fields set to: | And its fields are set to: | |||
length = Length; | length = Length; | |||
label = "MLS 1.0 " + Label; | label = "MLS 1.0 " + Label; | |||
context = Context; | context = Context; | |||
The value KDF.Nh is the size of an output from KDF.Extract, in bytes. | The value KDF.Nh is the size of an output from KDF.Extract, in bytes. | |||
In the below diagram: | In the below diagram: | |||
* KDF.Extract takes its salt argument from the top and its Input Key | * KDF.Extract takes its salt argument from the top and its Input | |||
Material (IKM) argument from the left | Keying Material (IKM) argument from the left. | |||
* DeriveSecret takes its Secret argument from the incoming arrow | * DeriveSecret takes its Secret argument from the incoming arrow. | |||
* 0 represents an all-zero byte string of length KDF.Nh. | * 0 represents an all-zero byte string of length KDF.Nh. | |||
When processing a handshake message, a client combines the following | When processing a handshake message, a client combines the following | |||
information to derive new epoch secrets: | information to derive new epoch secrets: | |||
* The init secret from the previous epoch | * The init secret from the previous epoch | |||
* The commit secret for the current epoch | * The commit secret for the current epoch | |||
skipping to change at page 71, line 45 ¶ | skipping to change at line 2844 ¶ | |||
+--> DeriveSecret(., <label>) | +--> DeriveSecret(., <label>) | |||
| = <secret> | | = <secret> | |||
| | | | |||
V | V | |||
DeriveSecret(., "init") | DeriveSecret(., "init") | |||
| | | | |||
| | | | |||
V | V | |||
init_secret_[n] | init_secret_[n] | |||
Figure 22: The MLS key schedule | Figure 22: The MLS Key Schedule | |||
A number of values are derived from the epoch secret for different | A number of values are derived from the epoch secret for different | |||
purposes: | purposes: | |||
+==================+=====================+=======================+ | +==================+=====================+=======================+ | |||
| Label | Secret | Purpose | | | Label | Secret | Purpose | | |||
+==================+=====================+=======================+ | +==================+=====================+=======================+ | |||
| "sender data" | sender_data_secret | Deriving keys to | | | "sender data" | sender_data_secret | Deriving keys to | | |||
| | | encrypt sender data | | | | | encrypt sender data | | |||
+------------------+---------------------+-----------------------+ | +------------------+---------------------+-----------------------+ | |||
skipping to change at page 72, line 26 ¶ | skipping to change at line 2870 ¶ | |||
| | | secrets | | | | | secrets | | |||
+------------------+---------------------+-----------------------+ | +------------------+---------------------+-----------------------+ | |||
| "external" | external_secret | Deriving the external | | | "external" | external_secret | Deriving the external | | |||
| | | init key | | | | | init key | | |||
+------------------+---------------------+-----------------------+ | +------------------+---------------------+-----------------------+ | |||
| "confirm" | confirmation_key | Computing the | | | "confirm" | confirmation_key | Computing the | | |||
| | | confirmation MAC for | | | | | confirmation MAC for | | |||
| | | an epoch | | | | | an epoch | | |||
+------------------+---------------------+-----------------------+ | +------------------+---------------------+-----------------------+ | |||
| "membership" | membership_key | Computing the | | | "membership" | membership_key | Computing the | | |||
| | | membership MAC for an | | | | | membership MAC for a | | |||
| | | PublicMessage | | | | | PublicMessage | | |||
+------------------+---------------------+-----------------------+ | +------------------+---------------------+-----------------------+ | |||
| "resumption" | resumption_psk | Proving membership in | | | "resumption" | resumption_psk | Proving membership in | | |||
| | | this epoch (via a PSK | | | | | this epoch (via a PSK | | |||
| | | injected later) | | | | | injected later) | | |||
+------------------+---------------------+-----------------------+ | +------------------+---------------------+-----------------------+ | |||
| "authentication" | epoch_authenticator | Confirming that two | | | "authentication" | epoch_authenticator | Confirming that two | | |||
| | | clients have the same | | | | | clients have the same | | |||
| | | view of the group | | | | | view of the group | | |||
+------------------+---------------------+-----------------------+ | +------------------+---------------------+-----------------------+ | |||
Table 4: Epoch-derived secrets | Table 4: Epoch-Derived Secrets | |||
The external_secret is used to derive an HPKE key pair whose private | The external_secret is used to derive an HPKE key pair whose private | |||
key is held by the entire group: | key is held by the entire group: | |||
external_priv, external_pub = KEM.DeriveKeyPair(external_secret) | external_priv, external_pub = KEM.DeriveKeyPair(external_secret) | |||
The public key external_pub can be published as part of the GroupInfo | The public key external_pub can be published as part of the GroupInfo | |||
struct in order to allow non-members to join the group using an | struct in order to allow non-members to join the group using an | |||
external commit. | external Commit. | |||
8.1. Group Context | 8.1. Group Context | |||
Each member of the group maintains a GroupContext object that | Each member of the group maintains a GroupContext object that | |||
summarizes the state of the group: | summarizes the state of the group: | |||
struct { | struct { | |||
ProtocolVersion version = mls10; | ProtocolVersion version = mls10; | |||
CipherSuite cipher_suite; | CipherSuite cipher_suite; | |||
opaque group_id<V>; | opaque group_id<V>; | |||
skipping to change at page 74, line 6 ¶ | skipping to change at line 2945 ¶ | |||
* The group_id field is constant. | * The group_id field is constant. | |||
* The epoch field increments by one for each Commit message that is | * The epoch field increments by one for each Commit message that is | |||
processed. | processed. | |||
* The tree_hash is updated to represent the current tree and | * The tree_hash is updated to represent the current tree and | |||
credentials. | credentials. | |||
* The confirmed_transcript_hash field is updated with the data for | * The confirmed_transcript_hash field is updated with the data for | |||
an AuthenticatedContent encoding a Commit message as described | an AuthenticatedContent encoding a Commit message, as described | |||
below. | below. | |||
* The extensions field changes when a GroupContextExtensions | * The extensions field changes when a GroupContextExtensions | |||
proposal is committed. | proposal is committed. | |||
8.2. Transcript Hashes | 8.2. Transcript Hashes | |||
The transcript hashes computed in MLS represent a running hash over | The transcript hashes computed in MLS represent a running hash over | |||
all Proposal and Commit messages that have ever been sent in a group. | all Proposal and Commit messages that have ever been sent in a group. | |||
Commit messages are included directly. Proposal messages are | Commit messages are included directly. Proposal messages are | |||
indirectly included via the Commit that applied them. Both types of | indirectly included via the Commit that applied them. Messages of | |||
message are included by hashing the AuthenticatedContent object in | both types are included by hashing the AuthenticatedContent object in | |||
which they were sent. | which they were sent. | |||
The transcript hash comprises two individual hashes: | The transcript hash comprises two individual hashes: | |||
* A confirmed_transcript_hash that represents a transcript over the | * A confirmed_transcript_hash that represents a transcript over the | |||
whole history of Commit messages, up to and including the | whole history of Commit messages, up to and including the | |||
signature of the most recent Commit. | signature of the most recent Commit. | |||
* An interim_transcript_hash that covers the confirmed transcript | * An interim_transcript_hash that covers the confirmed transcript | |||
hash plus the confirmation_tag of the most recent Commit. | hash plus the confirmation_tag of the most recent Commit. | |||
New members compute the interim transcript hash using the | New members compute the interim transcript hash using the | |||
confirmation_tag field of the GroupInfo struct, while existing | confirmation_tag field of the GroupInfo struct, while existing | |||
members can compute it directly. | members can compute it directly. | |||
Each Commit message updates these hashes by way of its enclosing | Each Commit message updates these hashes by way of its enclosing | |||
AuthenticatedContent. The AuthenticatedContent struct is split into | AuthenticatedContent. The AuthenticatedContent struct is split into | |||
ConfirmedTranscriptHashInput and InterimTranscriptHashInput. The | ConfirmedTranscriptHashInput and InterimTranscriptHashInput. The | |||
former is used to update the confirmed transcript hash and the latter | former is used to update the confirmed transcript hash and the latter | |||
to update the interim transcript hash. | is used to update the interim transcript hash. | |||
struct { | struct { | |||
WireFormat wire_format; | WireFormat wire_format; | |||
FramedContent content; /* with content_type == commit */ | FramedContent content; /* with content_type == commit */ | |||
opaque signature<V>; | opaque signature<V>; | |||
} ConfirmedTranscriptHashInput; | } ConfirmedTranscriptHashInput; | |||
struct { | struct { | |||
MAC confirmation_tag; | MAC confirmation_tag; | |||
} InterimTranscriptHashInput; | } InterimTranscriptHashInput; | |||
skipping to change at page 76, line 48 ¶ | skipping to change at line 3055 ¶ | |||
| | | | | | |||
| V | | V | |||
| +-----------------+ | | +-----------------+ | |||
+------------>| interim_[N+1] | | +------------>| interim_[N+1] | | |||
+--------+--------+ | +--------+--------+ | |||
| | | | |||
V | V | |||
... | ... | |||
Figure 23: Evolution of the transcript hashes through two epoch | Figure 23: Evolution of the Transcript Hashes through Two Epoch | |||
changes | Changes | |||
8.3. External Initialization | 8.3. External Initialization | |||
In addition to initializing a new epoch via KDF invocations as | In addition to initializing a new epoch via KDF invocations as | |||
described above, an MLS group can also initialize a new epoch via an | described above, an MLS group can also initialize a new epoch via an | |||
asymmetric interaction using the external key pair for the previous | asymmetric interaction using the external key pair for the previous | |||
epoch. This is done when a new member is joining via an external | epoch. This is done when a new member is joining via an external | |||
commit. | commit. | |||
In this process, the joiner sends a new init_secret value to the | In this process, the joiner sends a new init_secret value to the | |||
skipping to change at page 77, line 29 ¶ | skipping to change at line 3082 ¶ | |||
kem_output, context = SetupBaseS(external_pub, "") | kem_output, context = SetupBaseS(external_pub, "") | |||
init_secret = context.export("MLS 1.0 external init secret", KDF.Nh) | init_secret = context.export("MLS 1.0 external init secret", KDF.Nh) | |||
Members of the group receive the kem_output in an ExternalInit | Members of the group receive the kem_output in an ExternalInit | |||
proposal and perform the corresponding calculation to retrieve the | proposal and perform the corresponding calculation to retrieve the | |||
init_secret value. | init_secret value. | |||
context = SetupBaseR(kem_output, external_priv, "") | context = SetupBaseR(kem_output, external_priv, "") | |||
init_secret = context.export("MLS 1.0 external init secret", KDF.Nh) | init_secret = context.export("MLS 1.0 external init secret", KDF.Nh) | |||
In both cases, the info input to HPKE is set to the GroupInfo for the | ||||
previous epoch, encoded using the TLS serialization. | ||||
8.4. Pre-Shared Keys | 8.4. Pre-Shared Keys | |||
Groups that already have an out-of-band mechanism to generate shared | Groups that already have an out-of-band mechanism to generate shared | |||
group secrets can inject those into the MLS key schedule to seed the | group secrets can inject them into the MLS key schedule to | |||
MLS group secrets computations by this external entropy. | incorporate this external entropy in the computation of MLS group | |||
secrets. | ||||
Injecting an external PSK can improve security in the case where | Injecting an external PSK can improve security in the case where | |||
having a full run of Updates across members is too expensive, or if | having a full run of Updates across members is too expensive, or if | |||
the external group key establishment mechanism provides stronger | the external group key establishment mechanism provides stronger | |||
security against classical or quantum adversaries. | security against classical or quantum adversaries. | |||
Note that, as a PSK may have a different lifetime than an Update, it | Note that, as a PSK may have a different lifetime than an Update, it | |||
does not necessarily provide the same Forward Secrecy (FS) or Post- | does not necessarily provide the same forward secrecy or post- | |||
Compromise Security (PCS) guarantees as a Commit message. Unlike the | compromise security guarantees as a Commit message. Unlike the key | |||
key pairs populated in the tree by an Update or Commit, which are | pairs populated in the tree by an Update or Commit, which are always | |||
always freshly generated, PSKs may be pre-distributed and stored. | freshly generated, PSKs may be pre-distributed and stored. This | |||
This creates the risk that a PSK may be compromised in the process of | creates the risk that a PSK may be compromised in the process of | |||
distribution and storage. The security that the group gets from | distribution and storage. The security that the group gets from | |||
injecting a PSK thus depends on both the entropy of the PSK and the | injecting a PSK thus depends on both the entropy of the PSK and the | |||
risk of compromise. These factors are outside of the scope of this | risk of compromise. These factors are outside of the scope of this | |||
document, but should be considered by application designers relying | document, but they should be considered by application designers | |||
on PSKs. | relying on PSKs. | |||
Each PSK in MLS has a type that designates how it was provisioned. | Each PSK in MLS has a type that designates how it was provisioned. | |||
External PSKs are provided by the application, while resumption PSKs | External PSKs are provided by the application, while resumption PSKs | |||
are derived from the MLS key schedule and used in cases where it is | are derived from the MLS key schedule and used in cases where it is | |||
necessary to authenticate a member's participation in a prior epoch. | necessary to authenticate a member's participation in a prior epoch. | |||
The injection of one or more PSKs into the key schedule is signaled | The injection of one or more PSKs into the key schedule is signaled | |||
in two ways: Existing members are informed via PreSharedKey proposals | in two ways: Existing members are informed via PreSharedKey proposals | |||
covered by a Commit, and new members added in the Commit are informed | covered by a Commit, and new members added in the Commit are informed | |||
by the GroupSecrets object in the Welcome message corresponding to | by the GroupSecrets object in the Welcome message corresponding to | |||
skipping to change at page 79, line 36 ¶ | skipping to change at line 3150 ¶ | |||
case resumption: | case resumption: | |||
ResumptionPSKUsage usage; | ResumptionPSKUsage usage; | |||
opaque psk_group_id<V>; | opaque psk_group_id<V>; | |||
uint64 psk_epoch; | uint64 psk_epoch; | |||
}; | }; | |||
opaque psk_nonce<V>; | opaque psk_nonce<V>; | |||
} PreSharedKeyID; | } PreSharedKeyID; | |||
Each time a client injects a PSK into a group, the psk_nonce of its | Each time a client injects a PSK into a group, the psk_nonce of its | |||
PreSharedKeyID MUST be set to a fresh random value of length KDF.Nh, | PreSharedKeyID MUST be set to a fresh random value of length KDF.Nh, | |||
where KDF is the KDF for the ciphersuite of the group into which the | where KDF is the KDF for the cipher suite of the group into which the | |||
PSK is being injected. This ensures that even when a PSK is used | PSK is being injected. This ensures that even when a PSK is used | |||
multiple times, the value used as an input into the key schedule is | multiple times, the value used as an input into the key schedule is | |||
different each time. | different each time. | |||
Upon receiving a Commit with a PreSharedKey proposal or a | Upon receiving a Commit with a PreSharedKey proposal or a | |||
GroupSecrets object with the psks field set, the receiving Client | GroupSecrets object with the psks field set, the receiving client | |||
includes them in the key schedule in the order listed in the Commit, | includes them in the key schedule in the order listed in the Commit, | |||
or in the psks field respectively. For resumption PSKs, the PSK is | or in the psks field, respectively. For resumption PSKs, the PSK is | |||
defined as the resumption_psk of the group and epoch specified in the | defined as the resumption_psk of the group and epoch specified in the | |||
PreSharedKeyID object. Specifically, psk_secret is computed as | PreSharedKeyID object. Specifically, psk_secret is computed as | |||
follows: | follows: | |||
struct { | struct { | |||
PreSharedKeyID id; | PreSharedKeyID id; | |||
uint16 index; | uint16 index; | |||
uint16 count; | uint16 count; | |||
} PSKLabel; | } PSKLabel; | |||
skipping to change at page 80, line 41 ¶ | skipping to change at line 3199 ¶ | |||
0 | | 0 | | |||
| | | | | | |||
V V | V V | |||
psk_[1] --> Extract --> ExpandWithLabel --> Extract = psk_secret_[2] | psk_[1] --> Extract --> ExpandWithLabel --> Extract = psk_secret_[2] | |||
| | | | |||
0 ... | 0 ... | |||
| | | | | | |||
V V | V V | |||
psk_[n-1] --> Extract --> ExpandWithLabel --> Extract = psk_secret_[n] | psk_[n-1] --> Extract --> ExpandWithLabel --> Extract = psk_secret_[n] | |||
Figure 24: Computatation of a PSK secret from a set of PSKs | Figure 24: Computation of a PSK Secret from a Set of PSKs | |||
In particular, if there are no PreSharedKey proposals in a given | In particular, if there are no PreSharedKey proposals in a given | |||
Commit, then the resulting psk_secret is psk_secret_[0], the all-zero | Commit, then the resulting psk_secret is psk_secret_[0], the all-zero | |||
vector. | vector. | |||
8.5. Exporters | 8.5. Exporters | |||
The main MLS key schedule provides an exporter_secret which can be | The main MLS key schedule provides an exporter_secret that can be | |||
used by an application to derive new secrets for use outside of MLS. | used by an application to derive new secrets for use outside of MLS. | |||
MLS-Exporter(Label, Context, Length) = | MLS-Exporter(Label, Context, Length) = | |||
ExpandWithLabel(DeriveSecret(exporter_secret, Label), | ExpandWithLabel(DeriveSecret(exporter_secret, Label), | |||
"exported", Hash(Context), Length) | "exported", Hash(Context), Length) | |||
Applications SHOULD provide a unique label to MLS-Exporter that | Applications SHOULD provide a unique label to MLS-Exporter that | |||
identifies the secret's intended purpose. This is to help prevent | identifies the secret's intended purpose. This is to help prevent | |||
the same secret from being generated and used in two different | the same secret from being generated and used in two different | |||
places. To help avoid the same label being used in different | places. To help avoid the same label being used in different | |||
skipping to change at page 81, line 28 ¶ | skipping to change at line 3233 ¶ | |||
the group. | the group. | |||
It is RECOMMENDED for the application generating exported values to | It is RECOMMENDED for the application generating exported values to | |||
refresh those values after a Commit is processed. | refresh those values after a Commit is processed. | |||
8.6. Resumption PSK | 8.6. Resumption PSK | |||
The main MLS key schedule provides a resumption_psk that is used as a | The main MLS key schedule provides a resumption_psk that is used as a | |||
PSK to inject entropy from one epoch into another. This | PSK to inject entropy from one epoch into another. This | |||
functionality is used in the reinitialization and branching processes | functionality is used in the reinitialization and branching processes | |||
described in Section 11.2 and Section 11.3, but may be used by | described in Sections 11.2 and 11.3, but it may be used by | |||
applications for other purposes. | applications for other purposes. | |||
Some uses of resumption PSKs might call for the use of PSKs from | Some uses of resumption PSKs might call for the use of PSKs from | |||
historical epochs. The application SHOULD specify an upper limit on | historical epochs. The application SHOULD specify an upper limit on | |||
the number of past epochs for which the resumption_psk may be stored. | the number of past epochs for which the resumption_psk may be stored. | |||
8.7. Epoch Authenticators | 8.7. Epoch Authenticators | |||
The main MLS key schedule provides a per-epoch epoch_authenticator. | The main MLS key schedule provides a per-epoch epoch_authenticator. | |||
If one member of the group is being impersonated by an active | If one member of the group is being impersonated by an active | |||
attacker, the epoch_authenticator computed by their client will | attacker, the epoch_authenticator computed by their client will | |||
differ from those computed by the other group members. | differ from those computed by the other group members. | |||
This property can be used to construct defenses against impersonation | This property can be used to construct defenses against impersonation | |||
attacks that are effective even if members' signature keys are | attacks that are effective even if members' signature keys are | |||
compromised. As a trivial example, if the users of the clients in an | compromised. As a trivial example, if the users of the clients in an | |||
MLS group were to meet in person and reliably confirm that their | MLS group were to meet in person and reliably confirm that their | |||
epoch authenticator values were equal (using some suitable user | epoch authenticator values were equal (using some suitable user | |||
interface), then each user would be assured that the others were not | interface), then each user would be assured that the others were not | |||
being impersonated in the current epoch. As soon as the epoch | being impersonated in the current epoch. As soon as the epoch | |||
changed, though, they would need to re-do this confirmation. The | changed, though, they would need to redo this confirmation. The | |||
state of the group would have changed, possibly introducing an | state of the group would have changed, possibly introducing an | |||
attacker. | attacker. | |||
More generally, in order for the members of an MLS group to obtain | More generally, in order for the members of an MLS group to obtain | |||
concrete authentication protections using the epoch_authenticator, | concrete authentication protections using the epoch_authenticator, | |||
they will need to use it in some secondary protocol (such as the | they will need to use it in some secondary protocol (such as the | |||
face-to-face protocol above). The details of that protocol will then | face-to-face protocol above). The details of that protocol will then | |||
determine the specific authentication protections provided to the MLS | determine the specific authentication protections provided to the MLS | |||
group. | group. | |||
9. Secret Tree | 9. Secret Tree | |||
For the generation of encryption keys and nonces, the key schedule | For the generation of encryption keys and nonces, the key schedule | |||
begins with the encryption_secret at the root and derives a tree of | begins with the encryption_secret at the root and derives a tree of | |||
secrets with the same structure as the group's ratchet tree. Each | secrets with the same structure as the group's ratchet tree. Each | |||
leaf in the Secret Tree is associated with the same group member as | leaf in the secret tree is associated with the same group member as | |||
the corresponding leaf in the ratchet tree. | the corresponding leaf in the ratchet tree. | |||
If N is a parent node in the Secret Tree then the secrets of the | If N is a parent node in the secret tree, then the secrets of the | |||
children of N are defined as follows (where left(N) and right(N) | children of N are defined as follows (where left(N) and right(N) | |||
denote the children of N): | denote the children of N): | |||
tree_node_[N]_secret | tree_node_[N]_secret | |||
| | | | |||
| | | | |||
+--> ExpandWithLabel(., "tree", "left", KDF.Nh) | +--> ExpandWithLabel(., "tree", "left", KDF.Nh) | |||
| = tree_node_[left(N)]_secret | | = tree_node_[left(N)]_secret | |||
| | | | |||
+--> ExpandWithLabel(., "tree", "right", KDF.Nh) | +--> ExpandWithLabel(., "tree", "right", KDF.Nh) | |||
= tree_node_[right(N)]_secret | = tree_node_[right(N)]_secret | |||
Figure 25: Derivation of secrets from parent to children within a | Figure 25: Derivation of Secrets from Parent to Children within a | |||
secret tree | Secret Tree | |||
The secret in the leaf of the Secret Tree is used to initiate two | The secret in the leaf of the secret tree is used to initiate two | |||
symmetric hash ratchets, from which a sequence of single-use keys and | symmetric hash ratchets, from which a sequence of single-use keys and | |||
nonces are derived, as described in Section 9.1. The root of each | nonces are derived, as described in Section 9.1. The root of each | |||
ratchet is computed as: | ratchet is computed as: | |||
tree_node_[N]_secret | tree_node_[N]_secret | |||
| | | | |||
| | | | |||
+--> ExpandWithLabel(., "handshake", "", KDF.Nh) | +--> ExpandWithLabel(., "handshake", "", KDF.Nh) | |||
| = handshake_ratchet_secret_[N]_[0] | | = handshake_ratchet_secret_[N]_[0] | |||
| | | | |||
+--> ExpandWithLabel(., "application", "", KDF.Nh) | +--> ExpandWithLabel(., "application", "", KDF.Nh) | |||
= application_ratchet_secret_[N]_[0] | = application_ratchet_secret_[N]_[0] | |||
Figure 26: Initialization of the hash ratchets from the leaves of | Figure 26: Initialization of the Hash Ratchets from the Leaves of | |||
a secret tree | a Secret Tree | |||
9.1. Encryption Keys | 9.1. Encryption Keys | |||
As described in Section 6, MLS encrypts three different types of | As described in Section 6, MLS encrypts three different types of | |||
information: | information: | |||
* Metadata (sender information) | * Metadata (sender information) | |||
* Handshake messages (Proposal and Commit) | * Handshake messages (Proposal and Commit) | |||
skipping to change at page 83, line 47 ¶ | skipping to change at line 3348 ¶ | |||
HR0 AR0--+--K0 | HR0 AR0--+--K0 | |||
| | | | | | |||
| +--N0 | | +--N0 | |||
| | | | |||
AR1--+--K1 | AR1--+--K1 | |||
| | | | | | |||
| +--N1 | | +--N1 | |||
| | | | |||
AR2 | AR2 | |||
Figure 27: Secret tree for a four-member group | Figure 27: Secret Tree for a Four-Member Group | |||
A sender ratchet starts from a per-sender base secret derived from a | A sender ratchet starts from a per-sender base secret derived from a | |||
Secret Tree, as described in Section 9. The base secret initiates a | Secret Tree, as described in Section 9. The base secret initiates a | |||
symmetric hash ratchet which generates a sequence of keys and nonces. | symmetric hash ratchet, which generates a sequence of keys and | |||
The sender uses the j-th key/nonce pair in the sequence to encrypt | nonces. The sender uses the j-th key/nonce pair in the sequence to | |||
(using the AEAD) the j-th message they send during that epoch. Each | encrypt (using the AEAD) the j-th message they send during that | |||
key/nonce pair MUST NOT be used to encrypt more than one message. | epoch. Each key/nonce pair MUST NOT be used to encrypt more than one | |||
message. | ||||
Keys, nonces, and the secrets in ratchets are derived using | Keys, nonces, and the secrets in ratchets are derived using | |||
DeriveTreeSecret. The context in a given call consists of the | DeriveTreeSecret. The context in a given call consists of the | |||
current position in the ratchet. | current position in the ratchet. | |||
DeriveTreeSecret(Secret, Label, Generation, Length) = | DeriveTreeSecret(Secret, Label, Generation, Length) = | |||
ExpandWithLabel(Secret, Label, Generation, Length) | ExpandWithLabel(Secret, Label, Generation, Length) | |||
Where Generation is encoded as a big endian uint32. | Where Generation is encoded as a big endian uint32. | |||
skipping to change at page 84, line 33 ¶ | skipping to change at line 3379 ¶ | |||
+--> DeriveTreeSecret(., "nonce", j, AEAD.Nn) | +--> DeriveTreeSecret(., "nonce", j, AEAD.Nn) | |||
| = ratchet_nonce_[N]_[j] | | = ratchet_nonce_[N]_[j] | |||
| | | | |||
+--> DeriveTreeSecret(., "key", j, AEAD.Nk) | +--> DeriveTreeSecret(., "key", j, AEAD.Nk) | |||
| = ratchet_key_[N]_[j] | | = ratchet_key_[N]_[j] | |||
| | | | |||
V | V | |||
DeriveTreeSecret(., "secret", j, KDF.Nh) | DeriveTreeSecret(., "secret", j, KDF.Nh) | |||
= ratchet_secret_[N]_[j+1] | = ratchet_secret_[N]_[j+1] | |||
Here, AEAD.Nn and AEAD.Nk denote the lengths in bytes of the nonce | Here AEAD.Nn and AEAD.Nk denote the lengths in bytes of the nonce and | |||
and key for the AEAD scheme defined by the ciphersuite. | key for the AEAD scheme defined by the cipher suite. | |||
9.2. Deletion Schedule | 9.2. Deletion Schedule | |||
It is important to delete all security-sensitive values as soon as | It is important to delete all security-sensitive values as soon as | |||
they are _consumed_. A sensitive value S is said to be _consumed_ if | they are _consumed_. A sensitive value S is said to be _consumed_ if: | |||
* S was used to encrypt or (successfully) decrypt a message, or if | * S was used to encrypt or (successfully) decrypt a message, or | |||
* a key, nonce, or secret derived from S has been consumed. (This | * a key, nonce, or secret derived from S has been consumed. (This | |||
goes for values derived via DeriveSecret as well as | goes for values derived via DeriveSecret as well as | |||
ExpandWithLabel.) | ExpandWithLabel.) | |||
Here, S may be the init_secret, commit_secret, epoch_secret, | Here S may be the init_secret, commit_secret, epoch_secret, or | |||
encryption_secret as well as any secret in a Secret Tree or one of | encryption_secret as well as any secret in a secret tree or one of | |||
the ratchets. | the ratchets. | |||
As soon as a group member consumes a value they MUST immediately | As soon as a group member consumes a value, they MUST immediately | |||
delete (all representations of) that value. This is crucial to | delete (all representations of) that value. This is crucial to | |||
ensuring forward secrecy for past messages. Members MAY keep | ensuring forward secrecy for past messages. Members MAY keep | |||
unconsumed values around for some reasonable amount of time to handle | unconsumed values around for some reasonable amount of time to handle | |||
out-of-order message delivery. | out-of-order message delivery. | |||
For example, suppose a group member encrypts or (successfully) | For example, suppose a group member encrypts or (successfully) | |||
decrypts an application message using the j-th key and nonce in the | decrypts an application message using the j-th key and nonce in the | |||
ratchet of leaf node L in some epoch n. Then, for that member, at | ratchet of leaf node L in some epoch n. Then, for that member, at | |||
least the following values have been consumed and MUST be deleted: | least the following values have been consumed and MUST be deleted: | |||
* the commit_secret, joiner_secret, epoch_secret, encryption_secret | * the commit_secret, joiner_secret, epoch_secret, and | |||
of that epoch n as well as the init_secret of the previous epoch | encryption_secret of that epoch n as well as the init_secret of | |||
n-1, | the previous epoch n-1, | |||
* all node secrets in the Secret Tree on the path from the root to | * all node secrets in the secret tree on the path from the root to | |||
the leaf with node L, | the leaf with node L, | |||
* the first j secrets in the application data ratchet of node L and | * the first j secrets in the application data ratchet of node L, and | |||
* application_ratchet_nonce_[L]_[j] and | * application_ratchet_nonce_[L]_[j] and | |||
application_ratchet_key_[L]_[j]. | application_ratchet_key_[L]_[j]. | |||
Concretely, consider the Secret Tree shown in Figure 27. Client A, | Concretely, consider the secret tree shown in Figure 27. Client A, | |||
B, or C would generate the illustrated values on receiving a message | B, or C would generate the illustrated values on receiving a message | |||
from D with generation equal to 1, having not received a message with | from D with generation equal to 1, having not received a message with | |||
generation 0 (e.g., due to out-of-order delivery). In such a case, | generation 0 (e.g., due to out-of-order delivery). In such a case, | |||
the following values would be consumed: | the following values would be consumed: | |||
* The key K1 and nonce N1 used to decrypt the message | * The key K1 and nonce N1 used to decrypt the message | |||
* The application ratchet secrets AR1 and AR0 | * The application ratchet secrets AR1 and AR0 | |||
* The tree secrets D, F, G (recall that G is the encryption_secret | * The tree secrets D, F, and G (recall that G is the | |||
for the epoch) | encryption_secret for the epoch) | |||
* The epoch_secret, commit_secret, psk_secret, and joiner_secret for | * The epoch_secret, commit_secret, psk_secret, and joiner_secret for | |||
the current epoch | the current epoch | |||
Other values may be retained (not consumed): | Other values may be retained (not consumed): | |||
* K0 and N0 for decryption of an out-of-order message with | * K0 and N0 for decryption of an out-of-order message with | |||
generation 0 | generation 0 | |||
* AR2 for derivation of further message decryption keys and nonces | * AR2 for derivation of further message decryption keys and nonces | |||
skipping to change at page 86, line 4 ¶ | skipping to change at line 3444 ¶ | |||
the current epoch | the current epoch | |||
Other values may be retained (not consumed): | Other values may be retained (not consumed): | |||
* K0 and N0 for decryption of an out-of-order message with | * K0 and N0 for decryption of an out-of-order message with | |||
generation 0 | generation 0 | |||
* AR2 for derivation of further message decryption keys and nonces | * AR2 for derivation of further message decryption keys and nonces | |||
* HR0 for protection of handshake messages from D | * HR0 for protection of handshake messages from D | |||
* E and C for deriving secrets used by senders A, B, and C | * E and C for deriving secrets used by senders A, B, and C | |||
10. Key Packages | 10. Key Packages | |||
In order to facilitate the asynchronous addition of clients to a | In order to facilitate the asynchronous addition of clients to a | |||
group, key packages are pre-published that provide some public | group, clients can pre-publish KeyPackage objects that provide some | |||
information about a user. A KeyPackage object specifies: | public information about a user. A KeyPackage object specifies: | |||
1. A protocol version and ciphersuite that the client supports, | 1. a protocol version and cipher suite that the client supports, | |||
2. a public key that others can use to encrypt a Welcome message to | 2. a public key that others can use to encrypt a Welcome message to | |||
this client (an "init key"), and | this client (an "init key"), and | |||
3. the content of the leaf node that should be added to the tree to | 3. the content of the leaf node that should be added to the tree to | |||
represent this client. | represent this client. | |||
KeyPackages are intended to be used only once and SHOULD NOT be | KeyPackages are intended to be used only once and SHOULD NOT be | |||
reused except in the case of last resort (see Section 16.8). Clients | reused except in the case of a "last resort" KeyPackage (see | |||
MAY generate and publish multiple KeyPackages to support multiple | Section 16.8). Clients MAY generate and publish multiple KeyPackages | |||
ciphersuites. | to support multiple cipher suites. | |||
The value for init_key MUST be a public key for the asymmetric | The value for init_key MUST be a public key for the asymmetric | |||
encryption scheme defined by cipher_suite, and it MUST be unique | encryption scheme defined by cipher_suite, and it MUST be unique | |||
among the set of KeyPackages created by this client. Likewise, the | among the set of KeyPackages created by this client. Likewise, the | |||
leaf_node field MUST be valid for the ciphersuite, including both the | leaf_node field MUST be valid for the cipher suite, including both | |||
encryption_key and signature_key fields. The whole structure is | the encryption_key and signature_key fields. The whole structure is | |||
signed using the client's signature key. A KeyPackage object with an | signed using the client's signature key. A KeyPackage object with an | |||
invalid signature field MUST be considered malformed. | invalid signature field MUST be considered malformed. | |||
The signature is computed by the function SignWithLabel with a label | The signature is computed by the function SignWithLabel with a label | |||
KeyPackageTBS and a Content input comprising all of the fields except | "KeyPackageTBS" and a Content input comprising all of the fields | |||
for the signature field. | except for the signature field. | |||
struct { | struct { | |||
ProtocolVersion version; | ProtocolVersion version; | |||
CipherSuite cipher_suite; | CipherSuite cipher_suite; | |||
HPKEPublicKey init_key; | HPKEPublicKey init_key; | |||
LeafNode leaf_node; | LeafNode leaf_node; | |||
Extension extensions<V>; | Extension extensions<V>; | |||
/* SignWithLabel(., "KeyPackageTBS", KeyPackageTBS) */ | /* SignWithLabel(., "KeyPackageTBS", KeyPackageTBS) */ | |||
opaque signature<V>; | opaque signature<V>; | |||
} KeyPackage; | } KeyPackage; | |||
skipping to change at page 87, line 31 ¶ | skipping to change at line 3504 ¶ | |||
} KeyPackageTBS; | } KeyPackageTBS; | |||
If a client receives a KeyPackage carried within an MLSMessage | If a client receives a KeyPackage carried within an MLSMessage | |||
object, then it MUST verify that the version field of the KeyPackage | object, then it MUST verify that the version field of the KeyPackage | |||
has the same value as the version field of the MLSMessage. The | has the same value as the version field of the MLSMessage. The | |||
version field in the KeyPackage provides an explicit signal of the | version field in the KeyPackage provides an explicit signal of the | |||
intended version to the other members of group when they receive the | intended version to the other members of group when they receive the | |||
KeyPackage in an Add proposal. | KeyPackage in an Add proposal. | |||
The field leaf_node.capabilities indicates what protocol versions, | The field leaf_node.capabilities indicates what protocol versions, | |||
ciphersuites, credential types, and non-default proposal/extension | cipher suites, credential types, and non-default proposal/extension | |||
types are supported by the client. (Proposal and extension types | types are supported by the client. (As discussed in Section 7.2, | |||
defined in this document are considered "default" and not listed.) | some proposal and extension types defined in this document are | |||
This information allows MLS session establishment to be safe from | considered "default" and thus are not listed.) This information | |||
downgrade attacks on the parameters described (as discussed in | allows MLS session establishment to be safe from downgrade attacks on | |||
Section 11), while still only advertising one version / ciphersuite | the parameters described (as discussed in Section 11), while still | |||
per KeyPackage. | only advertising one version and one cipher suite per KeyPackage. | |||
The field leaf_node.leaf_node_source of the LeafNode in a KeyPackage | The field leaf_node.leaf_node_source of the LeafNode in a KeyPackage | |||
MUST be set to key_package. | MUST be set to key_package. | |||
Extensions included in the extensions or leaf_node.extensions fields | Extensions included in the extensions or leaf_node.extensions fields | |||
MUST be included in the leaf_node.capabilities field. As discussed | MUST be included in the leaf_node.capabilities field. As discussed | |||
in Section 13, unknown extensions in KeyPackage.extensions MUST be | in Section 13, unknown extensions in KeyPackage.extensions MUST be | |||
ignored, and the creator of a KeyPackage object SHOULD include some | ignored, and the creator of a KeyPackage object SHOULD include some | |||
random GREASE extensions to help ensure that other clients correctly | random GREASE extensions to help ensure that other clients correctly | |||
ignore unknown extensions. | ignore unknown extensions. | |||
skipping to change at page 88, line 13 ¶ | skipping to change at line 3534 ¶ | |||
The validity of a KeyPackage needs to be verified at a few stages: | The validity of a KeyPackage needs to be verified at a few stages: | |||
* When a KeyPackage is downloaded by a group member, before it is | * When a KeyPackage is downloaded by a group member, before it is | |||
used to add the client to the group | used to add the client to the group | |||
* When a KeyPackage is received by a group member in an Add message | * When a KeyPackage is received by a group member in an Add message | |||
The client verifies the validity of a KeyPackage using the following | The client verifies the validity of a KeyPackage using the following | |||
steps: | steps: | |||
* Verify that the ciphersuite and protocol version of the KeyPackage | * Verify that the cipher suite and protocol version of the | |||
match those in the GroupContext. | KeyPackage match those in the GroupContext. | |||
* Verify that the leaf_node of the KeyPackage is valid for a | * Verify that the leaf_node of the KeyPackage is valid for a | |||
KeyPackage according to Section 7.3. | KeyPackage according to Section 7.3. | |||
* Verify that the signature on the KeyPackage is valid using the | * Verify that the signature on the KeyPackage is valid using the | |||
public key in leaf_node.credential. | public key in leaf_node.credential. | |||
* Verify that the value of leaf_node.encryption_key is different | * Verify that the value of leaf_node.encryption_key is different | |||
from the value of the init_key field. | from the value of the init_key field. | |||
11. Group Creation | 11. Group Creation | |||
A group is always created with a single member, the "creator". Other | A group is always created with a single member, the "creator". Other | |||
members are then added to the group using the usual Add/Commit | members are then added to the group using the usual Add/Commit | |||
mechanism. | mechanism. | |||
The creator of a group is responsible for setting the group ID, | The creator of a group is responsible for setting the group ID, | |||
ciphersuite, and initial extensions for the group. If the creator | cipher suite, and initial extensions for the group. If the creator | |||
intends to add other members at the time of creation, then it SHOULD | intends to add other members at the time of creation, then it SHOULD | |||
Fetch KeyPackages for the members to be added, and select a | fetch KeyPackages for the members to be added, and select a cipher | |||
ciphersuite and extensions according to the capabilities of the | suite and extensions according to the capabilities of the members. | |||
members. To protect against downgrade attacks, the creator MUST use | To protect against downgrade attacks, the creator MUST use the | |||
the capabilities information in these KeyPackages to verify that the | capabilities information in these KeyPackages to verify that the | |||
chosen version and ciphersuite is the best option supported by all | chosen version and cipher suite is the best option supported by all | |||
members. | members. | |||
Group IDs SHOULD be constructed in such a way that there's an | Group IDs SHOULD be constructed in such a way that there is an | |||
overwhelmingly low probability of honest group creators generating | overwhelmingly low probability of honest group creators generating | |||
the same group ID, even without assistance from the Delivery Service. | the same group ID, even without assistance from the Delivery Service. | |||
For example, by making the group ID a freshly generated random value | This can be done, for example, by making the group ID a freshly | |||
of size KDF.Nh. The Delivery Service MAY attempt to ensure that | generated random value of size KDF.Nh. The Delivery Service MAY | |||
group IDs are globally unique by rejecting the creation of new groups | attempt to ensure that group IDs are globally unique by rejecting the | |||
with a previously used ID. | creation of new groups with a previously used ID. | |||
The creator of a group MUST take the following steps to initialize | To initialize a group, the creator of the group MUST take the | |||
the group: | following steps: | |||
* Initialize a one-member group with the following initial values: | * Initialize a one-member group with the following initial values: | |||
- Ratchet tree: A tree with a single node, a leaf containing an | - Ratchet tree: A tree with a single node, a leaf node containing | |||
HPKE public key and credential for the creator | an HPKE public key and credential for the creator | |||
- Group ID: A value set by the creator | - Group ID: A value set by the creator | |||
- Epoch: 0 | - Epoch: 0 | |||
- Tree hash: The root hash of the above ratchet tree | - Tree hash: The root hash of the above ratchet tree | |||
- Confirmed transcript hash: The zero-length octet string | - Confirmed transcript hash: The zero-length octet string | |||
- Epoch secret: A fresh random value of size KDF.Nh | - Epoch secret: A fresh random value of size KDF.Nh | |||
skipping to change at page 89, line 31 ¶ | skipping to change at line 3601 ¶ | |||
- Derive the confirmation_key for the epoch as described in | - Derive the confirmation_key for the epoch as described in | |||
Section 8. | Section 8. | |||
- Compute a confirmation_tag over the empty | - Compute a confirmation_tag over the empty | |||
confirmed_transcript_hash using the confirmation_key as | confirmed_transcript_hash using the confirmation_key as | |||
described in Section 6.1. | described in Section 6.1. | |||
- Compute the updated interim_transcript_hash from the | - Compute the updated interim_transcript_hash from the | |||
confirmed_transcript_hash and the confirmation_tag as described | confirmed_transcript_hash and the confirmation_tag as described | |||
in Section 8.2 | in Section 8.2. | |||
At this point, the creator's state represents a one-member group with | At this point, the creator's state represents a one-member group with | |||
a fully initialized key schedule, transcript hashes, etc. Proposals | a fully initialized key schedule, transcript hashes, etc. Proposals | |||
and Commits can be generated for this group state just like any other | and Commits can be generated for this group state just like any other | |||
state of the group, such as Add proposals and Commits to add other | state of the group, such as Add proposals and Commits to add other | |||
members to the group. A GroupInfo object for this group state can | members to the group. A GroupInfo object for this group state can | |||
also be published to facilitate external joins. | also be published to facilitate external joins. | |||
Members other than the creator join either by being sent a Welcome | Members other than the creator join either by being sent a Welcome | |||
message (as described in Section 12.4.3.1) or by sending an external | message (as described in Section 12.4.3.1) or by sending an external | |||
skipping to change at page 90, line 9 ¶ | skipping to change at line 3625 ¶ | |||
creator directly create a tree and choose a random value for first | creator directly create a tree and choose a random value for first | |||
epoch's epoch secret. We follow the steps above because it removes | epoch's epoch secret. We follow the steps above because it removes | |||
unnecessary choices, by which, for example, bad randomness could be | unnecessary choices, by which, for example, bad randomness could be | |||
introduced. The only choices the creator makes here are its own | introduced. The only choices the creator makes here are its own | |||
KeyPackage and the leaf secret from which the Commit is built. | KeyPackage and the leaf secret from which the Commit is built. | |||
11.1. Required Capabilities | 11.1. Required Capabilities | |||
The configuration of a group imposes certain requirements on clients | The configuration of a group imposes certain requirements on clients | |||
in the group. At a minimum, all members of the group need to support | in the group. At a minimum, all members of the group need to support | |||
the ciphersuite and protocol version in use. Additional requirements | the cipher suite and protocol version in use. Additional | |||
can be imposed by including a required_capabilities extension in the | requirements can be imposed by including a required_capabilities | |||
GroupContext. | extension in the GroupContext. | |||
struct { | struct { | |||
ExtensionType extension_types<V>; | ExtensionType extension_types<V>; | |||
ProposalType proposal_types<V>; | ProposalType proposal_types<V>; | |||
CredentialType credential_types<V>; | CredentialType credential_types<V>; | |||
} RequiredCapabilities; | } RequiredCapabilities; | |||
This extension lists the extensions, proposals, and credential types | This extension lists the extensions, proposals, and credential types | |||
that must be supported by all members of the group. The "default" | that must be supported by all members of the group. The "default" | |||
proposal and extension types defined in this document are assumed to | proposal and extension types defined in this document are assumed to | |||
skipping to change at page 90, line 42 ¶ | skipping to change at line 3658 ¶ | |||
default capabilities not supported by all current members. | default capabilities not supported by all current members. | |||
11.2. Reinitialization | 11.2. Reinitialization | |||
A group may be reinitialized by creating a new group with the same | A group may be reinitialized by creating a new group with the same | |||
membership and different parameters, and linking it to the old group | membership and different parameters, and linking it to the old group | |||
via a resumption PSK. The members of a group reinitialize it using | via a resumption PSK. The members of a group reinitialize it using | |||
the following steps: | the following steps: | |||
1. A member of the old group sends a ReInit proposal (see | 1. A member of the old group sends a ReInit proposal (see | |||
Section 12.1.5) | Section 12.1.5). | |||
2. A member of the old group sends a Commit covering the ReInit | 2. A member of the old group sends a Commit covering the ReInit | |||
proposal | proposal. | |||
3. A member of the old group creates an initial Commit that sets up | ||||
a new group that matches the ReInit and sends a Welcome message: | ||||
3. A member of the old group creates an initial Commit setting up a | ||||
new group that matches the ReInit and sends a Welcome message | ||||
* The version, cipher_suite, group_id, and extensions fields of | * The version, cipher_suite, group_id, and extensions fields of | |||
the GroupContext object in the Welcome message MUST be the | the GroupContext object in the Welcome message MUST be the | |||
same as the corresponding fields in the ReInit proposal. The | same as the corresponding fields in the ReInit proposal. The | |||
epoch in the Welcome message MUST be 1. | epoch in the Welcome message MUST be 1. | |||
* The Welcome MUST specify a PreSharedKeyID of type resumption | * The Welcome message MUST specify a PreSharedKeyID of type | |||
with usage reinit, where the group_id field matches the old | resumption with usage reinit, where the group_id field matches | |||
group and the epoch field indicates the epoch after the Commit | the old group and the epoch field indicates the epoch after | |||
covering the ReInit. | the Commit covering the ReInit. | |||
Note that these three steps may be done by the same group member or | Note that these three steps may be done by the same group member or | |||
different members. For example, if a group member sends a Commit | different members. For example, if a group member sends a Commit | |||
with an inline ReInit proposal (steps 1 and 2) but then goes offline, | with an inline ReInit proposal (steps 1 and 2) but then goes offline, | |||
another group member may recreate the group instead. This | another group member may recreate the group instead. This | |||
flexibility avoids situations where a group gets stuck between steps | flexibility avoids situations where a group gets stuck between steps | |||
2 and 3. | 2 and 3. | |||
Resumption PSKs with usage reinit MUST NOT be used in other contexts. | Resumption PSKs with usage reinit MUST NOT be used in other contexts. | |||
A PreSharedKey proposal with type resumption and usage reinit MUST be | A PreSharedKey proposal with type resumption and usage reinit MUST be | |||
skipping to change at page 91, line 37 ¶ | skipping to change at line 3699 ¶ | |||
A new group can be formed from a subset of an existing group's | A new group can be formed from a subset of an existing group's | |||
members, using the same parameters as the old group. | members, using the same parameters as the old group. | |||
A member can create a subgroup by performing the following steps: | A member can create a subgroup by performing the following steps: | |||
1. Fetch a new KeyPackage for each group member that should be | 1. Fetch a new KeyPackage for each group member that should be | |||
included in the subgroup. | included in the subgroup. | |||
2. Create an initial Commit message that sets up the new group and | 2. Create an initial Commit message that sets up the new group and | |||
contains a PreSharedKey proposal of type resumption with usage | contains a PreSharedKey proposal of type resumption with usage | |||
branch. To avoid key re-use, the psk_nonce included in the | branch. To avoid key reuse, the psk_nonce included in the | |||
PreSharedKeyID object MUST be a randomly sampled nonce of length | PreSharedKeyID object MUST be a randomly sampled nonce of length | |||
KDF.Nh. | KDF.Nh. | |||
3. Send the corresponding Welcome message to the subgroup members. | 3. Send the corresponding Welcome message to the subgroup members. | |||
A client receiving a Welcome including a PreSharedKey of type | A client receiving a Welcome message including a PreSharedKey of type | |||
resumption with usage branch MUST verify that the new group reflects | resumption with usage branch MUST verify that the new group reflects | |||
a subgroup branched from the referenced group by checking: | a subgroup branched from the referenced group by checking that: | |||
* The version and ciphersuite values in the Welcome are the same as | * The version and cipher_suite values in the Welcome message are the | |||
those used by the old group. | same as those used by the old group. | |||
* The epoch in the Welcome message MUST be 1. | * The epoch in the Welcome message MUST be 1. | |||
* Each LeafNode in a new subgroup MUST match some LeafNode in the | * Each LeafNode in a new subgroup MUST match some LeafNode in the | |||
original group. In this context, a pair of LeafNodes is said to | original group. In this context, a pair of LeafNodes is said to | |||
"match" if the identifiers presented by their respective | "match" if the identifiers presented by their respective | |||
credentials are considered equivalent by the application. | credentials are considered equivalent by the application. | |||
Resumption PSKs with usage branch MUST NOT be used in other contexts. | Resumption PSKs with usage branch MUST NOT be used in other contexts. | |||
A PreSharedKey proposal with type resumption and usage branch MUST be | A PreSharedKey proposal with type resumption and usage branch MUST be | |||
considered invalid. | considered invalid. | |||
12. Group Evolution | 12. Group Evolution | |||
Over the lifetime of a group, its membership can change, and existing | Over the lifetime of a group, its membership can change, and existing | |||
members might want to change their keys in order to achieve post- | members might want to change their keys in order to achieve post- | |||
compromise security. In MLS, each such change is accomplished by a | compromise security. In MLS, each such change is accomplished by a | |||
two-step process: | two-step process: | |||
1. A proposal to make the change is broadcast to the group in a | 1. A proposal to make the change is broadcast to the group in a | |||
Proposal message | Proposal message. | |||
2. A member of the group or a new member broadcasts a Commit message | 2. A member of the group or a new member broadcasts a Commit message | |||
that causes one or more proposed changes to enter into effect | that causes one or more proposed changes to enter into effect. | |||
In cases where the Proposal and Commit are sent by the same member, | In cases where the Proposal and Commit are sent by the same member, | |||
these two steps can be combined by sending the proposals in the | these two steps can be combined by sending the proposals in the | |||
commit. | commit. | |||
The group thus evolves from one cryptographic state to another each | The group thus evolves from one cryptographic state to another each | |||
time a Commit message is sent and processed. These states are | time a Commit message is sent and processed. These states are | |||
referred to as "epochs" and are uniquely identified among states of | referred to as "epochs" and are uniquely identified among states of | |||
the group by eight-octet epoch values. When a new group is | the group by eight-octet epoch values. When a new group is | |||
initialized, its initial state epoch is 0x0000000000000000. Each | initialized, its initial state epoch is 0x0000000000000000. Each | |||
time a state transition occurs, the epoch number is incremented by | time a state transition occurs, the epoch number is incremented by | |||
one. | one. | |||
12.1. Proposals | 12.1. Proposals | |||
Proposals are included in a FramedContent by way of a Proposal | Proposals are included in a FramedContent by way of a Proposal | |||
structure that indicates their type: | structure that indicates their type: | |||
// See IANA registry for registered values | // See the "MLS Proposal Types" IANA registry for values | |||
uint16 ProposalType; | uint16 ProposalType; | |||
struct { | struct { | |||
ProposalType proposal_type; | ProposalType proposal_type; | |||
select (Proposal.proposal_type) { | select (Proposal.proposal_type) { | |||
case add: Add; | case add: Add; | |||
case update: Update; | case update: Update; | |||
case remove: Remove; | case remove: Remove; | |||
case psk: PreSharedKey; | case psk: PreSharedKey; | |||
case reinit: ReInit; | case reinit: ReInit; | |||
skipping to change at page 93, line 51 ¶ | skipping to change at line 3799 ¶ | |||
An Add is applied after being included in a Commit message. The | An Add is applied after being included in a Commit message. The | |||
position of the Add in the list of proposals determines the leaf node | position of the Add in the list of proposals determines the leaf node | |||
where the new member will be added. For the first Add in the Commit, | where the new member will be added. For the first Add in the Commit, | |||
the corresponding new member will be placed in the leftmost empty | the corresponding new member will be placed in the leftmost empty | |||
leaf in the tree, for the second Add, the next empty leaf to the | leaf in the tree, for the second Add, the next empty leaf to the | |||
right, etc. If no empty leaf exists, the tree is extended to the | right, etc. If no empty leaf exists, the tree is extended to the | |||
right. | right. | |||
* Identify the leaf L for the new member: if there are empty leaves | * Identify the leaf L for the new member: if there are empty leaves | |||
in the tree, L is the leftmost empty leaf. Otherwise, the tree is | in the tree, L is the leftmost empty leaf. Otherwise, the tree is | |||
extended to the right as described in Section 7.7 and L is | extended to the right as described in Section 7.7, and L is | |||
assigned the leftmost new blank leaf. | assigned the leftmost new blank leaf. | |||
* For each non-blank intermediate node along the path from the leaf | * For each non-blank intermediate node along the path from the leaf | |||
L to the root, add L's leaf index to the unmerged_leaves list for | L to the root, add L's leaf index to the unmerged_leaves list for | |||
the node. | the node. | |||
* Set the leaf node L to a new node containing the LeafNode object | * Set the leaf node L to a new node containing the LeafNode object | |||
carried in the leaf_node field of the KeyPackage in the Add. | carried in the leaf_node field of the KeyPackage in the Add. | |||
12.1.2. Update | 12.1.2. Update | |||
skipping to change at page 94, line 29 ¶ | skipping to change at line 3826 ¶ | |||
LeafNode leaf_node; | LeafNode leaf_node; | |||
} Update; | } Update; | |||
An Update proposal is invalid if the LeafNode is invalid for an | An Update proposal is invalid if the LeafNode is invalid for an | |||
Update proposal according to Section 7.3. | Update proposal according to Section 7.3. | |||
A member of the group applies an Update message by taking the | A member of the group applies an Update message by taking the | |||
following steps: | following steps: | |||
* Replace the sender's LeafNode with the one contained in the Update | * Replace the sender's LeafNode with the one contained in the Update | |||
proposal | proposal. | |||
* Blank the intermediate nodes along the path from the sender's leaf | * Blank the intermediate nodes along the path from the sender's leaf | |||
to the root | to the root. | |||
12.1.3. Remove | 12.1.3. Remove | |||
A Remove proposal requests that the member with the leaf index | A Remove proposal requests that the member with the leaf index | |||
removed be removed from the group. | removed be removed from the group. | |||
struct { | struct { | |||
uint32 removed; | uint32 removed; | |||
} Remove; | } Remove; | |||
A Remove proposal is invalid if the removed field does not identify a | A Remove proposal is invalid if the removed field does not identify a | |||
non-blank leaf node. | non-blank leaf node. | |||
A member of the group applies a Remove message by taking the | A member of the group applies a Remove message by taking the | |||
following steps: | following steps: | |||
* Identify the leaf node matching removed. Let L be this leaf node. | * Identify the leaf node matching removed. Let L be this leaf node. | |||
* Replace the leaf node L with a blank node | * Replace the leaf node L with a blank node. | |||
* Blank the intermediate nodes along the path from L to the root | ||||
* Blank the intermediate nodes along the path from L to the root. | ||||
* Truncate the tree by removing the right subtree until there is at | * Truncate the tree by removing the right subtree until there is at | |||
least one non-blank leaf node in the right subtree. If the | least one non-blank leaf node in the right subtree. If the | |||
rightmost non-blank leaf has index L, then this will result in the | rightmost non-blank leaf has index L, then this will result in the | |||
tree having 2^d leaves, where d is the smallest value such that | tree having 2^d leaves, where d is the smallest value such that | |||
2^d > L. | 2^d > L. | |||
12.1.4. PreSharedKey | 12.1.4. PreSharedKey | |||
A PreSharedKey proposal can be used to request that a pre-shared key | A PreSharedKey proposal can be used to request that a pre-shared key | |||
skipping to change at page 95, line 46 ¶ | skipping to change at line 3892 ¶ | |||
The psk_nonce MUST be randomly sampled. When processing a Commit | The psk_nonce MUST be randomly sampled. When processing a Commit | |||
message that includes one or more PreSharedKey proposals, group | message that includes one or more PreSharedKey proposals, group | |||
members derive psk_secret as described in Section 8.4, where the | members derive psk_secret as described in Section 8.4, where the | |||
order of the PSKs corresponds to the order of the PreSharedKey | order of the PSKs corresponds to the order of the PreSharedKey | |||
proposals in the Commit. | proposals in the Commit. | |||
12.1.5. ReInit | 12.1.5. ReInit | |||
A ReInit proposal represents a request to reinitialize the group with | A ReInit proposal represents a request to reinitialize the group with | |||
different parameters, for example, to increase the version number or | different parameters, for example, to increase the version number or | |||
to change the ciphersuite. The reinitialization is done by creating | to change the cipher suite. The reinitialization is done by creating | |||
a completely new group and shutting down the old one. | a completely new group and shutting down the old one. | |||
struct { | struct { | |||
opaque group_id<V>; | opaque group_id<V>; | |||
ProtocolVersion version; | ProtocolVersion version; | |||
CipherSuite cipher_suite; | CipherSuite cipher_suite; | |||
Extension extensions<V>; | Extension extensions<V>; | |||
} ReInit; | } ReInit; | |||
A ReInit proposal is invalid if the version field is less than the | A ReInit proposal is invalid if the version field is less than the | |||
skipping to change at page 96, line 45 ¶ | skipping to change at line 3935 ¶ | |||
A GroupContextExtensions proposal is used to update the list of | A GroupContextExtensions proposal is used to update the list of | |||
extensions in the GroupContext for the group. | extensions in the GroupContext for the group. | |||
struct { | struct { | |||
Extension extensions<V>; | Extension extensions<V>; | |||
} GroupContextExtensions; | } GroupContextExtensions; | |||
A GroupContextExtensions proposal is invalid if it includes a | A GroupContextExtensions proposal is invalid if it includes a | |||
required_capabilities extension and some members of the group do not | required_capabilities extension and some members of the group do not | |||
support some of the required capabilities (including those added in | support some of the required capabilities (including those added in | |||
the same commit, and excluding those removed). | the same Commit, and excluding those removed). | |||
A member of the group applies a GroupContextExtensions proposal with | A member of the group applies a GroupContextExtensions proposal with | |||
the following steps: | the following steps: | |||
* Remove all of the existing extensions from the GroupContext object | * Remove all of the existing extensions from the GroupContext object | |||
for the group and replacing them with the list of extensions in | for the group and replace them with the list of extensions in the | |||
the proposal. (This is a wholesale replacement, not a merge. An | proposal. (This is a wholesale replacement, not a merge. An | |||
extension is only carried over if the sender of the proposal | extension is only carried over if the sender of the proposal | |||
includes it in the new list.) | includes it in the new list.) | |||
Note that once the GroupContext is updated, its inclusion in the | Note that once the GroupContext is updated, its inclusion in the | |||
confirmation_tag by way of the key schedule will confirm that all | confirmation_tag by way of the key schedule will confirm that all | |||
members of the group agree on the extensions in use. | members of the group agree on the extensions in use. | |||
12.1.8. External Proposals | 12.1.8. External Proposals | |||
Proposals can be constructed and sent to the group by a party that is | Proposals can be constructed and sent to the group by a party that is | |||
outside the group in two cases. One case, indicated by an external | outside the group in two cases. One case, indicated by the external | |||
SenderType is useful in cases where, for example, an automated | SenderType, allows an entity outside the group to submit proposals to | |||
service might propose to remove a member of a group who has been | the group. For example, an automated service might propose removing | |||
inactive for a long time, or propose adding a newly-hired staff | a member of a group who has been inactive for a long time, or propose | |||
member to a group representing a real-world team. An external sender | adding a newly hired staff member to a group representing a real- | |||
might send a ReInit proposal, to enforce a changed policy regarding | world team. An external sender might send a ReInit proposal to | |||
MLS version or ciphersuite. | enforce a changed policy regarding MLS versions or cipher suites. | |||
The external SenderType requires that signers are pre-provisioned to | The external SenderType requires that signers are pre-provisioned to | |||
the clients within a group and can only be used if the | the clients within a group and can only be used if the | |||
external_senders extension is present in the group's GroupContext. | external_senders extension is present in the group's GroupContext. | |||
The other case, indicated by a new_member_proposal SenderType is | The other case, indicated by the new_member_proposal SenderType, is | |||
useful when existing members of the group can independently authorize | useful when existing members of the group can independently verify | |||
the addition of an MLS client proposing it be added to the group. | that an Add proposal sent by the new joiner itself (not an existing | |||
External proposals which are not authorized are considered invalid. | member) is authorized. External proposals that are not authorized | |||
are considered invalid. | ||||
An external proposal MUST be sent as a PublicMessage object, since | An external proposal MUST be sent as a PublicMessage object, since | |||
the sender will not have the keys necessary to construct a | the sender will not have the keys necessary to construct a | |||
PrivateMessage object. | PrivateMessage object. | |||
Some types of proposal cannot be sent by an external sender. Among | Proposals of some types cannot be sent by an external sender. Among | |||
the proposal types defined in this document, only the following types | the proposal types defined in this document, only the following types | |||
may be sent by an external sender: | may be sent by an external sender: | |||
* add | * add | |||
* remove | * remove | |||
* psk | * psk | |||
* reinit | * reinit | |||
skipping to change at page 98, line 4 ¶ | skipping to change at line 3988 ¶ | |||
* add | * add | |||
* remove | * remove | |||
* psk | * psk | |||
* reinit | * reinit | |||
* group_context_extensions | * group_context_extensions | |||
Messages from external senders containing proposal types other than | Messages from external senders containing proposal types other than | |||
the above MUST be rejected as malformed. New proposal types defined | the above MUST be rejected as malformed. New proposal types defined | |||
in the future MUST define whether they may be sent by external | in the future MUST define whether they may be sent by external | |||
senders. A column is defined in the relevant IANA registry | senders. The "Ext" column in the "MLS Proposal Types" registry | |||
(Section 17.4) to reflect this property. | (Section 17.4) reflects this property. | |||
12.1.8.1. External Senders Extension | 12.1.8.1. External Senders Extension | |||
The external_senders extension is a group context extension that | The external_senders extension is a group context extension that | |||
contains the credentials and signature keys of senders that are | contains the credentials and signature keys of senders that are | |||
permitted to send external proposals to the group. | permitted to send external proposals to the group. | |||
struct { | struct { | |||
SignaturePublicKey signature_key; | SignaturePublicKey signature_key; | |||
Credential credential; | Credential credential; | |||
} ExternalSender; | } ExternalSender; | |||
ExternalSender external_senders<V>; | ExternalSender external_senders<V>; | |||
12.2. Proposal List Validation | 12.2. Proposal List Validation | |||
A group member creating a commit and a group member processing a | A group member creating a Commit and a group member processing a | |||
Commit MUST verify that the list of committed proposals is valid | Commit MUST verify that the list of committed proposals is valid | |||
using one of the following procedures, depending on whether the | using one of the following procedures, depending on whether the | |||
commit is external or not. If the list of proposals is invalid, then | Commit is external or not. If the list of proposals is invalid, then | |||
the Commit message MUST be rejected as invalid. | the Commit message MUST be rejected as invalid. | |||
For a regular, i.e. not external, commit the list is invalid if any | For a regular, i.e., not external, Commit, the list is invalid if any | |||
of the following occurs: | of the following occurs: | |||
* It contains an individual proposal that is invalid as specified in | * It contains an individual proposal that is invalid as specified in | |||
Section 12.1. | Section 12.1. | |||
* It contains an Update proposal generated by the committer. | * It contains an Update proposal generated by the committer. | |||
* It contains a Remove proposal that removes the committer. | * It contains a Remove proposal that removes the committer. | |||
* It contains multiple Update and/or Remove proposals that apply to | * It contains multiple Update and/or Remove proposals that apply to | |||
skipping to change at page 99, line 22 ¶ | skipping to change at line 4052 ¶ | |||
* It contains multiple GroupContextExtensions proposals. | * It contains multiple GroupContextExtensions proposals. | |||
* It contains a ReInit proposal together with any other proposal. | * It contains a ReInit proposal together with any other proposal. | |||
If the committer has received other proposals during the epoch, | If the committer has received other proposals during the epoch, | |||
they SHOULD prefer them over the ReInit proposal, allowing the | they SHOULD prefer them over the ReInit proposal, allowing the | |||
ReInit to be resent and applied in a subsequent epoch. | ReInit to be resent and applied in a subsequent epoch. | |||
* It contains an ExternalInit proposal. | * It contains an ExternalInit proposal. | |||
* It contains a proposal with a non-default proposal type that is | * It contains a Proposal with a non-default proposal type that is | |||
not supported by some members of the group that will process the | not supported by some members of the group that will process the | |||
Commit (i.e., members being added or removed by the Commit do not | Commit (i.e., members being added or removed by the Commit do not | |||
need to support the proposal type). | need to support the proposal type). | |||
* After processing the commit the ratchet tree is invalid, in | * After processing the Commit the ratchet tree is invalid, in | |||
particular, if it contains any leaf node that is invalid according | particular, if it contains any leaf node that is invalid according | |||
to Section 7.3. | to Section 7.3. | |||
An application may extend the above procedure by additional rules, | An application may extend the above procedure by additional rules, | |||
for example, requiring application-level permissions to add members, | for example, requiring application-level permissions to add members, | |||
or rules concerning non-default proposal types. | or rules concerning non-default proposal types. | |||
For an external commit, the list is valid if it contains only the | For an external Commit, the list is valid if it contains only the | |||
following proposals (not necessarily in this order): | following proposals (not necessarily in this order): | |||
* Exactly one ExternalInit | * Exactly one ExternalInit | |||
* At most one Remove proposal, with which the joiner removes an old | * At most one Remove proposal, with which the joiner removes an old | |||
version of themselves. If a Remove proposal is present, then the | version of themselves. If a Remove proposal is present, then the | |||
LeafNode in the path field of the external commit MUST meet the | LeafNode in the path field of the external Commit MUST meet the | |||
same criteria as would the LeafNode in an Update for the removed | same criteria as would the LeafNode in an Update for the removed | |||
leaf (see Section 12.1.2). In particular, the credential in the | leaf (see Section 12.1.2). In particular, the credential in the | |||
LeafNode MUST present a set of identifiers that is acceptable to | LeafNode MUST present a set of identifiers that is acceptable to | |||
the application for the removed participant. | the application for the removed participant. | |||
* Zero or more PreSharedKey proposals. | * Zero or more PreSharedKey proposals | |||
* No other proposals. | * No other proposals | |||
Proposal types defined in the future may make updates to the above | Proposal types defined in the future may make updates to the above | |||
validation logic to incorporate considerations related to proposals | validation logic to incorporate considerations related to proposals | |||
of the new type. | of the new type. | |||
12.3. Applying a Proposal List | 12.3. Applying a Proposal List | |||
The sections above defining each proposal type describe how each | The sections above defining each proposal type describe how each | |||
individual proposal is applied. When creating or processing a | individual proposal is applied. When creating or processing a | |||
Commit, a client applies a list of proposals to the ratchet tree and | Commit, a client applies a list of proposals to the ratchet tree and | |||
GroupContext. The client MUST apply the proposals in the list in the | GroupContext. The client MUST apply the proposals in the list in the | |||
following order: | following order: | |||
* If there is a GroupContextExtensions proposal, replace the | * If there is a GroupContextExtensions proposal, replace the | |||
extensions field of the GroupContext for the group with the | extensions field of the GroupContext for the group with the | |||
contents of the proposal. The new extensions MUST be used for | contents of the proposal. The new extensions MUST be used when | |||
evaluating other proposals in this list. For example, if a | evaluating other proposals in this list. For example, if a | |||
GroupContextExtensions proposal adds a required_capabilities | GroupContextExtensions proposal adds a required_capabilities | |||
extension, then any Add proposals need to indicate support for | extension, then any Add proposals need to indicate support for | |||
those capabilities. | those capabilities. | |||
* Apply any Update proposals to the ratchet tree, in any order. | * Apply any Update proposals to the ratchet tree, in any order. | |||
* Apply any Remove proposals to the ratchet tree, in any order. | * Apply any Remove proposals to the ratchet tree, in any order. | |||
* Apply any Add proposals to the ratchet tree, in the order they | * Apply any Add proposals to the ratchet tree, in the order they | |||
skipping to change at page 101, line 47 ¶ | skipping to change at line 4172 ¶ | |||
proposed during the epoch are actually removed before any application | proposed during the epoch are actually removed before any application | |||
data is transmitted. | data is transmitted. | |||
A sender and a receiver of a Commit MUST verify that the committed | A sender and a receiver of a Commit MUST verify that the committed | |||
list of proposals is valid as specified in Section 12.2. A list is | list of proposals is valid as specified in Section 12.2. A list is | |||
invalid if, for example, it includes an Update and a Remove for the | invalid if, for example, it includes an Update and a Remove for the | |||
same member, or an Add when the sender does not have the application- | same member, or an Add when the sender does not have the application- | |||
level permission to add new users. | level permission to add new users. | |||
The sender of a Commit SHOULD include all proposals that it has | The sender of a Commit SHOULD include all proposals that it has | |||
received during the current epoch, that are valid according to the | received during the current epoch that are valid according to the | |||
rules for their proposal types and according to application policy, | rules for their proposal types and according to application policy, | |||
as long as this results in a valid proposal list. | as long as this results in a valid proposal list. | |||
Due to the asynchronous nature of proposals, receivers of a Commit | Due to the asynchronous nature of proposals, receivers of a Commit | |||
SHOULD NOT enforce that all valid proposals sent within the current | SHOULD NOT enforce that all valid proposals sent within the current | |||
epoch are referenced by the next Commit. In the event that a valid | epoch are referenced by the next Commit. In the event that a valid | |||
proposal is omitted from the next Commit, and that proposal is still | proposal is omitted from the next Commit, and that proposal is still | |||
valid in the current epoch, the sender of the proposal MAY resend it | valid in the current epoch, the sender of the proposal MAY resend it | |||
after updating it to reflect the current epoch. | after updating it to reflect the current epoch. | |||
skipping to change at page 102, line 38 ¶ | skipping to change at line 4209 ¶ | |||
* add | * add | |||
* psk | * psk | |||
* reinit | * reinit | |||
New proposal types MUST state whether they require a path. If any | New proposal types MUST state whether they require a path. If any | |||
instance of a proposal type requires a path, then the proposal type | instance of a proposal type requires a path, then the proposal type | |||
requires a path. This attribute of a proposal type is reflected in | requires a path. This attribute of a proposal type is reflected in | |||
the "Path Required" field of the proposal type registry defined in | the "Path Required" field of the "MLS Proposal Types" registry | |||
Section 17.4. | defined in Section 17.4. | |||
Update and Remove proposals are the clearest examples of proposals | Update and Remove proposals are the clearest examples of proposals | |||
that require a path. An UpdatePath is required to evict the removed | that require a path. An UpdatePath is required to evict the removed | |||
member or the old appearance of the updated member. | member or the old appearance of the updated member. | |||
In pseudocode, the logic for validating the path field of a Commit is | In pseudocode, the logic for validating the path field of a Commit is | |||
as follows: | as follows: | |||
pathRequiredTypes = [ | pathRequiredTypes = [ | |||
update, | update, | |||
skipping to change at page 103, line 29 ¶ | skipping to change at line 4243 ¶ | |||
assert(commit.path != null) | assert(commit.path != null) | |||
To summarize, a Commit can have three different configurations, with | To summarize, a Commit can have three different configurations, with | |||
different uses: | different uses: | |||
1. An "empty" Commit that references no proposals, which updates the | 1. An "empty" Commit that references no proposals, which updates the | |||
committer's contribution to the group and provides PCS with | committer's contribution to the group and provides PCS with | |||
regard to the committer. | regard to the committer. | |||
2. A "partial" Commit that references proposals that do not require | 2. A "partial" Commit that references proposals that do not require | |||
a path, and where the path is empty. Such a commit doesn't | a path, and where the path is empty. Such a Commit doesn't | |||
provide PCS with regard to the committer. | provide PCS with regard to the committer. | |||
3. A "full" Commit that references proposals of any type, which | 3. A "full" Commit that references proposals of any type, which | |||
provides FS with regard to any removed members and PCS for the | provides FS with regard to any removed members and PCS for the | |||
committer and any updated members. | committer and any updated members. | |||
12.4.1. Creating a Commit | 12.4.1. Creating a Commit | |||
When creating or processing a Commit, a client updates the ratchet | When creating or processing a Commit, a client updates the ratchet | |||
tree and GroupContext for the group. These values advance from an | tree and GroupContext for the group. These values advance from an | |||
skipping to change at page 104, line 6 ¶ | skipping to change at line 4267 ¶ | |||
reflects changes due to the proposals and UpdatePath, but with the | reflects changes due to the proposals and UpdatePath, but with the | |||
old confirmed transcript hash. | old confirmed transcript hash. | |||
A member of the group creates a Commit message and the corresponding | A member of the group creates a Commit message and the corresponding | |||
Welcome message at the same time, by taking the following steps: | Welcome message at the same time, by taking the following steps: | |||
* Verify that the list of proposals to be committed is valid as | * Verify that the list of proposals to be committed is valid as | |||
specified in Section 12.2. | specified in Section 12.2. | |||
* Construct an initial Commit object with the proposals field | * Construct an initial Commit object with the proposals field | |||
populated from Proposals received during the current epoch, and an | populated from Proposals received during the current epoch, and | |||
empty path field. | with the path field empty. | |||
* Create the new ratchet tree and GroupContext by applying the list | * Create the new ratchet tree and GroupContext by applying the list | |||
of proposals to the old ratchet tree and GroupContext, as defined | of proposals to the old ratchet tree and GroupContext, as defined | |||
in Section 12.3 | in Section 12.3. | |||
* Decide whether to populate the path field: If the path field is | * Decide whether to populate the path field: If the path field is | |||
required based on the proposals that are in the commit (see | required based on the proposals that are in the Commit (see | |||
above), then it MUST be populated. Otherwise, the sender MAY omit | above), then it MUST be populated. Otherwise, the sender MAY omit | |||
the path field at its discretion. | the path field at its discretion. | |||
* If populating the path field: | * If populating the path field: | |||
- If this is an external commit, assign the sender the leftmost | - If this is an external Commit, assign the sender the leftmost | |||
blank leaf node in the new ratchet tree. If there are no blank | blank leaf node in the new ratchet tree. If there are no blank | |||
leaf nodes in the new ratchet tree, expand the tree to the | leaf nodes in the new ratchet tree, expand the tree to the | |||
right as defined in Section 7.7 and assign the leftmost new | right as defined in Section 7.7 and assign the leftmost new | |||
blank leaf to the sender. | blank leaf to the sender. | |||
- Update the sender's direct path in the ratchet tree as | - Update the sender's direct path in the ratchet tree as | |||
described in Section 7.5. Define commit_secret as the value | described in Section 7.5. Define commit_secret as the value | |||
path_secret[n+1] derived from the last path secret value | path_secret[n+1] derived from the last path secret value | |||
(path_secret[n]) derived for the UpdatePath. | (path_secret[n]) derived for the UpdatePath. | |||
skipping to change at page 105, line 21 ¶ | skipping to change at line 4331 ¶ | |||
of PSKs in the derivation corresponds to the order of PreSharedKey | of PSKs in the derivation corresponds to the order of PreSharedKey | |||
proposals in the proposals vector. | proposals in the proposals vector. | |||
* Construct a FramedContent object containing the Commit object. | * Construct a FramedContent object containing the Commit object. | |||
Sign the FramedContent using the old GroupContext as context. | Sign the FramedContent using the old GroupContext as context. | |||
- Use the FramedContent to update the confirmed transcript hash | - Use the FramedContent to update the confirmed transcript hash | |||
and update the new GroupContext. | and update the new GroupContext. | |||
- Use the init_secret from the previous epoch, the commit_secret | - Use the init_secret from the previous epoch, the commit_secret | |||
and the psk_secret as defined in the previous steps, and the | and psk_secret defined in the previous steps, and the new | |||
new GroupContext to compute the new joiner_secret, | GroupContext to compute the new joiner_secret, welcome_secret, | |||
welcome_secret, epoch_secret, and derived secrets for the new | epoch_secret, and derived secrets for the new epoch. | |||
epoch. | ||||
- Use the confirmation_key for the new epoch to compute the | - Use the confirmation_key for the new epoch to compute the | |||
confirmation_tag value. | confirmation_tag value. | |||
- Calculate the interim transcript hash using the new confirmed | - Calculate the interim transcript hash using the new confirmed | |||
transcript hash and the confirmation_tag from the | transcript hash and the confirmation_tag from the | |||
FramedContentAuthData. | FramedContentAuthData. | |||
* Protect the AuthenticatedContent object using keys from the old | * Protect the AuthenticatedContent object using keys from the old | |||
epoch: | epoch: | |||
- If encoding as PublicMessage, compute the membership_tag value | - If encoding as PublicMessage, compute the membership_tag value | |||
using the membership_key. | using the membership_key. | |||
- If encoding as a PrivateMessage, encrypt the message using the | - If encoding as a PrivateMessage, encrypt the message using the | |||
sender_data_secret and the next (key, nonce) pair from the | sender_data_secret and the next (key, nonce) pair from the | |||
sender's handshake ratchet. | sender's handshake ratchet. | |||
* Construct a GroupInfo reflecting the new state: | * Construct a GroupInfo reflecting the new state: | |||
- Group ID, epoch, tree, confirmed transcript hash, interim | - Set the group_id, epoch, tree, confirmed_transcript_hash, | |||
transcript hash, and group context extensions from the new | interim_transcript_hash, and group_context_extensions fields to | |||
state | reflect the new state. | |||
- The confirmation_tag from the FramedContentAuthData object | - Set the confirmation_tag field to the value of the | |||
corresponding field in the FramedContentAuthData object. | ||||
- Other extensions as defined by the application | - Add any other extensions as defined by the application. | |||
- Optionally derive an external keypair as described in Section 8 | ||||
(required for External Commits, see Section 12.4.3.2) | ||||
- Sign the GroupInfo using the member's private signing key | - Optionally derive an external key pair as described in | |||
Section 8. (required for external Commits, see | ||||
Section 12.4.3.2). | ||||
- Sign the GroupInfo using the member's private signing key. | ||||
- Encrypt the GroupInfo using the key and nonce derived from the | - Encrypt the GroupInfo using the key and nonce derived from the | |||
joiner_secret for the new epoch (see Section 12.4.3.1) | joiner_secret. for the new epoch (see Section 12.4.3.1). | |||
* For each new member in the group: | * For each new member in the group: | |||
- Identify the lowest common ancestor in the tree of the new | - Identify the lowest common ancestor in the tree of the new | |||
member's leaf node and the member sending the Commit | member's leaf node and the member sending the Commit. | |||
- If the path field was populated above: Compute the path secret | - If the path field was populated above: Compute the path secret | |||
corresponding to the common ancestor node | corresponding to the common ancestor node. | |||
- Compute an EncryptedGroupSecrets object that encapsulates the | - Compute an EncryptedGroupSecrets object that encapsulates the | |||
init_secret for the current epoch and the path secret (if | init_secret for the current epoch and the path secret (if | |||
present). | present). | |||
* Construct one or more Welcome messages from the encrypted | * Construct one or more Welcome messages from the encrypted | |||
GroupInfo object, the encrypted key packages, and any PSKs for | GroupInfo object, the encrypted key packages, and any PSKs for | |||
which a proposal was included in the Commit. The order of the | which a proposal was included in the Commit. The order of the | |||
psks MUST be the same as the order of PreSharedKey proposals in | psks MUST be the same as the order of PreSharedKey proposals in | |||
the proposals vector. As discussed on Section 12.4.3.1, the | the proposals vector. As discussed in Section 12.4.3.1, the | |||
committer is free to choose how many Welcome messages to | committer is free to choose how many Welcome messages to | |||
construct. However, the set of Welcome messages produced in this | construct. However, the set of Welcome messages produced in this | |||
step MUST cover every new member added in the Commit. | step MUST cover every new member added in the Commit. | |||
* If a ReInit proposal was part of the Commit, the committer MUST | * If a ReInit proposal was part of the Commit, the committer MUST | |||
create a new group with the parameters specified in the ReInit | create a new group with the parameters specified in the ReInit | |||
proposal, and with the same members as the original group. The | proposal, and with the same members as the original group. The | |||
Welcome message MUST include a PreSharedKeyID with the following | Welcome message MUST include a PreSharedKeyID with the following | |||
parameters: | parameters: | |||
skipping to change at page 107, line 6 ¶ | skipping to change at line 4413 ¶ | |||
- group_id: The group ID for the current group | - group_id: The group ID for the current group | |||
- epoch: The epoch that the group will be in after this Commit | - epoch: The epoch that the group will be in after this Commit | |||
12.4.2. Processing a Commit | 12.4.2. Processing a Commit | |||
A member of the group applies a Commit message by taking the | A member of the group applies a Commit message by taking the | |||
following steps: | following steps: | |||
* Verify that the epoch field of the enclosing FramedContent is | * Verify that the epoch field of the enclosing FramedContent is | |||
equal to the epoch field of the current GroupContext object | equal to the epoch field of the current GroupContext object. | |||
* Unprotect the Commit using the keys from the current epoch: | * Unprotect the Commit using the keys from the current epoch: | |||
- If the message is encoded as PublicMessage, verify the | - If the message is encoded as PublicMessage, verify the | |||
membership MAC using the membership_key | membership MAC using the membership_key. | |||
- If the message is encoded as PrivateMessage, decrypt the | - If the message is encoded as PrivateMessage, decrypt the | |||
message using the sender_data_secret and the (key, nonce) pair | message using the sender_data_secret and the (key, nonce) pair | |||
from the step on the sender's hash ratchet indicated by the | from the step on the sender's hash ratchet indicated by the | |||
generation field. | generation field. | |||
* Verify that the signature on the FramedContent message as | * Verify the signature on the FramedContent message as described in | |||
described in Section 6.1. | Section 6.1. | |||
* Verify that the proposals vector is valid as specified in | * Verify that the proposals vector is valid according to the rules | |||
Section 12.2. | in Section 12.2. | |||
* Verify that all PreSharedKey proposals in the proposals vector are | * Verify that all PreSharedKey proposals in the proposals vector are | |||
available. | available. | |||
* Create the new ratchet tree and GroupContext by applying the list | * Create the new ratchet tree and GroupContext by applying the list | |||
of proposals to the old ratchet tree and GroupContext, as defined | of proposals to the old ratchet tree and GroupContext, as defined | |||
in Section 12.3 | in Section 12.3. | |||
* Verify that the path value is populated if the proposals vector | * Verify that the path value is populated if the proposals vector | |||
contains any Update or Remove proposals, or if it's empty. | contains any Update or Remove proposals, or if it's empty. | |||
Otherwise, the path value MAY be omitted. | Otherwise, the path value MAY be omitted. | |||
* If the path value is populated, validate it and apply it to the | * If the path value is populated, validate it and apply it to the | |||
tree: | tree: | |||
- If this is an external commit, assign the sender the leftmost | - If this is an external Commit, assign the sender the leftmost | |||
blank leaf node in the new ratchet tree. If there are no blank | blank leaf node in the new ratchet tree. If there are no blank | |||
leaf nodes in the new ratchet tree, add a blank leaf to the | leaf nodes in the new ratchet tree, add a blank leaf to the | |||
right side of the new ratchet tree and assign it to the sender. | right side of the new ratchet tree and assign it to the sender. | |||
- Validate the LeafNode as specified in Section 7.3. The | - Validate the LeafNode as specified in Section 7.3. The | |||
leaf_node_source field MUST be set to commit. | leaf_node_source field MUST be set to commit. | |||
- Verify that the encryption_key value in the LeafNode is | - Verify that the encryption_key value in the LeafNode is | |||
different from the committer's current leaf node. | different from the committer's current leaf node. | |||
- Verify that none of the public keys in the UpdatePath appear in | - Verify that none of the public keys in the UpdatePath appear in | |||
any node of the new ratchet tree. | any node of the new ratchet tree. | |||
- Merge the UpdatePath into the new ratchet tree as described in | - Merge the UpdatePath into the new ratchet tree, as described in | |||
Section 7.5. | Section 7.5. | |||
- Construct a provisional GroupContext object containing the | - Construct a provisional GroupContext object containing the | |||
following values: | following values: | |||
o group_id: Same as the old GroupContext | o group_id: Same as the old GroupContext | |||
o epoch: The epoch number for the new epoch | o epoch: The epoch number for the new epoch | |||
o tree_hash: The tree hash of the new ratchet tree | o tree_hash: The tree hash of the new ratchet tree | |||
skipping to change at page 108, line 30 ¶ | skipping to change at line 4484 ¶ | |||
updated by a GroupContextExtensions proposal) | updated by a GroupContextExtensions proposal) | |||
- Decrypt the path secrets for UpdatePath as described in | - Decrypt the path secrets for UpdatePath as described in | |||
Section 7.5, using the provisional GroupContext as the context | Section 7.5, using the provisional GroupContext as the context | |||
for HPKE decryption. | for HPKE decryption. | |||
- Define commit_secret as the value path_secret[n+1] derived from | - Define commit_secret as the value path_secret[n+1] derived from | |||
the last path secret value (path_secret[n]) derived for the | the last path secret value (path_secret[n]) derived for the | |||
UpdatePath. | UpdatePath. | |||
* If the path value is not populated: Define commit_secret as the | * If the path value is not populated, define commit_secret as the | |||
all-zero vector of length KDF.Nh (the same length as a path_secret | all-zero vector of length KDF.Nh (the same length as a path_secret | |||
value would be). | value would be). | |||
* Update the confirmed and interim transcript hashes using the new | * Update the confirmed and interim transcript hashes using the new | |||
Commit, and generate the new GroupContext. | Commit, and generate the new GroupContext. | |||
* Derive the psk_secret as specified in Section 8.4, where the order | * Derive the psk_secret as specified in Section 8.4, where the order | |||
of PSKs in the derivation corresponds to the order of PreSharedKey | of PSKs in the derivation corresponds to the order of PreSharedKey | |||
proposals in the proposals vector. | proposals in the proposals vector. | |||
* Use the init_secret from the previous epoch, the commit_secret and | * Use the init_secret from the previous epoch, the commit_secret and | |||
the psk_secret as defined in the previous steps, and the new | psk_secret defined in the previous steps, and the new GroupContext | |||
GroupContext to compute the new joiner_secret, welcome_secret, | to compute the new joiner_secret, welcome_secret, epoch_secret, | |||
epoch_secret, and derived secrets for the new epoch. | and derived secrets for the new epoch. | |||
* Use the confirmation_key for the new epoch to compute the | * Use the confirmation_key for the new epoch to compute the | |||
confirmation tag for this message, as described below, and verify | confirmation tag for this message, as described below, and verify | |||
that it is the same as the confirmation_tag field in the | that it is the same as the confirmation_tag field in the | |||
FramedContentAuthData object. | FramedContentAuthData object. | |||
* If the above checks are successful, consider the new GroupContext | * If the above checks are successful, consider the new GroupContext | |||
object as the current state of the group. | object as the current state of the group. | |||
* If the Commit included a ReInit proposal, the client MUST NOT use | * If the Commit included a ReInit proposal, the client MUST NOT use | |||
the group to send messages anymore. Instead, it MUST wait for a | the group to send messages anymore. Instead, it MUST wait for a | |||
Welcome message from the committer meeting the requirements of | Welcome message from the committer meeting the requirements of | |||
Section 11.2. | Section 11.2. | |||
Note that clients need to be prepared to receive a valid Commit | Note that clients need to be prepared to receive a valid Commit | |||
message which removes them from the group. In this case, the client | message that removes them from the group. In this case, the client | |||
cannot send any more messages in the group and SHOULD promptly delete | cannot send any more messages in the group and SHOULD promptly delete | |||
its group state and secret tree. (A client might keep the secret | its group state and secret tree. (A client might keep the secret | |||
tree for a short time to decrypt late messages in the previous | tree for a short time to decrypt late messages in the previous | |||
epoch.) | epoch.) | |||
12.4.3. Adding Members to the Group | 12.4.3. Adding Members to the Group | |||
New members can join the group in two ways. Either by being added by | New members can join the group in two ways: by being added by a group | |||
a group member, or by adding themselves through an external Commit. | member or by adding themselves through an external Commit. In both | |||
In both cases, the new members need information to bootstrap their | cases, the new members need information to bootstrap their local | |||
local group state. | group state. | |||
struct { | struct { | |||
GroupContext group_context; | GroupContext group_context; | |||
Extension extensions<V>; | Extension extensions<V>; | |||
MAC confirmation_tag; | MAC confirmation_tag; | |||
uint32 signer; | uint32 signer; | |||
/* SignWithLabel(., "GroupInfoTBS", GroupInfoTBS) */ | /* SignWithLabel(., "GroupInfoTBS", GroupInfoTBS) */ | |||
opaque signature<V>; | opaque signature<V>; | |||
} GroupInfo; | } GroupInfo; | |||
skipping to change at page 109, line 49 ¶ | skipping to change at line 4552 ¶ | |||
GroupInfo may recompute the confirmation tag as MAC(confirmation_key, | GroupInfo may recompute the confirmation tag as MAC(confirmation_key, | |||
confirmed_transcript_hash).) | confirmed_transcript_hash).) | |||
As discussed in Section 13, unknown extensions in | As discussed in Section 13, unknown extensions in | |||
GroupInfo.extensions MUST be ignored, and the creator of a GroupInfo | GroupInfo.extensions MUST be ignored, and the creator of a GroupInfo | |||
object SHOULD include some random GREASE extensions to help ensure | object SHOULD include some random GREASE extensions to help ensure | |||
that other clients correctly ignore unknown extensions. Extensions | that other clients correctly ignore unknown extensions. Extensions | |||
in GroupInfo.group_context.extensions, however, MUST be supported by | in GroupInfo.group_context.extensions, however, MUST be supported by | |||
the new joiner. | the new joiner. | |||
New members MUST verify that group_id is unique among the groups | New members MUST verify that group_id is unique among the groups they | |||
they're currently participating in. | are currently participating in. | |||
New members also MUST verify the signature using the public key taken | New members also MUST verify the signature using the public key taken | |||
from the leaf node of the ratchet tree with leaf index signer. The | from the leaf node of the ratchet tree with leaf index signer. The | |||
signature covers the following structure, comprising all the fields | signature covers the following structure, comprising all the fields | |||
in the GroupInfo above signature: | in the GroupInfo above signature: | |||
struct { | struct { | |||
GroupContext group_context; | GroupContext group_context; | |||
Extension extensions<V>; | Extension extensions<V>; | |||
MAC confirmation_tag; | MAC confirmation_tag; | |||
skipping to change at page 110, line 34 ¶ | skipping to change at line 4584 ¶ | |||
could create one Welcome that is encrypted for all new members, a | could create one Welcome that is encrypted for all new members, a | |||
different Welcome for each new member, or Welcome messages for | different Welcome for each new member, or Welcome messages for | |||
batches of new members (according to some batching scheme that works | batches of new members (according to some batching scheme that works | |||
well for the application). The processes for creating and processing | well for the application). The processes for creating and processing | |||
the Welcome are the same in all cases, aside from the set of new | the Welcome are the same in all cases, aside from the set of new | |||
members for whom a given Welcome is encrypted. | members for whom a given Welcome is encrypted. | |||
The Welcome message provides the new members with the current state | The Welcome message provides the new members with the current state | |||
of the group after the application of the Commit message. The new | of the group after the application of the Commit message. The new | |||
members will not be able to decrypt or verify the Commit message, but | members will not be able to decrypt or verify the Commit message, but | |||
will have the secrets they need to participate in the epoch initiated | they will have the secrets they need to participate in the epoch | |||
by the Commit message. | initiated by the Commit message. | |||
In order to allow the same Welcome message to be sent to multiple new | In order to allow the same Welcome message to be sent to multiple new | |||
members, information describing the group is encrypted with a | members, information describing the group is encrypted with a | |||
symmetric key and nonce derived from the joiner_secret for the new | symmetric key and nonce derived from the joiner_secret for the new | |||
epoch. The joiner_secret is then encrypted to each new member using | epoch. The joiner_secret is then encrypted to each new member using | |||
HPKE. In the same encrypted package, the committer transmits the | HPKE. In the same encrypted package, the committer transmits the | |||
path secret for the lowest (closest to the leaf) node which is | path secret for the lowest (closest to the leaf) node that is | |||
contained in the direct paths of both the committer and the new | contained in the direct paths of both the committer and the new | |||
member. This allows the new member to compute private keys for nodes | member. This allows the new member to compute private keys for nodes | |||
in its direct path that are being reset by the corresponding Commit. | in its direct path that are being reset by the corresponding Commit. | |||
If the sender of the Welcome message wants the receiving member to | If the sender of the Welcome message wants the receiving member to | |||
include a PSK in the derivation of the epoch_secret, they can | include a PSK in the derivation of the epoch_secret, they can | |||
populate the psks field indicating which PSK to use. | populate the psks field indicating which PSK to use. | |||
struct { | struct { | |||
opaque path_secret<V>; | opaque path_secret<V>; | |||
skipping to change at page 111, line 39 ¶ | skipping to change at line 4635 ¶ | |||
otherwise (e.g., provided by a caching service on the Delivery | otherwise (e.g., provided by a caching service on the Delivery | |||
Service), then the client MUST download the tree before processing | Service), then the client MUST download the tree before processing | |||
the Welcome. | the Welcome. | |||
On receiving a Welcome message, a client processes it using the | On receiving a Welcome message, a client processes it using the | |||
following steps: | following steps: | |||
* Identify an entry in the secrets array where the new_member value | * Identify an entry in the secrets array where the new_member value | |||
corresponds to one of this client's KeyPackages, using the hash | corresponds to one of this client's KeyPackages, using the hash | |||
indicated by the cipher_suite field. If no such field exists, or | indicated by the cipher_suite field. If no such field exists, or | |||
if the ciphersuite indicated in the KeyPackage does not match the | if the cipher suite indicated in the KeyPackage does not match the | |||
one in the Welcome message, return an error. | one in the Welcome message, return an error. | |||
* Decrypt the encrypted_group_secrets value with the algorithms | * Decrypt the encrypted_group_secrets value with the algorithms | |||
indicated by the ciphersuite and the private key init_key_priv | indicated by the cipher suite and the private key init_key_priv | |||
corresponding to init_key in the referenced KeyPackage. | corresponding to init_key in the referenced KeyPackage. | |||
encrypted_group_secrets = EncryptWithLabel(init_key, "Welcome", | encrypted_group_secrets = | |||
encrypted_group_info, group_secrets) | EncryptWithLabel(init_key, "Welcome", | |||
encrypted_group_info, group_secrets) | ||||
group_secrets = DecryptWithLabel(init_key_priv, "Welcome", | group_secrets = | |||
encrypted_group_info, kem_output, ciphertext) | DecryptWithLabel(init_key_priv, "Welcome", | |||
encrypted_group_info, kem_output, ciphertext) | ||||
* If a PreSharedKeyID is part of the GroupSecrets and the client is | * If a PreSharedKeyID is part of the GroupSecrets and the client is | |||
not in possession of the corresponding PSK, return an error. | not in possession of the corresponding PSK, return an error. | |||
Additionally, if a PreSharedKeyID has type resumption with usage | Additionally, if a PreSharedKeyID has type resumption with usage | |||
reinit or branch, verify that it is the only such PSK. | reinit or branch, verify that it is the only such PSK. | |||
* From the joiner_secret in the decrypted GroupSecrets object and | * From the joiner_secret in the decrypted GroupSecrets object and | |||
the PSKs specified in the GroupSecrets, derive the welcome_secret | the PSKs specified in the GroupSecrets, derive the welcome_secret | |||
and using that the welcome_key and welcome_nonce. Use the key and | and then the welcome_key and welcome_nonce. Use the key and nonce | |||
nonce to decrypt the encrypted_group_info field. | to decrypt the encrypted_group_info field. | |||
welcome_nonce = ExpandWithLabel(welcome_secret, "nonce", "", AEAD.Nn) | welcome_nonce = ExpandWithLabel(welcome_secret, "nonce", "", AEAD.Nn) | |||
welcome_key = ExpandWithLabel(welcome_secret, "key", "", AEAD.Nk) | welcome_key = ExpandWithLabel(welcome_secret, "key", "", AEAD.Nk) | |||
* Verify the signature on the GroupInfo object. The signature input | * Verify the signature on the GroupInfo object. The signature input | |||
comprises all of the fields in the GroupInfo object except the | comprises all of the fields in the GroupInfo object except the | |||
signature field. The public key is taken from the LeafNode of the | signature field. The public key is taken from the LeafNode of the | |||
ratchet tree with leaf index signer. If the node is blank or if | ratchet tree with leaf index signer. If the node is blank or if | |||
signature verification fails, return an error. | signature verification fails, return an error. | |||
skipping to change at page 112, line 47 ¶ | skipping to change at line 4692 ¶ | |||
- For each non-empty leaf node, validate the LeafNode as | - For each non-empty leaf node, validate the LeafNode as | |||
described in Section 7.3. | described in Section 7.3. | |||
- For each non-empty parent node and each entry in the node's | - For each non-empty parent node and each entry in the node's | |||
unmerged_leaves field: | unmerged_leaves field: | |||
o Verify that the entry represents a non-blank leaf node that | o Verify that the entry represents a non-blank leaf node that | |||
is a descendant of the parent node. | is a descendant of the parent node. | |||
o Verify that every non-blank intermediate node beween the | o Verify that every non-blank intermediate node between the | |||
leaf node and the parent node also has an entry for the leaf | leaf node and the parent node also has an entry for the leaf | |||
node in its unmerged_leaves. | node in its unmerged_leaves. | |||
o Verify that the encryption key in the parent node does not | o Verify that the encryption key in the parent node does not | |||
appear in any other node of the tree. | appear in any other node of the tree. | |||
* Identify a leaf whose LeafNode is identical to the one in the | * Identify a leaf whose LeafNode is identical to the one in the | |||
KeyPackage. If no such field exists, return an error. Let | KeyPackage. If no such field exists, return an error. Let | |||
my_leaf represent this leaf in the tree. | my_leaf represent this leaf in the tree. | |||
* Construct a new group state using the information in the GroupInfo | * Construct a new group state using the information in the GroupInfo | |||
object. | object. | |||
- The GroupContext is the group_context field from the GroupInfo | - Initialize the GroupContext for the group from the | |||
object. | group_context field from the GroupInfo object. | |||
- The new member's position in the tree is at the leaf my_leaf, | ||||
as defined above. | ||||
- Update the leaf my_leaf with the private key corresponding to | - Update the leaf my_leaf with the private key corresponding to | |||
the public key in the node. | the public key in the node, where my_leaf is the new member's | |||
leaf node in the ratchet tree, as defined above. | ||||
- If the path_secret value is set in the GroupSecrets object: | - If the path_secret value is set in the GroupSecrets object: | |||
Identify the lowest common ancestor of the leaf node my_leaf | Identify the lowest common ancestor of the leaf node my_leaf | |||
and of the node of the member with leaf index GroupInfo.signer. | and of the node of the member with leaf index GroupInfo.signer. | |||
Set the private key for this node to the private key derived | Set the private key for this node to the private key derived | |||
from the path_secret. | from the path_secret. | |||
- For each parent of the common ancestor, up to the root of the | - For each parent of the common ancestor, up to the root of the | |||
tree, derive a new path secret and set the private key for the | tree, derive a new path secret, and set the private key for the | |||
node to the private key derived from the path secret. The | node to the private key derived from the path secret. The | |||
private key MUST be the private key that corresponds to the | private key MUST be the private key that corresponds to the | |||
public key in the node. | public key in the node. | |||
* Use the joiner_secret from the GroupSecrets object to generate the | * Use the joiner_secret from the GroupSecrets object to generate the | |||
epoch secret and other derived secrets for the current epoch. | epoch secret and other derived secrets for the current epoch. | |||
* Set the confirmed transcript hash in the new state to the value of | * Set the confirmed transcript hash in the new state to the value of | |||
the confirmed_transcript_hash in the GroupInfo. | the confirmed_transcript_hash in the GroupInfo. | |||
skipping to change at page 114, line 18 ¶ | skipping to change at line 4759 ¶ | |||
- For usage branch, verify that the version and cipher_suite of | - For usage branch, verify that the version and cipher_suite of | |||
the new group match those of the old group, and that the | the new group match those of the old group, and that the | |||
members of the new group compose a subset of the members of the | members of the new group compose a subset of the members of the | |||
old group, according to the application. | old group, according to the application. | |||
12.4.3.2. Joining via External Commits | 12.4.3.2. Joining via External Commits | |||
External Commits are a mechanism for new members (external parties | External Commits are a mechanism for new members (external parties | |||
that want to become members of the group) to add themselves to a | that want to become members of the group) to add themselves to a | |||
group, without requiring that an existing member has to come online | group, without requiring that an existing member has to come online | |||
to issue a Commit that references an Add Proposal. | to issue a Commit that references an Add proposal. | |||
Whether existing members of the group will accept or reject an | Whether existing members of the group will accept or reject an | |||
External Commit follows the same rules that are applied to other | external Commit follows the same rules that are applied to other | |||
handshake messages. | handshake messages. | |||
New members can create and issue an External Commit if they have | New members can create and issue an external Commit if they have | |||
access to the following information for the group's current epoch: | access to the following information for the group's current epoch: | |||
* group ID | * group ID | |||
* epoch ID | * epoch ID | |||
* ciphersuite | * cipher suite | |||
* public tree hash | * public tree hash | |||
* confirmed transcript hash | * confirmed transcript hash | |||
* confirmation tag of the most recent Commit | * confirmation tag of the most recent Commit | |||
* group extensions | * group extensions | |||
* external public key | * external public key | |||
In other words, to join a group via an External Commit, a new member | In other words, to join a group via an external Commit, a new member | |||
needs a GroupInfo with an external_pub extension present in its | needs a GroupInfo with an external_pub extension present in its | |||
extensions field. | extensions field. | |||
struct { | struct { | |||
HPKEPublicKey external_pub; | HPKEPublicKey external_pub; | |||
} ExternalPub; | } ExternalPub; | |||
Thus, a member of the group can enable new clients to join by making | Thus, a member of the group can enable new clients to join by making | |||
a GroupInfo object available to them. Note that because a GroupInfo | a GroupInfo object available to them. Note that because a GroupInfo | |||
object is specific to an epoch, it will need to be updated as the | object is specific to an epoch, it will need to be updated as the | |||
group advances. In particular, each GroupInfo object can be used for | group advances. In particular, each GroupInfo object can be used for | |||
one external join, since that external join will cause the epoch to | one external join, since that external join will cause the epoch to | |||
change. | change. | |||
Note that the tree_hash field is used the same way as in the Welcome | Note that the tree_hash field is used the same way as in the Welcome | |||
message. The full tree can be included via the ratchet_tree | message. The full tree can be included via the ratchet_tree | |||
extension Section 12.4.3.3. | extension (see Section 12.4.3.3). | |||
The information in a GroupInfo is not generally public information, | The information in a GroupInfo is not generally public information, | |||
but applications can choose to make it available to new members in | but applications can choose to make it available to new members in | |||
order to allow External Commits. | order to allow External Commits. | |||
In principle, External Commits work like regular Commits. However, | In principle, external Commits work like regular Commits. However, | |||
their content has to meet a specific set of requirements: | their content has to meet a specific set of requirements: | |||
* External Commits MUST contain a path field (and is therefore a | * External Commits MUST contain a path field (and is therefore a | |||
"full" Commit). The joiner is added at the leftmost free leaf | "full" Commit). The joiner is added at the leftmost free leaf | |||
node (just as if they were added with an Add proposal), and the | node (just as if they were added with an Add proposal), and the | |||
path is calculated relative to that leaf node. | path is calculated relative to that leaf node. | |||
* The Commit MUST NOT include any proposals by reference, since an | * The Commit MUST NOT include any proposals by reference, since an | |||
external joiner cannot determine the validity of proposals sent | external joiner cannot determine the validity of proposals sent | |||
within the group | within the group. | |||
* External Commits MUST be signed by the new member. In particular, | * External Commits MUST be signed by the new member. In particular, | |||
the signature on the enclosing AuthenticatedContent MUST verify | the signature on the enclosing AuthenticatedContent MUST verify | |||
using the public key for the credential in the leaf_node of the | using the public key for the credential in the leaf_node of the | |||
path field. | path field. | |||
* When processing a Commit, both existing and new members MUST use | * When processing a Commit, both existing and new members MUST use | |||
the external init secret as described in Section 8.3. | the external init secret as described in Section 8.3. | |||
* The sender type for the AuthenticatedContent encapsulating the | * The sender type for the AuthenticatedContent encapsulating the | |||
External Commit MUST be new_member_commit. | external Commit MUST be new_member_commit. | |||
External Commits come in two "flavors" -- a "join" commit that adds | External Commits come in two "flavors" -- a "join" Commit that adds | |||
the sender to the group or a "resync" commit that replaces a member's | the sender to the group or a "resync" Commit that replaces a member's | |||
prior appearance with a new one. | prior appearance with a new one. | |||
Note that the "resync" operation allows an attacker that has | Note that the "resync" operation allows an attacker that has | |||
compromised a member's signature private key to introduce themselves | compromised a member's signature private key to introduce themselves | |||
into the group and remove the prior, legitimate member in a single | into the group and remove the prior, legitimate member in a single | |||
Commit. Without resync, this can still be done, but requires two | Commit. Without resync, this can still be done, but it requires two | |||
operations, the external Commit to join and a second Commit to remove | operations: the external Commit to join and a second Commit to remove | |||
the old appearance. Applications for whom this distinction is | the old appearance. Applications for whom this distinction is | |||
salient can choose to disallow external commits that contain a | salient can choose to disallow external commits that contain a | |||
Remove, or to allow such resync commits only if they contain a | Remove, or to allow such resync commits only if they contain a | |||
"reinit" PSK proposal that demonstrates the joining member's presence | "reinit" PSK proposal that demonstrates the joining member's presence | |||
in a prior epoch of the group. With the latter approach, the | in a prior epoch of the group. With the latter approach, the | |||
attacker would need to compromise the PSK as well as the signing key, | attacker would need to compromise the PSK as well as the signing key, | |||
but the application will need to ensure that continuing, non- | but the application will need to ensure that continuing, non- | |||
resynchronizing members have the required PSK. | resynchronizing members have the required PSK. | |||
12.4.3.3. Ratchet Tree Extension | 12.4.3.3. Ratchet Tree Extension | |||
By default, a GroupInfo message only provides the joiner with a hash | By default, a GroupInfo message only provides the joiner with a hash | |||
of the group's ratchet tree. In order to process or generate | of the group's ratchet tree. In order to process or generate | |||
handshake messages, the joiner will need to get a copy of the ratchet | handshake messages, the joiner will need to get a copy of the ratchet | |||
tree from some other source. (For example, the DS might provide a | tree from some other source. (For example, the DS might provide a | |||
cached copy.) The inclusion of the tree hash in the GroupInfo | cached copy.) The inclusion of the tree hash in the GroupInfo | |||
message means that the source of the ratchet tree need not be trusted | message means that the source of the ratchet tree need not be trusted | |||
to maintain the integrity of tree. | to maintain the integrity of the tree. | |||
In cases where the application does not wish to provide such an | In cases where the application does not wish to provide such an | |||
external source, the whole public state of the ratchet tree can be | external source, the whole public state of the ratchet tree can be | |||
provided in an extension of type ratchet_tree, containing a | provided in an extension of type ratchet_tree, containing a | |||
ratchet_tree object of the following form: | ratchet_tree object of the following form: | |||
struct { | struct { | |||
NodeType node_type; | NodeType node_type; | |||
select (Node.node_type) { | select (Node.node_type) { | |||
case leaf: LeafNode leaf_node; | case leaf: LeafNode leaf_node; | |||
skipping to change at page 117, line 4 ¶ | skipping to change at line 4880 ¶ | |||
optional<Node> ratchet_tree<V>; | optional<Node> ratchet_tree<V>; | |||
Each entry in the ratchet_tree vector provides the value for a node | Each entry in the ratchet_tree vector provides the value for a node | |||
in the tree, or the null optional for a blank node. | in the tree, or the null optional for a blank node. | |||
The nodes are listed in the order specified by a left-to-right in- | The nodes are listed in the order specified by a left-to-right in- | |||
order traversal of the ratchet tree. Each node is listed between its | order traversal of the ratchet tree. Each node is listed between its | |||
left subtree and its right subtree. (This is the same ordering as | left subtree and its right subtree. (This is the same ordering as | |||
specified for the array-based trees outlined in Appendix C.) | specified for the array-based trees outlined in Appendix C.) | |||
If the tree has 2^d leaves, then it has 2^(d+1) - 1 nodes. The | If the tree has 2^d leaves, then it has 2^(d+1) - 1 nodes. The | |||
ratchet_tree vector logically has this number of entries, but the | ratchet_tree vector logically has this number of entries, but the | |||
sender MUST NOT include blank nodes after the last non-blank node. | sender MUST NOT include blank nodes after the last non-blank node. | |||
The receiver MUST check that the last node in ratchet_tree is non- | The receiver MUST check that the last node in ratchet_tree is non- | |||
blank, and extend it to the right until it has a length of the form | blank, and then extend the tree to the right until it has a length of | |||
2^(d+1) - 1, adding the minimum number of blank values possible. | the form 2^(d+1) - 1, adding the minimum number of blank values | |||
(Obviously, this may be done "virtually", by synthesizing blank nodes | possible. (Obviously, this may be done "virtually", by synthesizing | |||
when required, as opposed to actually changing the structure in | blank nodes when required, as opposed to actually changing the | |||
memory.) | structure in memory.) | |||
The leaves of the tree are stored in even-numbered entries in the | The leaves of the tree are stored in even-numbered entries in the | |||
array (the leaf with index L in array position 2*L). The root node | array (the leaf with index L in array position 2*L). The root node | |||
of the tree is at position 2^d - 1 of the array. Intermediate parent | of the tree is at position 2^d - 1 of the array. Intermediate parent | |||
nodes can be identified by performing the same calculation to the | nodes can be identified by performing the same calculation to the | |||
subarrays to the left and right of the root, following something like | subarrays to the left and right of the root, following something like | |||
the following algorithm: | the following algorithm: | |||
# Assuming a class Node that has left and right members | # Assuming a class Node that has left and right members | |||
def subtree_root(nodes): | def subtree_root(nodes): | |||
# If there is only one node in the array return it | # If there is only one node in the array, return it | |||
if len(nodes) == 1: | if len(nodes) == 1: | |||
return Node(nodes[0]) | return Node(nodes[0]) | |||
# Otherwise, the length of the array MUST be odd | # Otherwise, the length of the array MUST be odd | |||
if len(nodes) % 2 == 0: | if len(nodes) % 2 == 0: | |||
raise Exception("Malformed node array {}", len(nodes)) | raise Exception("Malformed node array {}", len(nodes)) | |||
# Identify the root of the subtree | # Identify the root of the subtree | |||
d = 0 | d = 0 | |||
while (2**(d+1)) < len(nodes): | while (2**(d+1)) < len(nodes): | |||
skipping to change at page 118, line 23 ¶ | skipping to change at line 4946 ¶ | |||
W _ Z _ | W _ Z _ | |||
/ \ / \ / \ / \ | / \ / \ / \ / \ | |||
A B C D E F _ _ | A B C D E F _ _ | |||
1 | 1 | |||
0 1 2 3 4 5 6 7 8 9 0 | 0 1 2 3 4 5 6 7 8 9 0 | |||
<-----------> R <-----------> | <-----------> R <-----------> | |||
<---> R <---> <---> R <---> | <---> R <---> <---> R <---> | |||
- R - - R - - R - - R - | - R - - R - - R - - R - | |||
Figure 28: Left-to-right in-order traversal of a six-member tree | Figure 28: Left-to-Right In-Order Traversal of a Six-Member Tree | |||
The presence of a ratchet_tree extension in a GroupInfo message does | The presence of a ratchet_tree extension in a GroupInfo message does | |||
not result in any changes to the GroupContext extensions for the | not result in any changes to the GroupContext extensions for the | |||
group. The ratchet tree provided is simply stored by the client and | group. The ratchet tree provided is simply stored by the client and | |||
used for MLS operations. | used for MLS operations. | |||
If this extension is not provided in a Welcome message, then the | If this extension is not provided in a Welcome message, then the | |||
client will need to fetch the ratchet tree over some other channel | client will need to fetch the ratchet tree over some other channel | |||
before it can generate or process Commit messages. Applications | before it can generate or process Commit messages. Applications | |||
should ensure that this out-of-band channel is provided with security | should ensure that this out-of-band channel is provided with security | |||
skipping to change at page 118, line 45 ¶ | skipping to change at line 4968 ¶ | |||
Proposal and Commit messages. For example, an application that | Proposal and Commit messages. For example, an application that | |||
encrypts Proposal and Commit messages might distribute ratchet trees | encrypts Proposal and Commit messages might distribute ratchet trees | |||
encrypted using a key exchanged over the MLS channel. | encrypted using a key exchanged over the MLS channel. | |||
Regardless of how the client obtains the tree, the client MUST verify | Regardless of how the client obtains the tree, the client MUST verify | |||
that the root hash of the ratchet tree matches the tree_hash of the | that the root hash of the ratchet tree matches the tree_hash of the | |||
GroupContext before using the tree for MLS operations. | GroupContext before using the tree for MLS operations. | |||
13. Extensibility | 13. Extensibility | |||
The base MLS protocol can be extended in a few ways. New | The base MLS protocol can be extended in a few ways. New cipher | |||
ciphersuites can be added to enable the use of new cryptographic | suites can be added to enable the use of new cryptographic | |||
algorithms. New types of proposals can be used to perform new | algorithms. New types of proposals can be used to perform new | |||
actions within an epoch. Extension fields can be used to add | actions within an epoch. Extension fields can be used to add | |||
additional information to the protocol. In this section, we discuss | additional information to the protocol. In this section, we discuss | |||
some constraints on these extensibility mechanisms that are necessary | some constraints on these extensibility mechanisms that are necessary | |||
to ensure broad interoperability. | to ensure broad interoperability. | |||
13.1. Additional Ciphersuites | 13.1. Additional Cipher Suites | |||
As discussed in Section 5.1, MLS allows the participants in a group | As discussed in Section 5.1, MLS allows the participants in a group | |||
to negotiate the cryptographic algorithms used within the group. | to negotiate the cryptographic algorithms used within the group. | |||
This extensibility is important for maintaining the security of the | This extensibility is important for maintaining the security of the | |||
protocol over time [RFC7696]. It also creates a risk of | protocol over time [RFC7696]. It also creates a risk of | |||
interoperability failure due to clients not supporting a common | interoperability failure due to clients not supporting a common | |||
ciphersuite. | cipher suite. | |||
The ciphersuite registry defined in Section 17.1 attempts to strike a | The cipher suite registry defined in Section 17.1 attempts to strike | |||
balance on this point. On the one hand, the base policy for the | a balance on this point. On the one hand, the base policy for the | |||
registry is Specification Required, a fairly low bar designed to | registry is Specification Required, a fairly low bar designed to | |||
avoid the need for standards work in cases where different ciphers | avoid the need for standards work in cases where different ciphers | |||
are needed for niche applications. There is a higher bar (Standards | are needed for niche applications. On the other hand, there is a | |||
Action) for ciphers to set the Recommended field in the registry. | higher bar (Standards Action) for ciphers to set the Recommended | |||
This higher bar is there in part to ensure that the interoperability | field in the registry. This higher bar is there in part to ensure | |||
implications of new ciphersuites are considered. | that the interoperability implications of new cipher suites are | |||
considered. | ||||
MLS ciphersuites are defined independent of MLS versions, so that in | MLS cipher suites are defined independent of MLS versions, so that in | |||
principle the same ciphersuite can be used across versions. | principle, the same cipher suite can be used across versions. | |||
Standards work defining new versions of MLS should consider whether | Standards work defining new versions of MLS should consider whether | |||
it is desirable for the new version to be compatible with existing | it is desirable for the new version to be compatible with existing | |||
ciphersuites, or whether the new version should rule out some | cipher suites, or whether the new version should rule out some cipher | |||
ciphersuites. For example, a new version could follow the example of | suites. For example, a new version could follow the example of | |||
HTTP/2, which restricted the set of allowed TLS ciphers (see | HTTP/2, which restricted the set of allowed TLS ciphers (see | |||
Section 9.2.2 of [RFC9113]. | Section 9.2.2 of [RFC9113]). | |||
13.2. Proposals | 13.2. Proposals | |||
Commit messages do not have an extension field because the set of | Commit messages do not have an extension field because the set of | |||
proposals is extensible. As discussed in Section 12.4, Proposals | proposals is extensible. As discussed in Section 12.4, Proposals | |||
with a non-default proposal type MUST NOT be included in a commit | with a non-default proposal type MUST NOT be included in a commit | |||
unless the proposal type is supported by all the members of the group | unless the proposal type is supported by all the members of the group | |||
that will process the Commit. | that will process the Commit. | |||
13.3. Credential Extensibility | 13.3. Credential Extensibility | |||
In order to ensure that MLS provides meaningful authentication it is | In order to ensure that MLS provides meaningful authentication, it is | |||
important that each member is able to authenticate some identity | important that each member is able to authenticate some identity | |||
information for each other member. Identity information is encoded | information for each other member. Identity information is encoded | |||
in Credentials, so this property is provided by ensuring that members | in Credentials, so this property is provided by ensuring that members | |||
use compatible credential types. | use compatible credential types. | |||
The types of credential that may be used in a group is restricted to | The only types of credential that may be used in a group are those | |||
what all members of the group support, as specified by the | that all members of the group support, as specified by the | |||
capabilities field of each LeafNode in the ratchet tree. An | capabilities field of each LeafNode in the ratchet tree. An | |||
application can introduce new credential types by choosing an | application can introduce new credential types by choosing an | |||
unallocated identifier from the registry in Section 17.5 and | unallocated identifier from the registry in Section 17.5 and | |||
indicating support for the credential type in published LeafNodes, | indicating support for the credential type in published LeafNodes, | |||
whether in Update proposals to existing groups or KeyPackages that | whether in Update proposals to existing groups or KeyPackages that | |||
are added to new groups. Once all members in a group indicate | are added to new groups. Once all members in a group indicate | |||
support for the credential type, members can start using LeafNodes | support for the credential type, members can start using LeafNodes | |||
with the new credential. Application may enforce that certain | with the new credential. Application may enforce that certain | |||
credential types always remain supported by adding a | credential types always remain supported by adding a | |||
required_capabilities extension to the group's GroupContext, which | required_capabilities extension to the group's GroupContext, which | |||
skipping to change at page 121, line 24 ¶ | skipping to change at line 5085 ¶ | |||
This extension mechanism is designed to allow for the secure and | This extension mechanism is designed to allow for the secure and | |||
forward-compatible negotiation of extensions. For this to work, | forward-compatible negotiation of extensions. For this to work, | |||
implementations MUST correctly handle extensible fields: | implementations MUST correctly handle extensible fields: | |||
* A client that posts a KeyPackage MUST support all parameters | * A client that posts a KeyPackage MUST support all parameters | |||
advertised in it. Otherwise, another client might fail to | advertised in it. Otherwise, another client might fail to | |||
interoperate by selecting one of those parameters. | interoperate by selecting one of those parameters. | |||
* A client processing a KeyPackage object MUST ignore all | * A client processing a KeyPackage object MUST ignore all | |||
unrecognized values in the capabilities field of the LeafNode, and | unrecognized values in the capabilities field of the LeafNode and | |||
all unknown extensions in the extensions and leaf_node.extensions | all unknown extensions in the extensions and leaf_node.extensions | |||
fields. Otherwise, it could fail to interoperate with newer | fields. Otherwise, it could fail to interoperate with newer | |||
clients. | clients. | |||
* A client processing a GroupInfo object MUST ignore all | * A client processing a GroupInfo object MUST ignore all | |||
unrecognized extensions in the extensions field. | unrecognized extensions in the extensions field. | |||
* Any field containing a list of extensions MUST NOT have more than | * Any field containing a list of extensions MUST NOT have more than | |||
one extension of any given type. | one extension of any given type. | |||
skipping to change at page 122, line 9 ¶ | skipping to change at line 5118 ¶ | |||
the group MUST be supported by all members of the group. | the group MUST be supported by all members of the group. | |||
The parameters of a group may be changed by sending a | The parameters of a group may be changed by sending a | |||
GroupContextExtensions proposal to enable additional extensions | GroupContextExtensions proposal to enable additional extensions | |||
(Section 12.1.7), or by reinitializing the group (Section 11.2). | (Section 12.1.7), or by reinitializing the group (Section 11.2). | |||
13.5. GREASE | 13.5. GREASE | |||
As described in Section 13.4, clients are required to ignore unknown | As described in Section 13.4, clients are required to ignore unknown | |||
values for certain parameters. To help ensure that other clients | values for certain parameters. To help ensure that other clients | |||
implement this behavior, a client can follow the “Generate Random | implement this behavior, a client can follow the "Generate Random | |||
Extensions And Sustain Extensibility” or GREASE approach described in | Extensions And Sustain Extensibility" or GREASE approach described in | |||
[RFC8701]. In the context of MLS, this means that a client | [RFC8701]. In the context of MLS, this means that a client | |||
generating a KeyPackage, LeafNode, or GroupInfo object includes | generating a KeyPackage, LeafNode, or GroupInfo object includes | |||
random values in certain fields which would be ignored by a | random values in certain fields which would be ignored by a correctly | |||
correctly-implemented client processing the message. A client that | implemented client processing the message. A client that incorrectly | |||
incorrectly rejects unknown code points will fail to process such a | rejects unknown code points will fail to process such a message, | |||
message, providing a signal to its implementer that the client needs | providing a signal to its implementer that the client needs to be | |||
to be fixed. | fixed. | |||
When generating the following fields, an MLS client SHOULD include a | When generating the following fields, an MLS client SHOULD include a | |||
random selection of values chosen from these GREASE values: | random selection of values chosen from these GREASE values: | |||
* LeafNode.capabilities.ciphersuites | * LeafNode.capabilities.cipher_suites | |||
* LeafNode.capabilities.extensions | * LeafNode.capabilities.extensions | |||
* LeafNode.capabilities.proposals | * LeafNode.capabilities.proposals | |||
* LeafNode.capabilities.credentials | * LeafNode.capabilities.credentials | |||
* LeafNode.extensions | * LeafNode.extensions | |||
* KeyPackage.extensions | * KeyPackage.extensions | |||
* GroupInfo.extensions | * GroupInfo.extensions | |||
For the KeyPackage and GroupInfo extensions, the extension_data for | For the KeyPackage and GroupInfo extensions, the extension_data for | |||
GREASE extensions MAY have any contents selected by the sender, since | GREASE extensions MAY have any contents selected by the sender, since | |||
they will be ignored by a correctly-implemented receiver. For | they will be ignored by a correctly implemented receiver. For | |||
example, a sender might populate these extensions with a randomly- | example, a sender might populate these extensions with a randomly | |||
sized amount of random data. | sized amount of random data. | |||
Note that any GREASE values added to LeafNode.extensions need to be | ||||
reflected in LeafNode.capabilities.extensions, since the LeafNode | ||||
validation process described in Section 7.3 requires that these two | ||||
fields be consistent. | ||||
GREASE values MUST NOT be sent in the following fields, because an | GREASE values MUST NOT be sent in the following fields, because an | |||
unsupported value in one these fields (including a GREASE value), | unsupported value in one these fields (including a GREASE value) will | |||
will cause the enclosing message to be rejected: | cause the enclosing message to be rejected: | |||
* Proposal.proposal_type | * Proposal.proposal_type | |||
* Credential.credential_type | * Credential.credential_type | |||
* GroupContext.extensions | * GroupContext.extensions | |||
* GroupContextExtensions.extensions | * GroupContextExtensions.extensions | |||
A set of values reserved for GREASE have been registered in the | ||||
various registries in Section 17. This prevents conflict between | Values reserved for GREASE have been registered in the various | |||
GREASE and real future values. The following values are reserved in | registries in Section 17. This prevents conflict between GREASE and | |||
each registry: 0x0A0A, 0x1A1A, 0x2A2A, 0x3A3A, 0x4A4A, 0x5A5A, | real future values. The following values are reserved in each | |||
0x6A6A, 0x7A7A, 0x8A8A, 0x9A9A, 0xAAAA, 0xBABA, 0xCACA, 0xDADA, and | registry: 0x0A0A, 0x1A1A, 0x2A2A, 0x3A3A, 0x4A4A, 0x5A5A, 0x6A6A, | |||
0xEAEA. (The value 0xFAFA falls within the private use range.) | 0x7A7A, 0x8A8A, 0x9A9A, 0xAAAA, 0xBABA, 0xCACA, 0xDADA, and 0xEAEA. | |||
These values MUST only appear in the fields listed above, and not, | (The value 0xFAFA falls within the private use range.) These values | |||
for example, in the proposal_type field of a Proposal. Clients MUST | MUST only appear in the fields listed above, and not, for example, in | |||
NOT implement any special processing rules for how to handle these | the proposal_type field of a Proposal. Clients MUST NOT implement | |||
values when receiving them, since this negates their utility for | any special processing rules for how to handle these values when | |||
detecting extensibility failures. | receiving them, since this negates their utility for detecting | |||
extensibility failures. | ||||
GREASE values MUST be handled using normal logic for processing | GREASE values MUST be handled using normal logic for processing | |||
unsupported values. When comparing lists of capabilities to identify | unsupported values. When comparing lists of capabilities to identify | |||
mutually-supported capabilities, clients MUST represent their own | mutually supported capabilities, clients MUST represent their own | |||
capabilities with a list containing only the capabilities actually | capabilities with a list containing only the capabilities actually | |||
supported, without any GREASE values. In other words, lists | supported, without any GREASE values. In other words, lists | |||
including GREASE values are only sent to other clients; | including GREASE values are only sent to other clients; | |||
representations of a client's own capabilities MUST NOT contain | representations of a client's own capabilities MUST NOT contain | |||
GREASE values. | GREASE values. | |||
14. Sequencing of State Changes | 14. Sequencing of State Changes | |||
Each Commit message is premised on a given starting state, indicated | Each Commit message is premised on a given starting state, indicated | |||
by the epoch field of the enclosing FramedContent. If the changes | by the epoch field of the enclosing FramedContent. If the changes | |||
skipping to change at page 124, line 20 ¶ | skipping to change at line 5226 ¶ | |||
been accepted. | been accepted. | |||
Regardless of how messages are kept in sequence, there is a risk that | Regardless of how messages are kept in sequence, there is a risk that | |||
in a sufficiently busy group, a given member may never be able to | in a sufficiently busy group, a given member may never be able to | |||
send a Commit message because they always lose to other members. The | send a Commit message because they always lose to other members. The | |||
degree to which this is a practical problem will depend on the | degree to which this is a practical problem will depend on the | |||
dynamics of the application. | dynamics of the application. | |||
15. Application Messages | 15. Application Messages | |||
The primary purpose of handshake messages are to provide an | The primary purpose of handshake messages is to provide an | |||
authenticated group key exchange to clients. In order to protect | authenticated group key exchange to clients. In order to protect | |||
application messages sent among the members of a group, the | application messages sent among the members of a group, the | |||
encryption_secret provided by the key schedule is used to derive a | encryption_secret provided by the key schedule is used to derive a | |||
sequence of nonces and keys for message encryption. Every epoch | sequence of nonces and keys for message encryption. Every epoch | |||
moves the key schedule forward which triggers the creation of a new | moves the key schedule forward, which triggers the creation of a new | |||
secret tree, as described in Section 9, along with a new set of | secret tree, as described in Section 9, along with a new set of | |||
symmetric ratchets of nonces and keys for each member. | symmetric ratchets of nonces and keys for each member. | |||
Each client maintains their own local copy of the key schedule for | Each client maintains their own local copy of the key schedule for | |||
each epoch during which they are a group member. They derive new | each epoch during which they are a group member. They derive new | |||
keys, nonces, and secrets as needed while deleting old ones as soon | keys, nonces, and secrets as needed while deleting old ones as soon | |||
as they have been used. | as they have been used. | |||
The group identifier and epoch allow a recipient to know which group | The group identifier and epoch allow a recipient to know which group | |||
secrets should be used and from which epoch_secret to start computing | secrets should be used and from which epoch_secret to start computing | |||
other secrets. The sender identifier and content type is used to | other secrets. The sender identifier and content type are used to | |||
identify which symmetric ratchet to use from the secret tree. The | identify which symmetric ratchet to use from the secret tree. The | |||
generation counter determines how far into the ratchet to iterate in | generation counter determines how far into the ratchet to iterate in | |||
order to produce the required nonce and key for encryption or | order to produce the required nonce and key for encryption or | |||
decryption. | decryption. | |||
15.1. Padding | 15.1. Padding | |||
Application messages MAY be padded to provide some resistance against | Application messages MAY be padded to provide some resistance against | |||
traffic analysis techniques over encrypted traffic [CLINIC] [HCJ16]. | traffic analysis techniques over encrypted traffic [CLINIC] [HCJ16]. | |||
While MLS might deliver the same payload less frequently across a lot | While MLS might deliver the same payload less frequently across a lot | |||
skipping to change at page 125, line 16 ¶ | skipping to change at line 5269 ¶ | |||
chosen by the sender at the time of message encryption. Senders may | chosen by the sender at the time of message encryption. Senders may | |||
use padding to reduce the ability of attackers outside the group to | use padding to reduce the ability of attackers outside the group to | |||
infer the size of the encrypted content. Note, however, that the | infer the size of the encrypted content. Note, however, that the | |||
transports used to carry MLS messages may have maximum message sizes, | transports used to carry MLS messages may have maximum message sizes, | |||
so padding schemes SHOULD avoid increasing message size beyond any | so padding schemes SHOULD avoid increasing message size beyond any | |||
such limits that exist in a given deployment scenario. | such limits that exist in a given deployment scenario. | |||
15.2. Restrictions | 15.2. Restrictions | |||
During each epoch, senders MUST NOT encrypt more data than permitted | During each epoch, senders MUST NOT encrypt more data than permitted | |||
by the security bounds of the AEAD scheme used | by the security bounds of the AEAD scheme used [CFRG-AEAD-LIMITS]. | |||
[I-D.irtf-cfrg-aead-limits]. | ||||
Note that each change to the group through a handshake message will | Note that each change to the group through a handshake message will | |||
also set a new encryption_secret. Hence this change MUST be applied | also set a new encryption_secret. Hence this change MUST be applied | |||
before encrypting any new application message. This is required both | before encrypting any new application message. This is required both | |||
to ensure that any users removed from the group can no longer receive | to ensure that any users removed from the group can no longer receive | |||
messages and to (potentially) recover confidentiality and | messages and to (potentially) recover confidentiality and | |||
authenticity for future messages despite a past state compromise. | authenticity for future messages despite a past state compromise. | |||
15.3. Delayed and Reordered Application messages | 15.3. Delayed and Reordered Application Messages | |||
Since each application message contains the group identifier, the | Since each application message contains the group identifier, the | |||
epoch, and a generation counter, a client can receive messages out of | epoch, and a generation counter, a client can receive messages out of | |||
order. When messages are received out of order, the client moves the | order. When messages are received out of order, the client moves the | |||
sender ratchet forward to match the received generation counter. Any | sender ratchet forward to match the received generation counter. Any | |||
unused nonce and key pairs from the ratchet are potentially stored so | unused nonce and key pairs from the ratchet are potentially stored so | |||
that they can be used to decrypt the messages which were delayed or | that they can be used to decrypt the messages that were delayed or | |||
reordered. | reordered. | |||
Applications SHOULD define a policy on how long to keep unused nonce | Applications SHOULD define a policy on how long to keep unused nonce | |||
and key pairs for a sender, and the maximum number to keep. This is | and key pairs for a sender, and the maximum number to keep. This is | |||
in addition to ensuring that these secrets are deleted according to | in addition to ensuring that these secrets are deleted according to | |||
the deletion schedule defined in Section 9.2. Applications SHOULD | the deletion schedule defined in Section 9.2. Applications SHOULD | |||
also define a policy limiting the maximum number of steps that | also define a policy limiting the maximum number of steps that | |||
clients will move the ratchet forward in response to a new message. | clients will move the ratchet forward in response to a new message. | |||
Messages received with a generation counter that's too much higher | Messages received with a generation counter that is too much higher | |||
than the last message received would then be rejected. This avoids | than the last message received would then be rejected. This avoids | |||
causing a denial-of-service attack by requiring the recipient to | causing a denial-of-service attack by requiring the recipient to | |||
perform an excessive number of key derivations. For example, a | perform an excessive number of key derivations. For example, a | |||
malicious group member could send a message with generation = | malicious group member could send a message with generation = | |||
0xffffffff at the beginning of a new epoch, forcing recipients to | 0xffffffff at the beginning of a new epoch, forcing recipients to | |||
perform billions of key derivations unless they apply limits of the | perform billions of key derivations unless they apply limits of the | |||
type discussed above. | type discussed above. | |||
16. Security Considerations | 16. Security Considerations | |||
The security goals of MLS are described in | The security goals of MLS are described in [MLS-ARCH]. We describe | |||
[I-D.ietf-mls-architecture]. We describe here how the protocol | here how the protocol achieves its goals at a high level, though a | |||
achieves its goals at a high level, though a complete security | complete security analysis is outside of the scope of this document. | |||
analysis is outside of the scope of this document. The Security | The Security Considerations section of [MLS-ARCH] provides some | |||
Considerations section of [I-D.ietf-mls-architecture] provides some | ||||
citations to detailed security analyses. | citations to detailed security analyses. | |||
16.1. Transport Security | 16.1. Transport Security | |||
Because MLS messages are protected at the message level, the | Because MLS messages are protected at the message level, the | |||
confidentiality and integrity of the group state do not depend on | confidentiality and integrity of the group state do not depend on | |||
those messages being protected in transit. However, an attacker who | those messages being protected in transit. However, an attacker who | |||
can observe those messages in transit will be able to learn about the | can observe those messages in transit will be able to learn about the | |||
group state, including potentially the group membership (see | group state, including potentially the group membership (see | |||
Section 16.4.3 below). Such an attacker might also be able to mount | Section 16.4.3 below). Such an attacker might also be able to mount | |||
denial-of-service attacks on the group or exclude new members by | denial-of-service attacks on the group or exclude new members by | |||
selectively removing messages in transit. In order to prevent this | selectively removing messages in transit. In order to prevent this | |||
form of attack, it is RECOMMENDED that all MLS messages be carried | form of attack, it is RECOMMENDED that all MLS messages be carried | |||
over a secure transport such as TLS [RFC8446] or QUIC [RFC9000]. | over a secure transport such as TLS [RFC8446] or QUIC [RFC9000]. | |||
16.2. Confidentiality of the Group Secrets | 16.2. Confidentiality of Group Secrets | |||
Group secrets are partly derived from the output of a ratchet tree. | Group secrets are partly derived from the output of a ratchet tree. | |||
Ratchet trees work by assigning each member of the group to a leaf in | Ratchet trees work by assigning each member of the group to a leaf in | |||
the tree and maintaining the following property: the private key of a | the tree and maintaining the following property: the private key of a | |||
node in the tree is known only to members of the group that are | node in the tree is known only to members of the group that are | |||
assigned a leaf in the node's subtree. This is called the _ratchet | assigned a leaf in the node's subtree. This is called the _tree | |||
tree invariant_ and it makes it possible to encrypt to all group | invariant_, and it makes it possible to encrypt to all group members | |||
members except one, with a number of ciphertexts that is logarithmic | except one, with a number of ciphertexts that is logarithmic in the | |||
in the number of group members. | number of group members. | |||
The ability to efficiently encrypt to all members except one allows | The ability to efficiently encrypt to all members except one allows | |||
members to be securely removed from a group. It also allows a member | members to be securely removed from a group. It also allows a member | |||
to rotate their keypair such that the old private key can no longer | to rotate their key pair such that the old private key can no longer | |||
be used to decrypt new messages. | be used to decrypt new messages. | |||
16.3. Confidentiality of Sender Data | 16.3. Confidentiality of Sender Data | |||
The PrivateMessage framing encrypts "sender data" that identifies | The PrivateMessage framing encrypts "sender data" that identifies | |||
which group member sent an encrypted message, as described in | which group member sent an encrypted message, as described in | |||
Section 6.3.2. As with the QUIC header protection scheme [RFC9001], | Section 6.3.2. As with the QUIC header protection scheme [RFC9001], | |||
Section 5.4, this scheme is a variant of the HN1 construction | Section 5.4, this scheme is a variant of the HN1 construction | |||
analyzed in [NAN]. A sample of the ciphertext is combined with a | analyzed in [NAN]. A sample of the ciphertext is combined with a | |||
sender_data_secret to derive a key and nonce that are used for AEAD | sender_data_secret to derive a key and nonce that are used for AEAD | |||
encryption of the sender data. | encryption of the sender data. | |||
pseudocode (key, nonce) = PRF(sender_data_secret, sample) | (key, nonce) = PRF(sender_data_secret, sample) | |||
encrypted_sender_data = AEAD.Seal(key, nonce, sender_data_aad, | encrypted_sender_data = | |||
sender_data) | AEAD.Seal(key, nonce, sender_data_aad, sender_data) | |||
The only differences between this construction and HN1 as described | The only differences between this construction and HN1 as described | |||
in [NAN] are (1) that it uses authenticated encryption instead of | in [NAN] are that it (1) uses authenticated encryption instead of | |||
unauthenticated encryption and (2) that it protects information used | unauthenticated encryption and (2) protects information used to | |||
to derive a nonce instead of the nonce itself. | derive a nonce instead of the nonce itself. | |||
Since the sender_data_secret is distinct from the content encryption | Since the sender_data_secret is distinct from the content encryption | |||
key, it follows that the sender data encryption scheme achieves AE2 | key, it follows that the sender data encryption scheme achieves AE2 | |||
security as defined in [NAN], and therefore guarantees the | security as defined in [NAN], and therefore guarantees the | |||
confidentiality of the sender data. | confidentiality of the sender data. | |||
Use of the same sender_data_secret and ciphertext sample more than | Use of the same sender_data_secret and ciphertext sample more than | |||
once risks compromising sender data protection by reusing an AEAD | once risks compromising sender data protection by reusing an AEAD | |||
(key, nonce) pair. For example, in many AEAD schemes, reusing a key | (key, nonce) pair. For example, in many AEAD schemes, reusing a key | |||
and nonce reveals the exclusive OR of the two plaintexts. Assuming | and nonce reveals the exclusive OR of the two plaintexts. Assuming | |||
the ciphertext output of the AEAD algorithm is indistinguishable from | the ciphertext output of the AEAD algorithm is indistinguishable from | |||
random data (i.e., the AEAD is AE1-secure in the phrasing of [NAN]), | random data (i.e., the AEAD is AE1-secure in the phrasing of [NAN]), | |||
the odds of two ciphertext samples being identical is roughly | the odds of two ciphertext samples being identical is roughly | |||
2^(-L/2), i.e., the birthday bound. | 2^(-L/2), i.e., the birthday bound. | |||
The AEAD algorithms for ciphersuites defined in this document all | The AEAD algorithms for cipher suites defined in this document all | |||
provide this property. The size of the sample depends on the | provide this property. The size of the sample depends on the cipher | |||
ciphersuite's hash function, but in all cases, the probability of | suite's hash function, but in all cases, the probability of collision | |||
collision is no more than 2^-128. Any future ciphersuite MUST use an | is no more than 2^-128. Any future cipher suite MUST use an | |||
AE1-secure AEAD algorithm. | AE1-secure AEAD algorithm. | |||
16.4. Confidentiality of Group Metadata | 16.4. Confidentiality of Group Metadata | |||
MLS does not provide confidentiality protection to some messages and | MLS does not provide confidentiality protection to some messages and | |||
fields within messages: | fields within messages: | |||
* KeyPackage messages | * KeyPackage messages | |||
* GroupInfo messages | * GroupInfo messages | |||
skipping to change at page 129, line 8 ¶ | skipping to change at line 5444 ¶ | |||
16.4.1. GroupID, Epoch, and Message Frequency | 16.4.1. GroupID, Epoch, and Message Frequency | |||
MLS provides no mechanism to protect the group ID and epoch of a | MLS provides no mechanism to protect the group ID and epoch of a | |||
message from the DS, so the group ID and the frequency of messages | message from the DS, so the group ID and the frequency of messages | |||
and epoch changes are not protected against inspection by the DS. | and epoch changes are not protected against inspection by the DS. | |||
However, any modifications to these will cause decryption failure. | However, any modifications to these will cause decryption failure. | |||
16.4.2. Group Extensions | 16.4.2. Group Extensions | |||
A group's extensions are first set by the group's creator and then | A group's extensions are first set by the group's creator and then | |||
updated by GroupContextExtensions proposals. A GroupContextExtension | updated by GroupContextExtensions proposals. A | |||
proposal sent as a PublicMessage leaks the group's extensions. | GroupContextExtensions proposal sent as a PublicMessage leaks the | |||
group's extensions. | ||||
A new member learns the group's extensions via a GroupInfo object. | A new member learns the group's extensions via a GroupInfo object. | |||
When the new member joins via a Welcome message, the Welcome | When the new member joins via a Welcome message, the Welcome | |||
message's encryption protects the GroupInfo message. When the new | message's encryption protects the GroupInfo message. When the new | |||
member joins via an external join, they must be provided with a | member joins via an external join, they must be provided with a | |||
GroupInfo object. Protection of this GroupInfo object is up to the | GroupInfo object. Protection of this GroupInfo object is up to the | |||
application -- if it is transmitted over a channel that is not | application -- if it is transmitted over a channel that is not | |||
confidential to the group and the new joiner, then it will leak the | confidential to the group and the new joiner, then it will leak the | |||
group's extensions. | group's extensions. | |||
skipping to change at page 129, line 42 ¶ | skipping to change at line 5479 ¶ | |||
reconstruct the group membership. | reconstruct the group membership. | |||
Welcome messages contain a hash of each KeyPackage for which the | Welcome messages contain a hash of each KeyPackage for which the | |||
Welcome message is encrypted. If a party has access to a pool of | Welcome message is encrypted. If a party has access to a pool of | |||
KeyPackages and observes a Welcome message, then they can identify | KeyPackages and observes a Welcome message, then they can identify | |||
the KeyPackage representing the new member. If the party can also | the KeyPackage representing the new member. If the party can also | |||
associate the Welcome with a group, then the party can infer that the | associate the Welcome with a group, then the party can infer that the | |||
identified new member was added to that group. | identified new member was added to that group. | |||
Note that these information leaks reveal the group's membership only | Note that these information leaks reveal the group's membership only | |||
to the degree that that membership is revealed by the contents of a | to the degree that membership is revealed by the contents of a | |||
member's LeafNode in the ratchet tree. In some cases, this may be | member's LeafNode in the ratchet tree. In some cases, this may be | |||
quite direct, e.g., due to credentials attesting to identifiers such | quite direct, e.g., due to credentials attesting to identifiers such | |||
as email addresses. An application could construct a member's leaf | as email addresses. An application could construct a member's leaf | |||
node to be less identifying, e.g., by using a pseudonymous credential | node to be less identifying, e.g., by using a pseudonymous credential | |||
and frequently rotating encryption and signature keys. | and frequently rotating encryption and signature keys. | |||
16.5. Authentication | 16.5. Authentication | |||
The first form of authentication we provide is that group members can | The first form of authentication we provide is that group members can | |||
verify a message originated from one of the members of the group. | verify a message originated from one of the members of the group. | |||
For encrypted messages, this is guaranteed because messages are | For encrypted messages, this is guaranteed because messages are | |||
encrypted with an AEAD under a key derived from the group secrets. | encrypted with an AEAD under a key derived from the group secrets. | |||
For plaintext messages, this is guaranteed by the use of a | For plaintext messages, this is guaranteed by the use of a | |||
membership_tag which constitutes a MAC over the message, under a key | membership_tag, which constitutes a MAC over the message, under a key | |||
derived from the group secrets. | derived from the group secrets. | |||
The second form of authentication is that group members can verify a | The second form of authentication is that group members can verify a | |||
message originated from a particular member of the group. This is | message originated from a particular member of the group. This is | |||
guaranteed by a digital signature on each message from the sender's | guaranteed by a digital signature on each message from the sender's | |||
signature key. | signature key. | |||
The signature keys held by group members are critical to the security | The signature keys held by group members are critical to the security | |||
of MLS against active attacks. If a member's signature key is | of MLS against active attacks. If a member's signature key is | |||
compromised, then an attacker can create LeafNodes and KeyPackages | compromised, then an attacker can create LeafNodes and KeyPackages | |||
impersonating the member; depending on the application, this can then | impersonating the member; depending on the application, this can then | |||
allow the attacker to join the group with the compromised member's | allow the attacker to join the group with the compromised member's | |||
identity. For example, if a group has enabled external parties to | identity. For example, if a group has enabled external parties to | |||
join via external commits, then an attacker that has compromised a | join via external commits, then an attacker that has compromised a | |||
member's signature key could use an external commit to insert | member's signature key could use an external Commit to insert | |||
themselves into the group -- even using a "resync"-style external | themselves into the group -- even using a "resync"-style external | |||
commit to replace the compromised member in the group. | Commit to replace the compromised member in the group. | |||
Applications can mitigate the risks of signature key compromise using | Applications can mitigate the risks of signature key compromise using | |||
pre-shared keys. If a group requires joiners to know a PSK in | pre-shared keys. If a group requires joiners to know a PSK in | |||
addition to authenticating with a credential, then in order to mount | addition to authenticating with a credential, then in order to mount | |||
an impersonation attack, the attacker would need to compromise the | an impersonation attack, the attacker would need to compromise the | |||
relevant PSK as well as the victim's signature key. The cost of this | relevant PSK as well as the victim's signature key. The cost of this | |||
mitigation is that the application needs some external arrangement | mitigation is that the application needs some external arrangement | |||
that ensures that the legitimate members of the group have the | that ensures that the legitimate members of the group have the | |||
required PSKs. | required PSKs. | |||
skipping to change at page 131, line 15 ¶ | skipping to change at line 5540 ¶ | |||
Compromise | Compromise | |||
| | | | |||
| | | | |||
| V | | | V | | |||
------------------|---------|-------------------------> | ------------------|---------|-------------------------> | |||
| | Time | | | Time | |||
<-----------------| |----------------> | <-----------------| |----------------> | |||
Forward Secrecy | | Post-Compromise | Forward Secrecy | | Post-Compromise | |||
| | Security | | | Security | |||
Figure 29: Forward secrecy and post-compromise security | Figure 29: Forward Secrecy and Post-Compromise Security | |||
Post-compromise security is provided between epochs by members | Post-compromise security is provided between epochs by members | |||
regularly updating their leaf key in the ratchet tree. Updating | regularly updating their leaf key in the ratchet tree. Updating | |||
their leaf key prevents group secrets from continuing to be encrypted | their leaf key prevents group secrets from continuing to be encrypted | |||
to public keys whose private keys had previously been compromised. | to public keys whose private keys had previously been compromised. | |||
Note that sending an Update proposal does not achieve PCS until | Note that sending an Update proposal does not achieve PCS until | |||
another member includes it in a Commit. Members can achieve | another member includes it in a Commit. Members can achieve | |||
immediate PCS by sending their own Commit and populating the path | immediate PCS by sending their own Commit and populating the path | |||
field, as described in Section 12.4. To be clear, in all these | field, as described in Section 12.4. To be clear, in all these | |||
cases, the PCS guarantees come into effect when the members of the | cases, the PCS guarantees come into effect when the members of the | |||
group process the relevant Commit, not when the sender creates it. | group process the relevant Commit, not when the sender creates it. | |||
Forward secrecy between epochs is provided by deleting private keys | Forward secrecy between epochs is provided by deleting private keys | |||
from past versions of the ratchet tree, as this prevents old group | from past versions of the ratchet tree, as this prevents old group | |||
secrets from being re-derived. Forward secrecy _within_ an epoch is | secrets from being re-derived. Forward secrecy _within_ an epoch is | |||
provided by deleting message encryption keys once they've been used | provided by deleting message encryption keys once they've been used | |||
to encrypt or decrypt a message. Note that group secrets and message | to encrypt or decrypt a message. Note that group secrets and message | |||
encryption keys are shared by the group, and thus there is a risk to | encryption keys are shared by the group. There is thus a risk to | |||
forward secrecy as long as any member has not deleted these keys. | forward secrecy as long as any member has not deleted these keys. | |||
This is a particular risk if a member is offline for a long period of | This is a particular risk if a member is offline for a long period of | |||
time. Applications SHOULD have mechanisms for evicting group members | time. Applications SHOULD have mechanisms for evicting group members | |||
which are offline for too long (i.e., have not changed their key | that are offline for too long (i.e., have not changed their key | |||
within some period). | within some period). | |||
New groups are also at risk of using previously compromised keys (as | New groups are also at risk of using previously compromised keys (as | |||
with post-compromise security), if a member is added to a new group | with post-compromise security) if a member is added to a new group | |||
via an old KeyPackage whose corresponding private key has been | via an old KeyPackage whose corresponding private key has been | |||
compromised. This risk can be mitigated by having clients regularly | compromised. This risk can be mitigated by having clients regularly | |||
generate new KeyPackages and upload them to the Delivery Service. | generate new KeyPackages and upload them to the Delivery Service. | |||
This way, the key material used to add a member to a new group is | This way, the key material used to add a member to a new group is | |||
more likely to be fresh and less likely to be compromised. | more likely to be fresh and less likely to be compromised. | |||
16.7. Uniqueness of Ratchet Tree Key Pairs | 16.7. Uniqueness of Ratchet Tree Key Pairs | |||
The encryption and signature keys stored in the encryption_key and | The encryption and signature keys stored in the encryption_key and | |||
signature_key fields of ratchet tree nodes MUST be distinct from one | signature_key fields of ratchet tree nodes MUST be distinct from one | |||
another. If two members' leaf nodes have the same signature key, for | another. If two members' leaf nodes have the same signature key, for | |||
example, then the data origin authentication properties afforded by | example, then the data origin authentication properties afforded by | |||
signatures within the group are degraded. | signatures within the group are degraded. | |||
Uniqueness of keys in leaf nodes is assured by explicit checks on | Uniqueness of keys in leaf nodes is assured by explicitly checking | |||
leaf nodes being added to the tree by Add or Update proposals, or in | each leaf node as it is added to the tree, whether in an Add | |||
the path field of a Commit. Details can be found in Section 7.3, | proposal, in an Update proposal, or in the path field of a Commit. | |||
Section 12.2, and Section 12.4.2. Uniqueness of encryption keys in | Details can be found in Sections 7.3, 12.2, and 12.4.2. Uniqueness | |||
parent nodes is assured by checking that the keys in an UpdatePath | of encryption keys in parent nodes is assured by checking that the | |||
are not found elsewhere in the tree (see Section 12.4.2. | keys in an UpdatePath are not found elsewhere in the tree (see | |||
Section 12.4.2). | ||||
16.8. KeyPackage Reuse | 16.8. KeyPackage Reuse | |||
KeyPackages are intended to be used only once. That is, once a | KeyPackages are intended to be used only once. That is, once a | |||
KeyPackage has been used to introduce the corresponding client to a | KeyPackage has been used to introduce the corresponding client to a | |||
group, it SHOULD be deleted from the KeyPackage publication system. | group, it SHOULD be deleted from the KeyPackage publication system. | |||
Reuse of KeyPackages can lead to replay attacks. | Reuse of KeyPackages can lead to replay attacks. | |||
An application MAY allow for reuse of a "last resort" KeyPackage in | An application MAY allow for reuse of a "last resort" KeyPackage in | |||
order to prevent denial-of-service attacks. Since a KeyPackage is | order to prevent denial-of-service attacks. Since a KeyPackage is | |||
needed to add a client to a new group, an attacker could prevent a | needed to add a client to a new group, an attacker could prevent a | |||
client being added to new groups by exhausting all available | client from being added to new groups by exhausting all available | |||
KeyPackages. To prevent such a denial-of-service attack, the | KeyPackages. To prevent such a denial-of-service attack, the | |||
KeyPackage publication system SHOULD rate-limit KeyPackage requests, | KeyPackage publication system SHOULD rate-limit KeyPackage requests, | |||
especially if not authenticated. | especially if not authenticated. | |||
16.9. Delivery Service Compromise | 16.9. Delivery Service Compromise | |||
MLS is designed to protect the confidentiality and integrity of the | MLS is designed to protect the confidentiality and integrity of the | |||
group data even in the face of a compromised DS. However, a | group data even in the face of a compromised DS. However, a | |||
compromised DS can still mount some attacks. While it cannot forge | compromised DS can still mount some attacks. While it cannot forge | |||
messages, it can selectively delay or remove them. This can in some | messages, it can selectively delay or remove them. In some cases, | |||
cases be observed by detecting gaps in the per-sender generation | this can be observed by detecting gaps in the per-sender generation | |||
counter, though it may not always be possible to distinguish an | counter, though it may not always be possible to distinguish an | |||
attack from message loss. In addition, the DS can permanently block | attack from message loss. In addition, the DS can permanently block | |||
messages to and from a group member. This will not always be | messages to and from a group member. This will not always be | |||
detectable by other members. If an application uses the DS to | detectable by other members. If an application uses the DS to | |||
resolve conflicts between simultaneous Commits (see Section 14), it | resolve conflicts between simultaneous Commits (see Section 14), it | |||
is also possible for the DS to influence which Commit is applied, | is also possible for the DS to influence which Commit is applied, | |||
even to the point of preventing a member from ever having its Commits | even to the point of preventing a member from ever having its Commits | |||
applied. | applied. | |||
When put together, these abilities potentially allow a DS to collude | When put together, these abilities potentially allow a DS to collude | |||
skipping to change at page 133, line 21 ¶ | skipping to change at line 5636 ¶ | |||
16.10. Authentication Service Compromise | 16.10. Authentication Service Compromise | |||
Authentication Service compromise is much more serious than | Authentication Service compromise is much more serious than | |||
compromise of the Delivery Service. A compromised AS can assert a | compromise of the Delivery Service. A compromised AS can assert a | |||
binding for a signature key and identity pair of its choice, thus | binding for a signature key and identity pair of its choice, thus | |||
allowing impersonation of a given user. This ability is sufficient | allowing impersonation of a given user. This ability is sufficient | |||
to allow the AS to join new groups as if it were that user. | to allow the AS to join new groups as if it were that user. | |||
Depending on the application architecture, it may also be sufficient | Depending on the application architecture, it may also be sufficient | |||
to allow the compromised AS to join the group as an existing user, | to allow the compromised AS to join the group as an existing user, | |||
for instance as if it were a new device associated with the same | for instance, as if it were a new device associated with the same | |||
user. If the application uses a transparency mechanism such as | user. If the application uses a transparency mechanism such as | |||
CONIKS [CONIKS] or Key Transparency [KT], then it may be possible for | CONIKS [CONIKS] or Key Transparency [KT], then it may be possible for | |||
end users to detect this kind of misbehavior by the AS. It is also | end users to detect this kind of misbehavior by the AS. It is also | |||
possible to construct schemes in which the various clients owned by a | possible to construct schemes in which the various clients owned by a | |||
user vouch for each other, e.g., by signing each others' keys. | user vouch for each other, e.g., by signing each others' keys. | |||
16.11. Additional Policy Enforcement | 16.11. Additional Policy Enforcement | |||
The DS and AS may also apply additional policies to MLS operations to | The DS and AS may also apply additional policies to MLS operations to | |||
obtain additional security properties. For example, MLS enables any | obtain additional security properties. For example, MLS enables any | |||
skipping to change at page 134, line 8 ¶ | skipping to change at line 5669 ¶ | |||
encrypts a sequence of path secrets to different subtrees of the | encrypts a sequence of path secrets to different subtrees of the | |||
group's ratchet trees. These path secrets should be derived in a | group's ratchet trees. These path secrets should be derived in a | |||
sequence as described in Section 7.4, but the UpdatePath syntax | sequence as described in Section 7.4, but the UpdatePath syntax | |||
allows the sender to encrypt arbitrary, unrelated secrets. The | allows the sender to encrypt arbitrary, unrelated secrets. The | |||
syntax also does not guarantee that the encrypted path secret for a | syntax also does not guarantee that the encrypted path secret for a | |||
given node corresponds to the public key provided for that node. | given node corresponds to the public key provided for that node. | |||
Both of these types of corruption will cause processing of a Commit | Both of these types of corruption will cause processing of a Commit | |||
to fail for some members of the group. If the public key for a node | to fail for some members of the group. If the public key for a node | |||
does not match the path secret, then the members that decrypt that | does not match the path secret, then the members that decrypt that | |||
path secret will reject the commit based on this mismatch. If the | path secret will reject the Commit based on this mismatch. If the | |||
path secret sequence is incorrect at some point, then members that | path secret sequence is incorrect at some point, then members that | |||
can decrypt nodes before that point will compute a different public | can decrypt nodes before that point will compute a different public | |||
key for the mismatched node than the one in the UpdatePath, which | key for the mismatched node than the one in the UpdatePath, which | |||
also causes the Commit to fail. Applications SHOULD provide | also causes the Commit to fail. Applications SHOULD provide | |||
mechanisms for failed commits to be reported, so that group members | mechanisms for failed commits to be reported, so that group members | |||
who were not able to recognize the error themselves can reinitialize | who were not able to recognize the error themselves can reinitialize | |||
the group if necessary. | the group if necessary. | |||
Even with such an error reporting mechanism in place, however, it is | Even with such an error reporting mechanism in place, however, it is | |||
still possible for members to get locked out of the group by a | still possible for members to get locked out of the group by a | |||
malformed commit. Since malformed Commits can only be recognized by | malformed Commit. Since malformed Commits can only be recognized by | |||
certain members of the group, in an asynchronous application, it may | certain members of the group, in an asynchronous application, it may | |||
be the case that all members that could detect a fault in a Commit | be the case that all members that could detect a fault in a Commit | |||
are offline. In such a case, the Commit will be accepted by the | are offline. In such a case, the Commit will be accepted by the | |||
group, and the resulting state possibly used as the basis for further | group, and the resulting state will possibly be used as the basis for | |||
Commits. When the affected members come back online, they will | further Commits. When the affected members come back online, they | |||
reject the first commit, and thus be unable to catch up with the | will reject the first Commit, and thus be unable to catch up with the | |||
group. These members will either need to add themselves back with an | group. These members will need to either add themselves back with an | |||
external Commit, or reinitialize the group from scratch. | external Commit or reinitialize the group from scratch. | |||
Applications can address this risk by requiring certain members of | Applications can address this risk by requiring certain members of | |||
the group to acknowledge successful processing of a Commit before the | the group to acknowledge successful processing of a Commit before the | |||
group regards the Commit as accepted. The minimum set of | group regards the Commit as accepted. The minimum set of | |||
acknowledgements necessary to verify that a Commit is well-formed | acknowledgements necessary to verify that a Commit is well-formed | |||
comprises an acknowledgement from one member per node in the | comprises an acknowledgement from one member per node in the | |||
UpdatePath, that is, one member from each subtree rooted in the | UpdatePath, that is, one member from each subtree rooted in the | |||
copath node corresponding to the node in the UpdatePath. MLS does | copath node corresponding to the node in the UpdatePath. MLS does | |||
not provide a built-in mechanism for such acknowledgements, but they | not provide a built-in mechanism for such acknowledgements, but they | |||
can be added at the application layer. | can be added at the application layer. | |||
17. IANA Considerations | 17. IANA Considerations | |||
This document requests the creation of the following new IANA | IANA has created the following registries: | |||
registries: | ||||
* MLS Ciphersuites (Section 17.1) | * MLS Cipher Suites (Section 17.1) | |||
* MLS Wire Formats (Section 17.2) | * MLS Wire Formats (Section 17.2) | |||
* MLS Extension Types (Section 17.3) | * MLS Extension Types (Section 17.3) | |||
* MLS Proposal Types (Section 17.4) | * MLS Proposal Types (Section 17.4) | |||
* MLS Credential Types (Section 17.5) | * MLS Credential Types (Section 17.5) | |||
* MLS Signature Labels (Section 17.6) | * MLS Signature Labels (Section 17.6) | |||
* MLS Public Key Encryption Labels (Section 17.7) | * MLS Public Key Encryption Labels (Section 17.7) | |||
* MLS Exporter Labels (Section 17.8) | * MLS Exporter Labels (Section 17.8) | |||
All of these registries should be under a heading of "Messaging Layer | All of these registries are under the "Messaging Layer Security" | |||
Security", and assignments are made via the Specification Required | group registry heading, and assignments are made via the | |||
policy [RFC8126]. See Section 17.9 for additional information about | Specification Required policy [RFC8126]. See Section 17.9 for | |||
the MLS Designated Experts (DEs). | additional information about the MLS Designated Experts (DEs). | |||
RFC EDITOR: Please replace XXXX throughout with the RFC number | ||||
assigned to this document | ||||
17.1. MLS Ciphersuites | 17.1. MLS Cipher Suites | |||
A ciphersuite is a combination of a protocol version and the set of | A cipher suite is a combination of a protocol version and the set of | |||
cryptographic algorithms that should be used. | cryptographic algorithms that should be used. | |||
Ciphersuite names follow the naming convention: | Cipher suite names follow the naming convention: | |||
CipherSuite MLS_LVL_KEM_AEAD_HASH_SIG = VALUE; | CipherSuite MLS_LVL_KEM_AEAD_HASH_SIG = VALUE; | |||
Where VALUE is represented as a sixteen-bit integer: | Where VALUE is represented as a 16-bit integer: | |||
uint16 CipherSuite; | uint16 CipherSuite; | |||
+===========+==================================+ | +===========+==================================+ | |||
| Component | Contents | | | Component | Contents | | |||
+===========+==================================+ | +===========+==================================+ | |||
| LVL | The security level (in bits) | | | LVL | The security level (in bits) | | |||
+-----------+----------------------------------+ | +-----------+----------------------------------+ | |||
| KEM | The KEM algorithm used for HPKE | | | KEM | The KEM algorithm used for HPKE | | |||
| | in ratchet tree operations | | | | in ratchet tree operations | | |||
+-----------+----------------------------------+ | +-----------+----------------------------------+ | |||
| AEAD | The AEAD algorithm used for HPKE | | | AEAD | The AEAD algorithm used for HPKE | | |||
| | and message protection | | | | and message protection | | |||
+-----------+----------------------------------+ | +-----------+----------------------------------+ | |||
| HASH | The hash algorithm used for HPKE | | | HASH | The hash algorithm used for HPKE | | |||
| | and the MLS transcript hash | | | | and the MLS transcript hash | | |||
+-----------+----------------------------------+ | +-----------+----------------------------------+ | |||
| SIG | The Signature algorithm used for | | | SIG | The signature algorithm used for | | |||
| | message authentication | | | | message authentication | | |||
+-----------+----------------------------------+ | +-----------+----------------------------------+ | |||
Table 5 | Table 5 | |||
The columns in the registry are as follows: | The columns in the registry are as follows: | |||
* Value: The numeric value of the ciphersuite | * Value: The numeric value of the cipher suite | |||
* Name: The name of the ciphersuite | ||||
[[ RFC EDITOR: This section should be the same as the corresponding | * Name: The name of the cipher suite | |||
text in draft-ietf-tls-rfc8447bis. Please align the two documents if | ||||
they have diverged in the approval process. ]] | ||||
* Recommended: Whether support for this ciphersuite is recommended | * Recommended: Whether support for this cipher suite is recommended | |||
by the IETF. Valid values are "Y", "N", and "D", as described | by the IETF. Valid values are "Y", "N", and "D", as described | |||
below. The default value of the "Recommended" column is "N". | below. The default value of the "Recommended" column is "N". | |||
Setting the Recommended item to "Y" or "D", or changing an item | Setting the Recommended item to "Y" or "D", or changing an item | |||
whose current value is "Y" or "D", requires Standards Action | whose current value is "Y" or "D", requires Standards Action | |||
[RFC8126]. | [RFC8126]. | |||
- Y: Indicates that the IETF has consensus that the item is | - Y: Indicates that the IETF has consensus that the item is | |||
RECOMMENDED. This only means that the associated mechanism is | RECOMMENDED. This only means that the associated mechanism is | |||
fit for the purpose for which it was defined. Careful reading | fit for the purpose for which it was defined. Careful reading | |||
of the documentation for the mechanism is necessary to | of the documentation for the mechanism is necessary to | |||
understand the applicability of that mechanism. The IETF could | understand the applicability of that mechanism. The IETF could | |||
recommend mechanisms that have limited applicability, but will | recommend mechanisms that have limited applicability, but it | |||
provide applicability statements that describe any limitations | will provide applicability statements that describe any | |||
of the mechanism or necessary constraints on its use. | limitations of the mechanism or necessary constraints on its | |||
use. | ||||
- N: Indicates that the item has not been evaluated by the IETF | - N: Indicates that the item has not been evaluated by the IETF | |||
and that the IETF has made no statement about the suitability | and that the IETF has made no statement about the suitability | |||
of the associated mechanism. This does not necessarily mean | of the associated mechanism. This does not necessarily mean | |||
that the mechanism is flawed, only that no consensus exists. | that the mechanism is flawed, only that no consensus exists. | |||
The IETF might have consensus to leave an item marked as "N" on | The IETF might have consensus to leave an item marked as "N" on | |||
the basis of it having limited applicability or usage | the basis of it having limited applicability or usage | |||
constraints. | constraints. | |||
- D: Indicates that the item is discouraged and SHOULD NOT or | - D: Indicates that the item is discouraged and SHOULD NOT or | |||
MUST NOT be used. This marking could be used to identify | MUST NOT be used. This marking could be used to identify | |||
mechanisms that might result in problems if they are used, such | mechanisms that might result in problems if they are used, such | |||
as a weak cryptographic algorithm or a mechanism that might | as a weak cryptographic algorithm or a mechanism that might | |||
cause interoperability problems in deployment. | cause interoperability problems in deployment. | |||
* Reference: The document where this ciphersuite is defined | * Reference: The document where this cipher suite is defined | |||
Initial contents: | Initial contents: | |||
+========+===================================================+=+====+ | +========+===================================================+=+====+ | |||
| Value |Name |R|Ref | | | Value |Name |R|Ref | | |||
+========+===================================================+=+====+ | +========+===================================================+=+====+ | |||
| 0x0000 |RESERVED |-|RFC | | | 0x0000 |RESERVED |-|RFC | | |||
| | | |XXXX| | | | | |9420| | |||
+--------+---------------------------------------------------+-+----+ | +--------+---------------------------------------------------+-+----+ | |||
| 0x0001 |MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519 |Y|RFC | | | 0x0001 |MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519 |Y|RFC | | |||
| | | |XXXX| | | | | |9420| | |||
+--------+---------------------------------------------------+-+----+ | +--------+---------------------------------------------------+-+----+ | |||
| 0x0002 |MLS_128_DHKEMP256_AES128GCM_SHA256_P256 |Y|RFC | | | 0x0002 |MLS_128_DHKEMP256_AES128GCM_SHA256_P256 |Y|RFC | | |||
| | | |XXXX| | | | | |9420| | |||
+--------+---------------------------------------------------+-+----+ | +--------+---------------------------------------------------+-+----+ | |||
| 0x0003 |MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519|Y|RFC | | | 0x0003 |MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519|Y|RFC | | |||
| | | |XXXX| | | | | |9420| | |||
+--------+---------------------------------------------------+-+----+ | +--------+---------------------------------------------------+-+----+ | |||
| 0x0004 |MLS_256_DHKEMX448_AES256GCM_SHA512_Ed448 |Y|RFC | | | 0x0004 |MLS_256_DHKEMX448_AES256GCM_SHA512_Ed448 |Y|RFC | | |||
| | | |XXXX| | | | | |9420| | |||
+--------+---------------------------------------------------+-+----+ | +--------+---------------------------------------------------+-+----+ | |||
| 0x0005 |MLS_256_DHKEMP521_AES256GCM_SHA512_P521 |Y|RFC | | | 0x0005 |MLS_256_DHKEMP521_AES256GCM_SHA512_P521 |Y|RFC | | |||
| | | |XXXX| | | | | |9420| | |||
+--------+---------------------------------------------------+-+----+ | +--------+---------------------------------------------------+-+----+ | |||
| 0x0006 |MLS_256_DHKEMX448_CHACHA20POLY1305_SHA512_Ed448 |Y|RFC | | | 0x0006 |MLS_256_DHKEMX448_CHACHA20POLY1305_SHA512_Ed448 |Y|RFC | | |||
| | | |XXXX| | | | | |9420| | |||
+--------+---------------------------------------------------+-+----+ | +--------+---------------------------------------------------+-+----+ | |||
| 0x0007 |MLS_256_DHKEMP384_AES256GCM_SHA384_P384. |Y|RFC | | | 0x0007 |MLS_256_DHKEMP384_AES256GCM_SHA384_P384 |Y|RFC | | |||
| | | |XXXX| | | | | |9420| | |||
+--------+---------------------------------------------------+-+----+ | +--------+---------------------------------------------------+-+----+ | |||
| 0x0A0A |GREASE |Y|RFC | | | 0x0A0A |GREASE |Y|RFC | | |||
| | | |XXXX| | | | | |9420| | |||
+--------+---------------------------------------------------+-+----+ | +--------+---------------------------------------------------+-+----+ | |||
| 0x1A1A |GREASE |Y|RFC | | | 0x1A1A |GREASE |Y|RFC | | |||
| | | |XXXX| | | | | |9420| | |||
+--------+---------------------------------------------------+-+----+ | +--------+---------------------------------------------------+-+----+ | |||
| 0x2A2A |GREASE |Y|RFC | | | 0x2A2A |GREASE |Y|RFC | | |||
| | | |XXXX| | | | | |9420| | |||
+--------+---------------------------------------------------+-+----+ | +--------+---------------------------------------------------+-+----+ | |||
| 0x3A3A |GREASE |Y|RFC | | | 0x3A3A |GREASE |Y|RFC | | |||
| | | |XXXX| | | | | |9420| | |||
+--------+---------------------------------------------------+-+----+ | +--------+---------------------------------------------------+-+----+ | |||
| 0x4A4A |GREASE |Y|RFC | | | 0x4A4A |GREASE |Y|RFC | | |||
| | | |XXXX| | | | | |9420| | |||
+--------+---------------------------------------------------+-+----+ | +--------+---------------------------------------------------+-+----+ | |||
| 0x5A5A |GREASE |Y|RFC | | | 0x5A5A |GREASE |Y|RFC | | |||
| | | |XXXX| | | | | |9420| | |||
+--------+---------------------------------------------------+-+----+ | +--------+---------------------------------------------------+-+----+ | |||
| 0x6A6A |GREASE |Y|RFC | | | 0x6A6A |GREASE |Y|RFC | | |||
| | | |XXXX| | | | | |9420| | |||
+--------+---------------------------------------------------+-+----+ | +--------+---------------------------------------------------+-+----+ | |||
| 0x7A7A |GREASE |Y|RFC | | | 0x7A7A |GREASE |Y|RFC | | |||
| | | |XXXX| | | | | |9420| | |||
+--------+---------------------------------------------------+-+----+ | +--------+---------------------------------------------------+-+----+ | |||
| 0x8A8A |GREASE |Y|RFC | | | 0x8A8A |GREASE |Y|RFC | | |||
| | | |XXXX| | | | | |9420| | |||
+--------+---------------------------------------------------+-+----+ | +--------+---------------------------------------------------+-+----+ | |||
| 0x9A9A |GREASE |Y|RFC | | | 0x9A9A |GREASE |Y|RFC | | |||
| | | |XXXX| | | | | |9420| | |||
+--------+---------------------------------------------------+-+----+ | +--------+---------------------------------------------------+-+----+ | |||
| 0xAAAA |GREASE |Y|RFC | | | 0xAAAA |GREASE |Y|RFC | | |||
| | | |XXXX| | | | | |9420| | |||
+--------+---------------------------------------------------+-+----+ | +--------+---------------------------------------------------+-+----+ | |||
| 0xBABA |GREASE |Y|RFC | | | 0xBABA |GREASE |Y|RFC | | |||
| | | |XXXX| | | | | |9420| | |||
+--------+---------------------------------------------------+-+----+ | +--------+---------------------------------------------------+-+----+ | |||
| 0xCACA |GREASE |Y|RFC | | | 0xCACA |GREASE |Y|RFC | | |||
| | | |XXXX| | | | | |9420| | |||
+--------+---------------------------------------------------+-+----+ | +--------+---------------------------------------------------+-+----+ | |||
| 0xDADA |GREASE |Y|RFC | | | 0xDADA |GREASE |Y|RFC | | |||
| | | |XXXX| | | | | |9420| | |||
+--------+---------------------------------------------------+-+----+ | +--------+---------------------------------------------------+-+----+ | |||
| 0xEAEA |GREASE |Y|RFC | | | 0xEAEA |GREASE |Y|RFC | | |||
| | | |XXXX| | | | | |9420| | |||
+--------+---------------------------------------------------+-+----+ | +--------+---------------------------------------------------+-+----+ | |||
| 0xF000 |Reserved for Private Use |-|RFC | | | 0xF000 |Reserved for Private Use |-|RFC | | |||
| - | | |XXXX| | | - | | |9420| | |||
| 0xFFFF | | | | | | 0xFFFF | | | | | |||
+--------+---------------------------------------------------+-+----+ | +--------+---------------------------------------------------+-+----+ | |||
Table 6 | Table 6: MLS Extension Types Registry | |||
All of these ciphersuites use HMAC [RFC2104] as their MAC function, | All of the non-GREASE cipher suites use HMAC [RFC2104] as their MAC | |||
with different hashes per ciphersuite. The mapping of ciphersuites | function, with different hashes per cipher suite. The mapping of | |||
to HPKE primitives, HMAC hash functions, and TLS signature schemes is | cipher suites to HPKE primitives [RFC9180], HMAC hash functions, and | |||
as follows [RFC9180] [RFC8446]: | TLS signature schemes [RFC8446] is as follows: | |||
+======+======+========+========+========+========================+ | +======+======+========+========+========+========================+ | |||
|Value |KEM | KDF | AEAD | Hash | Signature | | |Value |KEM | KDF | AEAD | Hash | Signature | | |||
+======+======+========+========+========+========================+ | +======+======+========+========+========+========================+ | |||
|0x0001|0x0020| 0x0001 | 0x0001 | SHA256 | ed25519 | | |0x0001|0x0020| 0x0001 | 0x0001 | SHA256 | ed25519 | | |||
+------+------+--------+--------+--------+------------------------+ | +------+------+--------+--------+--------+------------------------+ | |||
|0x0002|0x0010| 0x0001 | 0x0001 | SHA256 | ecdsa_secp256r1_sha256 | | |0x0002|0x0010| 0x0001 | 0x0001 | SHA256 | ecdsa_secp256r1_sha256 | | |||
+------+------+--------+--------+--------+------------------------+ | +------+------+--------+--------+--------+------------------------+ | |||
|0x0003|0x0020| 0x0001 | 0x0003 | SHA256 | ed25519 | | |0x0003|0x0020| 0x0001 | 0x0003 | SHA256 | ed25519 | | |||
+------+------+--------+--------+--------+------------------------+ | +------+------+--------+--------+--------+------------------------+ | |||
skipping to change at page 139, line 26 ¶ | skipping to change at line 5904 ¶ | |||
|0x0005|0x0012| 0x0003 | 0x0002 | SHA512 | ecdsa_secp521r1_sha512 | | |0x0005|0x0012| 0x0003 | 0x0002 | SHA512 | ecdsa_secp521r1_sha512 | | |||
+------+------+--------+--------+--------+------------------------+ | +------+------+--------+--------+--------+------------------------+ | |||
|0x0006|0x0021| 0x0003 | 0x0003 | SHA512 | ed448 | | |0x0006|0x0021| 0x0003 | 0x0003 | SHA512 | ed448 | | |||
+------+------+--------+--------+--------+------------------------+ | +------+------+--------+--------+--------+------------------------+ | |||
|0x0007|0x0011| 0x0002 | 0x0002 | SHA384 | ecdsa_secp384r1_sha384 | | |0x0007|0x0011| 0x0002 | 0x0002 | SHA384 | ecdsa_secp384r1_sha384 | | |||
+------+------+--------+--------+--------+------------------------+ | +------+------+--------+--------+--------+------------------------+ | |||
Table 7 | Table 7 | |||
The hash used for the MLS transcript hash is the one referenced in | The hash used for the MLS transcript hash is the one referenced in | |||
the ciphersuite name. In the ciphersuites defined above, "SHA256", | the cipher suite name. In the cipher suites defined above, "SHA256", | |||
"SHA384", and "SHA512" refer to the SHA-256, SHA-384, and SHA-512 | "SHA384", and "SHA512" refer, respectively, to the SHA-256, SHA-384, | |||
functions defined in [SHS]. | and SHA-512 functions defined in [SHS]. | |||
In addition to the general requirements of Section 13.1, future | In addition to the general requirements of Section 13.1, future | |||
ciphersuites MUST meet the requirements of Section 16.3. | cipher suites MUST meet the requirements of Section 16.3. | |||
It is advisable to keep the number of ciphersuites low to increase | It is advisable to keep the number of cipher suites low to increase | |||
the chances clients can interoperate in a federated environment, | the likelihood that clients can interoperate in a federated | |||
therefore the ciphersuites only include modern, yet well-established | environment. The cipher suites therefore include only modern, yet | |||
algorithms. Depending on their requirements, clients can choose | well-established algorithms. Depending on their requirements, | |||
between two security levels (roughly 128-bit and 256-bit). Within | clients can choose between two security levels (roughly 128-bit and | |||
the security levels clients can choose between faster X25519/X448 | 256-bit). Within the security levels, clients can choose between | |||
curves and FIPS 140-2 compliant curves for Diffie-Hellman key | faster X25519/X448 curves and curves compliant with FIPS 140-2 for | |||
negotiations. Clients may also choose ChaCha20Poly1305 or AES-GCM, | Diffie-Hellman key negotiations. Clients may also choose | |||
e.g., for performance reasons. Since ChaCha20Poly1305 is not listed | ChaCha20Poly1305 or AES-GCM, e.g., for performance reasons. Since | |||
by FIPS 140-2 it is not paired with FIPS 140-2 compliant curves. The | ChaCha20Poly1305 is not listed by FIPS 140-2, it is not paired with | |||
security level of symmetric encryption algorithms and hash functions | curves compliant with FIPS 140-2. The security level of symmetric | |||
is paired with the security level of the curves. | encryption algorithms and hash functions is paired with the security | |||
level of the curves. | ||||
The mandatory-to-implement ciphersuite for MLS 1.0 is | The mandatory-to-implement cipher suite for MLS 1.0 is | |||
MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519 which uses Curve25519 | MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519, which uses Curve25519 | |||
for key exchange, AES-128-GCM for HPKE, HKDF over SHA2-256, and | for key exchange, AES-128-GCM for HPKE, HKDF over SHA2-256, and | |||
Ed25519 for signatures. MLS clients MUST implement this ciphersuite. | Ed25519 for signatures. MLS clients MUST implement this cipher | |||
suite. | ||||
New ciphersuite values are assigned by IANA as described in | ||||
Section 17. | ||||
17.2. MLS Wire Formats | 17.2. MLS Wire Formats | |||
This registry lists identifiers for the types of messages that can be | The "MLS Wire Formats" registry lists identifiers for the types of | |||
sent in MLS. The wire format field is two bytes wide, so the valid | messages that can be sent in MLS. The wire format field is two bytes | |||
wire format values are in the range 0x0000 to 0xFFFF. | wide, so the valid wire format values are in the range 0x0000 to | |||
0xFFFF. | ||||
Template: | Template: | |||
* Value: The numeric value of the wire format | * Value: The numeric value of the wire format | |||
* Name: The name of the wire format | * Name: The name of the wire format | |||
* Recommended: Same as in Section 17.1 | * Recommended: Same as in Section 17.1 | |||
* Reference: The document where this wire format is defined | * Reference: The document where this wire format is defined | |||
Initial contents: | Initial contents: | |||
+=================+==========================+===+==========+ | +=================+==========================+===+==========+ | |||
| Value | Name | R | Ref | | | Value | Name | R | Ref | | |||
+=================+==========================+===+==========+ | +=================+==========================+===+==========+ | |||
| 0x0000 | RESERVED | - | RFC XXXX | | | 0x0000 | RESERVED | - | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
| 0x0001 | mls_public_message | Y | RFC XXXX | | | 0x0001 | mls_public_message | Y | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
| 0x0002 | mls_private_message | Y | RFC XXXX | | | 0x0002 | mls_private_message | Y | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
| 0x0003 | mls_welcome | Y | RFC XXXX | | | 0x0003 | mls_welcome | Y | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
| 0x0004 | mls_group_info | Y | RFC XXXX | | | 0x0004 | mls_group_info | Y | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
| 0x0005 | mls_key_package | Y | RFC XXXX | | | 0x0005 | mls_key_package | Y | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
| 0xF000 - 0xFFFF | Reserved for Private Use | - | RFC XXXX | | | 0xF000 - 0xFFFF | Reserved for Private Use | - | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
Table 8 | Table 8: MLS Wire Formats Registry | |||
17.3. MLS Extension Types | 17.3. MLS Extension Types | |||
This registry lists identifiers for extensions to the MLS protocol. | The "MLS Extension Types" registry lists identifiers for extensions | |||
The extension type field is two bytes wide, so valid extension type | to the MLS protocol. The extension type field is two bytes wide, so | |||
values are in the range 0x0000 to 0xFFFF. | valid extension type values are in the range 0x0000 to 0xFFFF. | |||
Template: | Template: | |||
* Value: The numeric value of the extension type | * Value: The numeric value of the extension type | |||
* Name: The name of the extension type | * Name: The name of the extension type | |||
* Message(s): The messages in which the extension may appear, drawn | * Message(s): The messages in which the extension may appear, drawn | |||
from the following list: | from the following list: | |||
- KP: KeyPackage objects | - KP: KeyPackage objects | |||
- LN: LeafNode objects | - LN: LeafNode objects | |||
- GC: GroupContext objects | - GC: GroupContext objects | |||
skipping to change at page 141, line 26 ¶ | skipping to change at line 6002 ¶ | |||
* Recommended: Same as in Section 17.1 | * Recommended: Same as in Section 17.1 | |||
* Reference: The document where this extension is defined | * Reference: The document where this extension is defined | |||
Initial contents: | Initial contents: | |||
+==========+=======================+============+===+==========+ | +==========+=======================+============+===+==========+ | |||
| Value | Name | Message(s) | R | Ref | | | Value | Name | Message(s) | R | Ref | | |||
+==========+=======================+============+===+==========+ | +==========+=======================+============+===+==========+ | |||
| 0x0000 | RESERVED | N/A | - | RFC XXXX | | | 0x0000 | RESERVED | N/A | - | RFC 9420 | | |||
+----------+-----------------------+------------+---+----------+ | +----------+-----------------------+------------+---+----------+ | |||
| 0x0001 | application_id | LN | Y | RFC XXXX | | | 0x0001 | application_id | LN | Y | RFC 9420 | | |||
+----------+-----------------------+------------+---+----------+ | +----------+-----------------------+------------+---+----------+ | |||
| 0x0002 | ratchet_tree | GI | Y | RFC XXXX | | | 0x0002 | ratchet_tree | GI | Y | RFC 9420 | | |||
+----------+-----------------------+------------+---+----------+ | +----------+-----------------------+------------+---+----------+ | |||
| 0x0003 | required_capabilities | GC | Y | RFC XXXX | | | 0x0003 | required_capabilities | GC | Y | RFC 9420 | | |||
+----------+-----------------------+------------+---+----------+ | +----------+-----------------------+------------+---+----------+ | |||
| 0x0004 | external_pub | GI | Y | RFC XXXX | | | 0x0004 | external_pub | GI | Y | RFC 9420 | | |||
+----------+-----------------------+------------+---+----------+ | +----------+-----------------------+------------+---+----------+ | |||
| 0x0005 | external_senders | GC | Y | RFC XXXX | | | 0x0005 | external_senders | GC | Y | RFC 9420 | | |||
+----------+-----------------------+------------+---+----------+ | +----------+-----------------------+------------+---+----------+ | |||
| 0x0A0A | GREASE | KP, GI | Y | RFC XXXX | | | 0x0A0A | GREASE | KP, GI, LN | Y | RFC 9420 | | |||
+----------+-----------------------+------------+---+----------+ | +----------+-----------------------+------------+---+----------+ | |||
| 0x1A1A | GREASE | KP, GI | Y | RFC XXXX | | | 0x1A1A | GREASE | KP, GI, LN | Y | RFC 9420 | | |||
+----------+-----------------------+------------+---+----------+ | +----------+-----------------------+------------+---+----------+ | |||
| 0x2A2A | GREASE | KP, GI | Y | RFC XXXX | | | 0x2A2A | GREASE | KP, GI, LN | Y | RFC 9420 | | |||
+----------+-----------------------+------------+---+----------+ | +----------+-----------------------+------------+---+----------+ | |||
| 0x3A3A | GREASE | KP, GI | Y | RFC XXXX | | | 0x3A3A | GREASE | KP, GI, LN | Y | RFC 9420 | | |||
+----------+-----------------------+------------+---+----------+ | +----------+-----------------------+------------+---+----------+ | |||
| 0x4A4A | GREASE | KP, GI | Y | RFC XXXX | | | 0x4A4A | GREASE | KP, GI, LN | Y | RFC 9420 | | |||
+----------+-----------------------+------------+---+----------+ | +----------+-----------------------+------------+---+----------+ | |||
| 0x5A5A | GREASE | KP, GI | Y | RFC XXXX | | | 0x5A5A | GREASE | KP, GI, LN | Y | RFC 9420 | | |||
+----------+-----------------------+------------+---+----------+ | +----------+-----------------------+------------+---+----------+ | |||
| 0x6A6A | GREASE | KP, GI | Y | RFC XXXX | | | 0x6A6A | GREASE | KP, GI, LN | Y | RFC 9420 | | |||
+----------+-----------------------+------------+---+----------+ | +----------+-----------------------+------------+---+----------+ | |||
| 0x7A7A | GREASE | KP, GI | Y | RFC XXXX | | | 0x7A7A | GREASE | KP, GI, LN | Y | RFC 9420 | | |||
+----------+-----------------------+------------+---+----------+ | +----------+-----------------------+------------+---+----------+ | |||
| 0x8A8A | GREASE | KP, GI | Y | RFC XXXX | | | 0x8A8A | GREASE | KP, GI, LN | Y | RFC 9420 | | |||
+----------+-----------------------+------------+---+----------+ | +----------+-----------------------+------------+---+----------+ | |||
| 0x9A9A | GREASE | KP, GI | Y | RFC XXXX | | | 0x9A9A | GREASE | KP, GI, LN | Y | RFC 9420 | | |||
+----------+-----------------------+------------+---+----------+ | +----------+-----------------------+------------+---+----------+ | |||
| 0xAAAA | GREASE | KP, GI | Y | RFC XXXX | | | 0xAAAA | GREASE | KP, GI, LN | Y | RFC 9420 | | |||
+----------+-----------------------+------------+---+----------+ | +----------+-----------------------+------------+---+----------+ | |||
| 0xBABA | GREASE | KP, GI | Y | RFC XXXX | | | 0xBABA | GREASE | KP, GI, LN | Y | RFC 9420 | | |||
+----------+-----------------------+------------+---+----------+ | +----------+-----------------------+------------+---+----------+ | |||
| 0xCACA | GREASE | KP, GI | Y | RFC XXXX | | | 0xCACA | GREASE | KP, GI, LN | Y | RFC 9420 | | |||
+----------+-----------------------+------------+---+----------+ | +----------+-----------------------+------------+---+----------+ | |||
| 0xDADA | GREASE | KP, GI | Y | RFC XXXX | | | 0xDADA | GREASE | KP, GI, LN | Y | RFC 9420 | | |||
+----------+-----------------------+------------+---+----------+ | +----------+-----------------------+------------+---+----------+ | |||
| 0xEAEA | GREASE | KP, GI | Y | RFC XXXX | | | 0xEAEA | GREASE | KP, GI, LN | Y | RFC 9420 | | |||
+----------+-----------------------+------------+---+----------+ | +----------+-----------------------+------------+---+----------+ | |||
| 0xF000 - | Reserved for Private | N/A | - | RFC XXXX | | | 0xF000 - | Reserved for Private | N/A | - | RFC 9420 | | |||
| 0xFFFF | Use | | | | | | 0xFFFF | Use | | | | | |||
+----------+-----------------------+------------+---+----------+ | +----------+-----------------------+------------+---+----------+ | |||
Table 9 | Table 9: MLS Extension Types Registry | |||
17.4. MLS Proposal Types | 17.4. MLS Proposal Types | |||
This registry lists identifiers for types of proposals that can be | The "MLS Proposal Types" registry lists identifiers for types of | |||
made for changes to an MLS group. The extension type field is two | proposals that can be made for changes to an MLS group. The | |||
bytes wide, so valid extension type values are in the range 0x0000 to | extension type field is two bytes wide, so valid extension type | |||
0xFFFF. | values are in the range 0x0000 to 0xFFFF. | |||
Template: | Template: | |||
* Value: The numeric value of the proposal type | * Value: The numeric value of the proposal type | |||
* Name: The name of the proposal type | * Name: The name of the proposal type | |||
* Recommended: Same as in Section 17.1 | * Recommended: Same as in Section 17.1 | |||
* External: Whether a proposal of this type may be sent by an | * External: Whether a proposal of this type may be sent by an | |||
external sender (see Section 12.1.8). | external sender (see Section 12.1.8) | |||
* Path Required: Whether a Commit covering a proposal of this type | * Path Required: Whether a Commit covering a proposal of this type | |||
is required to have its path field populated (see Section 12.4). | is required to have its path field populated (see Section 12.4) | |||
* Reference: The document where this extension is defined | * Reference: The document where this extension is defined | |||
Initial contents: | Initial contents: | |||
+==========+==========================+===+=====+======+==========+ | +==========+==========================+===+=====+======+==========+ | |||
| Value | Name | R | Ext | Path | Ref | | | Value | Name | R | Ext | Path | Ref | | |||
+==========+==========================+===+=====+======+==========+ | +==========+==========================+===+=====+======+==========+ | |||
| 0x0000 | RESERVED | - | - | - | RFC XXXX | | | 0x0000 | RESERVED | - | - | - | RFC 9420 | | |||
+----------+--------------------------+---+-----+------+----------+ | +----------+--------------------------+---+-----+------+----------+ | |||
| 0x0001 | add | Y | Y | N | RFC XXXX | | | 0x0001 | add | Y | Y | N | RFC 9420 | | |||
+----------+--------------------------+---+-----+------+----------+ | +----------+--------------------------+---+-----+------+----------+ | |||
| 0x0002 | update | Y | N | Y | RFC XXXX | | | 0x0002 | update | Y | N | Y | RFC 9420 | | |||
+----------+--------------------------+---+-----+------+----------+ | +----------+--------------------------+---+-----+------+----------+ | |||
| 0x0003 | remove | Y | Y | Y | RFC XXXX | | | 0x0003 | remove | Y | Y | Y | RFC 9420 | | |||
+----------+--------------------------+---+-----+------+----------+ | +----------+--------------------------+---+-----+------+----------+ | |||
| 0x0004 | psk | Y | Y | N | RFC XXXX | | | 0x0004 | psk | Y | Y | N | RFC 9420 | | |||
+----------+--------------------------+---+-----+------+----------+ | +----------+--------------------------+---+-----+------+----------+ | |||
| 0x0005 | reinit | Y | Y | N | RFC XXXX | | | 0x0005 | reinit | Y | Y | N | RFC 9420 | | |||
+----------+--------------------------+---+-----+------+----------+ | +----------+--------------------------+---+-----+------+----------+ | |||
| 0x0006 | external_init | Y | N | Y | RFC XXXX | | | 0x0006 | external_init | Y | N | Y | RFC 9420 | | |||
+----------+--------------------------+---+-----+------+----------+ | +----------+--------------------------+---+-----+------+----------+ | |||
| 0x0007 | group_context_extensions | Y | Y | Y | RFC XXXX | | | 0x0007 | group_context_extensions | Y | Y | Y | RFC 9420 | | |||
+----------+--------------------------+---+-----+------+----------+ | +----------+--------------------------+---+-----+------+----------+ | |||
| 0x0A0A | GREASE | Y | - | - | RFC XXXX | | | 0x0A0A | GREASE | Y | - | - | RFC 9420 | | |||
+----------+--------------------------+---+-----+------+----------+ | +----------+--------------------------+---+-----+------+----------+ | |||
| 0x1A1A | GREASE | Y | - | - | RFC XXXX | | | 0x1A1A | GREASE | Y | - | - | RFC 9420 | | |||
+----------+--------------------------+---+-----+------+----------+ | +----------+--------------------------+---+-----+------+----------+ | |||
| 0x2A2A | GREASE | Y | - | - | RFC XXXX | | | 0x2A2A | GREASE | Y | - | - | RFC 9420 | | |||
+----------+--------------------------+---+-----+------+----------+ | +----------+--------------------------+---+-----+------+----------+ | |||
| 0x3A3A | GREASE | Y | - | - | RFC XXXX | | | 0x3A3A | GREASE | Y | - | - | RFC 9420 | | |||
+----------+--------------------------+---+-----+------+----------+ | +----------+--------------------------+---+-----+------+----------+ | |||
| 0x4A4A | GREASE | Y | - | - | RFC XXXX | | | 0x4A4A | GREASE | Y | - | - | RFC 9420 | | |||
+----------+--------------------------+---+-----+------+----------+ | +----------+--------------------------+---+-----+------+----------+ | |||
| 0x5A5A | GREASE | Y | - | - | RFC XXXX | | | 0x5A5A | GREASE | Y | - | - | RFC 9420 | | |||
+----------+--------------------------+---+-----+------+----------+ | +----------+--------------------------+---+-----+------+----------+ | |||
| 0x6A6A | GREASE | Y | - | - | RFC XXXX | | | 0x6A6A | GREASE | Y | - | - | RFC 9420 | | |||
+----------+--------------------------+---+-----+------+----------+ | +----------+--------------------------+---+-----+------+----------+ | |||
| 0x7A7A | GREASE | Y | - | - | RFC XXXX | | | 0x7A7A | GREASE | Y | - | - | RFC 9420 | | |||
+----------+--------------------------+---+-----+------+----------+ | +----------+--------------------------+---+-----+------+----------+ | |||
| 0x8A8A | GREASE | Y | - | - | RFC XXXX | | | 0x8A8A | GREASE | Y | - | - | RFC 9420 | | |||
+----------+--------------------------+---+-----+------+----------+ | +----------+--------------------------+---+-----+------+----------+ | |||
| 0x9A9A | GREASE | Y | - | - | RFC XXXX | | | 0x9A9A | GREASE | Y | - | - | RFC 9420 | | |||
+----------+--------------------------+---+-----+------+----------+ | +----------+--------------------------+---+-----+------+----------+ | |||
| 0xAAAA | GREASE | Y | - | - | RFC XXXX | | | 0xAAAA | GREASE | Y | - | - | RFC 9420 | | |||
+----------+--------------------------+---+-----+------+----------+ | +----------+--------------------------+---+-----+------+----------+ | |||
| 0xBABA | GREASE | Y | - | - | RFC XXXX | | | 0xBABA | GREASE | Y | - | - | RFC 9420 | | |||
+----------+--------------------------+---+-----+------+----------+ | +----------+--------------------------+---+-----+------+----------+ | |||
| 0xCACA | GREASE | Y | - | - | RFC XXXX | | | 0xCACA | GREASE | Y | - | - | RFC 9420 | | |||
+----------+--------------------------+---+-----+------+----------+ | +----------+--------------------------+---+-----+------+----------+ | |||
| 0xDADA | GREASE | Y | - | - | RFC XXXX | | | 0xDADA | GREASE | Y | - | - | RFC 9420 | | |||
+----------+--------------------------+---+-----+------+----------+ | +----------+--------------------------+---+-----+------+----------+ | |||
| 0xEAEA | GREASE | Y | - | - | RFC XXXX | | | 0xEAEA | GREASE | Y | - | - | RFC 9420 | | |||
+----------+--------------------------+---+-----+------+----------+ | +----------+--------------------------+---+-----+------+----------+ | |||
| 0xF000 - | Reserved for Private Use | - | - | - | RFC XXXX | | | 0xF000 - | Reserved for Private Use | - | - | - | RFC 9420 | | |||
| 0xFFFF | | | | | | | | 0xFFFF | | | | | | | |||
+----------+--------------------------+---+-----+------+----------+ | +----------+--------------------------+---+-----+------+----------+ | |||
Table 10 | Table 10: MLS Proposal Types Registry | |||
17.5. MLS Credential Types | 17.5. MLS Credential Types | |||
This registry lists identifiers for types of credentials that can be | The "MLS Credential Types" registry lists identifiers for types of | |||
used for authentication in the MLS protocol. The credential type | credentials that can be used for authentication in the MLS protocol. | |||
field is two bytes wide, so valid credential type values are in the | The credential type field is two bytes wide, so valid credential type | |||
range 0x0000 to 0xFFFF. | values are in the range 0x0000 to 0xFFFF. | |||
Template: | Template: | |||
* Value: The numeric value of the credential type | * Value: The numeric value of the credential type | |||
* Name: The name of the credential type | * Name: The name of the credential type | |||
* Recommended: Same as in Section 17.1 | * Recommended: Same as in Section 17.1 | |||
* Reference: The document where this credential is defined | * Reference: The document where this credential is defined | |||
Initial contents: | Initial contents: | |||
+=================+==========================+===+==========+ | +=================+==========================+===+==========+ | |||
| Value | Name | R | Ref | | | Value | Name | R | Ref | | |||
+=================+==========================+===+==========+ | +=================+==========================+===+==========+ | |||
| 0x0000 | RESERVED | - | RFC XXXX | | | 0x0000 | RESERVED | - | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
| 0x0001 | basic | Y | RFC XXXX | | | 0x0001 | basic | Y | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
| 0x0002 | x509 | Y | RFC XXXX | | | 0x0002 | x509 | Y | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
| 0x0A0A | GREASE | Y | RFC XXXX | | | 0x0A0A | GREASE | Y | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
| 0x1A1A | GREASE | Y | RFC XXXX | | | 0x1A1A | GREASE | Y | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
| 0x2A2A | GREASE | Y | RFC XXXX | | | 0x2A2A | GREASE | Y | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
| 0x3A3A | GREASE | Y | RFC XXXX | | | 0x3A3A | GREASE | Y | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
| 0x4A4A | GREASE | Y | RFC XXXX | | | 0x4A4A | GREASE | Y | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
| 0x5A5A | GREASE | Y | RFC XXXX | | | 0x5A5A | GREASE | Y | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
| 0x6A6A | GREASE | Y | RFC XXXX | | | 0x6A6A | GREASE | Y | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
| 0x7A7A | GREASE | Y | RFC XXXX | | | 0x7A7A | GREASE | Y | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
| 0x8A8A | GREASE | Y | RFC XXXX | | | 0x8A8A | GREASE | Y | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
| 0x9A9A | GREASE | Y | RFC XXXX | | | 0x9A9A | GREASE | Y | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
| 0xAAAA | GREASE | Y | RFC XXXX | | | 0xAAAA | GREASE | Y | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
| 0xBABA | GREASE | Y | RFC XXXX | | | 0xBABA | GREASE | Y | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
| 0xCACA | GREASE | Y | RFC XXXX | | | 0xCACA | GREASE | Y | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
| 0xDADA | GREASE | Y | RFC XXXX | | | 0xDADA | GREASE | Y | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
| 0xEAEA | GREASE | Y | RFC XXXX | | | 0xEAEA | GREASE | Y | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
| 0xF000 - 0xFFFF | Reserved for Private Use | - | RFC XXXX | | | 0xF000 - 0xFFFF | Reserved for Private Use | - | RFC 9420 | | |||
+-----------------+--------------------------+---+----------+ | +-----------------+--------------------------+---+----------+ | |||
Table 11 | Table 11: MLS Credential Types Registry | |||
17.6. MLS Signature Labels | 17.6. MLS Signature Labels | |||
The SignWithLabel function defined in Section 5.1.2 avoids the risk | The SignWithLabel function defined in Section 5.1.2 avoids the risk | |||
of confusion between signatures in different contexts. Each context | of confusion between signatures in different contexts. Each context | |||
is assigned a distinct label that is incorporated into the signature. | is assigned a distinct label that is incorporated into the signature. | |||
This registry records the labels defined in this document, and allows | The "MLS Signature Labels" registry records the labels defined in | |||
additional labels to be registered in case extensions add other types | this document and allows additional labels to be registered in case | |||
of signature using the same signature keys used elsewhere in MLS. | extensions add other types of signatures using the same signature | |||
keys used elsewhere in MLS. | ||||
Template: | Template: | |||
* Label: The string to be used as the Label parameter to | * Label: The string to be used as the Label parameter to | |||
SignWithLabel | SignWithLabel | |||
* Recommended: Same as in Section 17.1 | * Recommended: Same as in Section 17.1 | |||
* Reference: The document where this credential is defined | * Reference: The document where this label is defined | |||
Initial contents: | Initial contents: | |||
+====================+===+==========+ | +====================+===+==========+ | |||
| Label | R | Ref | | | Label | R | Ref | | |||
+====================+===+==========+ | +====================+===+==========+ | |||
| "FramedContentTBS" | Y | RFC XXXX | | | "FramedContentTBS" | Y | RFC 9420 | | |||
+--------------------+---+----------+ | +--------------------+---+----------+ | |||
| "LeafNodeTBS" | Y | RFC XXXX | | | "LeafNodeTBS" | Y | RFC 9420 | | |||
+--------------------+---+----------+ | +--------------------+---+----------+ | |||
| "KeyPackageTBS" | Y | RFC XXXX | | | "KeyPackageTBS" | Y | RFC 9420 | | |||
+--------------------+---+----------+ | +--------------------+---+----------+ | |||
| "GroupInfoTBS" | Y | RFC XXXX | | | "GroupInfoTBS" | Y | RFC 9420 | | |||
+--------------------+---+----------+ | +--------------------+---+----------+ | |||
Table 12 | Table 12: MLS Signature Labels | |||
Registry | ||||
17.7. MLS Public Key Encryption Labels | 17.7. MLS Public Key Encryption Labels | |||
The EncryptWithLabel function defined in Section 5.1.3 avoids the | The EncryptWithLabel function defined in Section 5.1.3 avoids the | |||
risk of confusion between ciphertexts produced for different purposes | risk of confusion between ciphertexts produced for different purposes | |||
in different contexts. Each context is assigned a distinct label | in different contexts. Each context is assigned a distinct label | |||
that is incorporated into the signature. This registry records the | that is incorporated into the signature. The "MLS Public Key | |||
labels defined in this document, and allows additional labels to be | Encryption Labels" registry records the labels defined in this | |||
registered in case extensions add other types of public-key | document and allows additional labels to be registered in case | |||
encryption using the same HPKE keys used elsewhere in MLS. | extensions add other types of public key encryption using the same | |||
HPKE keys used elsewhere in MLS. | ||||
Template: | Template: | |||
* Label: The string to be used as the Label parameter to | * Label: The string to be used as the Label parameter to | |||
EncryptWithLabel | EncryptWithLabel | |||
* Recommended: Same as in Section 17.1 | * Recommended: Same as in Section 17.1 | |||
* Reference: The document where this credential is defined | * Reference: The document where this label is defined | |||
Initial contents: | Initial contents: | |||
+==================+===+==========+ | +==================+===+==========+ | |||
| Label | R | Ref | | | Label | R | Ref | | |||
+==================+===+==========+ | +==================+===+==========+ | |||
| "UpdatePathNode" | Y | RFC XXXX | | | "UpdatePathNode" | Y | RFC 9420 | | |||
+------------------+---+----------+ | +------------------+---+----------+ | |||
| "Welcome" | Y | RFC XXXX | | | "Welcome" | Y | RFC 9420 | | |||
+------------------+---+----------+ | +------------------+---+----------+ | |||
Table 13 | Table 13: MLS Public Key | |||
Encryption Labels Registry | ||||
17.8. MLS Exporter Labels | 17.8. MLS Exporter Labels | |||
The exporter function defined in Section 8.5 allows applications to | The exporter function defined in Section 8.5 allows applications to | |||
derive key material from the MLS key schedule. Like the TLS exporter | derive key material from the MLS key schedule. Like the TLS exporter | |||
[RFC8446], the MLS exporter uses a label to distinguish between | [RFC8446], the MLS exporter uses a label to distinguish between | |||
different applications' use of the exporter. This registry allows | different applications' use of the exporter. The "MLS Exporter | |||
applications to register their usage to avoid collisions. | Labels" registry allows applications to register their usage to avoid | |||
collisions. | ||||
Template: | Template: | |||
* Label: The string to be used as the Label parameter to MLS- | * Label: The string to be used as the Label parameter to MLS- | |||
Exporter | Exporter | |||
* Recommended: Same as in Section 17.1 | * Recommended: Same as in Section 17.1 | |||
* Reference: The document where this credential is defined | * Reference: The document where this label is defined | |||
The registry has no initial contents, since it is intended to be used | The registry has no initial contents, since it is intended to be used | |||
by applications, not the core protocol. The table below is intended | by applications, not the core protocol. The table below is intended | |||
only to show the column layout of the registry. | only to show the column layout of the registry. | |||
+=======+=============+===========+ | +=======+=============+===========+ | |||
| Label | Recommended | Reference | | | Label | Recommended | Reference | | |||
+=======+=============+===========+ | +=======+=============+===========+ | |||
| (N/A) | (N/A) | (N/A) | | | (N/A) | (N/A) | (N/A) | | |||
+-------+-------------+-----------+ | +-------+-------------+-----------+ | |||
Table 14 | Table 14: MLS Exporter Labels | |||
Registry | ||||
17.9. MLS Designated Expert Pool | 17.9. MLS Designated Expert Pool | |||
Specification Required [RFC8126] registry requests are registered | Specification Required [RFC8126] registry requests are registered | |||
after a three-week review period on the MLS DEs' mailing list: mls- | after a three-week review period on the MLS Designated Expert (DE) | |||
reg-review@ietf.org (mailto:mls-reg-review@ietf.org), on the advice | mailing list <mailto:mls-reg-review@ietf.org> on the advice of one or | |||
of one or more of the MLS DEs. However, to allow for the allocation | more of the MLS DEs. However, to allow for the allocation of values | |||
of values prior to publication, the MLS DEs may approve registration | prior to publication, the MLS DEs may approve registration once they | |||
once they are satisfied that such a specification will be published. | are satisfied that such a specification will be published. | |||
Registration requests sent to the MLS DEs mailing list for review | Registration requests sent to the MLS DEs' mailing list for review | |||
SHOULD use an appropriate subject (e.g., "Request to register value | SHOULD use an appropriate subject (e.g., "Request to register value | |||
in MLS Bar registry"). | in MLS Bar registry"). | |||
Within the review period, the MLS DEs will either approve or deny the | Within the review period, the MLS DEs will either approve or deny the | |||
registration request, communicating this decision to the MLS DEs | registration request, communicating this decision to the MLS DEs' | |||
mailing list and IANA. Denials SHOULD include an explanation and, if | mailing list and IANA. Denials SHOULD include an explanation and, if | |||
applicable, suggestions as to how to make the request successful. | applicable, suggestions as to how to make the request successful. | |||
Registration requests that are undetermined for a period longer than | Registration requests that are undetermined for a period longer than | |||
21 days can be brought to the IESG's attention for resolution using | 21 days can be brought to the IESG's attention for resolution using | |||
the iesg@ietf.org (mailto:iesg@ietf.org) mailing list. | the <mailto:iesg@ietf.org> mailing list. | |||
Criteria that SHOULD be applied by the MLS DEs includes determining | Criteria that SHOULD be applied by the MLS DEs includes determining | |||
whether the proposed registration duplicates existing functionality, | whether the proposed registration duplicates existing functionality, | |||
whether it is likely to be of general applicability or useful only | whether it is likely to be of general applicability or useful only | |||
for a single application, and whether the registration description is | for a single application, and whether the registration description is | |||
clear. For example, the MLS DEs will apply the ciphersuite-related | clear. For example, for cipher suite registrations, the MLS DEs will | |||
advisory found in Section 17.1. | apply the advisory found in Section 17.1. | |||
IANA MUST only accept registry updates from the MLS DEs and SHOULD | IANA MUST only accept registry updates from the MLS DEs and SHOULD | |||
direct all requests for registration to the MLS DEs' mailing list. | direct all requests for registration to the MLS DEs' mailing list. | |||
It is suggested that multiple MLS DEs be appointed who are able to | It is suggested that multiple MLS DEs who are able to represent the | |||
represent the perspectives of different applications using this | perspectives of different applications using this specification be | |||
specification, in order to enable broadly informed review of | appointed, in order to enable a broadly informed review of | |||
registration decisions. In cases where a registration decision could | registration decisions. In cases where a registration decision could | |||
be perceived as creating a conflict of interest for a particular MLS | be perceived as creating a conflict of interest for a particular MLS | |||
DE, that MLS DE SHOULD defer to the judgment of the other MLS DEs. | DE, that MLS DE SHOULD defer to the judgment of the other MLS DEs. | |||
17.10. The "message/mls" MIME Type | 17.10. The "message/mls" Media Type | |||
This document registers the "message/mls" MIME media type in order to | This document registers the "message/mls" media type in the "message" | |||
allow other protocols (e.g., HTTP [RFC9113]) to convey MLS messages. | registry in order to allow other protocols (e.g., HTTP [RFC9113]) to | |||
convey MLS messages. | ||||
Type name: message | Type name: message | |||
Subtype name: mls | Subtype name: mls | |||
Required parameters: none | Required parameters: none | |||
Optional parameters: version | Optional parameters: version | |||
version: The MLS protocol version expressed as | version: The MLS protocol version expressed as | |||
a string <major>.<minor>. If omitted the version is "1.0", | a string <major>.<minor>. If omitted, the version is "1.0", | |||
which corresponds to MLS ProtocolVersion mls10. If for some | which corresponds to MLS ProtocolVersion mls10. If for some | |||
reason the version number in the MIME type parameter differs | reason the version number in the media type parameter differs | |||
from the ProtocolVersion embedded in the protocol, the protocol | from the ProtocolVersion embedded in the protocol, the protocol | |||
takes precedence. | takes precedence. | |||
Encoding considerations: MLS messages are represented using the TLS | Encoding considerations: MLS messages are represented using the TLS | |||
presentation language [RFC8446]. Therefore MLS messages need to | presentation language [RFC8446]. Therefore, MLS messages need to | |||
be treated as binary data. | be treated as binary data. | |||
Security considerations: MLS is an encrypted messaging layer | Security considerations: MLS is an encrypted messaging layer | |||
designed to be transmitted over arbitrary lower layer protocols. | designed to be transmitted over arbitrary lower-layer protocols. | |||
The security considerations in this document (RFC XXXX) also | The security considerations in this document (RFC 9420) also | |||
apply. | apply. | |||
Interoperability considerations: N/A | Interoperability considerations: N/A | |||
Published specification: RFC XXXX | Published specification: RFC 9420 | |||
Applications that use this media type: MLS-based messaging | Applications that use this media type: MLS-based messaging | |||
applications | applications | |||
Fragment identifier considerations: N/A | Fragment identifier considerations: N/A | |||
Additional information: | Additional information: | |||
* Deprecated alias names for this type: N/A | Deprecated alias names for this type: N/A | |||
Magic number(s): N/A | ||||
* Magic number(s): N/A | File extension(s): N/A | |||
Macintosh file type code(s): N/A | ||||
* File extension(s): N/A | ||||
* Macintosh file type code(s): N/A | ||||
Person & email address to contact for further information: IETF MLS | Person & email address to contact for further information: IETF MLS | |||
Working Group mls@ietf.org (mailto:mls@ietf.org) | Working Group <mailto:mls@ietf.org> | |||
Intended usage: COMMON | Intended usage: COMMON | |||
Restrictions on usage: N/A | Restrictions on usage: N/A | |||
Author: IETF MLS Working Group | Author: IETF MLS Working Group | |||
Change controller: IESG | Change controller: IETF | |||
Provisional registration? (standards tree only): No | ||||
18. References | 18. References | |||
18.1. Normative References | 18.1. Normative References | |||
[RFC2104] Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed- | [RFC2104] Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed- | |||
Hashing for Message Authentication", RFC 2104, | Hashing for Message Authentication", RFC 2104, | |||
DOI 10.17487/RFC2104, February 1997, | DOI 10.17487/RFC2104, February 1997, | |||
<https://www.rfc-editor.org/rfc/rfc2104>. | <https://www.rfc-editor.org/info/rfc2104>. | |||
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate | [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate | |||
Requirement Levels", BCP 14, RFC 2119, | Requirement Levels", BCP 14, RFC 2119, | |||
DOI 10.17487/RFC2119, March 1997, | DOI 10.17487/RFC2119, March 1997, | |||
<https://www.rfc-editor.org/rfc/rfc2119>. | <https://www.rfc-editor.org/info/rfc2119>. | |||
[RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for | [RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for | |||
Writing an IANA Considerations Section in RFCs", BCP 26, | Writing an IANA Considerations Section in RFCs", BCP 26, | |||
RFC 8126, DOI 10.17487/RFC8126, June 2017, | RFC 8126, DOI 10.17487/RFC8126, June 2017, | |||
<https://www.rfc-editor.org/rfc/rfc8126>. | <https://www.rfc-editor.org/info/rfc8126>. | |||
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC | [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC | |||
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, | 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, | |||
May 2017, <https://www.rfc-editor.org/rfc/rfc8174>. | May 2017, <https://www.rfc-editor.org/info/rfc8174>. | |||
[RFC8446] Rescorla, E., "The Transport Layer Security (TLS) Protocol | [RFC8446] Rescorla, E., "The Transport Layer Security (TLS) Protocol | |||
Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018, | Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018, | |||
<https://www.rfc-editor.org/rfc/rfc8446>. | <https://www.rfc-editor.org/info/rfc8446>. | |||
[RFC9180] Barnes, R., Bhargavan, K., Lipp, B., and C. Wood, "Hybrid | [RFC9180] Barnes, R., Bhargavan, K., Lipp, B., and C. Wood, "Hybrid | |||
Public Key Encryption", RFC 9180, DOI 10.17487/RFC9180, | Public Key Encryption", RFC 9180, DOI 10.17487/RFC9180, | |||
February 2022, <https://www.rfc-editor.org/rfc/rfc9180>. | February 2022, <https://www.rfc-editor.org/info/rfc9180>. | |||
18.2. Informative References | 18.2. Informative References | |||
[ART] Cohn-Gordon, K., Cremers, C., Garratt, L., Millican, J., | [ART] Cohn-Gordon, K., Cremers, C., Garratt, L., Millican, J., | |||
and K. Milner, "On Ends-to-Ends Encryption: Asynchronous | and K. Milner, "On Ends-to-Ends Encryption: Asynchronous | |||
Group Messaging with Strong Security Guarantees", 18 | Group Messaging with Strong Security Guarantees", Version | |||
January 2018, <https://eprint.iacr.org/2017/666.pdf>. | 2.3, DOI 10.1145/3243734.3243747, March 2020, | |||
<https://eprint.iacr.org/2017/666.pdf>. | ||||
[CFRG-AEAD-LIMITS] | ||||
Günther, F., Thomson, M., and C. A. Wood, "Usage Limits on | ||||
AEAD Algorithms", Work in Progress, Internet-Draft, draft- | ||||
irtf-cfrg-aead-limits-07, 31 May 2023, | ||||
<https://datatracker.ietf.org/doc/html/draft-irtf-cfrg- | ||||
aead-limits-07>. | ||||
[CLINIC] Miller, B., Huang, L., Joseph, A., and J. Tygar, "I Know | [CLINIC] Miller, B., Huang, L., Joseph, A., and J. Tygar, "I Know | |||
Why You Went to the Clinic: Risks and Realization of HTTPS | Why You Went to the Clinic: Risks and Realization of HTTPS | |||
Traffic Analysis", Privacy Enhancing Technologies pp. | Traffic Analysis", Privacy Enhancing Technologies, pp. | |||
143-163, DOI 10.1007/978-3-319-08506-7_8, 2014, | 143-163, DOI 10.1007/978-3-319-08506-7_8, 2014, | |||
<https://doi.org/10.1007/978-3-319-08506-7_8>. | <https://doi.org/10.1007/978-3-319-08506-7_8>. | |||
[CONIKS] Melara, M. S., Blankstein, A., Bonneau, J., Felten, E. W., | [CONIKS] Melara, M. S., Blankstein, A., Bonneau, J., Felten, E. W., | |||
and M. J. Freedman, "CONIKS: Bringing Key Transparency to | and M. J. Freedman, "CONIKS: Bringing Key Transparency to | |||
End Users", 2015, | End Users", Proceedings of the 24th USENIX Security | |||
Symposium, ISBN 978-1-939133-11-3, August 2015, | ||||
<https://www.usenix.org/system/files/conference/ | <https://www.usenix.org/system/files/conference/ | |||
usenixsecurity15/sec15-paper-melara.pdf>. | usenixsecurity15/sec15-paper-melara.pdf>. | |||
[DoubleRatchet] | [DoubleRatchet] | |||
Cohn-Gordon, K., Cremers, C., Dowling, B., Garratt, L., | Cohn-Gordon, K., Cremers, C., Dowling, B., Garratt, L., | |||
and D. Stebila, "A Formal Security Analysis of the Signal | and D. Stebila, "A Formal Security Analysis of the Signal | |||
Messaging Protocol", 2017 IEEE European Symposium on | Messaging Protocol", 2017 IEEE European Symposium on | |||
Security and Privacy (EuroS&P), | Security and Privacy (EuroS&P), | |||
DOI 10.1109/eurosp.2017.27, April 2017, | DOI 10.1109/eurosp.2017.27, April 2017, | |||
<https://doi.org/10.1109/eurosp.2017.27>. | <https://doi.org/10.1109/eurosp.2017.27>. | |||
[HCJ16] Husák, M., Čermák, M., Jirsík, T., and P. Čeleda, "HTTPS | [HCJ16] Husák, M., Čermák, M., Jirsík, T., and P. Čeleda, "HTTPS | |||
traffic analysis and client identification using passive | traffic analysis and client identification using passive | |||
SSL/TLS fingerprinting", EURASIP Journal on Information | SSL/TLS fingerprinting", EURASIP Journal on Information | |||
Security vol. 2016, no. 1, DOI 10.1186/s13635-016-0030-7, | Security, Vol. 2016, Issue 1, | |||
February 2016, | DOI 10.1186/s13635-016-0030-7, February 2016, | |||
<https://doi.org/10.1186/s13635-016-0030-7>. | <https://doi.org/10.1186/s13635-016-0030-7>. | |||
[I-D.ietf-mls-architecture] | [KT] "Key Transparency Design Doc", commit fb0f87f, June 2020, | |||
Beurdouche, B., Rescorla, E., Omara, E., Inguva, S., and | <https://github.com/google/keytransparency/blob/master/ | |||
docs/design.md>. | ||||
[MLS-ARCH] Beurdouche, B., Rescorla, E., Omara, E., Inguva, S., and | ||||
A. Duric, "The Messaging Layer Security (MLS) | A. Duric, "The Messaging Layer Security (MLS) | |||
Architecture", Work in Progress, Internet-Draft, draft- | Architecture", Work in Progress, Internet-Draft, draft- | |||
ietf-mls-architecture-10, 16 December 2022, | ietf-mls-architecture-10, 16 December 2022, | |||
<https://datatracker.ietf.org/doc/html/draft-ietf-mls- | <https://datatracker.ietf.org/doc/html/draft-ietf-mls- | |||
architecture-10>. | architecture-10>. | |||
[I-D.irtf-cfrg-aead-limits] | ||||
Günther, F., Thomson, M., and C. A. Wood, "Usage Limits on | ||||
AEAD Algorithms", Work in Progress, Internet-Draft, draft- | ||||
irtf-cfrg-aead-limits-06, 30 January 2023, | ||||
<https://datatracker.ietf.org/doc/html/draft-irtf-cfrg- | ||||
aead-limits-06>. | ||||
[KT] "Key Transparency Design Doc", 26 June 2020, | ||||
<https://github.com/google/keytransparency/blob/master/ | ||||
docs/design.md>. | ||||
[NAN] Bellare, M., Ng, R., and B. Tackmann, "Nonces Are Noticed: | [NAN] Bellare, M., Ng, R., and B. Tackmann, "Nonces Are Noticed: | |||
AEAD Revisited", Advances in Cryptology - CRYPTO 2019 pp. | AEAD Revisited", Advances in Cryptology - CRYPTO 2019, pp. | |||
235-265, DOI 10.1007/978-3-030-26948-7_9, 2019, | 235-265, DOI 10.1007/978-3-030-26948-7_9, August 2019, | |||
<https://doi.org/10.1007/978-3-030-26948-7_9>. | <https://doi.org/10.1007/978-3-030-26948-7_9>. | |||
[RFC5116] McGrew, D., "An Interface and Algorithms for Authenticated | [RFC5116] McGrew, D., "An Interface and Algorithms for Authenticated | |||
Encryption", RFC 5116, DOI 10.17487/RFC5116, January 2008, | Encryption", RFC 5116, DOI 10.17487/RFC5116, January 2008, | |||
<https://www.rfc-editor.org/rfc/rfc5116>. | <https://www.rfc-editor.org/info/rfc5116>. | |||
[RFC5905] Mills, D., Martin, J., Ed., Burbank, J., and W. Kasch, | [RFC5905] Mills, D., Martin, J., Ed., Burbank, J., and W. Kasch, | |||
"Network Time Protocol Version 4: Protocol and Algorithms | "Network Time Protocol Version 4: Protocol and Algorithms | |||
Specification", RFC 5905, DOI 10.17487/RFC5905, June 2010, | Specification", RFC 5905, DOI 10.17487/RFC5905, June 2010, | |||
<https://www.rfc-editor.org/rfc/rfc5905>. | <https://www.rfc-editor.org/info/rfc5905>. | |||
[RFC6125] Saint-Andre, P. and J. Hodges, "Representation and | [RFC6125] Saint-Andre, P. and J. Hodges, "Representation and | |||
Verification of Domain-Based Application Service Identity | Verification of Domain-Based Application Service Identity | |||
within Internet Public Key Infrastructure Using X.509 | within Internet Public Key Infrastructure Using X.509 | |||
(PKIX) Certificates in the Context of Transport Layer | (PKIX) Certificates in the Context of Transport Layer | |||
Security (TLS)", RFC 6125, DOI 10.17487/RFC6125, March | Security (TLS)", RFC 6125, DOI 10.17487/RFC6125, March | |||
2011, <https://www.rfc-editor.org/rfc/rfc6125>. | 2011, <https://www.rfc-editor.org/info/rfc6125>. | |||
[RFC7696] Housley, R., "Guidelines for Cryptographic Algorithm | [RFC7696] Housley, R., "Guidelines for Cryptographic Algorithm | |||
Agility and Selecting Mandatory-to-Implement Algorithms", | Agility and Selecting Mandatory-to-Implement Algorithms", | |||
BCP 201, RFC 7696, DOI 10.17487/RFC7696, November 2015, | BCP 201, RFC 7696, DOI 10.17487/RFC7696, November 2015, | |||
<https://www.rfc-editor.org/rfc/rfc7696>. | <https://www.rfc-editor.org/info/rfc7696>. | |||
[RFC8032] Josefsson, S. and I. Liusvaara, "Edwards-Curve Digital | [RFC8032] Josefsson, S. and I. Liusvaara, "Edwards-Curve Digital | |||
Signature Algorithm (EdDSA)", RFC 8032, | Signature Algorithm (EdDSA)", RFC 8032, | |||
DOI 10.17487/RFC8032, January 2017, | DOI 10.17487/RFC8032, January 2017, | |||
<https://www.rfc-editor.org/rfc/rfc8032>. | <https://www.rfc-editor.org/info/rfc8032>. | |||
[RFC8701] Benjamin, D., "Applying Generate Random Extensions And | [RFC8701] Benjamin, D., "Applying Generate Random Extensions And | |||
Sustain Extensibility (GREASE) to TLS Extensibility", | Sustain Extensibility (GREASE) to TLS Extensibility", | |||
RFC 8701, DOI 10.17487/RFC8701, January 2020, | RFC 8701, DOI 10.17487/RFC8701, January 2020, | |||
<https://www.rfc-editor.org/rfc/rfc8701>. | <https://www.rfc-editor.org/info/rfc8701>. | |||
[RFC9000] Iyengar, J., Ed. and M. Thomson, Ed., "QUIC: A UDP-Based | [RFC9000] Iyengar, J., Ed. and M. Thomson, Ed., "QUIC: A UDP-Based | |||
Multiplexed and Secure Transport", RFC 9000, | Multiplexed and Secure Transport", RFC 9000, | |||
DOI 10.17487/RFC9000, May 2021, | DOI 10.17487/RFC9000, May 2021, | |||
<https://www.rfc-editor.org/rfc/rfc9000>. | <https://www.rfc-editor.org/info/rfc9000>. | |||
[RFC9001] Thomson, M., Ed. and S. Turner, Ed., "Using TLS to Secure | [RFC9001] Thomson, M., Ed. and S. Turner, Ed., "Using TLS to Secure | |||
QUIC", RFC 9001, DOI 10.17487/RFC9001, May 2021, | QUIC", RFC 9001, DOI 10.17487/RFC9001, May 2021, | |||
<https://www.rfc-editor.org/rfc/rfc9001>. | <https://www.rfc-editor.org/info/rfc9001>. | |||
[RFC9113] Thomson, M., Ed. and C. Benfield, Ed., "HTTP/2", RFC 9113, | [RFC9113] Thomson, M., Ed. and C. Benfield, Ed., "HTTP/2", RFC 9113, | |||
DOI 10.17487/RFC9113, June 2022, | DOI 10.17487/RFC9113, June 2022, | |||
<https://www.rfc-editor.org/rfc/rfc9113>. | <https://www.rfc-editor.org/info/rfc9113>. | |||
[SHS] Dang, Q., "Secure Hash Standard", National Institute of | [SHS] National Institute of Standards and Technology (NIST), | |||
Standards and Technology report, | "Secure Hash Standard (SHS)", FIPS PUB 180-4, | |||
DOI 10.6028/nist.fips.180-4, July 2015, | DOI 10.6028/NIST.FIPS.180-4, August 2015, | |||
<https://doi.org/10.6028/nist.fips.180-4>. | <https://doi.org/10.6028/NIST.FIPS.180-4>. | |||
[Signal] Perrin(ed), T. and M. Marlinspike, "The Double Ratchet | [Signal] Perrin(ed), T. and M. Marlinspike, "The Double Ratchet | |||
Algorithm", 20 November 2016, | Algorithm", Revision 1, November 2016, | |||
<https://www.signal.org/docs/specifications/ | <https://www.signal.org/docs/specifications/ | |||
doubleratchet/>. | doubleratchet/>. | |||
Appendix A. Protocol Origins of Example Trees | Appendix A. Protocol Origins of Example Trees | |||
Protocol operations in MLS give rise to specific forms of ratchet | Protocol operations in MLS give rise to specific forms of ratchet | |||
tree, typically affecting a whole direct path at once. In this | tree, typically affecting a whole direct path at once. In this | |||
section, we describe the protocol operations that could have given | section, we describe the protocol operations that could have given | |||
rise to the various example trees in this document. | rise to the various example trees in this document. | |||
To construct the tree in Figure 11: | To construct the tree in Figure 11: | |||
* A creates a group with B, ..., G | * A creates a group with B, ..., G | |||
* F sends an empty Commit, setting X, Y, W | * F sends an empty Commit, setting X, Y, and W | |||
* G removes C and D, blanking V, U, and setting Y, W | * G removes C and D, blanking V, U, and setting Y and W | |||
* B sends an empty Commit, setting T and W | * B sends an empty Commit, setting T and W | |||
To construct the tree in Figure 10: | To construct the tree in Figure 10: | |||
* A creates a group with B, ..., H, as well as some members outside | * A creates a group with B, ..., H, as well as some members outside | |||
this subtree | this subtree | |||
* F sends an empty Commit, setting Y and its ancestors | * F sends an empty Commit, setting Y and its ancestors | |||
skipping to change at page 153, line 49 ¶ | skipping to change at line 6571 ¶ | |||
of D | of D | |||
* Someone outside this subtree removes G, blanking the direct path | * Someone outside this subtree removes G, blanking the direct path | |||
of G | of G | |||
* A adds a new member at B with a partial Commit, adding B as | * A adds a new member at B with a partial Commit, adding B as | |||
unmerged at X | unmerged at X | |||
To construct the tree in Figure 13: | To construct the tree in Figure 13: | |||
* A creates a group with B, C, D | * A creates a group with B, C, and D | |||
* B sends a full Commit, setting X and Y | * B sends a full Commit, setting X and Y | |||
* D removes C, setting Z and Y | * D removes C, setting Z and Y | |||
* B adds a new member at C with a full Commit | * B adds a new member at C with a full Commit | |||
- The Add proposal adds C as unmerged at Z and Y | - The Add proposal adds C as unmerged at Z and Y | |||
- The path in the Commit resets X and Y, clearing Y's unmerged | - The path in the Commit resets X and Y, clearing Y's unmerged | |||
leaves | leaves | |||
To construct the tree in Figure 21: | To construct the tree in Figure 21: | |||
skipping to change at page 154, line 36 ¶ | skipping to change at line 6607 ¶ | |||
To better understand how parent hashes are maintained, let's look in | To better understand how parent hashes are maintained, let's look in | |||
detail at how they evolve in a small group. Consider the following | detail at how they evolve in a small group. Consider the following | |||
sequence of operations: | sequence of operations: | |||
1. A initializes a new group | 1. A initializes a new group | |||
2. A adds B to the group with a full Commit | 2. A adds B to the group with a full Commit | |||
3. B adds C and D to the group with a full Commit | 3. B adds C and D to the group with a full Commit | |||
4. C sends an empty Commit. | 4. C sends an empty Commit | |||
Y Y' | Y Y' | |||
| | | | | | |||
.-+-. .-+-. | .-+-. .-+-. | |||
==> ==> / \ ==> / \ | ==> ==> / \ ==> / \ | |||
X X' _=Z X' Z' | X X' _=Z X' Z' | |||
/ \ / \ / \ / \ / \ | / \ / \ / \ / \ / \ | |||
A A B A B C D A B C D | A A B A B C D A B C D | |||
Figure 30: Building a four-member tree to illustrate parent hashes | Figure 30: Building a Four-Member Tree to Illustrate Parent Hashes | |||
Then the parent hashes associated to the nodes will be updated as | Then the parent hashes associated to the nodes will be updated as | |||
follows (where we use the shorthand ph for parent hash, th for tree | follows (where we use the shorthand ph for parent hash, th for tree | |||
hash, and osth for original sibling tree hash): | hash, and osth for original sibling tree hash): | |||
1. A adds B: set X | 1. A adds B: set X | |||
* A.parent_hash = ph(X) = H(X, ph="", osth=th(B)) | * A.parent_hash = ph(X) = H(X, ph="", osth=th(B)) | |||
2. B adds C, D: set B', X', Y | 2. B adds C, D: set B', X', and Y | |||
* X'.parent_hash = ph(Y) = H(Y, ph="", osth=th(Z)), where th(Z) | * X'.parent_hash = ph(Y) = H(Y, ph="", osth=th(Z)), where th(Z) | |||
covers (C, _, D) | covers (C, _, D) | |||
* B'.parent_hash = ph(X') = H(X', ph=X'.parent_hash, osth=th(A)) | * B'.parent_hash = ph(X') = H(X', ph=X'.parent_hash, osth=th(A)) | |||
3. C sends empty Commit: set C', Z', Y' | 3. C sends empty Commit: set C', Z', Y' | |||
* Z'.parent_hash = ph(Y') = H(Y', ph="", osth=th(X')), where | * Z'.parent_hash = ph(Y') = H(Y', ph="", osth=th(X')), where | |||
th(X') covers (A, X', B') | th(X') covers (A, X', B') | |||
* C'.parent_hash = ph(Z') = H(Z', ph=Z'.parent_hash, osth=th(D)) | * C'.parent_hash = ph(Z') = H(Z', ph=Z'.parent_hash, osth=th(D)) | |||
When a new member joins, they will receive a tree that has the | When a new member joins, they will receive a tree that has the | |||
following parent hash values, and compute the indicated parent-hash | following parent hash values and compute the indicated parent hash | |||
validity relationships: | validity relationships: | |||
+======+======================================+=====================+ | +======+======================================+=====================+ | |||
| Node | Parent hash value | Valid? | | | Node | Parent Hash Value | Valid? | | |||
+======+======================================+=====================+ | +======+======================================+=====================+ | |||
| A | H(X, ph="", osth=th(B)) | No, B changed | | | A | H(X, ph="", osth=th(B)) | No, B changed | | |||
+------+--------------------------------------+---------------------+ | +------+--------------------------------------+---------------------+ | |||
| B' | H(X', ph=X'.parent_hash, osth=th(A)) | Yes | | | B' | H(X', ph=X'.parent_hash, osth=th(A)) | Yes | | |||
+------+--------------------------------------+---------------------+ | +------+--------------------------------------+---------------------+ | |||
| C' | H(Z', ph=Z'.parent_hash, osth=th(D)) | Yes | | | C' | H(Z', ph=Z'.parent_hash, osth=th(D)) | Yes | | |||
+------+--------------------------------------+---------------------+ | +------+--------------------------------------+---------------------+ | |||
| D | (none, never sent an UpdatePath) | N/A | | | D | (none, never sent an UpdatePath) | N/A | | |||
+------+--------------------------------------+---------------------+ | +------+--------------------------------------+---------------------+ | |||
| X' | H(Y, ph="", osth=th(Z)) | No, Y and Z | | | X' | H(Y, ph="", osth=th(Z)) | No, Y and Z | | |||
skipping to change at page 156, line 22 ¶ | skipping to change at line 6684 ¶ | |||
Figure 31: Parent-hash links connect all non-empty parent nodes | Figure 31: Parent-hash links connect all non-empty parent nodes | |||
to leaves | to leaves | |||
Since these chains collectively cover all non-blank parent nodes in | Since these chains collectively cover all non-blank parent nodes in | |||
the tree, the tree is parent-hash valid. | the tree, the tree is parent-hash valid. | |||
Note that this tree, though valid, contains invalid parent-hash | Note that this tree, though valid, contains invalid parent-hash | |||
links. If a client were checking parent hashes top-down from Y', for | links. If a client were checking parent hashes top-down from Y', for | |||
example, they would find that X' has an invalid parent hash relative | example, they would find that X' has an invalid parent hash relative | |||
to Y', but that Z' has valid parent hash. Likewise, if the client | to Y', but that Z' has a valid parent hash. Likewise, if the client | |||
were checking bottom-up, they would find that the chain from B' ends | were checking bottom-up, they would find that the chain from B' ends | |||
in an invalid link from X' to Y'. These invalid links are the | in an invalid link from X' to Y'. These invalid links are the | |||
natural result of multiple clients having committed. | natural result of multiple clients having committed. | |||
Note also the way the tree hash and the parent hash interact. The | Note also the way the tree hash and the parent hash interact. The | |||
parent hash of node C' includes the tree hash of node D. The parent | parent hash of node C' includes the tree hash of node D. The parent | |||
hash of node Z' includes the tree hash of X', which covers nodes A | hash of node Z' includes the tree hash of X', which covers nodes A | |||
and B' (including the parent hash of B'). Although the tree hash and | and B' (including the parent hash of B'). Although the tree hash and | |||
the parent hash depend on each other, the dependency relationships | the parent hash depend on each other, the dependency relationships | |||
are structured so that there's never a circular dependency. | are structured so that there is never a circular dependency. | |||
In the particular case where a new member first receives the tree for | In the particular case where a new member first receives the tree for | |||
a group (e.g., in a ratchet tree GroupInfo extension | a group (e.g., in a ratchet tree GroupInfo extension | |||
Section 12.4.3.3), the parent hashes will be expressed in the tree | Section 12.4.3.3), the parent hashes will be expressed in the tree | |||
representation, but the tree hash need not be. Instead, the new | representation, but the tree hash need not be. Instead, the new | |||
member will recompute the tree hashes for all the nodes in the tree, | member will recompute the tree hashes for all the nodes in the tree, | |||
verifying that this matches the tree hash in the GroupInfo object. | verifying that this matches the tree hash in the GroupInfo object. | |||
Then, if the tree is valid, then the subtree hashes computed in this | If the tree is valid, then the subtree hashes computed in this way | |||
way will align with the inputs needed for parent hash validation | will align with the inputs needed for parent hash validation (except | |||
(except where recomputation is needed to account for unmerged | where recomputation is needed to account for unmerged leaves). | |||
leaves). | ||||
Appendix C. Array-Based Trees | Appendix C. Array-Based Trees | |||
One benefit of using complete balanced trees is that they admit a | One benefit of using complete balanced trees is that they admit a | |||
simple flat array representation. In this representation, leaf nodes | simple flat array representation. In this representation, leaf nodes | |||
are even-numbered nodes, with the n-th leaf at 2*n. Intermediate | are even-numbered nodes, with the n-th leaf at 2*n. Intermediate | |||
nodes are held in odd-numbered nodes. For example, the tree with 8 | nodes are held in odd-numbered nodes. For example, the tree with 8 | |||
leaves has the following structure: | leaves has the following structure: | |||
X | X | |||
skipping to change at page 157, line 22 ¶ | skipping to change at line 6731 ¶ | |||
/ \ / \ | / \ / \ | |||
X X X X | X X X X | |||
/ \ / \ / \ / \ | / \ / \ / \ / \ | |||
/ \ / \ / \ / \ | / \ / \ / \ / \ | |||
X X X X X X X X | X X X X X X X X | |||
Node: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | Node: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |||
Leaf: 0 1 2 3 4 5 6 7 | Leaf: 0 1 2 3 4 5 6 7 | |||
Figure 32: An 8-member tree represented as an array | Figure 32: An Eight-Member Tree Represented as an Array | |||
This allows us to compute relationships between tree nodes simply by | This allows us to compute relationships between tree nodes simply by | |||
manipulating indices, rather than having to maintain complicated | manipulating indices, rather than having to maintain complicated | |||
structures in memory. The basic rule is that the high-order bits of | structures in memory. The basic rule is that the high-order bits of | |||
parent and child nodes indices have the following relation (where x | parent and child nodes indices have the following relation (where x | |||
is an arbitrary bit string): | is an arbitrary bit string): | |||
parent=01x => left=00x, right=10x | parent=01x => left=00x, right=10x | |||
Since node relationships are implicit, the algorithms for adding and | Since node relationships are implicit, the algorithms for adding and | |||
skipping to change at page 160, line 4 ¶ | skipping to change at line 6860 ¶ | |||
return min(dxy, key=level) | return min(dxy, key=level) | |||
# The common ancestor of two nodes is the lowest node that is in the | # The common ancestor of two nodes is the lowest node that is in the | |||
# direct paths of both leaves. | # direct paths of both leaves. | |||
def common_ancestor_direct(x, y, _): | def common_ancestor_direct(x, y, _): | |||
# Handle cases where one is an ancestor of the other | # Handle cases where one is an ancestor of the other | |||
lx, ly = level(x)+1, level(y)+1 | lx, ly = level(x)+1, level(y)+1 | |||
if (lx <= ly) and (x>>ly == y>>ly): | if (lx <= ly) and (x>>ly == y>>ly): | |||
return y | return y | |||
elif (ly <= lx) and (x>>lx == y>>lx): | elif (ly <= lx) and (x>>lx == y>>lx): | |||
return x | return x | |||
# Handle other cases | # Handle other cases | |||
xn, yn = x, y | xn, yn = x, y | |||
k = 0 | k = 0 | |||
while xn != yn: | while xn != yn: | |||
xn, yn = xn >> 1, yn >> 1 | xn, yn = xn >> 1, yn >> 1 | |||
k += 1 | k += 1 | |||
return (xn << k) + (1 << (k-1)) - 1 | return (xn << k) + (1 << (k-1)) - 1 | |||
Appendix D. Link-Based Trees | Appendix D. Link-Based Trees | |||
An implementation may choose to store ratchet trees in a "link-based" | An implementation may choose to store ratchet trees in a "link-based" | |||
representation, where each node stores references to its parents and/ | representation, where each node stores references to its parents and/ | |||
or children. (As opposed to the array-based representation suggested | or children (as opposed to the array-based representation suggested | |||
above, where these relationships are computed from relationships | above, where these relationships are computed from relationships | |||
between nodes' indices in the array.) Such an implementation needs | between nodes' indices in the array). Such an implementation needs | |||
to update these links to maintain the balanced structure of the tree | to update these links to maintain the balanced structure of the tree | |||
as the tree is extended to add new members, or truncated when members | as the tree is extended to add new members or truncated when members | |||
are removed. | are removed. | |||
The following code snippet shows how these algorithms could be | The following code snippet shows how these algorithms could be | |||
implemented in Python. | implemented in Python. | |||
class Node: | class Node: | |||
def __init__(self, value, left=None, right=None): | def __init__(self, value, left=None, right=None): | |||
self.value = value # Value of the node | self.value = value # Value of the node | |||
self.left = left # Left child node | self.left = left # Left child node | |||
self.right = right # Right child node | self.right = right # Right child node | |||
skipping to change at page 161, line 22 ¶ | skipping to change at line 6902 ¶ | |||
def blank_subtree(depth): | def blank_subtree(depth): | |||
if depth == 1: | if depth == 1: | |||
return Node(None) | return Node(None) | |||
L = Node.blank_subtree(depth-1) | L = Node.blank_subtree(depth-1) | |||
R = Node.blank_subtree(depth-1) | R = Node.blank_subtree(depth-1) | |||
return Node(None, left=L, right=R) | return Node(None, left=L, right=R) | |||
def empty(self): | def empty(self): | |||
L_empty = (self.left == None) or self.left.empty() | L_empty = (self.left == None) or self.left.empty() | |||
R_empty = (self.left == None) or self.left.empty() | R_empty = (self.right == None) or self.right.empty() | |||
return (self.value == None) and L_empty and R_empty | return (self.value == None) and L_empty and R_empty | |||
class Tree: | class Tree: | |||
def __init__(self): | def __init__(self): | |||
self.depth = 0 # Depth of the tree | self.depth = 0 # Depth of the tree | |||
self.root = None # Root node of the tree, initially empty | self.root = None # Root node of the tree, initially empty | |||
# Add a blank subtree to the right | # Add a blank subtree to the right | |||
def extend(self): | def extend(self): | |||
if self.depth == 0: | if self.depth == 0: | |||
self.depth = 1 | self.depth = 1 | |||
self.root = Node(None) | self.root = Node(None) | |||
L = self.root | L = self.root | |||
R = Node.blank_subtree(self.depth) | R = Node.blank_subtree(self.depth) | |||
self.root = Node(None, left=L, right=R) | self.root = Node(None, left=L, right=R) | |||
self.depth += 1 | self.depth += 1 | |||
# Truncate the right subtree | # Truncate the right subtree | |||
def truncate(self): | def truncate(self): | |||
if self.root == None or self.root.right == None: | if self.root == None: | |||
raise Exception("Cannot truncate a tree with 0 or 1 nodes") | return | |||
if not self.root.right.empty(): | if not self.root.right.empty(): | |||
raise Exception("Cannot truncate non-blank subtree") | raise Exception("Cannot truncate non-blank subtree") | |||
self.depth -= 1 | self.depth -= 1 | |||
self.root = self.root.left | self.root = self.root.left | |||
Contributors | Contributors | |||
Joel Alwen | Joel Alwen | |||
skipping to change at page 164, line 4 ¶ | skipping to change at line 7009 ¶ | |||
Inria & Mozilla | Inria & Mozilla | |||
Email: ietf@beurdouche.com | Email: ietf@beurdouche.com | |||
Raphael Robert | Raphael Robert | |||
Phoenix R&D | Phoenix R&D | |||
Email: ietf@raphaelrobert.com | Email: ietf@raphaelrobert.com | |||
Jon Millican | Jon Millican | |||
Meta Platforms | Meta Platforms | |||
Email: jmillican@meta.com | Email: jmillican@meta.com | |||
Emad Omara | Emad Omara | |||
Email: emad.omara@gmail.com | ||||
Email: emadomara@google.com | ||||
Katriel Cohn-Gordon | Katriel Cohn-Gordon | |||
University of Oxford | University of Oxford | |||
Email: me@katriel.co.uk | Email: me@katriel.co.uk | |||
End of changes. 556 change blocks. | ||||
1553 lines changed or deleted | 1150 lines changed or added | |||
This html diff was produced by rfcdiff 1.48. |