From b8b7793bd966b5ea2f6bd673c64aeaf33918e5b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Tue, 26 Aug 2025 16:38:48 +0200 Subject: [PATCH] Move SHA algos to metadata (#3991) --- esp-hal/src/sha.rs | 240 ++++++------------ .../src/_build_script_utils.rs | 72 ------ .../src/_generated_esp32.rs | 17 ++ .../src/_generated_esp32c2.rs | 16 ++ .../src/_generated_esp32c3.rs | 16 ++ .../src/_generated_esp32c6.rs | 16 ++ .../src/_generated_esp32h2.rs | 16 ++ .../src/_generated_esp32s2.rs | 25 ++ .../src/_generated_esp32s3.rs | 25 ++ esp-metadata/devices/esp32.toml | 2 +- esp-metadata/devices/esp32c2.toml | 2 +- esp-metadata/devices/esp32c3.toml | 2 +- esp-metadata/devices/esp32c6.toml | 2 +- esp-metadata/devices/esp32h2.toml | 2 +- esp-metadata/devices/esp32s2.toml | 11 +- esp-metadata/devices/esp32s3.toml | 11 +- esp-metadata/src/cfg.rs | 4 +- esp-metadata/src/cfg/sha.rs | 165 ++++++++++++ 18 files changed, 381 insertions(+), 263 deletions(-) create mode 100644 esp-metadata/src/cfg/sha.rs diff --git a/esp-hal/src/sha.rs b/esp-hal/src/sha.rs index 020bd85dd..1a7ab0924 100644 --- a/esp-hal/src/sha.rs +++ b/esp-hal/src/sha.rs @@ -8,15 +8,15 @@ //! ## Configuration //! This driver allows you to perform cryptographic hash operations using //! various hash algorithms supported by the SHA peripheral, such as: -//! * SHA-1 -//! * SHA-224 -//! * SHA-256 -//! * SHA-384 -//! * SHA-512 +//! * SHA-1 +//! * SHA-224 +//! * SHA-256 +//! * SHA-384 +//! * SHA-512 //! //! The driver supports two working modes: -//! * Typical SHA -//! * DMA-SHA +//! * Typical SHA (CPU-driven) +//! * DMA-SHA (not supported yet) //! //! It provides functions to update the hash calculation with input data, finish //! the hash calculation and retrieve the resulting hash value. The SHA @@ -54,8 +54,6 @@ //! //! # {after_snippet} //! ``` -//! ## Implementation State -//! - DMA-SHA Mode is not supported. use core::{borrow::Borrow, convert::Infallible, marker::PhantomData, mem::size_of}; @@ -540,146 +538,55 @@ impl<'d, A: ShaAlgorithm, S: Borrow>> digest::FixedOutput for ShaDigest< } } -/// This macro implements the Sha<'a, Dm> trait for a specified Sha algorithm -/// and a set of parameters -macro_rules! impl_sha { - ($name: ident, $digest_length: literal) => { - /// A SHA implementation struct. - /// - /// This struct is generated by the macro and represents a specific SHA hashing - /// algorithm (e.g., SHA-256, SHA-1). It manages the context and state required - /// for processing data using the selected hashing algorithm. - /// - /// The struct provides various functionalities such as initializing the hashing - /// process, updating the internal state with new data, and finalizing the - /// hashing operation to generate the final digest. +for_each_sha_algorithm! { + (algos $( ( $name:ident, $full_name:literal $sizes:tt $security:tt, $mode_bits:literal ) ),*) => { + + /// Specifies particular SHA algorithm. + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] + #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[non_exhaustive] - pub struct $name; - - impl crate::private::Sealed for $name {} - - impl $crate::sha::ShaAlgorithm for $name { - const ALGORITHM: &'static str = stringify!($name); - const ALGORITHM_KIND: ShaAlgorithmKind = ShaAlgorithmKind::$name; - - const CHUNK_LENGTH: usize = Self::ALGORITHM_KIND.chunk_length(); - - const DIGEST_LENGTH: usize = $digest_length; - - // We use paste to append `U` to the digest size to match a const defined in - // digest - type DigestOutputSize = paste::paste!(digest::consts::[< U $digest_length >]); + pub enum ShaAlgorithmKind { + $( + #[doc = concat!("The ", $full_name, " algorithm.")] + $name, + )* } }; } -/// Specifies particular SHA algorithm. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -#[non_exhaustive] -pub enum ShaAlgorithmKind { - /// The SHA-1 algorithm. - /// - /// Note that this algorithm is known to be insecure against collision attacks and length - /// extension attacks. - #[cfg(sha_algo_sha_1)] - Sha1, +for_each_sha_algorithm! { + (algos $( ( $name:ident, $full_name:literal (sizes: $block_size:literal, $digest_words:literal, $message_length_bytes:literal) $security:tt, $mode_bits:literal ) ),*) => { + impl ShaAlgorithmKind { + #[cfg(not(esp32))] + const fn mode_bits(self) -> u8 { + match self { + $(ShaAlgorithmKind::$name => $mode_bits,)* + } + } - /// The SHA-224 algorithm. - /// - /// Note that this algorithm is known to be insecure against length extension attacks. - #[cfg(sha_algo_sha_224)] - Sha224, + const fn chunk_length(self) -> usize { + match self { + $(ShaAlgorithmKind::$name => $block_size,)* + } + } - /// The SHA-256 algorithm. - /// - /// Note that this algorithm is known to be insecure against length extension attacks. - #[cfg(sha_algo_sha_256)] - Sha256, + /// Bytes needed to represent the length of the longest possible message. + const fn message_length_bytes(self) -> usize { + match self { + $(ShaAlgorithmKind::$name => $message_length_bytes,)* + } + } - /// The SHA-384 algorithm. - #[cfg(sha_algo_sha_384)] - Sha384, - - /// The SHA-512 algorithm. - /// - /// Note that this algorithm is known to be insecure against length extension attacks. - #[cfg(sha_algo_sha_512)] - Sha512, - - /// The SHA-512/224 algorithm. - #[cfg(sha_algo_sha_512_224)] - Sha512_224, - - /// The SHA-512/256 algorithm. - #[cfg(sha_algo_sha_512_256)] - Sha512_256, - // TODO - // #[allow(non_camel_case_types)] - // #[cfg(sha_algo_sha_512_t)] - // Sha512_t(u16), + const fn digest_length(self) -> usize { + match self { + $(ShaAlgorithmKind::$name => $digest_words,)* + } + } + } + }; } impl ShaAlgorithmKind { - #[cfg(not(esp32))] - const fn mode_bits(self) -> u8 { - match self { - #[cfg(sha_algo_sha_1)] - ShaAlgorithmKind::Sha1 => 0, - #[cfg(sha_algo_sha_224)] - ShaAlgorithmKind::Sha224 => 1, - #[cfg(sha_algo_sha_256)] - ShaAlgorithmKind::Sha256 => 2, - #[cfg(sha_algo_sha_384)] - ShaAlgorithmKind::Sha384 => 3, - #[cfg(sha_algo_sha_512)] - ShaAlgorithmKind::Sha512 => 4, - #[cfg(sha_algo_sha_512_224)] - ShaAlgorithmKind::Sha512_224 => 5, - #[cfg(sha_algo_sha_512_256)] - ShaAlgorithmKind::Sha512_256 => 6, - } - } - - const fn chunk_length(self) -> usize { - match self { - #[cfg(sha_algo_sha_1)] - ShaAlgorithmKind::Sha1 => 64, - #[cfg(sha_algo_sha_224)] - ShaAlgorithmKind::Sha224 => 64, - #[cfg(sha_algo_sha_256)] - ShaAlgorithmKind::Sha256 => 64, - #[cfg(sha_algo_sha_384)] - ShaAlgorithmKind::Sha384 => 128, - #[cfg(sha_algo_sha_512)] - ShaAlgorithmKind::Sha512 => 128, - #[cfg(sha_algo_sha_512_224)] - ShaAlgorithmKind::Sha512_224 => 128, - #[cfg(sha_algo_sha_512_256)] - ShaAlgorithmKind::Sha512_256 => 128, - } - } - - /// Bytes needed to represent the length of the longest possible message. - const fn message_length_bytes(self) -> usize { - match self { - #[cfg(sha_algo_sha_1)] - ShaAlgorithmKind::Sha1 => 8, - #[cfg(sha_algo_sha_224)] - ShaAlgorithmKind::Sha224 => 8, - #[cfg(sha_algo_sha_256)] - ShaAlgorithmKind::Sha256 => 8, - #[cfg(sha_algo_sha_384)] - ShaAlgorithmKind::Sha384 => 16, - #[cfg(sha_algo_sha_512)] - ShaAlgorithmKind::Sha512 => 16, - #[cfg(sha_algo_sha_512_224)] - ShaAlgorithmKind::Sha512_224 => 16, - #[cfg(sha_algo_sha_512_256)] - ShaAlgorithmKind::Sha512_256 => 16, - } - } - fn start(self, sha: &crate::peripherals::SHA<'_>) { let regs = sha.register_block(); cfg_if::cfg_if! { @@ -753,33 +660,36 @@ impl ShaAlgorithmKind { } } -// All the hash algorithms introduced in FIPS PUB 180-4 Spec. -// – SHA-1 -// – SHA-224 -// – SHA-256 -// – SHA-384 -// – SHA-512 -// – SHA-512/224 -// – SHA-512/256 -// – SHA-512/t (not implemented yet) -// Two working modes -// – Typical SHA -// – DMA-SHA (not implemented yet) -#[cfg(sha_algo_sha_1)] -impl_sha!(Sha1, 20); -#[cfg(sha_algo_sha_224)] -impl_sha!(Sha224, 28); -#[cfg(sha_algo_sha_256)] -impl_sha!(Sha256, 32); -#[cfg(sha_algo_sha_384)] -impl_sha!(Sha384, 48); -#[cfg(sha_algo_sha_512)] -impl_sha!(Sha512, 64); -#[cfg(sha_algo_sha_512_224)] -impl_sha!(Sha512_224, 28); -#[cfg(sha_algo_sha_512_256)] -impl_sha!(Sha512_256, 32); -// TODO: Allow/Implement SHA512_(u16) +// This macro call creates Sha algorithm structs that implement the ShaAlgorithm trait. +for_each_sha_algorithm! { + ( $name:ident, $full_name:literal (sizes: $block_size:literal, $digest_words:literal, $message_length_bytes:literal) (insecure_against: $($attack_kind:literal),*), $mode_bits:literal ) => { + #[doc = concat!("Hardware-accelerated ", $full_name, " implementation")] + /// + /// This struct manages the context and state required for processing data using the selected hashing algorithm. + /// + /// The struct provides various functionalities such as initializing the hashing + /// process, updating the internal state with new data, and finalizing the + /// hashing operation to generate the final digest. + $( + #[doc = ""] + #[doc = concat!(" > ⚠️ Note that this algorithm is known to be insecure against ", $attack_kind, " attacks.")] + )* + #[non_exhaustive] + pub struct $name; + + impl crate::private::Sealed for $name {} + + impl ShaAlgorithm for $name { + const ALGORITHM: &'static str = stringify!($name); + const ALGORITHM_KIND: ShaAlgorithmKind = ShaAlgorithmKind::$name; + + const CHUNK_LENGTH: usize = Self::ALGORITHM_KIND.chunk_length(); + const DIGEST_LENGTH: usize = Self::ALGORITHM_KIND.digest_length(); + + type DigestOutputSize = paste::paste!(digest::consts::[< U $digest_words >]); + } + }; +} fn h_mem(sha: &crate::peripherals::SHA<'_>, index: usize) -> *mut u32 { let sha = sha.register_block(); diff --git a/esp-metadata-generated/src/_build_script_utils.rs b/esp-metadata-generated/src/_build_script_utils.rs index 1c13f56cb..d3f5388b0 100644 --- a/esp-metadata-generated/src/_build_script_utils.rs +++ b/esp-metadata-generated/src/_build_script_utils.rs @@ -289,10 +289,6 @@ impl Chip { "rng_apb_cycle_wait_num=\"16\"", "rsa_size_increment=\"512\"", "rsa_memory_size_bytes=\"512\"", - "sha_algo_sha_1", - "sha_algo_sha_256", - "sha_algo_sha_384", - "sha_algo_sha_512", "timergroup_timg_has_timer1", "uart_ram_size=\"128\"", "has_dram_region", @@ -447,10 +443,6 @@ impl Chip { "cargo:rustc-cfg=rng_apb_cycle_wait_num=\"16\"", "cargo:rustc-cfg=rsa_size_increment=\"512\"", "cargo:rustc-cfg=rsa_memory_size_bytes=\"512\"", - "cargo:rustc-cfg=sha_algo_sha_1", - "cargo:rustc-cfg=sha_algo_sha_256", - "cargo:rustc-cfg=sha_algo_sha_384", - "cargo:rustc-cfg=sha_algo_sha_512", "cargo:rustc-cfg=timergroup_timg_has_timer1", "cargo:rustc-cfg=uart_ram_size=\"128\"", "cargo:rustc-cfg=has_dram_region", @@ -566,9 +558,6 @@ impl Chip { "interrupts_status_registers=\"2\"", "rng_apb_cycle_wait_num=\"16\"", "sha_dma", - "sha_algo_sha_1", - "sha_algo_sha_224", - "sha_algo_sha_256", "timergroup_timg_has_divcnt_rst", "timergroup_default_clock_source=\"0\"", "timergroup_default_clock_source_is_set", @@ -684,9 +673,6 @@ impl Chip { "cargo:rustc-cfg=interrupts_status_registers=\"2\"", "cargo:rustc-cfg=rng_apb_cycle_wait_num=\"16\"", "cargo:rustc-cfg=sha_dma", - "cargo:rustc-cfg=sha_algo_sha_1", - "cargo:rustc-cfg=sha_algo_sha_224", - "cargo:rustc-cfg=sha_algo_sha_256", "cargo:rustc-cfg=timergroup_timg_has_divcnt_rst", "cargo:rustc-cfg=timergroup_default_clock_source=\"0\"", "cargo:rustc-cfg=timergroup_default_clock_source_is_set", @@ -836,9 +822,6 @@ impl Chip { "rsa_size_increment=\"32\"", "rsa_memory_size_bytes=\"384\"", "sha_dma", - "sha_algo_sha_1", - "sha_algo_sha_224", - "sha_algo_sha_256", "timergroup_timg_has_divcnt_rst", "timergroup_default_clock_source=\"0\"", "timergroup_default_clock_source_is_set", @@ -984,9 +967,6 @@ impl Chip { "cargo:rustc-cfg=rsa_size_increment=\"32\"", "cargo:rustc-cfg=rsa_memory_size_bytes=\"384\"", "cargo:rustc-cfg=sha_dma", - "cargo:rustc-cfg=sha_algo_sha_1", - "cargo:rustc-cfg=sha_algo_sha_224", - "cargo:rustc-cfg=sha_algo_sha_256", "cargo:rustc-cfg=timergroup_timg_has_divcnt_rst", "cargo:rustc-cfg=timergroup_default_clock_source=\"0\"", "cargo:rustc-cfg=timergroup_default_clock_source_is_set", @@ -1189,9 +1169,6 @@ impl Chip { "rsa_size_increment=\"32\"", "rsa_memory_size_bytes=\"384\"", "sha_dma", - "sha_algo_sha_1", - "sha_algo_sha_224", - "sha_algo_sha_256", "timergroup_timg_has_divcnt_rst", "timergroup_default_clock_source=\"1\"", "timergroup_default_clock_source_is_set", @@ -1392,9 +1369,6 @@ impl Chip { "cargo:rustc-cfg=rsa_size_increment=\"32\"", "cargo:rustc-cfg=rsa_memory_size_bytes=\"384\"", "cargo:rustc-cfg=sha_dma", - "cargo:rustc-cfg=sha_algo_sha_1", - "cargo:rustc-cfg=sha_algo_sha_224", - "cargo:rustc-cfg=sha_algo_sha_256", "cargo:rustc-cfg=timergroup_timg_has_divcnt_rst", "cargo:rustc-cfg=timergroup_default_clock_source=\"1\"", "cargo:rustc-cfg=timergroup_default_clock_source_is_set", @@ -1576,9 +1550,6 @@ impl Chip { "rsa_size_increment=\"32\"", "rsa_memory_size_bytes=\"384\"", "sha_dma", - "sha_algo_sha_1", - "sha_algo_sha_224", - "sha_algo_sha_256", "timergroup_timg_has_divcnt_rst", "timergroup_default_clock_source=\"2\"", "timergroup_default_clock_source_is_set", @@ -1754,9 +1725,6 @@ impl Chip { "cargo:rustc-cfg=rsa_size_increment=\"32\"", "cargo:rustc-cfg=rsa_memory_size_bytes=\"384\"", "cargo:rustc-cfg=sha_dma", - "cargo:rustc-cfg=sha_algo_sha_1", - "cargo:rustc-cfg=sha_algo_sha_224", - "cargo:rustc-cfg=sha_algo_sha_256", "cargo:rustc-cfg=timergroup_timg_has_divcnt_rst", "cargo:rustc-cfg=timergroup_default_clock_source=\"2\"", "cargo:rustc-cfg=timergroup_default_clock_source_is_set", @@ -1928,14 +1896,6 @@ impl Chip { "rsa_size_increment=\"32\"", "rsa_memory_size_bytes=\"512\"", "sha_dma", - "sha_algo_sha_1", - "sha_algo_sha_224", - "sha_algo_sha_256", - "sha_algo_sha_384", - "sha_algo_sha_512", - "sha_algo_sha_512_224", - "sha_algo_sha_512_256", - "sha_algo_sha_512_t", "spi_master_has_octal", "timergroup_timg_has_timer1", "timergroup_default_clock_source=\"0\"", @@ -2102,14 +2062,6 @@ impl Chip { "cargo:rustc-cfg=rsa_size_increment=\"32\"", "cargo:rustc-cfg=rsa_memory_size_bytes=\"512\"", "cargo:rustc-cfg=sha_dma", - "cargo:rustc-cfg=sha_algo_sha_1", - "cargo:rustc-cfg=sha_algo_sha_224", - "cargo:rustc-cfg=sha_algo_sha_256", - "cargo:rustc-cfg=sha_algo_sha_384", - "cargo:rustc-cfg=sha_algo_sha_512", - "cargo:rustc-cfg=sha_algo_sha_512_224", - "cargo:rustc-cfg=sha_algo_sha_512_256", - "cargo:rustc-cfg=sha_algo_sha_512_t", "cargo:rustc-cfg=spi_master_has_octal", "cargo:rustc-cfg=timergroup_timg_has_timer1", "cargo:rustc-cfg=timergroup_default_clock_source=\"0\"", @@ -2296,14 +2248,6 @@ impl Chip { "rsa_size_increment=\"32\"", "rsa_memory_size_bytes=\"512\"", "sha_dma", - "sha_algo_sha_1", - "sha_algo_sha_224", - "sha_algo_sha_256", - "sha_algo_sha_384", - "sha_algo_sha_512", - "sha_algo_sha_512_224", - "sha_algo_sha_512_256", - "sha_algo_sha_512_t", "spi_master_has_octal", "timergroup_timg_has_timer1", "timergroup_default_clock_source=\"0\"", @@ -2486,14 +2430,6 @@ impl Chip { "cargo:rustc-cfg=rsa_size_increment=\"32\"", "cargo:rustc-cfg=rsa_memory_size_bytes=\"512\"", "cargo:rustc-cfg=sha_dma", - "cargo:rustc-cfg=sha_algo_sha_1", - "cargo:rustc-cfg=sha_algo_sha_224", - "cargo:rustc-cfg=sha_algo_sha_256", - "cargo:rustc-cfg=sha_algo_sha_384", - "cargo:rustc-cfg=sha_algo_sha_512", - "cargo:rustc-cfg=sha_algo_sha_512_224", - "cargo:rustc-cfg=sha_algo_sha_512_256", - "cargo:rustc-cfg=sha_algo_sha_512_t", "cargo:rustc-cfg=spi_master_has_octal", "cargo:rustc-cfg=timergroup_timg_has_timer1", "cargo:rustc-cfg=timergroup_default_clock_source=\"0\"", @@ -2644,10 +2580,6 @@ impl Config { println!("cargo:rustc-check-cfg=cfg(gpio_remap_iomux_pin_registers)"); println!("cargo:rustc-check-cfg=cfg(i2c_master_separate_filter_config_registers)"); println!("cargo:rustc-check-cfg=cfg(i2c_master_i2c0_data_register_ahb_address_is_set)"); - println!("cargo:rustc-check-cfg=cfg(sha_algo_sha_1)"); - println!("cargo:rustc-check-cfg=cfg(sha_algo_sha_256)"); - println!("cargo:rustc-check-cfg=cfg(sha_algo_sha_384)"); - println!("cargo:rustc-check-cfg=cfg(sha_algo_sha_512)"); println!("cargo:rustc-check-cfg=cfg(timergroup_timg_has_timer1)"); println!("cargo:rustc-check-cfg=cfg(esp32c2)"); println!("cargo:rustc-check-cfg=cfg(riscv)"); @@ -2692,7 +2624,6 @@ impl Config { println!("cargo:rustc-check-cfg=cfg(i2c_master_has_tx_fifo_watermark)"); println!("cargo:rustc-check-cfg=cfg(i2c_master_bus_timeout_is_exponential)"); println!("cargo:rustc-check-cfg=cfg(sha_dma)"); - println!("cargo:rustc-check-cfg=cfg(sha_algo_sha_224)"); println!("cargo:rustc-check-cfg=cfg(timergroup_timg_has_divcnt_rst)"); println!("cargo:rustc-check-cfg=cfg(timergroup_default_clock_source_is_set)"); println!("cargo:rustc-check-cfg=cfg(timergroup_default_wdt_clock_source_is_set)"); @@ -2785,9 +2716,6 @@ impl Config { println!("cargo:rustc-check-cfg=cfg(riscv_coproc_supported)"); println!("cargo:rustc-check-cfg=cfg(usb_otg)"); println!("cargo:rustc-check-cfg=cfg(aes_dma_mode_gcm)"); - println!("cargo:rustc-check-cfg=cfg(sha_algo_sha_512_224)"); - println!("cargo:rustc-check-cfg=cfg(sha_algo_sha_512_256)"); - println!("cargo:rustc-check-cfg=cfg(sha_algo_sha_512_t)"); println!("cargo:rustc-check-cfg=cfg(spi_master_has_octal)"); println!("cargo:rustc-check-cfg=cfg(esp32s3)"); println!("cargo:rustc-check-cfg=cfg(soc_has_interrupt_core1)"); diff --git a/esp-metadata-generated/src/_generated_esp32.rs b/esp-metadata-generated/src/_generated_esp32.rs index c0a98e332..bfc4fb15c 100644 --- a/esp-metadata-generated/src/_generated_esp32.rs +++ b/esp-metadata-generated/src/_generated_esp32.rs @@ -268,6 +268,23 @@ macro_rules! for_each_rsa_multiplication { _for_each_inner!((2048)); _for_each_inner!((all(512), (1024), (1536), (2048))); }; } +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_sha_algorithm { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} } + _for_each_inner!((Sha1, "SHA-1"(sizes : 64, 20, 8) (insecure_against : + "collision", "length extension"), 0)); _for_each_inner!((Sha256, "SHA-256"(sizes + : 64, 32, 8) (insecure_against : "length extension"), 0)); + _for_each_inner!((Sha384, "SHA-384"(sizes : 128, 48, 16) (insecure_against :), + 0)); _for_each_inner!((Sha512, "SHA-512"(sizes : 128, 64, 16) (insecure_against : + "length extension"), 0)); _for_each_inner!((algos(Sha1, "SHA-1"(sizes : 64, 20, + 8) (insecure_against : "collision", "length extension"), 0), (Sha256, + "SHA-256"(sizes : 64, 32, 8) (insecure_against : "length extension"), 0), + (Sha384, "SHA-384"(sizes : 128, 48, 16) (insecure_against :), 0), (Sha512, + "SHA-512"(sizes : 128, 64, 16) (insecure_against : "length extension"), 0))); + }; +} /// This macro can be used to generate code for each peripheral instance of the I2C master driver. /// /// For an explanation on the general syntax, as well as usage of individual/repeated diff --git a/esp-metadata-generated/src/_generated_esp32c2.rs b/esp-metadata-generated/src/_generated_esp32c2.rs index a4039e5f5..b07c5e0dc 100644 --- a/esp-metadata-generated/src/_generated_esp32c2.rs +++ b/esp-metadata-generated/src/_generated_esp32c2.rs @@ -210,6 +210,22 @@ macro_rules! for_each_soc_xtal_options { (40))); }; } +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_sha_algorithm { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} } + _for_each_inner!((Sha1, "SHA-1"(sizes : 64, 20, 8) (insecure_against : + "collision", "length extension"), 0)); _for_each_inner!((Sha224, "SHA-224"(sizes + : 64, 28, 8) (insecure_against : "length extension"), 1)); + _for_each_inner!((Sha256, "SHA-256"(sizes : 64, 32, 8) (insecure_against : + "length extension"), 2)); _for_each_inner!((algos(Sha1, "SHA-1"(sizes : 64, 20, + 8) (insecure_against : "collision", "length extension"), 0), (Sha224, + "SHA-224"(sizes : 64, 28, 8) (insecure_against : "length extension"), 1), + (Sha256, "SHA-256"(sizes : 64, 32, 8) (insecure_against : "length extension"), + 2))); + }; +} /// This macro can be used to generate code for each peripheral instance of the I2C master driver. /// /// For an explanation on the general syntax, as well as usage of individual/repeated diff --git a/esp-metadata-generated/src/_generated_esp32c3.rs b/esp-metadata-generated/src/_generated_esp32c3.rs index 6865b29e5..46465b42d 100644 --- a/esp-metadata-generated/src/_generated_esp32c3.rs +++ b/esp-metadata-generated/src/_generated_esp32c3.rs @@ -332,6 +332,22 @@ macro_rules! for_each_rsa_multiplication { (1344), (1376), (1408), (1440), (1472), (1504), (1536))); }; } +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_sha_algorithm { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} } + _for_each_inner!((Sha1, "SHA-1"(sizes : 64, 20, 8) (insecure_against : + "collision", "length extension"), 0)); _for_each_inner!((Sha224, "SHA-224"(sizes + : 64, 28, 8) (insecure_against : "length extension"), 1)); + _for_each_inner!((Sha256, "SHA-256"(sizes : 64, 32, 8) (insecure_against : + "length extension"), 2)); _for_each_inner!((algos(Sha1, "SHA-1"(sizes : 64, 20, + 8) (insecure_against : "collision", "length extension"), 0), (Sha224, + "SHA-224"(sizes : 64, 28, 8) (insecure_against : "length extension"), 1), + (Sha256, "SHA-256"(sizes : 64, 32, 8) (insecure_against : "length extension"), + 2))); + }; +} /// This macro can be used to generate code for each peripheral instance of the I2C master driver. /// /// For an explanation on the general syntax, as well as usage of individual/repeated diff --git a/esp-metadata-generated/src/_generated_esp32c6.rs b/esp-metadata-generated/src/_generated_esp32c6.rs index e5238e2ec..ef12f038f 100644 --- a/esp-metadata-generated/src/_generated_esp32c6.rs +++ b/esp-metadata-generated/src/_generated_esp32c6.rs @@ -344,6 +344,22 @@ macro_rules! for_each_rsa_multiplication { (1344), (1376), (1408), (1440), (1472), (1504), (1536))); }; } +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_sha_algorithm { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} } + _for_each_inner!((Sha1, "SHA-1"(sizes : 64, 20, 8) (insecure_against : + "collision", "length extension"), 0)); _for_each_inner!((Sha224, "SHA-224"(sizes + : 64, 28, 8) (insecure_against : "length extension"), 1)); + _for_each_inner!((Sha256, "SHA-256"(sizes : 64, 32, 8) (insecure_against : + "length extension"), 2)); _for_each_inner!((algos(Sha1, "SHA-1"(sizes : 64, 20, + 8) (insecure_against : "collision", "length extension"), 0), (Sha224, + "SHA-224"(sizes : 64, 28, 8) (insecure_against : "length extension"), 1), + (Sha256, "SHA-256"(sizes : 64, 32, 8) (insecure_against : "length extension"), + 2))); + }; +} /// This macro can be used to generate code for each peripheral instance of the I2C master driver. /// /// For an explanation on the general syntax, as well as usage of individual/repeated diff --git a/esp-metadata-generated/src/_generated_esp32h2.rs b/esp-metadata-generated/src/_generated_esp32h2.rs index 43f921b4d..e0daf1868 100644 --- a/esp-metadata-generated/src/_generated_esp32h2.rs +++ b/esp-metadata-generated/src/_generated_esp32h2.rs @@ -329,6 +329,22 @@ macro_rules! for_each_rsa_multiplication { (1344), (1376), (1408), (1440), (1472), (1504), (1536))); }; } +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_sha_algorithm { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} } + _for_each_inner!((Sha1, "SHA-1"(sizes : 64, 20, 8) (insecure_against : + "collision", "length extension"), 0)); _for_each_inner!((Sha224, "SHA-224"(sizes + : 64, 28, 8) (insecure_against : "length extension"), 1)); + _for_each_inner!((Sha256, "SHA-256"(sizes : 64, 32, 8) (insecure_against : + "length extension"), 2)); _for_each_inner!((algos(Sha1, "SHA-1"(sizes : 64, 20, + 8) (insecure_against : "collision", "length extension"), 0), (Sha224, + "SHA-224"(sizes : 64, 28, 8) (insecure_against : "length extension"), 1), + (Sha256, "SHA-256"(sizes : 64, 32, 8) (insecure_against : "length extension"), + 2))); + }; +} /// This macro can be used to generate code for each peripheral instance of the I2C master driver. /// /// For an explanation on the general syntax, as well as usage of individual/repeated diff --git a/esp-metadata-generated/src/_generated_esp32s2.rs b/esp-metadata-generated/src/_generated_esp32s2.rs index e225cbb6b..1fddc5b3e 100644 --- a/esp-metadata-generated/src/_generated_esp32s2.rs +++ b/esp-metadata-generated/src/_generated_esp32s2.rs @@ -354,6 +354,31 @@ macro_rules! for_each_rsa_multiplication { (1856), (1888), (1920), (1952), (1984), (2016), (2048))); }; } +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_sha_algorithm { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} } + _for_each_inner!((Sha1, "SHA-1"(sizes : 64, 20, 8) (insecure_against : + "collision", "length extension"), 0)); _for_each_inner!((Sha224, "SHA-224"(sizes + : 64, 28, 8) (insecure_against : "length extension"), 1)); + _for_each_inner!((Sha256, "SHA-256"(sizes : 64, 32, 8) (insecure_against : + "length extension"), 2)); _for_each_inner!((Sha384, "SHA-384"(sizes : 128, 48, + 16) (insecure_against :), 3)); _for_each_inner!((Sha512, "SHA-512"(sizes : 128, + 64, 16) (insecure_against : "length extension"), 4)); + _for_each_inner!((Sha512_224, "SHA-512/224"(sizes : 128, 28, 16) + (insecure_against :), 5)); _for_each_inner!((Sha512_256, "SHA-512/256"(sizes : + 128, 32, 16) (insecure_against :), 6)); _for_each_inner!((algos(Sha1, + "SHA-1"(sizes : 64, 20, 8) (insecure_against : "collision", "length extension"), + 0), (Sha224, "SHA-224"(sizes : 64, 28, 8) (insecure_against : + "length extension"), 1), (Sha256, "SHA-256"(sizes : 64, 32, 8) (insecure_against + : "length extension"), 2), (Sha384, "SHA-384"(sizes : 128, 48, 16) + (insecure_against :), 3), (Sha512, "SHA-512"(sizes : 128, 64, 16) + (insecure_against : "length extension"), 4), (Sha512_224, "SHA-512/224"(sizes : + 128, 28, 16) (insecure_against :), 5), (Sha512_256, "SHA-512/256"(sizes : 128, + 32, 16) (insecure_against :), 6))); + }; +} /// This macro can be used to generate code for each peripheral instance of the I2C master driver. /// /// For an explanation on the general syntax, as well as usage of individual/repeated diff --git a/esp-metadata-generated/src/_generated_esp32s3.rs b/esp-metadata-generated/src/_generated_esp32s3.rs index 7f1528a8c..7a68ab0f9 100644 --- a/esp-metadata-generated/src/_generated_esp32s3.rs +++ b/esp-metadata-generated/src/_generated_esp32s3.rs @@ -347,6 +347,31 @@ macro_rules! for_each_rsa_multiplication { (1856), (1888), (1920), (1952), (1984), (2016), (2048))); }; } +#[macro_export] +#[cfg_attr(docsrs, doc(cfg(feature = "_device-selected")))] +macro_rules! for_each_sha_algorithm { + ($($pattern:tt => $code:tt;)*) => { + macro_rules! _for_each_inner { $(($pattern) => $code;)* ($other : tt) => {} } + _for_each_inner!((Sha1, "SHA-1"(sizes : 64, 20, 8) (insecure_against : + "collision", "length extension"), 0)); _for_each_inner!((Sha224, "SHA-224"(sizes + : 64, 28, 8) (insecure_against : "length extension"), 1)); + _for_each_inner!((Sha256, "SHA-256"(sizes : 64, 32, 8) (insecure_against : + "length extension"), 2)); _for_each_inner!((Sha384, "SHA-384"(sizes : 128, 48, + 16) (insecure_against :), 3)); _for_each_inner!((Sha512, "SHA-512"(sizes : 128, + 64, 16) (insecure_against : "length extension"), 4)); + _for_each_inner!((Sha512_224, "SHA-512/224"(sizes : 128, 28, 16) + (insecure_against :), 5)); _for_each_inner!((Sha512_256, "SHA-512/256"(sizes : + 128, 32, 16) (insecure_against :), 6)); _for_each_inner!((algos(Sha1, + "SHA-1"(sizes : 64, 20, 8) (insecure_against : "collision", "length extension"), + 0), (Sha224, "SHA-224"(sizes : 64, 28, 8) (insecure_against : + "length extension"), 1), (Sha256, "SHA-256"(sizes : 64, 32, 8) (insecure_against + : "length extension"), 2), (Sha384, "SHA-384"(sizes : 128, 48, 16) + (insecure_against :), 3), (Sha512, "SHA-512"(sizes : 128, 64, 16) + (insecure_against : "length extension"), 4), (Sha512_224, "SHA-512/224"(sizes : + 128, 28, 16) (insecure_against :), 5), (Sha512_256, "SHA-512/256"(sizes : 128, + 32, 16) (insecure_against :), 6))); + }; +} /// This macro can be used to generate code for each peripheral instance of the I2C master driver. /// /// For an explanation on the general syntax, as well as usage of individual/repeated diff --git a/esp-metadata/devices/esp32.toml b/esp-metadata/devices/esp32.toml index 09ceac2d5..7a854439d 100644 --- a/esp-metadata/devices/esp32.toml +++ b/esp-metadata/devices/esp32.toml @@ -608,7 +608,7 @@ memory_size_bytes = 512 [device.sha] support_status = "partial" -algo = ["SHA-1", "SHA-256", "SHA-384", "SHA-512"] +algo = { sha1 = 0, sha256 = 0, sha384 = 0, sha512 = 0 } # fake mode bits, ESP32 has separate register sets [device.spi_master] support_status = "supported" diff --git a/esp-metadata/devices/esp32c2.toml b/esp-metadata/devices/esp32c2.toml index 554dbe9d0..0fd168c01 100644 --- a/esp-metadata/devices/esp32c2.toml +++ b/esp-metadata/devices/esp32c2.toml @@ -252,7 +252,7 @@ status_registers = 2 [device.sha] support_status = "partial" dma = true -algo = ["SHA-1", "SHA-224", "SHA-256"] +algo = { sha1 = 0, sha224 = 1, sha256 = 2 } [device.spi_master] support_status = "supported" diff --git a/esp-metadata/devices/esp32c3.toml b/esp-metadata/devices/esp32c3.toml index 69620db90..7fd3050a0 100644 --- a/esp-metadata/devices/esp32c3.toml +++ b/esp-metadata/devices/esp32c3.toml @@ -314,7 +314,7 @@ memory_size_bytes = 384 [device.sha] support_status = "partial" dma = true -algo = ["SHA-1", "SHA-224", "SHA-256"] +algo = { sha1 = 0, sha224 = 1, sha256 = 2 } [device.spi_master] support_status = "supported" diff --git a/esp-metadata/devices/esp32c6.toml b/esp-metadata/devices/esp32c6.toml index 421e6bf63..8032004ab 100644 --- a/esp-metadata/devices/esp32c6.toml +++ b/esp-metadata/devices/esp32c6.toml @@ -469,7 +469,7 @@ memory_size_bytes = 384 [device.sha] support_status = "partial" dma = true -algo = ["SHA-1", "SHA-224", "SHA-256"] +algo = { sha1 = 0, sha224 = 1, sha256 = 2 } [device.spi_master] support_status = "supported" diff --git a/esp-metadata/devices/esp32h2.toml b/esp-metadata/devices/esp32h2.toml index 0522c9151..a3e170fbd 100644 --- a/esp-metadata/devices/esp32h2.toml +++ b/esp-metadata/devices/esp32h2.toml @@ -386,7 +386,7 @@ memory_size_bytes = 384 [device.sha] support_status = "partial" dma = true -algo = ["SHA-1", "SHA-224", "SHA-256"] +algo = { sha1 = 0, sha224 = 1, sha256 = 2 } [device.spi_master] support_status = "supported" diff --git a/esp-metadata/devices/esp32s2.toml b/esp-metadata/devices/esp32s2.toml index 2a766b9df..791b25863 100644 --- a/esp-metadata/devices/esp32s2.toml +++ b/esp-metadata/devices/esp32s2.toml @@ -430,16 +430,7 @@ memory_size_bytes = 512 [device.sha] support_status = "partial" dma = true -algo = [ - "SHA-1", - "SHA-224", - "SHA-256", - "SHA-384", - "SHA-512", - "SHA-512/224", - "SHA-512/256", - "SHA-512/t", -] +algo = { sha1 = 0, sha224 = 1, sha256 = 2, sha384 = 3, sha512 = 4, sha512_224 = 5, sha512_256 = 6, sha512_t = 7 } [device.spi_master] support_status = "supported" diff --git a/esp-metadata/devices/esp32s3.toml b/esp-metadata/devices/esp32s3.toml index 5e368f39b..d35847c7d 100644 --- a/esp-metadata/devices/esp32s3.toml +++ b/esp-metadata/devices/esp32s3.toml @@ -606,16 +606,7 @@ memory_size_bytes = 512 [device.sha] support_status = "partial" dma = true -algo = [ - "SHA-1", - "SHA-224", - "SHA-256", - "SHA-384", - "SHA-512", - "SHA-512/224", - "SHA-512/256", - "SHA-512/t", -] +algo = { sha1 = 0, sha224 = 1, sha256 = 2, sha384 = 3, sha512 = 4, sha512_224 = 5, sha512_256 = 6, sha512_t = 7 } [device.spi_master] support_status = "supported" diff --git a/esp-metadata/src/cfg.rs b/esp-metadata/src/cfg.rs index 1801e51fd..8d78bae2f 100644 --- a/esp-metadata/src/cfg.rs +++ b/esp-metadata/src/cfg.rs @@ -2,6 +2,7 @@ pub(crate) mod aes; pub(crate) mod gpio; pub(crate) mod i2c_master; pub(crate) mod rsa; +pub(crate) mod sha; pub(crate) mod soc; pub(crate) mod spi_master; pub(crate) mod spi_slave; @@ -10,6 +11,7 @@ pub(crate) mod uart; pub(crate) use aes::*; pub(crate) use gpio::*; pub(crate) use i2c_master::*; +pub(crate) use sha::*; pub(crate) use spi_master::*; pub(crate) use spi_slave::*; pub(crate) use uart::*; @@ -510,7 +512,7 @@ driver_configs![ #[serde(default)] dma: bool, #[serde(default)] - algo: Vec, + algo: ShaAlgoMap, } }, SpiMasterProperties { diff --git a/esp-metadata/src/cfg/sha.rs b/esp-metadata/src/cfg/sha.rs new file mode 100644 index 000000000..30bb42e55 --- /dev/null +++ b/esp-metadata/src/cfg/sha.rs @@ -0,0 +1,165 @@ +use proc_macro2::Ident; +use quote::{ToTokens, format_ident, quote}; +use serde::{Deserialize, Serialize}; + +use crate::{generate_for_each_macro, number}; + +struct ShaAlgo { + name: &'static str, + ident: Ident, + digest_words: u32, + block_size: u32, + message_len_bytes: u32, + // These bits come from + insecure_against_collision: bool, + insecure_against_length_extension: bool, +} + +#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize)] +pub struct ShaAlgoMap { + sha1: Option, + sha224: Option, + sha256: Option, + sha384: Option, + sha512: Option, + sha512_224: Option, + sha512_256: Option, + sha512_t: Option, +} + +impl super::GenericProperty for ShaAlgoMap { + fn for_each_macro(&self) -> Option { + let modes = [ + ("SHA-1", self.sha1), + ("SHA-224", self.sha224), + ("SHA-256", self.sha256), + ("SHA-384", self.sha384), + ("SHA-512", self.sha512), + ("SHA-512/224", self.sha512_224), + ("SHA-512/256", self.sha512_256), + ("SHA-512/t", self.sha512_t), + ]; + + let algos = modes + .into_iter() + .filter_map(|(name, mode)| mode.map(|m| (name, m))) + .filter_map(|(name, mode)| ShaAlgo::new(name).map(|name| (name, mode))) + .map(|(algo, mode)| { + let mode = number(mode); + quote! { #algo, #mode } + }) + .collect::>(); + + Some(generate_for_each_macro( + "sha_algorithm", + &[("algos", &algos)], + )) + } +} + +impl ShaAlgo { + fn new(algo: &str) -> Option { + let known = [ + Self { + name: "SHA-1", + ident: format_ident!("Sha1"), + digest_words: 20, + block_size: 64, + message_len_bytes: 8, + insecure_against_collision: true, + insecure_against_length_extension: true, + }, + Self { + name: "SHA-224", + ident: format_ident!("Sha224"), + digest_words: 28, + block_size: 64, + message_len_bytes: 8, + insecure_against_collision: false, + insecure_against_length_extension: true, + }, + Self { + name: "SHA-256", + ident: format_ident!("Sha256"), + digest_words: 32, + block_size: 64, + message_len_bytes: 8, + insecure_against_collision: false, + insecure_against_length_extension: true, + }, + Self { + name: "SHA-384", + ident: format_ident!("Sha384"), + digest_words: 48, + block_size: 128, + message_len_bytes: 16, + insecure_against_collision: false, + insecure_against_length_extension: false, + }, + Self { + name: "SHA-512", + ident: format_ident!("Sha512"), + digest_words: 64, + block_size: 128, + message_len_bytes: 16, + insecure_against_collision: false, + insecure_against_length_extension: true, + }, + Self { + name: "SHA-512/224", + ident: format_ident!("Sha512_224"), + digest_words: 28, + block_size: 128, + message_len_bytes: 16, + insecure_against_collision: false, + insecure_against_length_extension: false, + }, + Self { + name: "SHA-512/256", + ident: format_ident!("Sha512_256"), + digest_words: 32, + block_size: 128, + message_len_bytes: 16, + insecure_against_collision: false, + insecure_against_length_extension: false, + }, + ]; + + for a in known { + if a.name == algo { + return Some(a); + } + } + + // Special-case (ignore) general truncated algo until we figure out how to describe its + // `digest_words`. + if algo == "SHA-512/t" { + return None; + } + + panic!("Unknown SHA algorithm: {algo}") + } +} + +impl ToTokens for ShaAlgo { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + let ident = &self.ident; + let name = &self.name; + let digest_words = number(self.digest_words); + let block_size = number(self.block_size); + let message_len_bytes = number(self.message_len_bytes); + + let mut insecure = vec![]; + + if self.insecure_against_collision { + insecure.push("collision"); + } + if self.insecure_against_length_extension { + insecure.push("length extension"); + } + + tokens.extend( + quote! { #ident, #name (sizes: #block_size, #digest_words, #message_len_bytes) (insecure_against: #(#insecure),*) }, + ); + } +}