mls_crypto_provider/
lib.rs

1#![doc = include_str!("../README.md")]
2
3pub use core_crypto_keystore::{Database, DatabaseKey};
4
5mod crypto_provider;
6mod error;
7mod pki;
8
9pub use crypto_provider::RustCrypto;
10pub use error::{MlsProviderError, MlsProviderResult};
11pub use pki::{CertProfile, CertificateGenerationArgs, PkiKeypair};
12
13use crate::pki::PkiEnvironmentProvider;
14
15pub mod reexports {
16    pub use rand_core;
17}
18
19/// 32-byte raw entropy seed
20pub type RawEntropySeed = <rand_chacha::ChaCha20Rng as rand::SeedableRng>::Seed;
21
22#[derive(Debug, Clone, Default, PartialEq, Eq, zeroize::ZeroizeOnDrop)]
23#[repr(transparent)]
24/// Wrapped 32-byte entropy seed with bounds check
25pub struct EntropySeed(RawEntropySeed);
26
27impl EntropySeed {
28    pub const EXPECTED_LEN: usize = std::mem::size_of::<EntropySeed>() / std::mem::size_of::<u8>();
29
30    pub fn try_from_slice(data: &[u8]) -> MlsProviderResult<Self> {
31        if data.len() < Self::EXPECTED_LEN {
32            return Err(MlsProviderError::EntropySeedLengthError {
33                actual: data.len(),
34                expected: Self::EXPECTED_LEN,
35            });
36        }
37
38        let mut inner = RawEntropySeed::default();
39        inner.copy_from_slice(&data[..Self::EXPECTED_LEN]);
40
41        Ok(Self(inner))
42    }
43
44    pub fn from_raw(raw: RawEntropySeed) -> Self {
45        Self(raw)
46    }
47}
48
49impl std::ops::Deref for EntropySeed {
50    type Target = [u8];
51    fn deref(&self) -> &Self::Target {
52        &self.0
53    }
54}
55
56impl std::ops::DerefMut for EntropySeed {
57    fn deref_mut(&mut self) -> &mut Self::Target {
58        &mut self.0
59    }
60}
61
62#[derive(Debug, Clone)]
63pub struct MlsCryptoProvider {
64    crypto: RustCrypto,
65    key_store: Database,
66    pki_env: PkiEnvironmentProvider,
67}
68
69impl MlsCryptoProvider {
70    /// Construct a crypto provider with defaults and a given [Database].
71    ///
72    /// See also:
73    ///
74    /// - [Database::open]
75    pub fn new(key_store: Database) -> Self {
76        Self {
77            key_store,
78            crypto: Default::default(),
79            pki_env: Default::default(),
80        }
81    }
82
83    /// Clones the references of the PkiEnvironment and the CryptoProvider into a transaction
84    /// keystore to pass to openmls as the `OpenMlsCryptoProvider`
85    pub async fn new_transaction(&self) -> MlsProviderResult<()> {
86        self.key_store.new_transaction().await.map_err(Into::into)
87    }
88
89    /// Replaces the PKI env currently in place
90    pub async fn update_pki_env(
91        &self,
92        pki_env: wire_e2e_identity::prelude::x509::revocation::PkiEnvironment,
93    ) -> MlsProviderResult<()> {
94        self.pki_env.update_env(pki_env).await
95    }
96
97    /// Returns whether we have a PKI env setup
98    pub async fn is_pki_env_setup(&self) -> bool {
99        self.pki_env.is_env_setup().await
100    }
101
102    /// Reseeds the internal CSPRNG entropy pool with a brand new one.
103    ///
104    /// If [None] is provided, the new entropy will be pulled through the current OS target's capabilities
105    pub fn reseed(&self, entropy_seed: Option<EntropySeed>) -> MlsProviderResult<()> {
106        self.crypto.reseed(entropy_seed)
107    }
108
109    /// Wait for any keystore transaction to finish, then close the database connection.
110    ///
111    /// Note: This does **not** destroy the data on-disk in case of persistent backing store
112    pub async fn close(self) -> MlsProviderResult<()> {
113        self.key_store.close().await.map_err(Into::into)
114    }
115
116    /// Clone keystore (its an `Arc` internnaly)
117    pub fn keystore(&self) -> Database {
118        self.key_store.clone()
119    }
120
121    /// Allows to retrieve the underlying key store directly
122    pub fn unwrap_keystore(self) -> Database {
123        self.key_store
124    }
125}
126
127impl openmls_traits::OpenMlsCryptoProvider for MlsCryptoProvider {
128    type CryptoProvider = RustCrypto;
129    type RandProvider = RustCrypto;
130    type KeyStoreProvider = Database;
131    type AuthenticationServiceProvider = PkiEnvironmentProvider;
132
133    fn crypto(&self) -> &Self::CryptoProvider {
134        &self.crypto
135    }
136
137    fn rand(&self) -> &Self::RandProvider {
138        &self.crypto
139    }
140
141    fn key_store(&self) -> &Self::KeyStoreProvider {
142        &self.key_store
143    }
144
145    fn authentication_service(&self) -> &Self::AuthenticationServiceProvider {
146        &self.pki_env
147    }
148}