1use rustls::crypto::{ActiveKeyExchange, SharedSecret, SupportedKxGroup};
11use rustls::{Error as RustlsError, NamedGroup, PeerMisbehaved};
12
13use ferritls_core::ecdh::{p256, p384, x25519};
14
15fn map_dh_err(_: ferritls_core::Error) -> RustlsError {
17 RustlsError::PeerMisbehaved(PeerMisbehaved::InvalidKeyShare)
18}
19
20#[derive(Debug)]
22pub struct X25519;
23
24#[derive(Debug)]
26pub struct SecP256R1;
27
28#[derive(Debug)]
30pub struct SecP384R1;
31
32impl SupportedKxGroup for X25519 {
33 fn start(&self) -> Result<Box<dyn ActiveKeyExchange>, RustlsError> {
34 let sk = x25519::SecretKey::generate().map_err(map_dh_err)?;
35 let pk = sk.public_key();
36 Ok(Box::new(ActiveX25519 { sk, pk }))
37 }
38
39 fn name(&self) -> NamedGroup {
40 NamedGroup::X25519
41 }
42
43 fn fips(&self) -> bool {
44 false
46 }
47}
48
49impl SupportedKxGroup for SecP256R1 {
50 fn start(&self) -> Result<Box<dyn ActiveKeyExchange>, RustlsError> {
51 let sk = p256::SecretKey::generate().map_err(map_dh_err)?;
52 let pk = sk.public_key();
53 Ok(Box::new(ActiveSecP256R1 { sk, pk }))
54 }
55
56 fn name(&self) -> NamedGroup {
57 NamedGroup::secp256r1
58 }
59
60 fn fips(&self) -> bool {
61 false
63 }
64}
65
66impl SupportedKxGroup for SecP384R1 {
67 fn start(&self) -> Result<Box<dyn ActiveKeyExchange>, RustlsError> {
68 let sk = p384::SecretKey::generate().map_err(map_dh_err)?;
69 let pk = sk.public_key();
70 Ok(Box::new(ActiveSecP384R1 { sk, pk }))
71 }
72
73 fn name(&self) -> NamedGroup {
74 NamedGroup::secp384r1
75 }
76
77 fn fips(&self) -> bool {
78 false
79 }
80}
81
82pub(crate) struct ActiveX25519 {
84 sk: x25519::SecretKey,
85 pk: [u8; 32],
86}
87
88pub(crate) struct ActiveSecP256R1 {
90 sk: p256::SecretKey,
91 pk: [u8; p256::PUBLIC_KEY_LEN],
92}
93
94pub(crate) struct ActiveSecP384R1 {
96 sk: p384::SecretKey,
97 pk: [u8; p384::PUBLIC_KEY_LEN],
98}
99
100impl std::fmt::Debug for ActiveX25519 {
101 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102 f.write_str("ActiveX25519")
103 }
104}
105
106impl std::fmt::Debug for ActiveSecP256R1 {
107 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108 f.write_str("ActiveSecP256R1")
109 }
110}
111
112impl std::fmt::Debug for ActiveSecP384R1 {
113 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
114 f.write_str("ActiveSecP384R1")
115 }
116}
117
118impl ActiveKeyExchange for ActiveX25519 {
119 fn complete(self: Box<Self>, peer_pub_key: &[u8]) -> Result<SharedSecret, RustlsError> {
120 let ss = self.sk.diffie_hellman(peer_pub_key).map_err(map_dh_err)?;
121 Ok(SharedSecret::from(ss.as_bytes().to_vec()))
122 }
123
124 fn pub_key(&self) -> &[u8] {
125 &self.pk
126 }
127
128 fn group(&self) -> NamedGroup {
129 NamedGroup::X25519
130 }
131}
132
133impl ActiveKeyExchange for ActiveSecP256R1 {
134 fn complete(self: Box<Self>, peer_pub_key: &[u8]) -> Result<SharedSecret, RustlsError> {
135 let ss = self.sk.diffie_hellman(peer_pub_key).map_err(map_dh_err)?;
136 Ok(SharedSecret::from(ss.as_bytes().to_vec()))
137 }
138
139 fn pub_key(&self) -> &[u8] {
140 &self.pk
141 }
142
143 fn group(&self) -> NamedGroup {
144 NamedGroup::secp256r1
145 }
146}
147
148impl ActiveKeyExchange for ActiveSecP384R1 {
149 fn complete(self: Box<Self>, peer_pub_key: &[u8]) -> Result<SharedSecret, RustlsError> {
150 let ss = self.sk.diffie_hellman(peer_pub_key).map_err(map_dh_err)?;
151 Ok(SharedSecret::from(ss.as_bytes().to_vec()))
152 }
153
154 fn pub_key(&self) -> &[u8] {
155 &self.pk
156 }
157
158 fn group(&self) -> NamedGroup {
159 NamedGroup::secp384r1
160 }
161}
162
163pub static X25519_GROUP: &dyn SupportedKxGroup = &X25519;
165pub static SECP256R1_GROUP: &dyn SupportedKxGroup = &SecP256R1;
167pub static SECP384R1_GROUP: &dyn SupportedKxGroup = &SecP384R1;
169
170pub static ALL_KX_GROUPS: &[&'static dyn SupportedKxGroup] = &[&X25519, &SecP256R1, &SecP384R1];
173
174pub static FIPS_KX_GROUPS: &[&'static dyn SupportedKxGroup] = &[&SecP256R1, &SecP384R1];