Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test #6

Merged
merged 2 commits into from
Nov 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ resolver = "2"
[workspace.dependencies]
boring = { version = "4.0", default-features = false }
boring-sys = { version = "4.0", default-features = false }
rustls = { version = "=0.22.0-alpha.4", default-features = false }
rustls = { version = "=0.22.0-alpha.5", default-features = false }
6 changes: 4 additions & 2 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This is just a dump of me figuring out how to interface with boring and rustls.
It works to establish a connection and exchange data but I haven't written real tests yet, nor did I cleanup the code or made the effort to make it look nice.
There is probably some code in here that should rather live in the `boring` crate.

Further, the rustls crypto provider API is still not stable it seems. This works currently with `rustls = 0.22.0-alpha.4`.
Further, the rustls crypto provider API is still not stable it seems. This works currently with `rustls = 0.22.0-alpha.5`.

### Supported ciphers
Currently, supports only TLS 1.3:
Expand All @@ -17,7 +17,9 @@ AES_256_GCM_SHA384
CHACHA20_POLY1305_SHA256
```

TLS 1.2 (only ECDSA is tested):
QUIC: not yet supported

TLS 1.2:
```
ECDHE_ECDSA_AES128_GCM_SHA256
ECDHE_RSA_AES128_GCM_SHA256
Expand Down
74 changes: 37 additions & 37 deletions boring-rustls-provider/src/aead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,19 @@ pub(crate) mod aes;
pub(crate) mod chacha20;

pub(crate) trait BoringCipher {
/// Constructs a new instance of this cipher as an AEAD algorithm
fn new_cipher() -> Algorithm;
/// The key size in bytes
fn key_size() -> usize;
/// The lengths of the explicit nonce. (Not the full nonce length, only the part that changes)
/// See also [`BoringCipher::fixed_iv_len`]
const EXPLICIT_NONCE_LEN: usize;
/// The IV's fixed length (Not the full IV length, only the part that doesn't change).
/// Together with [`BoringCipher::explicit_nonce_len`] it determines the total
/// lengths of the used nonce.
fn fixed_iv_len() -> usize;
/// The lengths of the explicit nonce. (Not the full nonce length, only the part that changes)
/// See also [`BoringCipher::fixed_iv_len`]
fn explicit_nonce_len() -> usize;
const FIXED_IV_LEN: usize;
/// The key size in bytes
const KEY_SIZE: usize;

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

/// Extract keys
fn extract_keys(key: cipher::AeadKey, iv: cipher::Iv) -> ConnectionTrafficSecrets;
}
Expand Down Expand Up @@ -107,7 +109,7 @@ where
T: BoringAead,
{
fn encrypt(
&self,
&mut self,
msg: cipher::BorrowedPlainMessage,
seq: u64,
) -> Result<cipher::OpaqueMessage, rustls::Error> {
Expand All @@ -116,11 +118,10 @@ where
match self.tls_version {
#[cfg(feature = "tls12")]
ProtocolVersion::TLSv1_2 => {
let fixed_iv_len = <T as BoringCipher>::fixed_iv_len();
let explicit_nonce_len = <T as BoringCipher>::explicit_nonce_len();
let fixed_iv_len = <T as BoringCipher>::FIXED_IV_LEN;
let explicit_nonce_len = <T as BoringCipher>::EXPLICIT_NONCE_LEN;

let total_len =
msg.payload.len() + self.crypter.max_overhead() + explicit_nonce_len;
let total_len = self.encrypted_payload_len(msg.payload.len());

let mut full_payload = Vec::with_capacity(total_len);
full_payload.extend_from_slice(&nonce.0.as_ref()[fixed_iv_len..]);
Expand All @@ -137,7 +138,7 @@ where
}

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

let mut payload = Vec::with_capacity(total_len);
payload.extend_from_slice(msg.payload);
Expand All @@ -158,28 +159,30 @@ where
}
}

// Next version seems to add this
// fn encrypted_payload_len(&self, payload_len: usize) -> usize {
// payload_len + 1 + self.crypter.max_overhead()
// }
fn encrypted_payload_len(&self, payload_len: usize) -> usize {
match self.tls_version {
ProtocolVersion::TLSv1_2 => {
payload_len + self.crypter.max_overhead() + <T as BoringCipher>::EXPLICIT_NONCE_LEN
}
ProtocolVersion::TLSv1_3 => payload_len + 1 + self.crypter.max_overhead(),
_ => unimplemented!(),
}
}
}

