From f15cfa9eb05a2edf0da9763b6190b21c5eba98f7 Mon Sep 17 00:00:00 2001 From: Matt Johnston <matt@ucc.asn.au> Date: Wed, 1 Jun 2022 12:44:11 +0800 Subject: [PATCH] Fakerandom --- Cargo.lock | 1 + sshproto/Cargo.toml | 9 +++++--- sshproto/src/kex.rs | 3 +-- sshproto/src/packets.rs | 15 +++++++++++++ sshproto/src/random.rs | 47 +++++++++++++++++++++++++++++++++++++++-- sshproto/src/sign.rs | 26 ++++++++++++++++------- sshproto/src/sshwire.rs | 5 +++++ 7 files changed, 91 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1d980fe..c978dbd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -355,6 +355,7 @@ dependencies = [ "pretty-hex 0.3.0", "proptest", "rand", + "rand_core 0.6.3", "serde_json", "sha2 0.10.2", "simplelog", diff --git a/sshproto/Cargo.toml b/sshproto/Cargo.toml index 71e5c34..9df5f76 100644 --- a/sshproto/Cargo.toml +++ b/sshproto/Cargo.toml @@ -13,7 +13,8 @@ heapless = "0.7.10" no-panic = "0.1" # TODO: needs changing for embedded platforms -rand = { version = "0.8", default-features = false, features = ["getrandom"] } +rand = { version = "0.8", default-features = false } +rand_core = { version = "0.6", default-features = false } ctr = "0.9" aes = "0.8" @@ -55,11 +56,13 @@ git = "https://github.com/mobilecoinfoundation/x25519-dalek" branch = "mobilecoin" [features] +default = [ "getrandom" ] std = ["async-trait"] # tokio-queue = ["dep:tokio"] -# serde_state = { version = "0.4", default-features = false, features = ["derive"]} -# serde_derive_state = { version = "0.4" } +getrandom = ["rand/getrandom"] +# don't use this +fakerandom = [] [dev-dependencies] # toml = "0.5" diff --git a/sshproto/src/kex.rs b/sshproto/src/kex.rs index c8cefd2..0d19ac1 100644 --- a/sshproto/src/kex.rs +++ b/sshproto/src/kex.rs @@ -9,7 +9,6 @@ use { use core::fmt; use core::marker::PhantomData; -use rand::rngs::OsRng; use sha2::Sha256; use digest::Digest; @@ -516,7 +515,7 @@ impl core::fmt::Debug for KexCurve25519 { impl KexCurve25519 { fn new() -> Result<Self> { - let ours = x25519_dalek::EphemeralSecret::new(OsRng); + let ours = x25519_dalek::EphemeralSecret::new(random::DoorRng::default()); let pubkey = (&ours).into(); Ok(KexCurve25519 { ours: Some(ours), pubkey }) } diff --git a/sshproto/src/packets.rs b/sshproto/src/packets.rs index 03cc81c..cbdd41a 100644 --- a/sshproto/src/packets.rs +++ b/sshproto/src/packets.rs @@ -259,6 +259,21 @@ pub struct RSAPubKey<'a> { pub n: BinString<'a>, } +// #[cfg(feature = "rsa")] +// impl TryFrom<RsaPubKey<'_> for rsa::RsaPublicKey { +// fn try_from(value: RsaPubKey<'_>) -> Result<Self, Self::Error> { +// use rsa::BigUint; +// rsa::RsaPublickey::new( +// BigUint::from_bytes_be(n.0), +// BigUint::from_bytes_be(e.0), +// ) +// .map_err(|e| { +// debug!("Bad RSA key: {e}"); +// Error::BadKey +// }) +// } +// } + #[derive(Debug, SSHEncode, SSHDecode)] #[sshwire(variant_prefix)] pub enum Signature<'a> { diff --git a/sshproto/src/random.rs b/sshproto/src/random.rs index 77cf6d1..9ae4012 100644 --- a/sshproto/src/random.rs +++ b/sshproto/src/random.rs @@ -4,11 +4,54 @@ use { log::{debug, error, info, log, trace, warn}, }; -use rand::RngCore; +use rand::{RngCore, Rng, CryptoRng}; +use core::num::Wrapping; + +#[cfg(feature = "getrandom")] +pub type DoorRng = rand::rngs::OsRng; + +#[cfg(feature = "fakerandom")] +pub type DoorRng = FakeRng; + +#[derive(Clone, Copy, Debug, Default)] +pub struct FakeRng { + state: Wrapping<u32>, +} + +impl CryptoRng for FakeRng {} + +impl RngCore for FakeRng { + fn next_u32(&mut self) -> u32 { + rand_core::impls::next_u32_via_fill(self) + } + + fn next_u64(&mut self) -> u64 { + rand_core::impls::next_u64_via_fill(self) + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + dest.fill_with(|| { + self.state = Wrapping(14013u32) * self.state + Wrapping(2531011u32); + ((self.state>>16).0 & 0xFF) as u8 + }); + dest.fill(8) + + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> { + Ok(dest.fill(8)) + // Ok(dest.fill_with(|| { + // self.state = Wrapping(14013u32) * self.state + Wrapping(2531011u32); + // ((self.state>>16).0 & 0xFF) as u8 + // })) + } + +} pub fn fill_random(buf: &mut [u8]) -> Result<(), Error> { // TODO: can this return an error? - rand::rngs::OsRng.try_fill_bytes(buf) + let mut rng = DoorRng::default(); + rng.try_fill_bytes(buf) .map_err(|e| { debug!("RNG failed: {e:?}"); Error::msg("RNG failed") diff --git a/sshproto/src/sign.rs b/sshproto/src/sign.rs index 11daae0..fce77ee 100644 --- a/sshproto/src/sign.rs +++ b/sshproto/src/sign.rs @@ -5,7 +5,6 @@ use { log::{debug, error, info, log, trace, warn}, }; -use rand::rngs::OsRng; use ed25519_dalek as dalek; use ed25519_dalek::{Verifier, Signer}; @@ -68,10 +67,21 @@ impl SigType { k.verify(message, &s).map_err(|_| Error::BadSignature) } - (SigType::RSA256, ..) => { + (SigType::RSA256, PubKey::RSA(_k), Signature::RSA256(_s)) => { // TODO warn!("RSA256 is not implemented for no_std"); Err(Error::BadSignature) + // // untested + // use rsa::{PublicKey, RsaPrivateKey, RsaPublicKey, PaddingScheme}; + // let k: RsaPublicKey = k.try_into()?; + // let h = sha2::Sha256::digest(message); + // k.verify(rsa::padding::PaddingScheme::PKCS1v15Sign{ hash: rsa::hash::Hash::SHA2_256}, + // &h, + // s.sig.0) + // .map_err(|e| { + // trace!("RSA signature failed: {e}"); + // Error::BadSignature + // }) } _ => { @@ -158,16 +168,16 @@ impl TryFrom<ssh_key::PrivateKey> for SignKey { #[cfg(test)] pub(crate) mod tests { - use rand::rngs::OsRng; use ed25519_dalek::Signer; - use crate::sshnames::SSH_NAME_ED25519; - use crate::packets; - use crate::sign::*; - use crate::doorlog::init_test_log; + use crate::*; + use sshnames::SSH_NAME_ED25519; + use packets; + use sign::*; + use doorlog::init_test_log; pub(crate) fn make_ed25519_signkey() -> SignKey { - let mut rng = OsRng{}; + let mut rng = random::DoorRng::default(); let ed = dalek::Keypair::generate(&mut rng); sign::SignKey::Ed25519(ed) } diff --git a/sshproto/src/sshwire.rs b/sshproto/src/sshwire.rs index 63d3cc9..4283030 100644 --- a/sshproto/src/sshwire.rs +++ b/sshproto/src/sshwire.rs @@ -54,6 +54,11 @@ pub fn packet_from_bytes<'a>(b: &'a [u8], ctx: &ParseContext) -> Result<Packet<' Packet::dec(&mut s) } +pub fn read_ssh<'a, T: SSHDecode<'a>>(b: &'a [u8], ctx: Option<ParseContext>) -> Result<T> { + let mut s = DecodeBytes { input: b, pos: 0, parse_ctx: ctx.unwrap_or_default() }; + T::dec(&mut s) +} + pub fn write_ssh<T>(target: &mut [u8], value: &T) -> Result<usize> where T: SSHEncode, -- GitLab