Skip to content
Open
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 @@ -12,7 +12,7 @@ readme = "README.md"
[dependencies]
foreign-types = "0.3.1"
once_cell = "1.8.0"
openssl = "0.10.68"
openssl = "0.10.79"
openssl-sys = "0.9.104"
rustls = { version = "0.23.20", default-features = false }
zeroize = "1.8.1"
Expand Down
16 changes: 5 additions & 11 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@

use std::env;

const OPENSSL_NO_CHACHA: &str = "OPENSSL_NO_CHACHA";

fn main() {
println!("cargo:rustc-check-cfg=cfg(chacha)");
println!("cargo:rustc-check-cfg=cfg(fips_module)");
println!("cargo:rustc-check-cfg=cfg(ossl300)");
println!("cargo:rustc-check-cfg=cfg(ossl320)");
println!("cargo:rustc-check-cfg=cfg(ossl350)");
// Determine whether to work around https://github.com/openssl/openssl/issues/23448
Expand All @@ -23,6 +21,10 @@ fn main() {
println!("cargo:rustc-cfg=fips_module");
}

if version >= 0x3_00_00_00_0 {
println!("cargo:rustc-cfg=ossl300");
}

if version >= 0x3_02_00_00_0 {
println!("cargo:rustc-cfg=ossl320");
}
Expand All @@ -31,12 +33,4 @@ fn main() {
println!("cargo:rustc-cfg=ossl350");
}
}

// Enable the `chacha` cfg if the `OPENSSL_NO_CHACHA` OpenSSL config is not set.
if std::env::var("DEP_OPENSSL_CONF")
.map(|conf_string| !conf_string.split(',').any(|conf| conf == OPENSSL_NO_CHACHA))
.unwrap_or(true)
{
println!("cargo:rustc-cfg=chacha");
}
}
25 changes: 21 additions & 4 deletions src/aead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use rustls::crypto::cipher::NONCE_LEN;
pub(crate) enum Algorithm {
Aes128Gcm,
Aes256Gcm,
#[cfg(all(chacha, not(feature = "fips")))]
ChaCha20Poly1305,
}

Expand All @@ -19,7 +18,6 @@ impl Algorithm {
match self {
Self::Aes128Gcm => Cipher::aes_128_gcm(),
Self::Aes256Gcm => Cipher::aes_256_gcm(),
#[cfg(all(chacha, not(feature = "fips")))]
Self::ChaCha20Poly1305 => Cipher::chacha20_poly1305(),
}
}
Expand All @@ -28,6 +26,18 @@ impl Algorithm {
self.openssl_cipher().key_length()
}

/// Returns `true` when OpenSSL can initialize this AEAD at runtime.
pub(crate) fn is_available(self) -> bool {
let key = vec![0u8; self.key_size()];
let nonce = [0u8; NONCE_LEN];

CipherCtx::new()
.and_then(|mut ctx| {
ctx.encrypt_init(Some(self.openssl_cipher()), Some(&key), Some(&nonce))
})
.is_ok()
}

/// Encrypts data in place and returns the tag.
pub(crate) fn encrypt_in_place(
self,
Expand Down Expand Up @@ -95,7 +105,6 @@ mod test {
super::Algorithm::Aes128Gcm | super::Algorithm::Aes256Gcm => {
wycheproof::aead::TestName::AesGcm
}
#[cfg(all(chacha, not(feature = "fips")))]
super::Algorithm::ChaCha20Poly1305 => wycheproof::aead::TestName::ChaCha20Poly1305,
};
let test_set = wycheproof::aead::TestSet::load(test_name).unwrap();
Expand Down Expand Up @@ -178,9 +187,17 @@ mod test {
test_aead(super::Algorithm::Aes256Gcm);
}

#[cfg(all(chacha, not(feature = "fips")))]
#[test]
fn test_aes_available() {
assert!(super::Algorithm::Aes128Gcm.is_available());
assert!(super::Algorithm::Aes256Gcm.is_available());
}

#[test]
fn test_chacha() {
if !super::Algorithm::ChaCha20Poly1305.is_available() {
return;
}
test_aead(super::Algorithm::ChaCha20Poly1305);
}
}
6 changes: 4 additions & 2 deletions src/kx_group/ec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,16 @@ mod test {
#[case::secp384r1(TestName::EcdhSecp384r1, NamedGroup::secp384r1, Nid::SECP384R1)]
fn test_ec_kx(#[case] test_name: TestName, #[case] rustls_group: NamedGroup, #[case] nid: Nid) {
let test_set = wycheproof::ecdh::TestSet::load(test_name).unwrap();
let ctx = openssl::bn::BigNumContext::new().unwrap();
let mut ctx = openssl::bn::BigNumContext::new().unwrap();

for test_group in &test_set.test_groups {
for test in &test_group.tests {
let group = EcGroup::from_curve_name(nid).unwrap();
let private_num = BigNum::from_slice(&test.private_key).unwrap();
let mut point = EcPoint::new(&group).unwrap();
point.mul_generator(&group, &private_num, &ctx).unwrap();
point
.mul_generator2(&group, &private_num, &mut ctx)
.unwrap();
let ec_key = EcKey::from_private_components(&group, &private_num, &point).unwrap();

let kx = EcKeyExchange {
Expand Down
56 changes: 41 additions & 15 deletions src/kx_group/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,53 +4,79 @@ use rustls::crypto::SupportedKxGroup;
mod ec;
pub use ec::{SECP256R1, SECP384R1};

#[cfg(not(feature = "fips"))]
mod x25519;
#[cfg(not(feature = "fips"))]
pub use x25519::X25519;

#[cfg(ossl350)]
#[cfg(ossl300)]
mod kem;
#[cfg(ossl350)]
#[cfg(ossl300)]
pub use kem::{MLKEM768, X25519MLKEM768};

/// Key exchanges enabled by default by this provider:
/// Key exchanges enabled by default by this provider.
///
/// This compile-time list is filtered at runtime based on OpenSSL algorithm
/// availability.
/// Use [available_default_groups()] for runtime-available defaults.
///
/// Compile-time set:
/// * [X25519MLKEM768] (OpenSSL 3.5+)
/// * [X25519] (if fips feature not enabled)
/// * [X25519]
/// * [SECP384R1]
/// * [SECP256R1]
///
/// If the `prefer-post-quantum` feature is enabled, X25519MLKEM768 will
/// be the first group offered, otherwise it will be the last.
pub static DEFAULT_KX_GROUPS: &[&dyn SupportedKxGroup] = &[
#[cfg(all(ossl350, feature = "prefer-post-quantum"))]
#[cfg(all(ossl300, feature = "prefer-post-quantum"))]
X25519MLKEM768,
#[cfg(not(feature = "fips"))]
X25519,
SECP256R1,
SECP384R1,
#[cfg(all(ossl350, not(feature = "prefer-post-quantum")))]
#[cfg(all(ossl300, not(feature = "prefer-post-quantum")))]
X25519MLKEM768,
];

/// All key exchanges supported by this provider:
/// All key exchanges supported by this provider.
///
/// This compile-time list is filtered at runtime based on OpenSSL algorithm
/// availability.
/// Use [available_groups()] for runtime-available groups.
///
/// Compile-time set:
/// * [X25519MLKEM768] (OpenSSL 3.5+)
/// * [X25519] (if fips feature not enabled)
/// * [X25519]
/// * [SECP384R1]
/// * [SECP256R1]
/// * [MLKEM768] (OpenSSL 3.5+)
///
/// If the `prefer-post-quantum` feature is enabled, X25519MLKEM768 will
/// be the first group offered, otherwise it will be the last.
pub static ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[
#[cfg(all(ossl350, feature = "prefer-post-quantum"))]
#[cfg(all(ossl300, feature = "prefer-post-quantum"))]
X25519MLKEM768,
#[cfg(not(feature = "fips"))]
X25519,
SECP256R1,
SECP384R1,
#[cfg(all(ossl350, not(feature = "prefer-post-quantum")))]
#[cfg(all(ossl300, not(feature = "prefer-post-quantum")))]
X25519MLKEM768,
#[cfg(ossl350)]
#[cfg(ossl300)]
MLKEM768,
];

/// Returns the algorithms from [DEFAULT_KX_GROUPS] that are available at runtime.
pub fn available_default_groups() -> Vec<&'static dyn SupportedKxGroup> {
DEFAULT_KX_GROUPS
.iter()
.copied()
.filter(|group| group.start().is_ok())
.collect()
}

/// Returns the algorithms from [ALL_KX_GROUPS] that are available at runtime.
pub fn available_groups() -> Vec<&'static dyn SupportedKxGroup> {
ALL_KX_GROUPS
.iter()
.copied()
.filter(|group| group.start().is_ok())
.collect()
}
Loading
Loading