| 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. | ||||