1 // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 // Copyright by contributors to this project.
3 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
4 
5 //! An implementation of the [IETF Messaging Layer Security](https://messaginglayersecurity.rocks)
6 //! end-to-end encryption (E2EE) protocol.
7 //!
8 //! ## What is MLS?
9 //!
10 //! MLS is a new IETF end-to-end encryption standard that is designed to
11 //! provide transport agnostic, asynchronous, and highly performant
12 //! communication between a group of clients.
13 //!
14 //! ## MLS Protocol Features
15 //!
16 //! - Multi-party E2EE [group evolution](https://www.rfc-editor.org/rfc/rfc9420.html#name-cryptographic-state-and-evo)
17 //! via a propose-then-commit mechanism.
18 //! - Asynchronous by design with pre-computed [key packages](https://www.rfc-editor.org/rfc/rfc9420.html#name-key-packages),
19 //!   allowing members to be added to a group while offline.
20 //! - Customizable credential system with built in support for X.509 certificates.
21 //! - [Extension system](https://www.rfc-editor.org/rfc/rfc9420.html#name-extensions)
22 //!   allowing for application specific data to be negotiated via the protocol.
23 //! - Strong forward secrecy and post compromise security.
24 //! - Crypto agility via support for multiple [cipher suites](https://www.rfc-editor.org/rfc/rfc9420.html#name-cipher-suites).
25 //! - Pre-shared key support.
26 //! - Subgroup branching.
27 //! - Group reinitialization for breaking changes such as protocol upgrades.
28 //!
29 //! ## Features
30 //!
31 //! - Easy to use client interface that can manage multiple MLS identities and groups.
32 //! - 100% RFC 9420 conformance with support for all default credential, proposal,
33 //!   and extension types.
34 //! - Support for WASM builds.
35 //! - Configurable storage for key packages, secrets and group state
36 //!   via traits along with provided "in memory" and SQLite implementations.
37 //! - Support for custom user proposal and extension types.
38 //! - Ability to create user defined credentials with custom validation
39 //!   routines that can bridge to existing credential schemes.
40 //! - OpenSSL and Rust Crypto based cipher suite implementations.
41 //! - Crypto agility with support for user defined cipher suite.
42 //! - Extensive test suite including security and interop focused tests against
43 //!   pre-computed test vectors.
44 //!
45 //! ## Crypto Providers
46 //!
47 //! For cipher suite descriptions see the RFC documentation [here](https://www.rfc-editor.org/rfc/rfc9420.html#name-mls-cipher-suites)
48 //!
49 //! | Name | Cipher Suites | X509 Support |
50 //! |------|---------------|--------------|
51 //! | OpenSSL | 1-7 | Stable |
52 //! | AWS-LC | 1,2,3,5,7 | Stable |
53 //! | Rust Crypto | 1,2,3 | ⚠️ Experimental |
54 //!
55 //! ## Security Notice
56 //!
57 //! This library has been validated for conformance to the RFC 9420 specification but has not yet received a full security audit by a 3rd party.
58 
59 #![allow(clippy::enum_variant_names)]
60 #![allow(clippy::result_large_err)]
61 #![allow(clippy::nonstandard_macro_braces)]
62 #![cfg_attr(not(feature = "std"), no_std)]
63 #![cfg_attr(docsrs, feature(doc_cfg))]
64 #![cfg_attr(coverage_nightly, feature(coverage_attribute))]
65 extern crate alloc;
66 
67 #[cfg(all(test, target_arch = "wasm32"))]
68 wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
69 
70 #[cfg(all(test, target_arch = "wasm32"))]
71 use wasm_bindgen_test::wasm_bindgen_test as futures_test;
72 
73 #[cfg(all(test, mls_build_async, not(target_arch = "wasm32")))]
74 use futures_test::test as futures_test;
75 
76 #[cfg(test)]
77 macro_rules! hex {
78     ($input:literal) => {
79         hex::decode($input).expect("invalid hex value")
80     };
81 }
82 
83 #[cfg(test)]
84 macro_rules! load_test_case_json {
85     ($name:ident, $generate:expr) => {
86         load_test_case_json!($name, $generate, to_vec_pretty)
87     };
88     ($name:ident, $generate:expr, $to_json:ident) => {{
89         #[cfg(any(target_arch = "wasm32", not(feature = "std")))]
90         {
91             // Do not remove `async`! (The goal of this line is to remove warnings
92             // about `$generate` not being used. Actually calling it will make tests fail.)
93             let _ = async { $generate };
94             serde_json::from_slice(include_bytes!(concat!(
95                 env!("CARGO_MANIFEST_DIR"),
96                 "/test_data/",
97                 stringify!($name),
98                 ".json"
99             )))
100             .unwrap()
101         }
102 
103         #[cfg(all(not(target_arch = "wasm32"), feature = "std"))]
104         {
105             let path = concat!(
106                 env!("CARGO_MANIFEST_DIR"),
107                 "/test_data/",
108                 stringify!($name),
109                 ".json"
110             );
111             if !std::path::Path::new(path).exists() {
112                 std::fs::write(path, serde_json::$to_json(&$generate).unwrap()).unwrap();
113             }
114             serde_json::from_slice(&std::fs::read(path).unwrap()).unwrap()
115         }
116     }};
117 }
118 
119 mod cipher_suite {
120     pub use mls_rs_core::crypto::CipherSuite;
121 }
122 
123 pub use cipher_suite::CipherSuite;
124 
125 mod protocol_version {
126     pub use mls_rs_core::protocol_version::ProtocolVersion;
127 }
128 
129 pub use protocol_version::ProtocolVersion;
130 
131 pub mod client;
132 pub mod client_builder;
133 mod client_config;
134 /// Dependencies of [`CryptoProvider`] and [`CipherSuiteProvider`]
135 pub mod crypto;
136 /// Extension utilities and built-in extension types.
137 pub mod extension;
138 /// Tools to observe groups without being a member, useful
139 /// for server implementations.
140 #[cfg(feature = "external_client")]
141 #[cfg_attr(docsrs, doc(cfg(feature = "external_client")))]
142 pub mod external_client;
143 mod grease;
144 /// E2EE group created by a [`Client`].
145 pub mod group;
146 mod hash_reference;
147 /// Identity providers to use with [`ClientBuilder`](client_builder::ClientBuilder).
148 pub mod identity;
149 mod iter;
150 mod key_package;
151 /// Pre-shared key support.
152 pub mod psk;
153 mod signer;
154 /// Storage providers to use with
155 /// [`ClientBuilder`](client_builder::ClientBuilder).
156 pub mod storage_provider;
157 
158 pub use mls_rs_core::{
159     crypto::{CipherSuiteProvider, CryptoProvider},
160     group::GroupStateStorage,
161     identity::IdentityProvider,
162     key_package::KeyPackageStorage,
163     psk::PreSharedKeyStorage,
164 };
165 
166 /// Dependencies of [`MlsRules`].
167 pub mod mls_rules {
168     pub use crate::group::{
169         mls_rules::{
170             CommitDirection, CommitOptions, CommitSource, DefaultMlsRules, EncryptionOptions,
171         },
172         proposal_filter::{ProposalBundle, ProposalInfo, ProposalSource},
173     };
174 
175     #[cfg(feature = "by_ref_proposal")]
176     pub use crate::group::proposal_ref::ProposalRef;
177 }
178 
179 pub use mls_rs_core::extension::{Extension, ExtensionList};
180 
181 pub use crate::{
182     client::Client,
183     group::{
184         framing::{MlsMessage, WireFormat},
185         mls_rules::MlsRules,
186         Group,
187     },
188     key_package::{KeyPackage, KeyPackageRef},
189 };
190 
191 /// Error types.
192 pub mod error {
193     pub use crate::client::MlsError;
194     pub use mls_rs_core::error::{AnyError, IntoAnyError};
195     pub use mls_rs_core::extension::ExtensionError;
196 }
197 
198 /// WASM compatible timestamp.
199 pub mod time {
200     pub use mls_rs_core::time::*;
201 }
202 
203 mod tree_kem;
204 
205 pub use mls_rs_codec;
206 
207 mod private {
208     pub trait Sealed {}
209 }
210 
211 use private::Sealed;
212 
213 #[cfg(any(test, feature = "test_util"))]
214 #[doc(hidden)]
215 pub mod test_utils;
216 
217 #[cfg(feature = "ffi")]
218 pub use safer_ffi_gen;
219