use rand_core::{CryptoRng, RngCore};
use zeroize::Zeroize;
use crate::bytearray::ByteArray;
use crate::cipherstate::CipherStates;
use crate::error::{HandshakeError, HandshakeResult};
use crate::handshakepattern::{HandshakePattern, Token};
use crate::symmetricstate::SymmetricState;
use crate::traits::{Cipher, Hash};
pub mod dual_layer;
pub mod nq;
pub mod pq;
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum HandshakeStatus {
Send,
Receive,
Ready,
Error,
}
pub(crate) struct HandshakeInternals<'a, C, H, RNG, K, P, EK, EP>
where
C: Cipher,
H: Hash,
RNG: RngCore + CryptoRng,
K: ByteArray,
P: ByteArray,
EK: ByteArray,
EP: ByteArray,
{
symmetricstate: SymmetricState<C, H>,
s: Option<K>,
e: Option<EK>,
rs: Option<P>,
re: Option<EP>,
pattern: HandshakePattern,
initiator: bool,
status: HandshakeStatus,
initiator_pattern_index: usize,
responder_pattern_index: usize,
rng: &'a mut RNG,
}
impl<'a, C, H, RNG, K, P, EK, EP> Drop for HandshakeInternals<'a, C, H, RNG, K, P, EK, EP>
where
C: Cipher,
H: Hash,
RNG: RngCore + CryptoRng,
K: ByteArray,
P: ByteArray,
EK: ByteArray,
EP: ByteArray,
{
fn drop(&mut self) {
self.s.zeroize();
self.e.zeroize();
}
}
impl<'a, C, H, RNG, K, P, EK, EP> HandshakeInternals<'a, C, H, RNG, K, P, EK, EP>
where
C: Cipher,
H: Hash,
RNG: RngCore + CryptoRng,
K: ByteArray,
P: ByteArray,
EK: ByteArray,
EP: ByteArray,
{
fn set_error(&mut self) {
self.status = HandshakeStatus::Error;
self.symmetricstate.zeroize();
}
fn status(&self) -> HandshakeStatus {
self.status
}
fn get_next_message(&self) -> HandshakeResult<&[Token]> {
let message = match (self.initiator, self.status) {
(true, HandshakeStatus::Send) | (false, HandshakeStatus::Receive) => self
.pattern
.get_initiator_pattern(self.initiator_pattern_index),
(true, HandshakeStatus::Receive) | (false, HandshakeStatus::Send) => self
.pattern
.get_responder_pattern(self.responder_pattern_index),
_ => return Err(HandshakeError::InvalidState),
};
Ok(message)
}
fn has_key(&self) -> bool {
self.symmetricstate.has_key()
}
fn update_hs_status(&mut self) {
if self.initiator_pattern_index == self.pattern.get_initiator_pattern_len()
&& self.responder_pattern_index == self.pattern.get_responder_pattern_len()
{
self.status = HandshakeStatus::Ready;
} else if self.status == HandshakeStatus::Receive {
self.status = HandshakeStatus::Send
} else {
self.status = HandshakeStatus::Receive
}
}
pub(crate) fn is_write_turn(&self) -> bool {
self.status == HandshakeStatus::Send
}
pub(crate) fn get_hash(&self) -> H::Output {
self.symmetricstate.get_hash()
}
pub(crate) fn get_ciphers(&self) -> CipherStates<C> {
self.symmetricstate.split()
}
}