core_crypto/
lib.rs

1// Wire
2// Copyright (C) 2022 Wire Swiss GmbH
3
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see http://www.gnu.org/licenses/.
16
17//! Core Crypto is a wrapper on top of OpenMLS aimed to provide an ergonomic API for usage in web
18//! through Web Assembly and in mobile devices through FFI.
19//!
20//! The goal is provide a easier and less verbose API to create, manage and interact with MLS
21//! groups.
22#![doc = include_str!("../../README.md")]
23#![cfg_attr(not(test), deny(missing_docs))]
24#![allow(clippy::single_component_path_imports)]
25
26use async_lock::Mutex;
27#[cfg(test)]
28pub use core_crypto_macros::{dispotent, durable, idempotent};
29use std::sync::Arc;
30
31pub use self::error::*;
32
33#[cfg(test)]
34#[macro_use]
35pub mod test_utils;
36// both imports above have to be defined at the beginning of the crate for rstest to work
37
38mod error;
39
40/// MLS Abstraction
41pub mod mls;
42
43/// re-export [rusty-jwt-tools](https://github.com/wireapp/rusty-jwt-tools) API
44pub mod e2e_identity;
45
46#[cfg(feature = "proteus")]
47/// Proteus Abstraction
48pub mod proteus;
49
50pub mod context;
51mod group_store;
52mod obfuscate;
53
54mod build_metadata;
55use crate::prelude::MlsCommitBundle;
56pub use build_metadata::{BUILD_METADATA, BuildMetadata};
57
58/// Common imports that should be useful for most uses of the crate
59pub mod prelude {
60    pub use openmls::{
61        group::{MlsGroup, MlsGroupConfig},
62        prelude::{
63            Ciphersuite as CiphersuiteName, Credential, GroupEpoch, KeyPackage, KeyPackageIn, KeyPackageRef,
64            MlsMessageIn, Node, group_info::VerifiableGroupInfo,
65        },
66    };
67
68    pub use mls_crypto_provider::{EntropySeed, MlsCryptoProvider, RawEntropySeed};
69
70    pub use crate::{
71        CoreCrypto, MlsTransport,
72        e2e_identity::{
73            E2eiEnrollment,
74            conversation_state::E2eiConversationState,
75            device_status::DeviceStatus,
76            identity::{WireIdentity, X509Identity},
77            types::{E2eiAcmeChallenge, E2eiAcmeDirectory, E2eiNewAcmeAuthz, E2eiNewAcmeOrder},
78        },
79        error::{CryptoboxMigrationError, Error, KeystoreError, LeafError, MlsError, ProteusError, RecursiveError},
80        mls::{
81            MlsCentral,
82            ciphersuite::MlsCiphersuite,
83            client::id::ClientId,
84            client::identifier::ClientIdentifier,
85            client::key_package::INITIAL_KEYING_MATERIAL_COUNT,
86            client::*,
87            config::MlsCentralConfiguration,
88            conversation::{
89                ConversationId, MlsConversation,
90                commit::{MlsCommitBundle, MlsConversationCreationMessage},
91                config::{MlsConversationConfiguration, MlsCustomConfiguration, MlsWirePolicy},
92                conversation_guard::decrypt::{MlsBufferedConversationDecryptMessage, MlsConversationDecryptMessage},
93                group_info::{GroupInfoPayload, MlsGroupInfoBundle, MlsGroupInfoEncryptionType, MlsRatchetTreeType},
94                proposal::MlsProposalBundle,
95                welcome::WelcomeBundle,
96            },
97            credential::{typ::MlsCredentialType, x509::CertificateBundle},
98            proposal::{MlsProposal, MlsProposalRef},
99        },
100        obfuscate::Obfuscated,
101    };
102}
103
104/// Response from the delivery service
105pub enum MlsTransportResponse {
106    /// The message was accepted by the delivery service
107    Success,
108    /// A client should have consumed all incoming messages before re-trying.
109    Retry,
110    /// The message was rejected by the delivery service and there's no recovery.
111    Abort {
112        /// Why did the delivery service reject the message?
113        reason: String,
114    },
115}
116
117/// Client callbacks to allow communication with the delivery service.
118/// There are two different endpoints, one for messages and one for commit bundles.
119#[cfg_attr(target_family = "wasm", async_trait::async_trait(?Send))]
120#[cfg_attr(not(target_family = "wasm"), async_trait::async_trait)]
121pub trait MlsTransport: std::fmt::Debug + Send + Sync {
122    /// Send a commit bundle to the corresponding endpoint.
123    async fn send_commit_bundle(&self, commit_bundle: MlsCommitBundle) -> Result<MlsTransportResponse>;
124    /// Send a message to the corresponding endpoint.
125    async fn send_message(&self, mls_message: Vec<u8>) -> Result<MlsTransportResponse>;
126}
127
128#[derive(Debug)]
129/// Wrapper superstruct for both [mls::MlsCentral] and [proteus::ProteusCentral]
130///
131/// As [std::ops::Deref] is implemented, this struct is automatically dereferred to [mls::MlsCentral] apart from `proteus_*` calls
132pub struct CoreCrypto {
133    mls: mls::MlsCentral,
134    #[cfg(feature = "proteus")]
135    proteus: Arc<Mutex<Option<proteus::ProteusCentral>>>,
136    #[cfg(not(feature = "proteus"))]
137    #[allow(dead_code)]
138    proteus: (),
139}
140
141impl From<mls::MlsCentral> for CoreCrypto {
142    fn from(mls: mls::MlsCentral) -> Self {
143        Self {
144            mls,
145            proteus: Default::default(),
146        }
147    }
148}
149
150impl std::ops::Deref for CoreCrypto {
151    type Target = mls::MlsCentral;
152
153    fn deref(&self) -> &Self::Target {
154        &self.mls
155    }
156}
157
158impl std::ops::DerefMut for CoreCrypto {
159    fn deref_mut(&mut self) -> &mut Self::Target {
160        &mut self.mls
161    }
162}
163
164impl CoreCrypto {
165    /// Allows to extract the MLS Client from the wrapper superstruct
166    #[inline]
167    pub fn take(self) -> mls::MlsCentral {
168        self.mls
169    }
170}