diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b51d43c8..47451a3a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -138,7 +138,7 @@ jobs: echo "${LIBCLANG_PATH}/../bin:$PATH" >> "$GITHUB_PATH" echo "LIBCLANG_PATH=${LIBCLANG_PATH}" >> "$GITHUB_ENV" echo "CLANG_PATH=${CLANG_PATH}" >> "$GITHUB_ENV" - + # TODO: Remove the manual espup installation and run once the action below # supports the `-r` flag to install the Espressif RISCV GCC toolchain # See https://github.com/esp-rs/xtensa-toolchain/issues/45 for more info @@ -175,7 +175,7 @@ jobs: retention-days: 1 path: | mbedtls-rs-sys/libs - mbedtls-rs-sys/src + mbedtls-rs-sys/src/include build-mcu: name: Build-MCU @@ -230,6 +230,30 @@ jobs: - name: Fmt Check - Examples run: cd examples/${{ matrix.mcu[0] }}; cargo fmt -- --check + - name: mbedtls init + run: git submodule update --init --recursive + + - name: Detect host target triple + run: | + export HOST_TARGET=$(rustup show | grep "Default host" | sed -e 's/.* //') + echo "HOST_TARGET=$HOST_TARGET" >> $GITHUB_ENV + + - name: Install espup + run: | + curl -LO https://github.com/esp-rs/espup/releases/latest/download/espup-${{ env.HOST_TARGET }}.zip + unzip -o espup-${{ env.HOST_TARGET }}.zip -d "$HOME/.cargo/bin" + chmod +x "$HOME/.cargo/bin/espup"* + echo "ESPUP_EXPORT_FILE=$HOME/exports" >> $GITHUB_ENV + + - name: Install espup toolchains (xtensa and riscv) + run: | + source "$HOME/.cargo/env" + "$HOME/.cargo/bin/espup" install -e -r + source "$HOME/exports" + echo "${LIBCLANG_PATH}/../bin:$PATH" >> "$GITHUB_PATH" + echo "LIBCLANG_PATH=${LIBCLANG_PATH}" >> "$GITHUB_ENV" + echo "CLANG_PATH=${CLANG_PATH}" >> "$GITHUB_ENV" + - name: Clippy - Examples run: export WIFI_SSID=ssid; export WIFI_PASS=pass; cd examples/${{ matrix.mcu[0] }}; cargo clippy --no-default-features --features ${{ matrix.mcu[1] }} --target ${{ matrix.mcu[2] }} -Zbuild-std=core,alloc,panic_abort -- -D warnings diff --git a/examples/esp/Cargo.toml b/examples/esp/Cargo.toml index 81d3effc..923040a6 100644 --- a/examples/esp/Cargo.toml +++ b/examples/esp/Cargo.toml @@ -34,13 +34,13 @@ opt-level = "z" [features] default = ["esp32c6"] -esp32 = ["esp-rtos/esp32", "esp-hal/esp32", "esp-backtrace/esp32", "esp-println/esp32", "esp-radio/esp32", "esp-bootloader-esp-idf/esp32", "esp-metadata-generated/esp32", "mbedtls-rs/accel-esp32"] -esp32c2 = ["esp-rtos/esp32c2", "esp-hal/esp32c2", "esp-backtrace/esp32c2", "esp-println/esp32c2", "esp-radio/esp32c2", "esp-bootloader-esp-idf/esp32c2", "esp-metadata-generated/esp32c2", "mbedtls-rs/accel-esp32c2"] -esp32c3 = ["esp-rtos/esp32c3", "esp-hal/esp32c3", "esp-backtrace/esp32c3", "esp-println/esp32c3", "esp-radio/esp32c3", "esp-bootloader-esp-idf/esp32c3", "esp-metadata-generated/esp32c3", "mbedtls-rs/accel-esp32c3"] -esp32c6 = ["esp-rtos/esp32c6", "esp-hal/esp32c6", "esp-backtrace/esp32c6", "esp-println/esp32c6", "esp-radio/esp32c6", "esp-bootloader-esp-idf/esp32c6", "esp-metadata-generated/esp32c6", "mbedtls-rs/accel-esp32c6"] -esp32h2 = ["esp-rtos/esp32h2", "esp-hal/esp32h2", "esp-backtrace/esp32h2", "esp-println/esp32h2", "esp-radio/esp32h2", "esp-bootloader-esp-idf/esp32h2", "esp-metadata-generated/esp32h2", "mbedtls-rs/accel-esp32h2"] -esp32s2 = ["esp-rtos/esp32s2", "esp-hal/esp32s2", "esp-backtrace/esp32s2", "esp-println/esp32s2", "esp-radio/esp32s2", "esp-bootloader-esp-idf/esp32s2", "esp-metadata-generated/esp32s2", "mbedtls-rs/accel-esp32s2"] -esp32s3 = ["esp-rtos/esp32s3", "esp-hal/esp32s3", "esp-backtrace/esp32s3", "esp-println/esp32s3", "esp-radio/esp32s3", "esp-bootloader-esp-idf/esp32s3", "esp-metadata-generated/esp32s3", "mbedtls-rs/accel-esp32s3"] +esp32 = ["esp-rtos/esp32", "esp-hal/esp32", "esp-backtrace/esp32", "esp-println/esp32", "esp-radio/esp32", "esp-bootloader-esp-idf/esp32", "esp-metadata-generated/esp32", "mbedtls-rs/accel-esp32", "mbedtls-rs/timer-embassy", "mbedtls-rs/wall-clock-esp32"] +esp32c2 = ["esp-rtos/esp32c2", "esp-hal/esp32c2", "esp-backtrace/esp32c2", "esp-println/esp32c2", "esp-radio/esp32c2", "esp-bootloader-esp-idf/esp32c2", "esp-metadata-generated/esp32c2", "mbedtls-rs/accel-esp32c2", "mbedtls-rs/timer-embassy", "mbedtls-rs/wall-clock-esp32c2"] +esp32c3 = ["esp-rtos/esp32c3", "esp-hal/esp32c3", "esp-backtrace/esp32c3", "esp-println/esp32c3", "esp-radio/esp32c3", "esp-bootloader-esp-idf/esp32c3", "esp-metadata-generated/esp32c3", "mbedtls-rs/accel-esp32c3", "mbedtls-rs/timer-embassy", "mbedtls-rs/wall-clock-esp32c3"] +esp32c6 = ["esp-rtos/esp32c6", "esp-hal/esp32c6", "esp-backtrace/esp32c6", "esp-println/esp32c6", "esp-radio/esp32c6", "esp-bootloader-esp-idf/esp32c6", "esp-metadata-generated/esp32c6", "mbedtls-rs/accel-esp32c6", "mbedtls-rs/timer-embassy", "mbedtls-rs/wall-clock-esp32c6"] +esp32h2 = ["esp-rtos/esp32h2", "esp-hal/esp32h2", "esp-backtrace/esp32h2", "esp-println/esp32h2", "esp-radio/esp32h2", "esp-bootloader-esp-idf/esp32h2", "esp-metadata-generated/esp32h2", "mbedtls-rs/accel-esp32h2", "mbedtls-rs/timer-embassy", "mbedtls-rs/wall-clock-esp32h2"] +esp32s2 = ["esp-rtos/esp32s2", "esp-hal/esp32s2", "esp-backtrace/esp32s2", "esp-println/esp32s2", "esp-radio/esp32s2", "esp-bootloader-esp-idf/esp32s2", "esp-metadata-generated/esp32s2", "mbedtls-rs/accel-esp32s2", "mbedtls-rs/timer-embassy", "mbedtls-rs/wall-clock-esp32s2"] +esp32s3 = ["esp-rtos/esp32s3", "esp-hal/esp32s3", "esp-backtrace/esp32s3", "esp-println/esp32s3", "esp-radio/esp32s3", "esp-bootloader-esp-idf/esp32s3", "esp-metadata-generated/esp32s3", "mbedtls-rs/accel-esp32s3", "mbedtls-rs/timer-embassy", "mbedtls-rs/wall-clock-esp32s3"] [dependencies] log = "0.4" diff --git a/examples/esp/build.rs b/examples/esp/build.rs new file mode 100644 index 00000000..e0bd96fd --- /dev/null +++ b/examples/esp/build.rs @@ -0,0 +1,10 @@ +use std::time::{SystemTime, UNIX_EPOCH}; + +fn main() { + let current_time_ms = SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("Time went backwards") + .as_millis(); + + println!("cargo:rustc-env=CURRENT_TIME_MS={}", current_time_ms); +} diff --git a/examples/esp/src/bin/client.rs b/examples/esp/src/bin/client.rs index d10c566f..7c024315 100644 --- a/examples/esp/src/bin/client.rs +++ b/examples/esp/src/bin/client.rs @@ -36,7 +36,8 @@ async fn main(spawner: Spawner) { let stack_resources = mk_static!(StackResources<3>, StackResources::new()); - let (mut tls, stack, mut accel) = bootstrap::bootstrap_stack(spawner, stack_resources).await; + let (mut tls, stack, mut accel, ..) = + bootstrap::bootstrap_stack(spawner, stack_resources).await; tls.set_debug(1); diff --git a/examples/esp/src/bin/edge_client.rs b/examples/esp/src/bin/edge_client.rs index 39c9d6b5..ef07f603 100644 --- a/examples/esp/src/bin/edge_client.rs +++ b/examples/esp/src/bin/edge_client.rs @@ -35,7 +35,8 @@ async fn main(spawner: Spawner) { let stack_resources = mk_static!(StackResources<3>, StackResources::new()); - let (mut tls, stack, mut accel) = bootstrap::bootstrap_stack(spawner, stack_resources).await; + let (mut tls, stack, mut accel, ..) = + bootstrap::bootstrap_stack(spawner, stack_resources).await; tls.set_debug(1); diff --git a/examples/esp/src/bin/edge_server.rs b/examples/esp/src/bin/edge_server.rs index f8158a0c..35f5ce66 100644 --- a/examples/esp/src/bin/edge_server.rs +++ b/examples/esp/src/bin/edge_server.rs @@ -41,7 +41,8 @@ async fn main(spawner: Spawner) { let stack_resources = mk_static!(StackResources<4>, StackResources::new()); - let (mut tls, stack, mut accel) = bootstrap::bootstrap_stack(spawner, stack_resources).await; + let (mut tls, stack, mut accel, ..) = + bootstrap::bootstrap_stack(spawner, stack_resources).await; tls.set_debug(1); diff --git a/examples/esp/src/bin/server.rs b/examples/esp/src/bin/server.rs index 19c3831b..031ac9d8 100644 --- a/examples/esp/src/bin/server.rs +++ b/examples/esp/src/bin/server.rs @@ -42,7 +42,8 @@ async fn main(spawner: Spawner) { let stack_resources = mk_static!(StackResources<4>, StackResources::new()); - let (mut tls, stack, mut accel) = bootstrap::bootstrap_stack(spawner, stack_resources).await; + let (mut tls, stack, mut accel, ..) = + bootstrap::bootstrap_stack(spawner, stack_resources).await; tls.set_debug(1); diff --git a/examples/esp/src/bin/time_verification.rs b/examples/esp/src/bin/time_verification.rs new file mode 100644 index 00000000..7b1ceab9 --- /dev/null +++ b/examples/esp/src/bin/time_verification.rs @@ -0,0 +1,115 @@ +//! Example demonstrating certificate time validation using the async API. +//! +//! This example connects to `https://httpbin.org/ip` twice to verify that: +//! 1. Certificate validation succeeds with correct time +//! 2. Certificate validation fails when time is manipulated (simulating an expired certificate) + +#![no_std] +#![no_main] +#![recursion_limit = "256"] + +use core::net::SocketAddr; + +use embassy_executor::Spawner; + +use embassy_net::tcp::TcpSocket; +use embassy_net::StackResources; + +use esp_alloc::heap_allocator; +use esp_backtrace as _; + +use log::info; + +use tinyrlibc as _; + +use crate::bootstrap::RECLAIMED_RAM; + +#[path = "../bootstrap.rs"] +mod bootstrap; +#[path = "../../../common/client.rs"] +mod client; + +const HEAP_SIZE: usize = 140 * 1024; + +#[esp_rtos::main] +async fn main(spawner: Spawner) { + heap_allocator!(size: HEAP_SIZE - RECLAIMED_RAM); + + let stack_resources = mk_static!(StackResources<3>, StackResources::new()); + + let (mut tls, stack, mut accel, _timer, rtc) = + bootstrap::bootstrap_stack(spawner, stack_resources).await; + + tls.set_debug(1); + + let _accel_queue = accel.start(); + + for (index, (server_name_cstr, server_path, expired_cert)) in [ + (c"httpbin.org", "/ip", false), + (c"httpbin.org", "/ip", true), + ] + .into_iter() + .enumerate() + { + let server_name = server_name_cstr.to_str().unwrap(); + + info!( + "\n\n\n\nREQUEST {}, EXPIRED_CERT: {} =============================", + index, expired_cert + ); + + if expired_cert { + // double current time to cause certificate validation to fail + rtc.set_current_time_us(rtc.current_time_us() * 2); + } + + info!("Resolving server {}", server_name); + + let ip = *stack + .dns_query(server_name, embassy_net::dns::DnsQueryType::A) + .await + .unwrap() + .iter() + .next() + .unwrap(); + + info!("Using IP addr {}", ip); + + info!("Creating TCP connection"); + + let mut rx_buf = [0; 1024]; + let mut tx_buf = [0; 1024]; + + let mut socket = TcpSocket::new(stack, &mut rx_buf, &mut tx_buf); + + //socket.set_timeout(Some(Duration::from_secs(10))); + socket + .connect(SocketAddr::new(ip.into(), 443)) + .await + .unwrap(); + + let mut buf = [0u8; 1024]; + + match client::request( + tls.reference(), + socket, + server_name_cstr, + server_path, + false, + &mut buf, + ) + .await + { + Ok(()) => { + if expired_cert { + panic!("request should have failed with failed certificate validation"); + } + } + Err(e) => { + if !expired_cert { + panic!("request should have succeeded: {}", e); + } + } + } + } +} diff --git a/examples/esp/src/bootstrap.rs b/examples/esp/src/bootstrap.rs index b72bb2f4..f5286101 100644 --- a/examples/esp/src/bootstrap.rs +++ b/examples/esp/src/bootstrap.rs @@ -17,6 +17,8 @@ use esp_hal::rng::TrngSource; use esp_hal::timer::timg::TimerGroup; use mbedtls_rs::sys::accel::esp::EspAccel; +use mbedtls_rs::sys::clock::esp::EspRtcWallClock; +use mbedtls_rs::sys::timer::embassy::EmbassyTimer; use mbedtls_rs::Tls; use esp_metadata_generated::memory_range; @@ -51,11 +53,18 @@ esp_bootloader_esp_idf::esp_app_desc!(); const WIFI_SSID: &str = env!("WIFI_SSID"); const WIFI_PASS: &str = env!("WIFI_PASS"); +const CURRENT_TIME_MS: &str = env!("CURRENT_TIME_MS"); pub async fn bootstrap_stack( spawner: Spawner, stack_resources: &'static mut StackResources, -) -> (Tls<'static>, Stack<'static>, EspAccel<'static>) { +) -> ( + Tls<'static>, + Stack<'static>, + EspAccel<'static>, + &'static EmbassyTimer, + &'static esp_hal::rtc_cntl::Rtc<'static>, +) { esp_println::logger::init_logger(log::LevelFilter::Info); info!("Starting..."); @@ -72,6 +81,31 @@ pub async fn bootstrap_stack( .software_interrupt0, ); + // Create static Embassy timer and "hook it" to mbedtls + let timer = mk_static!(EmbassyTimer, EmbassyTimer); + unsafe { + mbedtls_rs::sys::hook::timer::hook_timer(Some(timer)); + } + + // Setup RTC for EspRtcWallClock + let rtc = mk_static!( + esp_hal::rtc_cntl::Rtc, + esp_hal::rtc_cntl::Rtc::new(peripherals.LPWR) + ); + // In a real-life scenario NTP or equivalent should be used here to initialize the RTC + rtc.set_current_time_us( + CURRENT_TIME_MS + .parse::() + .expect("Failed to parse CURRENT_TIME_MS") + * 1000, // Convert milliseconds to microseconds + ); + + // Make EspRtcWallClock static and "hook it" to mbedtls + let clock = mk_static!(EspRtcWallClock, EspRtcWallClock::new(rtc)); + unsafe { + mbedtls_rs::sys::hook::wall_clock::hook_wall_clock(Some(clock)); + } + #[cfg(not(any(feature = "esp32", feature = "esp32c2")))] let accel = EspAccel::new(peripherals.SHA, peripherals.RSA); @@ -100,7 +134,7 @@ pub async fn bootstrap_stack( wait_ip(stack).await; - (Tls::new(trng).unwrap(), stack, accel) + (Tls::new(trng).unwrap(), stack, accel, timer, rtc) } async fn wait_ip(stack: Stack<'_>) { diff --git a/mbedtls-rs-sys/Cargo.toml b/mbedtls-rs-sys/Cargo.toml index 24b92d88..92b7336b 100644 --- a/mbedtls-rs-sys/Cargo.toml +++ b/mbedtls-rs-sys/Cargo.toml @@ -25,6 +25,7 @@ nohook-sha1 = [] nohook-sha256 = [] nohook-sha512 = [] nohook-exp-mod = [] + # Enable HW acceleration drivers for the ESP series of MCUs via `esp-hal` accel-esp32 = ["esp-hal/esp32", "crypto-bigint"] accel-esp32c2 = ["esp-hal/esp32c2"] @@ -34,6 +35,22 @@ accel-esp32h2 = ["esp-hal/esp32h2", "crypto-bigint"] accel-esp32s2 = ["esp-hal/esp32s2", "crypto-bigint"] accel-esp32s3 = ["esp-hal/esp32s3", "crypto-bigint"] +# Enable timer/wall-clock hooks for custom time implementations +hook-timer = [] +hook-wall-clock = ["hook-timer"] # 'hook-wall-clock' feature requires 'hook-timer' to be enabled. MbedTLS X.509 certificate validation requires both time() and gmtime_r() functions. + +timer-embassy = ["embassy-time", "hook-timer"] +timer-std = ["hook-timer"] + +wall-clock-std = ["time", "hook-wall-clock"] +wall-clock-esp32 = ["esp-hal/esp32", "time", "hook-wall-clock"] +wall-clock-esp32c2 = ["esp-hal/esp32c2", "time", "hook-wall-clock"] +wall-clock-esp32c3 = ["esp-hal/esp32c3", "time", "hook-wall-clock"] +wall-clock-esp32c6 = ["esp-hal/esp32c6", "time", "hook-wall-clock"] +wall-clock-esp32h2 = ["esp-hal/esp32h2", "time", "hook-wall-clock"] +wall-clock-esp32s2 = ["esp-hal/esp32s2", "time", "hook-wall-clock"] +wall-clock-esp32s3 = ["esp-hal/esp32s3", "time", "hook-wall-clock"] + [dependencies] defmt = { version = "1", optional = true } log = { version = "0.4", optional = true } @@ -43,12 +60,16 @@ digest = { version = "0.10", default-features = false } sha1 = { version = "0.10", default-features = false } # For some reason, `soft` results in enormous slowdowns on xtensa and riscv32 sha2 = { version = "0.10", default-features = false, features = ["force-soft-compact"] } +time = { version = "0.3", default-features = false, optional = true } critical-section = "1" # For esp-hal accel esp-hal = { version = "1", features = ["unstable"], optional = true } crypto-bigint = { version = "0.5.3", default-features = false, features = ["extra-sizes"], optional = true } +# For embassy timer support +embassy-time = {version = "0.5.0", optional = true} + # ESP-IDF: The mbedtls lib distributed with ESP-IDF is used # All other platforms: mbedtls libs and bindings are created on the fly [target.'cfg(target_os = "espidf")'.dependencies] diff --git a/mbedtls-rs-sys/build.rs b/mbedtls-rs-sys/build.rs index b78572b1..cd7012a6 100644 --- a/mbedtls-rs-sys/build.rs +++ b/mbedtls-rs-sys/build.rs @@ -1,9 +1,7 @@ -use std::{env, path::PathBuf}; - use anyhow::Result; -use enumset::EnumSet; +use std::{env, path::PathBuf}; -use crate::builder::Hook; +use crate::builder::{Hook, MbedtlsBuilder}; #[path = "gen/builder.rs"] mod builder; @@ -11,8 +9,8 @@ mod builder; fn main() -> Result<()> { let crate_root_path = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap()); - builder::MbedtlsBuilder::track(&crate_root_path.join("gen")); - builder::MbedtlsBuilder::track(&crate_root_path.join("mbedtls")); + MbedtlsBuilder::track(&crate_root_path.join("gen")); + MbedtlsBuilder::track(&crate_root_path.join("mbedtls")); let host = env::var("HOST").unwrap(); let target = env::var("TARGET").unwrap(); @@ -27,9 +25,8 @@ fn main() -> Result<()> { .join(format!("{target}.rs")); let pregen_libs_dir = crate_root_path.join("libs").join(&target); - // Figure out what MbedTLS hook options (ALT modules) to enable - let mut removed_hooks = EnumSet::empty(); - + // Figure out what MbedTLS hook options to enable + let mut hooks = builder::DEFAULT_HOOKS; for (feature, hook) in [ ("CARGO_FEATURE_NOHOOK_SHA1", Hook::Sha1), ("CARGO_FEATURE_NOHOOK_SHA256", Hook::Sha256), @@ -37,11 +34,22 @@ fn main() -> Result<()> { ("CARGO_FEATURE_NOHOOK_EXP_MOD", Hook::ExpMod), ] { if env::var(feature).is_ok() { - removed_hooks.insert(hook); + hooks.remove(hook); } } - let dirs = if pregen_bindings && pregen_bindings_rs_file.exists() && removed_hooks.is_empty() { + for (feature, hook) in [ + ("CARGO_FEATURE_HOOK_TIMER", Hook::Timer), + ("CARGO_FEATURE_HOOK_WALL_CLOCK", Hook::WallClock), + ] { + if env::var(feature).is_ok() { + hooks.insert(hook); + } + } + + let hooks_changed = hooks != builder::DEFAULT_HOOKS; + + let dirs = if pregen_bindings && pregen_bindings_rs_file.exists() && !hooks_changed { // Use the pre-generated bindings Some((pregen_bindings_rs_file, pregen_libs_dir)) } else if target.ends_with("-espidf") { @@ -50,9 +58,9 @@ fn main() -> Result<()> { } else { if pregen_bindings_rs_file.exists() { if !pregen_bindings { - println!("cargo::warning=Forcing on-the-fly build for target {target}"); + println!("cargo::warning=Forcing on-the-fly build for target {target} as bindings are not available."); } else { - println!("cargo::warning=Forcing on-the-fly build for {target} because some or all hooks are disabled: {removed_hooks:?}"); + println!("cargo::warning=Forcing on-the-fly build for {target} because hooks don't match default. Enabled hooks: {hooks:?}."); } } @@ -62,8 +70,8 @@ fn main() -> Result<()> { // Need to do on-the-fly build and bindings' generation let out = PathBuf::from(env::var_os("OUT_DIR").unwrap()); - let builder = builder::MbedtlsBuilder::new( - removed_hooks.complement(), + let builder = MbedtlsBuilder::new( + hooks, !use_gcc, crate_root_path.clone(), Some(target), diff --git a/mbedtls-rs-sys/gen/builder.rs b/mbedtls-rs-sys/gen/builder.rs index 43bba9a4..66fcc623 100644 --- a/mbedtls-rs-sys/gen/builder.rs +++ b/mbedtls-rs-sys/gen/builder.rs @@ -1,10 +1,15 @@ +use std::option::Option; use std::path::{Path, PathBuf}; use std::process::Command; use anyhow::{anyhow, Result}; use bindgen::Builder; use cmake::Config; -use enumset::{EnumSet, EnumSetType}; +use enumset::{enum_set, EnumSet, EnumSetType}; + +// This set MUST contain all opt-out hooks +pub const DEFAULT_HOOKS: EnumSet = + enum_set!(Hook::Sha1 | Hook::Sha256 | Hook::Sha512 | Hook::ExpMod); /// What hooks to install in MbedTLS #[derive(EnumSetType, Debug)] @@ -17,6 +22,10 @@ pub enum Hook { Sha512, /// MPI modular exponentiation ExpMod, + /// Timer support + Timer, + /// Wall clock support + WallClock, } /// The MbedTLS builder @@ -33,7 +42,7 @@ impl MbedtlsBuilder { /// Create a new MbedtlsBuilder /// /// Arguments: - /// - `hooks` - Set of algorithm hooks to enable + /// - `hooks` - Set of algorithm hooks to enable. /// - `force_clang`: If true, force the use of Clang as the C/C++ compiler /// - `crate_root_path`: Path to the root of the crate /// - `cmake_rust_target`: Optional target for CMake when building MbedTLS, with Rust target-triple syntax. If not specified, the "TARGET" env variable will be used @@ -156,15 +165,25 @@ impl MbedtlsBuilder { } for hook in self.hooks { - let def = self.hook_def(hook); + let defs = self.hook_defs(hook); - builder = builder.clang_arg(format!("-D{def}")); + for def in defs { + builder = builder.clang_arg(format!("-D{def}")); - if let Some(size_def) = self.hook_work_area_size_def(hook) { - builder = builder.clang_arg(format!("-D{def}_WORK_AREA_SIZE={size_def}")); + if let Some(size_def) = self.hook_work_area_size_def(hook) { + builder = builder.clang_arg(format!("-D{def}_WORK_AREA_SIZE={size_def}")); + } } } + if self.hooks.contains(Hook::Timer) { + builder = builder.allowlist_item("time_t"); + } + + if self.hooks.contains(Hook::WallClock) { + builder = builder.allowlist_item("tm"); + } + let bindings = builder .generate() .map_err(|_| anyhow!("Failed to generate bindings"))?; @@ -234,17 +253,25 @@ impl MbedtlsBuilder { .out_dir(&target_dir); for hook in self.hooks { - let def = self.hook_def(hook); + let defs = self.hook_defs(hook); - config.cflag(format!("-D{def}")).cxxflag(format!("-D{def}")); + for def in defs { + config.cflag(format!("-D{def}")).cxxflag(format!("-D{def}")); - if let Some(size_def) = self.hook_work_area_size_def(hook) { - config - .cflag(format!("-D{def}_WORK_AREA_SIZE={size_def}")) - .cxxflag(format!("-D{def}_WORK_AREA_SIZE={size_def}")); + if let Some(size_def) = self.hook_work_area_size_def(hook) { + config + .cflag(format!("-D{def}_WORK_AREA_SIZE={size_def}")) + .cxxflag(format!("-D{def}_WORK_AREA_SIZE={size_def}")); + } } } + if self.hooks.contains(Hook::Timer) { + // Unlike crypto alts, platform_time.h has no + // _alt.h inclusion mechanism, so we force-include it via -include. + config.cflag("-include time_alt.h"); + } + config.build(); Ok(lib_dir.to_path_buf()) @@ -256,12 +283,21 @@ impl MbedtlsBuilder { println!("cargo::rerun-if-changed={}", file_or_dir.display()) } - fn hook_def(&self, hook: Hook) -> &'static str { + fn hook_defs(&self, hook: Hook) -> &'static [&'static str] { match hook { - Hook::Sha1 => "MBEDTLS_SHA1_ALT", - Hook::Sha256 => "MBEDTLS_SHA256_ALT", - Hook::Sha512 => "MBEDTLS_SHA512_ALT", - Hook::ExpMod => "MBEDTLS_MPI_EXP_MOD_ALT_FALLBACK", + Hook::Sha1 => &["MBEDTLS_SHA1_ALT"], + Hook::Sha256 => &["MBEDTLS_SHA256_ALT"], + Hook::Sha512 => &["MBEDTLS_SHA512_ALT"], + Hook::ExpMod => &["MBEDTLS_MPI_EXP_MOD_ALT_FALLBACK"], + Hook::Timer => &[ + "MBEDTLS_HAVE_TIME", + // using a mbedtls prefix to ensure we don't have conflicting 'time' symbols on std + "MBEDTLS_PLATFORM_STD_TIME=mbedtls_sec_time", + // required to set MBEDTLS_PLATFORM_STD_TIME + "MBEDTLS_PLATFORM_TIME_ALT", + "MBEDTLS_PLATFORM_MS_TIME_ALT", + ], + Hook::WallClock => &["MBEDTLS_HAVE_TIME_DATE", "MBEDTLS_PLATFORM_GMTIME_R_ALT"], } } diff --git a/mbedtls-rs-sys/gen/include/time_alt.h b/mbedtls-rs-sys/gen/include/time_alt.h new file mode 100644 index 00000000..2acd7ce6 --- /dev/null +++ b/mbedtls-rs-sys/gen/include/time_alt.h @@ -0,0 +1,3 @@ +// Declares mbedtls_sec_time symbol for MBEDTLS_PLATFORM_STD_TIME. +#include +time_t mbedtls_sec_time(time_t *timer); diff --git a/mbedtls-rs-sys/gen/sysroot/include/time.h b/mbedtls-rs-sys/gen/sysroot/include/time.h new file mode 100644 index 00000000..6f6d1b40 --- /dev/null +++ b/mbedtls-rs-sys/gen/sysroot/include/time.h @@ -0,0 +1,22 @@ +#ifndef __TIME_H__ +#define __TIME_H__ + +#include + +typedef int64_t time_t; + +struct tm { + int tm_sec; // seconds after the minute - [0, 60] + int tm_min; // minutes after the hour - [0, 59] + int tm_hour; // hours since midnight - [0, 23] + int tm_mday; // day of the month - [1, 31] + int tm_mon; // months since January - [0, 11] + int tm_year; // years since 1900 + int tm_wday; // days since Sunday - [0, 6] + int tm_yday; // days since January 1 - [0, 365] + int tm_isdst; // Daylight Saving Time flag +}; + +time_t time(time_t* timer); + +#endif \ No newline at end of file diff --git a/mbedtls-rs-sys/libs/riscv32imac-unknown-none-elf/libmbedtls.a b/mbedtls-rs-sys/libs/riscv32imac-unknown-none-elf/libmbedtls.a index 8be73d82..d72f3e48 100644 Binary files a/mbedtls-rs-sys/libs/riscv32imac-unknown-none-elf/libmbedtls.a and b/mbedtls-rs-sys/libs/riscv32imac-unknown-none-elf/libmbedtls.a differ diff --git a/mbedtls-rs-sys/libs/riscv32imc-unknown-none-elf/libmbedtls.a b/mbedtls-rs-sys/libs/riscv32imc-unknown-none-elf/libmbedtls.a index 701c8354..4b1cf619 100644 Binary files a/mbedtls-rs-sys/libs/riscv32imc-unknown-none-elf/libmbedtls.a and b/mbedtls-rs-sys/libs/riscv32imc-unknown-none-elf/libmbedtls.a differ diff --git a/mbedtls-rs-sys/libs/xtensa-esp32-none-elf/libmbedtls.a b/mbedtls-rs-sys/libs/xtensa-esp32-none-elf/libmbedtls.a index 52d51750..492f90d7 100644 Binary files a/mbedtls-rs-sys/libs/xtensa-esp32-none-elf/libmbedtls.a and b/mbedtls-rs-sys/libs/xtensa-esp32-none-elf/libmbedtls.a differ diff --git a/mbedtls-rs-sys/libs/xtensa-esp32s2-none-elf/libmbedtls.a b/mbedtls-rs-sys/libs/xtensa-esp32s2-none-elf/libmbedtls.a index 52d51750..492f90d7 100644 Binary files a/mbedtls-rs-sys/libs/xtensa-esp32s2-none-elf/libmbedtls.a and b/mbedtls-rs-sys/libs/xtensa-esp32s2-none-elf/libmbedtls.a differ diff --git a/mbedtls-rs-sys/libs/xtensa-esp32s3-none-elf/libmbedtls.a b/mbedtls-rs-sys/libs/xtensa-esp32s3-none-elf/libmbedtls.a index 52d51750..492f90d7 100644 Binary files a/mbedtls-rs-sys/libs/xtensa-esp32s3-none-elf/libmbedtls.a and b/mbedtls-rs-sys/libs/xtensa-esp32s3-none-elf/libmbedtls.a differ diff --git a/mbedtls-rs-sys/src/clock.rs b/mbedtls-rs-sys/src/clock.rs new file mode 100644 index 00000000..38844727 --- /dev/null +++ b/mbedtls-rs-sys/src/clock.rs @@ -0,0 +1,13 @@ +#[cfg(any( + feature = "wall-clock-esp32", + feature = "wall-clock-esp32c2", + feature = "wall-clock-esp32c3", + feature = "wall-clock-esp32c6", + feature = "wall-clock-esp32h2", + feature = "wall-clock-esp32s2", + feature = "wall-clock-esp32s3", +))] +pub mod esp; + +#[cfg(feature = "wall-clock-std")] +mod std; diff --git a/mbedtls-rs-sys/src/clock/esp.rs b/mbedtls-rs-sys/src/clock/esp.rs new file mode 100644 index 00000000..61931b0a --- /dev/null +++ b/mbedtls-rs-sys/src/clock/esp.rs @@ -0,0 +1,78 @@ +use core::cell::Cell; +use critical_section::Mutex; + +use crate::bindings::tm; +use crate::hook::wall_clock::MbedtlsWallClock; + +/// ESP RTC-based wall clock backend for MbedTLS certificate validation. +/// +/// Uses the ESP RTC peripheral to provide calendar time. The RTC must be +/// initialized with the correct time before use (e.g., via NTP). +/// +/// # Usage +/// ```no_run +/// use esp_mbedtls_sys::clock::{hook_wall_clock, esp::EspRtcWallClock}; +/// +/// // Both RTC and wall clock must be static (using static_cell or similar) +/// static RTC: esp_hal::rtc_cntl::Rtc = /* ... */; +/// static WALL_CLOCK: EspRtcWallClock = EspRtcWallClock::new(&RTC); +/// +/// unsafe { +/// hook_wall_clock(Some(&WALL_CLOCK)); +/// } +/// // ... use MbedTLS ... +/// unsafe { +/// hook_wall_clock(None); +/// } +/// ``` +/// +pub struct EspRtcWallClock { + rtc: Mutex>>, +} + +impl EspRtcWallClock { + pub const fn new(rtc: &'static esp_hal::rtc_cntl::Rtc<'static>) -> Self { + Self { + rtc: Mutex::new(Cell::new(rtc)), + } + } + + #[inline] + fn with_rtc(&self, f: F) -> R + where + F: FnOnce(&esp_hal::rtc_cntl::Rtc<'_>) -> R, + { + critical_section::with(|cs| f(self.rtc.borrow(cs).get())) + } +} + +impl MbedtlsWallClock for EspRtcWallClock { + /// Returns the current time from the RTC. + /// + /// # Panics + /// + /// Panics if the RTC time is out of the valid range for `OffsetDateTime`. + /// This can occur if the RTC was not properly initialized with a valid timestamp + /// (e.g., via NTP or manual setting). + fn instant(&self) -> tm { + let rtc_time_secs = self.with_rtc(|rtc| (rtc.current_time_us() / 1_000_000) as i64); + + let datetime = time::OffsetDateTime::from_unix_timestamp(rtc_time_secs) + .expect("RTC time out of range, ensure RTC is initialized with valid time"); + + let date = datetime.date(); + let time = datetime.time(); + + tm { + tm_sec: time.second() as i32, + tm_min: time.minute() as i32, + tm_hour: time.hour() as i32, + tm_mday: date.day() as i32, + tm_mon: date.month() as i32 - 1, // tm_mon is 0-11, time::Month is 1-12 + tm_year: date.year() - 1900, // tm_year is years since 1900 + tm_wday: date.weekday().number_days_from_sunday() as i32, + tm_yday: date.ordinal() as i32 - 1, // MbedTLS uses 0-365 + tm_isdst: 0, + } + } +} diff --git a/mbedtls-rs-sys/src/clock/std.rs b/mbedtls-rs-sys/src/clock/std.rs new file mode 100644 index 00000000..901f8049 --- /dev/null +++ b/mbedtls-rs-sys/src/clock/std.rs @@ -0,0 +1,50 @@ +extern crate std; + +use std::time::SystemTime; + +use crate::bindings::tm; +use crate::hook::wall_clock::MbedtlsWallClock; + +/// Standard library wall clock backend for MbedTLS certificate validation. +/// +/// Uses `std::time::SystemTime` to provide calendar time. +#[derive(Debug, Default)] +pub struct StdWallClock; + +impl MbedtlsWallClock for StdWallClock { + /// Returns the current time from the system clock. + /// + /// # Panics + /// + /// Panics if: + /// - The system time is before the Unix epoch (January 1, 1970) + /// - The system time is out of the valid range for `OffsetDateTime` + /// + /// These conditions indicate a serious system clock misconfiguration that would + /// compromise TLS certificate validation. + fn instant(&self) -> tm { + let now = SystemTime::now(); + let duration = now + .duration_since(SystemTime::UNIX_EPOCH) + .expect("System time is before Unix epoch"); + let timestamp = i64::try_from(duration.as_secs()).unwrap_or(i64::MAX); + + let datetime = time::OffsetDateTime::from_unix_timestamp(timestamp) + .expect("System time out of range for OffsetDateTime"); + + let date = datetime.date(); + let time = datetime.time(); + + tm { + tm_sec: time.second() as i32, + tm_min: time.minute() as i32, + tm_hour: time.hour() as i32, + tm_mday: date.day() as i32, + tm_mon: date.month() as i32 - 1, // tm_mon is 0-11 + tm_year: date.year() - 1900, // tm_year is years since 1900 + tm_wday: date.weekday().number_days_from_sunday() as i32, + tm_yday: date.ordinal() as i32 - 1, // 0-365 + tm_isdst: 0, + } + } +} diff --git a/mbedtls-rs-sys/src/hook.rs b/mbedtls-rs-sys/src/hook.rs index fb993c43..b24c0b96 100644 --- a/mbedtls-rs-sys/src/hook.rs +++ b/mbedtls-rs-sys/src/hook.rs @@ -1,15 +1,19 @@ -//! This module allows for replacing (hooking) some crypto algorithms in MbedTLS -//! with custom ones. +//! This module allows for replacing (hooking) some crypto algorithms and timer/clock +//! functionality in MbedTLS with custom implementations. //! -//! The primary purpose being providing hardware-accelerated equivalents on platforms -//! that support it. +//! This enables providing hardware-accelerated crypto or platform-specific time sources +//! on platforms that support it. //! -//! NOTE: When hooking for some/all algorithms is enabled, those that remain "un-hooked" -//! by the user will NOT use the software implementations provided by MbedTLS, +//! NOTE: For crypto algorithms specifically, when hooking is enabled, those that remain +//! "un-hooked" by the user will NOT use the software implementations provided by MbedTLS, //! but rather - RustCrypto based ones! pub mod digest; pub mod exp_mod; +#[cfg(feature = "hook-timer")] +pub mod timer; +#[cfg(feature = "hook-wall-clock")] +pub mod wall_clock; /// The work area memory type used by MbedTLS algorithms' hooks pub type WorkAreaMemory = [u8]; diff --git a/mbedtls-rs-sys/src/hook/timer.rs b/mbedtls-rs-sys/src/hook/timer.rs new file mode 100644 index 00000000..cab9c343 --- /dev/null +++ b/mbedtls-rs-sys/src/hook/timer.rs @@ -0,0 +1,70 @@ +use crate::mbedtls_ms_time_t; + +pub trait MbedtlsTimer { + /// Get monotonic time in milliseconds. + /// + /// This should return a monotonically increasing value representing elapsed + /// milliseconds since an arbitrary epoch (e.g., system boot). This is used + /// for duration measurements, not calendar time. + fn now(&self) -> mbedtls_ms_time_t; +} + +/// Hook the timer function +/// +/// # Safety +/// - This function is unsafe because it modifies global state that affects +/// the behavior of MbedTLS. The caller MUST call this hook BEFORE +/// any MbedTLS functions that use time-based operations, +/// and ensure that the timer implementation is valid for the duration of its use. +pub unsafe fn hook_timer(timer: Option<&'static (dyn MbedtlsTimer + Send + Sync)>) { + critical_section::with(|cs| { + #[allow(clippy::if_same_then_else)] + if timer.is_some() { + debug!("TIMER hook: added custom impl"); + } else { + debug!("TIMER hook: removed"); + } + + alt::TIMER.borrow(cs).set(timer); + }); +} + +mod alt { + use crate::{mbedtls_ms_time_t, mbedtls_time_t}; + use core::cell::Cell; + use critical_section::Mutex; + + use super::MbedtlsTimer; + + pub(crate) static TIMER: Mutex>> = + Mutex::new(Cell::new(None)); + + /// Get current time in milliseconds since epoch. + /// + /// The time does not need to be correct, only time differences are used by MbedTls + #[no_mangle] + unsafe extern "C" fn mbedtls_ms_time() -> mbedtls_ms_time_t { + if let Some(timer) = critical_section::with(|cs| TIMER.borrow(cs).get()) { + timer.now() + } else { + 0 + } + } + + /// Get current time in seconds since epoch. + /// + /// The time does not need to be correct, only time differences are used by MbedTls + #[no_mangle] + unsafe extern "C" fn mbedtls_sec_time(timer: *mut mbedtls_time_t) -> mbedtls_time_t { + let time = if let Some(t) = critical_section::with(|cs| TIMER.borrow(cs).get()) { + t.now() / 1000 + } else { + 0 + } as mbedtls_time_t; + + if !timer.is_null() { + *timer = time; + } + time + } +} diff --git a/mbedtls-rs-sys/src/hook/wall_clock.rs b/mbedtls-rs-sys/src/hook/wall_clock.rs new file mode 100644 index 00000000..c72a8bcf --- /dev/null +++ b/mbedtls-rs-sys/src/hook/wall_clock.rs @@ -0,0 +1,102 @@ +use crate::tm; +pub trait MbedtlsWallClock { + /// Get current wall clock time as broken-down time structure. + /// + /// Returns the current calendar time in UTC as a `tm` structure. + /// + /// The `tm` struct contains the following fields: + /// - `tm_sec`: seconds after the minute - [0, 60] + /// - `tm_min`: minutes after the hour - [0, 59] + /// - `tm_hour`: hours since midnight - [0, 23] + /// - `tm_mday`: day of the month - [1, 31] + /// - `tm_mon`: months since January - [0, 11] + /// - `tm_year`: years since 1900 + /// - `tm_wday`: days since Sunday - [0, 6] + /// - `tm_yday`: days since January 1 - [0, 365] + /// - `tm_isdst`: Daylight Saving Time flag + /// + /// # Note + /// This function should return the current wall clock time. The wall clock implementation is + /// decoupled from the timer implementation (which provides monotonic timing for timeouts). + /// MbedTLS uses this for X.509 certificate time validation. + /// + /// # Returns + /// - `tm` - Current time as a broken-down time structure + fn instant(&self) -> tm; +} + +/// Hook the wall clock function +/// +/// # Safety +/// - This function is unsafe because it modifies global state that affects +/// the behavior of MbedTLS. The caller MUST call this hook BEFORE +/// any MbedTLS functions that need wall clock time (e.g., X.509 certificate +/// time validation), and ensure that the wall clock implementation is valid +/// for the duration of its use. +pub unsafe fn hook_wall_clock(wc: Option<&'static (dyn MbedtlsWallClock + Send + Sync)>) { + critical_section::with(|cs| { + #[allow(clippy::if_same_then_else)] + if wc.is_some() { + debug!("Wall Clock hook: added custom impl"); + } else { + debug!("Wall Clock hook: removed"); + } + + alt::WALL_CLOCK.borrow(cs).set(wc); + }); +} + +mod alt { + use crate::{mbedtls_time_t, tm}; + use core::cell::Cell; + use core::ptr; + use critical_section::Mutex; + + use super::MbedtlsWallClock; + + pub(crate) static WALL_CLOCK: Mutex>> = + Mutex::new(Cell::new(None)); + + /// Get current wall clock time as broken-down time in UTC. + /// + /// MbedTLS calls this function from X.509 certificate validation code + /// (`x509_get_current_time` and `x509_crt_verify_chain`) to get the current + /// calendar time. Although the standard `gmtime_r` signature takes a timestamp + /// to convert, MbedTLS always calls this with a freshly retrieved value from + /// `mbedtls_time(NULL)`. + /// + /// This implementation ignores the timestamp parameter and returns the current + /// wall clock time directly. This decouples the wall clock (calendar time) from + /// the timer (monotonic timing used for timeouts), allowing separate implementations + /// for each concern. + /// + /// # Parameters + /// - `_tt`: Ignored. MbedTLS passes `mbedtls_time(NULL)` here, but we return + /// current wall clock time regardless of this value. + /// - `tm_buf`: Pointer to buffer where the result will be written + /// + /// # Returns + /// Pointer to `tm_buf` on success, or null if: + /// - `tm_buf` is null + /// - No wall clock implementation is hooked + #[no_mangle] + unsafe extern "C" fn mbedtls_platform_gmtime_r( + _tt: *const mbedtls_time_t, + tm_buf: *mut tm, + ) -> *mut tm { + if tm_buf.is_null() { + return ptr::null_mut(); + } + + critical_section::with(|cs| { + WALL_CLOCK + .borrow(cs) + .get() + .map(|wc| { + *tm_buf = wc.instant(); + tm_buf + }) + .unwrap_or_default() + }) + } +} diff --git a/mbedtls-rs-sys/src/lib.rs b/mbedtls-rs-sys/src/lib.rs index 6d044a6b..01a4e199 100644 --- a/mbedtls-rs-sys/src/lib.rs +++ b/mbedtls-rs-sys/src/lib.rs @@ -16,8 +16,12 @@ mod extra_impls; // TODO: Figure out if we still need this #[cfg(not(target_os = "espidf"))] pub mod accel; #[cfg(not(target_os = "espidf"))] +pub mod clock; +#[cfg(not(target_os = "espidf"))] pub mod hook; pub mod self_test; +#[cfg(not(target_os = "espidf"))] +pub mod timer; #[allow( non_camel_case_types, diff --git a/mbedtls-rs-sys/src/timer.rs b/mbedtls-rs-sys/src/timer.rs new file mode 100644 index 00000000..1d76de3e --- /dev/null +++ b/mbedtls-rs-sys/src/timer.rs @@ -0,0 +1,5 @@ +#[cfg(feature = "timer-embassy")] +pub mod embassy; + +#[cfg(feature = "timer-std")] +pub mod std; diff --git a/mbedtls-rs-sys/src/timer/embassy.rs b/mbedtls-rs-sys/src/timer/embassy.rs new file mode 100644 index 00000000..49e549ce --- /dev/null +++ b/mbedtls-rs-sys/src/timer/embassy.rs @@ -0,0 +1,31 @@ +use crate::hook::timer::MbedtlsTimer; +use crate::mbedtls_ms_time_t; + +/// Embassy-based timer backend for MbedTLS timeout operations. +/// +/// Uses `embassy_time::Instant` to provide monotonic millisecond timing. +/// +/// # Usage +/// ```no_run +/// use esp_mbedtls_sys::timer::{hook_timer, embassy::EmbassyTimer}; +/// +/// // Create a static timer instance (using static_cell or similar) +/// static TIMER: EmbassyTimer = EmbassyTimer; +/// +/// unsafe { +/// hook_timer(Some(&TIMER)); +/// } +/// // ... use MbedTLS ... +/// unsafe { +/// hook_timer(None); +/// } +/// ``` +#[derive(Debug, Default)] +pub struct EmbassyTimer; + +impl MbedtlsTimer for EmbassyTimer { + fn now(&self) -> mbedtls_ms_time_t { + let ms = embassy_time::Instant::now().as_millis(); + mbedtls_ms_time_t::try_from(ms).unwrap_or(mbedtls_ms_time_t::MAX) + } +} diff --git a/mbedtls-rs-sys/src/timer/std.rs b/mbedtls-rs-sys/src/timer/std.rs new file mode 100644 index 00000000..09537363 --- /dev/null +++ b/mbedtls-rs-sys/src/timer/std.rs @@ -0,0 +1,25 @@ +extern crate std; + +use std::sync::OnceLock; +use std::time::Instant; + +use crate::hook::timer::MbedtlsTimer; +use crate::mbedtls_ms_time_t; + +static EPOCH: OnceLock = OnceLock::new(); + +/// Standard library timer backend for MbedTLS timer operations. +/// +/// Uses `std::time::Instant` to provide monotonic time measurements. +/// The first call to `now()` establishes the epoch, and all subsequent +/// calls return milliseconds elapsed since that epoch. +#[derive(Debug, Default)] +pub struct StdTimer; + +impl MbedtlsTimer for StdTimer { + fn now(&self) -> mbedtls_ms_time_t { + let epoch = EPOCH.get_or_init(|| Instant::now()); + let ms = Instant::now().duration_since(*epoch).as_millis(); + mbedtls_ms_time_t::try_from(ms).unwrap_or(mbedtls_ms_time_t::MAX) + } +} diff --git a/mbedtls-rs/Cargo.toml b/mbedtls-rs/Cargo.toml index c590b56f..0a44b59d 100644 --- a/mbedtls-rs/Cargo.toml +++ b/mbedtls-rs/Cargo.toml @@ -17,11 +17,17 @@ log = ["dep:log", "mbedtls-rs-sys/log"] use-gcc = ["mbedtls-rs-sys/use-gcc"] force-generate-bindings = ["mbedtls-rs-sys/force-generate-bindings"] force-esp-riscv-gcc = ["mbedtls-rs-sys/force-esp-riscv-gcc"] + nohook = ["mbedtls-rs-sys/nohook"] nohook-sha1 = ["mbedtls-rs-sys/nohook-sha1"] nohook-sha256 = ["mbedtls-rs-sys/nohook-sha256"] nohook-sha512 = ["mbedtls-rs-sys/nohook-sha512"] nohook-exp-mod = ["mbedtls-rs-sys/nohook-exp-mod"] + +# Time hooks: inclusion model (opt-in, new features) +hook-timer = ["mbedtls-rs-sys/hook-timer"] +hook-wall-clock = ["mbedtls-rs-sys/hook-wall-clock"] + accel-esp32 = ["mbedtls-rs-sys/accel-esp32"] accel-esp32c2 = ["mbedtls-rs-sys/accel-esp32c2"] accel-esp32c3 = ["mbedtls-rs-sys/accel-esp32c3"] @@ -30,6 +36,18 @@ accel-esp32h2 = ["mbedtls-rs-sys/accel-esp32h2"] accel-esp32s2 = ["mbedtls-rs-sys/accel-esp32s2"] accel-esp32s3 = ["mbedtls-rs-sys/accel-esp32s3"] +timer-embassy = ["mbedtls-rs-sys/timer-embassy"] +timer-std = ["mbedtls-rs-sys/timer-std"] + +wall-clock-std = ["mbedtls-rs-sys/wall-clock-std"] +wall-clock-esp32 = ["mbedtls-rs-sys/wall-clock-esp32"] +wall-clock-esp32c2 = ["mbedtls-rs-sys/wall-clock-esp32c2"] +wall-clock-esp32c3 = ["mbedtls-rs-sys/wall-clock-esp32c3"] +wall-clock-esp32c6 = ["mbedtls-rs-sys/wall-clock-esp32c6"] +wall-clock-esp32h2 = ["mbedtls-rs-sys/wall-clock-esp32h2"] +wall-clock-esp32s2 = ["mbedtls-rs-sys/wall-clock-esp32s2"] +wall-clock-esp32s3 = ["mbedtls-rs-sys/wall-clock-esp32s3"] + [dependencies] mbedtls-rs-sys = { path = "../mbedtls-rs-sys", default-features = false } defmt = { version = "1", optional = true } diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 4e9d9443..2ef2b3f9 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -1,12 +1,9 @@ -use std::env; use std::path::PathBuf; use anyhow::Result; use clap::{Parser, Subcommand}; -use enumset::EnumSet; - use log::LevelFilter; use tempdir::TempDir; @@ -39,6 +36,14 @@ enum Commands { #[arg(short = 'e', long = "force-esp-riscv-gcc")] force_esp_riscv_gcc: bool, + /// Enable timer hook support + #[arg(long = "timer")] + timer: bool, + + /// Enable wall clock hook support + #[arg(long = "wall-clock")] + wall_clock: bool, + /// Target triple for which to generate bindings and `.a` libraries target: String, }, @@ -62,6 +67,8 @@ fn main() -> Result<()> { target, use_gcc, force_esp_riscv_gcc, + timer, + wall_clock, }) = args.command { let use_gcc = use_gcc || force_esp_riscv_gcc; @@ -69,8 +76,17 @@ fn main() -> Result<()> { // For clang, use our own cross-platform sysroot let sysroot = (!use_gcc).then(|| sys_crate_root_path.join("gen").join("sysroot")); + // Build hooks set based on CLI flags + let mut hooks = builder::DEFAULT_HOOKS; + if timer { + hooks |= builder::Hook::Timer; + } + if wall_clock { + hooks |= builder::Hook::WallClock; + } + let builder = builder::MbedtlsBuilder::new( - EnumSet::all(), + hooks, !use_gcc, sys_crate_root_path.clone(), Some(target.clone()), @@ -100,6 +116,7 @@ fn main() -> Result<()> { .join(format!("{target}.rs")), ), )?; + } Ok(())