core_crypto_keystore/transaction/
mls.rs1use openmls_traits::key_store::{MlsEntity, MlsEntityId};
2use rusqlite::Connection;
3
4use crate::{
5 CryptoKeystoreError, Sha256Hash, Transaction,
6 ancillary::ConversationIdRef,
7 deser,
8 entities::{
9 PersistedMlsGroup, StoredEncryptionKeyPair, StoredEpochEncryptionKeypair, StoredEpochEncryptionKeypairPkRef,
10 StoredHpkePrivateKey, StoredKeyPackage, StoredPskBundle,
11 },
12 ser,
13 traits::{Entity as _, EntityDatabaseMutation as _, EntityDeleteBorrowed as _, EntityGetBorrowed as _},
14};
15
16pub(crate) fn read_mls_entity<V: MlsEntity>(conn: &Connection, id: &[u8]) -> Option<V> {
18 if id.is_empty() {
19 return None;
20 }
21
22 match V::ID {
23 MlsEntityId::GroupState => {
24 let v = PersistedMlsGroup::get_borrowed(conn, ConversationIdRef::new(id))
25 .ok()
26 .flatten()?;
27 deser(&v.state).ok()
28 }
29 MlsEntityId::SignatureKeyPair => {
30 unimplemented!("Don't use this API to load a signature key pair. Load a StoredCredential instead.")
31 }
32 MlsEntityId::KeyPackage => {
33 let v = StoredKeyPackage::get_borrowed(conn, id).ok().flatten()?;
34 deser(&v.key_package).ok()
35 }
36 MlsEntityId::HpkePrivateKey => {
37 let pub_key_hash = Sha256Hash::hash_from(id);
39 let v = StoredHpkePrivateKey::get(conn, &pub_key_hash).ok().flatten()?;
40 deser(&v.secret_key).ok()
41 }
42 MlsEntityId::PskBundle => {
43 let v = StoredPskBundle::get_borrowed(conn, id).ok().flatten()?;
44 deser(&v.psk).ok()
45 }
46 MlsEntityId::EncryptionKeyPair => {
47 let v = StoredEncryptionKeyPair::get_borrowed(conn, id).ok().flatten()?;
48 deser(&v.sk).ok()
49 }
50 MlsEntityId::EpochEncryptionKeyPair => {
51 let kp_ref = StoredEpochEncryptionKeypairPkRef::parse_bytes(id).ok()?;
52 let v = StoredEpochEncryptionKeypair::get_borrowed(conn, kp_ref)
53 .ok()
54 .flatten()?;
55 deser(&v.keypairs).ok()
56 }
57 }
58}
59
60#[cfg_attr(target_os = "unknown", async_trait::async_trait(?Send))]
61#[cfg_attr(not(target_os = "unknown"), async_trait::async_trait)]
62impl openmls_traits::key_store::OpenMlsKeyStore for Transaction {
63 type Error = CryptoKeystoreError;
64
65 async fn store<V: MlsEntity + Sync>(&self, id: &[u8], value: &V) -> Result<(), Self::Error>
66 where
67 Self: Sized,
68 {
69 if id.is_empty() {
70 return Err(CryptoKeystoreError::MlsKeyStoreError(
71 "The provided key is empty".into(),
72 ));
73 }
74
75 let data = ser(value)?;
76
77 match V::ID {
78 MlsEntityId::GroupState => {
79 return Err(CryptoKeystoreError::IncorrectApiUsage(
80 "Groups must not be saved using OpenMLS's APIs. You should use the keystore's provided methods",
81 ));
82 }
83 MlsEntityId::SignatureKeyPair => {
84 return Err(CryptoKeystoreError::IncorrectApiUsage(
85 "Signature keys must not be saved using OpenMLS's APIs. Save a credential via the keystore API
86 instead.",
87 ));
88 }
89 MlsEntityId::KeyPackage => {
90 StoredKeyPackage::from_openmls(id, data, value).save(self)?;
91 }
92 MlsEntityId::HpkePrivateKey => {
93 StoredHpkePrivateKey {
94 public_key_hash: Sha256Hash::hash_from(id),
95 secret_key: data,
96 }
97 .save(self)?;
98 }
99 MlsEntityId::PskBundle => {
100 StoredPskBundle {
101 psk_id: id.into(),
102 psk: data,
103 }
104 .save(self)?;
105 }
106 MlsEntityId::EncryptionKeyPair => {
107 StoredEncryptionKeyPair {
108 pk: id.into(),
109 sk: data,
110 }
111 .save(self)?;
112 }
113 MlsEntityId::EpochEncryptionKeyPair => {
114 let StoredEpochEncryptionKeypairPkRef {
115 conversation_id,
116 own_leaf_idx,
117 epoch,
118 } = StoredEpochEncryptionKeypairPkRef::parse_bytes(id)?;
119 StoredEpochEncryptionKeypair {
120 conversation_id: conversation_id.bytes().into(),
121 own_leaf_idx,
122 epoch,
123 keypairs: data,
124 }
125 .save(self)?;
126 }
127 }
128
129 Ok(())
130 }
131
132 async fn read<V: MlsEntity>(&self, id: &[u8]) -> Option<V>
133 where
134 Self: Sized,
135 {
136 let conn = self.conn().ok()?;
137 read_mls_entity(&conn, id)
138 }
139
140 async fn delete<V: MlsEntity>(&self, id: &[u8]) -> Result<(), Self::Error> {
141 match V::ID {
142 MlsEntityId::SignatureKeyPair => unimplemented!(
143 "Deleting a signature key pair should not be done through this API, any keypair should be deleted via
144 deleting a credential."
145 ),
146 MlsEntityId::GroupState => PersistedMlsGroup::delete_borrowed(self, ConversationIdRef::new(id))?,
147 MlsEntityId::HpkePrivateKey => StoredHpkePrivateKey::delete(self, &Sha256Hash::hash_from(id))?,
148 MlsEntityId::KeyPackage => StoredKeyPackage::delete_borrowed(self, id)?,
149 MlsEntityId::PskBundle => StoredPskBundle::delete_borrowed(self, id)?,
150 MlsEntityId::EncryptionKeyPair => StoredEncryptionKeyPair::delete_borrowed(self, id)?,
151 MlsEntityId::EpochEncryptionKeyPair => {
152 let kp_ref = StoredEpochEncryptionKeypairPkRef::parse_bytes(id)?;
153 StoredEpochEncryptionKeypair::delete_borrowed(self, kp_ref)?
154 }
155 };
156
157 Ok(())
158 }
159}