core_crypto_keystore/transaction/
dynamic_dispatch.rs

1//! This module exists merely because the `Entity` trait is not object safe.
2//! See <https://doc.rust-lang.org/reference/items/traits.html#object-safety.>.
3
4use crate::connection::TransactionWrapper;
5use crate::entities::{
6    ConsumerData, E2eiAcmeCA, E2eiCrl, E2eiEnrollment, E2eiIntermediateCert, E2eiRefreshToken, EntityBase,
7    EntityTransactionExt, MlsBufferedCommit, MlsCredential, MlsEncryptionKeyPair, MlsEpochEncryptionKeyPair,
8    MlsHpkePrivateKey, MlsKeyPackage, MlsPendingMessage, MlsPskBundle, MlsSignatureKeyPair, PersistedMlsGroup,
9    PersistedMlsPendingGroup, StringEntityId, UniqueEntity,
10};
11#[cfg(feature = "proteus-keystore")]
12use crate::entities::{ProteusIdentity, ProteusPrekey, ProteusSession};
13use crate::{CryptoKeystoreError, CryptoKeystoreResult};
14
15#[derive(Debug)]
16pub enum Entity {
17    ConsumerData(ConsumerData),
18    SignatureKeyPair(MlsSignatureKeyPair),
19    HpkePrivateKey(MlsHpkePrivateKey),
20    MlsKeyPackage(MlsKeyPackage),
21    PskBundle(MlsPskBundle),
22    EncryptionKeyPair(MlsEncryptionKeyPair),
23    MlsEpochEncryptionKeyPair(MlsEpochEncryptionKeyPair),
24    MlsCredential(MlsCredential),
25    MlsBufferedCommit(MlsBufferedCommit),
26    PersistedMlsGroup(PersistedMlsGroup),
27    PersistedMlsPendingGroup(PersistedMlsPendingGroup),
28    MlsPendingMessage(MlsPendingMessage),
29    E2eiEnrollment(E2eiEnrollment),
30    E2eiRefreshToken(E2eiRefreshToken),
31    E2eiAcmeCA(E2eiAcmeCA),
32    E2eiIntermediateCert(E2eiIntermediateCert),
33    E2eiCrl(E2eiCrl),
34    #[cfg(feature = "proteus-keystore")]
35    ProteusIdentity(ProteusIdentity),
36    #[cfg(feature = "proteus-keystore")]
37    ProteusPrekey(ProteusPrekey),
38    #[cfg(feature = "proteus-keystore")]
39    ProteusSession(ProteusSession),
40}
41
42#[derive(Debug, Clone, PartialEq)]
43pub enum EntityId {
44    SignatureKeyPair(Vec<u8>),
45    HpkePrivateKey(Vec<u8>),
46    KeyPackage(Vec<u8>),
47    PskBundle(Vec<u8>),
48    EncryptionKeyPair(Vec<u8>),
49    EpochEncryptionKeyPair(Vec<u8>),
50    MlsCredential(Vec<u8>),
51    MlsBufferedCommit(Vec<u8>),
52    PersistedMlsGroup(Vec<u8>),
53    PersistedMlsPendingGroup(Vec<u8>),
54    MlsPendingMessage(Vec<u8>),
55    E2eiEnrollment(Vec<u8>),
56    E2eiRefreshToken(Vec<u8>),
57    E2eiAcmeCA(Vec<u8>),
58    E2eiIntermediateCert(Vec<u8>),
59    E2eiCrl(Vec<u8>),
60    #[cfg(feature = "proteus-keystore")]
61    ProteusIdentity(Vec<u8>),
62    #[cfg(feature = "proteus-keystore")]
63    ProteusPrekey(Vec<u8>),
64    #[cfg(feature = "proteus-keystore")]
65    ProteusSession(Vec<u8>),
66}
67
68impl EntityId {
69    fn as_id(&self) -> StringEntityId<'_> {
70        match self {
71            EntityId::SignatureKeyPair(vec) => vec.as_slice().into(),
72            EntityId::HpkePrivateKey(vec) => vec.as_slice().into(),
73            EntityId::KeyPackage(vec) => vec.as_slice().into(),
74            EntityId::PskBundle(vec) => vec.as_slice().into(),
75            EntityId::EncryptionKeyPair(vec) => vec.as_slice().into(),
76            EntityId::EpochEncryptionKeyPair(vec) => vec.as_slice().into(),
77            EntityId::MlsCredential(vec) => vec.as_slice().into(),
78            EntityId::MlsBufferedCommit(vec) => vec.as_slice().into(),
79            EntityId::PersistedMlsGroup(vec) => vec.as_slice().into(),
80            EntityId::PersistedMlsPendingGroup(vec) => vec.as_slice().into(),
81            EntityId::MlsPendingMessage(vec) => vec.as_slice().into(),
82            EntityId::E2eiEnrollment(vec) => vec.as_slice().into(),
83            EntityId::E2eiRefreshToken(vec) => vec.as_slice().into(),
84            EntityId::E2eiAcmeCA(vec) => vec.as_slice().into(),
85            EntityId::E2eiIntermediateCert(vec) => vec.as_slice().into(),
86            EntityId::E2eiCrl(vec) => vec.as_slice().into(),
87            #[cfg(feature = "proteus-keystore")]
88            EntityId::ProteusIdentity(vec) => vec.as_slice().into(),
89            #[cfg(feature = "proteus-keystore")]
90            EntityId::ProteusSession(id) => id.as_slice().into(),
91            #[cfg(feature = "proteus-keystore")]
92            EntityId::ProteusPrekey(vec) => vec.as_slice().into(),
93        }
94    }
95
96    pub(crate) fn from_collection_name(entity_id: &'static str, id: &[u8]) -> CryptoKeystoreResult<Self> {
97        match entity_id {
98            MlsSignatureKeyPair::COLLECTION_NAME => Ok(Self::SignatureKeyPair(id.into())),
99            MlsHpkePrivateKey::COLLECTION_NAME => Ok(Self::HpkePrivateKey(id.into())),
100            MlsKeyPackage::COLLECTION_NAME => Ok(Self::KeyPackage(id.into())),
101            MlsPskBundle::COLLECTION_NAME => Ok(Self::PskBundle(id.into())),
102            MlsEncryptionKeyPair::COLLECTION_NAME => Ok(Self::EncryptionKeyPair(id.into())),
103            MlsEpochEncryptionKeyPair::COLLECTION_NAME => Ok(Self::EpochEncryptionKeyPair(id.into())),
104            MlsBufferedCommit::COLLECTION_NAME => Ok(Self::MlsBufferedCommit(id.into())),
105            PersistedMlsGroup::COLLECTION_NAME => Ok(Self::PersistedMlsGroup(id.into())),
106            PersistedMlsPendingGroup::COLLECTION_NAME => Ok(Self::PersistedMlsPendingGroup(id.into())),
107            MlsCredential::COLLECTION_NAME => Ok(Self::MlsCredential(id.into())),
108            MlsPendingMessage::COLLECTION_NAME => Ok(Self::MlsPendingMessage(id.into())),
109            E2eiEnrollment::COLLECTION_NAME => Ok(Self::E2eiEnrollment(id.into())),
110            E2eiCrl::COLLECTION_NAME => Ok(Self::E2eiCrl(id.into())),
111            E2eiAcmeCA::COLLECTION_NAME => Ok(Self::E2eiAcmeCA(id.into())),
112            E2eiRefreshToken::COLLECTION_NAME => Ok(Self::E2eiRefreshToken(id.into())),
113            E2eiIntermediateCert::COLLECTION_NAME => Ok(Self::E2eiIntermediateCert(id.into())),
114            #[cfg(feature = "proteus-keystore")]
115            ProteusIdentity::COLLECTION_NAME => Ok(Self::ProteusIdentity(id.into())),
116            #[cfg(feature = "proteus-keystore")]
117            ProteusPrekey::COLLECTION_NAME => Ok(Self::ProteusPrekey(id.into())),
118            #[cfg(feature = "proteus-keystore")]
119            ProteusSession::COLLECTION_NAME => Ok(Self::ProteusSession(id.into())),
120            _ => Err(CryptoKeystoreError::NotImplemented),
121        }
122    }
123
124    pub(crate) fn collection_name(&self) -> &'static str {
125        match self {
126            EntityId::SignatureKeyPair(_) => MlsSignatureKeyPair::COLLECTION_NAME,
127            EntityId::KeyPackage(_) => MlsKeyPackage::COLLECTION_NAME,
128            EntityId::PskBundle(_) => MlsPskBundle::COLLECTION_NAME,
129            EntityId::EncryptionKeyPair(_) => MlsEncryptionKeyPair::COLLECTION_NAME,
130            EntityId::EpochEncryptionKeyPair(_) => MlsEpochEncryptionKeyPair::COLLECTION_NAME,
131            EntityId::MlsCredential(_) => MlsCredential::COLLECTION_NAME,
132            EntityId::MlsBufferedCommit(_) => MlsBufferedCommit::COLLECTION_NAME,
133            EntityId::PersistedMlsGroup(_) => PersistedMlsGroup::COLLECTION_NAME,
134            EntityId::PersistedMlsPendingGroup(_) => PersistedMlsPendingGroup::COLLECTION_NAME,
135            EntityId::MlsPendingMessage(_) => MlsPendingMessage::COLLECTION_NAME,
136            EntityId::E2eiEnrollment(_) => E2eiEnrollment::COLLECTION_NAME,
137            EntityId::E2eiRefreshToken(_) => E2eiRefreshToken::COLLECTION_NAME,
138            EntityId::E2eiAcmeCA(_) => E2eiAcmeCA::COLLECTION_NAME,
139            EntityId::E2eiIntermediateCert(_) => E2eiIntermediateCert::COLLECTION_NAME,
140            EntityId::E2eiCrl(_) => E2eiCrl::COLLECTION_NAME,
141            #[cfg(feature = "proteus-keystore")]
142            EntityId::ProteusIdentity(_) => ProteusIdentity::COLLECTION_NAME,
143            #[cfg(feature = "proteus-keystore")]
144            EntityId::ProteusPrekey(_) => ProteusPrekey::COLLECTION_NAME,
145            #[cfg(feature = "proteus-keystore")]
146            EntityId::ProteusSession(_) => ProteusSession::COLLECTION_NAME,
147            EntityId::HpkePrivateKey(_) => MlsHpkePrivateKey::COLLECTION_NAME,
148        }
149    }
150}
151
152pub async fn execute_save(tx: &TransactionWrapper<'_>, entity: &Entity) -> CryptoKeystoreResult<()> {
153    match entity {
154        Entity::ConsumerData(consumer_data) => consumer_data.replace(tx).await,
155        Entity::SignatureKeyPair(mls_signature_key_pair) => mls_signature_key_pair.save(tx).await,
156        Entity::HpkePrivateKey(mls_hpke_private_key) => mls_hpke_private_key.save(tx).await,
157        Entity::MlsKeyPackage(mls_key_package) => mls_key_package.save(tx).await,
158        Entity::PskBundle(mls_psk_bundle) => mls_psk_bundle.save(tx).await,
159        Entity::EncryptionKeyPair(mls_encryption_key_pair) => mls_encryption_key_pair.save(tx).await,
160        Entity::MlsEpochEncryptionKeyPair(mls_epoch_encryption_key_pair) => {
161            mls_epoch_encryption_key_pair.save(tx).await
162        }
163        Entity::MlsCredential(mls_credential) => mls_credential.save(tx).await,
164        Entity::MlsBufferedCommit(mls_pending_commit) => mls_pending_commit.save(tx).await,
165        Entity::PersistedMlsGroup(persisted_mls_group) => persisted_mls_group.save(tx).await,
166        Entity::PersistedMlsPendingGroup(persisted_mls_pending_group) => persisted_mls_pending_group.save(tx).await,
167        Entity::MlsPendingMessage(mls_pending_message) => mls_pending_message.save(tx).await,
168        Entity::E2eiEnrollment(e2ei_enrollment) => e2ei_enrollment.save(tx).await,
169        Entity::E2eiRefreshToken(e2ei_refresh_token) => e2ei_refresh_token.replace(tx).await,
170        Entity::E2eiAcmeCA(e2ei_acme_ca) => e2ei_acme_ca.replace(tx).await,
171        Entity::E2eiIntermediateCert(e2ei_intermediate_cert) => e2ei_intermediate_cert.save(tx).await,
172        Entity::E2eiCrl(e2ei_crl) => e2ei_crl.save(tx).await,
173        #[cfg(feature = "proteus-keystore")]
174        Entity::ProteusSession(record) => record.save(tx).await,
175        #[cfg(feature = "proteus-keystore")]
176        Entity::ProteusIdentity(record) => record.save(tx).await,
177        #[cfg(feature = "proteus-keystore")]
178        Entity::ProteusPrekey(record) => record.save(tx).await,
179    }
180}
181
182pub async fn execute_delete(tx: &TransactionWrapper<'_>, entity_id: &EntityId) -> CryptoKeystoreResult<()> {
183    match entity_id {
184        id @ EntityId::SignatureKeyPair(_) => MlsSignatureKeyPair::delete(tx, id.as_id()).await,
185        id @ EntityId::HpkePrivateKey(_) => MlsHpkePrivateKey::delete(tx, id.as_id()).await,
186        id @ EntityId::KeyPackage(_) => MlsKeyPackage::delete(tx, id.as_id()).await,
187        id @ EntityId::PskBundle(_) => MlsPskBundle::delete(tx, id.as_id()).await,
188        id @ EntityId::EncryptionKeyPair(_) => MlsEncryptionKeyPair::delete(tx, id.as_id()).await,
189        id @ EntityId::EpochEncryptionKeyPair(_) => MlsEpochEncryptionKeyPair::delete(tx, id.as_id()).await,
190        id @ EntityId::MlsCredential(_) => MlsCredential::delete(tx, id.as_id()).await,
191        id @ EntityId::MlsBufferedCommit(_) => MlsBufferedCommit::delete(tx, id.as_id()).await,
192        id @ EntityId::PersistedMlsGroup(_) => PersistedMlsGroup::delete(tx, id.as_id()).await,
193        id @ EntityId::PersistedMlsPendingGroup(_) => PersistedMlsPendingGroup::delete(tx, id.as_id()).await,
194        id @ EntityId::MlsPendingMessage(_) => MlsPendingMessage::delete(tx, id.as_id()).await,
195        id @ EntityId::E2eiEnrollment(_) => E2eiEnrollment::delete(tx, id.as_id()).await,
196        id @ EntityId::E2eiRefreshToken(_) => E2eiRefreshToken::delete(tx, id.as_id()).await,
197        id @ EntityId::E2eiAcmeCA(_) => E2eiAcmeCA::delete(tx, id.as_id()).await,
198        id @ EntityId::E2eiIntermediateCert(_) => E2eiIntermediateCert::delete(tx, id.as_id()).await,
199        id @ EntityId::E2eiCrl(_) => E2eiCrl::delete(tx, id.as_id()).await,
200        #[cfg(feature = "proteus-keystore")]
201        id @ EntityId::ProteusSession(_) => ProteusSession::delete(tx, id.as_id()).await,
202        #[cfg(feature = "proteus-keystore")]
203        id @ EntityId::ProteusIdentity(_) => ProteusIdentity::delete(tx, id.as_id()).await,
204        #[cfg(feature = "proteus-keystore")]
205        id @ EntityId::ProteusPrekey(_) => ProteusPrekey::delete(tx, id.as_id()).await,
206    }
207}