ssh/algorithm/key_exchange/
mod.rs

1use crate::algorithm::hash::HashType;
2use crate::{SshError, SshResult};
3use ring::agreement;
4use ring::agreement::{EphemeralPrivateKey, UnparsedPublicKey};
5
6/// # Algorithms that used for key exchange
7///
8/// <https://www.rfc-editor.org/rfc/rfc4253#section-7>
9mod curve25519;
10mod dh;
11mod ecdh_sha2_nistp256;
12
13use super::Kex;
14use curve25519::CURVE25519;
15#[cfg(feature = "deprecated-dh-group1-sha1")]
16use dh::DiffieHellmanGroup1Sha1;
17use dh::{DiffieHellmanGroup14Sha1, DiffieHellmanGroup14Sha256};
18use ecdh_sha2_nistp256::EcdhP256;
19
20pub(crate) trait KeyExchange: Send + Sync {
21    fn new() -> SshResult<Self>
22    where
23        Self: Sized;
24    fn get_public_key(&self) -> &[u8];
25    fn get_shared_secret(&self, puk: Vec<u8>) -> SshResult<Vec<u8>>;
26    fn get_hash_type(&self) -> HashType;
27}
28
29pub(crate) fn agree_ephemeral<B: AsRef<[u8]>>(
30    private_key: EphemeralPrivateKey,
31    peer_public_key: &UnparsedPublicKey<B>,
32) -> SshResult<Vec<u8>> {
33    match agreement::agree_ephemeral(private_key, peer_public_key, |key_material| {
34        Ok(key_material.to_vec())
35    }) {
36        Ok(o) => o,
37        Err(e) => Err(SshError::KexError(e.to_string())),
38    }
39}
40
41pub(crate) fn from(s: &Kex) -> SshResult<Box<dyn KeyExchange>> {
42    match s {
43        Kex::Curve25519Sha256 => Ok(Box::new(CURVE25519::new()?)),
44        Kex::EcdhSha2Nistrp256 => Ok(Box::new(EcdhP256::new()?)),
45        #[cfg(feature = "deprecated-dh-group1-sha1")]
46        Kex::DiffieHellmanGroup1Sha1 => Ok(Box::new(DiffieHellmanGroup1Sha1::new()?)),
47        Kex::DiffieHellmanGroup14Sha1 => Ok(Box::new(DiffieHellmanGroup14Sha1::new()?)),
48        Kex::DiffieHellmanGroup14Sha256 => Ok(Box::new(DiffieHellmanGroup14Sha256::new()?)),
49    }
50}