mirror of https://github.com/ctz/rustls
make Decrypt trait use Borrowed{Opaque,Plain}Message
This commit is contained in:
parent
1b551e712e
commit
dc4cf38c03
|
@ -1,8 +1,11 @@
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
|
use chacha20poly1305::aead::Buffer;
|
||||||
use chacha20poly1305::{AeadInPlace, KeyInit, KeySizeUser};
|
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};
|
use rustls::{ConnectionTrafficSecrets, ContentType, ProtocolVersion};
|
||||||
|
|
||||||
pub struct Chacha20Poly1305;
|
pub struct Chacha20Poly1305;
|
||||||
|
@ -114,17 +117,17 @@ impl cipher::MessageEncrypter for Tls13Cipher {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl cipher::MessageDecrypter for Tls13Cipher {
|
impl cipher::MessageDecrypter for Tls13Cipher {
|
||||||
fn decrypt(
|
fn decrypt<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut m: cipher::OpaqueMessage,
|
mut m: cipher::BorrowedOpaqueMessage<'a>,
|
||||||
seq: u64,
|
seq: u64,
|
||||||
) -> Result<cipher::PlainMessage, rustls::Error> {
|
) -> Result<cipher::BorrowedPlainMessage<'a>, rustls::Error> {
|
||||||
let payload = m.payload_mut();
|
let payload = &mut m.payload;
|
||||||
let nonce = chacha20poly1305::Nonce::from(cipher::Nonce::new(&self.1, seq).0);
|
let nonce = chacha20poly1305::Nonce::from(cipher::Nonce::new(&self.1, seq).0);
|
||||||
let aad = cipher::make_tls13_aad(payload.len());
|
let aad = cipher::make_tls13_aad(payload.len());
|
||||||
|
|
||||||
self.0
|
self.0
|
||||||
.decrypt_in_place(&nonce, &aad, payload)
|
.decrypt_in_place(&nonce, &aad, &mut BufferAdapter(payload))
|
||||||
.map_err(|_| rustls::Error::DecryptError)?;
|
.map_err(|_| rustls::Error::DecryptError)?;
|
||||||
|
|
||||||
m.into_tls13_unpadded_message()
|
m.into_tls13_unpadded_message()
|
||||||
|
@ -159,12 +162,12 @@ impl cipher::MessageEncrypter for Tls12Cipher {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl cipher::MessageDecrypter for Tls12Cipher {
|
impl cipher::MessageDecrypter for Tls12Cipher {
|
||||||
fn decrypt(
|
fn decrypt<'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut m: cipher::OpaqueMessage,
|
mut m: cipher::BorrowedOpaqueMessage<'a>,
|
||||||
seq: u64,
|
seq: u64,
|
||||||
) -> Result<cipher::PlainMessage, rustls::Error> {
|
) -> Result<cipher::BorrowedPlainMessage<'a>, rustls::Error> {
|
||||||
let payload = m.payload();
|
let payload = &m.payload;
|
||||||
let nonce = chacha20poly1305::Nonce::from(cipher::Nonce::new(&self.1, seq).0);
|
let nonce = chacha20poly1305::Nonce::from(cipher::Nonce::new(&self.1, seq).0);
|
||||||
let aad = cipher::make_tls12_aad(
|
let aad = cipher::make_tls12_aad(
|
||||||
seq,
|
seq,
|
||||||
|
@ -173,9 +176,9 @@ impl cipher::MessageDecrypter for Tls12Cipher {
|
||||||
payload.len() - CHACHAPOLY1305_OVERHEAD,
|
payload.len() - CHACHAPOLY1305_OVERHEAD,
|
||||||
);
|
);
|
||||||
|
|
||||||
let payload = m.payload_mut();
|
let payload = &mut m.payload;
|
||||||
self.0
|
self.0
|
||||||
.decrypt_in_place(&nonce, &aad, payload)
|
.decrypt_in_place(&nonce, &aad, &mut BufferAdapter(payload))
|
||||||
.map_err(|_| rustls::Error::DecryptError)?;
|
.map_err(|_| rustls::Error::DecryptError)?;
|
||||||
|
|
||||||
Ok(m.into_plain_message())
|
Ok(m.into_plain_message())
|
||||||
|
@ -183,3 +186,27 @@ impl cipher::MessageDecrypter for Tls12Cipher {
|
||||||
}
|
}
|
||||||
|
|
||||||
const CHACHAPOLY1305_OVERHEAD: usize = 16;
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use crate::crypto::cipher::{
|
use crate::crypto::cipher::{
|
||||||
make_tls12_aad, AeadKey, Iv, KeyBlockShape, MessageDecrypter, MessageEncrypter, Nonce,
|
make_tls12_aad, AeadKey, BorrowedOpaqueMessage, Iv, KeyBlockShape, MessageDecrypter,
|
||||||
Tls12AeadAlgorithm, UnsupportedOperationError, NONCE_LEN,
|
MessageEncrypter, Nonce, Tls12AeadAlgorithm, UnsupportedOperationError, NONCE_LEN,
|
||||||
};
|
};
|
||||||
use crate::crypto::tls12::Prf;
|
use crate::crypto::tls12::Prf;
|
||||||
use crate::crypto::{ActiveKeyExchange, KeyExchangeAlgorithm};
|
use crate::crypto::{ActiveKeyExchange, KeyExchangeAlgorithm};
|
||||||
use crate::enums::{CipherSuite, SignatureScheme};
|
use crate::enums::{CipherSuite, SignatureScheme};
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::msgs::fragmenter::MAX_FRAGMENT_LEN;
|
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::suites::{CipherSuiteCommon, ConnectionTrafficSecrets, SupportedCipherSuite};
|
||||||
use crate::tls12::Tls12CipherSuite;
|
use crate::tls12::Tls12CipherSuite;
|
||||||
|
|
||||||
|
@ -252,8 +252,12 @@ const GCM_EXPLICIT_NONCE_LEN: usize = 8;
|
||||||
const GCM_OVERHEAD: usize = GCM_EXPLICIT_NONCE_LEN + 16;
|
const GCM_OVERHEAD: usize = GCM_EXPLICIT_NONCE_LEN + 16;
|
||||||
|
|
||||||
impl MessageDecrypter for GcmMessageDecrypter {
|
impl MessageDecrypter for GcmMessageDecrypter {
|
||||||
fn decrypt(&mut self, mut msg: OpaqueMessage, seq: u64) -> Result<PlainMessage, Error> {
|
fn decrypt<'a>(
|
||||||
let payload = msg.payload();
|
&mut self,
|
||||||
|
mut msg: BorrowedOpaqueMessage<'a>,
|
||||||
|
seq: u64,
|
||||||
|
) -> Result<BorrowedPlainMessage<'a>, Error> {
|
||||||
|
let payload = &msg.payload;
|
||||||
if payload.len() < GCM_OVERHEAD {
|
if payload.len() < GCM_OVERHEAD {
|
||||||
return Err(Error::DecryptError);
|
return Err(Error::DecryptError);
|
||||||
}
|
}
|
||||||
|
@ -272,7 +276,7 @@ impl MessageDecrypter for GcmMessageDecrypter {
|
||||||
payload.len() - GCM_OVERHEAD,
|
payload.len() - GCM_OVERHEAD,
|
||||||
));
|
));
|
||||||
|
|
||||||
let payload = msg.payload_mut();
|
let payload = &mut msg.payload;
|
||||||
let plain_len = self
|
let plain_len = self
|
||||||
.dec_key
|
.dec_key
|
||||||
.open_within(nonce, aad, payload, GCM_EXPLICIT_NONCE_LEN..)
|
.open_within(nonce, aad, payload, GCM_EXPLICIT_NONCE_LEN..)
|
||||||
|
@ -330,8 +334,12 @@ struct ChaCha20Poly1305MessageDecrypter {
|
||||||
const CHACHAPOLY1305_OVERHEAD: usize = 16;
|
const CHACHAPOLY1305_OVERHEAD: usize = 16;
|
||||||
|
|
||||||
impl MessageDecrypter for ChaCha20Poly1305MessageDecrypter {
|
impl MessageDecrypter for ChaCha20Poly1305MessageDecrypter {
|
||||||
fn decrypt(&mut self, mut msg: OpaqueMessage, seq: u64) -> Result<PlainMessage, Error> {
|
fn decrypt<'a>(
|
||||||
let payload = msg.payload();
|
&mut self,
|
||||||
|
mut msg: BorrowedOpaqueMessage<'a>,
|
||||||
|
seq: u64,
|
||||||
|
) -> Result<BorrowedPlainMessage<'a>, Error> {
|
||||||
|
let payload = &msg.payload;
|
||||||
|
|
||||||
if payload.len() < CHACHAPOLY1305_OVERHEAD {
|
if payload.len() < CHACHAPOLY1305_OVERHEAD {
|
||||||
return Err(Error::DecryptError);
|
return Err(Error::DecryptError);
|
||||||
|
@ -345,7 +353,7 @@ impl MessageDecrypter for ChaCha20Poly1305MessageDecrypter {
|
||||||
payload.len() - CHACHAPOLY1305_OVERHEAD,
|
payload.len() - CHACHAPOLY1305_OVERHEAD,
|
||||||
));
|
));
|
||||||
|
|
||||||
let payload = msg.payload_mut();
|
let payload = &mut msg.payload;
|
||||||
let plain_len = self
|
let plain_len = self
|
||||||
.dec_key
|
.dec_key
|
||||||
.open_in_place(nonce, aad, payload)
|
.open_in_place(nonce, aad, payload)
|
||||||
|
|
|
@ -3,14 +3,14 @@ use alloc::vec::Vec;
|
||||||
|
|
||||||
use crate::crypto;
|
use crate::crypto;
|
||||||
use crate::crypto::cipher::{
|
use crate::crypto::cipher::{
|
||||||
make_tls13_aad, AeadKey, Iv, MessageDecrypter, MessageEncrypter, Nonce, Tls13AeadAlgorithm,
|
make_tls13_aad, AeadKey, BorrowedOpaqueMessage, Iv, MessageDecrypter, MessageEncrypter, Nonce,
|
||||||
UnsupportedOperationError,
|
Tls13AeadAlgorithm, UnsupportedOperationError,
|
||||||
};
|
};
|
||||||
use crate::crypto::tls13::{Hkdf, HkdfExpander, OkmBlock, OutputLengthError};
|
use crate::crypto::tls13::{Hkdf, HkdfExpander, OkmBlock, OutputLengthError};
|
||||||
use crate::enums::{CipherSuite, ContentType, ProtocolVersion};
|
use crate::enums::{CipherSuite, ContentType, ProtocolVersion};
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::msgs::codec::Codec;
|
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::suites::{CipherSuiteCommon, ConnectionTrafficSecrets, SupportedCipherSuite};
|
||||||
use crate::tls13::Tls13CipherSuite;
|
use crate::tls13::Tls13CipherSuite;
|
||||||
|
|
||||||
|
@ -235,8 +235,12 @@ impl MessageEncrypter for AeadMessageEncrypter {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MessageDecrypter for AeadMessageDecrypter {
|
impl MessageDecrypter for AeadMessageDecrypter {
|
||||||
fn decrypt(&mut self, mut msg: OpaqueMessage, seq: u64) -> Result<PlainMessage, Error> {
|
fn decrypt<'a>(
|
||||||
let payload = msg.payload_mut();
|
&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() {
|
if payload.len() < self.dec_key.algorithm().tag_len() {
|
||||||
return Err(Error::DecryptError);
|
return Err(Error::DecryptError);
|
||||||
}
|
}
|
||||||
|
@ -290,8 +294,12 @@ struct GcmMessageDecrypter {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MessageDecrypter for GcmMessageDecrypter {
|
impl MessageDecrypter for GcmMessageDecrypter {
|
||||||
fn decrypt(&mut self, mut msg: OpaqueMessage, seq: u64) -> Result<PlainMessage, Error> {
|
fn decrypt<'a>(
|
||||||
let payload = msg.payload_mut();
|
&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() {
|
if payload.len() < self.dec_key.algorithm().tag_len() {
|
||||||
return Err(Error::DecryptError);
|
return Err(Error::DecryptError);
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,11 @@ pub struct KeyBlockShape {
|
||||||
pub trait MessageDecrypter: Send + Sync {
|
pub trait MessageDecrypter: Send + Sync {
|
||||||
/// Decrypt the given TLS message `msg`, using the sequence number
|
/// Decrypt the given TLS message `msg`, using the sequence number
|
||||||
/// `seq` which can be used to derive a unique [`Nonce`].
|
/// `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.
|
/// Objects with this trait can encrypt TLS messages.
|
||||||
|
@ -317,7 +321,11 @@ impl MessageEncrypter for InvalidMessageEncrypter {
|
||||||
struct InvalidMessageDecrypter {}
|
struct InvalidMessageDecrypter {}
|
||||||
|
|
||||||
impl MessageDecrypter for 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)
|
Err(Error::DecryptError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use crate::crypto::cipher::{
|
use crate::crypto::cipher::{
|
||||||
make_tls12_aad, AeadKey, Iv, KeyBlockShape, MessageDecrypter, MessageEncrypter, Nonce,
|
make_tls12_aad, AeadKey, BorrowedOpaqueMessage, Iv, KeyBlockShape, MessageDecrypter,
|
||||||
Tls12AeadAlgorithm, UnsupportedOperationError, NONCE_LEN,
|
MessageEncrypter, Nonce, Tls12AeadAlgorithm, UnsupportedOperationError, NONCE_LEN,
|
||||||
};
|
};
|
||||||
use crate::crypto::tls12::PrfUsingHmac;
|
use crate::crypto::tls12::PrfUsingHmac;
|
||||||
use crate::crypto::KeyExchangeAlgorithm;
|
use crate::crypto::KeyExchangeAlgorithm;
|
||||||
use crate::enums::{CipherSuite, SignatureScheme};
|
use crate::enums::{CipherSuite, SignatureScheme};
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::msgs::fragmenter::MAX_FRAGMENT_LEN;
|
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::suites::{CipherSuiteCommon, ConnectionTrafficSecrets, SupportedCipherSuite};
|
||||||
use crate::tls12::Tls12CipherSuite;
|
use crate::tls12::Tls12CipherSuite;
|
||||||
|
|
||||||
|
@ -237,8 +237,12 @@ const GCM_EXPLICIT_NONCE_LEN: usize = 8;
|
||||||
const GCM_OVERHEAD: usize = GCM_EXPLICIT_NONCE_LEN + 16;
|
const GCM_OVERHEAD: usize = GCM_EXPLICIT_NONCE_LEN + 16;
|
||||||
|
|
||||||
impl MessageDecrypter for GcmMessageDecrypter {
|
impl MessageDecrypter for GcmMessageDecrypter {
|
||||||
fn decrypt(&mut self, mut msg: OpaqueMessage, seq: u64) -> Result<PlainMessage, Error> {
|
fn decrypt<'a>(
|
||||||
let payload = msg.payload();
|
&mut self,
|
||||||
|
mut msg: BorrowedOpaqueMessage<'a>,
|
||||||
|
seq: u64,
|
||||||
|
) -> Result<BorrowedPlainMessage<'a>, Error> {
|
||||||
|
let payload = &msg.payload;
|
||||||
if payload.len() < GCM_OVERHEAD {
|
if payload.len() < GCM_OVERHEAD {
|
||||||
return Err(Error::DecryptError);
|
return Err(Error::DecryptError);
|
||||||
}
|
}
|
||||||
|
@ -257,7 +261,7 @@ impl MessageDecrypter for GcmMessageDecrypter {
|
||||||
payload.len() - GCM_OVERHEAD,
|
payload.len() - GCM_OVERHEAD,
|
||||||
));
|
));
|
||||||
|
|
||||||
let payload = msg.payload_mut();
|
let payload = &mut msg.payload;
|
||||||
let plain_len = self
|
let plain_len = self
|
||||||
.dec_key
|
.dec_key
|
||||||
.open_within(nonce, aad, payload, GCM_EXPLICIT_NONCE_LEN..)
|
.open_within(nonce, aad, payload, GCM_EXPLICIT_NONCE_LEN..)
|
||||||
|
@ -315,8 +319,12 @@ struct ChaCha20Poly1305MessageDecrypter {
|
||||||
const CHACHAPOLY1305_OVERHEAD: usize = 16;
|
const CHACHAPOLY1305_OVERHEAD: usize = 16;
|
||||||
|
|
||||||
impl MessageDecrypter for ChaCha20Poly1305MessageDecrypter {
|
impl MessageDecrypter for ChaCha20Poly1305MessageDecrypter {
|
||||||
fn decrypt(&mut self, mut msg: OpaqueMessage, seq: u64) -> Result<PlainMessage, Error> {
|
fn decrypt<'a>(
|
||||||
let payload = msg.payload();
|
&mut self,
|
||||||
|
mut msg: BorrowedOpaqueMessage<'a>,
|
||||||
|
seq: u64,
|
||||||
|
) -> Result<BorrowedPlainMessage<'a>, Error> {
|
||||||
|
let payload = &msg.payload;
|
||||||
|
|
||||||
if payload.len() < CHACHAPOLY1305_OVERHEAD {
|
if payload.len() < CHACHAPOLY1305_OVERHEAD {
|
||||||
return Err(Error::DecryptError);
|
return Err(Error::DecryptError);
|
||||||
|
@ -330,7 +338,7 @@ impl MessageDecrypter for ChaCha20Poly1305MessageDecrypter {
|
||||||
payload.len() - CHACHAPOLY1305_OVERHEAD,
|
payload.len() - CHACHAPOLY1305_OVERHEAD,
|
||||||
));
|
));
|
||||||
|
|
||||||
let payload = msg.payload_mut();
|
let payload = &mut msg.payload;
|
||||||
let plain_len = self
|
let plain_len = self
|
||||||
.dec_key
|
.dec_key
|
||||||
.open_in_place(nonce, aad, payload)
|
.open_in_place(nonce, aad, payload)
|
||||||
|
|
|
@ -3,14 +3,14 @@ use alloc::vec::Vec;
|
||||||
|
|
||||||
use crate::crypto;
|
use crate::crypto;
|
||||||
use crate::crypto::cipher::{
|
use crate::crypto::cipher::{
|
||||||
make_tls13_aad, AeadKey, Iv, MessageDecrypter, MessageEncrypter, Nonce, Tls13AeadAlgorithm,
|
make_tls13_aad, AeadKey, BorrowedOpaqueMessage, Iv, MessageDecrypter, MessageEncrypter, Nonce,
|
||||||
UnsupportedOperationError,
|
Tls13AeadAlgorithm, UnsupportedOperationError,
|
||||||
};
|
};
|
||||||
use crate::crypto::tls13::{Hkdf, HkdfExpander, OkmBlock, OutputLengthError};
|
use crate::crypto::tls13::{Hkdf, HkdfExpander, OkmBlock, OutputLengthError};
|
||||||
use crate::enums::{CipherSuite, ContentType, ProtocolVersion};
|
use crate::enums::{CipherSuite, ContentType, ProtocolVersion};
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::msgs::codec::Codec;
|
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::suites::{CipherSuiteCommon, ConnectionTrafficSecrets, SupportedCipherSuite};
|
||||||
use crate::tls13::Tls13CipherSuite;
|
use crate::tls13::Tls13CipherSuite;
|
||||||
|
|
||||||
|
@ -207,8 +207,12 @@ impl MessageEncrypter for Tls13MessageEncrypter {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MessageDecrypter for Tls13MessageDecrypter {
|
impl MessageDecrypter for Tls13MessageDecrypter {
|
||||||
fn decrypt(&mut self, mut msg: OpaqueMessage, seq: u64) -> Result<PlainMessage, Error> {
|
fn decrypt<'a>(
|
||||||
let payload = msg.payload_mut();
|
&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() {
|
if payload.len() < self.dec_key.algorithm().tag_len() {
|
||||||
return Err(Error::DecryptError);
|
return Err(Error::DecryptError);
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,9 +57,39 @@ impl<'a> DerefMut for BorrowedPayload<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> 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 {
|
pub(crate) fn read(r: &mut ReaderMut<'a>) -> Self {
|
||||||
Self(r.rest())
|
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> {
|
impl<'a> Codec for CertificateDer<'a> {
|
||||||
|
|
|
@ -68,7 +68,7 @@ impl MessageDeframer {
|
||||||
// If so, deframe it and place the message onto the frames output queue.
|
// 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 mut rd = codec::ReaderMut::init(buffer.filled_get_mut(start..));
|
||||||
let m = match BorrowedOpaqueMessage::read(&mut rd) {
|
let m = match BorrowedOpaqueMessage::read(&mut rd) {
|
||||||
Ok(m) => m.into_owned(),
|
Ok(m) => m,
|
||||||
Err(msg_err) => {
|
Err(msg_err) => {
|
||||||
let err_kind = match msg_err {
|
let err_kind = match msg_err {
|
||||||
MessageError::TooShortForHeader | MessageError::TooShortForLength => {
|
MessageError::TooShortForHeader | MessageError::TooShortForLength => {
|
||||||
|
@ -101,7 +101,7 @@ impl MessageDeframer {
|
||||||
ContentType::Alert
|
ContentType::Alert
|
||||||
if version_is_tls13
|
if version_is_tls13
|
||||||
&& !record_layer.has_decrypted()
|
&& !record_layer.has_decrypted()
|
||||||
&& m.payload().len() <= 2 =>
|
&& m.payload.len() <= 2 =>
|
||||||
{
|
{
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -109,13 +109,14 @@ impl MessageDeframer {
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
if self.joining_hs.is_none() && allowed_plaintext {
|
if self.joining_hs.is_none() && allowed_plaintext {
|
||||||
|
let message = m.into_plain_message().into_owned();
|
||||||
// This is unencrypted. We check the contents later.
|
// This is unencrypted. We check the contents later.
|
||||||
buffer.queue_discard(end);
|
buffer.queue_discard(end);
|
||||||
return Ok(Some(Deframed {
|
return Ok(Some(Deframed {
|
||||||
want_close_before_decrypt: false,
|
want_close_before_decrypt: false,
|
||||||
aligned: true,
|
aligned: true,
|
||||||
trial_decryption_finished: false,
|
trial_decryption_finished: false,
|
||||||
message: m.into_plain_message(),
|
message,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,9 +84,8 @@ impl MessagePayload {
|
||||||
/// # Decryption
|
/// # Decryption
|
||||||
/// Internally the message payload is stored as a `Vec<u8>`; this can by mutably borrowed with
|
/// 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.
|
/// [`OpaqueMessage::payload_mut()`]. This is useful for decrypting a message in-place.
|
||||||
/// After the message is decrypted, call [`OpaqueMessage::into_plain_message()`] or
|
/// After the message is decrypted, call [`OpaqueMessage::into_plain_message()`] or borrow this
|
||||||
/// [`OpaqueMessage::into_tls13_unpadded_message()`] (depending on the
|
/// message and call [`BorrowedOpaqueMessage::into_tls13_unpadded_message`].
|
||||||
/// protocol version).
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct OpaqueMessage {
|
pub struct OpaqueMessage {
|
||||||
pub typ: ContentType,
|
pub typ: ContentType,
|
||||||
|
@ -154,28 +153,13 @@ impl OpaqueMessage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For TLS1.3 (only), checks the length msg.payload is valid and removes the padding.
|
#[cfg(test)]
|
||||||
///
|
pub(crate) fn borrow(&mut self) -> BorrowedOpaqueMessage {
|
||||||
/// Returns an error if the message (pre-unpadding) is too long, or the padding is invalid,
|
BorrowedOpaqueMessage {
|
||||||
/// or the message (post-unpadding) is too long.
|
typ: self.typ,
|
||||||
pub fn into_tls13_unpadded_message(mut self) -> Result<PlainMessage, Error> {
|
version: self.version,
|
||||||
let payload = &mut self.payload.0;
|
payload: BorrowedPayload::new(self.payload_mut()),
|
||||||
|
|
||||||
if payload.len() > MAX_FRAGMENT_LEN + 1 {
|
|
||||||
return Err(Error::PeerSentOversizedRecord);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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.
|
/// This is the maximum on-the-wire size of a TLSCiphertext.
|
||||||
|
@ -197,8 +181,42 @@ pub struct BorrowedOpaqueMessage<'a> {
|
||||||
pub payload: BorrowedPayload<'a>,
|
pub payload: BorrowedPayload<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
impl<'a> BorrowedOpaqueMessage<'a> {
|
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> {
|
pub(crate) fn read(r: &mut ReaderMut<'a>) -> Result<Self, MessageError> {
|
||||||
let (typ, version, len) = r.as_reader(read_opaque_message_header)?;
|
let (typ, version, len) = r.as_reader(read_opaque_message_header)?;
|
||||||
|
|
||||||
|
@ -213,19 +231,6 @@ impl<'a> BorrowedOpaqueMessage<'a> {
|
||||||
payload,
|
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(
|
fn read_opaque_message_header(
|
||||||
|
@ -268,9 +273,9 @@ fn read_opaque_message_header(
|
||||||
/// the content type, which is returned. See RFC8446 s5.2.
|
/// the content type, which is returned. See RFC8446 s5.2.
|
||||||
///
|
///
|
||||||
/// ContentType(0) is returned if the message payload is empty or all zeroes.
|
/// 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 {
|
loop {
|
||||||
match v.pop() {
|
match p.pop() {
|
||||||
Some(0) => {}
|
Some(0) => {}
|
||||||
Some(content_type) => return ContentType::from(content_type),
|
Some(content_type) => return ContentType::from(content_type),
|
||||||
None => return ContentType::Unknown(0),
|
None => return ContentType::Unknown(0),
|
||||||
|
@ -385,6 +390,7 @@ impl TryFrom<PlainMessage> for Message {
|
||||||
///
|
///
|
||||||
/// This type also cannot decode its internals and
|
/// This type also cannot decode its internals and
|
||||||
/// cannot be read/encoded; only `OpaqueMessage` can do that.
|
/// cannot be read/encoded; only `OpaqueMessage` can do that.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct BorrowedPlainMessage<'a> {
|
pub struct BorrowedPlainMessage<'a> {
|
||||||
pub typ: ContentType,
|
pub typ: ContentType,
|
||||||
pub version: ProtocolVersion,
|
pub version: ProtocolVersion,
|
||||||
|
@ -403,6 +409,19 @@ impl<'a> BorrowedPlainMessage<'a> {
|
||||||
pub fn encoded_len(&self, record_layer: &RecordLayer) -> usize {
|
pub fn encoded_len(&self, record_layer: &RecordLayer) -> usize {
|
||||||
OpaqueMessage::HEADER_SIZE as usize + record_layer.encrypted_len(self.payload.len())
|
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)]
|
#[derive(Debug)]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use core::num::NonZeroU64;
|
use core::num::NonZeroU64;
|
||||||
|
|
||||||
use crate::crypto::cipher::{MessageDecrypter, MessageEncrypter};
|
use crate::crypto::cipher::{BorrowedOpaqueMessage, MessageDecrypter, MessageEncrypter};
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::msgs::message::{BorrowedPlainMessage, OpaqueMessage, PlainMessage};
|
use crate::msgs::message::{BorrowedPlainMessage, OpaqueMessage, PlainMessage};
|
||||||
|
|
||||||
|
@ -62,12 +62,12 @@ impl RecordLayer {
|
||||||
/// an error is returned.
|
/// an error is returned.
|
||||||
pub(crate) fn decrypt_incoming(
|
pub(crate) fn decrypt_incoming(
|
||||||
&mut self,
|
&mut self,
|
||||||
encr: OpaqueMessage,
|
encr: BorrowedOpaqueMessage<'_>,
|
||||||
) -> Result<Option<Decrypted>, Error> {
|
) -> Result<Option<Decrypted>, Error> {
|
||||||
if self.decrypt_state != DirectionState::Active {
|
if self.decrypt_state != DirectionState::Active {
|
||||||
return Ok(Some(Decrypted {
|
return Ok(Some(Decrypted {
|
||||||
want_close_before_decrypt: false,
|
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.
|
// failure has already happened.
|
||||||
let want_close_before_decrypt = self.read_seq == SEQ_SOFT_LIMIT;
|
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
|
match self
|
||||||
.message_decrypter
|
.message_decrypter
|
||||||
.decrypt(encr, self.read_seq)
|
.decrypt(encr, self.read_seq)
|
||||||
|
@ -93,7 +93,7 @@ impl RecordLayer {
|
||||||
}
|
}
|
||||||
Ok(Some(Decrypted {
|
Ok(Some(Decrypted {
|
||||||
want_close_before_decrypt,
|
want_close_before_decrypt,
|
||||||
plaintext,
|
plaintext: plaintext.into_owned(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
Err(Error::DecryptError) if self.doing_trial_decryption(encrypted_len) => {
|
Err(Error::DecryptError) if self.doing_trial_decryption(encrypted_len) => {
|
||||||
|
@ -255,7 +255,11 @@ mod tests {
|
||||||
|
|
||||||
struct PassThroughDecrypter;
|
struct PassThroughDecrypter;
|
||||||
impl MessageDecrypter for 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())
|
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
|
// Decrypting a message should update the read_seq and track that we have now performed
|
||||||
// a decryption.
|
// a decryption.
|
||||||
let msg = OpaqueMessage::new(
|
let mut msg = OpaqueMessage::new(
|
||||||
ContentType::Handshake,
|
ContentType::Handshake,
|
||||||
ProtocolVersion::TLSv1_2,
|
ProtocolVersion::TLSv1_2,
|
||||||
vec![0xC0, 0xFF, 0xEE],
|
vec![0xC0, 0xFF, 0xEE],
|
||||||
);
|
);
|
||||||
record_layer
|
record_layer
|
||||||
.decrypt_incoming(msg)
|
.decrypt_incoming(msg.borrow())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(matches!(record_layer.decrypt_state, DirectionState::Active));
|
assert!(matches!(record_layer.decrypt_state, DirectionState::Active));
|
||||||
assert_eq!(record_layer.read_seq, 1);
|
assert_eq!(record_layer.read_seq, 1);
|
||||||
|
|
Loading…
Reference in New Issue