use crate::{
hash::Hash,
key::PublicKey,
noise::{CipherState, CipherStateError},
};
pub struct TransportState<H: Hash, PK: PublicKey> {
handshake_hash: H::HASH,
local: CipherState,
remote: CipherState,
remote_id: PK,
}
pub struct TransportSendHalf<H: Hash, PK: PublicKey> {
handshake_hash: H::HASH,
local: CipherState,
remote_id: PK,
}
pub struct TransportReceiveHalf<H: Hash, PK: PublicKey> {
handshake_hash: H::HASH,
remote: CipherState,
remote_id: PK,
}
impl<H: Hash, PK: PublicKey> TransportState<H, PK> {
pub(crate) fn new(
handshake_hash: H::HASH,
local: CipherState,
remote: CipherState,
remote_id: PK,
) -> Self {
TransportState {
handshake_hash,
local,
remote,
remote_id,
}
}
pub fn split(self) -> (TransportSendHalf<H, PK>, TransportReceiveHalf<H, PK>) {
let Self {
handshake_hash,
local,
remote,
remote_id,
} = self;
let send = TransportSendHalf {
handshake_hash: handshake_hash.clone(),
local,
remote_id: remote_id.clone(),
};
let receive = TransportReceiveHalf {
handshake_hash,
remote,
remote_id,
};
(send, receive)
}
pub fn noise_session(&self) -> &H::HASH {
&self.handshake_hash
}
pub fn remote_public_identity(&self) -> &PK {
&self.remote_id
}
pub fn count_received(&self) -> u64 {
self.remote.nonce().into_u64()
}
pub fn count_sent(&self) -> u64 {
self.local.nonce().into_u64()
}
pub fn send(
&mut self,
input: impl AsRef<[u8]>,
output: &mut [u8],
) -> Result<(), CipherStateError> {
self.local.encrypt_with_ad(&[], input, output)?;
self.local.rekey();
Ok(())
}
pub fn receive(
&mut self,
input: impl AsRef<[u8]>,
output: &mut [u8],
) -> Result<(), CipherStateError> {
self.remote.decrypt_with_ad(&[], input, output)?;
self.remote.rekey();
Ok(())
}
}
impl<H: Hash, PK: PublicKey> TransportSendHalf<H, PK> {
pub fn noise_session(&self) -> &H::HASH {
&self.handshake_hash
}
pub fn remote_public_identity(&self) -> &PK {
&self.remote_id
}
pub fn count_sent(&self) -> u64 {
self.local.nonce().into_u64()
}
pub fn send(
&mut self,
input: impl AsRef<[u8]>,
output: &mut [u8],
) -> Result<(), CipherStateError> {
self.local.encrypt_with_ad(&[], input, output)?;
self.local.rekey();
Ok(())
}
}
impl<H: Hash, PK: PublicKey> TransportReceiveHalf<H, PK> {
pub fn noise_session(&self) -> &H::HASH {
&self.handshake_hash
}
pub fn remote_public_identity(&self) -> &PK {
&self.remote_id
}
pub fn count_received(&self) -> u64 {
self.remote.nonce().into_u64()
}
pub fn receive(
&mut self,
input: impl AsRef<[u8]>,
output: &mut [u8],
) -> Result<(), CipherStateError> {
self.remote.decrypt_with_ad(&[], input, output)?;
self.remote.rekey();
Ok(())
}
}
#[cfg(test)]
pub(crate) mod tests {
use super::*;
pub fn test_transport<H: Hash, PK: PublicKey>(
mut initiator: TransportState<H, PK>,
mut responder: TransportState<H, PK>,
messages_init_to_responder: Vec<Vec<u8>>,
messages_resp_to_initiator: Vec<Vec<u8>>,
) -> bool {
for message in messages_init_to_responder {
let mut output = vec![0; message.len() + CipherState::TAG_LEN];
initiator
.send(&message, &mut output)
.expect("send encrypted message");
let input = output;
let mut output = vec![0; message.len()];
responder
.receive(&input, &mut output)
.expect("receive message");
assert!(message == output, "decryption of the message failed")
}
for message in messages_resp_to_initiator {
let mut output = vec![0; message.len() + CipherState::TAG_LEN];
responder
.send(&message, &mut output)
.expect("send encrypted message");
let input = output;
let mut output = vec![0; message.len()];
initiator
.receive(&input, &mut output)
.expect("receive message");
assert!(message == output, "decryption of the message failed")
}
true
}
}