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