use super::{Handshake, Successful};
use crate::{
Error,
crypto::{Backend, Kdf, Scheme},
};
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct HalfOpen<const KEY_SIZE: usize> {
pub(super) rnd_a: [u8; KEY_SIZE],
pub(super) rnd_b: [u8; KEY_SIZE],
}
impl<const KEY_SIZE: usize, AlgorithmT> Handshake<KEY_SIZE, AlgorithmT, HalfOpen<KEY_SIZE>>
where
Scheme<KEY_SIZE, AlgorithmT>: Backend<KEY_SIZE>,
([u8; KEY_SIZE], [u8; KEY_SIZE]): Kdf<KEY_SIZE>,
{
pub fn complete<IoBackendErrorT>(
self,
input: &[u8],
) -> Result<Handshake<KEY_SIZE, AlgorithmT, Successful>, Error<IoBackendErrorT>> {
let Self {
mut keying,
state: HalfOpen {
rnd_a: e_rnd_a,
rnd_b,
},
} = self;
if input.len() != KEY_SIZE {
return Err(Error::BadSize);
}
let mut plaintext = input.to_vec();
keying.decrypt(&mut plaintext);
let mut rnd_a: [u8; KEY_SIZE] = plaintext.try_into().unwrap();
rnd_a.rotate_right(1);
if rnd_a != e_rnd_a {
return Err(Error::InvalidHandshakeResponse);
}
let session_key = (rnd_a, rnd_b).derive();
Ok(Handshake {
keying: Scheme::<KEY_SIZE, AlgorithmT>::new(session_key),
state: Successful,
})
}
}