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()
25 .cloned()
26 .map(from_stored)
27 .filter_map(|kp| kp.ok())
30 .collect();
31
32 Ok(keypackages)
33 }
34
35 pub async fn get_keypackage_refs(&self) -> Result<Vec<KeypackageRef>> {
37 self.get_key_packages()
38 .await?
39 .iter()
40 .map(|keypackage| keypackage.make_ref().map_err(Into::into))
41 .collect()
42 }
43
44 pub(crate) async fn load_key_package(&self, kp_ref: &KeypackageRef) -> Result<Option<Keypackage>> {
46 self.database
47 .get_borrowed::<StoredKeyPackage>(kp_ref.hash_ref())
48 .await
49 .map_err(KeystoreError::wrap("loading keypackage from database"))?
50 .map(from_stored)
51 .transpose()
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use std::time::Duration;
58
59 use openmls::prelude::{KeyPackageIn, ProtocolVersion};
60 use openmls_traits::types::VerifiableCiphersuite;
61
62 use crate::{ConversationConfiguration, mls::key_package::KeypackageExt as _, test_utils::*};
63
64 #[apply(all_cred_cipher)]
65 async fn can_assess_keypackage_expiration(case: TestContext) {
66 let [session] = case.sessions().await;
67
68 let kp_std_exp = session.new_keypackage(&case).await;
70 assert!(kp_std_exp.is_valid());
71
72 let kp_1s_exp = session
74 .new_keypackage_with_lifetime(&case, Some(Duration::from_secs(1)))
75 .await;
76
77 smol::Timer::after(std::time::Duration::from_secs(2)).await;
79 assert!(!kp_1s_exp.is_valid());
80 }
81
82 #[apply(all_cred_cipher)]
83 async fn new_keypackage_has_correct_extensions(case: TestContext) {
84 let [cc] = case.sessions().await;
85 Box::pin(async move {
86 let kp = cc.new_keypackage(&case).await;
87
88 let _ = KeyPackageIn::from(kp.clone())
90 .standalone_validate(
91 &cc.transaction.crypto_provider().await.unwrap(),
92 ProtocolVersion::Mls10,
93 true,
94 )
95 .await
96 .unwrap();
97
98 assert!(kp.extensions().is_empty());
100
101 assert_eq!(kp.leaf_node().capabilities().versions(), &[ProtocolVersion::Mls10]);
102 assert_eq!(
103 kp.leaf_node().capabilities().ciphersuites().to_vec(),
104 ConversationConfiguration::DEFAULT_SUPPORTED_CIPHERSUITES
105 .iter()
106 .map(|c| VerifiableCiphersuite::from(*c))
107 .collect::<Vec<_>>()
108 );
109 assert!(kp.leaf_node().capabilities().proposals().is_empty());
110 assert!(kp.leaf_node().capabilities().extensions().is_empty());
111 assert_eq!(
112 kp.leaf_node().capabilities().credentials(),
113 ConversationConfiguration::DEFAULT_SUPPORTED_CREDENTIALS
114 );
115 })
116 .await
117 }
118
119 #[apply(all_cred_cipher)]
120 async fn can_store_and_load_key_packages(case: TestContext) {
121 let [cc] = case.sessions().await;
122
123 let kp = cc.new_keypackage(&case).await;
125
126 let all_keypackages = cc.session.read().await.get_key_packages().await.unwrap();
127 assert_eq!(all_keypackages[0], kp);
128
129 let kp_ref = kp.make_ref().unwrap();
130 let by_ref = cc
131 .session
132 .read()
133 .await
134 .load_key_package(&kp_ref)
135 .await
136 .unwrap()
137 .unwrap();
138 assert_eq!(kp, by_ref);
139 }
140}