-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathkx.rs
More file actions
108 lines (90 loc) · 3.4 KB
/
kx.rs
File metadata and controls
108 lines (90 loc) · 3.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#[cfg(feature = "alloc")]
use alloc::boxed::Box;
use crypto::{SharedSecret, SupportedKxGroup};
use paste::paste;
use rustls::crypto;
#[derive(Debug)]
pub struct X25519;
impl crypto::SupportedKxGroup for X25519 {
fn name(&self) -> rustls::NamedGroup {
rustls::NamedGroup::X25519
}
fn start(&self) -> Result<Box<dyn crypto::ActiveKeyExchange>, rustls::Error> {
let priv_key = x25519_dalek::EphemeralSecret::random_from_rng(crate::CryptoProviderRng);
let pub_key = (&priv_key).into();
Ok(Box::new(X25519KeyExchange { priv_key, pub_key }))
}
}
pub struct X25519KeyExchange {
priv_key: x25519_dalek::EphemeralSecret,
pub_key: x25519_dalek::PublicKey,
}
impl crypto::ActiveKeyExchange for X25519KeyExchange {
fn complete(self: Box<X25519KeyExchange>, peer: &[u8]) -> Result<SharedSecret, rustls::Error> {
let peer_array: [u8; 32] = peer
.try_into()
.map_err(|_| rustls::Error::from(rustls::PeerMisbehaved::InvalidKeyShare))?;
Ok(self
.priv_key
.diffie_hellman(&peer_array.into())
.as_ref()
.into())
}
fn pub_key(&self) -> &[u8] {
self.pub_key.as_bytes()
}
fn group(&self) -> rustls::NamedGroup {
X25519.name()
}
}
macro_rules! impl_kx {
($name:ident, $kx_name:ty, $secret:ty, $public_key:ty) => {
paste! {
#[derive(Debug)]
#[allow(non_camel_case_types)]
pub struct $name;
impl crypto::SupportedKxGroup for $name {
fn name(&self) -> rustls::NamedGroup {
$kx_name
}
fn start(&self) -> Result<Box<dyn crypto::ActiveKeyExchange>, rustls::Error> {
let priv_key = $secret::random(&mut crate::CryptoProviderRng);
let pub_key: $public_key = (&priv_key).into();
Ok(Box::new([<$name KeyExchange>] {
priv_key,
pub_key: pub_key.to_sec1_bytes(),
}))
}
}
#[allow(non_camel_case_types)]
pub struct [<$name KeyExchange>] {
priv_key: $secret,
pub_key: Box<[u8]>,
}
impl crypto::ActiveKeyExchange for [<$name KeyExchange>] {
fn complete(
self: Box<[<$name KeyExchange>]>,
peer: &[u8],
) -> Result<SharedSecret, rustls::Error> {
let their_pub = $public_key::from_sec1_bytes(peer)
.map_err(|_| rustls::Error::from(rustls::PeerMisbehaved::InvalidKeyShare))?;
Ok(self
.priv_key
.diffie_hellman(&their_pub)
.raw_secret_bytes()
.as_slice()
.into())
}
fn pub_key(&self) -> &[u8] {
&self.pub_key
}
fn group(&self) -> rustls::NamedGroup {
$name.name()
}
}
}
};
}
impl_kx! {SecP256R1, rustls::NamedGroup::secp256r1, p256::ecdh::EphemeralSecret, p256::PublicKey}
impl_kx! {SecP384R1, rustls::NamedGroup::secp384r1, p384::ecdh::EphemeralSecret, p384::PublicKey}
pub const ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[&X25519, &SecP256R1, &SecP384R1];