1use openmls_traits::storage::{traits, Entity, Key, CURRENT_VERSION};
11
12#[cfg(feature = "migration-import")]
15pub use crate::group::migration_import::GroupMigrationBundle;
16
17use crate::binary_tree::LeafNodeIndex;
18use crate::group::proposal_store::QueuedProposal;
19use crate::group::{MlsGroupJoinConfig, MlsGroupState};
20#[cfg(feature = "extensions-draft")]
21use crate::schedule::application_export_tree::ApplicationExportTree;
22use crate::{
23 ciphersuite::hash_ref::ProposalRef,
24 group::{GroupContext, GroupId, InterimTranscriptHash},
25 messages::ConfirmationTag,
26 treesync::{LeafNode, TreeSync},
27};
28use crate::{
29 group::{past_secrets::MessageSecretsStore, GroupEpoch},
30 prelude::KeyPackageBundle,
31 schedule::{
32 psk::{store::ResumptionPskStore, PskBundle},
33 GroupEpochSecrets, Psk,
34 },
35 treesync::{node::encryption_keys::EncryptionKeyPair, EncryptionKey},
36};
37
38#[cfg(test)]
39pub mod kat_storage_stability;
40
41pub trait StorageProvider: openmls_traits::storage::StorageProvider<CURRENT_VERSION> {}
44
45pub trait PublicStorageProvider:
48 openmls_traits::public_storage::PublicStorageProvider<
49 CURRENT_VERSION,
50 PublicError = <Self as PublicStorageProvider>::Error,
51>
52{
53 type Error: core::fmt::Debug + std::error::Error;
56}
57
58impl<P: openmls_traits::storage::StorageProvider<CURRENT_VERSION>> StorageProvider for P {}
59
60impl<P: openmls_traits::public_storage::PublicStorageProvider<CURRENT_VERSION>>
61 PublicStorageProvider for P
62{
63 type Error = P::PublicError;
64}
65
66pub trait OpenMlsProvider:
70 openmls_traits::OpenMlsProvider<StorageProvider = Self::Storage>
71{
72 type Storage: StorageProvider<Error = Self::StorageError>;
74 type StorageError: std::error::Error;
76}
77
78impl<
79 Error: std::error::Error,
80 SP: StorageProvider<Error = Error>,
81 OP: openmls_traits::OpenMlsProvider<StorageProvider = SP>,
82 > OpenMlsProvider for OP
83{
84 type Storage = SP;
85 type StorageError = Error;
86}
87
88impl Entity<CURRENT_VERSION> for QueuedProposal {}
91impl traits::QueuedProposal<CURRENT_VERSION> for QueuedProposal {}
92
93impl Entity<CURRENT_VERSION> for TreeSync {}
94impl traits::TreeSync<CURRENT_VERSION> for TreeSync {}
95
96impl Key<CURRENT_VERSION> for GroupId {}
97impl traits::GroupId<CURRENT_VERSION> for GroupId {}
98
99impl Key<CURRENT_VERSION> for ProposalRef {}
100impl Entity<CURRENT_VERSION> for ProposalRef {}
101impl traits::ProposalRef<CURRENT_VERSION> for ProposalRef {}
102impl traits::HashReference<CURRENT_VERSION> for ProposalRef {}
103
104impl Entity<CURRENT_VERSION> for GroupContext {}
105impl traits::GroupContext<CURRENT_VERSION> for GroupContext {}
106
107impl Entity<CURRENT_VERSION> for InterimTranscriptHash {}
108impl traits::InterimTranscriptHash<CURRENT_VERSION> for InterimTranscriptHash {}
109
110impl Entity<CURRENT_VERSION> for ConfirmationTag {}
111impl traits::ConfirmationTag<CURRENT_VERSION> for ConfirmationTag {}
112
113impl Entity<CURRENT_VERSION> for KeyPackageBundle {}
114impl traits::KeyPackage<CURRENT_VERSION> for KeyPackageBundle {}
115
116impl Key<CURRENT_VERSION> for EncryptionKey {}
117impl traits::EncryptionKey<CURRENT_VERSION> for EncryptionKey {}
118
119impl Entity<CURRENT_VERSION> for EncryptionKeyPair {}
120impl traits::HpkeKeyPair<CURRENT_VERSION> for EncryptionKeyPair {}
121
122impl Entity<CURRENT_VERSION> for LeafNodeIndex {}
123impl traits::LeafNodeIndex<CURRENT_VERSION> for LeafNodeIndex {}
124
125impl Entity<CURRENT_VERSION> for GroupEpochSecrets {}
126impl traits::GroupEpochSecrets<CURRENT_VERSION> for GroupEpochSecrets {}
127
128impl Entity<CURRENT_VERSION> for MessageSecretsStore {}
129impl traits::MessageSecrets<CURRENT_VERSION> for MessageSecretsStore {}
130
131impl Entity<CURRENT_VERSION> for ResumptionPskStore {}
132impl traits::ResumptionPskStore<CURRENT_VERSION> for ResumptionPskStore {}
133
134impl Entity<CURRENT_VERSION> for MlsGroupJoinConfig {}
135impl traits::MlsGroupJoinConfig<CURRENT_VERSION> for MlsGroupJoinConfig {}
136
137impl Entity<CURRENT_VERSION> for MlsGroupState {}
138impl traits::GroupState<CURRENT_VERSION> for MlsGroupState {}
139
140impl Entity<CURRENT_VERSION> for LeafNode {}
141impl traits::LeafNode<CURRENT_VERSION> for LeafNode {}
142
143impl Key<CURRENT_VERSION> for GroupEpoch {}
146impl traits::EpochKey<CURRENT_VERSION> for GroupEpoch {}
147
148impl Key<CURRENT_VERSION> for Psk {}
149impl traits::PskId<CURRENT_VERSION> for Psk {}
150
151impl Entity<CURRENT_VERSION> for PskBundle {}
152impl traits::PskBundle<CURRENT_VERSION> for PskBundle {}
153
154#[cfg(feature = "extensions-draft")]
155impl Entity<CURRENT_VERSION> for ApplicationExportTree {}
156#[cfg(feature = "extensions-draft")]
157impl traits::ApplicationExportTree<CURRENT_VERSION> for ApplicationExportTree {}
158
159#[cfg(feature = "virtual-clients-draft")]
160mod virtual_clients_storage {
161 use super::*;
162 use crate::components::vc_derivation_info::{
163 EpochId, RetainedKeyPackageMaterial, VcDerivationEpochLogEntry, VcDerivationEpochState,
164 VcEmulationBinding,
165 };
166 use crate::components::vc_operation_tree::OperationSecretTree;
167
168 impl Key<CURRENT_VERSION> for EpochId {}
170 impl Entity<CURRENT_VERSION> for EpochId {}
171 impl traits::VcEpochId<CURRENT_VERSION> for EpochId {}
172
173 impl Entity<CURRENT_VERSION> for VcDerivationEpochState {}
174 impl traits::VcDerivationEpochState<CURRENT_VERSION> for VcDerivationEpochState {}
175
176 impl Entity<CURRENT_VERSION> for VcEmulationBinding {}
177 impl traits::VcEmulationBinding<CURRENT_VERSION> for VcEmulationBinding {}
178
179 impl Entity<CURRENT_VERSION> for VcDerivationEpochLogEntry {}
180 impl traits::VcDerivationEpochLogEntry<CURRENT_VERSION> for VcDerivationEpochLogEntry {}
181
182 impl Entity<CURRENT_VERSION> for OperationSecretTree {}
183 impl traits::VcOperationTree<CURRENT_VERSION> for OperationSecretTree {}
184
185 impl Entity<CURRENT_VERSION> for RetainedKeyPackageMaterial {}
186 impl traits::RetainedKeyPackageMaterial<CURRENT_VERSION> for RetainedKeyPackageMaterial {}
187}
188
189#[cfg(test)]
190mod test {
191 use crate::{
192 group::mls_group::tests_and_kats::utils::setup_client, prelude::KeyPackageBuilder,
193 test_utils::minimal_capabilities_for,
194 };
195
196 use super::*;
197
198 use openmls_rust_crypto::{MemoryStorage, OpenMlsRustCrypto};
199 use openmls_traits::{
200 storage::{traits as type_traits, StorageProvider, V_TEST},
201 types::{Ciphersuite, HpkePrivateKey},
202 OpenMlsProvider,
203 };
204 use serde::{Deserialize, Serialize};
205
206 #[derive(Serialize, Deserialize)]
209 struct NewKeyPackageBundle {
210 ciphersuite: Ciphersuite,
211 key_package: crate::key_packages::KeyPackage,
212 private_init_key: HpkePrivateKey,
213 private_encryption_key: crate::treesync::node::encryption_keys::EncryptionPrivateKey,
214 }
215
216 impl Entity<V_TEST> for NewKeyPackageBundle {}
217 impl type_traits::KeyPackage<V_TEST> for NewKeyPackageBundle {}
218
219 impl Key<V_TEST> for EncryptionKey {}
220 impl type_traits::EncryptionKey<V_TEST> for EncryptionKey {}
221
222 impl Entity<V_TEST> for EncryptionKeyPair {}
223 impl type_traits::HpkeKeyPair<V_TEST> for EncryptionKeyPair {}
224
225 impl Key<V_TEST> for ProposalRef {}
226 impl type_traits::HashReference<V_TEST> for ProposalRef {}
227
228 #[test]
229 fn key_packages_key_upgrade() {
230 const CIPHERSUITE: Ciphersuite =
231 Ciphersuite::MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519;
232
233 let provider = OpenMlsRustCrypto::default();
235
236 let (credential_with_key, _kpb, signer, _pk) =
237 setup_client("Alice", CIPHERSUITE, &provider);
238
239 let key_package_bundle = KeyPackageBuilder::new()
241 .leaf_node_capabilities(minimal_capabilities_for(CIPHERSUITE).build())
242 .build(
243 Ciphersuite::MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519,
244 &provider,
245 &signer,
246 credential_with_key,
247 )
248 .unwrap();
249
250 let key_package = key_package_bundle.key_package();
251 let key_package_ref = key_package.hash_ref(provider.crypto()).unwrap();
252
253 let new_storage_provider = MemoryStorage::default();
257
258 let read_key_package_bundle: crate::prelude::KeyPackageBundle =
260 <MemoryStorage as StorageProvider<CURRENT_VERSION>>::key_package(
261 provider.storage(),
262 &key_package_ref,
263 )
264 .unwrap()
265 .unwrap();
266
267 let new_key_package_bundle = NewKeyPackageBundle {
269 ciphersuite: read_key_package_bundle.key_package().ciphersuite(),
270 key_package: read_key_package_bundle.key_package().clone(),
271 private_init_key: read_key_package_bundle.init_private_key().clone(),
272 private_encryption_key: read_key_package_bundle.private_encryption_key.clone(),
273 };
274
275 <MemoryStorage as StorageProvider<V_TEST>>::write_key_package(
277 &new_storage_provider,
278 &key_package_ref,
279 &new_key_package_bundle,
280 )
281 .unwrap();
282
283 let read_new_key_package_bundle: NewKeyPackageBundle =
285 <MemoryStorage as StorageProvider<V_TEST>>::key_package(
286 &new_storage_provider,
287 &key_package_ref,
288 )
289 .unwrap()
290 .unwrap();
291
292 assert_eq!(
295 &read_new_key_package_bundle.key_package,
296 key_package_bundle.key_package()
297 );
298 assert_eq!(
299 read_new_key_package_bundle.ciphersuite,
300 key_package_bundle.key_package().ciphersuite()
301 );
302 assert_eq!(
303 &read_new_key_package_bundle.private_encryption_key,
304 &key_package_bundle.private_encryption_key
305 );
306 assert_eq!(
307 &read_new_key_package_bundle.private_init_key,
308 &key_package_bundle.private_init_key
309 );
310 }
311}