Skip to content

Commit

Permalink
Update to rustls 0.23
Browse files Browse the repository at this point in the history
  • Loading branch information
howardjohn authored and janrueth committed Mar 27, 2024
1 parent 03b4813 commit aa6e1c3
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 44 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ resolver = "2"
[workspace.dependencies]
boring = { version = "4", default-features = false }
boring-sys = { version = "4", default-features = false }
rustls = { version = "0.22", default-features = false }
rustls = { version = "0.23", default-features = false }
rustls-pemfile = { version = "2" }
rustls-pki-types = { version = "1" }
tokio-rustls = { version = "0.25" }
tokio-rustls = { version = "0.26", default-features = false }
webpki = { package = "rustls-webpki", version = "0.102", default-features = false }
webpki-roots = { version = "0.26" }
136 changes: 104 additions & 32 deletions boring-rustls-provider/src/aead.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use std::marker::PhantomData;

use aead::{AeadCore, AeadInPlace, Nonce, Tag};
use aead::{AeadCore, AeadInPlace, Buffer, Nonce, Tag};
use boring::error::ErrorStack;
use boring_additions::aead::Algorithm;
use rustls::crypto::cipher::{self, make_tls12_aad, make_tls13_aad, Iv};
use rustls::crypto::cipher::{
self, make_tls12_aad, make_tls13_aad, BorrowedPayload, Iv, PrefixedPayload,
};
use rustls::{ConnectionTrafficSecrets, ContentType, ProtocolVersion};

