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::context("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::context("getting all key package refs for transaction"))
66 .map_err(Into::into)
67 }
68
69 pub async fn remove_key_package(&self, kp_ref: &KeypackageRef) -> Result<()> {
76 let Some(kp) = self
77 .session()
78 .await?
79 .load_key_package(kp_ref)
80 .await
81 .map_err(RecursiveError::context("loading key packages on session"))?
82 else {
83 return Ok(());
84 };
85
86 let inner = self.inner().await?;
87 inner
88 .transaction
89 .remove_borrowed::<StoredKeyPackage>(kp_ref.hash_ref())
90 .await
91 .map_err(KeystoreError::wrap("removing key package from keystore"))?;
92 inner
93 .transaction
94 .remove_borrowed::<StoredHpkePrivateKey>(kp.hpke_init_key().as_slice())
95 .await
96 .map_err(KeystoreError::wrap("removing private key from keystore"))?;
97 inner
98 .transaction
99 .remove_borrowed::<StoredEncryptionKeyPair>(kp.leaf_node().encryption_key().as_slice())
100 .await
101 .map_err(KeystoreError::wrap("removing encryption keypair from keystore"))?;
102
103 Ok(())
104 }
105
106 pub async fn remove_key_packages_for(&self, credential_ref: &CredentialRef) -> Result<()> {
114 let inner = self.inner().await?;
115 let credential = credential_ref
116 .load(&inner.transaction)
117 .await
118 .map_err(RecursiveError::context("loading credential"))?;
119 let signature_public_key = credential.signature_key_pair.public();
120
121 let mut first_err = None;
122 macro_rules! try_retain_err {
123 ($e:expr) => {
124 match $e {
125 Err(err) => {
126 if first_err.is_none() {
127 first_err = Some(Error::from(err));
128 }
129 continue;
130 }
131 Ok(val) => val,
132 }
133 };
134 }
135
136 let session = self.session().await?;
137 for keypackage in session
138 .get_key_packages()
139 .await
140 .map_err(RecursiveError::context("loading key packages"))?
141 .into_iter()
142 .filter(|keypackage| keypackage.leaf_node().signature_key().as_slice() == signature_public_key)
143 {
144 let kp_ref = try_retain_err!(keypackage.make_ref());
145 try_retain_err!(self.remove_key_package(&kp_ref).await);
146 }
147
148 match first_err {
149 None => Ok(()),
150 Some(err) => Err(err),
151 }
152 }
153
154 pub(crate) async fn restore_key_package(&self, key_package_ref: &[u8]) -> Result<()> {
160 let inner = self.inner().await?;
161
162 inner
163 .transaction
164 .restore::<StoredKeyPackage>(key_package_ref)
165 .await
166 .map_err(KeystoreError::wrap(
167 "restoring key package deleted in current transaction",
168 ))?;
169
170 let Some(key_package) = inner
171 .transaction
172 .get_borrowed::<StoredKeyPackage>(key_package_ref)
173 .await
174 .map_err(KeystoreError::wrap("loading keypackage from database"))?
175 .map(crate::mls::session::key_package::from_stored)
176 .transpose()
177 .map_err(RecursiveError::context("loading key package"))?
178 else {
179 return Ok(());
180 };
181
182 inner
183 .transaction
184 .restore::<StoredHpkePrivateKey>(key_package.hpke_init_key().as_slice())
185 .await
186 .map_err(KeystoreError::wrap("restoring private key from keystore"))?;
187 inner
188 .transaction
189 .restore::<StoredEncryptionKeyPair>(key_package.leaf_node().encryption_key().as_slice())
190 .await
191 .map_err(KeystoreError::wrap("restoring encryption keypair from keystore"))?;
192
193 Ok(())
194 }
195}