1use openmls_traits::storage::{traits, Entity, Key, CURRENT_VERSION};
11
12use crate::binary_tree::LeafNodeIndex;
13use crate::group::proposal_store::QueuedProposal;
14use crate::group::{MlsGroupJoinConfig, MlsGroupState};
15#[cfg(feature = "extensions-draft-08")]
16use crate::schedule::application_export_tree::ApplicationExportTree;
17use crate::{
18 ciphersuite::hash_ref::ProposalRef,
19 group::{GroupContext, GroupId, InterimTranscriptHash},
20 messages::ConfirmationTag,
21 treesync::{LeafNode, TreeSync},
22};
23use crate::{
24 group::{past_secrets::MessageSecretsStore, GroupEpoch},
25 prelude::KeyPackageBundle,
26 schedule::{
27 psk::{store::ResumptionPskStore, PskBundle},
28 GroupEpochSecrets, Psk,
29 },
30 treesync::{node::encryption_keys::EncryptionKeyPair, EncryptionKey},
31};
32
33#[cfg(test)]
34pub mod kat_storage_stability;
35
36pub trait StorageProvider: openmls_traits::storage::StorageProvider<CURRENT_VERSION> {}
39
40pub trait PublicStorageProvider:
43 openmls_traits::public_storage::PublicStorageProvider<
44 CURRENT_VERSION,
45 PublicError = <Self as PublicStorageProvider>::Error,
46>
47{
48 type Error: core::fmt::Debug + std::error::Error;
51}
52
53impl<P: openmls_traits::storage::StorageProvider<CURRENT_VERSION>> StorageProvider for P {}
54
55impl<P: openmls_traits::public_storage::PublicStorageProvider<CURRENT_VERSION>>
56 PublicStorageProvider for P
57{
58 type Error = P::PublicError;
59}
60
61pub trait OpenMlsProvider:
65 openmls_traits::OpenMlsProvider<StorageProvider = Self::Storage>
66{
67 type Storage: StorageProvider<Error = Self::StorageError>;
69 type StorageError: std::error::Error;
71}
72
73impl<
74 Error: std::error::Error,
75 SP: StorageProvider<Error = Error>,
76 OP: openmls_traits::OpenMlsProvider<StorageProvider = SP>,
77 > OpenMlsProvider for OP
78{
79 type Storage = SP;
80 type StorageError = Error;
81}
82
83impl Entity<CURRENT_VERSION> for QueuedProposal {}
86impl traits::QueuedProposal<CURRENT_VERSION> for QueuedProposal {}
87
88impl Entity<CURRENT_VERSION> for TreeSync {}
89impl traits::TreeSync<CURRENT_VERSION> for TreeSync {}
90
91impl Key<CURRENT_VERSION> for GroupId {}
92impl traits::GroupId<CURRENT_VERSION> for GroupId {}
93
94impl Key<CURRENT_VERSION> for ProposalRef {}
95impl Entity<CURRENT_VERSION> for ProposalRef {}
96impl traits::ProposalRef<CURRENT_VERSION> for ProposalRef {}
97impl traits::HashReference<CURRENT_VERSION> for ProposalRef {}
98
99impl Entity<CURRENT_VERSION> for GroupContext {}
100impl traits::GroupContext<CURRENT_VERSION> for GroupContext {}
101
102impl Entity<CURRENT_VERSION> for InterimTranscriptHash {}
103impl traits::InterimTranscriptHash<CURRENT_VERSION> for InterimTranscriptHash {}
104
105impl Entity<CURRENT_VERSION> for ConfirmationTag {}
106impl traits::ConfirmationTag<CURRENT_VERSION> for ConfirmationTag {}
107
108impl Entity<CURRENT_VERSION> for KeyPackageBundle {}
109impl traits::KeyPackage<CURRENT_VERSION> for KeyPackageBundle {}
110
111impl Key<CURRENT_VERSION> for EncryptionKey {}
112impl traits::EncryptionKey<CURRENT_VERSION> for EncryptionKey {}
113
114impl Entity<CURRENT_VERSION> for EncryptionKeyPair {}
115impl traits::HpkeKeyPair<CURRENT_VERSION> for EncryptionKeyPair {}
116
117impl Entity<CURRENT_VERSION> for LeafNodeIndex {}
118impl traits::LeafNodeIndex<CURRENT_VERSION> for LeafNodeIndex {}
119
120impl Entity<CURRENT_VERSION> for GroupEpochSecrets {}
121impl traits::GroupEpochSecrets<CURRENT_VERSION> for GroupEpochSecrets {}
122
123impl Entity<CURRENT_VERSION> for MessageSecretsStore {}
124impl traits::MessageSecrets<CURRENT_VERSION> for MessageSecretsStore {}
125
126impl Entity<CURRENT_VERSION> for ResumptionPskStore {}
127impl traits::ResumptionPskStore<CURRENT_VERSION> for ResumptionPskStore {}
128
129impl Entity<CURRENT_VERSION> for MlsGroupJoinConfig {}
130impl traits::MlsGroupJoinConfig<CURRENT_VERSION> for MlsGroupJoinConfig {}
131
132impl Entity<CURRENT_VERSION> for MlsGroupState {}
133impl traits::GroupState<CURRENT_VERSION> for MlsGroupState {}
134
135impl Entity<CURRENT_VERSION> for LeafNode {}
136impl traits::LeafNode<CURRENT_VERSION> for LeafNode {}
137
138impl Key<CURRENT_VERSION> for GroupEpoch {}
141impl traits::EpochKey<CURRENT_VERSION> for GroupEpoch {}
142
143impl Key<CURRENT_VERSION> for Psk {}
144impl traits::PskId<CURRENT_VERSION> for Psk {}
145
146impl Entity<CURRENT_VERSION> for PskBundle {}
147impl traits::PskBundle<CURRENT_VERSION> for PskBundle {}
148
149#[cfg(feature = "extensions-draft-08")]
150impl Entity<CURRENT_VERSION> for ApplicationExportTree {}
151#[cfg(feature = "extensions-draft-08")]
152impl traits::ApplicationExportTree<CURRENT_VERSION> for ApplicationExportTree {}
153
154#[cfg(test)]
155mod test {
156 use crate::{
157 group::mls_group::tests_and_kats::utils::setup_client, prelude::KeyPackageBuilder,
158 };
159
160 use super::*;
161
162 use openmls_rust_crypto::{MemoryStorage, OpenMlsRustCrypto};
163 use openmls_traits::{
164 storage::{traits as type_traits, StorageProvider, V_TEST},
165 types::{Ciphersuite, HpkePrivateKey},
166 OpenMlsProvider,
167 };
168 use serde::{Deserialize, Serialize};
169
170 #[derive(Serialize, Deserialize)]
173 struct NewKeyPackageBundle {
174 ciphersuite: Ciphersuite,
175 key_package: crate::key_packages::KeyPackage,
176 private_init_key: HpkePrivateKey,
177 private_encryption_key: crate::treesync::node::encryption_keys::EncryptionPrivateKey,
178 }
179
180 impl Entity<V_TEST> for NewKeyPackageBundle {}
181 impl type_traits::KeyPackage<V_TEST> for NewKeyPackageBundle {}
182
183 impl Key<V_TEST> for EncryptionKey {}
184 impl type_traits::EncryptionKey<V_TEST> for EncryptionKey {}
185
186 impl Entity<V_TEST> for EncryptionKeyPair {}
187 impl type_traits::HpkeKeyPair<V_TEST> for EncryptionKeyPair {}
188
189 impl Key<V_TEST> for ProposalRef {}
190 impl type_traits::HashReference<V_TEST> for ProposalRef {}
191
192 #[test]
193 fn key_packages_key_upgrade() {
194 let provider = OpenMlsRustCrypto::default();
196
197 let (credential_with_key, _kpb, signer, _pk) = setup_client(
198 "Alice",
199 Ciphersuite::MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519,
200 &provider,
201 );
202
203 let key_package_bundle = KeyPackageBuilder::new()
205 .build(
206 Ciphersuite::MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519,
207 &provider,
208 &signer,
209 credential_with_key,
210 )
211 .unwrap();
212
213 let key_package = key_package_bundle.key_package();
214 let key_package_ref = key_package.hash_ref(provider.crypto()).unwrap();
215
216 let new_storage_provider = MemoryStorage::default();
220
221 let read_key_package_bundle: crate::prelude::KeyPackageBundle =
223 <MemoryStorage as StorageProvider<CURRENT_VERSION>>::key_package(
224 provider.storage(),
225 &key_package_ref,
226 )
227 .unwrap()
228 .unwrap();
229
230 let new_key_package_bundle = NewKeyPackageBundle {
232 ciphersuite: read_key_package_bundle.key_package().ciphersuite(),
233 key_package: read_key_package_bundle.key_package().clone(),
234 private_init_key: read_key_package_bundle.init_private_key().clone(),
235 private_encryption_key: read_key_package_bundle.private_encryption_key.clone(),
236 };
237
238 <MemoryStorage as StorageProvider<V_TEST>>::write_key_package(
240 &new_storage_provider,
241 &key_package_ref,
242 &new_key_package_bundle,
243 )
244 .unwrap();
245
246 let read_new_key_package_bundle: NewKeyPackageBundle =
248 <MemoryStorage as StorageProvider<V_TEST>>::key_package(
249 &new_storage_provider,
250 &key_package_ref,
251 )
252 .unwrap()
253 .unwrap();
254
255 assert_eq!(
258 &read_new_key_package_bundle.key_package,
259 key_package_bundle.key_package()
260 );
261 assert_eq!(
262 read_new_key_package_bundle.ciphersuite,
263 key_package_bundle.key_package().ciphersuite()
264 );
265 assert_eq!(
266 &read_new_key_package_bundle.private_encryption_key,
267 &key_package_bundle.private_encryption_key
268 );
269 assert_eq!(
270 &read_new_key_package_bundle.private_init_key,
271 &key_package_bundle.private_init_key
272 );
273 }
274}