core_crypto/transaction_context/
key_package.rs1use std::time::Duration;
4
5use core_crypto_keystore::{
6 entities::{StoredEncryptionKeyPair, StoredHpkePrivateKey, StoredKeypackage},
7 traits::FetchFromDatabase as _,
8};
9use openmls::prelude::{CryptoConfig, Lifetime};
10
11use super::{Error, Result, TransactionContext};
12use crate::{
13 ConversationConfiguration, CredentialRef, Keypackage, KeypackageRef, KeystoreError, RecursiveError,
14 mls::key_package::KeypackageExt as _,
15};
16
17pub const KEYPACKAGE_DEFAULT_LIFETIME: Duration = Duration::from_secs(60 * 60 * 24 * 28 * 3); impl TransactionContext {
21 pub async fn generate_key_package(
31 &self,
32 credential_ref: &CredentialRef,
33 lifetime: Option<Duration>,
34 ) -> Result<Keypackage> {
35 let inner = self.inner().await?;
36 let lifetime = Lifetime::new(lifetime.unwrap_or(KEYPACKAGE_DEFAULT_LIFETIME).as_secs());
37 let credential = credential_ref
38 .load(&inner.transaction)
39 .await
40 .map_err(RecursiveError::mls_credential_ref("loading credential"))?;
41 let config = CryptoConfig {
42 ciphersuite: credential.cipher_suite.into(),
43 version: openmls::versions::ProtocolVersion::default(),
44 };
45
46 Keypackage::builder()
47 .leaf_node_capabilities(ConversationConfiguration::default_leaf_capabilities())
48 .key_package_lifetime(lifetime)
49 .build(
50 config,
51 &self.crypto_provider().await?,
52 &credential.signature_key_pair,
53 credential.to_mls_credential_with_key(),
54 )
55 .await
56 .map_err(Error::key_package_new())
57 }
58
59 pub async fn get_key_package_refs(&self) -> Result<Vec<KeypackageRef>> {
61 let session = self.session().await?;
62 session
63 .get_keypackage_refs()
64 .await
65 .map_err(RecursiveError::mls_client(
66 "getting all key package refs for transaction",
67 ))
68 .map_err(Into::into)
69 }
70
71 pub async fn remove_key_package(&self, kp_ref: &KeypackageRef) -> Result<()> {
78 let Some(kp) = self
79 .session()
80 .await?
81 .load_key_package(kp_ref)
82 .await
83 .map_err(RecursiveError::mls_client("loading key packages on session"))?
84 else {
85 return Ok(());
86 };
87
88 let inner = self.inner().await?;
89 inner
90 .transaction
91 .remove_borrowed::<StoredKeypackage>(kp_ref.hash_ref())
92 .await
93 .map_err(KeystoreError::wrap("removing key package from keystore"))?;
94 inner
95 .transaction
96 .remove_borrowed::<StoredHpkePrivateKey>(kp.hpke_init_key().as_slice())
97 .await
98 .map_err(KeystoreError::wrap("removing private key from keystore"))?;
99 inner
100 .transaction
101 .remove_borrowed::<StoredEncryptionKeyPair>(kp.leaf_node().encryption_key().as_slice())
102 .await
103 .map_err(KeystoreError::wrap("removing encryption keypair from keystore"))?;
104
105 Ok(())
106 }
107
108 pub async fn remove_key_packages_for(&self, credential_ref: &CredentialRef) -> Result<()> {
116 let inner = self.inner().await?;
117 let credential = credential_ref
118 .load(&inner.transaction)
119 .await
120 .map_err(RecursiveError::mls_credential_ref("loading credential"))?;
121 let signature_public_key = credential.signature_key_pair.public();
122
123 let mut first_err = None;
124 macro_rules! try_retain_err {
125 ($e:expr) => {
126 match $e {
127 Err(err) => {
128 if first_err.is_none() {
129 first_err = Some(Error::from(err));
130 }
131 continue;
132 }
133 Ok(val) => val,
134 }
135 };
136 }
137
138 let session = self.session().await?;
139 for keypackage in session
140 .get_key_packages()
141 .await
142 .map_err(RecursiveError::mls_client("loading key packages"))?
143 .into_iter()
144 .filter(|keypackage| keypackage.leaf_node().signature_key().as_slice() == signature_public_key)
145 {
146 let kp_ref = try_retain_err!(keypackage.make_ref());
147 try_retain_err!(self.remove_key_package(&kp_ref).await);
148 }
149
150 match first_err {
151 None => Ok(()),
152 Some(err) => Err(err),
153 }
154 }
155
156 pub(crate) async fn restore_key_package(&self, key_package_ref: &[u8]) -> Result<()> {
162 let inner = self.inner().await?;
163
164 inner
165 .transaction
166 .restore::<StoredKeypackage>(key_package_ref)
167 .await
168 .map_err(KeystoreError::wrap(
169 "restoring key package deleted in current transaction",
170 ))?;
171
172 let Some(key_package) = inner
173 .transaction
174 .get_borrowed::<StoredKeypackage>(key_package_ref)
175 .await
176 .map_err(KeystoreError::wrap("loading keypackage from database"))?
177 .map(|stored_keypackage| crate::mls::session::key_package::from_stored(&stored_keypackage))
178 .transpose()
179 .map_err(RecursiveError::mls_client("loading key package"))?
180 else {
181 return Ok(());
182 };
183
184 inner
185 .transaction
186 .restore::<StoredHpkePrivateKey>(key_package.hpke_init_key().as_slice())
187 .await
188 .map_err(KeystoreError::wrap("restoring private key from keystore"))?;
189 inner
190 .transaction
191 .restore::<StoredEncryptionKeyPair>(key_package.leaf_node().encryption_key().as_slice())
192 .await
193 .map_err(KeystoreError::wrap("restoring encryption keypair from keystore"))?;
194
195 Ok(())
196 }
197}