core_crypto_keystore/transaction/
mls.rs1use openmls::prelude::Ciphersuite;
2use openmls_basic_credential::SignatureKeyPair;
3use openmls_traits::key_store::{MlsEntity, MlsEntityId, OpenMlsKeyStore};
4
5use crate::{
6 CryptoKeystoreError, Sha256Hash, Transaction, deser,
7 entities::{
8 PersistedMlsGroup, StoredCredential, StoredEncryptionKeyPair, StoredEpochEncryptionKeypair,
9 StoredHpkePrivateKey, StoredKeypackage, StoredPskBundle,
10 },
11 ser,
12 traits::FetchFromDatabase,
13};
14
15#[cfg_attr(target_os = "unknown", async_trait::async_trait(?Send))]
16#[cfg_attr(not(target_os = "unknown"), async_trait::async_trait)]
17impl OpenMlsKeyStore for Transaction {
18 type Error = CryptoKeystoreError;
19
20 async fn store<V: MlsEntity + Sync>(&self, id: &[u8], value: &V) -> Result<(), Self::Error>
21 where
22 Self: Sized,
23 {
24 if id.is_empty() {
25 return Err(CryptoKeystoreError::MlsKeyStoreError(
26 "The provided key is empty".into(),
27 ));
28 }
29
30 let data = ser(value)?;
31
32 match V::ID {
33 MlsEntityId::GroupState => {
34 return Err(CryptoKeystoreError::IncorrectApiUsage(
35 "Groups must not be saved using OpenMLS's APIs. You should use the keystore's provided methods",
36 ));
37 }
38 MlsEntityId::SignatureKeyPair => {
39 return Err(CryptoKeystoreError::IncorrectApiUsage(
40 "Signature keys must not be saved using OpenMLS's APIs. Save a credential via the keystore API
41 instead.",
42 ));
43 }
44 MlsEntityId::KeyPackage => {
45 let kp = StoredKeypackage {
46 keypackage_ref: id.into(),
47 keypackage: data,
48 };
49 self.save(kp).await?;
50 }
51 MlsEntityId::HpkePrivateKey => {
52 let kp = StoredHpkePrivateKey {
53 pk: id.into(),
54 sk: data,
55 };
56 self.save(kp).await?;
57 }
58 MlsEntityId::PskBundle => {
59 let kp = StoredPskBundle {
60 psk_id: id.into(),
61 psk: data,
62 };
63 self.save(kp).await?;
64 }
65 MlsEntityId::EncryptionKeyPair => {
66 let kp = StoredEncryptionKeyPair {
67 pk: id.into(),
68 sk: data,
69 };
70 self.save(kp).await?;
71 }
72 MlsEntityId::EpochEncryptionKeyPair => {
73 let kp = StoredEpochEncryptionKeypair {
74 id: id.into(),
75 keypairs: data,
76 };
77 self.save(kp).await?;
78 }
79 }
80
81 Ok(())
82 }
83
84 async fn read<V: MlsEntity>(&self, id: &[u8]) -> Option<V>
85 where
86 Self: Sized,
87 {
88 if id.is_empty() {
89 return None;
90 }
91
92 match V::ID {
93 MlsEntityId::GroupState => {
94 let v = FetchFromDatabase::get_borrowed::<PersistedMlsGroup>(self, id)
95 .await
96 .ok()
97 .flatten()?;
98 deser(&v.state).ok()
99 }
100 MlsEntityId::SignatureKeyPair => {
101 let hash = Sha256Hash::from_existing_hash(id).ok()?;
102 let stored_credential = FetchFromDatabase::get::<StoredCredential>(self, &hash)
103 .await
104 .ok()
105 .flatten()?;
106 let ciphersuite = Ciphersuite::try_from(stored_credential.ciphersuite).ok()?;
107 let signature_scheme = ciphersuite.signature_algorithm();
108
109 let mls_keypair = SignatureKeyPair::from_raw(
110 signature_scheme,
111 stored_credential.private_key.to_vec(),
112 stored_credential.public_key.to_vec(),
113 );
114
115 let data = ser(&mls_keypair).ok()?;
118 deser(&data).ok()
119 }
120 MlsEntityId::KeyPackage => {
121 let v = FetchFromDatabase::get_borrowed::<StoredKeypackage>(self, id)
122 .await
123 .ok()
124 .flatten()?;
125 deser(&v.keypackage).ok()
126 }
127 MlsEntityId::HpkePrivateKey => {
128 let v = FetchFromDatabase::get_borrowed::<StoredHpkePrivateKey>(self, id)
129 .await
130 .ok()
131 .flatten()?;
132 deser(&v.sk).ok()
133 }
134 MlsEntityId::PskBundle => {
135 let v = FetchFromDatabase::get_borrowed::<StoredPskBundle>(self, id)
136 .await
137 .ok()
138 .flatten()?;
139 deser(&v.psk).ok()
140 }
141 MlsEntityId::EncryptionKeyPair => {
142 let v = FetchFromDatabase::get_borrowed::<StoredEncryptionKeyPair>(self, id)
143 .await
144 .ok()
145 .flatten()?;
146 deser(&v.sk).ok()
147 }
148 MlsEntityId::EpochEncryptionKeyPair => {
149 let v = FetchFromDatabase::get_borrowed::<StoredEpochEncryptionKeypair>(self, id)
150 .await
151 .ok()
152 .flatten()?;
153 deser(&v.keypairs).ok()
154 }
155 }
156 }
157
158 async fn delete<V: MlsEntity>(&self, id: &[u8]) -> Result<(), Self::Error> {
159 match V::ID {
160 MlsEntityId::GroupState => self.remove_borrowed::<PersistedMlsGroup>(id).await?,
161 MlsEntityId::SignatureKeyPair => unimplemented!(
162 "Deleting a signature key pair should not be done through this API, any keypair should be deleted via
163 deleting a credential."
164 ),
165 MlsEntityId::HpkePrivateKey => self.remove_borrowed::<StoredHpkePrivateKey>(id).await?,
166 MlsEntityId::KeyPackage => self.remove_borrowed::<StoredKeypackage>(id).await?,
167 MlsEntityId::PskBundle => self.remove_borrowed::<StoredPskBundle>(id).await?,
168 MlsEntityId::EncryptionKeyPair => self.remove_borrowed::<StoredEncryptionKeyPair>(id).await?,
169 MlsEntityId::EpochEncryptionKeyPair => self.remove_borrowed::<StoredEpochEncryptionKeypair>(id).await?,
170 }
171
172 Ok(())
173 }
174}