use rustls::crypto::{ActiveKeyExchange, SharedSecret, SupportedKxGroup};
use rustls::{Error as RustlsError, NamedGroup, PeerMisbehaved};
use ferritls_core::ecdh::{p256, p384, x25519};
fn map_dh_err(_: ferritls_core::Error) -> RustlsError {
RustlsError::PeerMisbehaved(PeerMisbehaved::InvalidKeyShare)
}
#[derive(Debug)]
pub struct X25519;
#[derive(Debug)]
pub struct SecP256R1;
#[derive(Debug)]
pub struct SecP384R1;
impl SupportedKxGroup for X25519 {
fn start(&self) -> Result<Box<dyn ActiveKeyExchange>, RustlsError> {
let sk = x25519::SecretKey::generate().map_err(map_dh_err)?;
let pk = sk.public_key();
Ok(Box::new(ActiveX25519 { sk, pk }))
}
fn name(&self) -> NamedGroup {
NamedGroup::X25519
}
fn fips(&self) -> bool {
false
}
}
impl SupportedKxGroup for SecP256R1 {
fn start(&self) -> Result<Box<dyn ActiveKeyExchange>, RustlsError> {
let sk = p256::SecretKey::generate().map_err(map_dh_err)?;
let pk = sk.public_key();
Ok(Box::new(ActiveSecP256R1 { sk, pk }))
}
fn name(&self) -> NamedGroup {
NamedGroup::secp256r1
}
fn fips(&self) -> bool {
false
}
}
impl SupportedKxGroup for SecP384R1 {
fn start(&self) -> Result<Box<dyn ActiveKeyExchange>, RustlsError> {
let sk = p384::SecretKey::generate().map_err(map_dh_err)?;
let pk = sk.public_key();
Ok(Box::new(ActiveSecP384R1 { sk, pk }))
}
fn name(&self) -> NamedGroup {
NamedGroup::secp384r1
}
fn fips(&self) -> bool {
false
}
}
pub(crate) struct ActiveX25519 {
sk: x25519::SecretKey,
pk: [u8; 32],
}
pub(crate) struct ActiveSecP256R1 {
sk: p256::SecretKey,
pk: [u8; p256::PUBLIC_KEY_LEN],
}
pub(crate) struct ActiveSecP384R1 {
sk: p384::SecretKey,
pk: [u8; p384::PUBLIC_KEY_LEN],
}
impl std::fmt::Debug for ActiveX25519 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("ActiveX25519")
}
}
impl std::fmt::Debug for ActiveSecP256R1 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("ActiveSecP256R1")
}
}
impl std::fmt::Debug for ActiveSecP384R1 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("ActiveSecP384R1")
}
}
impl ActiveKeyExchange for ActiveX25519 {
fn complete(self: Box<Self>, peer_pub_key: &[u8]) -> Result<SharedSecret, RustlsError> {
let ss = self.sk.diffie_hellman(peer_pub_key).map_err(map_dh_err)?;
Ok(SharedSecret::from(ss.as_bytes().to_vec()))
}
fn pub_key(&self) -> &[u8] {
&self.pk
}
fn group(&self) -> NamedGroup {
NamedGroup::X25519
}
}
impl ActiveKeyExchange for ActiveSecP256R1 {
fn complete(self: Box<Self>, peer_pub_key: &[u8]) -> Result<SharedSecret, RustlsError> {
let ss = self.sk.diffie_hellman(peer_pub_key).map_err(map_dh_err)?;
Ok(SharedSecret::from(ss.as_bytes().to_vec()))
}
fn pub_key(&self) -> &[u8] {
&self.pk
}
fn group(&self) -> NamedGroup {
NamedGroup::secp256r1
}
}
impl ActiveKeyExchange for ActiveSecP384R1 {
fn complete(self: Box<Self>, peer_pub_key: &[u8]) -> Result<SharedSecret, RustlsError> {
let ss = self.sk.diffie_hellman(peer_pub_key).map_err(map_dh_err)?;
Ok(SharedSecret::from(ss.as_bytes().to_vec()))
}
fn pub_key(&self) -> &[u8] {
&self.pk
}
fn group(&self) -> NamedGroup {
NamedGroup::secp384r1
}
}
pub static X25519_GROUP: &dyn SupportedKxGroup = &X25519;
pub static SECP256R1_GROUP: &dyn SupportedKxGroup = &SecP256R1;
pub static SECP384R1_GROUP: &dyn SupportedKxGroup = &SecP384R1;
pub static ALL_KX_GROUPS: &[&'static dyn SupportedKxGroup] = &[&X25519, &SecP256R1, &SecP384R1];
pub static FIPS_KX_GROUPS: &[&'static dyn SupportedKxGroup] = &[&SecP256R1, &SecP384R1];