impl<T> cipher::MessageDecrypter for BoringAeadCrypter<T>
where
T: BoringAead,
{
fn decrypt(
&self,
&mut self,
mut m: cipher::OpaqueMessage,
seq: u64,
) -> Result<cipher::PlainMessage, rustls::Error> {
// construct nonce

// construct the aad and decrypt
match self.tls_version {
#[cfg(feature = "tls12")]
ProtocolVersion::TLSv1_2 => {
let explicit_nonce_len = <T as BoringCipher>::explicit_nonce_len();
let explicit_nonce_len = <T as BoringCipher>::EXPLICIT_NONCE_LEN;

// payload is: [nonce] | [ciphertext] | [auth tag]
let actual_payload_length =
Expand All @@ -193,12 +196,12 @@ where
let (explicit_nonce, payload) = payload.split_at_mut(explicit_nonce_len);

let nonce = {
let fixed_iv_len = <T as BoringCipher>::fixed_iv_len();
let fixed_iv_len = <T as BoringCipher>::FIXED_IV_LEN;

assert_eq!(explicit_nonce_len + fixed_iv_len, 12);

// grab the IV by constructing a nonce, this is just an xor
let iv = cipher::Nonce::new(&self.iv, 0).0;
let iv = cipher::Nonce::new(&self.iv, seq).0;
let mut nonce = [0u8; 12];
nonce[..fixed_iv_len].copy_from_slice(&iv[..fixed_iv_len]);
nonce[fixed_iv_len..].copy_from_slice(explicit_nonce);
Expand All @@ -211,7 +214,7 @@ where

self.crypter
.open_in_place(&nonce, &aad, payload, tag)
.map_err(|_| rustls::Error::DecryptError)
.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);
Expand Down Expand Up @@ -256,7 +259,7 @@ impl<T: BoringAead + 'static> cipher::Tls13AeadAlgorithm for Aead<T> {
}

fn key_len(&self) -> usize {
<T as BoringCipher>::key_size()
<T as BoringCipher>::KEY_SIZE
}

fn extract_keys(
Expand Down Expand Up @@ -286,10 +289,9 @@ impl<T: BoringAead + 'static> cipher::Tls12AeadAlgorithm for Aead<T> {
}

fn decrypter(&self, key: cipher::AeadKey, iv: &[u8]) -> Box<dyn cipher::MessageDecrypter> {
let mut pseudo_iv =
Vec::with_capacity(iv.len() + <T as BoringCipher>::explicit_nonce_len());
let mut pseudo_iv = Vec::with_capacity(iv.len() + <T as BoringCipher>::EXPLICIT_NONCE_LEN);
pseudo_iv.extend_from_slice(iv);
pseudo_iv.extend_from_slice(&vec![0u8; <T as BoringCipher>::explicit_nonce_len()]);
pseudo_iv.extend_from_slice(&vec![0u8; <T as BoringCipher>::EXPLICIT_NONCE_LEN]);
Box::new(
BoringAeadCrypter::<T>::new(
Iv::copy(&pseudo_iv),
Expand All @@ -302,11 +304,9 @@ impl<T: BoringAead + 'static> cipher::Tls12AeadAlgorithm for Aead<T> {

fn key_block_shape(&self) -> cipher::KeyBlockShape {
cipher::KeyBlockShape {
enc_key_len: <T as BoringCipher>::key_size(),
// there is no benefit of splitting these up here, we'd need to stich them anyways
// by only setting fixed_iv_len we get the full lengths
fixed_iv_len: <T as BoringCipher>::fixed_iv_len(),
explicit_nonce_len: <T as BoringCipher>::explicit_nonce_len(),
enc_key_len: <T as BoringCipher>::KEY_SIZE,
fixed_iv_len: <T as BoringCipher>::FIXED_IV_LEN,
explicit_nonce_len: <T as BoringCipher>::EXPLICIT_NONCE_LEN,
}
}

Expand All @@ -317,8 +317,8 @@ impl<T: BoringAead + 'static> cipher::Tls12AeadAlgorithm for Aead<T> {
explicit: &[u8],
) -> Result<ConnectionTrafficSecrets, cipher::UnsupportedOperationError> {
let nonce = {
let fixed_iv_len = <T as BoringCipher>::fixed_iv_len();
let explicit_nonce_len = <T as BoringCipher>::explicit_nonce_len();
let fixed_iv_len = <T as BoringCipher>::FIXED_IV_LEN;
let explicit_nonce_len = <T as BoringCipher>::EXPLICIT_NONCE_LEN;
assert_eq!(explicit_nonce_len + fixed_iv_len, 12);

// grab the IV by constructing a nonce, this is just an xor
Expand Down
36 changes: 12 additions & 24 deletions boring-rustls-provider/src/aead/aes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,19 @@ pub struct Aes128 {}
impl BoringAead for Aes128 {}

impl BoringCipher for Aes128 {
const EXPLICIT_NONCE_LEN: usize = 8;

const FIXED_IV_LEN: usize = 4;

const KEY_SIZE: usize = 16;

fn new_cipher() -> Algorithm {
Algorithm::aes_128_gcm()
}

fn key_size() -> usize {
16
}

fn extract_keys(key: cipher::AeadKey, iv: cipher::Iv) -> ConnectionTrafficSecrets {
ConnectionTrafficSecrets::Aes128Gcm { key, iv }
}

fn fixed_iv_len() -> usize {
4
}

fn explicit_nonce_len() -> usize {
8
}
}

impl aead::AeadCore for Aes128 {
Expand All @@ -42,25 +36,19 @@ pub struct Aes256 {}
impl BoringAead for Aes256 {}

impl BoringCipher for Aes256 {
const EXPLICIT_NONCE_LEN: usize = 8;

const FIXED_IV_LEN: usize = 4;

const KEY_SIZE: usize = 32;

fn new_cipher() -> Algorithm {
Algorithm::aes_256_gcm()
}

fn key_size() -> usize {
32
}

fn extract_keys(key: cipher::AeadKey, iv: cipher::Iv) -> ConnectionTrafficSecrets {
ConnectionTrafficSecrets::Aes256Gcm { key, iv }
}

fn fixed_iv_len() -> usize {
4
}

fn explicit_nonce_len() -> usize {
8
}
}

impl aead::AeadCore for Aes256 {
Expand Down
18 changes: 6 additions & 12 deletions boring-rustls-provider/src/aead/chacha20.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,19 @@ pub struct ChaCha20Poly1305 {}
impl BoringAead for ChaCha20Poly1305 {}

impl BoringCipher for ChaCha20Poly1305 {
const EXPLICIT_NONCE_LEN: usize = 0;

const FIXED_IV_LEN: usize = 12;

const KEY_SIZE: usize = 32;

fn new_cipher() -> Algorithm {
Algorithm::chacha20_poly1305()
}

fn key_size() -> usize {
32
}

fn extract_keys(key: cipher::AeadKey, iv: cipher::Iv) -> ConnectionTrafficSecrets {
ConnectionTrafficSecrets::Chacha20Poly1305 { key, iv }
}

fn fixed_iv_len() -> usize {
4
}

fn explicit_nonce_len() -> usize {
8
}
}

impl AeadCore for ChaCha20Poly1305 {
Expand Down
1 change: 1 addition & 0 deletions boring-rustls-provider/src/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub(crate) fn cvt(r: c_int) -> Result<i32, ErrorStack> {
}

#[cfg(feature = "log")]
#[inline(always)]
pub(crate) fn log_and_map<E: core::fmt::Display, T>(func: &'static str, e: E, mapped: T) -> T {
trace!("failed {}, error: {}", func, e);
mapped
Expand Down
12 changes: 12 additions & 0 deletions boring-rustls-provider/src/tls12.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ pub static ECDHE_ECDSA_AES128_GCM_SHA256: Tls12CipherSuite = Tls12CipherSuite {
common: rustls::CipherSuiteCommon {
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 @@ -37,6 +39,8 @@ pub static ECDHE_RSA_AES128_GCM_SHA256: Tls12CipherSuite = Tls12CipherSuite {
common: rustls::CipherSuiteCommon {
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 @@ -48,6 +52,8 @@ pub static ECDHE_ECDSA_AES256_GCM_SHA384: Tls12CipherSuite = Tls12CipherSuite {
common: rustls::CipherSuiteCommon {
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 @@ -59,6 +65,8 @@ pub static ECDHE_RSA_AES256_GCM_SHA384: Tls12CipherSuite = Tls12CipherSuite {
common: rustls::CipherSuiteCommon {
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 @@ -70,6 +78,8 @@ pub static ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: Tls12CipherSuite = Tls12Ci
common: rustls::CipherSuiteCommon {
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 @@ -81,6 +91,8 @@ pub static ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: Tls12CipherSuite = Tls12Ciph
common: rustls::CipherSuiteCommon {
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
9 changes: 9 additions & 0 deletions boring-rustls-provider/src/tls13.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,35 @@ pub static AES_128_GCM_SHA256: Tls13CipherSuite = Tls13CipherSuite {
common: rustls::CipherSuiteCommon {
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,
quic: None,
};

pub static AES_256_GCM_SHA384: Tls13CipherSuite = Tls13CipherSuite {
common: rustls::CipherSuiteCommon {
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,
quic: None,
};

pub static CHACHA20_POLY1305_SHA256: Tls13CipherSuite = Tls13CipherSuite {
common: rustls::CipherSuiteCommon {
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,
aead_alg: &aead::Aead::<aead::chacha20::ChaCha20Poly1305>::DEFAULT,
quic: None,
};
Loading