Fix AES256 using wrong hash
Add TLS 1.2 Move aead crypter to boring-additions crate
This commit is contained in:
parent
5c45b9426b
commit
319029f2d4
17 changed files with 424 additions and 51 deletions
|
|
@ -1,5 +1,7 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
|
# things that should probably be in boring crate
|
||||||
|
"boring-additions",
|
||||||
# the main library and tests
|
# the main library and tests
|
||||||
"boring-rustls-provider",
|
"boring-rustls-provider",
|
||||||
# tests and example code
|
# tests and example code
|
||||||
|
|
@ -13,4 +15,6 @@ default-members = [
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[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.4", default-features = false }
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ Further, the rustls crypto provider API is still not stable it seems. This works
|
||||||
Currently, supports only TLS 1.3:
|
Currently, supports only TLS 1.3:
|
||||||
```
|
```
|
||||||
AES_128_GCM_SHA256
|
AES_128_GCM_SHA256
|
||||||
AES_256_GCM_SHA256
|
AES_256_GCM_SHA384
|
||||||
CHACHA20_POLY1305_SHA256
|
CHACHA20_POLY1305_SHA256
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
18
boring-additions/Cargo.toml
Normal file
18
boring-additions/Cargo.toml
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
[package]
|
||||||
|
name = "boring-additions"
|
||||||
|
version = "0.0.1"
|
||||||
|
authors = ["Jan Rüth <boring-rustls-provider@djiehmail.com>"]
|
||||||
|
edition = "2021"
|
||||||
|
license = "MIT"
|
||||||
|
description = "Boring additions"
|
||||||
|
publish = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
aead = { version = "0.5", default_features = false, features = ["alloc"] }
|
||||||
|
boring = { workspace = true }
|
||||||
|
boring-sys = { workspace = true }
|
||||||
|
foreign-types = "0.5"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
29
boring-additions/src/helper.rs
Normal file
29
boring-additions/src/helper.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
use std::os::raw::c_int;
|
||||||
|
|
||||||
|
use boring::error::ErrorStack;
|
||||||
|
|
||||||
|
/// Check the value returned from a BoringSSL ffi call
|
||||||
|
/// that returns a pointer.
|
||||||
|
///
|
||||||
|
/// If the pointer is null, this method returns the BoringSSL
|
||||||
|
/// ErrorStack as Err, the pointer otherwise.
|
||||||
|
pub(crate) fn cvt_p<T>(r: *mut T) -> Result<*mut T, ErrorStack> {
|
||||||
|
if r.is_null() {
|
||||||
|
Err(ErrorStack::get())
|
||||||
|
} else {
|
||||||
|
Ok(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check the value returned from a BoringSSL ffi call that
|
||||||
|
/// returns a integer.
|
||||||
|
///
|
||||||
|
/// Returns the BoringSSL Errorstack when the result is <= 0.
|
||||||
|
/// And forwards the return code otherwise
|
||||||
|
pub(crate) fn cvt(r: c_int) -> Result<i32, ErrorStack> {
|
||||||
|
if r <= 0 {
|
||||||
|
Err(ErrorStack::get())
|
||||||
|
} else {
|
||||||
|
Ok(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
2
boring-additions/src/lib.rs
Normal file
2
boring-additions/src/lib.rs
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
pub mod aead;
|
||||||
|
pub(crate) mod helper;
|
||||||
|
|
@ -8,16 +8,19 @@ description = "Boringssl rustls provider"
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = ["tls12"]
|
||||||
# Use a FIPS-validated version of boringssl.
|
# Use a FIPS-validated version of boringssl.
|
||||||
#fips = ["boring/fips", "boring-sys/fips"]
|
#fips = ["boring/fips", "boring-sys/fips"]
|
||||||
logging = ["log"]
|
logging = ["log"]
|
||||||
|
fips-only = []
|
||||||
|
tls12 = ["rustls/tls12"]
|
||||||
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
aead = {version = "0.5", default_features = false, features = ["alloc"] }
|
aead = {version = "0.5", default_features = false, features = ["alloc"] }
|
||||||
boring = { version = "4.0", default-features = false }
|
boring = { workspace = true }
|
||||||
boring-sys = { version = "4.0", default-features = false }
|
boring-additions = { path = "../boring-additions" }
|
||||||
|
boring-sys = { workspace = true }
|
||||||
foreign-types = "0.5"
|
foreign-types = "0.5"
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
log = { version = "0.4.4", optional = true }
|
log = { version = "0.4.4", optional = true }
|
||||||
|
|
|
||||||
|
|
@ -2,28 +2,37 @@ use std::marker::PhantomData;
|
||||||
|
|
||||||
use aead::{AeadCore, AeadInPlace, Nonce, Tag};
|
use aead::{AeadCore, AeadInPlace, Nonce, Tag};
|
||||||
use boring::error::ErrorStack;
|
use boring::error::ErrorStack;
|
||||||
use rustls::crypto::cipher::{self, make_tls13_aad, Iv};
|
use boring_additions::aead::Algorithm;
|
||||||
|
use rustls::crypto::cipher::{self, make_tls12_aad, make_tls13_aad, Iv};
|
||||||
use rustls::{ConnectionTrafficSecrets, ContentType, ProtocolVersion};
|
use rustls::{ConnectionTrafficSecrets, ContentType, ProtocolVersion};
|
||||||
|
|
||||||
use crate::helper::error_stack_to_aead_error;
|
use crate::helper::error_stack_to_aead_error;
|
||||||
|
|
||||||
use self::aead2::Algorithm;
|
|
||||||
|
|
||||||
pub(crate) mod aead2;
|
|
||||||
pub(crate) mod aes;
|
pub(crate) mod aes;
|
||||||
pub(crate) mod chacha20;
|
pub(crate) mod chacha20;
|
||||||
|
|
||||||
pub(crate) trait BoringCipher {
|
pub(crate) trait BoringCipher {
|
||||||
|
/// Constructs a new instance of this cipher as an AEAD algorithm
|
||||||
fn new() -> Algorithm;
|
fn new() -> Algorithm;
|
||||||
|
/// The key size in bytes
|
||||||
fn key_size() -> usize;
|
fn key_size() -> 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;
|
||||||
|
/// Extract keys
|
||||||
fn extract_keys(key: cipher::AeadKey, iv: cipher::Iv) -> ConnectionTrafficSecrets;
|
fn extract_keys(key: cipher::AeadKey, iv: cipher::Iv) -> ConnectionTrafficSecrets;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait BoringAead: BoringCipher + AeadCore + Send + Sync {}
|
pub(crate) trait BoringAead: BoringCipher + AeadCore + Send + Sync {}
|
||||||
|
|
||||||
pub(crate) struct BoringAeadCrypter<T: BoringAead> {
|
pub(crate) struct BoringAeadCrypter<T: BoringAead> {
|
||||||
crypter: aead2::Crypter,
|
crypter: boring_additions::aead::Crypter,
|
||||||
iv: Iv,
|
iv: Iv,
|
||||||
|
tls_version: ProtocolVersion,
|
||||||
phantom: PhantomData<T>,
|
phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -41,7 +50,14 @@ impl<T: BoringAead> AeadCore for BoringAeadCrypter<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: BoringAead> BoringAeadCrypter<T> {
|
impl<T: BoringAead> BoringAeadCrypter<T> {
|
||||||
pub fn new(iv: Iv, key: &[u8]) -> Result<Self, ErrorStack> {
|
pub fn new(iv: Iv, key: &[u8], tls_version: ProtocolVersion) -> Result<Self, ErrorStack> {
|
||||||
|
assert!(match tls_version {
|
||||||
|
#[cfg(feature = "tls12")]
|
||||||
|
ProtocolVersion::TLSv1_2 => true,
|
||||||
|
ProtocolVersion::TLSv1_3 => true,
|
||||||
|
_ => false,
|
||||||
|
});
|
||||||
|
|
||||||
let cipher = <T as BoringCipher>::new();
|
let cipher = <T as BoringCipher>::new();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
@ -50,8 +66,9 @@ impl<T: BoringAead> BoringAeadCrypter<T> {
|
||||||
);
|
);
|
||||||
|
|
||||||
let crypter = BoringAeadCrypter {
|
let crypter = BoringAeadCrypter {
|
||||||
crypter: aead2::Crypter::new(cipher, key)?,
|
crypter: boring_additions::aead::Crypter::new(cipher, key)?,
|
||||||
iv,
|
iv,
|
||||||
|
tls_version,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
};
|
};
|
||||||
Ok(crypter)
|
Ok(crypter)
|
||||||
|
|
@ -104,6 +121,15 @@ where
|
||||||
|
|
||||||
let nonce = cipher::Nonce::new(&self.iv, seq);
|
let nonce = cipher::Nonce::new(&self.iv, seq);
|
||||||
|
|
||||||
|
match self.tls_version {
|
||||||
|
#[cfg(feature = "tls12")]
|
||||||
|
ProtocolVersion::TLSv1_2 => {
|
||||||
|
let aad = cipher::make_tls12_aad(seq, msg.typ, msg.version, total_len);
|
||||||
|
self.encrypt_in_place(Nonce::<T>::from_slice(&nonce.0), &aad, &mut payload)
|
||||||
|
.map_err(|_| rustls::Error::EncryptError)
|
||||||
|
.map(|_| cipher::OpaqueMessage::new(msg.typ, msg.version, payload))
|
||||||
|
}
|
||||||
|
ProtocolVersion::TLSv1_3 => {
|
||||||
let aad = cipher::make_tls13_aad(total_len);
|
let aad = cipher::make_tls13_aad(total_len);
|
||||||
self.encrypt_in_place(Nonce::<T>::from_slice(&nonce.0), &aad, &mut payload)
|
self.encrypt_in_place(Nonce::<T>::from_slice(&nonce.0), &aad, &mut payload)
|
||||||
.map_err(|_| rustls::Error::EncryptError)
|
.map_err(|_| rustls::Error::EncryptError)
|
||||||
|
|
@ -115,6 +141,14 @@ where
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next version seems to add this
|
||||||
|
// fn encrypted_payload_len(&self, payload_len: usize) -> usize {
|
||||||
|
// payload_len + 1 + self.crypter.max_overhead()
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> cipher::MessageDecrypter for BoringAeadCrypter<T>
|
impl<T> cipher::MessageDecrypter for BoringAeadCrypter<T>
|
||||||
|
|
@ -126,19 +160,27 @@ where
|
||||||
mut m: cipher::OpaqueMessage,
|
mut m: cipher::OpaqueMessage,
|
||||||
seq: u64,
|
seq: u64,
|
||||||
) -> Result<cipher::PlainMessage, rustls::Error> {
|
) -> Result<cipher::PlainMessage, rustls::Error> {
|
||||||
let payload = m.payload_mut();
|
|
||||||
|
|
||||||
// construct nonce
|
// construct nonce
|
||||||
let nonce = cipher::Nonce::new(&self.iv, seq);
|
let nonce = cipher::Nonce::new(&self.iv, seq);
|
||||||
|
|
||||||
// construct the aad
|
// construct the aad and decrypt
|
||||||
let aad = make_tls13_aad(payload.len());
|
match self.tls_version {
|
||||||
|
#[cfg(feature = "tls12")]
|
||||||
// decrypt on clone to ensure this can be done in parallel
|
ProtocolVersion::TLSv1_2 => {
|
||||||
self.decrypt_in_place(Nonce::<T>::from_slice(&nonce.0), &aad, payload)
|
let aad = make_tls12_aad(seq, m.typ, m.version, m.payload().len());
|
||||||
|
self.decrypt_in_place(Nonce::<T>::from_slice(&nonce.0), &aad, m.payload_mut())
|
||||||
|
.map_err(|_| rustls::Error::DecryptError)
|
||||||
|
.map(|_| m.into_plain_message())
|
||||||
|
}
|
||||||
|
ProtocolVersion::TLSv1_3 => {
|
||||||
|
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)
|
.map_err(|_| rustls::Error::DecryptError)
|
||||||
.and_then(|_| m.into_tls13_unpadded_message())
|
.and_then(|_| m.into_tls13_unpadded_message())
|
||||||
}
|
}
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct Aead<T: BoringCipher>(PhantomData<T>);
|
pub(crate) struct Aead<T: BoringCipher>(PhantomData<T>);
|
||||||
|
|
@ -153,13 +195,15 @@ impl<T: BoringCipher> Aead<T> {
|
||||||
impl<T: BoringAead + 'static> cipher::Tls13AeadAlgorithm for Aead<T> {
|
impl<T: BoringAead + 'static> cipher::Tls13AeadAlgorithm for Aead<T> {
|
||||||
fn encrypter(&self, key: cipher::AeadKey, iv: cipher::Iv) -> Box<dyn cipher::MessageEncrypter> {
|
fn encrypter(&self, key: cipher::AeadKey, iv: cipher::Iv) -> Box<dyn cipher::MessageEncrypter> {
|
||||||
Box::new(
|
Box::new(
|
||||||
BoringAeadCrypter::<T>::new(iv, key.as_ref()).expect("failed to create AEAD crypter"),
|
BoringAeadCrypter::<T>::new(iv, key.as_ref(), ProtocolVersion::TLSv1_3)
|
||||||
|
.expect("failed to create AEAD crypter"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decrypter(&self, key: cipher::AeadKey, iv: cipher::Iv) -> Box<dyn cipher::MessageDecrypter> {
|
fn decrypter(&self, key: cipher::AeadKey, iv: cipher::Iv) -> Box<dyn cipher::MessageDecrypter> {
|
||||||
Box::new(
|
Box::new(
|
||||||
BoringAeadCrypter::<T>::new(iv, key.as_ref()).expect("failed to create AEAD crypter"),
|
BoringAeadCrypter::<T>::new(iv, key.as_ref(), ProtocolVersion::TLSv1_3)
|
||||||
|
.expect("failed to create AEAD crypter"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -175,3 +219,45 @@ impl<T: BoringAead + 'static> cipher::Tls13AeadAlgorithm for Aead<T> {
|
||||||
Ok(<T as BoringCipher>::extract_keys(key, iv))
|
Ok(<T as BoringCipher>::extract_keys(key, iv))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "tls12")]
|
||||||
|
impl<T: BoringAead + 'static> cipher::Tls12AeadAlgorithm for Aead<T> {
|
||||||
|
fn encrypter(
|
||||||
|
&self,
|
||||||
|
key: cipher::AeadKey,
|
||||||
|
iv: &[u8],
|
||||||
|
_extra: &[u8],
|
||||||
|
) -> Box<dyn cipher::MessageEncrypter> {
|
||||||
|
Box::new(
|
||||||
|
BoringAeadCrypter::<T>::new(Iv::copy(iv), key.as_ref(), ProtocolVersion::TLSv1_2)
|
||||||
|
.expect("failed to create AEAD crypter"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decrypter(&self, key: cipher::AeadKey, iv: &[u8]) -> Box<dyn cipher::MessageDecrypter> {
|
||||||
|
Box::new(
|
||||||
|
BoringAeadCrypter::<T>::new(Iv::copy(iv), key.as_ref(), ProtocolVersion::TLSv1_2)
|
||||||
|
.expect("failed to create AEAD crypter"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
+ <T as BoringCipher>::explicit_nonce_len(),
|
||||||
|
explicit_nonce_len: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extract_keys(
|
||||||
|
&self,
|
||||||
|
key: cipher::AeadKey,
|
||||||
|
iv: &[u8],
|
||||||
|
_explicit: &[u8],
|
||||||
|
) -> Result<ConnectionTrafficSecrets, cipher::UnsupportedOperationError> {
|
||||||
|
Ok(<T as BoringCipher>::extract_keys(key, Iv::copy(iv)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
|
use super::{BoringAead, BoringCipher};
|
||||||
use aead::consts::{U12, U16};
|
use aead::consts::{U12, U16};
|
||||||
|
use boring_additions::aead::Algorithm;
|
||||||
use rustls::{crypto::cipher, ConnectionTrafficSecrets};
|
use rustls::{crypto::cipher, ConnectionTrafficSecrets};
|
||||||
|
|
||||||
use super::{aead2::Algorithm, BoringAead, BoringCipher};
|
|
||||||
|
|
||||||
pub struct Aes128 {}
|
pub struct Aes128 {}
|
||||||
|
|
||||||
impl BoringAead for Aes128 {}
|
impl BoringAead for Aes128 {}
|
||||||
|
|
@ -21,6 +21,14 @@ impl BoringCipher for Aes128 {
|
||||||
fn extract_keys(key: cipher::AeadKey, iv: cipher::Iv) -> ConnectionTrafficSecrets {
|
fn extract_keys(key: cipher::AeadKey, iv: cipher::Iv) -> ConnectionTrafficSecrets {
|
||||||
ConnectionTrafficSecrets::Aes128Gcm { key, iv }
|
ConnectionTrafficSecrets::Aes128Gcm { key, iv }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fixed_iv_len() -> usize {
|
||||||
|
4
|
||||||
|
}
|
||||||
|
|
||||||
|
fn explicit_nonce_len() -> usize {
|
||||||
|
8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl aead::AeadCore for Aes128 {
|
impl aead::AeadCore for Aes128 {
|
||||||
|
|
@ -47,6 +55,14 @@ impl BoringCipher for Aes256 {
|
||||||
fn extract_keys(key: cipher::AeadKey, iv: cipher::Iv) -> ConnectionTrafficSecrets {
|
fn extract_keys(key: cipher::AeadKey, iv: cipher::Iv) -> ConnectionTrafficSecrets {
|
||||||
ConnectionTrafficSecrets::Aes256Gcm { key, iv }
|
ConnectionTrafficSecrets::Aes256Gcm { key, iv }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fixed_iv_len() -> usize {
|
||||||
|
4
|
||||||
|
}
|
||||||
|
|
||||||
|
fn explicit_nonce_len() -> usize {
|
||||||
|
8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl aead::AeadCore for Aes256 {
|
impl aead::AeadCore for Aes256 {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
|
use super::{BoringAead, BoringCipher};
|
||||||
use aead::{
|
use aead::{
|
||||||
consts::{U12, U16},
|
consts::{U12, U16},
|
||||||
AeadCore,
|
AeadCore,
|
||||||
};
|
};
|
||||||
|
use boring_additions::aead::Algorithm;
|
||||||
use rustls::{crypto::cipher, ConnectionTrafficSecrets};
|
use rustls::{crypto::cipher, ConnectionTrafficSecrets};
|
||||||
|
|
||||||
use super::{aead2::Algorithm, BoringAead, BoringCipher};
|
|
||||||
|
|
||||||
pub struct ChaCha20Poly1305 {}
|
pub struct ChaCha20Poly1305 {}
|
||||||
|
|
||||||
impl BoringAead for ChaCha20Poly1305 {}
|
impl BoringAead for ChaCha20Poly1305 {}
|
||||||
|
|
@ -24,6 +24,14 @@ impl BoringCipher for ChaCha20Poly1305 {
|
||||||
fn extract_keys(key: cipher::AeadKey, iv: cipher::Iv) -> ConnectionTrafficSecrets {
|
fn extract_keys(key: cipher::AeadKey, iv: cipher::Iv) -> ConnectionTrafficSecrets {
|
||||||
ConnectionTrafficSecrets::Chacha20Poly1305 { key, iv }
|
ConnectionTrafficSecrets::Chacha20Poly1305 { key, iv }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fixed_iv_len() -> usize {
|
||||||
|
4
|
||||||
|
}
|
||||||
|
|
||||||
|
fn explicit_nonce_len() -> usize {
|
||||||
|
8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AeadCore for ChaCha20Poly1305 {
|
impl AeadCore for ChaCha20Poly1305 {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use rustls::crypto::hash;
|
use rustls::crypto::hash;
|
||||||
|
|
||||||
pub const SHA256: &dyn hash::Hash = &Hash(boring::nid::Nid::SHA256);
|
pub const SHA256: &dyn hash::Hash = &Hash(boring::nid::Nid::SHA256);
|
||||||
|
pub const SHA384: &dyn hash::Hash = &Hash(boring::nid::Nid::SHA384);
|
||||||
|
|
||||||
pub struct Hash(pub boring::nid::Nid);
|
pub struct Hash(pub boring::nid::Nid);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,13 @@ impl BoringHash for Sha256 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Sha384();
|
||||||
|
impl BoringHash for Sha384 {
|
||||||
|
fn new() -> boring::hash::MessageDigest {
|
||||||
|
boring::hash::MessageDigest::sha384()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Hkdf<T: BoringHash>(PhantomData<T>);
|
pub struct Hkdf<T: BoringHash>(PhantomData<T>);
|
||||||
|
|
||||||
impl<T: BoringHash> Hkdf<T> {
|
impl<T: BoringHash> Hkdf<T> {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use crate::helper::{cvt, cvt_p};
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub const SHA256: &dyn crypto::hmac::Hmac = &BoringHmac(boring::nid::Nid::SHA256);
|
pub const SHA256: &dyn crypto::hmac::Hmac = &BoringHmac(boring::nid::Nid::SHA256);
|
||||||
|
pub const SHA384: &dyn crypto::hmac::Hmac = &BoringHmac(boring::nid::Nid::SHA384);
|
||||||
|
|
||||||
pub struct BoringHmac(pub boring::nid::Nid);
|
pub struct BoringHmac(pub boring::nid::Nid);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ mod hkdf;
|
||||||
mod hmac;
|
mod hmac;
|
||||||
mod kx;
|
mod kx;
|
||||||
mod sign;
|
mod sign;
|
||||||
|
#[cfg(feature = "tls12")]
|
||||||
|
mod tls12;
|
||||||
mod tls13;
|
mod tls13;
|
||||||
mod verify;
|
mod verify;
|
||||||
|
|
||||||
|
|
@ -27,17 +29,23 @@ impl CryptoProvider for Provider {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_cipher_suites(&self) -> &'static [SupportedCipherSuite] {
|
fn default_cipher_suites(&self) -> &'static [SupportedCipherSuite] {
|
||||||
if boring::fips::enabled() {
|
#[cfg(feature = "fips-only")]
|
||||||
ALL_FIPS_SUITES
|
{
|
||||||
} else {
|
ALL_FIPS_CIPHER_SUITES
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "fips-only"))]
|
||||||
|
{
|
||||||
ALL_CIPHER_SUITES
|
ALL_CIPHER_SUITES
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_kx_groups(&self) -> &'static [&'static dyn SupportedKxGroup] {
|
fn default_kx_groups(&self) -> &'static [&'static dyn SupportedKxGroup] {
|
||||||
if boring::fips::enabled() {
|
#[cfg(feature = "fips-only")]
|
||||||
|
{
|
||||||
ALL_FIPS_KX_GROUPS
|
ALL_FIPS_KX_GROUPS
|
||||||
} else {
|
}
|
||||||
|
#[cfg(not(feature = "fips-only"))]
|
||||||
|
{
|
||||||
ALL_KX_GROUPS
|
ALL_KX_GROUPS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -52,22 +60,65 @@ impl CryptoProvider for Provider {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature_verification_algorithms(&self) -> rustls::WebPkiSupportedAlgorithms {
|
fn signature_verification_algorithms(&self) -> rustls::WebPkiSupportedAlgorithms {
|
||||||
|
#[cfg(feature = "fips-only")]
|
||||||
|
{
|
||||||
|
verify::ALL_FIPS_ALGORITHMS
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "fips-only"))]
|
||||||
|
{
|
||||||
verify::ALL_ALGORITHMS
|
verify::ALL_ALGORITHMS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static ALL_FIPS_SUITES: &[SupportedCipherSuite] = &[
|
#[allow(unused)]
|
||||||
|
static ALL_FIPS_CIPHER_SUITES: &[SupportedCipherSuite] = &[
|
||||||
|
SupportedCipherSuite::Tls13(&tls13::AES_256_GCM_SHA384),
|
||||||
SupportedCipherSuite::Tls13(&tls13::AES_128_GCM_SHA256),
|
SupportedCipherSuite::Tls13(&tls13::AES_128_GCM_SHA256),
|
||||||
SupportedCipherSuite::Tls13(&tls13::AES_256_GCM_SHA256),
|
#[cfg(feature = "tls12")]
|
||||||
|
SupportedCipherSuite::Tls12(&tls12::ECDHE_ECDSA_AES256_GCM_SHA384),
|
||||||
|
#[cfg(feature = "tls12")]
|
||||||
|
SupportedCipherSuite::Tls12(&tls12::ECDHE_RSA_AES256_GCM_SHA384),
|
||||||
|
#[cfg(feature = "tls12")]
|
||||||
|
SupportedCipherSuite::Tls12(&tls12::ECDHE_ECDSA_AES128_GCM_SHA256),
|
||||||
|
#[cfg(feature = "tls12")]
|
||||||
|
SupportedCipherSuite::Tls12(&tls12::ECDHE_RSA_AES128_GCM_SHA256),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
static ALL_CIPHER_SUITES: &[SupportedCipherSuite] = &[
|
static ALL_CIPHER_SUITES: &[SupportedCipherSuite] = &[
|
||||||
SupportedCipherSuite::Tls13(&tls13::AES_128_GCM_SHA256),
|
|
||||||
SupportedCipherSuite::Tls13(&tls13::AES_256_GCM_SHA256),
|
|
||||||
SupportedCipherSuite::Tls13(&tls13::CHACHA20_POLY1305_SHA256),
|
SupportedCipherSuite::Tls13(&tls13::CHACHA20_POLY1305_SHA256),
|
||||||
|
SupportedCipherSuite::Tls13(&tls13::AES_256_GCM_SHA384),
|
||||||
|
SupportedCipherSuite::Tls13(&tls13::AES_128_GCM_SHA256),
|
||||||
|
#[cfg(feature = "tls12")]
|
||||||
|
SupportedCipherSuite::Tls12(&tls12::ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256),
|
||||||
|
#[cfg(feature = "tls12")]
|
||||||
|
SupportedCipherSuite::Tls12(&tls12::ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256),
|
||||||
|
#[cfg(feature = "tls12")]
|
||||||
|
SupportedCipherSuite::Tls12(&tls12::ECDHE_ECDSA_AES256_GCM_SHA384),
|
||||||
|
#[cfg(feature = "tls12")]
|
||||||
|
SupportedCipherSuite::Tls12(&tls12::ECDHE_RSA_AES256_GCM_SHA384),
|
||||||
|
#[cfg(feature = "tls12")]
|
||||||
|
SupportedCipherSuite::Tls12(&tls12::ECDHE_ECDSA_AES128_GCM_SHA256),
|
||||||
|
#[cfg(feature = "tls12")]
|
||||||
|
SupportedCipherSuite::Tls12(&tls12::ECDHE_RSA_AES128_GCM_SHA256),
|
||||||
];
|
];
|
||||||
|
|
||||||
pub const ALL_FIPS_KX_GROUPS: &[&dyn SupportedKxGroup] = &[];
|
/// Allowed KX curves for FIPS are recommended
|
||||||
|
/// in [NIST SP 800-186](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-186.pdf)
|
||||||
|
///
|
||||||
|
/// See Sec. 3.1.2 Table 2
|
||||||
|
/// Ordered in decending order of security strength
|
||||||
|
#[allow(unused)]
|
||||||
|
pub const ALL_FIPS_KX_GROUPS: &[&dyn SupportedKxGroup] = &[
|
||||||
|
&kx::Secp521r1 as _, // P-521 in FIPS lingo
|
||||||
|
&kx::X448 as _, // Curve448 in FIPS lingo
|
||||||
|
&kx::Secp384r1 as _, // P-384 in FIPS lingo
|
||||||
|
&kx::X25519 as _, // Curve25519 in FIPS lingo
|
||||||
|
&kx::Secp256r1 as _, // P-256 in FIPS lingo
|
||||||
|
];
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub const ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[
|
pub const ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[
|
||||||
&kx::X25519 as _,
|
&kx::X25519 as _,
|
||||||
&kx::X448 as _,
|
&kx::X448 as _,
|
||||||
|
|
|
||||||
89
boring-rustls-provider/src/tls12.rs
Normal file
89
boring-rustls-provider/src/tls12.rs
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
use rustls::{crypto, SignatureScheme, Tls12CipherSuite};
|
||||||
|
|
||||||
|
use crate::{aead, hash, hmac};
|
||||||
|
|
||||||
|
static ALL_ECDSA_SCHEMES: &[SignatureScheme] = &[
|
||||||
|
SignatureScheme::ECDSA_NISTP256_SHA256,
|
||||||
|
SignatureScheme::ECDSA_NISTP384_SHA384,
|
||||||
|
SignatureScheme::ECDSA_NISTP521_SHA512,
|
||||||
|
SignatureScheme::ED25519,
|
||||||
|
SignatureScheme::ED448,
|
||||||
|
];
|
||||||
|
|
||||||
|
static ALL_RSA_SCHEMES: &[SignatureScheme] = &[
|
||||||
|
SignatureScheme::RSA_PKCS1_SHA256,
|
||||||
|
SignatureScheme::RSA_PKCS1_SHA384,
|
||||||
|
SignatureScheme::RSA_PKCS1_SHA512,
|
||||||
|
SignatureScheme::RSA_PSS_SHA256,
|
||||||
|
SignatureScheme::RSA_PSS_SHA384,
|
||||||
|
SignatureScheme::RSA_PSS_SHA512,
|
||||||
|
];
|
||||||
|
|
||||||
|
const PRF_SHA256: crypto::tls12::PrfUsingHmac<'_> = crypto::tls12::PrfUsingHmac(hmac::SHA256);
|
||||||
|
const PRF_SHA384: crypto::tls12::PrfUsingHmac<'_> = crypto::tls12::PrfUsingHmac(hmac::SHA384);
|
||||||
|
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
aead_alg: &aead::Aead::<aead::aes::Aes128>::DEFAULT,
|
||||||
|
prf_provider: &PRF_SHA256,
|
||||||
|
kx: crypto::KeyExchangeAlgorithm::ECDHE,
|
||||||
|
sign: ALL_ECDSA_SCHEMES,
|
||||||
|
};
|
||||||
|
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
aead_alg: &aead::Aead::<aead::aes::Aes128>::DEFAULT,
|
||||||
|
prf_provider: &PRF_SHA256,
|
||||||
|
kx: crypto::KeyExchangeAlgorithm::ECDHE,
|
||||||
|
sign: ALL_RSA_SCHEMES,
|
||||||
|
};
|
||||||
|
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
aead_alg: &aead::Aead::<aead::aes::Aes256>::DEFAULT,
|
||||||
|
prf_provider: &PRF_SHA384,
|
||||||
|
kx: crypto::KeyExchangeAlgorithm::ECDHE,
|
||||||
|
sign: ALL_ECDSA_SCHEMES,
|
||||||
|
};
|
||||||
|
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
aead_alg: &aead::Aead::<aead::aes::Aes256>::DEFAULT,
|
||||||
|
prf_provider: &PRF_SHA384,
|
||||||
|
kx: crypto::KeyExchangeAlgorithm::ECDHE,
|
||||||
|
sign: ALL_RSA_SCHEMES,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub static ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: Tls12CipherSuite = Tls12CipherSuite {
|
||||||
|
common: rustls::CipherSuiteCommon {
|
||||||
|
suite: rustls::CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||||
|
hash_provider: hash::SHA256,
|
||||||
|
},
|
||||||
|
aead_alg: &aead::Aead::<aead::chacha20::ChaCha20Poly1305>::DEFAULT,
|
||||||
|
prf_provider: &PRF_SHA256,
|
||||||
|
kx: crypto::KeyExchangeAlgorithm::ECDHE,
|
||||||
|
sign: ALL_ECDSA_SCHEMES,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub static ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: Tls12CipherSuite = Tls12CipherSuite {
|
||||||
|
common: rustls::CipherSuiteCommon {
|
||||||
|
suite: rustls::CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||||
|
hash_provider: hash::SHA256,
|
||||||
|
},
|
||||||
|
aead_alg: &aead::Aead::<aead::chacha20::ChaCha20Poly1305>::DEFAULT,
|
||||||
|
prf_provider: &PRF_SHA256,
|
||||||
|
kx: crypto::KeyExchangeAlgorithm::ECDHE,
|
||||||
|
sign: ALL_RSA_SCHEMES,
|
||||||
|
};
|
||||||
|
|
@ -11,12 +11,12 @@ pub static AES_128_GCM_SHA256: Tls13CipherSuite = Tls13CipherSuite {
|
||||||
aead_alg: &aead::Aead::<aead::aes::Aes128>::DEFAULT,
|
aead_alg: &aead::Aead::<aead::aes::Aes128>::DEFAULT,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub static AES_256_GCM_SHA256: Tls13CipherSuite = Tls13CipherSuite {
|
pub static AES_256_GCM_SHA384: Tls13CipherSuite = Tls13CipherSuite {
|
||||||
common: rustls::CipherSuiteCommon {
|
common: rustls::CipherSuiteCommon {
|
||||||
suite: rustls::CipherSuite::TLS13_AES_128_GCM_SHA256,
|
suite: rustls::CipherSuite::TLS13_AES_256_GCM_SHA384,
|
||||||
hash_provider: hash::SHA256,
|
hash_provider: hash::SHA384,
|
||||||
},
|
},
|
||||||
hkdf_provider: &hkdf::Hkdf::<hkdf::Sha256>::DEFAULT,
|
hkdf_provider: &hkdf::Hkdf::<hkdf::Sha384>::DEFAULT,
|
||||||
aead_alg: &aead::Aead::<aead::aes::Aes256>::DEFAULT,
|
aead_alg: &aead::Aead::<aead::aes::Aes256>::DEFAULT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ pub(crate) mod ec;
|
||||||
mod ed;
|
mod ed;
|
||||||
pub(crate) mod rsa;
|
pub(crate) mod rsa;
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub static ALL_ALGORITHMS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms {
|
pub static ALL_ALGORITHMS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms {
|
||||||
all: &[
|
all: &[
|
||||||
&rsa::BoringRsaVerifier::RSA_PKCS1_SHA256,
|
&rsa::BoringRsaVerifier::RSA_PKCS1_SHA256,
|
||||||
|
|
@ -59,3 +60,60 @@ pub static ALL_ALGORITHMS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms
|
||||||
(SignatureScheme::ED448, &[&ed::BoringEdVerifier::ED448]),
|
(SignatureScheme::ED448, &[&ed::BoringEdVerifier::ED448]),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
pub static ALL_FIPS_ALGORITHMS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms {
|
||||||
|
all: &[
|
||||||
|
&rsa::BoringRsaVerifier::RSA_PKCS1_SHA256,
|
||||||
|
&rsa::BoringRsaVerifier::RSA_PKCS1_SHA384,
|
||||||
|
&rsa::BoringRsaVerifier::RSA_PKCS1_SHA512,
|
||||||
|
&rsa::BoringRsaVerifier::RSA_PSS_SHA256,
|
||||||
|
&rsa::BoringRsaVerifier::RSA_PSS_SHA384,
|
||||||
|
&rsa::BoringRsaVerifier::RSA_PSS_SHA512,
|
||||||
|
&ec::BoringEcVerifier::ECDSA_NISTP256_SHA256,
|
||||||
|
&ec::BoringEcVerifier::ECDSA_NISTP384_SHA384,
|
||||||
|
&ec::BoringEcVerifier::ECDSA_NISTP521_SHA512,
|
||||||
|
//&ed::BoringEdVerifier::ED25519, // FIPS 186-5: requires SHA512 but boring doesn't want us to set a digest, correct?
|
||||||
|
//&ed::BoringEdVerifier::ED448, // FIPS 186-5: requires SHAKE256 but boring doesn't want us to set a digest, correct?
|
||||||
|
],
|
||||||
|
mapping: &[
|
||||||
|
(
|
||||||
|
SignatureScheme::RSA_PKCS1_SHA256,
|
||||||
|
&[&rsa::BoringRsaVerifier::RSA_PKCS1_SHA256],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
SignatureScheme::RSA_PKCS1_SHA384,
|
||||||
|
&[&rsa::BoringRsaVerifier::RSA_PKCS1_SHA384],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
SignatureScheme::RSA_PKCS1_SHA512,
|
||||||
|
&[&rsa::BoringRsaVerifier::RSA_PKCS1_SHA512],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
SignatureScheme::RSA_PSS_SHA256,
|
||||||
|
&[&rsa::BoringRsaVerifier::RSA_PSS_SHA256],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
SignatureScheme::RSA_PSS_SHA384,
|
||||||
|
&[&rsa::BoringRsaVerifier::RSA_PSS_SHA384],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
SignatureScheme::RSA_PSS_SHA512,
|
||||||
|
&[&rsa::BoringRsaVerifier::RSA_PSS_SHA512],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
SignatureScheme::ECDSA_NISTP256_SHA256,
|
||||||
|
&[&ec::BoringEcVerifier::ECDSA_NISTP256_SHA256],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
SignatureScheme::ECDSA_NISTP384_SHA384,
|
||||||
|
&[&ec::BoringEcVerifier::ECDSA_NISTP384_SHA384],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
SignatureScheme::ECDSA_NISTP521_SHA512,
|
||||||
|
&[&ec::BoringEcVerifier::ECDSA_NISTP521_SHA512],
|
||||||
|
),
|
||||||
|
// (SignatureScheme::ED25519, &[&ed::BoringEdVerifier::ED25519]),
|
||||||
|
// (SignatureScheme::ED448, &[&ed::BoringEdVerifier::ED448]),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue