diff --git a/CHANGELOG.md b/CHANGELOG.md index b26ac8a5bcc..925f24bff48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add initial support for `I2S` in ESP32-H2 (#597) - Fix rom::crc docs - Add octal PSRAM support for ESP32-S3 (#610) +- Add MD5 functions from ESP ROM (#618) ### Changed diff --git a/esp-hal-common/devices/esp32.toml b/esp-hal-common/devices/esp32.toml index 1919427207a..5e7db919b67 100644 --- a/esp-hal-common/devices/esp32.toml +++ b/esp-hal-common/devices/esp32.toml @@ -61,6 +61,7 @@ peripherals = [ # ROM capabilities "rom_crc_le", "rom_crc_be", + "rom_md5_bsd", # Wakeup SOC based on ESP-IDF: "pm_support_ext0_wakeup", diff --git a/esp-hal-common/devices/esp32c2.toml b/esp-hal-common/devices/esp32c2.toml index ee7787fa3ba..419d5c6b18c 100644 --- a/esp-hal-common/devices/esp32c2.toml +++ b/esp-hal-common/devices/esp32c2.toml @@ -42,6 +42,7 @@ peripherals = [ # ROM capabilities "rom_crc_le", "rom_crc_be", + "rom_md5_mbedtls", # Wakeup SOC based on ESP-IDF: "pm_support_wifi_wakeup", diff --git a/esp-hal-common/devices/esp32c3.toml b/esp-hal-common/devices/esp32c3.toml index 9441ccc40f4..40eed2d444d 100644 --- a/esp-hal-common/devices/esp32c3.toml +++ b/esp-hal-common/devices/esp32c3.toml @@ -54,6 +54,7 @@ peripherals = [ # ROM capabilities "rom_crc_le", "rom_crc_be", + "rom_md5_bsd", # Wakeup SOC based on ESP-IDF: "pm_support_wifi_wakeup", diff --git a/esp-hal-common/devices/esp32c6.toml b/esp-hal-common/devices/esp32c6.toml index 37b861a83d3..cb1705fb406 100644 --- a/esp-hal-common/devices/esp32c6.toml +++ b/esp-hal-common/devices/esp32c6.toml @@ -83,6 +83,7 @@ peripherals = [ # ROM capabilities "rom_crc_le", "rom_crc_be", + "rom_md5_bsd", # Wakeup SOC based on ESP-IDF: "pm_support_wifi_wakeup", diff --git a/esp-hal-common/devices/esp32h2.toml b/esp-hal-common/devices/esp32h2.toml index 17ae249ed61..79c4d1a3169 100644 --- a/esp-hal-common/devices/esp32h2.toml +++ b/esp-hal-common/devices/esp32h2.toml @@ -72,4 +72,5 @@ peripherals = [ # ROM capabilities "rom_crc_le", "rom_crc_be", + "rom_md5_bsd", ] diff --git a/esp-hal-common/devices/esp32s2.toml b/esp-hal-common/devices/esp32s2.toml index 2956939c308..5534775518c 100644 --- a/esp-hal-common/devices/esp32s2.toml +++ b/esp-hal-common/devices/esp32s2.toml @@ -57,6 +57,7 @@ peripherals = [ # ROM capabilities "rom_crc_le", + "rom_md5_bsd", # Wakeup SOC based on ESP-IDF: "pm_support_ext0_wakeup", diff --git a/esp-hal-common/devices/esp32s3.toml b/esp-hal-common/devices/esp32s3.toml index 1ee9fa646db..0cafed3ebe9 100644 --- a/esp-hal-common/devices/esp32s3.toml +++ b/esp-hal-common/devices/esp32s3.toml @@ -70,6 +70,7 @@ peripherals = [ # ROM capabilities "rom_crc_le", "rom_crc_be", + "rom_md5_bsd", # Wakeup SOC based on ESP-IDF: "pm_support_ext0_wakeup", diff --git a/esp-hal-common/src/rom/md5.rs b/esp-hal-common/src/rom/md5.rs new file mode 100644 index 00000000000..cabb4cba434 --- /dev/null +++ b/esp-hal-common/src/rom/md5.rs @@ -0,0 +1,232 @@ +//! MD5 Message-Digest Algorithm +//! +//! # Security Warning +//! +//! MD5 is a **cryptographically broken** message digest. It should **not** +//! be used for data security, for example, to check if data has been +//! intentionally tampered with. +//! +//! However, it is still very useful for purposes of data **integrity**, for +//! example, to check if data has been **accidentally** tampered with, such as +//! detecting data corrupted during transmission in a stream or stored in +//! flash. This is especially important on microcontrollers where the +//! computational efficiency of MD5 is desired. +//! +//! # Compatibility +//! +//! The public API exposed by this module tries to *mimic* the public API +//! offered by the [MD5][1] crate in an effort to act as a drop-in replacement. +//! The actual implementation, however, links to whatever is available in the +//! ROM of the particular ESP32 target. Each chip target may offer a different +//! underlying MD5 implementation with varying functionality. +//! +//! This module offers a least-common-denominator API to stay consistent with +//! all of them. Usage of this module may help make program binaries smaller +//! than it would be if you included an MD5 implementation in your project. +//! +//! # Example +//! +//! To compute a full digest from a single buffer, use the following: +//! +//! ``` +//! let d: md5::Digest = md5::compute(&data); +//! writeln!(uart0, "{}", d); +//! ``` +//! +//! To compute a digest over multiple buffers: +//! +//! ``` +//! let mut ctx = md5::Context::new(); +//! ctx.consume(&data0); +//! ctx.consume(&data1); +//! let d: md5::Digest = ctx.compute(); +//! writeln!(uart0, "{}", d); +//! ``` +//! +//! [1]: + +#[allow(unused)] +use core::ffi::{c_int, c_uchar, c_void}; +use core::{ + convert::From, + fmt, + mem::MaybeUninit, + ops::{Deref, DerefMut}, +}; + +// If there is not exactly one of the MD5 variations defined in the device +// toml file then `InternalContext` will be either undefined or multiple +// defined and this module will fail to compile letting you know to fix it + +#[cfg(doc)] +struct InternalContext; + +#[cfg(rom_md5_bsd)] +#[derive(Clone)] +#[repr(C)] +struct InternalContext { + buf: [u32; 4], + bits: [u32; 2], + _in: [u8; 64], +} + +#[cfg(rom_md5_bsd)] +extern "C" { + fn esp_rom_md5_init(context: *mut InternalContext); + fn esp_rom_md5_update(context: *mut InternalContext, buf: *const c_void, len: u32); + fn esp_rom_md5_final(digest: *mut u8, context: *mut InternalContext); +} + +#[cfg(rom_md5_mbedtls)] +#[derive(Clone)] +#[repr(C)] +struct InternalContext { + total: [u32; 2], + state: [u32; 4], + buffer: [c_uchar; 64], +} + +#[cfg(rom_md5_mbedtls)] +extern "C" { + fn esp_rom_mbedtls_md5_starts_ret(context: *mut InternalContext) -> c_int; + fn esp_rom_mbedtls_md5_update_ret( + context: *mut InternalContext, + buf: *const c_void, + len: u32, + ) -> c_int; + fn esp_rom_mbedtls_md5_finish_ret(context: *mut InternalContext, digest: *mut u8) -> c_int; +} + +/// MD5 context for an ongoing computation +#[derive(Clone)] +pub struct Context(InternalContext); + +impl Context { + /// Create a new MD5 context + #[inline] + pub fn new() -> Self { + let mut ctx = MaybeUninit::::uninit(); + unsafe { + #[cfg(rom_md5_bsd)] + esp_rom_md5_init(ctx.as_mut_ptr()); + + #[cfg(rom_md5_mbedtls)] + let _ = esp_rom_mbedtls_md5_starts_ret(ctx.as_mut_ptr()); + + Self(ctx.assume_init()) + } + } + + /// Feed data to the hasher + #[inline] + pub fn consume>(&mut self, data: T) { + let data = data.as_ref(); + unsafe { + #[cfg(rom_md5_bsd)] + esp_rom_md5_update( + &mut self.0 as *mut _, + data.as_ptr() as *const c_void, + data.len() as u32, + ); + + #[cfg(rom_md5_mbedtls)] + let _ = esp_rom_mbedtls_md5_update_ret( + &mut self.0 as *mut _, + data.as_ptr() as *const c_void, + data.len() as u32, + ); + } + } + + /// Finalize and return a digest + #[inline] + pub fn compute(mut self) -> Digest { + let mut digest = MaybeUninit::<[u8; 16]>::uninit(); + unsafe { + #[cfg(rom_md5_bsd)] + esp_rom_md5_final(digest.as_mut_ptr() as *mut _, &mut self.0 as *mut _); + + #[cfg(rom_md5_mbedtls)] + let _ = esp_rom_mbedtls_md5_finish_ret( + &mut self.0 as *mut _, + digest.as_mut_ptr() as *mut _, + ); + + Digest(digest.assume_init()) + } + } +} + +/// Compute a full digest from a single buffer +#[inline] +pub fn compute>(data: T) -> Digest { + let mut ctx = Context::new(); + ctx.consume(data); + ctx.compute() +} + +/// 16-byte message digest +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +pub struct Digest(pub [u8; 16]); + +impl fmt::LowerHex for Digest { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for &byte in &self.0 { + write!(f, "{:02x}", byte)?; + } + Ok(()) + } +} + +impl fmt::UpperHex for Digest { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for &byte in &self.0 { + write!(f, "{:02X}", byte)?; + } + Ok(()) + } +} + +impl fmt::Display for Digest { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + ::fmt(self, f) + } +} + +impl fmt::Debug for Digest { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + ::fmt(self, f) + } +} + +impl From for [u8; 16] { + #[inline] + fn from(digest: Digest) -> Self { + digest.0 + } +} + +impl From for Digest { + #[inline] + fn from(context: Context) -> Digest { + context.compute() + } +} + +impl Deref for Digest { + type Target = [u8; 16]; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Digest { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} diff --git a/esp-hal-common/src/rom/mod.rs b/esp-hal-common/src/rom/mod.rs index 2cb39ef9504..f47452572bf 100644 --- a/esp-hal-common/src/rom/mod.rs +++ b/esp-hal-common/src/rom/mod.rs @@ -4,6 +4,7 @@ //! read-only memory. pub mod crc; +pub mod md5; #[allow(unused)] extern "C" { diff --git a/esp32-hal/examples/crc.rs b/esp32-hal/examples/crc.rs index 26d817be42e..cd3df918865 100644 --- a/esp32-hal/examples/crc.rs +++ b/esp32-hal/examples/crc.rs @@ -9,7 +9,7 @@ use esp32_hal::{ clock::ClockControl, peripherals::Peripherals, prelude::*, - rom::crc, + rom::{crc, md5}, timer::TimerGroup, Rtc, Uart, @@ -40,6 +40,7 @@ fn main() -> ! { timer0.start(1u64.secs()); let data = "123456789"; + let sentence = "The quick brown fox jumps over a lazy dog"; writeln!( serial0, @@ -66,10 +67,38 @@ fn main() -> ! { assert_eq!(crc_rohc, 0xd0); assert_eq!(crc_smbus, 0xf4); + // Hash the sentence one word at a time to *really* test the context + // Use Peekable while iter_intersperse is unstable + let mut md5_ctx = md5::Context::new(); + let mut it = sentence.split_whitespace().peekable(); + while let Some(word) = it.next() { + md5_ctx.consume(word); + if it.peek().is_some() { + md5_ctx.consume(" "); + } + } + let md5_digest = md5_ctx.compute(); + + assert_eq!( + md5_digest, + md5::Digest([ + 0x30, 0xde, 0xd8, 0x07, 0xd6, 0x5e, 0xe0, 0x37, 0x0f, 0xc6, 0xd7, 0x3d, 0x6a, 0xb5, + 0x5a, 0x95 + ]) + ); + writeln!( serial0, - "{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x}", - crc_hdlc, crc_bzip2, crc_mpeg2, crc_cksum, crc_kermit, crc_genibus, crc_rohc, crc_smbus + "{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x} {}", + crc_hdlc, + crc_bzip2, + crc_mpeg2, + crc_cksum, + crc_kermit, + crc_genibus, + crc_rohc, + crc_smbus, + md5_digest ) .unwrap(); diff --git a/esp32-hal/ld/rom-functions.x b/esp32-hal/ld/rom-functions.x index 77c7bb4f73f..b21a2be2b7f 100644 --- a/esp32-hal/ld/rom-functions.x +++ b/esp32-hal/ld/rom-functions.x @@ -23,3 +23,7 @@ PROVIDE (esp_rom_crc8_be = 0x4005d114); PROVIDE (esp_rom_crc32_le = 0x4005cfec); PROVIDE (esp_rom_crc16_le = 0x4005d05c); PROVIDE (esp_rom_crc8_le = 0x4005d0e0); + +PROVIDE (esp_rom_md5_init = 0x4005da7c); +PROVIDE (esp_rom_md5_update = 0x4005da9c); +PROVIDE (esp_rom_md5_final = 0x4005db1c); diff --git a/esp32c2-hal/examples/crc.rs b/esp32c2-hal/examples/crc.rs index 7c474089ae7..0521d487f3b 100644 --- a/esp32c2-hal/examples/crc.rs +++ b/esp32c2-hal/examples/crc.rs @@ -9,7 +9,7 @@ use esp32c2_hal::{ clock::ClockControl, peripherals::Peripherals, prelude::*, - rom::crc, + rom::{crc, md5}, timer::TimerGroup, Rtc, Uart, @@ -41,6 +41,7 @@ fn main() -> ! { timer0.start(1u64.secs()); let data = "123456789"; + let sentence = "The quick brown fox jumps over a lazy dog"; writeln!( serial0, @@ -67,10 +68,38 @@ fn main() -> ! { assert_eq!(crc_rohc, 0xd0); assert_eq!(crc_smbus, 0xf4); + // Hash the sentence one word at a time to *really* test the context + // Use Peekable while iter_intersperse is unstable + let mut md5_ctx = md5::Context::new(); + let mut it = sentence.split_whitespace().peekable(); + while let Some(word) = it.next() { + md5_ctx.consume(word); + if it.peek().is_some() { + md5_ctx.consume(" "); + } + } + let md5_digest = md5_ctx.compute(); + + assert_eq!( + md5_digest, + md5::Digest([ + 0x30, 0xde, 0xd8, 0x07, 0xd6, 0x5e, 0xe0, 0x37, 0x0f, 0xc6, 0xd7, 0x3d, 0x6a, 0xb5, + 0x5a, 0x95 + ]) + ); + writeln!( serial0, - "{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x}", - crc_hdlc, crc_bzip2, crc_mpeg2, crc_cksum, crc_kermit, crc_genibus, crc_rohc, crc_smbus + "{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x} {}", + crc_hdlc, + crc_bzip2, + crc_mpeg2, + crc_cksum, + crc_kermit, + crc_genibus, + crc_rohc, + crc_smbus, + md5_digest ) .unwrap(); diff --git a/esp32c2-hal/ld/rom-functions.x b/esp32c2-hal/ld/rom-functions.x index 1f0dc23a108..db797d42a00 100644 --- a/esp32c2-hal/ld/rom-functions.x +++ b/esp32c2-hal/ld/rom-functions.x @@ -12,3 +12,7 @@ PROVIDE(esp_rom_crc8_be = 0x40000810); PROVIDE(esp_rom_crc32_le = 0x400007fc); PROVIDE(esp_rom_crc16_le = 0x40000800); PROVIDE(esp_rom_crc8_le = 0x40000804); + +PROVIDE(esp_rom_mbedtls_md5_starts_ret = 0x40002be4); +PROVIDE(esp_rom_mbedtls_md5_update_ret = 0x40002be8); +PROVIDE(esp_rom_mbedtls_md5_finish_ret = 0x40002bec); diff --git a/esp32c3-hal/examples/crc.rs b/esp32c3-hal/examples/crc.rs index f11e8781444..5d92adc7ddd 100644 --- a/esp32c3-hal/examples/crc.rs +++ b/esp32c3-hal/examples/crc.rs @@ -9,7 +9,7 @@ use esp32c3_hal::{ clock::ClockControl, peripherals::Peripherals, prelude::*, - rom::crc, + rom::{crc, md5}, timer::TimerGroup, Rtc, Uart, @@ -48,6 +48,7 @@ fn main() -> ! { timer0.start(1u64.secs()); let data = "123456789"; + let sentence = "The quick brown fox jumps over a lazy dog"; writeln!( uart0, @@ -74,10 +75,38 @@ fn main() -> ! { assert_eq!(crc_rohc, 0xd0); assert_eq!(crc_smbus, 0xf4); + // Hash the sentence one word at a time to *really* test the context + // Use Peekable while iter_intersperse is unstable + let mut md5_ctx = md5::Context::new(); + let mut it = sentence.split_whitespace().peekable(); + while let Some(word) = it.next() { + md5_ctx.consume(word); + if it.peek().is_some() { + md5_ctx.consume(" "); + } + } + let md5_digest = md5_ctx.compute(); + + assert_eq!( + md5_digest, + md5::Digest([ + 0x30, 0xde, 0xd8, 0x07, 0xd6, 0x5e, 0xe0, 0x37, 0x0f, 0xc6, 0xd7, 0x3d, 0x6a, 0xb5, + 0x5a, 0x95 + ]) + ); + writeln!( uart0, - "{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x}", - crc_hdlc, crc_bzip2, crc_mpeg2, crc_cksum, crc_kermit, crc_genibus, crc_rohc, crc_smbus + "{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x} {}", + crc_hdlc, + crc_bzip2, + crc_mpeg2, + crc_cksum, + crc_kermit, + crc_genibus, + crc_rohc, + crc_smbus, + md5_digest ) .unwrap(); diff --git a/esp32c3-hal/ld/rom-functions.x b/esp32c3-hal/ld/rom-functions.x index b57ae2db17a..cd57ab6a754 100644 --- a/esp32c3-hal/ld/rom-functions.x +++ b/esp32c3-hal/ld/rom-functions.x @@ -19,3 +19,7 @@ PROVIDE(esp_rom_crc8_be = 0x4000063c); PROVIDE(esp_rom_crc32_le = 0x40000628); PROVIDE(esp_rom_crc16_le = 0x40000630); PROVIDE(esp_rom_crc8_le = 0x40000638); + +PROVIDE(esp_rom_md5_init = 0x40000614); +PROVIDE(esp_rom_md5_update = 0x40000618); +PROVIDE(esp_rom_md5_final = 0x4000061c); diff --git a/esp32c6-hal/examples/crc.rs b/esp32c6-hal/examples/crc.rs index 6f006327a99..854e6eb2067 100644 --- a/esp32c6-hal/examples/crc.rs +++ b/esp32c6-hal/examples/crc.rs @@ -9,7 +9,7 @@ use esp32c6_hal::{ clock::ClockControl, peripherals::Peripherals, prelude::*, - rom::crc, + rom::{crc, md5}, timer::TimerGroup, Rtc, Uart, @@ -48,6 +48,7 @@ fn main() -> ! { timer0.start(1u64.secs()); let data = "123456789"; + let sentence = "The quick brown fox jumps over a lazy dog"; writeln!( uart0, @@ -74,10 +75,38 @@ fn main() -> ! { assert_eq!(crc_rohc, 0xd0); assert_eq!(crc_smbus, 0xf4); + // Hash the sentence one word at a time to *really* test the context + // Use Peekable while iter_intersperse is unstable + let mut md5_ctx = md5::Context::new(); + let mut it = sentence.split_whitespace().peekable(); + while let Some(word) = it.next() { + md5_ctx.consume(word); + if it.peek().is_some() { + md5_ctx.consume(" "); + } + } + let md5_digest = md5_ctx.compute(); + + assert_eq!( + md5_digest, + md5::Digest([ + 0x30, 0xde, 0xd8, 0x07, 0xd6, 0x5e, 0xe0, 0x37, 0x0f, 0xc6, 0xd7, 0x3d, 0x6a, 0xb5, + 0x5a, 0x95 + ]) + ); + writeln!( uart0, - "{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x}", - crc_hdlc, crc_bzip2, crc_mpeg2, crc_cksum, crc_kermit, crc_genibus, crc_rohc, crc_smbus + "{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x} {}", + crc_hdlc, + crc_bzip2, + crc_mpeg2, + crc_cksum, + crc_kermit, + crc_genibus, + crc_rohc, + crc_smbus, + md5_digest ) .unwrap(); diff --git a/esp32c6-hal/ld/rom-functions.x b/esp32c6-hal/ld/rom-functions.x index 18a92ba8be9..8184f36a489 100644 --- a/esp32c6-hal/ld/rom-functions.x +++ b/esp32c6-hal/ld/rom-functions.x @@ -19,3 +19,7 @@ PROVIDE(esp_rom_crc8_be = 0x4000076c); PROVIDE(esp_rom_crc32_le = 0x40000758); PROVIDE(esp_rom_crc16_le = 0x4000075c); PROVIDE(esp_rom_crc8_le = 0x40000760); + +PROVIDE(esp_rom_md5_init = 0x4000074c); +PROVIDE(esp_rom_md5_update = 0x40000750); +PROVIDE(esp_rom_md5_final = 0x40000754); diff --git a/esp32h2-hal/examples/crc.rs b/esp32h2-hal/examples/crc.rs index 906557a1d02..423530bba74 100644 --- a/esp32h2-hal/examples/crc.rs +++ b/esp32h2-hal/examples/crc.rs @@ -9,7 +9,7 @@ use esp32h2_hal::{ clock::ClockControl, peripherals::Peripherals, prelude::*, - rom::crc, + rom::{crc, md5}, timer::TimerGroup, Rtc, Uart, @@ -49,6 +49,7 @@ fn main() -> ! { timer0.start(1u64.secs()); let data = "123456789"; + let sentence = "The quick brown fox jumps over a lazy dog"; writeln!( uart0, @@ -75,10 +76,38 @@ fn main() -> ! { assert_eq!(crc_rohc, 0xd0); assert_eq!(crc_smbus, 0xf4); + // Hash the sentence one word at a time to *really* test the context + // Use Peekable while iter_intersperse is unstable + let mut md5_ctx = md5::Context::new(); + let mut it = sentence.split_whitespace().peekable(); + while let Some(word) = it.next() { + md5_ctx.consume(word); + if it.peek().is_some() { + md5_ctx.consume(" "); + } + } + let md5_digest = md5_ctx.compute(); + + assert_eq!( + md5_digest, + md5::Digest([ + 0x30, 0xde, 0xd8, 0x07, 0xd6, 0x5e, 0xe0, 0x37, 0x0f, 0xc6, 0xd7, 0x3d, 0x6a, 0xb5, + 0x5a, 0x95 + ]) + ); + writeln!( uart0, - "{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x}", - crc_hdlc, crc_bzip2, crc_mpeg2, crc_cksum, crc_kermit, crc_genibus, crc_rohc, crc_smbus + "{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x} {}", + crc_hdlc, + crc_bzip2, + crc_mpeg2, + crc_cksum, + crc_kermit, + crc_genibus, + crc_rohc, + crc_smbus, + md5_digest ) .unwrap(); diff --git a/esp32h2-hal/ld/rom-functions.x b/esp32h2-hal/ld/rom-functions.x index 0b02f14f495..3c9c5aec860 100644 --- a/esp32h2-hal/ld/rom-functions.x +++ b/esp32h2-hal/ld/rom-functions.x @@ -19,3 +19,7 @@ PROVIDE(esp_rom_crc8_be = 0x40000738); PROVIDE(esp_rom_crc32_le = 0x40000724); PROVIDE(esp_rom_crc16_le = 0x40000728); PROVIDE(esp_rom_crc8_le = 0x4000072c); + +PROVIDE(esp_rom_md5_init = 0x40000718); +PROVIDE(esp_rom_md5_update = 0x4000071c); +PROVIDE(esp_rom_md5_final = 0x40000720); diff --git a/esp32s2-hal/examples/crc.rs b/esp32s2-hal/examples/crc.rs index 011b05d96d2..1c2b944a947 100644 --- a/esp32s2-hal/examples/crc.rs +++ b/esp32s2-hal/examples/crc.rs @@ -9,7 +9,7 @@ use esp32s2_hal::{ clock::ClockControl, peripherals::Peripherals, prelude::*, - rom::crc, + rom::{crc, md5}, timer::TimerGroup, Rtc, Uart, @@ -40,6 +40,7 @@ fn main() -> ! { timer0.start(1u64.secs()); let data = "123456789"; + let sentence = "The quick brown fox jumps over a lazy dog"; writeln!( serial0, @@ -66,10 +67,38 @@ fn main() -> ! { assert_eq!(crc_rohc, 0xd0); assert_eq!(crc_smbus, 0xf4); + // Hash the sentence one word at a time to *really* test the context + // Use Peekable while iter_intersperse is unstable + let mut md5_ctx = md5::Context::new(); + let mut it = sentence.split_whitespace().peekable(); + while let Some(word) = it.next() { + md5_ctx.consume(word); + if it.peek().is_some() { + md5_ctx.consume(" "); + } + } + let md5_digest = md5_ctx.compute(); + + assert_eq!( + md5_digest, + md5::Digest([ + 0x30, 0xde, 0xd8, 0x07, 0xd6, 0x5e, 0xe0, 0x37, 0x0f, 0xc6, 0xd7, 0x3d, 0x6a, 0xb5, + 0x5a, 0x95 + ]) + ); + writeln!( serial0, - "{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x}", - crc_hdlc, crc_bzip2, crc_mpeg2, crc_cksum, crc_kermit, crc_genibus, crc_rohc, crc_smbus + "{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x} {}", + crc_hdlc, + crc_bzip2, + crc_mpeg2, + crc_cksum, + crc_kermit, + crc_genibus, + crc_rohc, + crc_smbus, + md5_digest ) .unwrap(); diff --git a/esp32s2-hal/ld/rom-functions.x b/esp32s2-hal/ld/rom-functions.x index f5c0329e8b6..1c697c10eb3 100644 --- a/esp32s2-hal/ld/rom-functions.x +++ b/esp32s2-hal/ld/rom-functions.x @@ -23,3 +23,7 @@ PROVIDE ( esp_rom_spi_cmd_config = 0x40017c58 ); PROVIDE(esp_rom_crc32_le = 0x400119dc); PROVIDE(esp_rom_crc16_le = 0x40011a10); PROVIDE(esp_rom_crc8_le = 0x40011a4c); + +PROVIDE(esp_rom_md5_final = 0x4000530c); +PROVIDE(esp_rom_md5_init = 0x4000526c); +PROVIDE(esp_rom_md5_update = 0x4000528c); diff --git a/esp32s3-hal/examples/crc.rs b/esp32s3-hal/examples/crc.rs index 746fd83a6da..71d6b4f785b 100644 --- a/esp32s3-hal/examples/crc.rs +++ b/esp32s3-hal/examples/crc.rs @@ -9,7 +9,7 @@ use esp32s3_hal::{ clock::ClockControl, peripherals::Peripherals, prelude::*, - rom::crc, + rom::{crc, md5}, timer::TimerGroup, Rtc, Uart, @@ -40,6 +40,7 @@ fn main() -> ! { timer0.start(1u64.secs()); let data = "123456789"; + let sentence = "The quick brown fox jumps over a lazy dog"; writeln!( serial0, @@ -66,10 +67,38 @@ fn main() -> ! { assert_eq!(crc_rohc, 0xd0); assert_eq!(crc_smbus, 0xf4); + // Hash the sentence one word at a time to *really* test the context + // Use Peekable while iter_intersperse is unstable + let mut md5_ctx = md5::Context::new(); + let mut it = sentence.split_whitespace().peekable(); + while let Some(word) = it.next() { + md5_ctx.consume(word); + if it.peek().is_some() { + md5_ctx.consume(" "); + } + } + let md5_digest = md5_ctx.compute(); + + assert_eq!( + md5_digest, + md5::Digest([ + 0x30, 0xde, 0xd8, 0x07, 0xd6, 0x5e, 0xe0, 0x37, 0x0f, 0xc6, 0xd7, 0x3d, 0x6a, 0xb5, + 0x5a, 0x95 + ]) + ); + writeln!( serial0, - "{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x}", - crc_hdlc, crc_bzip2, crc_mpeg2, crc_cksum, crc_kermit, crc_genibus, crc_rohc, crc_smbus + "{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x} {}", + crc_hdlc, + crc_bzip2, + crc_mpeg2, + crc_cksum, + crc_kermit, + crc_genibus, + crc_rohc, + crc_smbus, + md5_digest ) .unwrap(); diff --git a/esp32s3-hal/ld/rom-functions.x b/esp32s3-hal/ld/rom-functions.x index e0987de8eeb..08a4832baf3 100644 --- a/esp32s3-hal/ld/rom-functions.x +++ b/esp32s3-hal/ld/rom-functions.x @@ -27,6 +27,10 @@ PROVIDE(esp_rom_crc32_le = 0x40001c98); PROVIDE(esp_rom_crc16_le = 0x40001cb0); PROVIDE(esp_rom_crc8_le = 0x40001cc8); +PROVIDE(esp_rom_md5_init = 0x40001c5c); +PROVIDE(esp_rom_md5_update = 0x40001c68); +PROVIDE(esp_rom_md5_final = 0x40001c74); + PROVIDE (esp_rom_opiflash_exec_cmd = 0x400008b8); PROVIDE( esp_rom_spi_set_dtr_swap_mode = 0x4000093c ); PROVIDE( esp_rom_opiflash_pin_config = 0x40000894 );