Split and implement `OutgoingOpaqueMessage`

This commit is contained in:
Joseph Birr-Pixton 2023-12-04 17:03:37 +00:00
parent 22f083e404
commit 0cca8222ed
6 changed files with 107 additions and 74 deletions

View File

@ -8,9 +8,7 @@ use crate::msgs::enums::{AlertLevel, KeyUpdateRequest};
use crate::msgs::fragmenter::MessageFragmenter;
use crate::msgs::handshake::CertificateChain;
use crate::msgs::message::MessagePayload;
use crate::msgs::message::{
BorrowedPlainMessage, Message, OpaqueMessage, OutgoingOpaqueMessage, PlainMessage,
};
use crate::msgs::message::{BorrowedPlainMessage, Message, OutgoingOpaqueMessage, PlainMessage};
use crate::quic;
use crate::record_layer;
use crate::suites::PartiallyExtractedSecrets;
@ -373,7 +371,7 @@ impl CommonState {
// Put m into sendable_tls for writing.
fn queue_tls_message(&mut self, m: OutgoingOpaqueMessage) {
self.sendable_tls.append(m.encode());
self.sendable_tls.append(m.into_bytes());
}
/// Send a raw TLS message, fragmenting it if needed.
@ -563,7 +561,7 @@ impl CommonState {
self.queued_key_update_message = Some(
self.record_layer
.encrypt_outgoing(message.borrow())
.encode(),
.into_bytes(),
);
}

View File

@ -300,16 +300,16 @@ impl MessageEncrypter for GcmMessageEncrypter {
let aad = aead::Aad::from(make_tls12_aad(seq, msg.typ, msg.version, msg.payload.len()));
let total_len = self.encrypted_payload_len(msg.payload.len());
let mut payload = Vec::with_capacity(total_len);
payload.extend_from_slice(&nonce.as_ref()[4..]);
payload.extend_from_slice(msg.payload);
let mut out = OutgoingOpaqueMessage::new(msg.typ, msg.version, total_len);
out.extend_from_slice(&nonce.as_ref()[4..]);
out.extend_from_slice(msg.payload);
self.enc_key
.seal_in_place_separate_tag(nonce, aad, &mut payload[GCM_EXPLICIT_NONCE_LEN..])
.map(|tag| payload.extend(tag.as_ref()))
.seal_in_place_separate_tag(nonce, aad, &mut out.as_mut()[GCM_EXPLICIT_NONCE_LEN..])
.map(|tag| out.extend_from_slice(tag.as_ref()))
.map_err(|_| Error::EncryptError)?;
Ok(OutgoingOpaqueMessage::new(msg.typ, msg.version, payload))
Ok(out)
}
fn encrypted_payload_len(&self, payload_len: usize) -> usize {
@ -377,14 +377,14 @@ impl MessageEncrypter for ChaCha20Poly1305MessageEncrypter {
let aad = aead::Aad::from(make_tls12_aad(seq, msg.typ, msg.version, msg.payload.len()));
let total_len = self.encrypted_payload_len(msg.payload.len());
let mut buf = Vec::with_capacity(total_len);
buf.extend_from_slice(msg.payload);
let mut out = OutgoingOpaqueMessage::new(msg.typ, msg.version, total_len);
out.extend_from_slice(msg.payload);
self.enc_key
.seal_in_place_append_tag(nonce, aad, &mut buf)
.seal_in_place_append_tag(nonce, aad, &mut out)
.map_err(|_| Error::EncryptError)?;
Ok(OutgoingOpaqueMessage::new(msg.typ, msg.version, buf))
Ok(out)
}
fn encrypted_payload_len(&self, payload_len: usize) -> usize {

View File

@ -216,23 +216,23 @@ impl MessageEncrypter for AeadMessageEncrypter {
seq: u64,
) -> Result<OutgoingOpaqueMessage, Error> {
let total_len = self.encrypted_payload_len(msg.payload.len());
let mut payload = Vec::with_capacity(total_len);
payload.extend_from_slice(msg.payload);
msg.typ.encode(&mut payload);
let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, seq).0);
let aad = aead::Aad::from(make_tls13_aad(total_len));
self.enc_key
.seal_in_place_append_tag(nonce, aad, &mut payload)
.map_err(|_| Error::EncryptError)?;
Ok(OutgoingOpaqueMessage::new(
let mut out = OutgoingOpaqueMessage::new(
ContentType::ApplicationData,
// Note: all TLS 1.3 application data records use TLSv1_2 (0x0303) as the legacy record
// protocol version, see https://www.rfc-editor.org/rfc/rfc8446#section-5.1
ProtocolVersion::TLSv1_2,
payload,
))
total_len,
);
out.extend_from_slice(msg.payload);
out.extend_from_slice(&[msg.typ.get_u8()]);
let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, seq).0);
let aad = aead::Aad::from(make_tls13_aad(total_len));
self.enc_key
.seal_in_place_append_tag(nonce, aad, &mut out)
.map_err(|_| Error::EncryptError)?;
Ok(out)
}
fn encrypted_payload_len(&self, payload_len: usize) -> usize {
@ -271,22 +271,22 @@ impl MessageEncrypter for GcmMessageEncrypter {
msg: BorrowedPlainMessage,
seq: u64,
) -> Result<OutgoingOpaqueMessage, Error> {
let total_len = msg.payload.len() + 1 + self.enc_key.algorithm().tag_len();
let mut payload = Vec::with_capacity(total_len);
payload.extend_from_slice(msg.payload);
msg.typ.encode(&mut payload);
let total_len = self.encrypted_payload_len(msg.payload.len());
let mut out = OutgoingOpaqueMessage::new(
ContentType::ApplicationData,
ProtocolVersion::TLSv1_2,
total_len,
);
out.extend_from_slice(msg.payload);
out.extend_from_slice(&[msg.typ.get_u8()]);
let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, seq).0);
let aad = aead::Aad::from(make_tls13_aad(total_len));
self.enc_key
.seal_in_place_append_tag(nonce, aad, &mut payload)
.seal_in_place_append_tag(nonce, aad, &mut out)
.map_err(|_| Error::EncryptError)?;
Ok(OutgoingOpaqueMessage::new(
ContentType::ApplicationData,
ProtocolVersion::TLSv1_2,
payload,
))
Ok(out)
}
fn encrypted_payload_len(&self, payload_len: usize) -> usize {

View File

@ -285,16 +285,16 @@ impl MessageEncrypter for GcmMessageEncrypter {
let aad = aead::Aad::from(make_tls12_aad(seq, msg.typ, msg.version, msg.payload.len()));
let total_len = self.encrypted_payload_len(msg.payload.len());
let mut payload = Vec::with_capacity(total_len);
payload.extend_from_slice(&nonce.as_ref()[4..]);
payload.extend_from_slice(msg.payload);
let mut out = OutgoingOpaqueMessage::new(msg.typ, msg.version, total_len);
out.extend_from_slice(&nonce.as_ref()[4..]);
out.extend_from_slice(msg.payload);
self.enc_key
.seal_in_place_separate_tag(nonce, aad, &mut payload[GCM_EXPLICIT_NONCE_LEN..])
.map(|tag| payload.extend(tag.as_ref()))
.seal_in_place_separate_tag(nonce, aad, &mut out.as_mut()[GCM_EXPLICIT_NONCE_LEN..])
.map(|tag| out.extend_from_slice(tag.as_ref()))
.map_err(|_| Error::EncryptError)?;
Ok(OutgoingOpaqueMessage::new(msg.typ, msg.version, payload))
Ok(out)
}
fn encrypted_payload_len(&self, payload_len: usize) -> usize {
@ -362,14 +362,14 @@ impl MessageEncrypter for ChaCha20Poly1305MessageEncrypter {
let aad = aead::Aad::from(make_tls12_aad(seq, msg.typ, msg.version, msg.payload.len()));
let total_len = self.encrypted_payload_len(msg.payload.len());
let mut buf = Vec::with_capacity(total_len);
buf.extend_from_slice(msg.payload);
let mut out = OutgoingOpaqueMessage::new(msg.typ, msg.version, total_len);
out.extend_from_slice(msg.payload);
self.enc_key
.seal_in_place_append_tag(nonce, aad, &mut buf)
.seal_in_place_append_tag(nonce, aad, &mut out)
.map_err(|_| Error::EncryptError)?;
Ok(OutgoingOpaqueMessage::new(msg.typ, msg.version, buf))
Ok(out)
}
fn encrypted_payload_len(&self, payload_len: usize) -> usize {

View File

@ -188,23 +188,23 @@ impl MessageEncrypter for Tls13MessageEncrypter {
seq: u64,
) -> Result<OutgoingOpaqueMessage, Error> {
let total_len = self.encrypted_payload_len(msg.payload.len());
let mut payload = Vec::with_capacity(total_len);
payload.extend_from_slice(msg.payload);
msg.typ.encode(&mut payload);
let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, seq).0);
let aad = aead::Aad::from(make_tls13_aad(total_len));
self.enc_key
.seal_in_place_append_tag(nonce, aad, &mut payload)
.map_err(|_| Error::EncryptError)?;
Ok(OutgoingOpaqueMessage::new(
let mut out = OutgoingOpaqueMessage::new(
ContentType::ApplicationData,
// Note: all TLS 1.3 application data records use TLSv1_2 (0x0303) as the legacy record
// protocol version, see https://www.rfc-editor.org/rfc/rfc8446#section-5.1
ProtocolVersion::TLSv1_2,
payload,
))
total_len,
);
out.extend_from_slice(msg.payload);
out.extend_from_slice(&[msg.typ.get_u8()]);
let nonce = aead::Nonce::assume_unique_for_key(Nonce::new(&self.iv, seq).0);
let aad = aead::Aad::from(make_tls13_aad(total_len));
self.enc_key
.seal_in_place_append_tag(nonce, aad, &mut out)
.map_err(|_| Error::EncryptError)?;
Ok(out)
}
fn encrypted_payload_len(&self, payload_len: usize) -> usize {

View File

@ -72,7 +72,46 @@ impl MessagePayload {
}
/// A TLS frame in the process of being sent, named TLSPlaintext in the standard.
pub type OutgoingOpaqueMessage = OpaqueMessage;
///
/// This is stored pre-encoded.
pub struct OutgoingOpaqueMessage(Vec<u8>);
impl OutgoingOpaqueMessage {
/// Encode a new `OutgoingOpaqueMessage` from the header items.
///
/// On exit, the interior `Vec` has a capacity of `body_len` plus `OpaqueMessage::HEADER_SIZE` bytes,
/// and has a size of `OpaqueMessage::HEADER_SIZE`.
///
/// The caller must then append exactly `body_len` bytes.
pub fn new(typ: ContentType, version: ProtocolVersion, body_len: usize) -> Self {
let mut buf =
Vec::with_capacity(body_len.saturating_add(OpaqueMessage::HEADER_SIZE as usize));
typ.encode(&mut buf);
version.encode(&mut buf);
(body_len as u16).encode(&mut buf);
Self(buf)
}
pub fn extend_from_slice(&mut self, slice: &[u8]) {
self.0.extend_from_slice(slice);
}
pub(crate) fn into_bytes(self) -> Vec<u8> {
self.0
}
}
impl<'a> Extend<&'a u8> for OutgoingOpaqueMessage {
fn extend<T: IntoIterator<Item = &'a u8>>(&mut self, iter: T) {
self.0.extend(iter);
}
}
impl AsMut<[u8]> for OutgoingOpaqueMessage {
fn as_mut(&mut self) -> &mut [u8] {
&mut self.0[OpaqueMessage::HEADER_SIZE as usize..]
}
}
/// A TLS frame, named TLSPlaintext in the standard.
///
@ -263,12 +302,10 @@ pub struct PlainMessage {
}
impl PlainMessage {
pub fn into_unencrypted_opaque(self) -> OpaqueMessage {
OpaqueMessage {
version: self.version,
typ: self.typ,
payload: self.payload,
}
pub fn into_unencrypted_opaque(self) -> OutgoingOpaqueMessage {
let mut r = OutgoingOpaqueMessage::new(self.typ, self.version, self.payload.0.len());
r.extend_from_slice(&self.payload.0);
r
}
pub fn borrow(&self) -> BorrowedPlainMessage<'_> {
@ -345,12 +382,10 @@ pub struct BorrowedPlainMessage<'a> {
}
impl<'a> BorrowedPlainMessage<'a> {
pub fn to_unencrypted_opaque(&self) -> OpaqueMessage {
OpaqueMessage {
version: self.version,
typ: self.typ,
payload: Payload(self.payload.to_vec()),
}
pub fn to_unencrypted_opaque(&self) -> OutgoingOpaqueMessage {
let mut r = OutgoingOpaqueMessage::new(self.typ, self.version, self.payload.len());
r.extend_from_slice(self.payload);
r
}
}