make Decrypt trait use Borrowed{Opaque,Plain}Message

This commit is contained in:
Christian Poveda 2023-12-18 11:31:49 -05:00 committed by Daniel McCarney
parent 1b551e712e
commit dc4cf38c03
10 changed files with 212 additions and 95 deletions

View File

@ -1,8 +1,11 @@
use alloc::boxed::Box;
use alloc::vec::Vec;
use chacha20poly1305::aead::Buffer;
use chacha20poly1305::{AeadInPlace, KeyInit, KeySizeUser};
use rustls::crypto::cipher::{self, AeadKey, Iv, UnsupportedOperationError, NONCE_LEN};
use rustls::crypto::cipher::{
self, AeadKey, BorrowedPayload, Iv, UnsupportedOperationError, NONCE_LEN,
};
use rustls::{ConnectionTrafficSecrets, ContentType, ProtocolVersion};
pub struct Chacha20Poly1305;
@ -114,17 +117,17 @@ impl cipher::MessageEncrypter for Tls13Cipher {
}
impl cipher::MessageDecrypter for Tls13Cipher {
fn decrypt(
fn decrypt<'a>(
&mut self,
mut m: cipher::OpaqueMessage,
mut m: cipher::BorrowedOpaqueMessage<'a>,
seq: u64,
) -> Result<cipher::PlainMessage, rustls::Error> {
let payload = m.payload_mut();
) -> Result<cipher::BorrowedPlainMessage<'a>, rustls::Error> {
let payload = &mut m.payload;
let nonce = chacha20poly1305::Nonce::from(cipher::Nonce::new(&self.1, seq).0);
let aad = cipher::make_tls13_aad(payload.len());
self.0
.decrypt_in_place(&nonce, &aad, payload)
.decrypt_in_place(&nonce, &aad, &mut BufferAdapter(payload))
.map_err(|_| rustls::Error::DecryptError)?;
m.into_tls13_unpadded_message()
@ -159,12 +162,12 @@ impl cipher::MessageEncrypter for Tls12Cipher {
}
impl cipher::MessageDecrypter for Tls12Cipher {
fn decrypt(
fn decrypt<'a>(
&mut self,
mut m: cipher::OpaqueMessage,
mut m: cipher::BorrowedOpaqueMessage<'a>,
seq: u64,
) -> Result<cipher::PlainMessage, rustls::Error> {
let payload = m.payload();
) -> Result<cipher::BorrowedPlainMessage<'a>, rustls::Error> {
let payload = &m.payload;
let nonce = chacha20poly1305::Nonce::from(cipher::Nonce::new(&self.1, seq).0);
let aad = cipher::make_tls12_aad(
seq,
@ -173,9 +176,9 @@ impl cipher::MessageDecrypter for Tls12Cipher {
payload.len() - CHACHAPOLY1305_OVERHEAD,
);
let payload = m.payload_mut();
let payload = &mut m.payload;
self.0
.decrypt_in_place(&nonce, &aad, payload)
.decrypt_in_place(&nonce, &aad, &mut BufferAdapter(payload))
.map_err(|_| rustls::Error::DecryptError)?;
Ok(m.into_plain_message())
@ -183,3 +186,27 @@ impl cipher::MessageDecrypter for Tls12Cipher {
}
const CHACHAPOLY1305_OVERHEAD: usize = 16;
struct BufferAdapter<'a, 'p>(&'a mut BorrowedPayload<'p>);
impl AsRef<[u8]> for BufferAdapter<'_, '_> {
fn as_ref(&self) -> &[u8] {
self.0
}
}
impl AsMut<[u8]> for BufferAdapter<'_, '_> {
fn as_mut(&mut self) -> &mut [u8] {
self.0
}
}
impl Buffer for BufferAdapter<'_, '_> {
fn extend_from_slice(&mut self, _: &[u8]) -> chacha20poly1305::aead::Result<()> {
unreachable!("not used by `AeadInPlace::decrypt_in_place`")
}
fn truncate(&mut self, len: usize) {
self.0.truncate(len)
}
}

View File

@ -1,13 +1,13 @@
use crate::crypto::cipher::{
make_tls12_aad, AeadKey, Iv, KeyBlockShape, MessageDecrypter, MessageEncrypter, Nonce,
Tls12AeadAlgorithm, UnsupportedOperationError, NONCE_LEN,
make_tls12_aad, AeadKey, BorrowedOpaqueMessage, Iv, KeyBlockShape, MessageDecrypter,
MessageEncrypter, Nonce, Tls12AeadAlgorithm, UnsupportedOperationError, NONCE_LEN,
};
use crate::crypto::tls12::Prf;
use crate::crypto::{ActiveKeyExchange, KeyExchangeAlgorithm};
use crate::enums::{CipherSuite, SignatureScheme};
use crate::error::Error;
use crate::msgs::fragmenter::MAX_FRAGMENT_LEN;
use crate::msgs::message::{BorrowedPlainMessage, OpaqueMessage, PlainMessage};
use crate::msgs::message::{BorrowedPlainMessage, OpaqueMessage};
use crate::suites::{CipherSuiteCommon, ConnectionTrafficSecrets, SupportedCipherSuite};
use crate::tls12::Tls12CipherSuite;
@ -252,8 +252,12 @@ const GCM_EXPLICIT_NONCE_LEN: usize = 8;
const GCM_OVERHEAD: usize = GCM_EXPLICIT_NONCE_LEN + 16;
impl MessageDecrypter for GcmMessageDecrypter {
fn decrypt(&mut self, mut msg: OpaqueMessage, seq: u64) -> Result<PlainMessage, Error> {
let payload = msg.payload();
fn decrypt<'a>(
&mut self,
mut msg: BorrowedOpaqueMessage<'a>,
seq: u64,
) -> Result<BorrowedPlainMessage<'a>, Error> {
let payload = &msg.payload;
if payload.len() < GCM_OVERHEAD {
return Err(Error::DecryptError);
}
@ -272,7 +276,7 @@ impl MessageDecrypter for GcmMessageDecrypter {
payload.len() - GCM_OVERHEAD,
));
let payload = msg.payload_mut();
let payload = &mut msg.payload;
let plain_len = self
.dec_key
.open_within(nonce, aad, payload, GCM_EXPLICIT_NONCE_LEN..)
@ -330,8 +334,12 @@ struct ChaCha20Poly1305MessageDecrypter {
const CHACHAPOLY1305_OVERHEAD: usize = 16;
impl MessageDecrypter for ChaCha20Poly1305MessageDecrypter {
fn decrypt(&mut self, mut msg: OpaqueMessage, seq: u64) -> Result<PlainMessage, Error> {
let payload = msg.payload();
fn decrypt<'a>(
&mut self,
mut msg: BorrowedOpaqueMessage<'a>,
seq: u64,
) -> Result<BorrowedPlainMessage<'a>, Error> {
let payload = &msg.payload;
if payload.len() < CHACHAPOLY1305_OVERHEAD {
return Err(Error::DecryptError);
@ -345,7 +353,7 @@ impl MessageDecrypter for ChaCha20Poly1305MessageDecrypter {
payload.len() - CHACHAPOLY1305_OVERHEAD,
));
let payload = msg.payload_mut();
let payload = &mut msg.payload;
let plain_len = self
.dec_key
.open_in_place(nonce, aad, payload)

View File

@ -3,14 +3,14 @@ use alloc::vec::Vec;
use crate::crypto;
use crate::crypto::cipher::{
make_tls13_aad, AeadKey, Iv, MessageDecrypter, MessageEncrypter, Nonce, Tls13AeadAlgorithm,
UnsupportedOperationError,
make_tls13_aad, AeadKey, BorrowedOpaqueMessage, Iv, MessageDecrypter, MessageEncrypter, Nonce,
Tls13AeadAlgorithm, UnsupportedOperationError,
};
use crate::crypto::tls13::{Hkdf, HkdfExpander, OkmBlock, OutputLengthError};
use crate::enums::{CipherSuite, ContentType, ProtocolVersion};
use crate::error::Error;
use crate::msgs::codec::Codec;
use crate::msgs::message::{BorrowedPlainMessage, OpaqueMessage, PlainMessage};
use crate::msgs::message::{BorrowedPlainMessage, OpaqueMessage};
use crate::suites::{CipherSuiteCommon, ConnectionTrafficSecrets, SupportedCipherSuite};
use crate::tls13::Tls13CipherSuite;
@ -235,8 +235,12 @@ impl MessageEncrypter for AeadMessageEncrypter {
}
impl MessageDecrypter for AeadMessageDecrypter {
fn decrypt(&mut self, mut msg: OpaqueMessage, seq: u64) -> Result<PlainMessage, Error> {
let payload = msg.payload_mut();
fn decrypt<'a>(
&mut self,
mut msg: BorrowedOpaqueMessage<'a>,
seq: u64,
) -> Result<BorrowedPlainMessage<'a>, Error> {
let payload = &mut msg.payload;
if payload.len() < self.dec_key.algorithm().tag_len() {
return Err(Error::DecryptError);
}
@ -290,8 +294,12 @@ struct GcmMessageDecrypter {
}
impl MessageDecrypter for GcmMessageDecrypter {
fn decrypt(&mut self, mut msg: OpaqueMessage, seq: u64) -> Result<PlainMessage, Error> {
let payload = msg.payload_mut();
fn decrypt<'a>(
&mut self,
mut msg: BorrowedOpaqueMessage<'a>,
seq: u64,
) -> Result<BorrowedPlainMessage<'a>, Error> {
let payload = &mut msg.payload;
if payload.len() < self.dec_key.algorithm().tag_len() {
return Err(Error::DecryptError);
}

View File

@ -127,7 +127,11 @@ pub struct KeyBlockShape {
pub trait MessageDecrypter: Send + Sync {
/// Decrypt the given TLS message `msg`, using the sequence number
/// `seq` which can be used to derive a unique [`Nonce`].
fn decrypt(&mut self, msg: OpaqueMessage, seq: u64) -> Result<PlainMessage, Error>;
fn decrypt<'a>(
&mut self,
msg: BorrowedOpaqueMessage<'a>,
seq: u64,
) -> Result<BorrowedPlainMessage<'a>, Error>;
}
/// Objects with this trait can encrypt TLS messages.
@ -317,7 +321,11 @@ impl MessageEncrypter for InvalidMessageEncrypter {
struct InvalidMessageDecrypter {}
impl MessageDecrypter for InvalidMessageDecrypter {
fn decrypt(&mut self, _m: OpaqueMessage, _seq: u64) -> Result<PlainMessage, Error> {
fn decrypt<'a>(
&mut self,
_m: BorrowedOpaqueMessage<'a>,
_seq: u64,
) -> Result<BorrowedPlainMessage<'a>, Error> {
Err(Error::DecryptError)
}
}

View File

@ -1,13 +1,13 @@
use crate::crypto::cipher::{
make_tls12_aad, AeadKey, Iv, KeyBlockShape, MessageDecrypter, MessageEncrypter, Nonce,
Tls12AeadAlgorithm, UnsupportedOperationError, NONCE_LEN,
make_tls12_aad, AeadKey, BorrowedOpaqueMessage, Iv, KeyBlockShape, MessageDecrypter,
MessageEncrypter, Nonce, Tls12AeadAlgorithm, UnsupportedOperationError, NONCE_LEN,
};
use crate::crypto::tls12::PrfUsingHmac;
use crate::crypto::KeyExchangeAlgorithm;
use crate::enums::{CipherSuite, SignatureScheme};
use crate::error::Error;
use crate::msgs::fragmenter::MAX_FRAGMENT_LEN;
use crate::msgs::message::{BorrowedPlainMessage, OpaqueMessage, PlainMessage};
use crate::msgs::message::{BorrowedPlainMessage, OpaqueMessage};
use crate::suites::{CipherSuiteCommon, ConnectionTrafficSecrets, SupportedCipherSuite};
use crate::tls12::Tls12CipherSuite;
@ -237,8 +237,12 @@ const GCM_EXPLICIT_NONCE_LEN: usize = 8;
const GCM_OVERHEAD: usize = GCM_EXPLICIT_NONCE_LEN + 16;
impl MessageDecrypter for GcmMessageDecrypter {
fn decrypt(&mut self, mut msg: OpaqueMessage, seq: u64) -> Result<PlainMessage, Error> {
let payload = msg.payload();
fn decrypt<'a>(
&mut self,
mut msg: BorrowedOpaqueMessage<'a>,
seq: u64,
) -> Result<BorrowedPlainMessage<'a>, Error> {
let payload = &msg.payload;
if payload.len() < GCM_OVERHEAD {
return Err(Error::DecryptError);
}
@ -257,7 +261,7 @@ impl MessageDecrypter for GcmMessageDecrypter {
payload.len() - GCM_OVERHEAD,
));
let payload = msg.payload_mut();
let payload = &mut msg.payload;
let plain_len = self
.dec_key
.open_within(nonce, aad, payload, GCM_EXPLICIT_NONCE_LEN..)
@ -315,8 +319,12 @@ struct ChaCha20Poly1305MessageDecrypter {
const CHACHAPOLY1305_OVERHEAD: usize = 16;
impl MessageDecrypter for ChaCha20Poly1305MessageDecrypter {
fn decrypt(&mut self, mut msg: OpaqueMessage, seq: u64) -> Result<PlainMessage, Error> {
let payload = msg.payload();
fn decrypt<'a>(
&mut self,
mut msg: BorrowedOpaqueMessage<'a>,
seq: u64,
) -> Result<BorrowedPlainMessage<'a>, Error> {
let payload = &msg.payload;
if payload.len() < CHACHAPOLY1305_OVERHEAD {
return Err(Error::DecryptError);
@ -330,7 +338,7 @@ impl MessageDecrypter for ChaCha20Poly1305MessageDecrypter {
payload.len() - CHACHAPOLY1305_OVERHEAD,
));
let payload = msg.payload_mut();
let payload = &mut msg.payload;
let plain_len = self
.dec_key
.open_in_place(nonce, aad, payload)

View File

@ -3,14 +3,14 @@ use alloc::vec::Vec;
use crate::crypto;
use crate::crypto::cipher::{
make_tls13_aad, AeadKey, Iv, MessageDecrypter, MessageEncrypter, Nonce, Tls13AeadAlgorithm,
UnsupportedOperationError,
make_tls13_aad, AeadKey, BorrowedOpaqueMessage, Iv, MessageDecrypter, MessageEncrypter, Nonce,
Tls13AeadAlgorithm, UnsupportedOperationError,
};
use crate::crypto::tls13::{Hkdf, HkdfExpander, OkmBlock, OutputLengthError};
use crate::enums::{CipherSuite, ContentType, ProtocolVersion};
use crate::error::Error;
use crate::msgs::codec::Codec;
use crate::msgs::message::{BorrowedPlainMessage, OpaqueMessage, PlainMessage};
use crate::msgs::message::{BorrowedPlainMessage, OpaqueMessage};
use crate::suites::{CipherSuiteCommon, ConnectionTrafficSecrets, SupportedCipherSuite};
use crate::tls13::Tls13CipherSuite;
@ -207,8 +207,12 @@ impl MessageEncrypter for Tls13MessageEncrypter {
}
impl MessageDecrypter for Tls13MessageDecrypter {
fn decrypt(&mut self, mut msg: OpaqueMessage, seq: u64) -> Result<PlainMessage, Error> {
let payload = msg.payload_mut();
fn decrypt<'a>(
&mut self,
mut msg: BorrowedOpaqueMessage<'a>,
seq: u64,
) -> Result<BorrowedPlainMessage<'a>, Error> {
let payload = &mut msg.payload;
if payload.len() < self.dec_key.algorithm().tag_len() {
return Err(Error::DecryptError);
}

View File

@ -57,9 +57,39 @@ impl<'a> DerefMut for BorrowedPayload<'a> {
}
impl<'a> BorrowedPayload<'a> {
#[cfg(test)]
pub(crate) fn new(bytes: &'a mut [u8]) -> Self {
Self(bytes)
}
pub fn truncate(&mut self, len: usize) {
if len >= self.len() {
return;
}
self.0 = core::mem::take(&mut self.0)
.split_at_mut(len)
.0;
}
pub(crate) fn read(r: &mut ReaderMut<'a>) -> Self {
Self(r.rest())
}
pub(crate) fn into_inner(self) -> &'a mut [u8] {
self.0
}
pub(crate) fn pop(&mut self) -> Option<u8> {
if self.is_empty() {
return None;
}
let len = self.len();
let last = self[len - 1];
self.truncate(len - 1);
Some(last)
}
}
impl<'a> Codec for CertificateDer<'a> {

View File

@ -68,7 +68,7 @@ impl MessageDeframer {
// If so, deframe it and place the message onto the frames output queue.
let mut rd = codec::ReaderMut::init(buffer.filled_get_mut(start..));
let m = match BorrowedOpaqueMessage::read(&mut rd) {
Ok(m) => m.into_owned(),
Ok(m) => m,
Err(msg_err) => {
let err_kind = match msg_err {
MessageError::TooShortForHeader | MessageError::TooShortForLength => {
@ -101,7 +101,7 @@ impl MessageDeframer {
ContentType::Alert
if version_is_tls13
&& !record_layer.has_decrypted()
&& m.payload().len() <= 2 =>
&& m.payload.len() <= 2 =>
{
true
}
@ -109,13 +109,14 @@ impl MessageDeframer {
_ => false,
};
if self.joining_hs.is_none() && allowed_plaintext {
let message = m.into_plain_message().into_owned();
// This is unencrypted. We check the contents later.
buffer.queue_discard(end);
return Ok(Some(Deframed {
want_close_before_decrypt: false,
aligned: true,
trial_decryption_finished: false,
message: m.into_plain_message(),
message,
}));
}

View File

@ -84,9 +84,8 @@ impl MessagePayload {
/// # Decryption
/// Internally the message payload is stored as a `Vec<u8>`; this can by mutably borrowed with
/// [`OpaqueMessage::payload_mut()`]. This is useful for decrypting a message in-place.
/// After the message is decrypted, call [`OpaqueMessage::into_plain_message()`] or
/// [`OpaqueMessage::into_tls13_unpadded_message()`] (depending on the
/// protocol version).
/// After the message is decrypted, call [`OpaqueMessage::into_plain_message()`] or borrow this
/// message and call [`BorrowedOpaqueMessage::into_tls13_unpadded_message`].
#[derive(Clone, Debug)]
pub struct OpaqueMessage {
pub typ: ContentType,
@ -154,28 +153,13 @@ impl OpaqueMessage {
}
}
/// For TLS1.3 (only), checks the length msg.payload is valid and removes the padding.
///
/// Returns an error if the message (pre-unpadding) is too long, or the padding is invalid,
/// or the message (post-unpadding) is too long.
pub fn into_tls13_unpadded_message(mut self) -> Result<PlainMessage, Error> {
let payload = &mut self.payload.0;
if payload.len() > MAX_FRAGMENT_LEN + 1 {
return Err(Error::PeerSentOversizedRecord);
#[cfg(test)]
pub(crate) fn borrow(&mut self) -> BorrowedOpaqueMessage {
BorrowedOpaqueMessage {
typ: self.typ,
version: self.version,
payload: BorrowedPayload::new(self.payload_mut()),
}
self.typ = unpad_tls13(payload);
if self.typ == ContentType::Unknown(0) {
return Err(PeerMisbehaved::IllegalTlsInnerPlaintext.into());
}
if payload.len() > MAX_FRAGMENT_LEN {
return Err(Error::PeerSentOversizedRecord);
}
self.version = ProtocolVersion::TLSv1_3;
Ok(self.into_plain_message())
}
/// This is the maximum on-the-wire size of a TLSCiphertext.
@ -197,8 +181,42 @@ pub struct BorrowedOpaqueMessage<'a> {
pub payload: BorrowedPayload<'a>,
}
#[allow(dead_code)]
impl<'a> BorrowedOpaqueMessage<'a> {
/// Force conversion into a plaintext message.
///
/// See [`OpaqueMessage::into_plain_message`] for more information
pub fn into_plain_message(self) -> BorrowedPlainMessage<'a> {
BorrowedPlainMessage {
typ: self.typ,
version: self.version,
payload: self.payload.into_inner(),
}
}
/// For TLS1.3 (only), checks the length msg.payload is valid and removes the padding.
///
/// Returns an error if the message (pre-unpadding) is too long, or the padding is invalid,
/// or the message (post-unpadding) is too long.
pub fn into_tls13_unpadded_message(mut self) -> Result<BorrowedPlainMessage<'a>, Error> {
let payload = &mut self.payload;
if payload.len() > MAX_FRAGMENT_LEN + 1 {
return Err(Error::PeerSentOversizedRecord);
}
self.typ = unpad_tls13_payload(payload);
if self.typ == ContentType::Unknown(0) {
return Err(PeerMisbehaved::IllegalTlsInnerPlaintext.into());
}
if payload.len() > MAX_FRAGMENT_LEN {
return Err(Error::PeerSentOversizedRecord);
}
self.version = ProtocolVersion::TLSv1_3;
Ok(self.into_plain_message())
}
pub(crate) fn read(r: &mut ReaderMut<'a>) -> Result<Self, MessageError> {
let (typ, version, len) = r.as_reader(read_opaque_message_header)?;
@ -213,19 +231,6 @@ impl<'a> BorrowedOpaqueMessage<'a> {
payload,
})
}
pub(crate) fn into_owned(self) -> OpaqueMessage {
let Self {
typ,
version,
payload,
} = self;
OpaqueMessage {
typ,
version,
payload: Payload::new(&*payload),
}
}
}
fn read_opaque_message_header(
@ -268,9 +273,9 @@ fn read_opaque_message_header(
/// the content type, which is returned. See RFC8446 s5.2.
///
/// ContentType(0) is returned if the message payload is empty or all zeroes.
fn unpad_tls13(v: &mut Vec<u8>) -> ContentType {
fn unpad_tls13_payload(p: &mut BorrowedPayload) -> ContentType {
loop {
match v.pop() {
match p.pop() {
Some(0) => {}
Some(content_type) => return ContentType::from(content_type),
None => return ContentType::Unknown(0),
@ -385,6 +390,7 @@ impl TryFrom<PlainMessage> for Message {
///
/// This type also cannot decode its internals and
/// cannot be read/encoded; only `OpaqueMessage` can do that.
#[derive(Debug)]
pub struct BorrowedPlainMessage<'a> {
pub typ: ContentType,
pub version: ProtocolVersion,
@ -403,6 +409,19 @@ impl<'a> BorrowedPlainMessage<'a> {
pub fn encoded_len(&self, record_layer: &RecordLayer) -> usize {
OpaqueMessage::HEADER_SIZE as usize + record_layer.encrypted_len(self.payload.len())
}
pub(crate) fn into_owned(self) -> PlainMessage {
let Self {
typ,
version,
payload,
} = self;
PlainMessage {
typ,
version,
payload: Payload::new(payload),
}
}
}
#[derive(Debug)]

View File

@ -1,6 +1,6 @@
use core::num::NonZeroU64;
use crate::crypto::cipher::{MessageDecrypter, MessageEncrypter};
use crate::crypto::cipher::{BorrowedOpaqueMessage, MessageDecrypter, MessageEncrypter};
use crate::error::Error;
use crate::msgs::message::{BorrowedPlainMessage, OpaqueMessage, PlainMessage};
@ -62,12 +62,12 @@ impl RecordLayer {
/// an error is returned.
pub(crate) fn decrypt_incoming(
&mut self,
encr: OpaqueMessage,
encr: BorrowedOpaqueMessage<'_>,
) -> Result<Option<Decrypted>, Error> {
if self.decrypt_state != DirectionState::Active {
return Ok(Some(Decrypted {
want_close_before_decrypt: false,
plaintext: encr.into_plain_message(),
plaintext: encr.into_plain_message().into_owned(),
}));
}
@ -81,7 +81,7 @@ impl RecordLayer {
// failure has already happened.
let want_close_before_decrypt = self.read_seq == SEQ_SOFT_LIMIT;
let encrypted_len = encr.payload().len();
let encrypted_len = encr.payload.len();
match self
.message_decrypter
.decrypt(encr, self.read_seq)
@ -93,7 +93,7 @@ impl RecordLayer {
}
Ok(Some(Decrypted {
want_close_before_decrypt,
plaintext,
plaintext: plaintext.into_owned(),
}))
}
Err(Error::DecryptError) if self.doing_trial_decryption(encrypted_len) => {
@ -255,7 +255,11 @@ mod tests {
struct PassThroughDecrypter;
impl MessageDecrypter for PassThroughDecrypter {
fn decrypt(&mut self, m: OpaqueMessage, _: u64) -> Result<PlainMessage, Error> {
fn decrypt<'a>(
&mut self,
m: BorrowedOpaqueMessage<'a>,
_: u64,
) -> Result<BorrowedPlainMessage<'a>, Error> {
Ok(m.into_plain_message())
}
}
@ -287,13 +291,13 @@ mod tests {
// Decrypting a message should update the read_seq and track that we have now performed
// a decryption.
let msg = OpaqueMessage::new(
let mut msg = OpaqueMessage::new(
ContentType::Handshake,
ProtocolVersion::TLSv1_2,
vec![0xC0, 0xFF, 0xEE],
);
record_layer
.decrypt_incoming(msg)
.decrypt_incoming(msg.borrow())
.unwrap();
assert!(matches!(record_layer.decrypt_state, DirectionState::Active));
assert_eq!(record_layer.read_seq, 1);