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