core_crypto/transaction_context/
key_package.rs1use std::time::Duration;
4
5use core_crypto_keystore::{
6 Sha256Hash,
7 entities::{StoredEncryptionKeyPair, StoredHpkePrivateKey, StoredKeyPackage},
8 traits::EntityDeleteBorrowed as _,
9};
10use openmls::prelude::{CryptoConfig, Lifetime};
11
12use super::{Error, Result, TransactionContext};
13use crate::{
14 ConversationConfiguration, CredentialRef, Keypackage, KeypackageRef, KeystoreError, RecursiveError,
15 mls::key_package::KeypackageExt as _,
16};
17
18pub const KEYPACKAGE_DEFAULT_LIFETIME: Duration = Duration::from_secs(60 * 60 * 24 * 28 * 3); impl TransactionContext {
29 pub async fn generate_key_package(
39 &self,
40 credential_ref: &CredentialRef,
41 lifetime: Option<Duration>,
42 ) -> Result<Keypackage> {
43 let inner = self.inner()?;
44 let lifetime = Lifetime::new(lifetime.unwrap_or(KEYPACKAGE_DEFAULT_LIFETIME).as_secs());
45 let credential = credential_ref
46 .load(&inner.transaction)
47 .await
48 .map_err(RecursiveError::context("loading credential"))?;
49 let config = CryptoConfig {
50 ciphersuite: credential.cipher_suite.into(),
51 version: openmls::versions::ProtocolVersion::default(),
52 };
53
54 Keypackage::builder()
55 .leaf_node_capabilities(ConversationConfiguration::default_leaf_capabilities())
56 .key_package_lifetime(lifetime)
57 .build(
58 config,
59 &self.crypto_provider().await?,
60 &credential.signature_key_pair,
61 credential.to_mls_credential_with_key(),
62 )
63 .await
64 .map_err(Error::key_package_new())
65 }
66
67 pub async fn get_key_package_refs(&self) -> Result<Vec<KeypackageRef>> {
69 let session = self.session().await?;
70 session
71 .get_keypackage_refs()
72 .await
73 .map_err(RecursiveError::context("getting all key package refs for transaction"))
74 .map_err(Into::into)
75 }
76
77 pub async fn remove_key_package(&self, kp_ref: &KeypackageRef) -> Result<()> {
84 let Some(kp) = self
85 .session()
86 .await?
87 .load_key_package(kp_ref)
88 .await
89 .map_err(RecursiveError::context("loading key packages on session"))?
90 else {
91 return Ok(());
92 };
93
94 let inner = self.inner()?;
95 let tx = inner.transaction();
96 StoredKeyPackage::delete_borrowed(tx, kp_ref.hash_ref())
97 .map_err(KeystoreError::wrap("removing key package from keystore"))?;
98 StoredHpkePrivateKey::delete_borrowed(tx, kp.hpke_init_key().as_slice())
99 .map_err(KeystoreError::wrap("removing private key from keystore"))?;
100 StoredEncryptionKeyPair::delete_borrowed(tx, kp.leaf_node().encryption_key().as_slice())
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 mut first_err = None;
115 macro_rules! try_retain_err {
116 ($e:expr) => {
117 match $e {
118 Err(err) => {
119 if first_err.is_none() {
120 first_err = Some(Error::from(err));
121 }
122 continue;
123 }
124 Ok(val) => val,
125 }
126 };
127 }
128
129 let session = self.session().await?;
130 for keypackage in session
131 .get_key_packages()
132 .await
133 .map_err(RecursiveError::context("loading key packages"))?
134 .into_iter()
135 .filter(|keypackage| {
136 Sha256Hash::hash_from(keypackage.leaf_node().signature_key().as_slice())
137 == credential_ref.public_key_hash()
138 })
139 {
140 let kp_ref = try_retain_err!(keypackage.make_ref());
141 try_retain_err!(self.remove_key_package(&kp_ref).await);
142 }
143
144 match first_err {
145 None => Ok(()),
146 Some(err) => Err(err),
147 }
148 }
149}