core_crypto/
lib.rs

1//! Core Crypto is a wrapper on top of OpenMLS aimed to provide an ergonomic API for usage in web
2//! through Web Assembly and in mobile devices through FFI.
3//!
4//! The goal is provide a easier and less verbose API to create, manage and interact with MLS
5//! groups.
6#![doc = include_str!(env!("STRIPPED_README_PATH"))]
7#![cfg_attr(not(test), deny(missing_docs))]
8#![allow(clippy::single_component_path_imports)]
9
10#[cfg(test)]
11pub use core_crypto_macros::{dispotent, durable, idempotent};
12#[cfg(feature = "proteus")]
13use {async_lock::Mutex, std::sync::Arc};
14
15pub use self::error::*;
16
17#[cfg(test)]
18#[macro_use]
19pub mod test_utils;
20// both imports above have to be defined at the beginning of the crate for rstest to work
21
22mod error;
23
24/// MLS Abstraction
25pub mod mls;
26
27/// re-export [rusty-jwt-tools](https://github.com/wireapp/rusty-jwt-tools) API
28pub mod e2e_identity;
29
30/// Proteus Abstraction
31#[cfg(feature = "proteus")]
32pub mod proteus;
33
34mod ephemeral;
35mod group_store;
36pub mod transaction_context;
37
38mod build_metadata;
39use crate::prelude::MlsCommitBundle;
40pub use build_metadata::{BUILD_METADATA, BuildMetadata};
41
42use crate::ephemeral::HistorySecret;
43pub use core_crypto_keystore::DatabaseKey;
44
45/// Common imports that should be useful for most uses of the crate
46pub mod prelude {
47    pub use openmls::{
48        group::{MlsGroup, MlsGroupConfig},
49        prelude::{
50            Ciphersuite as CiphersuiteName, Credential, GroupEpoch, KeyPackage, KeyPackageIn, KeyPackageRef,
51            MlsMessageIn, Node, group_info::VerifiableGroupInfo,
52        },
53    };
54
55    pub use mls_crypto_provider::{EntropySeed, MlsCryptoProvider, RawEntropySeed};
56
57    pub use crate::{
58        CoreCrypto, MlsTransport,
59        e2e_identity::{
60            E2eiEnrollment,
61            device_status::DeviceStatus,
62            identity::{WireIdentity, X509Identity},
63            types::{E2eiAcmeChallenge, E2eiAcmeDirectory, E2eiNewAcmeAuthz, E2eiNewAcmeOrder},
64        },
65        ephemeral::{HISTORY_CLIENT_ID_PREFIX, HistorySecret},
66        error::{Error, KeystoreError, LeafError, MlsError, ProteusError, RecursiveError},
67        mls::{
68            ciphersuite::MlsCiphersuite,
69            conversation::{
70                ConversationId, MlsConversation,
71                commit::MlsCommitBundle,
72                config::{MlsConversationConfiguration, MlsCustomConfiguration, MlsWirePolicy},
73                conversation_guard::decrypt::{MlsBufferedConversationDecryptMessage, MlsConversationDecryptMessage},
74                group_info::{GroupInfoPayload, MlsGroupInfoBundle, MlsGroupInfoEncryptionType, MlsRatchetTreeType},
75                proposal::MlsProposalBundle,
76                welcome::WelcomeBundle,
77            },
78            credential::{typ::MlsCredentialType, x509::CertificateBundle},
79            proposal::{MlsProposal, MlsProposalRef},
80            session::{
81                Session,
82                config::{SessionConfig, ValidatedSessionConfig},
83                id::ClientId,
84                identifier::ClientIdentifier,
85                key_package::INITIAL_KEYING_MATERIAL_COUNT,
86                *,
87            },
88        },
89        transaction_context::e2e_identity::conversation_state::E2eiConversationState,
90    };
91}
92
93/// Response from the delivery service
94pub enum MlsTransportResponse {
95    /// The message was accepted by the delivery service
96    Success,
97    /// A client should have consumed all incoming messages before re-trying.
98    Retry,
99    /// The message was rejected by the delivery service and there's no recovery.
100    Abort {
101        /// Why did the delivery service reject the message?
102        reason: String,
103    },
104}
105
106/// An entity / data which has been packaged by the application to be encrypted
107/// and transmitted in an application message.
108#[derive(Debug, derive_more::From, derive_more::Deref, serde::Serialize, serde::Deserialize)]
109pub struct MlsTransportData(pub Vec<u8>);
110
111/// Client callbacks to allow communication with the delivery service.
112/// There are two different endpoints, one for messages and one for commit bundles.
113#[cfg_attr(target_family = "wasm", async_trait::async_trait(?Send))]
114#[cfg_attr(not(target_family = "wasm"), async_trait::async_trait)]
115pub trait MlsTransport: std::fmt::Debug + Send + Sync {
116    /// Send a commit bundle to the corresponding endpoint.
117    async fn send_commit_bundle(&self, commit_bundle: MlsCommitBundle) -> Result<MlsTransportResponse>;
118    /// Send a message to the corresponding endpoint.
119    async fn send_message(&self, mls_message: Vec<u8>) -> Result<MlsTransportResponse>;
120
121    /// This function will be called before a history secret is sent to the mls transport to allow
122    /// the application to package it in a suitable transport container (json, protobuf, ...).
123    ///
124    /// The `secret` parameter contain the history client's secrets which will be sent over the mls transport.
125    ///
126    /// Returns the history secret packaged for transport
127    async fn prepare_for_transport(&self, secret: &HistorySecret) -> Result<MlsTransportData>;
128}
129
130/// Wrapper superstruct for both [mls::session::Session] and [proteus::ProteusCentral]
131///
132/// As [std::ops::Deref] is implemented, this struct is automatically dereferred to [mls::session::Session] apart from `proteus_*` calls
133///
134/// This is cheap to clone as all internal members have `Arc` wrappers or are `Copy`.
135#[derive(Debug, Clone)]
136pub struct CoreCrypto {
137    mls: mls::session::Session,
138    #[cfg(feature = "proteus")]
139    proteus: Arc<Mutex<Option<proteus::ProteusCentral>>>,
140    #[cfg(not(feature = "proteus"))]
141    #[allow(dead_code)]
142    proteus: (),
143}
144
145impl From<mls::session::Session> for CoreCrypto {
146    fn from(mls: mls::session::Session) -> Self {
147        Self {
148            mls,
149            proteus: Default::default(),
150        }
151    }
152}
153
154impl std::ops::Deref for CoreCrypto {
155    type Target = mls::session::Session;
156
157    fn deref(&self) -> &Self::Target {
158        &self.mls
159    }
160}
161
162impl std::ops::DerefMut for CoreCrypto {
163    fn deref_mut(&mut self) -> &mut Self::Target {
164        &mut self.mls
165    }
166}
167
168impl CoreCrypto {
169    /// Allows to extract the MLS Client from the wrapper superstruct
170    #[inline]
171    pub fn take(self) -> mls::session::Session {
172        self.mls
173    }
174}