From 1adf798c5d2333e802c4f05cd09494b257f26a89 Mon Sep 17 00:00:00 2001 From: Noratrieb <48135649+Noratrieb@users.noreply.github.com> Date: Sat, 10 Aug 2024 23:43:20 +0200 Subject: [PATCH] more --- Cargo.lock | 2 ++ Cargo.toml | 1 + ssh-transport/Cargo.toml | 1 + ssh-transport/src/keys.rs | 60 +++++++++++++++++++++++-------------- ssh-transport/src/packet.rs | 2 ++ 5 files changed, 44 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7780ebd..0d80663 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -249,6 +249,7 @@ name = "fakessh" version = "0.1.0" dependencies = [ "eyre", + "hex-literal", "ssh-transport", "tokio", "tracing", @@ -700,6 +701,7 @@ dependencies = [ "rand", "rand_core", "sha2", + "subtle", "tracing", "tracing-subscriber", "x25519-dalek", diff --git a/Cargo.toml b/Cargo.toml index 6f2ca4d..0c3aec2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" [dependencies] eyre = "0.6.12" +hex-literal = "0.4.1" ssh-transport = { path = "./ssh-transport" } tokio = { version = "1.39.2", features = ["full"] } diff --git a/ssh-transport/Cargo.toml b/ssh-transport/Cargo.toml index ae90965..90f6956 100644 --- a/ssh-transport/Cargo.toml +++ b/ssh-transport/Cargo.toml @@ -12,6 +12,7 @@ poly1305 = "0.8.0" rand = "0.8.5" rand_core = "0.6.4" sha2 = "0.10.8" +subtle = "2.6.1" tracing = "0.1.40" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } x25519-dalek = "2.0.1" diff --git a/ssh-transport/src/keys.rs b/ssh-transport/src/keys.rs index 3edc1e8..2c04eac 100644 --- a/ssh-transport/src/keys.rs +++ b/ssh-transport/src/keys.rs @@ -1,6 +1,6 @@ use chacha20::cipher::{KeyInit, KeyIvInit, StreamCipher, StreamCipherSeek}; -use poly1305::universal_hash::UniversalHash; use sha2::Digest; +use subtle::ConstantTimeEq; use crate::{ packet::{Packet, RawPacket}, @@ -73,17 +73,18 @@ impl Decryptor for Session { /// Derive a key from the shared secret K and exchange hash H. /// -fn derive_key( - k: [u8; 32], - h: [u8; 32], - letter: &str, - session_id: [u8; 32], -) -> [u8; KEY_LEN] { +fn derive_key(k: [u8; 32], h: [u8; 32], letter: &str, session_id: [u8; 32]) -> [u8; 64] { let sha2len = sha2::Sha256::output_size(); + let mut output = [0; 64]; - let mut output = [0; KEY_LEN]; + //let mut hash = sha2::Sha256::new(); + //encode_mpint_for_hash(&k, |data| hash.update(data)); + //hash.update(h); + //hash.update(letter.as_bytes()); + //hash.update(session_id); + //output[..sha2len].copy_from_slice(&hash.finalize()); - for i in 0..(KEY_LEN / sha2len) { + for i in 0..(64 / sha2len) { let mut hash = sha2::Sha256::new(); encode_mpint_for_hash(&k, |data| hash.update(data)); hash.update(h); @@ -91,8 +92,9 @@ fn derive_key( if i == 0 { hash.update(letter.as_bytes()); hash.update(session_id); + } else { + hash.update(&output[..(i * sha2len)]); } - hash.update(&output[..(i * sha2len)]); output[(i * sha2len)..][..sha2len].copy_from_slice(&hash.finalize()) } @@ -135,6 +137,7 @@ impl SshChaCha20Poly1305 { } fn decrypt_len(&self, bytes: &mut [u8], packet_number: u64) { + eprintln!("encrypted len: {:x?}", &bytes); // let mut cipher = SshChaCha20::new(&self.header_key, &packet_number.to_be_bytes().into()); cipher.apply_keystream(bytes); @@ -156,23 +159,36 @@ impl SshChaCha20Poly1305 { //) //.map_err(|err| crate::client_error!("failed to decrypt invalid poly1305 MAC: {err}"))?; - let mut cipher = SshChaCha20::new(&self.main_key2, &packet_number.to_be_bytes().into()); - - let mut mac = { - let mut poly1305_key = [0; poly1305::KEY_SIZE]; - cipher.apply_keystream(&mut poly1305_key); - poly1305::Poly1305::new(&poly1305_key.into()) - }; + let mut cipher = ::new( + &self.main_key2, + &packet_number.to_be_bytes().into(), + ); let tag_offset = bytes.full_packet().len() - 16; - let aead_payload = &bytes.full_packet()[..tag_offset]; - mac.update_padded(aead_payload); + let data_to_mac = &bytes.full_packet()[..tag_offset]; + eprintln!("data_to_mac: {:x?}", &data_to_mac); + + let mac = { + let mut poly1305_key = [0; poly1305::KEY_SIZE]; + cipher.apply_keystream(&mut poly1305_key); + poly1305::Poly1305::new(&poly1305_key.into()).compute_unpadded(data_to_mac) + }; + let read_tag = poly1305::Tag::from_slice(&bytes.full_packet()[tag_offset..]); - mac.verify(read_tag) - .map_err(|err| crate::client_error!("failed to decrypt invalid poly1305 MAC: {err}"))?; + eprintln!("expected MAC: {mac:x?}"); + eprintln!("found MAC: {read_tag:x?}"); - cipher.seek(1); + if !bool::from(mac.ct_eq(read_tag)) { + return Err(crate::client_error!( + "failed to decrypt: invalid poly1305 MAC" + )); + } + + //mac.verify(read_tag) + // .map_err(|err| crate::client_error!("failed to decrypt invalid poly1305 MAC: {err}"))?; + + cipher.seek(64); todo!() } diff --git a/ssh-transport/src/packet.rs b/ssh-transport/src/packet.rs index 62f00cd..b7d4b0b 100644 --- a/ssh-transport/src/packet.rs +++ b/ssh-transport/src/packet.rs @@ -325,6 +325,8 @@ impl PacketParser { let packet_length = u32::from_be_bytes(len_to_decrypt); let packet_length = packet_length.try_into().unwrap(); + dbg!(packet_length); + self.packet_length = Some(packet_length); // We have the data.