Skip to main content

core_crypto_keystore/transaction/
mls.rs

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