Add MD5 functionality from ESP ROM (#618)

* Add ROM MD5 definitions in linker and devices

* Add initial MD5 support

* Implement traits and add comments to MD5 module

* Add MD5 example to ESP32-C3

* Test MD5 context on the quick brown fox

* Implemenr From<Context> for Digest

* Add MD5 to the rest of the examples

* Add docs for MD5

* Remove #[repr(transparent)] from md5::Digest

* Update CHANGELOG.md
This commit is contained in:
Jordan Halase 2023-06-26 02:01:34 -05:00 committed by Scott Mabin
parent b5fe37e6e7
commit 28fafa05e1
24 changed files with 493 additions and 21 deletions

View File

@ -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) - Add initial support for `I2S` in ESP32-H2 (#597)
- Fix rom::crc docs - Fix rom::crc docs
- Add octal PSRAM support for ESP32-S3 (#610) - Add octal PSRAM support for ESP32-S3 (#610)
- Add MD5 functions from ESP ROM (#618)
### Changed ### Changed

View File

@ -61,6 +61,7 @@ peripherals = [
# ROM capabilities # ROM capabilities
"rom_crc_le", "rom_crc_le",
"rom_crc_be", "rom_crc_be",
"rom_md5_bsd",
# Wakeup SOC based on ESP-IDF: # Wakeup SOC based on ESP-IDF:
"pm_support_ext0_wakeup", "pm_support_ext0_wakeup",

View File

@ -42,6 +42,7 @@ peripherals = [
# ROM capabilities # ROM capabilities
"rom_crc_le", "rom_crc_le",
"rom_crc_be", "rom_crc_be",
"rom_md5_mbedtls",
# Wakeup SOC based on ESP-IDF: # Wakeup SOC based on ESP-IDF:
"pm_support_wifi_wakeup", "pm_support_wifi_wakeup",

View File

@ -54,6 +54,7 @@ peripherals = [
# ROM capabilities # ROM capabilities
"rom_crc_le", "rom_crc_le",
"rom_crc_be", "rom_crc_be",
"rom_md5_bsd",
# Wakeup SOC based on ESP-IDF: # Wakeup SOC based on ESP-IDF:
"pm_support_wifi_wakeup", "pm_support_wifi_wakeup",

View File

@ -83,6 +83,7 @@ peripherals = [
# ROM capabilities # ROM capabilities
"rom_crc_le", "rom_crc_le",
"rom_crc_be", "rom_crc_be",
"rom_md5_bsd",
# Wakeup SOC based on ESP-IDF: # Wakeup SOC based on ESP-IDF:
"pm_support_wifi_wakeup", "pm_support_wifi_wakeup",

View File

@ -72,4 +72,5 @@ peripherals = [
# ROM capabilities # ROM capabilities
"rom_crc_le", "rom_crc_le",
"rom_crc_be", "rom_crc_be",
"rom_md5_bsd",
] ]

View File

@ -57,6 +57,7 @@ peripherals = [
# ROM capabilities # ROM capabilities
"rom_crc_le", "rom_crc_le",
"rom_md5_bsd",
# Wakeup SOC based on ESP-IDF: # Wakeup SOC based on ESP-IDF:
"pm_support_ext0_wakeup", "pm_support_ext0_wakeup",

View File

@ -70,6 +70,7 @@ peripherals = [
# ROM capabilities # ROM capabilities
"rom_crc_le", "rom_crc_le",
"rom_crc_be", "rom_crc_be",
"rom_md5_bsd",
# Wakeup SOC based on ESP-IDF: # Wakeup SOC based on ESP-IDF:
"pm_support_ext0_wakeup", "pm_support_ext0_wakeup",

View File

@ -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]: <https://crates.io/crates/md5>
#[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::<InternalContext>::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<T: AsRef<[u8]>>(&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<T: AsRef<[u8]>>(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 {
<Digest as fmt::LowerHex>::fmt(self, f)
}
}
impl fmt::Debug for Digest {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<Digest as fmt::LowerHex>::fmt(self, f)
}
}
impl From<Digest> for [u8; 16] {
#[inline]
fn from(digest: Digest) -> Self {
digest.0
}
}
impl From<Context> 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
}
}

View File

@ -4,6 +4,7 @@
//! read-only memory. //! read-only memory.
pub mod crc; pub mod crc;
pub mod md5;
#[allow(unused)] #[allow(unused)]
extern "C" { extern "C" {

View File

@ -9,7 +9,7 @@ use esp32_hal::{
clock::ClockControl, clock::ClockControl,
peripherals::Peripherals, peripherals::Peripherals,
prelude::*, prelude::*,
rom::crc, rom::{crc, md5},
timer::TimerGroup, timer::TimerGroup,
Rtc, Rtc,
Uart, Uart,
@ -40,6 +40,7 @@ fn main() -> ! {
timer0.start(1u64.secs()); timer0.start(1u64.secs());
let data = "123456789"; let data = "123456789";
let sentence = "The quick brown fox jumps over a lazy dog";
writeln!( writeln!(
serial0, serial0,
@ -66,10 +67,38 @@ fn main() -> ! {
assert_eq!(crc_rohc, 0xd0); assert_eq!(crc_rohc, 0xd0);
assert_eq!(crc_smbus, 0xf4); 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!( writeln!(
serial0, serial0,
"{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x}", "{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x} {}",
crc_hdlc, crc_bzip2, crc_mpeg2, crc_cksum, crc_kermit, crc_genibus, crc_rohc, crc_smbus crc_hdlc,
crc_bzip2,
crc_mpeg2,
crc_cksum,
crc_kermit,
crc_genibus,
crc_rohc,
crc_smbus,
md5_digest
) )
.unwrap(); .unwrap();

View File

@ -23,3 +23,7 @@ PROVIDE (esp_rom_crc8_be = 0x4005d114);
PROVIDE (esp_rom_crc32_le = 0x4005cfec); PROVIDE (esp_rom_crc32_le = 0x4005cfec);
PROVIDE (esp_rom_crc16_le = 0x4005d05c); PROVIDE (esp_rom_crc16_le = 0x4005d05c);
PROVIDE (esp_rom_crc8_le = 0x4005d0e0); PROVIDE (esp_rom_crc8_le = 0x4005d0e0);
PROVIDE (esp_rom_md5_init = 0x4005da7c);
PROVIDE (esp_rom_md5_update = 0x4005da9c);
PROVIDE (esp_rom_md5_final = 0x4005db1c);

View File

@ -9,7 +9,7 @@ use esp32c2_hal::{
clock::ClockControl, clock::ClockControl,
peripherals::Peripherals, peripherals::Peripherals,
prelude::*, prelude::*,
rom::crc, rom::{crc, md5},
timer::TimerGroup, timer::TimerGroup,
Rtc, Rtc,
Uart, Uart,
@ -41,6 +41,7 @@ fn main() -> ! {
timer0.start(1u64.secs()); timer0.start(1u64.secs());
let data = "123456789"; let data = "123456789";
let sentence = "The quick brown fox jumps over a lazy dog";
writeln!( writeln!(
serial0, serial0,
@ -67,10 +68,38 @@ fn main() -> ! {
assert_eq!(crc_rohc, 0xd0); assert_eq!(crc_rohc, 0xd0);
assert_eq!(crc_smbus, 0xf4); 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!( writeln!(
serial0, serial0,
"{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x}", "{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x} {}",
crc_hdlc, crc_bzip2, crc_mpeg2, crc_cksum, crc_kermit, crc_genibus, crc_rohc, crc_smbus crc_hdlc,
crc_bzip2,
crc_mpeg2,
crc_cksum,
crc_kermit,
crc_genibus,
crc_rohc,
crc_smbus,
md5_digest
) )
.unwrap(); .unwrap();

View File

@ -12,3 +12,7 @@ PROVIDE(esp_rom_crc8_be = 0x40000810);
PROVIDE(esp_rom_crc32_le = 0x400007fc); PROVIDE(esp_rom_crc32_le = 0x400007fc);
PROVIDE(esp_rom_crc16_le = 0x40000800); PROVIDE(esp_rom_crc16_le = 0x40000800);
PROVIDE(esp_rom_crc8_le = 0x40000804); 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);

View File

@ -9,7 +9,7 @@ use esp32c3_hal::{
clock::ClockControl, clock::ClockControl,
peripherals::Peripherals, peripherals::Peripherals,
prelude::*, prelude::*,
rom::crc, rom::{crc, md5},
timer::TimerGroup, timer::TimerGroup,
Rtc, Rtc,
Uart, Uart,
@ -48,6 +48,7 @@ fn main() -> ! {
timer0.start(1u64.secs()); timer0.start(1u64.secs());
let data = "123456789"; let data = "123456789";
let sentence = "The quick brown fox jumps over a lazy dog";
writeln!( writeln!(
uart0, uart0,
@ -74,10 +75,38 @@ fn main() -> ! {
assert_eq!(crc_rohc, 0xd0); assert_eq!(crc_rohc, 0xd0);
assert_eq!(crc_smbus, 0xf4); 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!( writeln!(
uart0, uart0,
"{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x}", "{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x} {}",
crc_hdlc, crc_bzip2, crc_mpeg2, crc_cksum, crc_kermit, crc_genibus, crc_rohc, crc_smbus crc_hdlc,
crc_bzip2,
crc_mpeg2,
crc_cksum,
crc_kermit,
crc_genibus,
crc_rohc,
crc_smbus,
md5_digest
) )
.unwrap(); .unwrap();

View File

@ -19,3 +19,7 @@ PROVIDE(esp_rom_crc8_be = 0x4000063c);
PROVIDE(esp_rom_crc32_le = 0x40000628); PROVIDE(esp_rom_crc32_le = 0x40000628);
PROVIDE(esp_rom_crc16_le = 0x40000630); PROVIDE(esp_rom_crc16_le = 0x40000630);
PROVIDE(esp_rom_crc8_le = 0x40000638); PROVIDE(esp_rom_crc8_le = 0x40000638);
PROVIDE(esp_rom_md5_init = 0x40000614);
PROVIDE(esp_rom_md5_update = 0x40000618);
PROVIDE(esp_rom_md5_final = 0x4000061c);

View File

@ -9,7 +9,7 @@ use esp32c6_hal::{
clock::ClockControl, clock::ClockControl,
peripherals::Peripherals, peripherals::Peripherals,
prelude::*, prelude::*,
rom::crc, rom::{crc, md5},
timer::TimerGroup, timer::TimerGroup,
Rtc, Rtc,
Uart, Uart,
@ -48,6 +48,7 @@ fn main() -> ! {
timer0.start(1u64.secs()); timer0.start(1u64.secs());
let data = "123456789"; let data = "123456789";
let sentence = "The quick brown fox jumps over a lazy dog";
writeln!( writeln!(
uart0, uart0,
@ -74,10 +75,38 @@ fn main() -> ! {
assert_eq!(crc_rohc, 0xd0); assert_eq!(crc_rohc, 0xd0);
assert_eq!(crc_smbus, 0xf4); 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!( writeln!(
uart0, uart0,
"{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x}", "{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x} {}",
crc_hdlc, crc_bzip2, crc_mpeg2, crc_cksum, crc_kermit, crc_genibus, crc_rohc, crc_smbus crc_hdlc,
crc_bzip2,
crc_mpeg2,
crc_cksum,
crc_kermit,
crc_genibus,
crc_rohc,
crc_smbus,
md5_digest
) )
.unwrap(); .unwrap();

View File

@ -19,3 +19,7 @@ PROVIDE(esp_rom_crc8_be = 0x4000076c);
PROVIDE(esp_rom_crc32_le = 0x40000758); PROVIDE(esp_rom_crc32_le = 0x40000758);
PROVIDE(esp_rom_crc16_le = 0x4000075c); PROVIDE(esp_rom_crc16_le = 0x4000075c);
PROVIDE(esp_rom_crc8_le = 0x40000760); PROVIDE(esp_rom_crc8_le = 0x40000760);
PROVIDE(esp_rom_md5_init = 0x4000074c);
PROVIDE(esp_rom_md5_update = 0x40000750);
PROVIDE(esp_rom_md5_final = 0x40000754);

View File

@ -9,7 +9,7 @@ use esp32h2_hal::{
clock::ClockControl, clock::ClockControl,
peripherals::Peripherals, peripherals::Peripherals,
prelude::*, prelude::*,
rom::crc, rom::{crc, md5},
timer::TimerGroup, timer::TimerGroup,
Rtc, Rtc,
Uart, Uart,
@ -49,6 +49,7 @@ fn main() -> ! {
timer0.start(1u64.secs()); timer0.start(1u64.secs());
let data = "123456789"; let data = "123456789";
let sentence = "The quick brown fox jumps over a lazy dog";
writeln!( writeln!(
uart0, uart0,
@ -75,10 +76,38 @@ fn main() -> ! {
assert_eq!(crc_rohc, 0xd0); assert_eq!(crc_rohc, 0xd0);
assert_eq!(crc_smbus, 0xf4); 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!( writeln!(
uart0, uart0,
"{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x}", "{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x} {}",
crc_hdlc, crc_bzip2, crc_mpeg2, crc_cksum, crc_kermit, crc_genibus, crc_rohc, crc_smbus crc_hdlc,
crc_bzip2,
crc_mpeg2,
crc_cksum,
crc_kermit,
crc_genibus,
crc_rohc,
crc_smbus,
md5_digest
) )
.unwrap(); .unwrap();

View File

@ -19,3 +19,7 @@ PROVIDE(esp_rom_crc8_be = 0x40000738);
PROVIDE(esp_rom_crc32_le = 0x40000724); PROVIDE(esp_rom_crc32_le = 0x40000724);
PROVIDE(esp_rom_crc16_le = 0x40000728); PROVIDE(esp_rom_crc16_le = 0x40000728);
PROVIDE(esp_rom_crc8_le = 0x4000072c); PROVIDE(esp_rom_crc8_le = 0x4000072c);
PROVIDE(esp_rom_md5_init = 0x40000718);
PROVIDE(esp_rom_md5_update = 0x4000071c);
PROVIDE(esp_rom_md5_final = 0x40000720);

View File

@ -9,7 +9,7 @@ use esp32s2_hal::{
clock::ClockControl, clock::ClockControl,
peripherals::Peripherals, peripherals::Peripherals,
prelude::*, prelude::*,
rom::crc, rom::{crc, md5},
timer::TimerGroup, timer::TimerGroup,
Rtc, Rtc,
Uart, Uart,
@ -40,6 +40,7 @@ fn main() -> ! {
timer0.start(1u64.secs()); timer0.start(1u64.secs());
let data = "123456789"; let data = "123456789";
let sentence = "The quick brown fox jumps over a lazy dog";
writeln!( writeln!(
serial0, serial0,
@ -66,10 +67,38 @@ fn main() -> ! {
assert_eq!(crc_rohc, 0xd0); assert_eq!(crc_rohc, 0xd0);
assert_eq!(crc_smbus, 0xf4); 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!( writeln!(
serial0, serial0,
"{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x}", "{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x} {}",
crc_hdlc, crc_bzip2, crc_mpeg2, crc_cksum, crc_kermit, crc_genibus, crc_rohc, crc_smbus crc_hdlc,
crc_bzip2,
crc_mpeg2,
crc_cksum,
crc_kermit,
crc_genibus,
crc_rohc,
crc_smbus,
md5_digest
) )
.unwrap(); .unwrap();

View File

@ -23,3 +23,7 @@ PROVIDE ( esp_rom_spi_cmd_config = 0x40017c58 );
PROVIDE(esp_rom_crc32_le = 0x400119dc); PROVIDE(esp_rom_crc32_le = 0x400119dc);
PROVIDE(esp_rom_crc16_le = 0x40011a10); PROVIDE(esp_rom_crc16_le = 0x40011a10);
PROVIDE(esp_rom_crc8_le = 0x40011a4c); PROVIDE(esp_rom_crc8_le = 0x40011a4c);
PROVIDE(esp_rom_md5_final = 0x4000530c);
PROVIDE(esp_rom_md5_init = 0x4000526c);
PROVIDE(esp_rom_md5_update = 0x4000528c);

View File

@ -9,7 +9,7 @@ use esp32s3_hal::{
clock::ClockControl, clock::ClockControl,
peripherals::Peripherals, peripherals::Peripherals,
prelude::*, prelude::*,
rom::crc, rom::{crc, md5},
timer::TimerGroup, timer::TimerGroup,
Rtc, Rtc,
Uart, Uart,
@ -40,6 +40,7 @@ fn main() -> ! {
timer0.start(1u64.secs()); timer0.start(1u64.secs());
let data = "123456789"; let data = "123456789";
let sentence = "The quick brown fox jumps over a lazy dog";
writeln!( writeln!(
serial0, serial0,
@ -66,10 +67,38 @@ fn main() -> ! {
assert_eq!(crc_rohc, 0xd0); assert_eq!(crc_rohc, 0xd0);
assert_eq!(crc_smbus, 0xf4); 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!( writeln!(
serial0, serial0,
"{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x}", "{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x} {}",
crc_hdlc, crc_bzip2, crc_mpeg2, crc_cksum, crc_kermit, crc_genibus, crc_rohc, crc_smbus crc_hdlc,
crc_bzip2,
crc_mpeg2,
crc_cksum,
crc_kermit,
crc_genibus,
crc_rohc,
crc_smbus,
md5_digest
) )
.unwrap(); .unwrap();

View File

@ -27,6 +27,10 @@ PROVIDE(esp_rom_crc32_le = 0x40001c98);
PROVIDE(esp_rom_crc16_le = 0x40001cb0); PROVIDE(esp_rom_crc16_le = 0x40001cb0);
PROVIDE(esp_rom_crc8_le = 0x40001cc8); 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_opiflash_exec_cmd = 0x400008b8);
PROVIDE( esp_rom_spi_set_dtr_swap_mode = 0x4000093c ); PROVIDE( esp_rom_spi_set_dtr_swap_mode = 0x4000093c );
PROVIDE( esp_rom_opiflash_pin_config = 0x40000894 ); PROVIDE( esp_rom_opiflash_pin_config = 0x40000894 );