about summary refs log tree commit diff
path: root/src/libstd/sys/unix/rand.rs
diff options
context:
space:
mode:
authorRaph Levien <raph@google.com>2016-10-24 16:42:57 -0700
committerRaph Levien <raph@google.com>2016-10-24 16:48:45 -0700
commit592d7bfb3af75ded9c5233ee243cc6c751531671 (patch)
treeccf54ae7f1b236245a4ae662121ed5ecf294d348 /src/libstd/sys/unix/rand.rs
parent4879166194ed63ebd2a8c3ce8db1ccde4a6a1920 (diff)
downloadrust-592d7bfb3af75ded9c5233ee243cc6c751531671.tar.gz
rust-592d7bfb3af75ded9c5233ee243cc6c751531671.zip
Add support for kernel randomness for Fuchsia
Wire up cprng syscall as provider for rand::os::OsRng on Fuchsia.
Diffstat (limited to 'src/libstd/sys/unix/rand.rs')
-rw-r--r--src/libstd/sys/unix/rand.rs54
1 files changed, 53 insertions, 1 deletions
diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs
index f28a6ad3375..3aebb8c18ec 100644
--- a/src/libstd/sys/unix/rand.rs
+++ b/src/libstd/sys/unix/rand.rs
@@ -27,7 +27,8 @@ fn next_u64(mut fill_buf: &mut FnMut(&mut [u8])) -> u64 {
 #[cfg(all(unix,
           not(target_os = "ios"),
           not(target_os = "openbsd"),
-          not(target_os = "freebsd")))]
+          not(target_os = "freebsd"),
+          not(target_os = "fuchsia")))]
 mod imp {
     use self::OsRngInner::*;
     use super::{next_u32, next_u64};
@@ -339,3 +340,54 @@ mod imp {
         }
     }
 }
+
+#[cfg(target_os = "fuchsia")]
+mod imp {
+    use super::{next_u32, next_u64};
+
+    use io;
+    use rand::Rng;
+
+    #[link(name = "magenta")]
+    extern {
+        fn mx_cprng_draw(buffer: *mut u8, len: usize) -> isize;
+    }
+
+    fn getrandom(buf: &mut [u8]) -> isize {
+        unsafe { mx_cprng_draw(buf.as_mut_ptr(), buf.len()) }
+    }
+
+    pub struct OsRng {
+        // dummy field to ensure that this struct cannot be constructed outside
+        // of this module
+        _dummy: (),
+    }
+
+    impl OsRng {
+        /// Create a new `OsRng`.
+        pub fn new() -> io::Result<OsRng> {
+            Ok(OsRng { _dummy: () })
+        }
+    }
+
+    impl Rng for OsRng {
+        fn next_u32(&mut self) -> u32 {
+            next_u32(&mut |v| self.fill_bytes(v))
+        }
+        fn next_u64(&mut self) -> u64 {
+            next_u64(&mut |v| self.fill_bytes(v))
+        }
+        fn fill_bytes(&mut self, v: &mut [u8]) {
+            let mut buf = v;
+            while !buf.is_empty() {
+                let ret = getrandom(buf);
+                if ret < 0 {
+                    panic!("kernel mx_cprng_draw call failed! (returned {}, buf.len() {})",
+                        ret, buf.len());
+                }
+                let move_buf = buf;
+                buf = &mut move_buf[(ret as usize)..];
+            }
+        }
+    }
+}