From 75c612161b67c53b875f6e9af6748f98e034c257 Mon Sep 17 00:00:00 2001 From: Edwin Svensson Date: Thu, 2 Dec 2021 02:22:14 +0100 Subject: [PATCH 1/4] rand_core impl & support all integers in rng --- .github/workflows/ci.yml | 2 +- .github/workflows/nightly.yml | 2 +- Cargo.toml | 6 ++ src/lib.rs | 4 +- src/rng.rs | 101 ++++++++++++++++++++++++++++++++-- 5 files changed, 107 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2c64145a..752e0c66 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: - stm32h7b0 - stm32h735 env: # Peripheral Feature flags - FLAGS: rt,xspi,sdmmc,fmc,usb_hs,rtc,ethernet,ltdc,crc + FLAGS: rt,xspi,sdmmc,sdmmc-fatfs,fmc,usb_hs,rtc,ethernet,ltdc,crc,rand steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 42a86bc9..dddbed3e 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -19,7 +19,7 @@ jobs: - log-semihost - log-rtt env: # Peripheral Feature flags - FLAGS: rt,xspi,sdmmc,fmc,usb_hs,rtc,ethernet,ltdc,crc + FLAGS: rt,xspi,sdmmc,sdmmc-fatfs,fmc,usb_hs,rtc,ethernet,ltdc,crc,rand steps: - uses: actions/checkout@v2 diff --git a/Cargo.toml b/Cargo.toml index b16cab0e..4952e0a0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,6 +51,11 @@ version = "0.4" default-features = false optional = true +[dependencies.rand_core] +version = "0.6" +default-features = false +optional = true + [dev-dependencies] cortex-m-rt = ">=0.6.15,<0.8" cortex-m-rtic = { version = "0.5.8", default-features = false, features = ["cortex-m-7"] } @@ -93,6 +98,7 @@ sdmmc-fatfs = ["embedded-sdmmc", "sdmmc"] ethernet = ["smoltcp"] rtc = ["chrono"] crc = [] +rand = ["rand_core"] rt = ["stm32h7/rt"] usb_hs = ["synopsys-usb-otg", "synopsys-usb-otg/hs"] stm32h742 = ["stm32h7/stm32h743", "device-selected", "rm0433"] diff --git a/src/lib.rs b/src/lib.rs index a0098ab9..6b99f5be 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,7 +31,7 @@ //! External Memory //! //! * [Flexible Memory Controller (FMC)](crate::fmc) Feature gate `fmc` -//! * [SD Card (SDMMC)](crate::sdmmc) Feature gate `sdmmc` +//! * [SD Card (SDMMC)](crate::sdmmc) Feature gate `sdmmc` (FAT16/32 driver is available under the `sdmmc-fatfs` feature gate) //! //! Timing functions //! @@ -44,7 +44,7 @@ //! Others //! //! * [Cyclic Redundancy Check (CRC)](crate::crc) Feature gate `crc` -//! * [Random Number Generator](crate::rng) +//! * [Random Number Generator](crate::rng) ([rand_core::RngCore](rand_core::RngCore) is implemented under the`rand` feature gate) //! * [System Window Watchdog](crate::watchdog) #![cfg_attr(not(test), no_std)] diff --git a/src/rng.rs b/src/rng.rs index c4a48b9d..ed64005d 100644 --- a/src/rng.rs +++ b/src/rng.rs @@ -15,8 +15,8 @@ use crate::time::Hertz; #[derive(Debug)] pub enum ErrorKind { - ClockError, - SeedError, + ClockError = 1, + SeedError = 2, } trait KerClk { @@ -131,8 +131,101 @@ macro_rules! rng_core { }; } -rng_core!(u32, u16, u8); +// Only for types larger than 32 bits +macro_rules! rng_core_large { + ($($type:ty),+) => { + $( + impl RngCore<$type> for Rng { + fn gen(&mut self) -> Result<$type, ErrorKind> { + const WORDS: usize = mem::size_of::<$type>() / mem::size_of::(); + let mut res: $type = 0; + + for i in 0..WORDS { + res |= (self.value()? as $type) << (i * (mem::size_of::() * 8)) + } + + Ok(res) + } + + fn fill(&mut self, dest: &mut [$type]) -> Result<(), ErrorKind> { + let len = dest.len() * (mem::size_of::<$type>() / mem::size_of::()); + let ptr = dest.as_mut_ptr() as *mut u32; + let slice_u32 = unsafe { core::slice::from_raw_parts_mut(ptr, len) }; + self.fill(slice_u32) + } + } + )+ + }; +} + +macro_rules! rng_core_transmute { + ($($type:ty = $from:ty),+) => { + $( + impl RngCore<$type> for Rng { + fn gen(&mut self) -> Result<$type, ErrorKind> { + let num = >::gen(self)?; + Ok(unsafe { mem::transmute::<$from, $type>(num) }) + } -// Test host may have > 32-bit types, which we don't consider. + fn fill(&mut self, dest: &mut [$type]) -> Result<(), ErrorKind> { + let unsigned_slice = unsafe { mem::transmute::<&mut [$type], &mut [$from]>(dest) }; + >::fill(self, unsigned_slice) + } + } + )+ + }; +} + +rng_core!(u8, u16, u32); +rng_core_large!(u64, u128); +rng_core_transmute!( + i8 = u8, + i16 = u16, + i32 = u32, + i64 = u64, + i128 = u128, + isize = usize +); + +// If usize is 32 bits, use the rng_core! impl #[cfg(target_pointer_width = "32")] rng_core!(usize); + +// If usize is 64 bits, use the rng_core_large! impl +#[cfg(target_pointer_width = "64")] +rng_core_large!(usize); + +// rand_core +#[cfg(feature = "rand")] +impl rand_core::RngCore for Rng { + /// Generate a random u32 + /// Panics if RNG fails. + fn next_u32(&mut self) -> u32 { + self.gen().unwrap() + } + + /// Generate a random u64 + /// Panics if RNG fails. + fn next_u64(&mut self) -> u64 { + self.gen().unwrap() + } + + /// Fill a slice with random data. + /// Panics if RNG fails. + fn fill_bytes(&mut self, dest: &mut [u8]) { + self.fill(dest).unwrap() + } + + /// Try to fill a slice with random data. Return an error if RNG fails. + fn try_fill_bytes( + &mut self, + dest: &mut [u8], + ) -> Result<(), rand_core::Error> { + self.fill(dest).map_err(|e| { + core::num::NonZeroU32::new(e as u32) + // This should never fail as long as no enum variant is equal to 0 + .expect("Internal hal error") + .into() + }) + } +} From d78c3109618ef50081fab1123cdee06285e10b6d Mon Sep 17 00:00:00 2001 From: Edwin Svensson Date: Thu, 2 Dec 2021 02:29:42 +0100 Subject: [PATCH 2/4] impl rand_core::CryptoRng --- src/rng.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/rng.rs b/src/rng.rs index ed64005d..37540428 100644 --- a/src/rng.rs +++ b/src/rng.rs @@ -229,3 +229,6 @@ impl rand_core::RngCore for Rng { }) } } + +#[cfg(feature = "rand")] +impl rand_core::CryptoRng for Rng {} From 027d2e2a088e9cbb759b41b86d1055e1ef9e500d Mon Sep 17 00:00:00 2001 From: Edwin Svensson Date: Thu, 2 Dec 2021 06:51:35 +0100 Subject: [PATCH 3/4] add error code offset & add comments about alignment --- src/rng.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/rng.rs b/src/rng.rs index 37540428..735f8df6 100644 --- a/src/rng.rs +++ b/src/rng.rs @@ -177,7 +177,13 @@ macro_rules! rng_core_transmute { } rng_core!(u8, u16, u32); + +// Alignment of these types must be a multiple of mem::align_of::<32>() rng_core_large!(u64, u128); + +// A and B must have the same alignment +// rng_core_transmute!(A = B) +// assert!(mem::align_of::() == mem::align_of::()) rng_core_transmute!( i8 = u8, i16 = u16, @@ -222,10 +228,12 @@ impl rand_core::RngCore for Rng { dest: &mut [u8], ) -> Result<(), rand_core::Error> { self.fill(dest).map_err(|e| { - core::num::NonZeroU32::new(e as u32) - // This should never fail as long as no enum variant is equal to 0 - .expect("Internal hal error") - .into() + core::num::NonZeroU32::new( + rand_core::Error::CUSTOM_START + e as u32, + ) + // This should never fail as long as no enum variant is equal to 0 + .expect("Internal hal error") + .into() }) } } From c6a0d31edfad73c8abe43adcd52651ce7b1fc3fc Mon Sep 17 00:00:00 2001 From: Edwin Svensson Date: Sun, 5 Dec 2021 01:21:50 +0100 Subject: [PATCH 4/4] change enum values --- src/rng.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rng.rs b/src/rng.rs index 735f8df6..708dbe3c 100644 --- a/src/rng.rs +++ b/src/rng.rs @@ -15,8 +15,8 @@ use crate::time::Hertz; #[derive(Debug)] pub enum ErrorKind { - ClockError = 1, - SeedError = 2, + ClockError = 0, + SeedError = 1, } trait KerClk {