Skip to content

[BEEEP/POC] Noise IPC CryptoProvider #219

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking โ€œSign up for GitHubโ€, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions crates/bitwarden-ipc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -19,9 +19,11 @@ wasm = [

[dependencies]
bitwarden-error = { workspace = true }
ciborium = "0.2.2"
js-sys = { workspace = true, optional = true }
serde = { workspace = true }
serde_json = { workspace = true }
snow = "0.9.6"
thiserror = { workspace = true }
tokio = { features = ["sync", "time"], workspace = true }
tsify-next = { workspace = true, optional = true }
12 changes: 12 additions & 0 deletions crates/bitwarden-ipc/src/error.rs
Original file line number Diff line number Diff line change
@@ -7,6 +7,9 @@

#[error("Communication error: {0}")]
Communication(Com),

#[error("Handshake error")]
HandshakeError,
}

#[derive(Clone, Debug, Error, PartialEq, Eq)]
@@ -19,6 +22,12 @@

#[error("Communication error: {0}")]
Communication(Com),

#[error("Handshake error")]
HandshakeError,

#[error("Decode Error")]
DecodeError,
}

#[derive(Clone, Debug, Error, PartialEq, Eq)]
@@ -44,6 +53,9 @@
ReceiveError::Timeout => TypedReceiveError::Timeout,
ReceiveError::Crypto(crypto) => TypedReceiveError::Crypto(crypto),
ReceiveError::Communication(com) => TypedReceiveError::Communication(com),
// todo
ReceiveError::HandshakeError => TypedReceiveError::Timeout,
ReceiveError::DecodeError => TypedReceiveError::Timeout,

Check warning on line 58 in crates/bitwarden-ipc/src/error.rs

Codecov / codecov/patch

crates/bitwarden-ipc/src/error.rs#L57-L58

Added lines #L57 - L58 were not covered by tests
}
}
}
67 changes: 65 additions & 2 deletions crates/bitwarden-ipc/src/ipc_client.rs
Original file line number Diff line number Diff line change
@@ -102,8 +102,11 @@ mod tests {
use crate::{
endpoint::Endpoint,
traits::{
tests::{TestCommunicationBackend, TestCommunicationBackendReceiveError},
InMemorySessionRepository, NoEncryptionCryptoProvider,
tests::{
TestCommunicationBackend, TestCommunicationBackendReceiveError,
TestTwoWayCommunicationBackend,
},
InMemorySessionRepository, NoEncryptionCryptoProvider, NoiseCryptoProvider,
},
};

@@ -369,4 +372,64 @@ mod tests {
Err(TypedReceiveError::Typing(serde_json::Error { .. }))
));
}

#[tokio::test]
async fn communication_provider_ping_pong() {
let (sender_communication_provider, receiver_communication_provider) =
TestTwoWayCommunicationBackend::new();

let a = tokio::spawn(async move {
let receiver_crypto_provider = NoiseCryptoProvider;
let receiver_session_map = InMemorySessionRepository::new(HashMap::new());
let receiver_client = IpcClient::new(
receiver_crypto_provider,
receiver_communication_provider.clone(),
receiver_session_map,
);

for i in 0..10 {
let recv_message = receiver_client.receive(None, None).await.unwrap();
println!(
"A: Received Message {:?}",
String::from_utf8(recv_message.payload.clone())
);
let message = OutgoingMessage {
payload: format!("Hello, world! {}", i).as_bytes().to_vec(),
destination: Endpoint::BrowserBackground,
topic: None,
};
println!("A: Sending Message {:?}", message);
receiver_client.send(message.clone()).await.unwrap();
}
});

let b = tokio::spawn(async move {
let sender_crypto_provider = NoiseCryptoProvider;
let sender_session_map = InMemorySessionRepository::new(HashMap::new());
let sender_client = IpcClient::new(
sender_crypto_provider,
sender_communication_provider.clone(),
sender_session_map,
);

for i in 0..10 {
let message = OutgoingMessage {
payload: format!("Hello, world! {}", i).as_bytes().to_vec(),
destination: Endpoint::BrowserBackground,
topic: None,
};
println!("B: Sending Message {:?}", message);
sender_client.send(message.clone()).await.unwrap();

let recv_message = sender_client.receive(None, None).await.unwrap();
println!(
"B: Received Message {:?}",
String::from_utf8(recv_message.payload.clone())
);
assert_eq!(recv_message.payload, message.payload);
}
});

let _ = tokio::join!(a, b);
}
}
50 changes: 48 additions & 2 deletions crates/bitwarden-ipc/src/traits/communication_backend.rs
Original file line number Diff line number Diff line change
@@ -23,10 +23,13 @@ pub trait CommunicationBackend {
}
#[cfg(test)]
pub mod tests {
use std::{collections::VecDeque, rc::Rc};
use std::{collections::VecDeque, rc::Rc, sync::Arc};

use thiserror::Error;
use tokio::sync::RwLock;
use tokio::sync::{
mpsc::{self, Receiver, Sender},
Mutex, RwLock,
};

use super::*;

@@ -80,4 +83,47 @@ pub mod tests {
}
}
}

#[derive(Debug, Clone)]
pub struct TestTwoWayCommunicationBackend {
outgoing: Sender<OutgoingMessage>,
incoming: Arc<Mutex<Receiver<OutgoingMessage>>>,
}

impl TestTwoWayCommunicationBackend {
pub fn new() -> (Self, Self) {
let (outgoing0, incoming0) = mpsc::channel(10);
let (outgoing1, incoming1) = mpsc::channel(10);
let one = TestTwoWayCommunicationBackend {
outgoing: outgoing0,
incoming: Arc::new(Mutex::new(incoming1)),
};
let two = TestTwoWayCommunicationBackend {
outgoing: outgoing1,
incoming: Arc::new(Mutex::new(incoming0)),
};
(one, two)
}
}

impl CommunicationBackend for TestTwoWayCommunicationBackend {
type SendError = ();
type ReceiveError = TestCommunicationBackendReceiveError;

async fn send(&self, message: OutgoingMessage) -> Result<(), Self::SendError> {
self.outgoing.send(message).await.unwrap();
Ok(())
}

async fn receive(&self) -> Result<IncomingMessage, Self::ReceiveError> {
let mut receiver = self.incoming.lock().await;
let message = receiver.recv().await.unwrap();
Ok(IncomingMessage {
payload: message.payload,
destination: message.destination,
source: crate::endpoint::Endpoint::DesktopRenderer,
topic: None,
})
}
}
}
3 changes: 3 additions & 0 deletions crates/bitwarden-ipc/src/traits/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
mod communication_backend;
mod crypto_provider;
mod noise_crypto_provider;
mod session_repository;

#[cfg(test)]
pub use communication_backend::tests;
pub use communication_backend::CommunicationBackend;
pub use crypto_provider::{CryptoProvider, NoEncryptionCryptoProvider};
#[cfg(test)]
pub use noise_crypto_provider::NoiseCryptoProvider;
pub use session_repository::{InMemorySessionRepository, SessionRepository};
Loading