diff --git a/documentation/API-GUIDELINES.md b/documentation/API-GUIDELINES.md index 093ac5a2775..f706dd9802b 100644 --- a/documentation/API-GUIDELINES.md +++ b/documentation/API-GUIDELINES.md @@ -15,16 +15,16 @@ The following paragraphs contain additional recommendations. ## Construction and Destruction of Drivers -- Drivers take peripherals and pins via the `PeripheralRef` pattern - they don't consume peripherals/pins -- Consider adding a `Drop` implementation resetting the peripheral to idle state -- Consider using a builder-like pattern for configuration which must be done during initialization +- Drivers take peripherals and pins via the `PeripheralRef` pattern - they don't consume peripherals/pins. +- Consider adding a `Drop` implementation resetting the peripheral to idle state. +- Consider using a builder-like pattern for configuration which must be done during initialization. ## Interoperability -- `cfg` gated `defmt` derives and impls are added to new structs and enums +- `cfg` gated `defmt` derives and impls are added to new structs and enums. - see [this example](https://github.com/esp-rs/esp-hal/blob/df2b7bd8472cc1d18db0d9441156575570f59bb3/esp-hal/src/spi/mod.rs#L15) - e.g. `#[cfg_attr(feature = "defmt", derive(defmt::Format))]` -- Don't use `log::XXX!` macros directly - use the wrappers in `fmt.rs` (e.g. just `info!` instead of `log::info!` or importing `log::*`) +- Don't use `log::XXX!` macros directly - use the wrappers in `fmt.rs` (e.g. just `info!` instead of `log::info!` or importing `log::*`)! ## API Surface @@ -52,6 +52,7 @@ The following paragraphs contain additional recommendations. - If you are porting code from ESP-IDF (or anything else), please include a link WITH the commit hash in it, and please highlight the relevant line(s) of code - If necessary provide further context as comments (consider linking to code, PRs, TRM - make sure to use permanent links, e.g. include the hash when linking to a Git repository, include the revision, page number etc. when linking to TRMs) - Generally, follow common "good practices" and idiomatic Rust style +- All `Future` objects (public or private) must be marked with ``#[must_use = "futures do nothing unless you `.await` or poll them"]``. ## Modules Documentation @@ -77,7 +78,7 @@ Modules should have the following documentation format: //! ``` //! //! ## Implementation State -//! List unsuported features +//! List unsupported features ``` - If any of the headers is empty, remove it - When possible, use ESP-IDF docs and TRM as references and include links if possible. diff --git a/esp-hal/src/aes/mod.rs b/esp-hal/src/aes/mod.rs index f360b39111c..1070d6459fb 100644 --- a/esp-hal/src/aes/mod.rs +++ b/esp-hal/src/aes/mod.rs @@ -19,8 +19,8 @@ //! ```rust, no_run #![doc = crate::before_snippet!()] //! # use esp_hal::aes::{Aes, Mode}; -//! # let keytext = "SUp4SeCp@sSw0rd".as_bytes(); -//! # let plaintext = "message".as_bytes(); +//! # let keytext = b"SUp4SeCp@sSw0rd"; +//! # let plaintext = b"message"; //! # let mut keybuf = [0_u8; 16]; //! # keybuf[..keytext.len()].copy_from_slice(keytext); //! let mut block_buf = [0_u8; 16]; diff --git a/esp-hal/src/analog/adc/mod.rs b/esp-hal/src/analog/adc/mod.rs index ff9981d62be..45d9032735a 100644 --- a/esp-hal/src/analog/adc/mod.rs +++ b/esp-hal/src/analog/adc/mod.rs @@ -27,7 +27,6 @@ //! # use esp_hal::analog::adc::Adc; //! # use esp_hal::delay::Delay; //! # use esp_hal::gpio::Io; -//! # use core::result::Result::Err; //! //! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); #![cfg_attr(esp32, doc = "let analog_pin = io.pins.gpio32;")] diff --git a/esp-hal/src/dma/mod.rs b/esp-hal/src/dma/mod.rs index 1c174166402..270f8236e45 100644 --- a/esp-hal/src/dma/mod.rs +++ b/esp-hal/src/dma/mod.rs @@ -2716,12 +2716,12 @@ pub(crate) mod asynch { use super::*; + #[must_use = "futures do nothing unless you `.await` or poll them"] pub struct DmaTxFuture<'a, TX> where TX: Tx, { pub(crate) tx: &'a mut TX, - _a: (), } impl<'a, TX> DmaTxFuture<'a, TX> @@ -2729,7 +2729,7 @@ pub(crate) mod asynch { TX: Tx, { pub fn new(tx: &'a mut TX) -> Self { - Self { tx, _a: () } + Self { tx } } } @@ -2768,12 +2768,12 @@ pub(crate) mod asynch { } } + #[must_use = "futures do nothing unless you `.await` or poll them"] pub struct DmaRxFuture<'a, RX> where RX: Rx, { pub(crate) rx: &'a mut RX, - _a: (), } impl<'a, RX> DmaRxFuture<'a, RX> @@ -2781,7 +2781,7 @@ pub(crate) mod asynch { RX: Rx, { pub fn new(rx: &'a mut RX) -> Self { - Self { rx, _a: () } + Self { rx } } #[allow(dead_code)] // Dead on the C2 diff --git a/esp-hal/src/gpio/mod.rs b/esp-hal/src/gpio/mod.rs index bd781cb0156..1c16ea9c7dd 100644 --- a/esp-hal/src/gpio/mod.rs +++ b/esp-hal/src/gpio/mod.rs @@ -2865,6 +2865,7 @@ mod asynch { } } + #[must_use = "futures do nothing unless you `.await` or poll them"] pub struct PinFuture { pin_num: u8, } diff --git a/esp-hal/src/i2c.rs b/esp-hal/src/i2c.rs index b4c72604fea..520eaef4460 100644 --- a/esp-hal/src/i2c.rs +++ b/esp-hal/src/i2c.rs @@ -22,7 +22,6 @@ #![doc = crate::before_snippet!()] //! # use esp_hal::i2c::I2C; //! # use esp_hal::gpio::Io; -//! # use core::option::Option::None; //! # use crate::esp_hal::prelude::_fugit_RateExtU32; //! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); //! // Create a new peripheral object with the described wiring @@ -50,7 +49,6 @@ #![doc = crate::before_snippet!()] //! # use esp_hal::i2c::I2C; //! # use esp_hal::gpio::Io; -//! # use core::option::Option::None; //! # use crate::esp_hal::prelude::_fugit_RateExtU32; //! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); //! // Create a new peripheral object with the described wiring @@ -516,6 +514,7 @@ mod asynch { } #[cfg(not(esp32))] + #[must_use = "futures do nothing unless you `.await` or poll them"] pub(crate) struct I2cFuture<'a, T> where T: Instance, diff --git a/esp-hal/src/lcd_cam/mod.rs b/esp-hal/src/lcd_cam/mod.rs index 72c0ef54c9e..5bc898c8e9e 100644 --- a/esp-hal/src/lcd_cam/mod.rs +++ b/esp-hal/src/lcd_cam/mod.rs @@ -129,6 +129,7 @@ pub mod asynch { static TX_WAKER: AtomicWaker = AtomicWaker::new(); + #[must_use = "futures do nothing unless you `.await` or poll them"] pub(crate) struct LcdDoneFuture {} impl LcdDoneFuture { diff --git a/esp-hal/src/parl_io.rs b/esp-hal/src/parl_io.rs index 2d99381066a..b1d89623e07 100644 --- a/esp-hal/src/parl_io.rs +++ b/esp-hal/src/parl_io.rs @@ -1675,6 +1675,7 @@ pub mod asynch { static TX_WAKER: AtomicWaker = AtomicWaker::new(); + #[must_use = "futures do nothing unless you `.await` or poll them"] struct TxDoneFuture {} impl TxDoneFuture { diff --git a/esp-hal/src/rmt.rs b/esp-hal/src/rmt.rs index 99929bc44fd..30f6e4bbc2b 100644 --- a/esp-hal/src/rmt.rs +++ b/esp-hal/src/rmt.rs @@ -1149,6 +1149,7 @@ pub mod asynch { const INIT: AtomicWaker = AtomicWaker::new(); static WAKER: [AtomicWaker; NUM_CHANNELS] = [INIT; NUM_CHANNELS]; + #[must_use = "futures do nothing unless you `.await` or poll them"] pub(crate) struct RmtTxFuture where T: TxChannelAsync, @@ -1212,6 +1213,7 @@ pub mod asynch { } } + #[must_use = "futures do nothing unless you `.await` or poll them"] pub(crate) struct RmtRxFuture where T: RxChannelAsync, diff --git a/esp-hal/src/rsa/esp32.rs b/esp-hal/src/rsa/esp32.rs index 6cf1efde639..bb9a3796dc8 100644 --- a/esp-hal/src/rsa/esp32.rs +++ b/esp-hal/src/rsa/esp32.rs @@ -92,10 +92,12 @@ impl<'a, 'd, T: RsaMode, DM: crate::Mode, const N: usize> RsaModularMultiplicati where T: RsaMode, { - /// Creates an Instance of `RsaMultiplication`. - /// `m_prime` could be calculated using `-(modular multiplicative inverse of - /// modulus) mod 2^32`, for more information check 24.3.2 in the - /// + /// Creates an instance of `RsaMultiplication`. + /// + /// `m_prime` can be calculated using `-(modular multiplicative inverse of + /// modulus) mod 2^32`. + /// + /// For more information refer to 24.3.2 of . pub fn new(rsa: &'a mut Rsa<'d, DM>, modulus: &T::InputType, m_prime: u32) -> Self { Self::set_mode(rsa); unsafe { @@ -113,36 +115,35 @@ where rsa.write_multi_mode((N / 16 - 1) as u32) } - /// Starts the first step of modular multiplication operation. `r` could be - /// calculated using `2 ^ ( bitlength * 2 ) mod modulus`, - /// for more information check 24.3.2 in the - /// + /// Starts the first step of modular multiplication operation. + /// + /// `r` can be calculated using `2 ^ ( bitlength * 2 ) mod modulus`. + /// + /// For more information refer to 24.3.2 of . pub fn start_step1(&mut self, operand_a: &T::InputType, r: &T::InputType) { unsafe { self.rsa.write_operand_a(operand_a); self.rsa.write_r(r); } - self.set_start(); + self.start(); } /// Starts the second step of modular multiplication operation. + /// /// This is a non blocking function that returns without an error if /// operation is completed successfully. `start_step1` must be called /// before calling this function. pub fn start_step2(&mut self, operand_b: &T::InputType) { - loop { - if self.rsa.is_idle() { - self.rsa.clear_interrupt(); - unsafe { - self.rsa.write_operand_a(operand_b); - } - self.set_start(); - break; - } + while !self.rsa.is_idle() {} + + self.rsa.clear_interrupt(); + unsafe { + self.rsa.write_operand_a(operand_b); } + self.start(); } - fn set_start(&mut self) { + fn start(&mut self) { self.rsa.write_multi_start(); } } @@ -151,10 +152,12 @@ impl<'a, 'd, T: RsaMode, DM: crate::Mode, const N: usize> RsaModularExponentiati where T: RsaMode, { - /// Creates an Instance of `RsaModularExponentiation`. - /// `m_prime` could be calculated using `-(modular multiplicative inverse of - /// modulus) mod 2^32`, for more information check 24.3.2 in the - /// + /// Creates an instance of `RsaModularExponentiation`. + /// + /// `m_prime` can be calculated using `-(modular multiplicative inverse of + /// modulus) mod 2^32`. + /// + /// For more information refer to 24.3.2 of . pub fn new( rsa: &'a mut Rsa<'d, DM>, exponent: &T::InputType, @@ -179,7 +182,7 @@ where } /// Starts the modular exponentiation operation on the RSA hardware. - pub(super) fn set_start(&mut self) { + pub(super) fn start(&mut self) { self.rsa.write_modexp_start(); } } @@ -188,7 +191,7 @@ impl<'a, 'd, T: RsaMode + Multi, DM: crate::Mode, const N: usize> RsaMultiplicat where T: RsaMode, { - /// Creates an Instance of `RsaMultiplication`. + /// Creates an instance of `RsaMultiplication`. pub fn new(rsa: &'a mut Rsa<'d, DM>) -> Self { Self::set_mode(rsa); Self { @@ -203,16 +206,16 @@ where self.rsa.write_multi_operand_a(operand_a); self.rsa.write_multi_operand_b(operand_b); } - self.set_start(); + self.start(); } - /// Sets the multiplication mode for the RSA hardware. + /// Sets the multiplication mode for the RSA hardware. pub(super) fn set_mode(rsa: &mut Rsa<'d, DM>) { rsa.write_multi_mode(((N * 2) / 16 + 7) as u32) } /// Starts the multiplication operation on the RSA hardware. - pub(super) fn set_start(&mut self) { + pub(super) fn start(&mut self) { self.rsa.write_multi_start(); } } diff --git a/esp-hal/src/rsa/esp32cX.rs b/esp-hal/src/rsa/esp32cX.rs index b84135e2159..c09fa73902e 100644 --- a/esp-hal/src/rsa/esp32cX.rs +++ b/esp-hal/src/rsa/esp32cX.rs @@ -21,8 +21,10 @@ impl<'d, DM: crate::Mode> Rsa<'d, DM> { Ok(()) } - /// Enables/disables rsa interrupt, when enabled rsa perpheral would - /// generate an interrupt when a operation is finished. + /// Enables/disables rsa interrupt. + /// + /// When enabled rsa peripheral would generate an interrupt when a operation + /// is finished. pub fn enable_disable_interrupt(&mut self, enable: bool) { match enable { true => self.rsa.int_ena().write(|w| w.int_ena().set_bit()), @@ -34,10 +36,15 @@ impl<'d, DM: crate::Mode> Rsa<'d, DM> { self.rsa.mode().write(|w| unsafe { w.bits(mode) }); } - /// Enables/disables search acceleration, when enabled it would increases - /// the performance of modular exponentiation by discarding the - /// exponent's bits before the most significant set bit. Note: this might - /// affect the security, for more info refer 18.3.4 of + /// Enables/disables search acceleration. + /// + /// When enabled it would increases the performance of modular + /// exponentiation by discarding the exponent's bits before the most + /// significant set bit. + /// + /// Note: this might decrease security. + /// + /// For more information refer to 18.3.4 of pub fn enable_disable_search_acceleration(&mut self, enable: bool) { match enable { true => self @@ -63,11 +70,16 @@ impl<'d, DM: crate::Mode> Rsa<'d, DM> { .write(|w| unsafe { w.bits(search_position) }); } - /// Enables/disables constant time acceleration, when enabled it would - /// increases the performance of modular exponentiation by simplifying - /// the calculation concerning the 0 bits of the exponent i.e. lesser the - /// hamming weight, greater the performance. Note : this might affect - /// the security, for more info refer 18.3.4 of + /// Enables/disables constant time acceleration. + /// + /// When enabled it would increases the performance of modular + /// exponentiation by simplifying the calculation concerning the 0 bits + /// of the exponent. I.e. lesser the hamming weight, greater the + /// performance. + /// + /// Note: this might decrease security. + /// + /// For more information refer to 18.3.4 of . pub fn enable_disable_constant_time_acceleration(&mut self, enable: bool) { match enable { true => self @@ -228,10 +240,12 @@ impl<'a, 'd, T: RsaMode, DM: crate::Mode, const N: usize> RsaModularExponentiati where T: RsaMode, { - /// Creates an Instance of `RsaModularExponentiation`. + /// Creates an instance of `RsaModularExponentiation`. + /// /// `m_prime` could be calculated using `-(modular multiplicative inverse of - /// modulus) mod 2^32`, for more information check 19.3.1 in the - /// + /// modulus) mod 2^32`. + /// + /// For more information refer to 19.3.1 of . pub fn new( rsa: &'a mut Rsa<'d, DM>, exponent: &T::InputType, @@ -269,7 +283,7 @@ where } /// Starts the modular exponentiation operation on the RSA hardware. - pub(super) fn set_start(&mut self) { + pub(super) fn start(&mut self) { self.rsa.write_modexp_start(); } } @@ -282,10 +296,12 @@ where rsa.write_mode((N - 1) as u32) } - /// Creates an Instance of `RsaModularMultiplication`. - /// `m_prime` could be calculated using `-(modular multiplicative inverse of - /// modulus) mod 2^32`, for more information check 19.3.1 in the - /// + /// Creates an instance of `RsaModularMultiplication`. + /// + /// `m_prime` can be calculated using `-(modular multiplicative inverse of + /// modulus) mod 2^32`. + /// + /// For more information refer to 19.3.1 of . pub fn new( rsa: &'a mut Rsa<'d, DM>, operand_a: &T::InputType, @@ -306,17 +322,19 @@ where } } - /// Starts the modular multiplication operation. `r` could be calculated - /// using `2 ^ ( bitlength * 2 ) mod modulus`, for more information - /// check 19.3.1 in the + /// Starts the modular multiplication operation. + /// + /// `r` could be calculated using `2 ^ ( bitlength * 2 ) mod modulus`. + /// + /// For more information refer to 19.3.1 of . pub fn start_modular_multiplication(&mut self, r: &T::InputType) { unsafe { self.rsa.write_r(r); } - self.set_start(); + self.start(); } - fn set_start(&mut self) { + fn start(&mut self) { self.rsa.write_modmulti_start(); } } @@ -325,7 +343,7 @@ impl<'a, 'd, T: RsaMode + Multi, DM: crate::Mode, const N: usize> RsaMultiplicat where T: RsaMode, { - /// Creates an Instance of `RsaMultiplication`. + /// Creates an instance of `RsaMultiplication`. pub fn new(rsa: &'a mut Rsa<'d, DM>, operand_a: &T::InputType) -> Self { Self::set_mode(rsa); unsafe { @@ -342,16 +360,16 @@ where unsafe { self.rsa.write_multi_operand_b(operand_b); } - self.set_start(); + self.start(); } - /// Sets the multiplication mode for the RSA hardware. + /// Sets the multiplication mode for the RSA hardware. pub(super) fn set_mode(rsa: &mut Rsa<'d, DM>) { rsa.write_mode((N * 2 - 1) as u32) } /// Starts the multiplication operation on the RSA hardware. - pub(super) fn set_start(&mut self) { + pub(super) fn start(&mut self) { self.rsa.write_multi_start(); } } diff --git a/esp-hal/src/rsa/esp32sX.rs b/esp-hal/src/rsa/esp32sX.rs index bc521333e8e..aefab89a668 100644 --- a/esp-hal/src/rsa/esp32sX.rs +++ b/esp-hal/src/rsa/esp32sX.rs @@ -11,9 +11,10 @@ use crate::rsa::{ }; impl<'d, DM: crate::Mode> Rsa<'d, DM> { - /// After the RSA Accelerator is released from reset, the memory blocks + /// After the RSA accelerator is released from reset, the memory blocks /// needs to be initialized, only after that peripheral should be used. - /// This function would return without an error if the memory is initialized + /// This function would return without an error if the memory is + /// initialized. pub fn ready(&mut self) -> nb::Result<(), Infallible> { if self.rsa.clean().read().clean().bit_is_clear() { return Err(nb::Error::WouldBlock); @@ -21,8 +22,10 @@ impl<'d, DM: crate::Mode> Rsa<'d, DM> { Ok(()) } - /// Enables/disables rsa interrupt, when enabled rsa peripheral would - /// generate an interrupt when a operation is finished. + /// Enables/disables rsa interrupt. + /// + /// When enabled rsa peripheral would generate an interrupt when a operation + /// is finished. pub fn enable_disable_interrupt(&mut self, enable: bool) { match enable { true => self @@ -40,10 +43,15 @@ impl<'d, DM: crate::Mode> Rsa<'d, DM> { self.rsa.mode().write(|w| unsafe { w.bits(mode) }); } - /// Enables/disables search acceleration, when enabled it would increases - /// the performance of modular exponentiation by discarding the - /// exponent's bits before the most significant set bit. Note: this might - /// affect the security, for more info refer 18.3.4 of + /// Enables/disables search acceleration. + /// + /// When enabled it would increases the performance of modular + /// exponentiation by discarding the exponent's bits before the most + /// significant set bit. + /// + /// Note: this might decrease security. + /// + /// For more information refer to 20.3.4 of . pub fn enable_disable_search_acceleration(&mut self, enable: bool) { match enable { true => self @@ -69,11 +77,16 @@ impl<'d, DM: crate::Mode> Rsa<'d, DM> { .write(|w| unsafe { w.bits(search_position) }); } - /// Enables/disables constant time acceleration, when enabled it would - /// increases the performance of modular exponentiation by simplifying - /// the calculation concerning the 0 bits of the exponent i.e. lesser the - /// hamming weight, greater the performance. Note : this might affect - /// the security, for more info refer 18.3.4 of + /// Enables/disables constant time acceleration. + /// + /// When enabled it would increases the performance of modular + /// exponentiation by simplifying the calculation concerning the 0 bits + /// of the exponent. I.e. lesser the hamming weight, greater the + /// performance. + /// + /// Note: this might decrease security. + /// + /// For more information refer to 20.3.4 of . pub fn enable_disable_constant_time_acceleration(&mut self, enable: bool) { match enable { true => self @@ -268,10 +281,12 @@ impl<'a, 'd, T: RsaMode, DM: crate::Mode, const N: usize> RsaModularExponentiati where T: RsaMode, { - /// Creates an Instance of `RsaModularExponentiation`. - /// `m_prime` could be calculated using `-(modular multiplicative inverse of - /// modulus) mod 2^32`, for more information check 19.3.1 in the - /// + /// Creates an instance of `RsaModularExponentiation`. + /// + /// `m_prime` can be calculated using `-(modular multiplicative inverse of + /// modulus) mod 2^32`. + /// + /// For more information refer to 20.3.1 of . pub fn new( rsa: &'a mut Rsa<'d, DM>, exponent: &T::InputType, @@ -309,7 +324,7 @@ where } /// Starts the modular exponentiation operation on the RSA hardware. - pub(super) fn set_start(&mut self) { + pub(super) fn start(&mut self) { self.rsa.write_modexp_start(); } } @@ -318,10 +333,12 @@ impl<'a, 'd, T: RsaMode, DM: crate::Mode, const N: usize> RsaModularMultiplicati where T: RsaMode, { - /// Creates an Instance of `RsaModularMultiplication`. + /// Creates an instance of `RsaModularMultiplication`. + /// /// `m_prime` could be calculated using `-(modular multiplicative inverse of - /// modulus) mod 2^32`, for more information check 19.3.1 in the - /// + /// modulus) mod 2^32`. + /// + /// For more information refer to 20.3.1 of . pub fn new( rsa: &'a mut Rsa<'d, DM>, operand_a: &T::InputType, @@ -346,17 +363,19 @@ where rsa.write_mode((N - 1) as u32) } - /// Starts the modular multiplication operation. `r` could be calculated - /// using `2 ^ ( bitlength * 2 ) mod modulus`, for more information - /// check 19.3.1 in the + /// Starts the modular multiplication operation. + /// + /// `r` could be calculated using `2 ^ ( bitlength * 2 ) mod modulus`. + /// + /// For more information refer to 19.3.1 of . pub fn start_modular_multiplication(&mut self, r: &T::InputType) { unsafe { self.rsa.write_r(r); } - self.set_start(); + self.start(); } - fn set_start(&mut self) { + fn start(&mut self) { self.rsa.write_modmulti_start(); } } @@ -365,7 +384,7 @@ impl<'a, 'd, T: RsaMode + Multi, DM: crate::Mode, const N: usize> RsaMultiplicat where T: RsaMode, { - /// Creates an Instance of `RsaMultiplication`. + /// Creates an instance of `RsaMultiplication`. pub fn new(rsa: &'a mut Rsa<'d, DM>, operand_a: &T::InputType) -> Self { Self::set_mode(rsa); unsafe { @@ -382,7 +401,7 @@ where unsafe { self.rsa.write_multi_operand_b(operand_b); } - self.set_start(); + self.start(); } /// Sets the multiplication mode for the RSA hardware. @@ -391,7 +410,7 @@ where } /// Starts the multiplication operation on the RSA hardware. - pub(super) fn set_start(&mut self) { + pub(super) fn start(&mut self) { self.rsa.write_multi_start(); } } diff --git a/esp-hal/src/rsa/mod.rs b/esp-hal/src/rsa/mod.rs index 41139cf8e7f..e8c54c550b2 100644 --- a/esp-hal/src/rsa/mod.rs +++ b/esp-hal/src/rsa/mod.rs @@ -1,38 +1,31 @@ -//! # Rivest–Shamir–Adleman (RSA) Accelerator. +//! # RSA (Rivest–Shamir–Adleman) accelerator. //! //! ## Overview -//! The RSA Accelerator provides hardware support for high precision computation +//! +//! The RSA accelerator provides hardware support for high precision computation //! used in various RSA asymmetric cipher algorithms by significantly reducing //! their software complexity. Compared with RSA algorithms implemented solely //! in software, this hardware accelerator can speed up RSA algorithms //! significantly. //! //! ## Configuration -//! The RSA Accelerator also supports operands of different lengths, which -//! provides more flexibility during the computation. -//! -//! ## Usage -//! Implementation details; -//! * The driver uses low-level peripheral access to read and write data -//! from/to the `RSA` peripheral. -//! * The driver contains `unsafe` code blocks as it directly manipulates -//! memory addresses for data transfer. -//! * The driver supports different sizes of operands based on the generic -//! types provided during instantiation. -//! * The [nb] crate is used to handle non-blocking operations. -//! * The driver provides a set of high-level abstractions to simplify `RSA` -//! cryptographic operations on `ESP` chips, allowing developers to -//! leverage the `RSA accelerator` for improved performance. //! -//! This peripheral supports `async` on every available chip except of `esp32` -//! (to be solved). +//! The RSA accelerator also supports operands of different lengths, which +//! provides more flexibility during the computation. //! //! ## Examples +//! //! ### Modular Exponentiation, Modular Multiplication, and Multiplication -//! Visit the [RSA] test for an example of using the peripheral. +//! Visit the [RSA test] for an example of using the peripheral. +//! +//! ## Implementation State +//! +//! - The [nb] crate is used to handle non-blocking operations. +//! - This peripheral supports `async` on every available chip except of `esp32` +//! (to be solved). //! //! [nb]: https://docs.rs/nb/1.1.0/nb/ -//! [the repository with corresponding example]: https://github.com/esp-rs/esp-hal/blob/main/hil-test/tests/rsa.rs +//! [RSA test]: https://github.com/esp-rs/esp-hal/blob/main/hil-test/tests/rsa.rs use core::{marker::PhantomData, ptr::copy_nonoverlapping}; @@ -68,6 +61,14 @@ impl<'d, DM: crate::Mode> Rsa<'d, DM> { .unwrap(); } } + + fn read_results(&mut self, outbuf: &mut [u32; N]) { + while !self.is_idle() {} + unsafe { + self.read_out(outbuf); + } + self.clear_interrupt(); + } } impl<'d> Rsa<'d, crate::Blocking> { @@ -139,15 +140,15 @@ impl<'d, DM: crate::Mode> Rsa<'d, DM> { } } -/// Defines an RSA operation mode. +/// Defines the input size of an RSA operation. pub trait RsaMode: crate::private::Sealed { - /// The input data type used for the RSA operation. + /// The input data type used for the operation. type InputType; } -/// A trait for RSA operations that involve multiple inputs and outputs. +/// Defines the output type of RSA multiplications. pub trait Multi: RsaMode { - /// The type of the output produced by the RSA operation. + /// The type of the output produced by the operation. type OutputType; } @@ -156,16 +157,13 @@ macro_rules! implement_op { paste! { /// Represents an RSA operation for the given bit size with multi-output. pub struct []; - } - paste! { + impl Multi for [] { type OutputType = [u32; $x * 2 / 32]; } - } - paste! { + impl crate::private::Sealed for [] {} - } - paste! { + impl RsaMode for [] { type InputType = [u32; $x / 32]; } @@ -176,11 +174,9 @@ macro_rules! implement_op { paste! { /// Represents an RSA operation for the given bit size. pub struct []; - } - paste! { + impl crate::private::Sealed for [] {} - } - paste! { + impl RsaMode for [] { type InputType = [u32; $x / 32]; } @@ -208,31 +204,26 @@ impl<'a, 'd, T: RsaMode, DM: crate::Mode, const N: usize> RsaModularExponentiati where T: RsaMode, { - /// starts the modular exponentiation operation. `r` could be calculated - /// using `2 ^ ( bitlength * 2 ) mod modulus`, for more information - /// check 24.3.2 in the + /// Starts the modular exponentiation operation. + /// + /// `r` can be calculated using `2 ^ ( bitlength * 2 ) mod modulus`. + /// + /// For more information refer to 24.3.2 of . pub fn start_exponentiation(&mut self, base: &T::InputType, r: &T::InputType) { unsafe { self.rsa.write_operand_a(base); self.rsa.write_r(r); } - self.set_start(); + self.start(); } - /// reads the result to the given buffer. + /// Reads the result to the given buffer. + /// /// This is a non blocking function that returns without an error if /// operation is completed successfully. `start_exponentiation` must be /// called before calling this function. pub fn read_results(&mut self, outbuf: &mut T::InputType) { - loop { - if self.rsa.is_idle() { - unsafe { - self.rsa.read_out(outbuf); - } - self.rsa.clear_interrupt(); - break; - } - } + self.rsa.read_results(outbuf); } } @@ -253,15 +244,7 @@ where /// This is a non blocking function that returns without an error if /// operation is completed successfully. pub fn read_results(&mut self, outbuf: &mut T::InputType) { - loop { - if self.rsa.is_idle() { - unsafe { - self.rsa.read_out(outbuf); - } - self.rsa.clear_interrupt(); - break; - } - } + self.rsa.read_results(outbuf); } } @@ -286,15 +269,7 @@ where where T: Multi, { - loop { - if self.rsa.is_idle() { - unsafe { - self.rsa.read_out(outbuf); - } - self.rsa.clear_interrupt(); - break; - } - } + self.rsa.read_results(outbuf); } } @@ -317,41 +292,42 @@ pub(crate) mod asynch { static WAKER: AtomicWaker = AtomicWaker::new(); /// `Future` that waits for the RSA operation to complete. + #[must_use = "futures do nothing unless you `.await` or poll them"] pub(crate) struct RsaFuture<'d> { instance: &'d crate::peripherals::RSA, } impl<'d> RsaFuture<'d> { /// Asynchronously initializes the RSA peripheral. - pub async fn new(instance: &'d crate::peripherals::RSA) -> Self { - #[cfg(not(any(esp32, esp32s2, esp32s3)))] - instance.int_ena().modify(|_, w| w.int_ena().set_bit()); - - #[cfg(any(esp32s2, esp32s3))] - instance - .interrupt_ena() - .modify(|_, w| w.interrupt_ena().set_bit()); - - #[cfg(esp32)] - instance.interrupt().modify(|_, w| w.interrupt().set_bit()); + pub fn new(instance: &'d crate::peripherals::RSA) -> Self { + cfg_if::cfg_if! { + if #[cfg(esp32)] { + instance.interrupt().modify(|_, w| w.interrupt().set_bit()); + } else if #[cfg(any(esp32s2, esp32s3))] { + instance.interrupt_ena().modify(|_, w| w.interrupt_ena().set_bit()); + } else { + instance.int_ena().modify(|_, w| w.int_ena().set_bit()); + } + } Self { instance } } fn event_bit_is_clear(&self) -> bool { - #[cfg(not(any(esp32, esp32s2, esp32s3)))] - return self.instance.int_ena().read().int_ena().bit_is_clear(); - - #[cfg(any(esp32s2, esp32s3))] - return self - .instance - .interrupt_ena() - .read() - .interrupt_ena() - .bit_is_clear(); - - #[cfg(esp32)] - return self.instance.interrupt().read().interrupt().bit_is_clear(); + cfg_if::cfg_if! { + if #[cfg(esp32)] { + self.instance.interrupt().read().interrupt().bit_is_clear() + } else if #[cfg(any(esp32s2, esp32s3))] { + self + .instance + .interrupt_ena() + .read() + .interrupt_ena() + .bit_is_clear() + } else { + self.instance.int_ena().read().int_ena().bit_is_clear() + } + } } } diff --git a/esp-hal/src/sha.rs b/esp-hal/src/sha.rs index 20861a53951..783e0973bbe 100644 --- a/esp-hal/src/sha.rs +++ b/esp-hal/src/sha.rs @@ -33,19 +33,17 @@ #![doc = crate::before_snippet!()] //! # use esp_hal::sha::Sha; //! # use esp_hal::sha::Sha256; -//! # use core::option::Option::None; //! # use nb::block; -//! let source_data = "HELLO, ESPRESSIF!".as_bytes(); -//! let mut remaining = source_data; +//! let mut source_data = "HELLO, ESPRESSIF!".as_bytes(); //! let mut hasher = Sha256::new(); //! // Short hashes can be created by decreasing the output buffer to the //! // desired length //! let mut output = [0u8; 32]; //! -//! while remaining.len() > 0 { +//! while !source_data.is_empty() { //! // All the HW Sha functions are infallible so unwrap is fine to use if //! // you use block! -//! remaining = block!(hasher.update(remaining)).unwrap(); +//! source_data = block!(hasher.update(source_data)).unwrap(); //! } //! //! // Finish can be called as many times as desired to get multiple copies of @@ -161,20 +159,8 @@ pub trait Sha: core::ops::DerefMut> { /// Checks if the SHA peripheral is busy processing data. /// /// Returns `true` if the SHA peripheral is busy, `false` otherwise. - /// ESP32 uses a different register per hash mode. - #[cfg(esp32)] fn is_busy(&self) -> bool; - /// Checks if the SHA peripheral is busy processing data. - /// - /// Returns `true` if the SHA peripheral is busy, `false` otherwise. - #[cfg(not(esp32))] - fn is_busy(&self) -> bool { - // Safety: This is safe because we only read `SHA_BUSY_REG` - let sha = unsafe { crate::peripherals::SHA::steal() }; - sha.busy().read().bits() != 0 - } - /// Processes the data buffer and updates the hash state. /// /// This method is platform-specific and differs for ESP32 and non-ESP32 @@ -201,11 +187,8 @@ pub trait Sha: core::ops::DerefMut> { } else { // Restore previously saved hash if interleaving operation if let Some(ref saved_digest) = self.saved_digest.take() { - self.alignment_helper.volatile_write_regset( - sha.h_mem(0).as_ptr(), - saved_digest, - 64, - ); + self.alignment_helper + .volatile_write_regset(h_mem(&sha, 0), saved_digest, 64); } // SET SHA_CONTINUE_REG sha.continue_().write(|w| unsafe { w.bits(1) }); @@ -217,7 +200,7 @@ pub trait Sha: core::ops::DerefMut> { // Save the content of the current hash for interleaving operation. let mut saved_digest = [0u8; 64]; self.alignment_helper.volatile_read_regset( - sha.h_mem(0).as_ptr(), + h_mem(&sha, 0), &mut saved_digest, 64 / self.alignment_helper.align_size(), ); @@ -245,19 +228,13 @@ pub trait Sha: core::ops::DerefMut> { unsafe { core::ptr::copy_nonoverlapping( ctx.buffer.as_ptr(), - #[cfg(esp32)] - sha.text(0).as_ptr(), - #[cfg(not(esp32))] - sha.m_mem(0).as_ptr(), + m_mem(&sha, 0), (ctx.cursor % chunk_len) / ctx.alignment_helper.align_size(), ); } let flushed = ctx.alignment_helper.flush_to( - #[cfg(esp32)] - sha.text(0).as_ptr(), - #[cfg(not(esp32))] - sha.m_mem(0).as_ptr(), + m_mem(&sha, 0), (ctx.cursor % chunk_len) / ctx.alignment_helper.align_size(), ); @@ -295,14 +272,7 @@ pub trait Sha: core::ops::DerefMut> { // be fully processed then saved. unsafe { let sha = crate::peripherals::SHA::steal(); - core::ptr::copy_nonoverlapping( - self.buffer.as_ptr(), - #[cfg(esp32)] - sha.text(0).as_ptr(), - #[cfg(not(esp32))] - sha.m_mem(0).as_ptr(), - 32, - ); + core::ptr::copy_nonoverlapping(self.buffer.as_ptr(), m_mem(&sha, 0), 32); } self.process_buffer(); } @@ -336,11 +306,10 @@ pub trait Sha: core::ops::DerefMut> { // If not enough free space for length+1, add length at end of a new zero'd // block - let sha = unsafe { crate::peripherals::SHA::steal() }; - if self.is_busy() { return Err(nb::Error::WouldBlock); } + let sha = unsafe { crate::peripherals::SHA::steal() }; let chunk_len = self.chunk_length(); @@ -356,11 +325,9 @@ pub trait Sha: core::ops::DerefMut> { // buffer let pad_len = chunk_len - mod_cursor; let ctx = self.deref_mut(); + ctx.alignment_helper.volatile_write_bytes( - #[cfg(esp32)] - sha.text(0).as_ptr(), - #[cfg(not(esp32))] - sha.m_mem(0).as_ptr(), + m_mem(&sha, 0), 0_u8, pad_len / ctx.alignment_helper.align_size(), mod_cursor / ctx.alignment_helper.align_size(), @@ -378,21 +345,16 @@ pub trait Sha: core::ops::DerefMut> { let pad_len = chunk_len - mod_cursor - core::mem::size_of::(); let ctx = self.deref_mut(); + ctx.alignment_helper.volatile_write_bytes( - #[cfg(esp32)] - sha.text(0).as_ptr(), - #[cfg(not(esp32))] - sha.m_mem(0).as_ptr(), + m_mem(&sha, 0), 0_u8, pad_len / ctx.alignment_helper.align_size(), mod_cursor / ctx.alignment_helper.align_size(), ); ctx.alignment_helper.aligned_volatile_copy( - #[cfg(esp32)] - sha.text(0).as_ptr(), - #[cfg(not(esp32))] - sha.m_mem(0).as_ptr(), + m_mem(&sha, 0), &length, chunk_len / ctx.alignment_helper.align_size(), (chunk_len - core::mem::size_of::()) / ctx.alignment_helper.align_size(), @@ -411,10 +373,7 @@ pub trait Sha: core::ops::DerefMut> { } self.alignment_helper.volatile_read_regset( - #[cfg(esp32)] - sha.text(0).as_ptr(), - #[cfg(not(esp32))] - sha.h_mem(0).as_ptr(), + h_mem(&sha, 0), output, core::cmp::min(output.len(), 32) / self.alignment_helper.align_size(), ); @@ -511,11 +470,16 @@ macro_rules! impl_sha { } } - #[cfg(esp32)] fn is_busy(&self) -> bool { let sha = unsafe { crate::peripherals::SHA::steal() }; - paste::paste! { - sha.[< $name:lower _busy >]().read().[< $name:lower _busy >]().bit_is_set() + cfg_if::cfg_if! { + if #[cfg(esp32)] { + paste::paste! { + sha.[< $name:lower _busy >]().read().[< $name:lower _busy >]().bit_is_set() + } + } else { + sha.busy().read().bits() != 0 + } } } @@ -593,3 +557,23 @@ impl_sha!(Sha512, 4, 64, 128); impl_sha!(Sha512_224, 5, 28, 128); #[cfg(any(esp32s2, esp32s3))] impl_sha!(Sha512_256, 6, 32, 128); + +fn h_mem(sha: &crate::peripherals::SHA, index: usize) -> *mut u32 { + cfg_if::cfg_if! { + if #[cfg(esp32)] { + sha.text(index).as_ptr() + } else { + sha.h_mem(index).as_ptr() + } + } +} + +fn m_mem(sha: &crate::peripherals::SHA, index: usize) -> *mut u32 { + cfg_if::cfg_if! { + if #[cfg(esp32)] { + sha.text(index).as_ptr() + } else { + sha.m_mem(index).as_ptr() + } + } +} diff --git a/esp-hal/src/timer/systimer.rs b/esp-hal/src/timer/systimer.rs index d2e36f38179..6386496f310 100644 --- a/esp-hal/src/timer/systimer.rs +++ b/esp-hal/src/timer/systimer.rs @@ -1022,6 +1022,7 @@ mod asynch { const INIT: AtomicWaker = AtomicWaker::new(); static WAKERS: [AtomicWaker; NUM_ALARMS] = [INIT; NUM_ALARMS]; + #[must_use = "futures do nothing unless you `.await` or poll them"] pub(crate) struct AlarmFuture<'a, COMP: Comparator, UNIT: Unit> { alarm: &'a Alarm<'a, Periodic, crate::Async, COMP, UNIT>, } diff --git a/esp-hal/src/touch.rs b/esp-hal/src/touch.rs index 8aa5021695a..a6e59684e15 100644 --- a/esp-hal/src/touch.rs +++ b/esp-hal/src/touch.rs @@ -544,6 +544,7 @@ mod asynch { // Helper variable to store which pins need handling. static TOUCHED_PINS: AtomicU16 = AtomicU16::new(0); + #[must_use = "futures do nothing unless you `.await` or poll them"] pub struct TouchFuture { touch_nr: u8, } diff --git a/esp-hal/src/twai/mod.rs b/esp-hal/src/twai/mod.rs index 2a5ab3fbd95..b6df8150c78 100644 --- a/esp-hal/src/twai/mod.rs +++ b/esp-hal/src/twai/mod.rs @@ -31,7 +31,6 @@ //! # use esp_hal::twai::TwaiMode; //! # use esp_hal::gpio::Io; //! # use embedded_can::Frame; -//! # use core::option::Option::None; //! # use nb::block; //! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); //! // Use GPIO pins 2 and 3 to connect to the respective pins on the TWAI @@ -87,7 +86,6 @@ //! # use esp_hal::twai::TwaiMode; //! # use esp_hal::gpio::Io; //! # use embedded_can::Frame; -//! # use core::option::Option::None; //! # use nb::block; //! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); //! // Use GPIO pins 2 and 3 to connect to the respective pins on the TWAI diff --git a/esp-hal/src/uart.rs b/esp-hal/src/uart.rs index c0c05fd3fb5..7e61755db1c 100644 --- a/esp-hal/src/uart.rs +++ b/esp-hal/src/uart.rs @@ -20,7 +20,6 @@ //! //! ```rust, no_run #![doc = crate::before_snippet!()] -//! # use core::option::Option::Some; //! # use esp_hal::uart::{config::Config, Uart}; //! use esp_hal::gpio::Io; //! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); @@ -31,7 +30,7 @@ //! ``` //! //! The UART controller can be configured to invert the polarity of the pins. -//! This is achived by inverting the desired pins, and then constucting the +//! This is achived by inverting the desired pins, and then constructing the //! UART instance using the inverted pins. //! //! ## Usage @@ -60,7 +59,7 @@ //! # io.pins.gpio2, //! # ).unwrap(); //! // Write bytes out over the UART: -//! uart1.write_bytes("Hello, world!".as_bytes()).expect("write error!"); +//! uart1.write_bytes(b"Hello, world!").expect("write error!"); //! # } //! ``` //! @@ -1989,11 +1988,13 @@ mod asynch { /// Upon construction the future enables the passed interrupt and when it /// is dropped it disables the interrupt again. The future returns the event /// that was initially passed, when it resolves. + #[must_use = "futures do nothing unless you `.await` or poll them"] pub(crate) struct UartRxFuture<'d, T: Instance> { events: EnumSet, phantom: PhantomData<&'d mut T>, registered: bool, } + #[must_use = "futures do nothing unless you `.await` or poll them"] pub(crate) struct UartTxFuture<'d, T: Instance> { events: EnumSet, phantom: PhantomData<&'d mut T>, diff --git a/esp-hal/src/usb_serial_jtag.rs b/esp-hal/src/usb_serial_jtag.rs index 188e3843ae2..892ce742b10 100644 --- a/esp-hal/src/usb_serial_jtag.rs +++ b/esp-hal/src/usb_serial_jtag.rs @@ -45,7 +45,7 @@ //! let mut usb_serial = UsbSerialJtag::new(peripherals.USB_DEVICE); //! //! // Write bytes out over the USB Serial/JTAG: -//! usb_serial.write_bytes("Hello, world!".as_bytes()).expect("write error!"); +//! usb_serial.write_bytes(b"Hello, world!").expect("write error!"); //! } //! ``` //! @@ -681,6 +681,7 @@ mod asynch { static WAKER_TX: AtomicWaker = AtomicWaker::new(); static WAKER_RX: AtomicWaker = AtomicWaker::new(); + #[must_use = "futures do nothing unless you `.await` or poll them"] pub(crate) struct UsbSerialJtagWriteFuture<'d> { phantom: PhantomData<&'d mut USB_DEVICE>, } @@ -723,6 +724,7 @@ mod asynch { } } + #[must_use = "futures do nothing unless you `.await` or poll them"] pub(crate) struct UsbSerialJtagReadFuture<'d> { phantom: PhantomData<&'d mut USB_DEVICE>, } diff --git a/esp-wifi/src/ble/controller/mod.rs b/esp-wifi/src/ble/controller/mod.rs index 69d06e7df2b..0962330fe3b 100644 --- a/esp-wifi/src/ble/controller/mod.rs +++ b/esp-wifi/src/ble/controller/mod.rs @@ -158,6 +158,7 @@ pub mod asynch { } } + #[must_use = "futures do nothing unless you `.await` or poll them"] pub(crate) struct HciReadyEventFuture; impl core::future::Future for HciReadyEventFuture { diff --git a/esp-wifi/src/esp_now/mod.rs b/esp-wifi/src/esp_now/mod.rs index e272f5e3f40..f90ae622e04 100644 --- a/esp-wifi/src/esp_now/mod.rs +++ b/esp-wifi/src/esp_now/mod.rs @@ -832,14 +832,12 @@ mod asynch { /// This function takes mutable reference to self because the /// implementation of `ReceiveFuture` is not logically thread /// safe. - #[must_use] pub fn receive_async(&mut self) -> ReceiveFuture<'_> { self.receiver.receive_async() } /// The returned future must not be dropped before it's ready to avoid /// getting wrong status for sendings. - #[must_use] pub fn send_async<'s, 'r>( &'s mut self, dst_addr: &'r [u8; 6], @@ -849,6 +847,7 @@ mod asynch { } } + #[must_use = "futures do nothing unless you `.await` or poll them"] pub struct SendFuture<'s, 'r> { _sender: PhantomData<&'s mut EspNowSender<'s>>, addr: &'r [u8; 6], @@ -886,6 +885,7 @@ mod asynch { /// It's not logically safe to poll multiple instances of `ReceiveFuture` /// simultaneously since the callback can only wake one future, leaving /// the rest of them unwakable. + #[must_use = "futures do nothing unless you `.await` or poll them"] pub struct ReceiveFuture<'r>(PhantomData<&'r mut EspNowReceiver<'r>>); impl<'r> core::future::Future for ReceiveFuture<'r> { diff --git a/esp-wifi/src/wifi/mod.rs b/esp-wifi/src/wifi/mod.rs index e4771f20156..9f9063e7012 100644 --- a/esp-wifi/src/wifi/mod.rs +++ b/esp-wifi/src/wifi/mod.rs @@ -2829,6 +2829,7 @@ mod asynch { } } + #[must_use = "futures do nothing unless you `.await` or poll them"] pub(crate) struct WifiEventFuture { event: WifiEvent, } @@ -2855,6 +2856,7 @@ mod asynch { } } + #[must_use = "futures do nothing unless you `.await` or poll them"] pub(crate) struct MultiWifiEventFuture { event: EnumSet, } diff --git a/hil-test/tests/aes.rs b/hil-test/tests/aes.rs index 812a42ea8b9..3ef80264711 100644 --- a/hil-test/tests/aes.rs +++ b/hil-test/tests/aes.rs @@ -38,8 +38,8 @@ mod tests { #[test] fn test_aes_128_encryption(mut ctx: Context<'static>) { - let keytext = "SUp4SeCp@sSw0rd".as_bytes(); - let plaintext = "message".as_bytes(); + let keytext = b"SUp4SeCp@sSw0rd"; + let plaintext = b"message"; let encrypted_message = [ 0xb3, 0xc8, 0xd2, 0x3b, 0xa7, 0x36, 0x5f, 0x18, 0x61, 0x70, 0x0, 0x3e, 0xd9, 0x3a, 0x31, 0x96, @@ -58,8 +58,8 @@ mod tests { #[test] fn test_aes_128_decryption(mut ctx: Context<'static>) { - let keytext = "SUp4SeCp@sSw0rd".as_bytes(); - let plaintext = "message".as_bytes(); + let keytext = b"SUp4SeCp@sSw0rd"; + let plaintext = b"message"; let mut encrypted_message = [ 0xb3, 0xc8, 0xd2, 0x3b, 0xa7, 0x36, 0x5f, 0x18, 0x61, 0x70, 0x0, 0x3e, 0xd9, 0x3a, 0x31, 0x96, @@ -76,8 +76,8 @@ mod tests { #[test] #[cfg(any(feature = "esp32", feature = "esp32s2"))] fn test_aes_192_encryption(mut ctx: Context<'static>) { - let keytext = "SUp4SeCp@sSw0rd".as_bytes(); - let plaintext = "message".as_bytes(); + let keytext = b"SUp4SeCp@sSw0rd"; + let plaintext = b"message"; let encrypted_message = [ 0x79, 0x88, 0x3f, 0x9d, 0x67, 0x27, 0xf4, 0x18, 0x3, 0xe3, 0xc6, 0x6a, 0x2e, 0x76, 0xb6, 0xf7, @@ -97,8 +97,8 @@ mod tests { #[test] #[cfg(any(feature = "esp32", feature = "esp32s2"))] fn test_aes_192_decryption(mut ctx: Context<'static>) { - let keytext = "SUp4SeCp@sSw0rd".as_bytes(); - let plaintext = "message".as_bytes(); + let keytext = b"SUp4SeCp@sSw0rd"; + let plaintext = b"message"; let mut encrypted_message = [ 0x79, 0x88, 0x3f, 0x9d, 0x67, 0x27, 0xf4, 0x18, 0x3, 0xe3, 0xc6, 0x6a, 0x2e, 0x76, 0xb6, 0xf7, @@ -114,8 +114,8 @@ mod tests { #[test] fn test_aes_256_encryption(mut ctx: Context<'static>) { - let keytext = "SUp4SeCp@sSw0rd".as_bytes(); - let plaintext = "message".as_bytes(); + let keytext = b"SUp4SeCp@sSw0rd"; + let plaintext = b"message"; let encrypted_message = [ 0x0, 0x63, 0x3f, 0x2, 0xa4, 0x53, 0x9, 0x72, 0x20, 0x6d, 0xc9, 0x8, 0x7c, 0xe5, 0xfd, 0xc, @@ -134,8 +134,8 @@ mod tests { #[test] fn test_aes_256_decryption(mut ctx: Context<'static>) { - let keytext = "SUp4SeCp@sSw0rd".as_bytes(); - let plaintext = "message".as_bytes(); + let keytext = b"SUp4SeCp@sSw0rd"; + let plaintext = b"message"; let mut encrypted_message = [ 0x0, 0x63, 0x3f, 0x2, 0xa4, 0x53, 0x9, 0x72, 0x20, 0x6d, 0xc9, 0x8, 0x7c, 0xe5, 0xfd, 0xc, diff --git a/hil-test/tests/aes_dma.rs b/hil-test/tests/aes_dma.rs index c253af98603..63ab5f49edb 100644 --- a/hil-test/tests/aes_dma.rs +++ b/hil-test/tests/aes_dma.rs @@ -44,11 +44,11 @@ mod tests { rx_descriptors, ); - let keytext = "SUp4SeCp@sSw0rd".as_bytes(); + let keytext = b"SUp4SeCp@sSw0rd"; let mut keybuf = [0_u8; 16]; keybuf[..keytext.len()].copy_from_slice(keytext); - let plaintext = "message".as_bytes(); + let plaintext = b"message"; input[..plaintext.len()].copy_from_slice(plaintext); let encrypted_message = [ @@ -88,11 +88,11 @@ mod tests { rx_descriptors, ); - let keytext = "SUp4SeCp@sSw0rd".as_bytes(); + let keytext = b"SUp4SeCp@sSw0rd"; let mut keybuf = [0_u8; 16]; keybuf[..keytext.len()].copy_from_slice(keytext); - let plaintext = "message".as_bytes(); + let plaintext = b"message"; let encrypted_message = [ 0xb3, 0xc8, 0xd2, 0x3b, 0xa7, 0x36, 0x5f, 0x18, 0x61, 0x70, 0x0, 0x3e, 0xd9, 0x3a, 0x31, 0x96, @@ -131,11 +131,11 @@ mod tests { rx_descriptors, ); - let keytext = "SUp4SeCp@sSw0rd".as_bytes(); + let keytext = b"SUp4SeCp@sSw0rd"; let mut keybuf = [0_u8; 16]; keybuf[..keytext.len()].copy_from_slice(keytext); - let plaintext = "message".as_bytes(); + let plaintext = b"message"; input[..plaintext.len()].copy_from_slice(plaintext); let encrypted_message = [ @@ -175,11 +175,11 @@ mod tests { rx_descriptors, ); - let keytext = "SUp4SeCp@sSw0rd".as_bytes(); + let keytext = b"SUp4SeCp@sSw0rd"; let mut keybuf = [0_u8; 16]; keybuf[..keytext.len()].copy_from_slice(keytext); - let plaintext = "message".as_bytes(); + let plaintext = b"message"; let encrypted_message = [ 0x0, 0x63, 0x3f, 0x2, 0xa4, 0x53, 0x9, 0x72, 0x20, 0x6d, 0xc9, 0x8, 0x7c, 0xe5, 0xfd, 0xc, diff --git a/hil-test/tests/sha.rs b/hil-test/tests/sha.rs index a1a63a3fd2a..bdaf699d7b7 100644 --- a/hil-test/tests/sha.rs +++ b/hil-test/tests/sha.rs @@ -6,6 +6,12 @@ #![no_main] use digest::Digest; +#[cfg(not(feature = "esp32"))] +use esp_hal::sha::Sha224; +#[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] +use esp_hal::sha::{Sha384, Sha512}; +#[cfg(any(feature = "esp32s2", feature = "esp32s3"))] +use esp_hal::sha::{Sha512_224, Sha512_256}; use esp_hal::{ clock::ClockControl, peripherals::Peripherals, @@ -13,382 +19,241 @@ use esp_hal::{ rng::Rng, sha::{Sha, Sha1, Sha256}, system::SystemControl, + Blocking, }; use hil_test as _; use nb::block; -use sha1; -use sha2; /// Dummy data used to feed the hasher. -static CHAR_ARRAY: [u8; 200] = [b'a'; 200]; - -/// Dummy random data used to feed the Sha1 hasher -static mut SHA1_RANDOM_ARRAY: [u8; 256] = [0u8; 256]; - -/// Dummy random data used to feed the Sha224 hasher -static mut SHA224_RANDOM_ARRAY: [u8; 256] = [0u8; 256]; - -/// Dummy random data used to feed the Sha256 hasher -static mut SHA256_RANDOM_ARRAY: [u8; 256] = [0u8; 256]; - -/// Dummy random data used to feed the Sha384 hasher -#[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] -static mut SHA384_RANDOM_ARRAY: [u8; 256] = [0u8; 256]; - -/// Dummy random data used to feed the Sha512 hasher -#[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] -static mut SHA512_RANDOM_ARRAY: [u8; 256] = [0u8; 256]; - -#[cfg(test)] -#[embedded_test::tests] -mod tests { - use defmt::assert_eq; - - use super::*; - - #[init] - fn init() {} - - #[test] - fn test_sha_1() { - let mut sha = Sha1::new(); +const SOURCE_DATA: &[u8] = &[b'a'; 258]; - let source_data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".as_bytes(); - let mut remaining = source_data; - let expected_output = [ - 0x57, 0xf5, 0x3e, 0xd5, 0x59, 0x85, 0x24, 0x49, 0x3e, 0xc5, 0x76, 0x77, 0xa, 0xaf, - 0x3b, 0xb1, 0x0, 0x63, 0xe3, 0xce, 0xef, 0x5, 0xf8, 0xe3, 0xfe, 0x3d, 0x96, 0xa4, 0x63, - 0x29, 0xa5, 0x78, - ]; - let mut output = [0u8; 32]; +#[track_caller] +fn assert_sw_hash(input: &[u8], expected_output: &[u8]) { + let mut hasher = D::new(); + hasher.update(input); + let soft_result = hasher.finalize(); - while remaining.len() > 0 { - remaining = block!(Sha::update(&mut sha, remaining)).unwrap(); - } - block!(sha.finish(output.as_mut_slice())).unwrap(); + defmt::assert_eq!(expected_output, &soft_result[..]); +} - assert_eq!(expected_output, output); +fn hash_sha + Default>(mut input: &[u8], output: &mut [u8]) { + let mut hasher = S::default(); + while !input.is_empty() { + input = block!(Sha::update(&mut hasher, input)).unwrap(); } + block!(hasher.finish(output)).unwrap(); +} - #[test] - fn test_sha_1_digest() { - let mut sha: Sha1 = digest::Digest::new(); +fn hash_digest(input: &[u8], output: &mut [u8]) { + let mut hasher = S::new(); + digest::Digest::update(&mut hasher, input); + output.copy_from_slice(&digest::Digest::finalize(hasher)); +} - let source_data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".as_bytes(); - let expected_output = [ - 0x57, 0xf5, 0x3e, 0xd5, 0x59, 0x85, 0x24, 0x49, 0x3e, 0xc5, 0x76, 0x77, 0xa, 0xaf, - 0x3b, 0xb1, 0x0, 0x63, 0xe3, 0xce, - ]; - digest::Digest::update(&mut sha, source_data); - let output: [u8; 20] = digest::Digest::finalize(sha).into(); +/// A simple test using the Sha trait. This will compare the result with a +/// software implementation. +#[track_caller] +fn assert_sha + Default, const N: usize>(input: &[u8]) { + let mut output = [0u8; N]; + hash_sha::(input, &mut output); - assert_eq!(expected_output, output); + // Compare against Software result. + match N { + 20 => assert_sw_hash::(input, &output), + 28 => assert_sw_hash::(input, &output), + 32 => assert_sw_hash::(input, &output), + 48 => assert_sw_hash::(input, &output), + 64 => assert_sw_hash::(input, &output), + _ => unreachable!(), } +} - #[test] - #[cfg(not(feature = "esp32"))] - fn test_sha_224() { - let mut sha = esp_hal::sha::Sha224::new(); - - let source_data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".as_bytes(); - let mut remaining = source_data; - let expected_output = [ - 0x3b, 0x29, 0x33, 0xca, 0xfa, 0x6, 0xc0, 0x29, 0x68, 0x10, 0xa1, 0x3e, 0x54, 0x5f, - 0x25, 0x40, 0xa4, 0x35, 0x17, 0x3, 0x6d, 0xa2, 0xb, 0xeb, 0x8c, 0xbe, 0x79, 0x3b, - ]; - let mut output = [0u8; 28]; - - while remaining.len() > 0 { - remaining = block!(Sha::update(&mut sha, remaining)).unwrap(); - } - block!(sha.finish(output.as_mut_slice())).unwrap(); +/// A simple test using the Digest trait. This will compare the result with a +/// software implementation. +#[track_caller] +fn assert_digest(input: &[u8]) { + let mut output = [0u8; N]; + hash_digest::(input, &mut output); - assert_eq!(expected_output, output); + // Compare against Software result. + match N { + 20 => assert_sw_hash::(input, &output), + 28 => assert_sw_hash::(input, &output), + 32 => assert_sw_hash::(input, &output), + 48 => assert_sw_hash::(input, &output), + 64 => assert_sw_hash::(input, &output), + _ => unreachable!(), } +} - #[test] +fn with_random_data( + mut rng: Rng, + f: impl Fn( + (&[u8], &mut [u8]), + (&[u8], &mut [u8]), + (&[u8], &mut [u8]), + (&[u8], &mut [u8]), + (&[u8], &mut [u8]), + ), +) { + const BUFFER_LEN: usize = 256; + + let mut sha1_random = [0u8; BUFFER_LEN]; + #[cfg_attr(feature = "esp32", allow(unused_mut))] + let mut sha224_random = [0u8; BUFFER_LEN]; + let mut sha256_random = [0u8; BUFFER_LEN]; + let mut sha384_random = [0u8; BUFFER_LEN]; + let mut sha512_random = [0u8; BUFFER_LEN]; + + // Fill source data with random data + rng.read(&mut sha1_random); #[cfg(not(feature = "esp32"))] - fn test_sha_224_digest() { - let mut sha: esp_hal::sha::Sha224 = digest::Digest::new(); - - let source_data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".as_bytes(); - let expected_output = [ - 0x3b, 0x29, 0x33, 0xca, 0xfa, 0x6, 0xc0, 0x29, 0x68, 0x10, 0xa1, 0x3e, 0x54, 0x5f, - 0x25, 0x40, 0xa4, 0x35, 0x17, 0x3, 0x6d, 0xa2, 0xb, 0xeb, 0x8c, 0xbe, 0x79, 0x3b, - ]; - - digest::Digest::update(&mut sha, source_data); - let output: [u8; 28] = digest::Digest::finalize(sha).into(); - - assert_eq!(expected_output, output); - } - - #[test] - fn test_sha_256() { - let mut sha = Sha256::new(); - - let source_data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".as_bytes(); - let mut remaining = source_data; - let expected_output = [ - 0x1e, 0xbb, 0xda, 0xb3, 0x35, 0xe0, 0x54, 0x01, 0x5f, 0x0f, 0xc1, 0x7f, 0x62, 0x77, - 0x06, 0x09, 0x72, 0x3d, 0x92, 0xc6, 0x40, 0xb6, 0x5b, 0xa9, 0x97, 0x4d, 0x66, 0x6c, - 0x36, 0x4a, 0x3a, 0x63, - ]; - let mut output = [0u8; 32]; - - while remaining.len() > 0 { - remaining = block!(Sha::update(&mut sha, remaining)).unwrap(); - } - block!(sha.finish(output.as_mut_slice())).unwrap(); - - assert_eq!(expected_output, output); + { + rng.read(&mut sha224_random); } - - #[test] - fn test_sha_256_digest() { - let mut sha: Sha256 = digest::Digest::new(); - - let source_data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".as_bytes(); - let expected_output = [ - 0x1e, 0xbb, 0xda, 0xb3, 0x35, 0xe0, 0x54, 0x01, 0x5f, 0x0f, 0xc1, 0x7f, 0x62, 0x77, - 0x06, 0x09, 0x72, 0x3d, 0x92, 0xc6, 0x40, 0xb6, 0x5b, 0xa9, 0x97, 0x4d, 0x66, 0x6c, - 0x36, 0x4a, 0x3a, 0x63, - ]; - - digest::Digest::update(&mut sha, source_data); - let output: [u8; 32] = digest::Digest::finalize(sha).into(); - - assert_eq!(expected_output, output); - } - - #[test] - #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - fn test_sha_384() { - let mut sha = esp_hal::sha::Sha384::new(); - - let source_data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".as_bytes(); - let mut remaining = source_data; - let expected_output = [ - 0x8a, 0x1d, 0xe0, 0x7f, 0xa9, 0xc, 0x4c, 0xbb, 0xac, 0xe4, 0x62, 0xbd, 0xd9, 0x2f, - 0x90, 0x88, 0x61, 0x69, 0x40, 0xc0, 0x55, 0x6b, 0x80, 0x6, 0xaa, 0xfc, 0xd4, 0xff, - 0xc1, 0x8, 0xe9, 0xb2, - ]; - let mut output = [0u8; 32]; - - while remaining.len() > 0 { - remaining = block!(Sha::update(&mut sha, remaining)).unwrap(); - } - block!(sha.finish(output.as_mut_slice())).unwrap(); - - assert_eq!(expected_output, output); - } - - #[test] + rng.read(&mut sha256_random); #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - fn test_sha_384_digest() { - let mut sha: esp_hal::sha::Sha384 = digest::Digest::new(); - - let source_data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".as_bytes(); - let expected_output = [ - 0x8a, 0x1d, 0xe0, 0x7f, 0xa9, 0xc, 0x4c, 0xbb, 0xac, 0xe4, 0x62, 0xbd, 0xd9, 0x2f, - 0x90, 0x88, 0x61, 0x69, 0x40, 0xc0, 0x55, 0x6b, 0x80, 0x6, 0xaa, 0xfc, 0xd4, 0xff, - 0xc1, 0x8, 0xe9, 0xb2, 0xcd, 0xd8, 0xa9, 0x77, 0x36, 0x98, 0x2e, 0x36, 0x3f, 0x69, - 0xa0, 0x7a, 0x20, 0xfa, 0x1c, 0xeb, - ]; - - digest::Digest::update(&mut sha, source_data); - let output: [u8; 48] = digest::Digest::finalize(sha).into(); - - assert_eq!(expected_output, output); + { + rng.read(&mut sha384_random); + rng.read(&mut sha512_random); } - #[test] - #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - fn test_sha_512() { - let mut sha = esp_hal::sha::Sha512::new(); - - let source_data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".as_bytes(); - let mut remaining = source_data; - let expected_output = [ - 0xee, 0x8d, 0xe, 0x15, 0xde, 0xdc, 0xd8, 0xc8, 0x86, 0xa2, 0xef, 0xb1, 0xac, 0x6a, - 0x49, 0xcf, 0xd8, 0x3f, 0x67, 0x65, 0x64, 0xb3, 0x0, 0xce, 0x48, 0x51, 0x5e, 0xce, - 0x5f, 0x4b, 0xee, 0x10, - ]; - let mut output = [0u8; 32]; - - while remaining.len() > 0 { - remaining = block!(Sha::update(&mut sha, remaining)).unwrap(); + for size in [1, 64, 128, 256] { + let mut sha1_output = [0u8; 20]; + let mut sha224_output = [0u8; 28]; + let mut sha256_output = [0u8; 32]; + let mut sha384_output = [0u8; 48]; + let mut sha512_output = [0u8; 64]; + f( + (&sha1_random[..size], &mut sha1_output[..]), + (&sha224_random[..size], &mut sha224_output[..]), + (&sha256_random[..size], &mut sha256_output[..]), + (&sha384_random[..size], &mut sha384_output[..]), + (&sha512_random[..size], &mut sha512_output[..]), + ); + + // Calculate software result to compare against + // Sha1 + assert_sw_hash::(&sha1_random[..size], &sha1_output); + + // Sha224 + #[cfg(not(feature = "esp32"))] + { + assert_sw_hash::(&sha224_random[..size], &sha224_output); } - block!(sha.finish(output.as_mut_slice())).unwrap(); - assert_eq!(expected_output, output); - } - - #[test] - #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - fn test_sha_512_digest() { - let mut sha: esp_hal::sha::Sha512 = digest::Digest::new(); + // Sha256 + assert_sw_hash::(&sha256_random[..size], &sha256_output); - let source_data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".as_bytes(); - let expected_output = [ - 0xee, 0x8d, 0x0e, 0x15, 0xde, 0xdc, 0xd8, 0xc8, 0x86, 0xa2, 0xef, 0xb1, 0xac, 0x6a, - 0x49, 0xcf, 0xd8, 0x3f, 0x67, 0x65, 0x64, 0xb3, 0x00, 0xce, 0x48, 0x51, 0x5e, 0xce, - 0x5f, 0x4b, 0xee, 0x10, 0xe1, 0x1d, 0x89, 0xc2, 0x1c, 0x21, 0x81, 0x53, 0xc3, 0xb2, - 0x31, 0xab, 0x77, 0xca, 0xed, 0xc9, 0x6c, 0x24, 0xd7, 0xe5, 0x9a, 0x94, 0x86, 0x80, - 0xe1, 0x51, 0x00, 0x1a, 0xe1, 0x8c, 0xec, 0x80, - ]; - - digest::Digest::update(&mut sha, source_data); - let output: [u8; 64] = digest::Digest::finalize(sha).into(); + #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] + { + // Sha384 + assert_sw_hash::(&sha384_random[..size], &sha384_output); - assert_eq!(expected_output, output); + // Sha512 + assert_sw_hash::(&sha512_random[..size], &sha512_output); + } } +} - #[test] - #[cfg(any(feature = "esp32s2", feature = "esp32s3"))] - fn test_sha_512_224() { - let mut sha = esp_hal::sha::Sha512_224::new(); +#[cfg(test)] +#[embedded_test::tests] +mod tests { + use defmt::assert_eq; - let source_data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".as_bytes(); - let mut remaining = source_data; - let expected_output = [ - 0x19, 0xf2, 0xb3, 0x88, 0x22, 0x86, 0x94, 0x38, 0xee, 0x24, 0xc1, 0xc3, 0xb0, 0xb1, - 0x21, 0x6a, 0xf4, 0x81, 0x14, 0x8f, 0x4, 0x34, 0xfd, 0xd7, 0x54, 0x3, 0x2b, 0x88, 0xa3, - 0xc1, 0xb8, 0x60, - ]; - let mut output = [0u8; 32]; + use super::*; - while remaining.len() > 0 { - remaining = block!(Sha::update(&mut sha, remaining)).unwrap(); + #[init] + fn init() -> Rng { + let peripherals = Peripherals::take(); + let system = SystemControl::new(peripherals.SYSTEM); + cfg_if::cfg_if! { + if #[cfg(feature = "esp32")] { + // FIXME: max speed fails...? + let _clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + } else { + let _clocks = ClockControl::max(system.clock_control).freeze(); + } } - block!(sha.finish(output.as_mut_slice())).unwrap(); - assert_eq!(expected_output, output); + Rng::new(peripherals.RNG) } #[test] #[cfg(any(feature = "esp32s2", feature = "esp32s3"))] - fn test_sha_512_224_digest() { - let mut sha: esp_hal::sha::Sha512_224 = digest::Digest::new(); - - let source_data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".as_bytes(); + fn test_sha_512_224() { let expected_output = [ 0x19, 0xf2, 0xb3, 0x88, 0x22, 0x86, 0x94, 0x38, 0xee, 0x24, 0xc1, 0xc3, 0xb0, 0xb1, 0x21, 0x6a, 0xf4, 0x81, 0x14, 0x8f, 0x4, 0x34, 0xfd, 0xd7, 0x54, 0x3, 0x2b, 0x88, ]; + let mut output = [0u8; 28]; + hash_sha::>(SOURCE_DATA, &mut output); + assert_eq!(output, expected_output); - digest::Digest::update(&mut sha, source_data); - let output: [u8; 28] = digest::Digest::finalize(sha).into(); - - assert_eq!(expected_output, output); + let mut output = [0u8; 28]; + hash_digest::>(SOURCE_DATA, &mut output); + assert_eq!(output, expected_output); } #[test] #[cfg(any(feature = "esp32s2", feature = "esp32s3"))] fn test_sha_512_256() { - let mut sha = esp_hal::sha::Sha512_256::new(); - - let source_data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".as_bytes(); - let mut remaining = source_data; let expected_output = [ 0xb7, 0x49, 0x4e, 0xe1, 0xdb, 0xcd, 0xe5, 0x47, 0x5a, 0x61, 0x25, 0xac, 0x27, 0xc2, 0x1b, 0x53, 0xcd, 0x6b, 0x16, 0x33, 0xb4, 0x94, 0xac, 0xa4, 0x2a, 0xe6, 0x99, 0x2f, 0xe7, 0xd, 0x83, 0x19, ]; let mut output = [0u8; 32]; + hash_sha::>(SOURCE_DATA, &mut output); + assert_eq!(output, expected_output); - while remaining.len() > 0 { - remaining = block!(Sha::update(&mut sha, remaining)).unwrap(); - } - block!(sha.finish(output.as_mut_slice())).unwrap(); - - assert_eq!(expected_output, output); - } - - #[test] - #[cfg(any(feature = "esp32s2", feature = "esp32s3"))] - fn test_sha_512_256_digest() { - let mut sha: esp_hal::sha::Sha512_256 = digest::Digest::new(); - - let source_data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".as_bytes(); - let expected_output = [ - 0xb7, 0x49, 0x4e, 0xe1, 0xdb, 0xcd, 0xe5, 0x47, 0x5a, 0x61, 0x25, 0xac, 0x27, 0xc2, - 0x1b, 0x53, 0xcd, 0x6b, 0x16, 0x33, 0xb4, 0x94, 0xac, 0xa4, 0x2a, 0xe6, 0x99, 0x2f, - 0xe7, 0xd, 0x83, 0x19, - ]; - - digest::Digest::update(&mut sha, source_data); - let output: [u8; 32] = digest::Digest::finalize(sha).into(); - - assert_eq!(expected_output, output); + let mut output = [0u8; 32]; + hash_digest::>(SOURCE_DATA, &mut output); + assert_eq!(output, expected_output); } - /// A test that runs a hashing on a digest of every size between 1 and 256 + /// A test that runs a hashing on a digest of every size between 1 and 200 /// inclusively. #[test] fn test_digest_of_size_1_to_200() { for i in 1..=200 { - test_for_size::, 20>(i); + assert_sha::, 20>(&SOURCE_DATA[..i]); + assert_digest::, 20>(&SOURCE_DATA[..i]); + #[cfg(not(feature = "esp32"))] - test_for_size::, 28>(i); - test_for_size::, 32>(i); - #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - test_for_size::, 48>(i); + { + assert_sha::, 28>(&SOURCE_DATA[..i]); + assert_digest::, 28>(&SOURCE_DATA[..i]); + } + + assert_sha::, 32>(&SOURCE_DATA[..i]); + assert_digest::, 32>(&SOURCE_DATA[..i]); + #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - test_for_size::, 64>(i); + { + assert_sha::, 48>(&SOURCE_DATA[..i]); + assert_digest::, 48>(&SOURCE_DATA[..i]); + + assert_sha::, 64>(&SOURCE_DATA[..i]); + assert_digest::, 64>(&SOURCE_DATA[..i]); + } } } /// A rolling test that loops between hasher for every step to test /// interleaving. This specifically test the Sha trait implementation #[test] - fn test_sha_rolling() { - let peripherals = Peripherals::take(); - let system = SystemControl::new(peripherals.SYSTEM); - let _clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - - let mut rng = Rng::new(peripherals.RNG); - - // Fill source data with random data - use core::ptr::addr_of_mut; - for slice in unsafe { - [ - addr_of_mut!(SHA1_RANDOM_ARRAY), - addr_of_mut!(SHA224_RANDOM_ARRAY), - addr_of_mut!(SHA256_RANDOM_ARRAY), - #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - addr_of_mut!(SHA384_RANDOM_ARRAY), - #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - addr_of_mut!(SHA512_RANDOM_ARRAY), - ] - } { - rng.read(unsafe { &mut *slice }); - } - - for size in [1, 64, 128, 256] { - // Use different random data for each hasher. - let sha1_source_data = - unsafe { core::slice::from_raw_parts(SHA1_RANDOM_ARRAY.as_ptr(), size) }; - #[cfg(not(feature = "esp32"))] - let sha224_source_data = - unsafe { core::slice::from_raw_parts(SHA224_RANDOM_ARRAY.as_ptr(), size) }; - let sha256_source_data = - unsafe { core::slice::from_raw_parts(SHA256_RANDOM_ARRAY.as_ptr(), size) }; - #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - let sha384_source_data = - unsafe { core::slice::from_raw_parts(SHA384_RANDOM_ARRAY.as_ptr(), size) }; - #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - let sha512_source_data = - unsafe { core::slice::from_raw_parts(SHA512_RANDOM_ARRAY.as_ptr(), size) }; - - let mut sha1_remaining = sha1_source_data; + fn test_sha_rolling(rng: Rng) { + #[allow(unused)] + with_random_data(rng, |sha1_p, sha224_p, sha256_p, sha384_p, sha512_p| { + let mut sha1_remaining = sha1_p.0; #[cfg(not(feature = "esp32"))] - let mut sha224_remaining = sha224_source_data; - let mut sha256_remaining = sha256_source_data; + let mut sha224_remaining = sha224_p.0; + let mut sha256_remaining = sha256_p.0; #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - let mut sha384_remaining = sha384_source_data; + let mut sha384_remaining = sha384_p.0; #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - let mut sha512_remaining = sha512_source_data; + let mut sha512_remaining = sha512_p.0; let mut sha1 = esp_hal::sha::Sha1::default(); #[cfg(not(feature = "esp32"))] @@ -399,272 +264,96 @@ mod tests { #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] let mut sha512 = esp_hal::sha::Sha512::default(); - // All sources are the same length - while sha1_remaining.len() > 0 { - sha1_remaining = block!(Sha::update(&mut sha1, sha1_remaining)).unwrap(); + loop { + let mut all_done = true; + if !sha1_remaining.is_empty() { + sha1_remaining = block!(Sha::update(&mut sha1, sha1_remaining)).unwrap(); + all_done = false; + } #[cfg(not(feature = "esp32"))] - { + if !sha224_remaining.is_empty() { sha224_remaining = block!(Sha::update(&mut sha224, sha224_remaining)).unwrap(); + all_done = false; } - sha256_remaining = block!(Sha::update(&mut sha256, sha256_remaining)).unwrap(); + + if !sha256_remaining.is_empty() { + sha256_remaining = block!(Sha::update(&mut sha256, sha256_remaining)).unwrap(); + all_done = false; + } + #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] { - sha384_remaining = block!(Sha::update(&mut sha384, sha384_remaining)).unwrap(); - sha512_remaining = block!(Sha::update(&mut sha512, sha512_remaining)).unwrap(); + if !sha384_remaining.is_empty() { + sha384_remaining = + block!(Sha::update(&mut sha384, sha384_remaining)).unwrap(); + all_done = false; + } + + if !sha512_remaining.is_empty() { + sha512_remaining = + block!(Sha::update(&mut sha512, sha512_remaining)).unwrap(); + all_done = false; + } } - } - let mut sha1_output = [0u8; 20]; - block!(sha1.finish(sha1_output.as_mut_slice())).unwrap(); - #[cfg(not(feature = "esp32"))] - let mut sha224_output = [0u8; 28]; - #[cfg(not(feature = "esp32"))] - block!(sha224.finish(sha224_output.as_mut_slice())).unwrap(); - let mut sha256_output = [0u8; 32]; - block!(sha256.finish(sha256_output.as_mut_slice())).unwrap(); - #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - let mut sha384_output = [0u8; 48]; - #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - block!(sha384.finish(sha384_output.as_mut_slice())).unwrap(); - #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - let mut sha512_output = [0u8; 64]; - #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - block!(sha512.finish(sha512_output.as_mut_slice())).unwrap(); - - // Calculate software result to compare against - // Sha1 - let mut sha1_sw = sha1::Sha1::new(); - sha1_sw.update(sha1_source_data); - let soft_result = sha1_sw.finalize(); - for (a, b) in sha1_output.iter().zip(soft_result) { - assert_eq!(*a, b); - } - - // Sha224 - #[cfg(not(feature = "esp32"))] - { - let mut sha224_sw = sha2::Sha224::new(); - sha224_sw.update(sha224_source_data); - let soft_result = sha224_sw.finalize(); - for (a, b) in sha224_output.iter().zip(soft_result) { - assert_eq!(*a, b); + if all_done { + break; } } - // Sha256 - let mut sha256_sw = sha2::Sha256::new(); - sha256_sw.update(sha256_source_data); - let soft_result = sha256_sw.finalize(); - for (a, b) in sha256_output.iter().zip(soft_result) { - assert_eq!(*a, b); - } - - // Sha384 - #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] + block!(sha1.finish(sha1_p.1)).unwrap(); + #[cfg(not(feature = "esp32"))] { - let mut sha384_sw = sha2::Sha384::new(); - sha384_sw.update(sha384_source_data); - let soft_result = sha384_sw.finalize(); - for (a, b) in sha384_output.iter().zip(soft_result) { - assert_eq!(*a, b); - } + block!(sha224.finish(sha224_p.1)).unwrap(); } - - // Sha512 + block!(sha256.finish(sha256_p.1)).unwrap(); #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] { - let mut sha512_sw = sha2::Sha512::new(); - sha512_sw.update(sha512_source_data); - let soft_result = sha512_sw.finalize(); - for (a, b) in sha512_output.iter().zip(soft_result) { - assert_eq!(*a, b); - } + block!(sha384.finish(sha384_p.1)).unwrap(); + block!(sha512.finish(sha512_p.1)).unwrap(); } - } + }); } /// A rolling test that loops between hasher for every step to test /// interleaving. This specifically test the Digest trait implementation #[test] - fn test_for_digest_rolling() { - let peripherals = Peripherals::take(); - let system = SystemControl::new(peripherals.SYSTEM); - let _clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - - let mut rng = Rng::new(peripherals.RNG); - - // Fill source data with random data - use core::ptr::addr_of_mut; - for slice in unsafe { - [ - addr_of_mut!(SHA1_RANDOM_ARRAY), - addr_of_mut!(SHA224_RANDOM_ARRAY), - addr_of_mut!(SHA256_RANDOM_ARRAY), - #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - addr_of_mut!(SHA384_RANDOM_ARRAY), - #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - addr_of_mut!(SHA512_RANDOM_ARRAY), - ] - } { - rng.read(unsafe { &mut *slice }); - } - - for size in [1, 64, 128, 256] { - // Use different random data for each hasher. - let sha1_source_data = - unsafe { core::slice::from_raw_parts(SHA1_RANDOM_ARRAY.as_ptr(), size) }; - #[cfg(not(feature = "esp32"))] - let sha224_source_data = - unsafe { core::slice::from_raw_parts(SHA224_RANDOM_ARRAY.as_ptr(), size) }; - let sha256_source_data = - unsafe { core::slice::from_raw_parts(SHA256_RANDOM_ARRAY.as_ptr(), size) }; - #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - let sha384_source_data = - unsafe { core::slice::from_raw_parts(SHA384_RANDOM_ARRAY.as_ptr(), size) }; - #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - let sha512_source_data = - unsafe { core::slice::from_raw_parts(SHA512_RANDOM_ARRAY.as_ptr(), size) }; - - let mut sha1 = esp_hal::sha::Sha1::default(); - #[cfg(not(feature = "esp32"))] - let mut sha224 = esp_hal::sha::Sha224::default(); - let mut sha256 = esp_hal::sha::Sha256::default(); - #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - let mut sha384 = esp_hal::sha::Sha384::default(); - #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - let mut sha512 = esp_hal::sha::Sha512::default(); - + fn test_for_digest_rolling(rng: Rng) { + #[allow(unused)] + with_random_data(rng, |sha1_p, sha224_p, sha256_p, sha384_p, sha512_p| { // The Digest::update will consume the entirety of remaining. We don't need to // loop until remaining is fully consumed. - Digest::update(&mut sha1, sha1_source_data); - #[cfg(not(feature = "esp32"))] - Digest::update(&mut sha224, sha224_source_data); - Digest::update(&mut sha256, sha256_source_data); - #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - Digest::update(&mut sha384, sha384_source_data); - #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - Digest::update(&mut sha512, sha512_source_data); - let sha1_output: [u8; 20] = Digest::finalize(sha1).into(); - #[cfg(not(feature = "esp32"))] - let sha224_output: [u8; 28] = Digest::finalize(sha224).into(); - let sha256_output: [u8; 32] = Digest::finalize(sha256).into(); - #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - let sha384_output: [u8; 48] = Digest::finalize(sha384).into(); - #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - let sha512_output: [u8; 64] = Digest::finalize(sha512).into(); - - // Calculate software result to compare against - // Sha1 - let mut sha1_sw = sha1::Sha1::new(); - sha1_sw.update(sha1_source_data); - let soft_result = sha1_sw.finalize(); - for (a, b) in sha1_output.iter().zip(soft_result) { - assert_eq!(*a, b); - } + let mut sha1 = esp_hal::sha::Sha1::default(); + Digest::update(&mut sha1, sha1_p.0); + let sha1_output = Digest::finalize(sha1); + sha1_p.1.copy_from_slice(&sha1_output); - // Sha224 #[cfg(not(feature = "esp32"))] { - let mut sha224_sw = sha2::Sha224::new(); - sha224_sw.update(sha224_source_data); - let soft_result = sha224_sw.finalize(); - for (a, b) in sha224_output.iter().zip(soft_result) { - assert_eq!(*a, b); - } + let mut sha224 = esp_hal::sha::Sha224::default(); + Digest::update(&mut sha224, sha224_p.0); + let sha224_output = Digest::finalize(sha224); + sha224_p.1.copy_from_slice(&sha224_output); } - // Sha256 - let mut sha256_sw = sha2::Sha256::new(); - sha256_sw.update(sha256_source_data); - let soft_result = sha256_sw.finalize(); - for (a, b) in sha256_output.iter().zip(soft_result) { - assert_eq!(*a, b); - } - - // Sha384 - #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] - { - let mut sha384_sw = sha2::Sha384::new(); - sha384_sw.update(sha384_source_data); - let soft_result = sha384_sw.finalize(); - for (a, b) in sha384_output.iter().zip(soft_result) { - assert_eq!(*a, b); - } - } + let mut sha256 = esp_hal::sha::Sha256::default(); + Digest::update(&mut sha256, sha256_p.0); + let sha256_output = Digest::finalize(sha256); + sha256_p.1.copy_from_slice(&sha256_output); - // Sha512 #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] { - let mut sha512_sw = sha2::Sha512::new(); - sha512_sw.update(sha512_source_data); - let soft_result = sha512_sw.finalize(); - for (a, b) in sha512_output.iter().zip(soft_result) { - assert_eq!(*a, b); - } + let mut sha384 = esp_hal::sha::Sha384::default(); + Digest::update(&mut sha384, sha384_p.0); + let sha384_output = Digest::finalize(sha384); + sha384_p.1.copy_from_slice(&sha384_output); + + let mut sha512 = esp_hal::sha::Sha512::default(); + Digest::update(&mut sha512, sha512_p.0); + let sha512_output = Digest::finalize(sha512); + sha512_p.1.copy_from_slice(&sha512_output); } - } - } -} - -/// A simple test using [esp_hal::sha::Sha] trait to test hashing for an -/// algorithm against a specific size. This will compare the result with a -/// software implementation and return false if there's a mismatch -fn test_for_size, const N: usize>(size: usize) { - let source_data = unsafe { core::slice::from_raw_parts(CHAR_ARRAY.as_ptr(), size) }; - let mut remaining = source_data; - let mut hasher = D::default(); - - let mut output = [0u8; N]; - - while remaining.len() > 0 { - remaining = block!(Sha::update(&mut hasher, &remaining)).unwrap(); + }); } - - block!(hasher.finish(output.as_mut_slice())).unwrap(); - - // Compare against Software result. - match N { - 20 => { - let mut hasher = sha1::Sha1::new(); - hasher.update(source_data); - let soft_result = hasher.finalize(); - for (a, b) in output.iter().zip(soft_result) { - assert_eq!(*a, b); - } - } - 28 => { - let mut hasher = sha2::Sha224::new(); - hasher.update(source_data); - let soft_result = hasher.finalize(); - for (a, b) in output.iter().zip(soft_result) { - assert_eq!(*a, b); - } - } - 32 => { - let mut hasher = sha2::Sha256::new(); - hasher.update(source_data); - let soft_result = hasher.finalize(); - for (a, b) in output.iter().zip(soft_result) { - assert_eq!(*a, b); - } - } - 48 => { - let mut hasher = sha2::Sha384::new(); - hasher.update(source_data); - let soft_result = hasher.finalize(); - for (a, b) in output.iter().zip(soft_result) { - assert_eq!(*a, b); - } - } - 64 => { - let mut hasher = sha2::Sha512::new(); - hasher.update(source_data); - let soft_result = hasher.finalize(); - for (a, b) in output.iter().zip(soft_result) { - assert_eq!(*a, b); - } - } - _ => unreachable!(), - }; }