bitwarden_ipc/traits/crypto_provider.rs
1use std::fmt::Debug;
2
3use super::{CommunicationBackend, CommunicationBackendReceiver, SessionRepository};
4use crate::message::{IncomingMessage, OutgoingMessage};
5
6pub trait CryptoProvider<Com, Ses>: Send + Sync + 'static
7where
8 Com: CommunicationBackend,
9 Ses: SessionRepository<Self::Session>,
10{
11 type Session: Send + Sync + 'static;
12 type SendError: Debug + Send + Sync + 'static;
13 type ReceiveError: Debug + Send + Sync + 'static;
14
15 /// Send a message.
16 ///
17 /// Calling this function may result in multiple messages being sent, depending on the
18 /// implementation of the trait. For example, if the destination does not have a
19 /// session, the function may first send a message to establish a session and then send the
20 /// original message. The implementation of this function should handle this logic.
21 ///
22 /// An error should only be returned for fatal and unrecoverable errors e.g. if the session
23 /// storage is full or cannot be accessed. Returning an error will cause the IPC client to
24 /// stop processing messages.
25 fn send(
26 &self,
27 communication: &Com,
28 sessions: &Ses,
29 message: OutgoingMessage,
30 ) -> impl std::future::Future<Output = Result<(), Self::SendError>> + Send;
31
32 /// Receive a message.
33 ///
34 /// Calling this function may also result in messages being sent, depending on the trait
35 /// implementation. For example, if an encrypted message is received from a destination that
36 /// does not have a session. The function may then try to establish a session and then
37 /// re-request the original message. The implementation of this function should handle this
38 /// logic.
39 ///
40 /// An error should only be returned for fatal and unrecoverable errors e.g. if the session
41 /// storage is full or cannot be accessed. Returning an error will cause the IPC client to
42 /// stop processing messages.
43 fn receive(
44 &self,
45 receiver: &Com::Receiver,
46 communication: &Com,
47 sessions: &Ses,
48 ) -> impl std::future::Future<Output = Result<IncomingMessage, Self::ReceiveError>> + Send + Sync;
49}
50
51/// A no-op crypto provider that performs no encryption and simply passes messages through as-is.
52pub struct NoEncryptionCryptoProvider;
53
54impl<Com, Ses> CryptoProvider<Com, Ses> for NoEncryptionCryptoProvider
55where
56 Com: CommunicationBackend,
57 Ses: SessionRepository<()>,
58{
59 type Session = ();
60 type SendError = Com::SendError;
61 type ReceiveError = <Com::Receiver as CommunicationBackendReceiver>::ReceiveError;
62
63 async fn send(
64 &self,
65 communication: &Com,
66 _sessions: &Ses,
67 message: OutgoingMessage,
68 ) -> Result<(), Self::SendError> {
69 communication.send(message).await
70 }
71
72 async fn receive(
73 &self,
74 receiver: &Com::Receiver,
75 _communication: &Com,
76 _sessions: &Ses,
77 ) -> Result<IncomingMessage, Self::ReceiveError> {
78 receiver.receive().await
79 }
80}