use crate::cipher::{MessageDecrypter, MessageEncrypter};
use crate::error::Error;
use crate::msgs::message::{BorrowedPlainMessage, OpaqueMessage, PlainMessage};
static SEQ_SOFT_LIMIT: u64 = 0xffff_ffff_ffff_0000u64;
static SEQ_HARD_LIMIT: u64 = 0xffff_ffff_ffff_fffeu64;
#[derive(PartialEq)]
enum DirectionState {
Invalid,
Prepared,
Active,
}
pub(crate) struct RecordLayer {
message_encrypter: Box<dyn MessageEncrypter>,
message_decrypter: Box<dyn MessageDecrypter>,
write_seq: u64,
read_seq: u64,
encrypt_state: DirectionState,
decrypt_state: DirectionState,
}
impl RecordLayer {
pub(crate) fn new() -> Self {
Self {
message_encrypter: <dyn MessageEncrypter>::invalid(),
message_decrypter: <dyn MessageDecrypter>::invalid(),
write_seq: 0,
read_seq: 0,
encrypt_state: DirectionState::Invalid,
decrypt_state: DirectionState::Invalid,
}
}
pub(crate) fn is_encrypting(&self) -> bool {
self.encrypt_state == DirectionState::Active
}
pub(crate) fn is_decrypting(&self) -> bool {
self.decrypt_state == DirectionState::Active
}
pub(crate) fn prepare_message_encrypter(&mut self, cipher: Box<dyn MessageEncrypter>) {
self.message_encrypter = cipher;
self.write_seq = 0;
self.encrypt_state = DirectionState::Prepared;
}
pub(crate) fn prepare_message_decrypter(&mut self, cipher: Box<dyn MessageDecrypter>) {
self.message_decrypter = cipher;
self.read_seq = 0;
self.decrypt_state = DirectionState::Prepared;
}
pub(crate) fn start_encrypting(&mut self) {
debug_assert!(self.encrypt_state == DirectionState::Prepared);
self.encrypt_state = DirectionState::Active;
}
pub(crate) fn start_decrypting(&mut self) {
debug_assert!(self.decrypt_state == DirectionState::Prepared);
self.decrypt_state = DirectionState::Active;
}
pub(crate) fn set_message_encrypter(&mut self, cipher: Box<dyn MessageEncrypter>) {
self.prepare_message_encrypter(cipher);
self.start_encrypting();
}
pub(crate) fn set_message_decrypter(&mut self, cipher: Box<dyn MessageDecrypter>) {
self.prepare_message_decrypter(cipher);
self.start_decrypting();
}
pub(crate) fn wants_close_before_decrypt(&self) -> bool {
self.read_seq == SEQ_SOFT_LIMIT
}
pub(crate) fn wants_close_before_encrypt(&self) -> bool {
self.write_seq == SEQ_SOFT_LIMIT
}
pub(crate) fn encrypt_exhausted(&self) -> bool {
self.write_seq >= SEQ_HARD_LIMIT
}
pub(crate) fn decrypt_incoming(&mut self, encr: OpaqueMessage) -> Result<PlainMessage, Error> {
debug_assert!(self.decrypt_state == DirectionState::Active);
let seq = self.read_seq;
self.read_seq += 1;
self.message_decrypter
.decrypt(encr, seq)
}
pub(crate) fn encrypt_outgoing(&mut self, plain: BorrowedPlainMessage) -> OpaqueMessage {
debug_assert!(self.encrypt_state == DirectionState::Active);
assert!(!self.encrypt_exhausted());
let seq = self.write_seq;
self.write_seq += 1;
self.message_encrypter
.encrypt(plain, seq)
.unwrap()
}
}