use crate::bytearray::ByteArray;
use crate::cipherstate::CipherStates;
use crate::constants::MAX_MESSAGE_LEN;
use crate::error::{HandshakeError, HandshakeResult, TransportError, TransportResult};
use crate::traits::{Cipher, Handshaker, Hash};
pub struct TransportState<C: Cipher, H: Hash> {
cipherstates: CipherStates<C>,
h: H::Output,
initiator: bool,
}
impl<C: Cipher, H: Hash> TransportState<C, H> {
pub fn new<Hs: Handshaker<C, H>>(hs: Hs) -> HandshakeResult<TransportState<C, H>> {
if !hs.is_finished() {
return Err(HandshakeError::InvalidState);
}
Ok(TransportState {
cipherstates: hs.get_ciphers(),
h: hs.get_hash(),
initiator: hs.is_initiator(),
})
}
pub fn send(&mut self, msg: &[u8], buf: &mut [u8]) -> TransportResult<usize> {
let out_len = msg.len() + C::tag_len();
if out_len > MAX_MESSAGE_LEN {
panic!("Maximum Noise message length exceeded");
}
if buf.len() < out_len {
return Err(TransportError::BufferTooSmall);
}
let c = if self.initiator {
&mut self.cipherstates.initiator_to_responder
} else {
&mut self.cipherstates.responder_to_initiator
};
c.encrypt_with_ad(&[], msg, &mut buf[..out_len])?;
Ok(out_len)
}
pub fn send_in_place(&mut self, msg: &mut [u8], msg_len: usize) -> TransportResult<usize> {
let out_len = msg_len + C::tag_len();
if out_len > MAX_MESSAGE_LEN {
panic!("Maximum Noise message length exceeded");
}
if msg.len() < out_len {
return Err(TransportError::BufferTooSmall);
}
let c = if self.initiator {
&mut self.cipherstates.initiator_to_responder
} else {
&mut self.cipherstates.responder_to_initiator
};
c.encrypt_with_ad_in_place(&[], msg, msg_len)?;
Ok(out_len)
}
pub fn receive(&mut self, msg: &[u8], buf: &mut [u8]) -> TransportResult<usize> {
let out_len = msg.len() - C::tag_len();
if msg.len() > MAX_MESSAGE_LEN {
panic!("Maximum Noise message length exceeded");
}
if buf.len() < out_len {
return Err(TransportError::BufferTooSmall);
}
let c = if self.initiator {
&mut self.cipherstates.responder_to_initiator
} else {
&mut self.cipherstates.initiator_to_responder
};
c.decrypt_with_ad(&[], msg, &mut buf[..out_len])?;
Ok(out_len)
}
pub fn receive_in_place(&mut self, msg: &mut [u8], msg_len: usize) -> TransportResult<usize> {
if msg_len > MAX_MESSAGE_LEN {
panic!("Maximum Noise message length exceeded");
}
if msg_len > msg.len() {
return Err(TransportError::BufferTooSmall);
}
let c = if self.initiator {
&mut self.cipherstates.responder_to_initiator
} else {
&mut self.cipherstates.initiator_to_responder
};
c.decrypt_with_ad_in_place(&[], msg, msg_len)?;
Ok(msg_len - C::tag_len())
}
#[must_use]
pub fn receiving_nonce(&self) -> u64 {
if self.initiator {
self.cipherstates.responder_to_initiator.get_nonce()
} else {
self.cipherstates.initiator_to_responder.get_nonce()
}
}
#[must_use]
pub fn sending_nonce(&self) -> u64 {
if self.initiator {
self.cipherstates.initiator_to_responder.get_nonce()
} else {
self.cipherstates.responder_to_initiator.get_nonce()
}
}
pub fn set_receiving_nonce(&mut self, nonce: u64) {
if self.initiator {
self.cipherstates.responder_to_initiator.set_nonce(nonce);
} else {
self.cipherstates.initiator_to_responder.set_nonce(nonce);
}
}
#[must_use]
pub fn get_handshake_hash(&self) -> H::Output {
self.h.clone()
}
pub fn rekey_sender(&mut self) {
if self.initiator {
self.cipherstates.initiator_to_responder.rekey();
} else {
self.cipherstates.responder_to_initiator.rekey();
}
}
pub fn rekey_receiver(&mut self) {
if self.initiator {
self.cipherstates.responder_to_initiator.rekey();
} else {
self.cipherstates.initiator_to_responder.rekey();
}
}
pub fn take(self) -> CipherStates<C> {
self.cipherstates
}
}