Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
- Add feature enabling directly hooking the interrupt vector table

### Changed
Expand All @@ -54,6 +55,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed wrong variable access (FOSC CLK calibration for ESP32-C6 #593)
- Fixed [trap location in ram](https://github.com/esp-rs/esp-hal/pull/605#issuecomment-1604039683) (#605)
- Fixed a possible overlap of `.data` and `.rwtext` (#616)
- Avoid SDA/SCL being low while configuring pins for I2C

### Changed

Expand All @@ -63,7 +65,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Breaking

- Significantly simplified user-facing GPIO pin types. (#553)
- No longer re-export the `soc` moduleand the contents of the `interrupt` module at the package level (#607)
- No longer re-export the `soc` module and the contents of the `interrupt` module at the package level (#607)

## [0.9.0] - 2023-05-02

Expand Down
1 change: 1 addition & 0 deletions esp-hal-common/devices/esp32.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions esp-hal-common/devices/esp32c2.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions esp-hal-common/devices/esp32c3.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions esp-hal-common/devices/esp32c6.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions esp-hal-common/devices/esp32h2.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,5 @@ peripherals = [
# ROM capabilities
"rom_crc_le",
"rom_crc_be",
"rom_md5_bsd",
]
1 change: 1 addition & 0 deletions esp-hal-common/devices/esp32s2.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ peripherals = [

# ROM capabilities
"rom_crc_le",
"rom_md5_bsd",

# Wakeup SOC based on ESP-IDF:
"pm_support_ext0_wakeup",
Expand Down
1 change: 1 addition & 0 deletions esp-hal-common/devices/esp32s3.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
5 changes: 4 additions & 1 deletion esp-hal-common/src/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,10 @@ where

let mut i2c = I2C { peripheral: i2c };

// initialize SCL first to not confuse some devices like MPU6050
// avoid SCL/SDA going low during configuration
scl.set_output_high(true);
sda.set_output_high(true);

scl.set_to_open_drain_output()
.enable_input(true)
.internal_pull_up(true)
Expand Down
232 changes: 232 additions & 0 deletions esp-hal-common/src/rom/md5.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
1 change: 1 addition & 0 deletions esp-hal-common/src/rom/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//! read-only memory.

pub mod crc;
pub mod md5;

#[allow(unused)]
extern "C" {
Expand Down
35 changes: 32 additions & 3 deletions esp32-hal/examples/crc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use esp32_hal::{
clock::ClockControl,
peripherals::Peripherals,
prelude::*,
rom::crc,
rom::{crc, md5},
timer::TimerGroup,
Rtc,
Uart,
Expand Down Expand Up @@ -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,
Expand All @@ -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();

Expand Down
4 changes: 4 additions & 0 deletions esp32-hal/ld/rom-functions.x
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Loading