Drop X448, P-521, FFDHE2048 to match boring's default group list
This commit is contained in:
parent
fafbf296b1
commit
c71d5bbfd8
6 changed files with 57 additions and 244 deletions
16
Readme.md
16
Readme.md
|
|
@ -42,23 +42,13 @@ ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
|
||||||
|
|
||||||
### Key Exchange Groups
|
### Key Exchange Groups
|
||||||
|
|
||||||
Post-quantum hybrid (requires `mlkem` feature, TLS 1.3 only):
|
Matches boring's default supported group list:
|
||||||
```
|
|
||||||
X25519MLKEM768 (0x11ec)
|
|
||||||
```
|
|
||||||
|
|
||||||
ECDHE:
|
|
||||||
```
|
```
|
||||||
|
X25519MLKEM768 (0x11ec, requires mlkem feature, TLS 1.3 only)
|
||||||
X25519
|
X25519
|
||||||
X448
|
|
||||||
secp256r1 (P-256)
|
secp256r1 (P-256)
|
||||||
secp384r1 (P-384)
|
secp384r1 (P-384)
|
||||||
secp521r1 (P-521)
|
|
||||||
```
|
|
||||||
|
|
||||||
FFDHE:
|
|
||||||
```
|
|
||||||
ffdhe2048
|
|
||||||
```
|
```
|
||||||
|
|
||||||
When `mlkem` is enabled, X25519MLKEM768 is the preferred (first) group in both
|
When `mlkem` is enabled, X25519MLKEM768 is the preferred (first) group in both
|
||||||
|
|
@ -108,7 +98,7 @@ boring's `fips202205` compliance policy:
|
||||||
|
|
||||||
- **Cipher suites**: AES-GCM only (no ChaCha20-Poly1305).
|
- **Cipher suites**: AES-GCM only (no ChaCha20-Poly1305).
|
||||||
- **Key exchange groups**: X25519MLKEM768 (preferred), P-256, and P-384 only
|
- **Key exchange groups**: X25519MLKEM768 (preferred), P-256, and P-384 only
|
||||||
(no standalone X25519, X448, P-521, or FFDHE).
|
(no standalone X25519).
|
||||||
- **Signature algorithms**: RSA PKCS#1 / PSS and ECDSA with P-256 or P-384 only
|
- **Signature algorithms**: RSA PKCS#1 / PSS and ECDSA with P-256 or P-384 only
|
||||||
(no P-521, Ed25519, or Ed448).
|
(no P-521, Ed25519, or Ed448).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,123 +0,0 @@
|
||||||
use boring::{dh::Dh, error::ErrorStack, pkey::Private};
|
|
||||||
use foreign_types::ForeignType;
|
|
||||||
use rustls::crypto;
|
|
||||||
|
|
||||||
use crate::helper::{cvt, cvt_p, log_and_map};
|
|
||||||
|
|
||||||
use super::DhKeyType;
|
|
||||||
|
|
||||||
/// This type can be used to perform a
|
|
||||||
/// Diffie-Hellman key exchange.
|
|
||||||
pub struct KeyExchange {
|
|
||||||
dh: Dh<Private>,
|
|
||||||
pub_bytes: Vec<u8>,
|
|
||||||
key_type: DhKeyType,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl KeyExchange {
|
|
||||||
// Generate a new KeyExchange with a random FFDHE_2048 private key
|
|
||||||
pub fn generate_ffdhe_2048() -> Result<Self, ErrorStack> {
|
|
||||||
let mut me = Self {
|
|
||||||
dh: unsafe { Dh::from_ptr(cvt_p(boring_sys::DH_get_rfc7919_2048())?) },
|
|
||||||
pub_bytes: Vec::new(),
|
|
||||||
key_type: DhKeyType::FFDHE2048,
|
|
||||||
};
|
|
||||||
|
|
||||||
me.pub_bytes = unsafe {
|
|
||||||
// generate a new key pair
|
|
||||||
cvt(boring_sys::DH_generate_key(me.dh.as_ptr()))?;
|
|
||||||
|
|
||||||
// get a reference to the pub key
|
|
||||||
let pubkey = boring_sys::DH_get0_pub_key(me.dh.as_ptr());
|
|
||||||
|
|
||||||
// figure out how many bytes we need, round up to the next full byte
|
|
||||||
let size = (boring_sys::BN_num_bits(pubkey) as usize).div_ceil(8);
|
|
||||||
|
|
||||||
// alloc a vector with enough capacity
|
|
||||||
let mut v = Vec::with_capacity(size);
|
|
||||||
|
|
||||||
// convert to binary representation
|
|
||||||
let after_size = boring_sys::BN_bn2bin(pubkey, v.as_mut_ptr());
|
|
||||||
// size should be what we calculated before
|
|
||||||
assert_eq!(size, after_size);
|
|
||||||
|
|
||||||
// ensure those bytes are accessible in the vec
|
|
||||||
v.set_len(size);
|
|
||||||
v
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(me)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generate a shared secret with the other's raw public key
|
|
||||||
fn diffie_hellman(&self, raw_public_key: &[u8]) -> Result<Vec<u8>, ErrorStack> {
|
|
||||||
let peer = boring::bn::BigNum::from_slice(raw_public_key)?;
|
|
||||||
|
|
||||||
let secret_len = unsafe { cvt(boring_sys::DH_size(self.dh.as_ptr()))? } as usize;
|
|
||||||
let mut secret = vec![0u8; secret_len];
|
|
||||||
|
|
||||||
let secret_len = unsafe {
|
|
||||||
cvt(boring_sys::DH_compute_key_padded(
|
|
||||||
secret.as_mut_ptr(),
|
|
||||||
peer.as_ptr(),
|
|
||||||
self.dh.as_ptr(),
|
|
||||||
))?
|
|
||||||
} as usize;
|
|
||||||
|
|
||||||
secret.truncate(secret_len);
|
|
||||||
Ok(secret)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl crypto::ActiveKeyExchange for KeyExchange {
|
|
||||||
fn complete(
|
|
||||||
self: Box<Self>,
|
|
||||||
peer_pub_key: &[u8],
|
|
||||||
) -> Result<crypto::SharedSecret, rustls::Error> {
|
|
||||||
let expected_len = self.pub_bytes.len();
|
|
||||||
|
|
||||||
if peer_pub_key.len() != expected_len {
|
|
||||||
return Err(rustls::Error::from(rustls::PeerMisbehaved::InvalidKeyShare));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(crypto::SharedSecret::from(
|
|
||||||
self.diffie_hellman(peer_pub_key)
|
|
||||||
.map_err(|e| {
|
|
||||||
log_and_map(
|
|
||||||
"dh::KeyExchange::diffie_hellman",
|
|
||||||
e,
|
|
||||||
rustls::PeerMisbehaved::InvalidKeyShare,
|
|
||||||
)
|
|
||||||
})?
|
|
||||||
.as_ref(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pub_key(&self) -> &[u8] {
|
|
||||||
self.pub_bytes.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn group(&self) -> rustls::NamedGroup {
|
|
||||||
match self.key_type {
|
|
||||||
DhKeyType::FFDHE2048 => rustls::NamedGroup::FFDHE2048,
|
|
||||||
_ => unimplemented!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use crate::kx::dh::KeyExchange;
|
|
||||||
use rustls::crypto::ActiveKeyExchange;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_derive_dh() {
|
|
||||||
let alice = KeyExchange::generate_ffdhe_2048().unwrap();
|
|
||||||
let bob = KeyExchange::generate_ffdhe_2048().unwrap();
|
|
||||||
|
|
||||||
let shared_secret1 = alice.diffie_hellman(bob.pub_key()).unwrap();
|
|
||||||
let shared_secret2 = bob.diffie_hellman(alice.pub_key()).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(shared_secret1, shared_secret2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
use std::{
|
#[cfg(not(feature = "fips"))]
|
||||||
mem::MaybeUninit,
|
use std::{mem::MaybeUninit, ptr};
|
||||||
ptr::{self},
|
|
||||||
};
|
|
||||||
|
|
||||||
use boring::{
|
use boring::{
|
||||||
ec::{EcGroup, EcKey},
|
ec::{EcGroup, EcKey},
|
||||||
|
|
@ -9,12 +7,16 @@ use boring::{
|
||||||
nid::Nid,
|
nid::Nid,
|
||||||
pkey::{PKey, PKeyRef, Private},
|
pkey::{PKey, PKeyRef, Private},
|
||||||
};
|
};
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
use boring_additions::evp::EvpPkeyCtx;
|
use boring_additions::evp::EvpPkeyCtx;
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
use foreign_types::ForeignType;
|
use foreign_types::ForeignType;
|
||||||
use rustls::crypto;
|
use rustls::crypto;
|
||||||
use spki::der::Decode;
|
use spki::der::Decode;
|
||||||
|
|
||||||
use crate::helper::{cvt, cvt_p, log_and_map};
|
use crate::helper::log_and_map;
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
|
use crate::helper::{cvt, cvt_p};
|
||||||
|
|
||||||
use super::DhKeyType;
|
use super::DhKeyType;
|
||||||
|
|
||||||
|
|
@ -30,16 +32,11 @@ pub struct KeyExchange {
|
||||||
impl KeyExchange {
|
impl KeyExchange {
|
||||||
/// Creates a new `KeyExchange` using a random
|
/// Creates a new `KeyExchange` using a random
|
||||||
/// private key for the `X25519` Edwards curve
|
/// private key for the `X25519` Edwards curve
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
pub fn with_x25519() -> Result<Self, ErrorStack> {
|
pub fn with_x25519() -> Result<Self, ErrorStack> {
|
||||||
Self::ed_from_curve(Nid::from_raw(boring_sys::NID_X25519))
|
Self::ed_from_curve(Nid::from_raw(boring_sys::NID_X25519))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new `KeyExchange` using a random
|
|
||||||
/// private key for the `X448` Edwards curve
|
|
||||||
pub fn with_x448() -> Result<Self, ErrorStack> {
|
|
||||||
Self::ed_from_curve(Nid::from_raw(boring_sys::NID_X448))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new `KeyExchange` using a random
|
/// Creates a new `KeyExchange` using a random
|
||||||
/// private key for `sepc256r1` curve
|
/// private key for `sepc256r1` curve
|
||||||
/// Also known as `X9_62_PRIME256V1`
|
/// Also known as `X9_62_PRIME256V1`
|
||||||
|
|
@ -53,12 +50,6 @@ impl KeyExchange {
|
||||||
Self::ec_from_curve(Nid::SECP384R1)
|
Self::ec_from_curve(Nid::SECP384R1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new `KeyExchange` using a random
|
|
||||||
/// private key for `sep521r1` curve
|
|
||||||
pub fn with_secp521r1() -> Result<Self, ErrorStack> {
|
|
||||||
Self::ec_from_curve(Nid::SECP521R1)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Allows getting a new `KeyExchange` using Eliptic Curves
|
/// Allows getting a new `KeyExchange` using Eliptic Curves
|
||||||
/// on the specified curve
|
/// on the specified curve
|
||||||
fn ec_from_curve(nid: Nid) -> Result<Self, ErrorStack> {
|
fn ec_from_curve(nid: Nid) -> Result<Self, ErrorStack> {
|
||||||
|
|
@ -76,6 +67,7 @@ impl KeyExchange {
|
||||||
|
|
||||||
/// Allows getting a new `KeyExchange` using Edwards Curves
|
/// Allows getting a new `KeyExchange` using Edwards Curves
|
||||||
/// on the specified curve
|
/// on the specified curve
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
fn ed_from_curve(nid: Nid) -> Result<Self, ErrorStack> {
|
fn ed_from_curve(nid: Nid) -> Result<Self, ErrorStack> {
|
||||||
let pkey_ctx = unsafe {
|
let pkey_ctx = unsafe {
|
||||||
EvpPkeyCtx::from_ptr(cvt_p(boring_sys::EVP_PKEY_CTX_new_id(
|
EvpPkeyCtx::from_ptr(cvt_p(boring_sys::EVP_PKEY_CTX_new_id(
|
||||||
|
|
@ -129,8 +121,8 @@ impl KeyExchange {
|
||||||
|
|
||||||
crate::verify::ec::create_public_key(group, point.as_ref())?
|
crate::verify::ec::create_public_key(group, point.as_ref())?
|
||||||
}
|
}
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
DhKeyType::ED(nid) => crate::verify::ed::public_key(peer_pub_key, Nid::from_raw(*nid))?,
|
DhKeyType::ED(nid) => crate::verify::ed::public_key(peer_pub_key, Nid::from_raw(*nid))?,
|
||||||
_ => unimplemented!(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut deriver = boring::derive::Deriver::new(&self.own_key)?;
|
let mut deriver = boring::derive::Deriver::new(&self.own_key)?;
|
||||||
|
|
@ -163,12 +155,11 @@ impl crypto::ActiveKeyExchange for KeyExchange {
|
||||||
|
|
||||||
fn group(&self) -> rustls::NamedGroup {
|
fn group(&self) -> rustls::NamedGroup {
|
||||||
match self.key_type {
|
match self.key_type {
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
DhKeyType::ED(boring_sys::NID_X25519) => rustls::NamedGroup::X25519,
|
DhKeyType::ED(boring_sys::NID_X25519) => rustls::NamedGroup::X25519,
|
||||||
DhKeyType::ED(boring_sys::NID_X448) => rustls::NamedGroup::X448,
|
|
||||||
DhKeyType::EC((_, boring_sys::NID_X9_62_prime256v1)) => rustls::NamedGroup::secp256r1,
|
DhKeyType::EC((_, boring_sys::NID_X9_62_prime256v1)) => rustls::NamedGroup::secp256r1,
|
||||||
DhKeyType::EC((_, boring_sys::NID_secp384r1)) => rustls::NamedGroup::secp384r1,
|
DhKeyType::EC((_, boring_sys::NID_secp384r1)) => rustls::NamedGroup::secp384r1,
|
||||||
DhKeyType::EC((_, boring_sys::NID_secp521r1)) => rustls::NamedGroup::secp521r1,
|
_ => unreachable!("unsupported key type"),
|
||||||
_ => unimplemented!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -190,6 +181,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
fn test_derive_ed() {
|
fn test_derive_ed() {
|
||||||
let alice = Box::new(KeyExchange::with_x25519().unwrap());
|
let alice = Box::new(KeyExchange::with_x25519().unwrap());
|
||||||
let bob = KeyExchange::with_x25519().unwrap();
|
let bob = KeyExchange::with_x25519().unwrap();
|
||||||
|
|
|
||||||
|
|
@ -2,23 +2,26 @@ use rustls::crypto::{self, ActiveKeyExchange};
|
||||||
|
|
||||||
use crate::helper::log_and_map;
|
use crate::helper::log_and_map;
|
||||||
|
|
||||||
mod dh;
|
|
||||||
mod ex;
|
mod ex;
|
||||||
#[cfg(feature = "mlkem")]
|
#[cfg(feature = "mlkem")]
|
||||||
mod pq;
|
mod pq;
|
||||||
#[cfg(feature = "mlkem")]
|
#[cfg(feature = "mlkem")]
|
||||||
pub(crate) use pq::X25519MlKem768;
|
pub(crate) use pq::X25519MlKem768;
|
||||||
|
|
||||||
|
/// Key type discriminant used by [`ex::KeyExchange`] to select the
|
||||||
|
/// appropriate peer key parsing and DH derivation logic.
|
||||||
enum DhKeyType {
|
enum DhKeyType {
|
||||||
EC((boring::ec::EcGroup, i32)),
|
EC((boring::ec::EcGroup, i32)),
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
ED(i32),
|
ED(i32),
|
||||||
FFDHE2048,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A X25519-based key exchange
|
/// A X25519-based key exchange
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct X25519;
|
pub struct X25519;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
impl crypto::SupportedKxGroup for X25519 {
|
impl crypto::SupportedKxGroup for X25519 {
|
||||||
fn start(&self) -> Result<Box<dyn ActiveKeyExchange + 'static>, rustls::Error> {
|
fn start(&self) -> Result<Box<dyn ActiveKeyExchange + 'static>, rustls::Error> {
|
||||||
Ok(Box::new(ex::KeyExchange::with_x25519().map_err(|e| {
|
Ok(Box::new(ex::KeyExchange::with_x25519().map_err(|e| {
|
||||||
|
|
@ -31,22 +34,6 @@ impl crypto::SupportedKxGroup for X25519 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A X448-based key exchange
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct X448;
|
|
||||||
|
|
||||||
impl crypto::SupportedKxGroup for X448 {
|
|
||||||
fn start(&self) -> Result<Box<dyn ActiveKeyExchange + 'static>, rustls::Error> {
|
|
||||||
Ok(Box::new(ex::KeyExchange::with_x448().map_err(|e| {
|
|
||||||
log_and_map("X448.start", e, crypto::GetRandomFailed)
|
|
||||||
})?))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn name(&self) -> rustls::NamedGroup {
|
|
||||||
rustls::NamedGroup::X448
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A secp256r1-based key exchange
|
/// A secp256r1-based key exchange
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Secp256r1;
|
pub struct Secp256r1;
|
||||||
|
|
@ -78,35 +65,3 @@ impl crypto::SupportedKxGroup for Secp384r1 {
|
||||||
rustls::NamedGroup::secp384r1
|
rustls::NamedGroup::secp384r1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A secp521r1-based key exchange
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Secp521r1;
|
|
||||||
|
|
||||||
impl crypto::SupportedKxGroup for Secp521r1 {
|
|
||||||
fn start(&self) -> Result<Box<dyn ActiveKeyExchange + 'static>, rustls::Error> {
|
|
||||||
Ok(Box::new(ex::KeyExchange::with_secp521r1().map_err(
|
|
||||||
|e| log_and_map("Secp521r1.start", e, crypto::GetRandomFailed),
|
|
||||||
)?))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn name(&self) -> rustls::NamedGroup {
|
|
||||||
rustls::NamedGroup::secp521r1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A ffedhe2048-based key exchange
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct FfDHe2048;
|
|
||||||
|
|
||||||
impl crypto::SupportedKxGroup for FfDHe2048 {
|
|
||||||
fn start(&self) -> Result<Box<dyn ActiveKeyExchange + 'static>, rustls::Error> {
|
|
||||||
Ok(Box::new(dh::KeyExchange::generate_ffdhe_2048().map_err(
|
|
||||||
|e| log_and_map("FfDHe2048.start", e, crypto::GetRandomFailed),
|
|
||||||
)?))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn name(&self) -> rustls::NamedGroup {
|
|
||||||
rustls::NamedGroup::FFDHE2048
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ impl rustls::crypto::KeyProvider for Provider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[cfg(feature = "fips")]
|
||||||
static ALL_FIPS_CIPHER_SUITES: &[SupportedCipherSuite] = &[
|
static ALL_FIPS_CIPHER_SUITES: &[SupportedCipherSuite] = &[
|
||||||
SupportedCipherSuite::Tls13(&tls13::AES_256_GCM_SHA384),
|
SupportedCipherSuite::Tls13(&tls13::AES_256_GCM_SHA384),
|
||||||
SupportedCipherSuite::Tls13(&tls13::AES_128_GCM_SHA256),
|
SupportedCipherSuite::Tls13(&tls13::AES_128_GCM_SHA256),
|
||||||
|
|
@ -80,7 +80,7 @@ static ALL_FIPS_CIPHER_SUITES: &[SupportedCipherSuite] = &[
|
||||||
SupportedCipherSuite::Tls12(&tls12::ECDHE_RSA_AES128_GCM_SHA256),
|
SupportedCipherSuite::Tls12(&tls12::ECDHE_RSA_AES128_GCM_SHA256),
|
||||||
];
|
];
|
||||||
|
|
||||||
#[allow(unused)]
|
#[cfg(not(feature = "fips"))]
|
||||||
static ALL_CIPHER_SUITES: &[SupportedCipherSuite] = &[
|
static ALL_CIPHER_SUITES: &[SupportedCipherSuite] = &[
|
||||||
SupportedCipherSuite::Tls13(&tls13::CHACHA20_POLY1305_SHA256),
|
SupportedCipherSuite::Tls13(&tls13::CHACHA20_POLY1305_SHA256),
|
||||||
SupportedCipherSuite::Tls13(&tls13::AES_256_GCM_SHA384),
|
SupportedCipherSuite::Tls13(&tls13::AES_256_GCM_SHA384),
|
||||||
|
|
@ -102,47 +102,28 @@ static ALL_CIPHER_SUITES: &[SupportedCipherSuite] = &[
|
||||||
/// Allowed KX groups for FIPS per [SP 800-52r2](https://doi.org/10.6028/NIST.SP.800-52r2),
|
/// Allowed KX groups for FIPS per [SP 800-52r2](https://doi.org/10.6028/NIST.SP.800-52r2),
|
||||||
/// aligned with boring's `fips202205` compliance policy.
|
/// aligned with boring's `fips202205` compliance policy.
|
||||||
///
|
///
|
||||||
/// X25519MLKEM768 is preferred when the `mlkem` feature is enabled.
|
/// The `fips` feature implies `mlkem`, so X25519MLKEM768 is always
|
||||||
/// The `fips` feature implies `mlkem`, so the PQ hybrid is always
|
/// available and preferred in FIPS mode.
|
||||||
/// available in FIPS mode.
|
#[cfg(feature = "fips")]
|
||||||
#[cfg(feature = "mlkem")]
|
|
||||||
#[allow(unused)]
|
|
||||||
static ALL_FIPS_KX_GROUPS: &[&dyn SupportedKxGroup] = &[
|
static ALL_FIPS_KX_GROUPS: &[&dyn SupportedKxGroup] = &[
|
||||||
&kx::X25519MlKem768 as _, // PQ hybrid preferred
|
&kx::X25519MlKem768 as _, // PQ hybrid preferred
|
||||||
&kx::Secp256r1 as _, // P-256
|
&kx::Secp256r1 as _, // P-256
|
||||||
&kx::Secp384r1 as _, // P-384
|
&kx::Secp384r1 as _, // P-384
|
||||||
];
|
];
|
||||||
|
|
||||||
/// See [`ALL_FIPS_KX_GROUPS`] (mlkem variant).
|
|
||||||
#[cfg(not(feature = "mlkem"))]
|
|
||||||
#[allow(unused)]
|
|
||||||
static ALL_FIPS_KX_GROUPS: &[&dyn SupportedKxGroup] = &[
|
|
||||||
&kx::Secp256r1 as _, // P-256
|
|
||||||
&kx::Secp384r1 as _, // P-384
|
|
||||||
];
|
|
||||||
|
|
||||||
/// All supported KX groups, ordered by preference.
|
/// All supported KX groups, ordered by preference.
|
||||||
/// Matches boring's default group preference order.
|
///
|
||||||
#[cfg(feature = "mlkem")]
|
/// Matches boring's default supported group list exactly:
|
||||||
#[allow(unused)]
|
/// X25519MLKEM768 (when mlkem enabled), X25519, P-256, P-384.
|
||||||
|
#[cfg(all(not(feature = "fips"), feature = "mlkem"))]
|
||||||
static ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[
|
static ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[
|
||||||
&kx::X25519MlKem768 as _, // PQ hybrid preferred
|
&kx::X25519MlKem768 as _, // PQ hybrid preferred
|
||||||
&kx::X25519 as _,
|
&kx::X25519 as _,
|
||||||
&kx::X448 as _,
|
|
||||||
&kx::Secp256r1 as _,
|
&kx::Secp256r1 as _,
|
||||||
&kx::Secp384r1 as _,
|
&kx::Secp384r1 as _,
|
||||||
&kx::Secp521r1 as _,
|
|
||||||
&kx::FfDHe2048 as _,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
/// See [`ALL_KX_GROUPS`] (mlkem variant).
|
/// See [`ALL_KX_GROUPS`] (mlkem variant).
|
||||||
#[cfg(not(feature = "mlkem"))]
|
#[cfg(not(any(feature = "fips", feature = "mlkem")))]
|
||||||
#[allow(unused)]
|
static ALL_KX_GROUPS: &[&dyn SupportedKxGroup] =
|
||||||
static ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[
|
&[&kx::X25519 as _, &kx::Secp256r1 as _, &kx::Secp384r1 as _];
|
||||||
&kx::X25519 as _,
|
|
||||||
&kx::Secp256r1 as _,
|
|
||||||
&kx::Secp384r1 as _,
|
|
||||||
&kx::Secp521r1 as _,
|
|
||||||
&kx::X448 as _,
|
|
||||||
&kx::FfDHe2048 as _,
|
|
||||||
];
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,13 @@ async fn test_tls13_crypto() {
|
||||||
let root_store = pki.client_root_store();
|
let root_store = pki.client_root_store();
|
||||||
let server_config = pki.server_config();
|
let server_config = pki.server_config();
|
||||||
|
|
||||||
let ciphers = [
|
#[cfg(feature = "fips")]
|
||||||
|
let ciphers = vec![
|
||||||
|
SupportedCipherSuite::Tls13(&tls13::AES_128_GCM_SHA256),
|
||||||
|
SupportedCipherSuite::Tls13(&tls13::AES_256_GCM_SHA384),
|
||||||
|
];
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
|
let ciphers = vec![
|
||||||
SupportedCipherSuite::Tls13(&tls13::AES_128_GCM_SHA256),
|
SupportedCipherSuite::Tls13(&tls13::AES_128_GCM_SHA256),
|
||||||
SupportedCipherSuite::Tls13(&tls13::AES_256_GCM_SHA384),
|
SupportedCipherSuite::Tls13(&tls13::AES_256_GCM_SHA384),
|
||||||
SupportedCipherSuite::Tls13(&tls13::CHACHA20_POLY1305_SHA256),
|
SupportedCipherSuite::Tls13(&tls13::CHACHA20_POLY1305_SHA256),
|
||||||
|
|
@ -324,12 +330,12 @@ fn non_fips_provider_includes_pq_group() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
groups[1],
|
groups[1],
|
||||||
NamedGroup::X25519,
|
NamedGroup::X25519,
|
||||||
"X25519 should remain the first classical fallback"
|
"X25519 should be the first classical fallback"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
groups[2],
|
groups[2],
|
||||||
NamedGroup::X448,
|
NamedGroup::secp256r1,
|
||||||
"X448 should remain ahead of NIST P-curves in non-FIPS mode"
|
"P-256 should follow X25519, matching boring's default order"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -341,7 +347,13 @@ async fn test_tls12_ec_crypto() {
|
||||||
let root_store = pki.client_root_store();
|
let root_store = pki.client_root_store();
|
||||||
let server_config = pki.server_config();
|
let server_config = pki.server_config();
|
||||||
|
|
||||||
let ciphers = [
|
#[cfg(feature = "fips")]
|
||||||
|
let ciphers = vec![
|
||||||
|
SupportedCipherSuite::Tls12(&tls12::ECDHE_ECDSA_AES128_GCM_SHA256),
|
||||||
|
SupportedCipherSuite::Tls12(&tls12::ECDHE_ECDSA_AES256_GCM_SHA384),
|
||||||
|
];
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
|
let ciphers = vec![
|
||||||
SupportedCipherSuite::Tls12(&tls12::ECDHE_ECDSA_AES128_GCM_SHA256),
|
SupportedCipherSuite::Tls12(&tls12::ECDHE_ECDSA_AES128_GCM_SHA256),
|
||||||
SupportedCipherSuite::Tls12(&tls12::ECDHE_ECDSA_AES256_GCM_SHA384),
|
SupportedCipherSuite::Tls12(&tls12::ECDHE_ECDSA_AES256_GCM_SHA384),
|
||||||
SupportedCipherSuite::Tls12(&tls12::ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256),
|
SupportedCipherSuite::Tls12(&tls12::ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256),
|
||||||
|
|
@ -368,7 +380,13 @@ async fn test_tls12_rsa_crypto() {
|
||||||
let root_store = pki.client_root_store();
|
let root_store = pki.client_root_store();
|
||||||
let server_config = pki.server_config();
|
let server_config = pki.server_config();
|
||||||
|
|
||||||
let ciphers = [
|
#[cfg(feature = "fips")]
|
||||||
|
let ciphers = vec![
|
||||||
|
SupportedCipherSuite::Tls12(&tls12::ECDHE_RSA_AES128_GCM_SHA256),
|
||||||
|
SupportedCipherSuite::Tls12(&tls12::ECDHE_RSA_AES256_GCM_SHA384),
|
||||||
|
];
|
||||||
|
#[cfg(not(feature = "fips"))]
|
||||||
|
let ciphers = vec![
|
||||||
SupportedCipherSuite::Tls12(&tls12::ECDHE_RSA_AES128_GCM_SHA256),
|
SupportedCipherSuite::Tls12(&tls12::ECDHE_RSA_AES128_GCM_SHA256),
|
||||||
SupportedCipherSuite::Tls12(&tls12::ECDHE_RSA_AES256_GCM_SHA384),
|
SupportedCipherSuite::Tls12(&tls12::ECDHE_RSA_AES256_GCM_SHA384),
|
||||||
SupportedCipherSuite::Tls12(&tls12::ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256),
|
SupportedCipherSuite::Tls12(&tls12::ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue