use std::os::raw::c_int;
use crate::error::{last_error, Error, Result};
use crate::ffi::SslCtx;
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum NamedGroup {
X25519,
Secp256r1,
Secp384r1,
Secp521r1,
X25519MLKEM768,
SecP256r1MLKEM768,
SecP384r1MLKEM1024,
}
impl NamedGroup {
pub(crate) fn nid(self) -> c_int {
match self {
Self::X25519 => aws_lc_sys::NID_X25519,
Self::Secp256r1 => aws_lc_sys::NID_X9_62_prime256v1,
Self::Secp384r1 => aws_lc_sys::NID_secp384r1,
Self::Secp521r1 => aws_lc_sys::NID_secp521r1,
Self::X25519MLKEM768 => aws_lc_sys::NID_X25519MLKEM768,
Self::SecP256r1MLKEM768 => aws_lc_sys::NID_SecP256r1MLKEM768,
Self::SecP384r1MLKEM1024 => aws_lc_sys::NID_SecP384r1MLKEM1024,
}
}
}
pub(crate) fn apply_to_ctx(ctx: &SslCtx, groups: &[NamedGroup]) -> Result<()> {
debug_assert!(!groups.is_empty(), "caller must guard against empty list");
let nids: Vec<c_int> = groups.iter().copied().map(NamedGroup::nid).collect();
let ok = unsafe { aws_lc_sys::SSL_CTX_set1_groups(ctx.as_ptr(), nids.as_ptr(), nids.len()) };
if ok != 1 {
return Err(Error::Init(format!(
"SSL_CTX_set1_groups: {}",
last_error()
)));
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn nids_match_bindings() {
assert_eq!(NamedGroup::X25519.nid(), aws_lc_sys::NID_X25519);
assert_eq!(
NamedGroup::Secp256r1.nid(),
aws_lc_sys::NID_X9_62_prime256v1
);
assert_eq!(NamedGroup::Secp384r1.nid(), aws_lc_sys::NID_secp384r1);
assert_eq!(NamedGroup::Secp521r1.nid(), aws_lc_sys::NID_secp521r1);
assert_eq!(
NamedGroup::X25519MLKEM768.nid(),
aws_lc_sys::NID_X25519MLKEM768
);
assert_eq!(
NamedGroup::SecP256r1MLKEM768.nid(),
aws_lc_sys::NID_SecP256r1MLKEM768
);
assert_eq!(
NamedGroup::SecP384r1MLKEM1024.nid(),
aws_lc_sys::NID_SecP384r1MLKEM1024
);
}
#[test]
fn apply_to_ctx_accepts_known_groups() {
let raw = unsafe { aws_lc_sys::SSL_CTX_new(aws_lc_sys::TLS_client_method()) };
let ctx = unsafe { SslCtx::from_raw(raw) }.expect("SSL_CTX_new");
apply_to_ctx(
&ctx,
&[
NamedGroup::X25519,
NamedGroup::Secp256r1,
NamedGroup::X25519MLKEM768,
],
)
.expect("apply_to_ctx accepts a mixed classical/PQ list");
}
}