use crate::helper::log_and_map;
Expand All @@ -25,6 +27,12 @@ pub(crate) trait BoringCipher {
/// The length of the authentication tag
const TAG_LEN: usize;

/// integrity limit
const INTEGRITY_LIMIT: u64;

/// confidentiality limit
const CONFIDENTIALITY_LIMIT: u64;

/// Constructs a new instance of this cipher as an AEAD algorithm
fn new_cipher() -> Algorithm;

Expand Down Expand Up @@ -123,11 +131,10 @@ where
{
fn encrypt(
&mut self,
msg: cipher::BorrowedPlainMessage,
msg: cipher::OutboundPlainMessage,
seq: u64,
) -> Result<cipher::OpaqueMessage, rustls::Error> {
) -> Result<cipher::OutboundOpaqueMessage, rustls::Error> {
let nonce = cipher::Nonce::new(&self.iv, seq);

match self.tls_version {
#[cfg(feature = "tls12")]
ProtocolVersion::TLSv1_2 => {
Expand All @@ -136,37 +143,41 @@ where

let total_len = self.encrypted_payload_len(msg.payload.len());

let mut full_payload = Vec::with_capacity(total_len);
let mut full_payload = PrefixedPayload::with_capacity(total_len);
full_payload.extend_from_slice(&nonce.0.as_ref()[fixed_iv_len..]);
full_payload.extend_from_slice(msg.payload);
full_payload.extend_from_chunks(&msg.payload);
full_payload.extend_from_slice(&vec![0u8; self.crypter.max_overhead()]);

let (_, payload) = full_payload.split_at_mut(explicit_nonce_len);
let (_, payload) = full_payload.as_mut().split_at_mut(explicit_nonce_len);
let (payload, tag) = payload.split_at_mut(msg.payload.len());
let aad = cipher::make_tls12_aad(seq, msg.typ, msg.version, msg.payload.len());
self.crypter
.seal_in_place(&nonce.0, &aad, payload, tag)
.map_err(|_| rustls::Error::EncryptError)
.map(|_| cipher::OpaqueMessage::new(msg.typ, msg.version, full_payload))
.map(|_| cipher::OutboundOpaqueMessage::new(msg.typ, msg.version, full_payload))
}

ProtocolVersion::TLSv1_3 => {
let total_len = self.encrypted_payload_len(msg.payload.len());

let mut payload = Vec::with_capacity(total_len);
payload.extend_from_slice(msg.payload);
payload.push(msg.typ.get_u8());
let mut payload = PrefixedPayload::with_capacity(total_len);
payload.extend_from_chunks(&msg.payload);
payload.extend_from_slice(&msg.typ.to_array());

let aad = cipher::make_tls13_aad(total_len);
self.encrypt_in_place(Nonce::<T>::from_slice(&nonce.0), &aad, &mut payload)
.map_err(|_| rustls::Error::EncryptError)
.map(|_| {
cipher::OpaqueMessage::new(
ContentType::ApplicationData,
ProtocolVersion::TLSv1_2,
payload,
)
})
self.encrypt_in_place(
Nonce::<T>::from_slice(&nonce.0),
&aad,
&mut EncryptBufferAdapter(&mut payload),
)
.map_err(|_| rustls::Error::EncryptError)
.map(|_| {
cipher::OutboundOpaqueMessage::new(
ContentType::ApplicationData,
ProtocolVersion::TLSv1_2,
payload,
)
})
}
_ => unimplemented!(),
}
Expand All @@ -187,23 +198,23 @@ impl<T> cipher::MessageDecrypter for BoringAeadCrypter<T>
where
T: BoringAead,
{
fn decrypt(
fn decrypt<'a>(
&mut self,
mut m: cipher::OpaqueMessage,
mut m: cipher::InboundOpaqueMessage<'a>,
seq: u64,
) -> Result<cipher::PlainMessage, rustls::Error> {
) -> Result<cipher::InboundPlainMessage<'a>, rustls::Error> {
match self.tls_version {
#[cfg(feature = "tls12")]
ProtocolVersion::TLSv1_2 => {
let explicit_nonce_len = <T as BoringCipher>::EXPLICIT_NONCE_LEN;

// payload is: [nonce] | [ciphertext] | [auth tag]
let actual_payload_length =
m.payload().len() - self.crypter.max_overhead() - explicit_nonce_len;
m.payload.len() - self.crypter.max_overhead() - explicit_nonce_len;

let aad = make_tls12_aad(seq, m.typ, m.version, actual_payload_length);

let payload = m.payload_mut();
let payload = &mut m.payload;

// get the nonce
let (explicit_nonce, payload) = payload.split_at_mut(explicit_nonce_len);
Expand All @@ -230,20 +241,24 @@ where
.map_err(|e| log_and_map("open_in_place", e, rustls::Error::DecryptError))
.map(|_| {
// rotate the nonce to the end
m.payload_mut().rotate_left(explicit_nonce_len);
m.payload.rotate_left(explicit_nonce_len);

// truncate buffer to the actual payload
m.payload_mut().truncate(actual_payload_length);
m.payload.truncate(actual_payload_length);

m.into_plain_message()
})
}
ProtocolVersion::TLSv1_3 => {
let nonce = cipher::Nonce::new(&self.iv, seq);
let aad = make_tls13_aad(m.payload().len());
self.decrypt_in_place(Nonce::<T>::from_slice(&nonce.0), &aad, m.payload_mut())
.map_err(|_| rustls::Error::DecryptError)
.and_then(|_| m.into_tls13_unpadded_message())
let aad = make_tls13_aad(m.payload.len());
self.decrypt_in_place(
Nonce::<T>::from_slice(&nonce.0),
&aad,
&mut DecryptBufferAdapter(&mut m.payload),
)
.map_err(|_| rustls::Error::DecryptError)
.and_then(|_| m.into_tls13_unpadded_message())
}
_ => unimplemented!(),
}
Expand Down Expand Up @@ -290,6 +305,14 @@ where
fn tag_len(&self) -> usize {
<T as BoringCipher>::TAG_LEN
}

fn confidentiality_limit(&self) -> u64 {
<T as BoringCipher>::CONFIDENTIALITY_LIMIT
}

fn integrity_limit(&self) -> u64 {
<T as BoringCipher>::INTEGRITY_LIMIT
}
}

pub(crate) struct Aead<T>(PhantomData<T>);
Expand Down Expand Up @@ -494,6 +517,55 @@ where
}
}

struct DecryptBufferAdapter<'a, 'p>(&'a mut BorrowedPayload<'p>);

impl AsRef<[u8]> for DecryptBufferAdapter<'_, '_> {
fn as_ref(&self) -> &[u8] {
self.0
}
}

impl AsMut<[u8]> for DecryptBufferAdapter<'_, '_> {
fn as_mut(&mut self) -> &mut [u8] {
self.0
}
}

impl Buffer for DecryptBufferAdapter<'_, '_> {
fn extend_from_slice(&mut self, _: &[u8]) -> aead::Result<()> {
unreachable!("not used by `AeadInPlace::decrypt_in_place`")
}

fn truncate(&mut self, len: usize) {
self.0.truncate(len)
}
}

struct EncryptBufferAdapter<'a>(&'a mut PrefixedPayload);

