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