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, RegisteredVcDerivationEpoch, RetainedKeyPackageMaterial, VcDerivationEpochState,
164 VcEmulationBindings,
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 VcEmulationBindings {}
177 impl traits::VcEmulationBindings<CURRENT_VERSION> for VcEmulationBindings {}
178
179 impl Entity<CURRENT_VERSION> for RegisteredVcDerivationEpoch {}
180 impl traits::RegisteredVcDerivationEpoch<CURRENT_VERSION> for RegisteredVcDerivationEpoch {}
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 };
194
195 use super::*;
196
197 use openmls_rust_crypto::{MemoryStorage, OpenMlsRustCrypto};
198 use openmls_traits::{
199 storage::{traits as type_traits, StorageProvider, V_TEST},
200 types::{Ciphersuite, HpkePrivateKey},
201 OpenMlsProvider,
202 };
203 use serde::{Deserialize, Serialize};
204
205 #[derive(Serialize, Deserialize)]
208 struct NewKeyPackageBundle {
209 ciphersuite: Ciphersuite,
210 key_package: crate::key_packages::KeyPackage,
211 private_init_key: HpkePrivateKey,
212 private_encryption_key: crate::treesync::node::encryption_keys::EncryptionPrivateKey,
213 }
214
215 impl Entity<V_TEST> for NewKeyPackageBundle {}
216 impl type_traits::KeyPackage<V_TEST> for NewKeyPackageBundle {}
217
218 impl Key<V_TEST> for EncryptionKey {}
219 impl type_traits::EncryptionKey<V_TEST> for EncryptionKey {}
220
221 impl Entity<V_TEST> for EncryptionKeyPair {}
222 impl type_traits::HpkeKeyPair<V_TEST> for EncryptionKeyPair {}
223
224 impl Key<V_TEST> for ProposalRef {}
225 impl type_traits::HashReference<V_TEST> for ProposalRef {}
226
227 #[test]
228 fn key_packages_key_upgrade() {
229 let provider = OpenMlsRustCrypto::default();
231
232 let (credential_with_key, _kpb, signer, _pk) = setup_client(
233 "Alice",
234 Ciphersuite::MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519,
235 &provider,
236 );
237
238 let key_package_bundle = KeyPackageBuilder::new()
240 .build(
241 Ciphersuite::MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519,
242 &provider,
243 &signer,
244 credential_with_key,
245 )
246 .unwrap();
247
248 let key_package = key_package_bundle.key_package();
249 let key_package_ref = key_package.hash_ref(provider.crypto()).unwrap();
250
251 let new_storage_provider = MemoryStorage::default();
255
256 let read_key_package_bundle: crate::prelude::KeyPackageBundle =
258 <MemoryStorage as StorageProvider<CURRENT_VERSION>>::key_package(
259 provider.storage(),
260 &key_package_ref,
261 )
262 .unwrap()
263 .unwrap();
264
265 let new_key_package_bundle = NewKeyPackageBundle {
267 ciphersuite: read_key_package_bundle.key_package().ciphersuite(),
268 key_package: read_key_package_bundle.key_package().clone(),
269 private_init_key: read_key_package_bundle.init_private_key().clone(),
270 private_encryption_key: read_key_package_bundle.private_encryption_key.clone(),
271 };
272
273 <MemoryStorage as StorageProvider<V_TEST>>::write_key_package(
275 &new_storage_provider,
276 &key_package_ref,
277 &new_key_package_bundle,
278 )
279 .unwrap();
280
281 let read_new_key_package_bundle: NewKeyPackageBundle =
283 <MemoryStorage as StorageProvider<V_TEST>>::key_package(
284 &new_storage_provider,
285 &key_package_ref,
286 )
287 .unwrap()
288 .unwrap();
289
290 assert_eq!(
293 &read_new_key_package_bundle.key_package,
294 key_package_bundle.key_package()
295 );
296 assert_eq!(
297 read_new_key_package_bundle.ciphersuite,
298 key_package_bundle.key_package().ciphersuite()
299 );
300 assert_eq!(
301 &read_new_key_package_bundle.private_encryption_key,
302 &key_package_bundle.private_encryption_key
303 );
304 assert_eq!(
305 &read_new_key_package_bundle.private_init_key,
306 &key_package_bundle.private_init_key
307 );
308 }
309}