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