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