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,
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
16/// Implementation of the `MlsEntity::read` function; we want to share this elsewhere.
17pub(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}