From 982de536688b29503494be3ccb2778edc17519f7 Mon Sep 17 00:00:00 2001 From: Noratrieb <48135649+Noratrieb@users.noreply.github.com> Date: Tue, 13 Aug 2024 17:04:19 +0200 Subject: [PATCH] refactor --- ssh-transport/src/crypto.rs | 50 +++++++++++++++++++++++++++++++------ ssh-transport/src/lib.rs | 28 ++++++++------------- ssh-transport/src/packet.rs | 32 ++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 24 deletions(-) diff --git a/ssh-transport/src/crypto.rs b/ssh-transport/src/crypto.rs index a068bff..ae7cb03 100644 --- a/ssh-transport/src/crypto.rs +++ b/ssh-transport/src/crypto.rs @@ -1,12 +1,13 @@ use aes_gcm::aead::AeadMutInPlace; use chacha20::cipher::{KeyInit, StreamCipher, StreamCipherSeek}; -use p256::ecdsa::signature::{Signer}; +use p256::ecdsa::signature::Signer; use sha2::Digest; use subtle::ConstantTimeEq; use crate::{ client_error, packet::{EncryptedPacket, MsgKind, Packet, RawPacket}, + parse::Writer, Msg, Result, SshRng, }; @@ -129,11 +130,14 @@ pub const ENC_AES256_GCM: EncryptionAlgorithm = EncryptionAlgorithm { }, }; +pub struct EncodedSshPublicHostKey(pub Vec); +pub struct EncodedSshSignature(pub Vec); + pub struct HostKeySigningAlgorithm { name: &'static str, hostkey_private: Vec, - public_key: fn(private_key: &[u8]) -> Vec, - sign: fn(private_key: &[u8], data: &[u8]) -> Vec, + public_key: fn(private_key: &[u8]) -> EncodedSshPublicHostKey, + sign: fn(private_key: &[u8], data: &[u8]) -> EncodedSshSignature, } impl AlgorithmName for HostKeySigningAlgorithm { @@ -143,10 +147,10 @@ impl AlgorithmName for HostKeySigningAlgorithm { } impl HostKeySigningAlgorithm { - pub fn sign(&self, data: &[u8]) -> Vec { + pub fn sign(&self, data: &[u8]) -> EncodedSshSignature { (self.sign)(&self.hostkey_private, data) } - pub fn public_key(&self) -> Vec { + pub fn public_key(&self) -> EncodedSshPublicHostKey { (self.public_key)(&self.hostkey_private) } } @@ -157,11 +161,43 @@ pub fn hostkey_ed25519(hostkey_private: Vec) -> HostKeySigningAlgorithm { hostkey_private, public_key: |key| { let key = ed25519_dalek::SigningKey::from_bytes(key.try_into().unwrap()); - key.verifying_key().as_bytes().to_vec() + let public_key = key.verifying_key(); + + // + let mut data = Writer::new(); + data.string(b"ssh-ed25519"); + data.string(public_key.as_bytes()); + EncodedSshPublicHostKey(data.finish()) }, sign: |key, data| { let key = ed25519_dalek::SigningKey::from_bytes(key.try_into().unwrap()); - key.sign(data).to_vec() + let signature = key.sign(data); + + // + let mut data = Writer::new(); + data.string(b"ssh-ed25519"); + data.string(&signature.to_bytes()); + EncodedSshSignature(data.finish()) + }, + } +} +pub fn hostkey_ecdsa_sha2_p256(hostkey_private: Vec) -> HostKeySigningAlgorithm { + HostKeySigningAlgorithm { + name: "ecdsa-sha2-nistp256", + hostkey_private, + public_key: |key| { + let key = p256::ecdsa::SigningKey::from_slice(key).unwrap(); + key.verifying_key() + .to_encoded_point(true) + .as_bytes() + .to_vec(); + todo!() + }, + sign: |key, data| { + let key = p256::ecdsa::SigningKey::from_slice(key).unwrap(); + let signature: p256::ecdsa::Signature = key.sign(data); + signature.to_vec(); + todo!() }, } } diff --git a/ssh-transport/src/lib.rs b/ssh-transport/src/lib.rs index 94e048e..810831f 100644 --- a/ssh-transport/src/lib.rs +++ b/ssh-transport/src/lib.rs @@ -7,7 +7,6 @@ use core::str; use std::{collections::VecDeque, mem::take}; use crypto::{AlgorithmName, AlgorithmNegotiation, EncryptionAlgorithm, HostKeySigningAlgorithm}; -use ed25519_dalek::ed25519::signature::Signer; use packet::{ KeyExchangeEcDhInitPacket, KeyExchangeInitPacket, Packet, PacketTransport, SshPublicKey, SshSignature, @@ -198,13 +197,15 @@ impl ServerConnection { let kex_algorithm = kex_algorithms.find(kex.kex_algorithms.0)?; debug!(name = %kex_algorithm.name(), "Using KEX algorithm"); - // TODO: support ecdsa-sha2-nistp256 let hostkey_algorithms = AlgorithmNegotiation { - supported: vec![crypto::hostkey_ed25519(ED25519_PRIVKEY_BYTES.to_vec())], + supported: vec![ + //crypto::hostkey_ed25519(ED25519_PRIVKEY_BYTES.to_vec()), + crypto::hostkey_ecdsa_sha2_p256(ECDSA_P256_PRIVKEY_BYTES.to_vec()), + ], }; - let server_host_key_algorithm = hostkey_algorithms.find(kex.server_host_key_algorithms.0)?; + debug!(name = %server_host_key_algorithm.name(), "Using host key algorithm"); let encryption_algorithms_client_to_server = AlgorithmNegotiation { supported: vec![crypto::ENC_CHACHA20POLY1305, crypto::ENC_AES256_GCM], @@ -299,7 +300,7 @@ impl ServerConnection { shared_secret, } = (kex_algorithm.exchange)(client_public_key, &mut *self.rng)?; - /*let hostkey = + let hostkey = p256::ecdsa::SigningKey::random(&mut SshRngRandAdapter(&mut *self.rng)); eprintln!( @@ -310,12 +311,9 @@ impl ServerConnection { .map(|b| format!("0x{b:x}")) .collect::>() .join(", ") - );*/ + ); - let pub_hostkey = SshPublicKey { - format: server_host_key_algorithm.name().as_bytes(), - data: &server_host_key_algorithm.public_key(), - }; + let pub_hostkey = server_host_key_algorithm.public_key(); let mut hash = sha2::Sha256::new(); let add_hash = |hash: &mut sha2::Sha256, bytes: &[u8]| { @@ -339,7 +337,7 @@ impl ServerConnection { ); // V_S hash_string(&mut hash, client_kexinit); // I_C hash_string(&mut hash, server_kexinit); // I_S - hash_string(&mut hash, &pub_hostkey.to_bytes()); // K_S + hash_string(&mut hash, &pub_hostkey.0); // K_S // For normal DH as in RFC4253, e and f are mpints. // But for ECDH as defined in RFC5656, Q_C and Q_S are strings. @@ -358,13 +356,9 @@ impl ServerConnection { // eprintln!("hash: {:x?}", hash); let packet = Packet::new_msg_kex_ecdh_reply( - &pub_hostkey.to_bytes(), + &pub_hostkey.0, &server_public_key, - &SshSignature { - format: server_host_key_algorithm.name().as_bytes(), - data: &signature, - } - .to_bytes(), + &signature.0, ); self.packet_transport.queue_packet(packet); diff --git a/ssh-transport/src/packet.rs b/ssh-transport/src/packet.rs index 6ad49f0..de3757f 100644 --- a/ssh-transport/src/packet.rs +++ b/ssh-transport/src/packet.rs @@ -333,6 +333,24 @@ impl SshPublicKey<'_> { data.finish() } } +#[derive(Debug)] +pub(crate) struct SshPublicKeyEcdsa<'a> { + pub(crate) format: &'a [u8], + pub(crate) ident: &'a [u8], + pub(crate) data: &'a [u8], +} +impl SshPublicKeyEcdsa<'_> { + pub(crate) fn to_bytes(&self) -> Vec { + let mut data = Writer::new(); + // ECDSA-specific! + // + data.string(self.format); + data.string(self.ident); + data.string(self.data); + data.finish() + } +} + #[derive(Debug)] pub(crate) struct SshSignature<'a> { pub(crate) format: &'a [u8], @@ -349,6 +367,20 @@ impl SshSignature<'_> { } } +pub(crate) struct SshSignatureEcdsa<'a> { + pub(crate) format: &'a [u8], + pub(crate) data: &'a [u8], +} + +impl SshSignatureEcdsa<'_> { + pub(crate) fn to_bytes(&self) -> Vec { + let mut data = Writer::new(); + // + data.string(self.format); + data.finish() + } +} + pub(crate) struct RawPacket { pub mac_len: usize, pub raw: Vec,