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