xref: /webrtc/dtls/src/curve/named_curve.rs (revision d5318c9e)
1 use rand_core::OsRng; // requires 'getrandom' feature
2 
3 use crate::error::*;
4 
5 // https://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8
6 #[repr(u16)]
7 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
8 pub enum NamedCurve {
9     Unsupported = 0x0000,
10     P256 = 0x0017,
11     P384 = 0x0018,
12     X25519 = 0x001d,
13 }
14 
15 impl From<u16> for NamedCurve {
from(val: u16) -> Self16     fn from(val: u16) -> Self {
17         match val {
18             0x0017 => NamedCurve::P256,
19             0x0018 => NamedCurve::P384,
20             0x001d => NamedCurve::X25519,
21             _ => NamedCurve::Unsupported,
22         }
23     }
24 }
25 
26 pub(crate) enum NamedCurvePrivateKey {
27     EphemeralSecretP256(p256::ecdh::EphemeralSecret),
28     EphemeralSecretP384(p384::ecdh::EphemeralSecret),
29     StaticSecretX25519(x25519_dalek::StaticSecret),
30 }
31 
32 pub struct NamedCurveKeypair {
33     pub(crate) curve: NamedCurve,
34     pub(crate) public_key: Vec<u8>,
35     pub(crate) private_key: NamedCurvePrivateKey,
36 }
37 
elliptic_curve_keypair(curve: NamedCurve) -> Result<NamedCurveKeypair>38 fn elliptic_curve_keypair(curve: NamedCurve) -> Result<NamedCurveKeypair> {
39     let (public_key, private_key) = match curve {
40         NamedCurve::P256 => {
41             let secret_key = p256::ecdh::EphemeralSecret::random(&mut OsRng);
42             let public_key = p256::EncodedPoint::from(secret_key.public_key());
43             (
44                 public_key.as_bytes().to_vec(),
45                 NamedCurvePrivateKey::EphemeralSecretP256(secret_key),
46             )
47         }
48         NamedCurve::P384 => {
49             let secret_key = p384::ecdh::EphemeralSecret::random(&mut OsRng);
50             let public_key = p384::EncodedPoint::from(secret_key.public_key());
51             (
52                 public_key.as_bytes().to_vec(),
53                 NamedCurvePrivateKey::EphemeralSecretP384(secret_key),
54             )
55         }
56         NamedCurve::X25519 => {
57             let secret_key = x25519_dalek::StaticSecret::random_from_rng(OsRng);
58             let public_key = x25519_dalek::PublicKey::from(&secret_key);
59             (
60                 public_key.as_bytes().to_vec(),
61                 NamedCurvePrivateKey::StaticSecretX25519(secret_key),
62             )
63         }
64         _ => return Err(Error::ErrInvalidNamedCurve),
65     };
66 
67     Ok(NamedCurveKeypair {
68         curve,
69         public_key,
70         private_key,
71     })
72 }
73 
74 impl NamedCurve {
generate_keypair(&self) -> Result<NamedCurveKeypair>75     pub fn generate_keypair(&self) -> Result<NamedCurveKeypair> {
76         match *self {
77             NamedCurve::X25519 => elliptic_curve_keypair(NamedCurve::X25519),
78             NamedCurve::P256 => elliptic_curve_keypair(NamedCurve::P256),
79             NamedCurve::P384 => elliptic_curve_keypair(NamedCurve::P384),
80             _ => Err(Error::ErrInvalidNamedCurve),
81         }
82     }
83 }
84