core_crypto/mls/session/
key_package.rs1use std::sync::Arc;
2
3use core_crypto_keystore::{entities::StoredKeyPackage, traits::FetchFromDatabase};
4
5use super::Result;
6use crate::{Keypackage, KeypackageRef, KeystoreError, Session, mls::key_package::KeypackageExt};
7
8pub(crate) fn from_stored(stored_keypackage: Arc<StoredKeyPackage>) -> Result<Keypackage> {
9 core_crypto_keystore::deser::<Keypackage>(&stored_keypackage.key_package)
10 .map_err(KeystoreError::wrap("deserializing keypackage"))
11 .map_err(Into::into)
12}
13
14impl Session {
15 pub(crate) async fn get_key_packages(&self) -> Result<Vec<Keypackage>> {
17 let stored_keypackages = self
18 .database
19 .load_all::<StoredKeyPackage>()
20 .await
21 .map_err(KeystoreError::wrap("finding all keypackages"))?;
22
23 let keypackages = stored_keypackages
24 .iter().cloned()
25 .map(from_stored)
26 .filter_map(|kp| kp.ok())
29 .collect();
30
31 Ok(keypackages)
32 }
33
34 pub async fn get_keypackage_refs(&self) -> Result<Vec<KeypackageRef>> {
36 self.get_key_packages()
37 .await?
38 .iter()
39 .map(|keypackage| keypackage.make_ref().map_err(Into::into))
40 .collect()
41 }
42
43 pub(crate) async fn load_key_package(&self, kp_ref: &KeypackageRef) -> Result<Option<Keypackage>> {
45 self.database
46 .get_borrowed::<StoredKeyPackage>(kp_ref.hash_ref())
47 .await
48 .map_err(KeystoreError::wrap("loading keypackage from database"))?
49 .map(from_stored)
50 .transpose()
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use std::time::Duration;
57
58 use openmls::prelude::{KeyPackageIn, ProtocolVersion};
59 use openmls_traits::types::VerifiableCiphersuite;
60
61 use crate::{ConversationConfiguration, mls::key_package::KeypackageExt as _, test_utils::*};
62
63 #[apply(all_cred_cipher)]
64 async fn can_assess_keypackage_expiration(case: TestContext) {
65 let [session] = case.sessions().await;
66
67 let kp_std_exp = session.new_keypackage(&case).await;
69 assert!(kp_std_exp.is_valid());
70
71 let kp_1s_exp = session
73 .new_keypackage_with_lifetime(&case, Some(Duration::from_secs(1)))
74 .await;
75
76 smol::Timer::after(std::time::Duration::from_secs(2)).await;
78 assert!(!kp_1s_exp.is_valid());
79 }
80
81 #[apply(all_cred_cipher)]
82 async fn new_keypackage_has_correct_extensions(case: TestContext) {
83 let [cc] = case.sessions().await;
84 Box::pin(async move {
85 let kp = cc.new_keypackage(&case).await;
86
87 let _ = KeyPackageIn::from(kp.clone())
89 .standalone_validate(
90 &cc.transaction.crypto_provider().await.unwrap(),
91 ProtocolVersion::Mls10,
92 true,
93 )
94 .await
95 .unwrap();
96
97 assert!(kp.extensions().is_empty());
99
100 assert_eq!(kp.leaf_node().capabilities().versions(), &[ProtocolVersion::Mls10]);
101 assert_eq!(
102 kp.leaf_node().capabilities().ciphersuites().to_vec(),
103 ConversationConfiguration::DEFAULT_SUPPORTED_CIPHERSUITES
104 .iter()
105 .map(|c| VerifiableCiphersuite::from(*c))
106 .collect::<Vec<_>>()
107 );
108 assert!(kp.leaf_node().capabilities().proposals().is_empty());
109 assert!(kp.leaf_node().capabilities().extensions().is_empty());
110 assert_eq!(
111 kp.leaf_node().capabilities().credentials(),
112 ConversationConfiguration::DEFAULT_SUPPORTED_CREDENTIALS
113 );
114 })
115 .await
116 }
117
118 #[apply(all_cred_cipher)]
119 async fn can_store_and_load_key_packages(case: TestContext) {
120 let [cc] = case.sessions().await;
121
122 let kp = cc.new_keypackage(&case).await;
124
125 let all_keypackages = cc.session.read().await.get_key_packages().await.unwrap();
126 assert_eq!(all_keypackages[0], kp);
127
128 let kp_ref = kp.make_ref().unwrap();
129 let by_ref = cc
130 .session
131 .read()
132 .await
133 .load_key_package(&kp_ref)
134 .await
135 .unwrap()
136 .unwrap();
137 assert_eq!(kp, by_ref);
138 }
139}