impl AsRef<[u8]> for EncryptBufferAdapter<'_> {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}

impl AsMut<[u8]> for EncryptBufferAdapter<'_> {
fn as_mut(&mut self) -> &mut [u8] {
self.0.as_mut()
}
}

impl Buffer for EncryptBufferAdapter<'_> {
fn extend_from_slice(&mut self, other: &[u8]) -> aead::Result<()> {
self.0.extend_from_slice(other);
Ok(())
}

fn truncate(&mut self, len: usize) {
self.0.truncate(len)
}
}

#[cfg(test)]
mod tests {
use hex_literal::hex;
Expand Down
6 changes: 6 additions & 0 deletions boring-rustls-provider/src/aead/aes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ impl BoringCipher for Aes128 {

const TAG_LEN: usize = 16;

const INTEGRITY_LIMIT: u64 = 1 << 52;
const CONFIDENTIALITY_LIMIT: u64 = 1 << 23;

fn new_cipher() -> Algorithm {
Algorithm::aes_128_gcm()
}
Expand Down Expand Up @@ -58,6 +61,9 @@ impl BoringCipher for Aes256 {

const TAG_LEN: usize = 16;

const INTEGRITY_LIMIT: u64 = 1 << 52;
const CONFIDENTIALITY_LIMIT: u64 = 1 << 23;

fn new_cipher() -> Algorithm {
Algorithm::aes_256_gcm()
}
Expand Down
3 changes: 3 additions & 0 deletions boring-rustls-provider/src/aead/chacha20.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ impl BoringCipher for ChaCha20Poly1305 {

const TAG_LEN: usize = 16;

const INTEGRITY_LIMIT: u64 = 1 << 36;
const CONFIDENTIALITY_LIMIT: u64 = u64::MAX;

fn new_cipher() -> Algorithm {
Algorithm::chacha20_poly1305()
}
Expand Down
6 changes: 0 additions & 6 deletions boring-rustls-provider/src/tls12.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ pub static ECDHE_ECDSA_AES128_GCM_SHA256: Tls12CipherSuite = Tls12CipherSuite {
suite: rustls::CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
hash_provider: hash::SHA256,
confidentiality_limit: 1 << 23,
integrity_limit: 1 << 52,
},
aead_alg: &aead::Aead::<aead::aes::Aes128>::DEFAULT,
prf_provider: &PRF_SHA256,
Expand All @@ -40,7 +39,6 @@ pub static ECDHE_RSA_AES128_GCM_SHA256: Tls12CipherSuite = Tls12CipherSuite {
suite: rustls::CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
hash_provider: hash::SHA256,
confidentiality_limit: 1 << 23,
integrity_limit: 1 << 52,
},
aead_alg: &aead::Aead::<aead::aes::Aes128>::DEFAULT,
prf_provider: &PRF_SHA256,
Expand All @@ -53,7 +51,6 @@ pub static ECDHE_ECDSA_AES256_GCM_SHA384: Tls12CipherSuite = Tls12CipherSuite {
suite: rustls::CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
hash_provider: hash::SHA384,
confidentiality_limit: 1 << 23,
integrity_limit: 1 << 52,
},
aead_alg: &aead::Aead::<aead::aes::Aes256>::DEFAULT,
prf_provider: &PRF_SHA384,
Expand All @@ -66,7 +63,6 @@ pub static ECDHE_RSA_AES256_GCM_SHA384: Tls12CipherSuite = Tls12CipherSuite {
suite: rustls::CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
hash_provider: hash::SHA384,
confidentiality_limit: 1 << 23,
integrity_limit: 1 << 52,
},
aead_alg: &aead::Aead::<aead::aes::Aes256>::DEFAULT,
prf_provider: &PRF_SHA384,
Expand All @@ -79,7 +75,6 @@ pub static ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: Tls12CipherSuite = Tls12Ci
suite: rustls::CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
hash_provider: hash::SHA256,
confidentiality_limit: u64::MAX,
integrity_limit: 1 << 36,
},
aead_alg: &aead::Aead::<aead::chacha20::ChaCha20Poly1305>::DEFAULT,
prf_provider: &PRF_SHA256,
Expand All @@ -92,7 +87,6 @@ pub static ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: Tls12CipherSuite = Tls12Ciph
suite: rustls::CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
hash_provider: hash::SHA256,
confidentiality_limit: u64::MAX,
integrity_limit: 1 << 36,
},
aead_alg: &aead::Aead::<aead::chacha20::ChaCha20Poly1305>::DEFAULT,
prf_provider: &PRF_SHA256,
Expand Down
3 changes: 0 additions & 3 deletions boring-rustls-provider/src/tls13.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ pub static AES_128_GCM_SHA256: Tls13CipherSuite = Tls13CipherSuite {
suite: rustls::CipherSuite::TLS13_AES_128_GCM_SHA256,
hash_provider: hash::SHA256,
confidentiality_limit: 1 << 23,
integrity_limit: 1 << 52,
},
hkdf_provider: &hkdf::Hkdf::<hkdf::Sha256>::DEFAULT,
aead_alg: &aead::Aead::<aead::aes::Aes128>::DEFAULT,
Expand All @@ -19,7 +18,6 @@ pub static AES_256_GCM_SHA384: Tls13CipherSuite = Tls13CipherSuite {
suite: rustls::CipherSuite::TLS13_AES_256_GCM_SHA384,
hash_provider: hash::SHA384,
confidentiality_limit: 1 << 23,
integrity_limit: 1 << 52,
},
hkdf_provider: &hkdf::Hkdf::<hkdf::Sha384>::DEFAULT,
aead_alg: &aead::Aead::<aead::aes::Aes256>::DEFAULT,
Expand All @@ -31,7 +29,6 @@ pub static CHACHA20_POLY1305_SHA256: Tls13CipherSuite = Tls13CipherSuite {
suite: rustls::CipherSuite::TLS13_CHACHA20_POLY1305_SHA256,
hash_provider: hash::SHA256,
confidentiality_limit: u64::MAX,
integrity_limit: 1 << 36,
},

hkdf_provider: &hkdf::Hkdf::<hkdf::Sha256>::DEFAULT,
Expand Down
2 changes: 1 addition & 1 deletion examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ log = { version = "0.4.4" }
mio = { version = "0.8", features = ["net", "os-poll"] }
pki-types = { package = "rustls-pki-types", version = "0.2" }
rcgen = { version = "0.11.3", features = ["pem"], default-features = false }
rustls = { workspace = true, features = [ "logging" ]}
rustls = { workspace = true, features = [ "logging", "std" ]}
boring-rustls-provider = { path = "../boring-rustls-provider", features = ["logging"] }
rustls-pemfile = { workspace = true }
serde = "1.0"
Expand Down

0 comments on commit aa6e1c3

Please sign in to comment.