core_crypto/transaction_context/
key_package.rs1use std::time::Duration;
4
5use core_crypto_keystore::{
6 entities::{StoredEncryptionKeyPair, StoredHpkePrivateKey, StoredKeyPackage},
7 traits::EntityDeleteBorrowed 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 let tx = inner.transaction();
88 StoredKeyPackage::delete_borrowed(tx, kp_ref.hash_ref())
89 .map_err(KeystoreError::wrap("removing key package from keystore"))?;
90 StoredHpkePrivateKey::delete_borrowed(tx, kp.hpke_init_key().as_slice())
91 .map_err(KeystoreError::wrap("removing private key from keystore"))?;
92 StoredEncryptionKeyPair::delete_borrowed(tx, kp.leaf_node().encryption_key().as_slice())
93 .map_err(KeystoreError::wrap("removing encryption keypair from keystore"))?;
94
95 Ok(())
96 }
97
98 pub async fn remove_key_packages_for(&self, credential_ref: &CredentialRef) -> Result<()> {
106 let inner = self.inner().await?;
107 let credential = credential_ref
108 .load(&inner.transaction)
109 .await
110 .map_err(RecursiveError::context("loading credential"))?;
111 let signature_public_key = credential.signature_key_pair.public();
112
113 let mut first_err = None;
114 macro_rules! try_retain_err {
115 ($e:expr) => {
116 match $e {
117 Err(err) => {
118 if first_err.is_none() {
119 first_err = Some(Error::from(err));
120 }
121 continue;
122 }
123 Ok(val) => val,
124 }
125 };
126 }
127
128 let session = self.session().await?;
129 for keypackage in session
130 .get_key_packages()
131 .await
132 .map_err(RecursiveError::context("loading key packages"))?
133 .into_iter()
134 .filter(|keypackage| keypackage.leaf_node().signature_key().as_slice() == signature_public_key)
135 {
136 let kp_ref = try_retain_err!(keypackage.make_ref());
137 try_retain_err!(self.remove_key_package(&kp_ref).await);
138 }
139
140 match first_err {
141 None => Ok(()),
142 Some(err) => Err(err),
143 }
144 }
145}