From 1b582ba202b795d578bc47838866712756cf475a Mon Sep 17 00:00:00 2001 From: cscherr Date: Fri, 18 Jul 2025 10:32:11 +0200 Subject: [PATCH] feat(alg): ffi for sha2 of algc --- .cargo/config.toml | 4 +- crates/algorithms/.cargo/config.toml | 13 -- .../algorithms/algorithms-c/src/hash/sha2.c | 2 +- .../algorithms/algorithms-c/src/hash/sha2.h | 2 +- .../algorithms-c/test/hash/test_sha2.c | 4 +- crates/algorithms/src/crc/ffi/crc32.rs | 8 +- crates/algorithms/src/ffi/mod.rs | 9 +- crates/algorithms/src/hash/ffi/mod.rs | 4 +- crates/algorithms/src/hash/ffi/sha1.rs | 0 crates/algorithms/src/hash/ffi/sha2.rs | 123 ++++++++++++++++++ crates/algorithms/src/hash/mod.rs | 4 +- crates/algorithms/src/hash/sha1.rs | 0 crates/algorithms/src/hash/sha2.rs | 15 +++ 13 files changed, 159 insertions(+), 29 deletions(-) delete mode 100755 crates/algorithms/.cargo/config.toml delete mode 100644 crates/algorithms/src/hash/ffi/sha1.rs create mode 100644 crates/algorithms/src/hash/ffi/sha2.rs delete mode 100644 crates/algorithms/src/hash/sha1.rs create mode 100644 crates/algorithms/src/hash/sha2.rs diff --git a/.cargo/config.toml b/.cargo/config.toml index 998b1b5..7cb5002 100755 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,8 +1,8 @@ [target.thumbv6m-none-eabi] runner = 'probe-rs run --chip STM32L053R8' -[build] -target = "thumbv6m-none-eabi" +# [build] +# target = "thumbv6m-none-eabi" [alias] arun = "run --target thumbv6m-none-eabi" diff --git a/crates/algorithms/.cargo/config.toml b/crates/algorithms/.cargo/config.toml deleted file mode 100755 index 2ee3037..0000000 --- a/crates/algorithms/.cargo/config.toml +++ /dev/null @@ -1,13 +0,0 @@ -[build] -target = "x86_64-unknown-linux-gnu" - -[alias] -abuild = "build --target thumbv6m-none-eabi" -atest = "test --target x86_64-unknown-linux-gnu" -abench = "bench --target x86_64-unknown-linux-gnu" -acheck = "check --target x86_64-unknown-linux-gnu" -aclippy = "clippy --target thumbv6m-none-eabi" -cflash = "flash --chip STM32L053R8" - -[env] -DEFMT_LOG = "trace" # sets the log level to trace diff --git a/crates/algorithms/algorithms-c/src/hash/sha2.c b/crates/algorithms/algorithms-c/src/hash/sha2.c index 1363237..997857f 100644 --- a/crates/algorithms/algorithms-c/src/hash/sha2.c +++ b/crates/algorithms/algorithms-c/src/hash/sha2.c @@ -401,7 +401,7 @@ SHA2Result sha2_256_result(SHA2Context *context, SHA2Digest digest) { return shaSuccess; } -SHA2Result sha2_256_oneshot(const uint8_t *data, const size_t len, +SHA2Result sha2_256_oneshot(const uint8_t data[], const size_t len, SHA2Digest digest) { SHA2Context context; SHA2Result res; diff --git a/crates/algorithms/algorithms-c/src/hash/sha2.h b/crates/algorithms/algorithms-c/src/hash/sha2.h index dfee25c..900e099 100644 --- a/crates/algorithms/algorithms-c/src/hash/sha2.h +++ b/crates/algorithms/algorithms-c/src/hash/sha2.h @@ -43,7 +43,7 @@ typedef struct SHA2Context { } SHA2Context; /** data should always be null terminated */ -extern SHA2Result sha2_256_oneshot(const uint8_t *data, const size_t len, +extern SHA2Result sha2_256_oneshot(const uint8_t data[], const size_t len, SHA2Digest digest); extern SHA2Result sha2_256_reset(SHA2Context *context); extern SHA2Result sha2_256_input(SHA2Context *context, const uint8_t data[], diff --git a/crates/algorithms/algorithms-c/test/hash/test_sha2.c b/crates/algorithms/algorithms-c/test/hash/test_sha2.c index d1633df..91ca198 100644 --- a/crates/algorithms/algorithms-c/test/hash/test_sha2.c +++ b/crates/algorithms/algorithms-c/test/hash/test_sha2.c @@ -14,10 +14,12 @@ void tearDown(void) {} #define SAMPLE(INPUT, HASH) \ {(uint8_t[]){INPUT "\0"}, (uint8_t *)(uint32_t[])HASH} -#define TEST_VALUES_LEN 1 +#define TEST_VALUES_LEN 2 uint8_t *test_values[TEST_VALUES_LEN][2] = { SAMPLE("AAAA", HASH(0x63c1dd95, 0x1ffedf6f, 0x7fd968ad, 0x4efa39b8, 0xed584f16, 0x2f46e715, 0x114ee184, 0xf8de9201)), + SAMPLE("BAAA", HASH(0x49e3cd45, 0x27c96cdc, 0x010160ff, 0x08520e0c, + 0xb63c6ef8, 0xc4e7d486, 0x08995343, 0x7f83a159)), }; void test_sha2_check(void) { diff --git a/crates/algorithms/src/crc/ffi/crc32.rs b/crates/algorithms/src/crc/ffi/crc32.rs index 00a6304..5ba85c0 100755 --- a/crates/algorithms/src/crc/ffi/crc32.rs +++ b/crates/algorithms/src/crc/ffi/crc32.rs @@ -1,6 +1,4 @@ -use core::ffi::c_void; - -use crate::{crc::Crc, ffi::ref_to_voidptr}; +use crate::{crc::Crc, ffi::ref_to_ptr}; pub type ChecksumCrc32 = u32; // uint32_t in C @@ -28,7 +26,7 @@ impl Crc for Crc32 { #[inline] fn process(&mut self, data: &Self::Input) { - unsafe { crc32_process(data, data.len() as u32, self as *mut Self) } + unsafe { crc32_process(ref_to_ptr(data), data.len() as u32, self as *mut Self) } } #[inline] @@ -38,7 +36,7 @@ impl Crc for Crc32 { #[inline] fn checksum(data: &Self::Input) -> Self::Checksum { - unsafe { crc32_checksum(data, data.len() as u32) } + unsafe { crc32_checksum(ref_to_ptr(data), data.len() as u32) } } } diff --git a/crates/algorithms/src/ffi/mod.rs b/crates/algorithms/src/ffi/mod.rs index 091b773..ccaa155 100755 --- a/crates/algorithms/src/ffi/mod.rs +++ b/crates/algorithms/src/ffi/mod.rs @@ -10,8 +10,13 @@ pub fn ffi_is_loaded() -> bool { } #[inline] -pub(crate) fn ref_to_voidptr(r: &T) -> *const c_void { - r as *const T as *const c_void +pub(crate) fn ref_to_ptr(r: &T) -> *const P { + r as *const T as *const P +} + +#[inline] +pub(crate) fn ref_to_ptr_mut(r: &mut T) -> *mut P { + r as *mut T as *mut P } #[cfg(test)] diff --git a/crates/algorithms/src/hash/ffi/mod.rs b/crates/algorithms/src/hash/ffi/mod.rs index 0317aeb..71a40f0 100644 --- a/crates/algorithms/src/hash/ffi/mod.rs +++ b/crates/algorithms/src/hash/ffi/mod.rs @@ -1,2 +1,2 @@ -mod sha1; -pub use sha1::*; +mod sha2; +pub use sha2::*; diff --git a/crates/algorithms/src/hash/ffi/sha1.rs b/crates/algorithms/src/hash/ffi/sha1.rs deleted file mode 100644 index e69de29..0000000 diff --git a/crates/algorithms/src/hash/ffi/sha2.rs b/crates/algorithms/src/hash/ffi/sha2.rs new file mode 100644 index 0000000..6bde16d --- /dev/null +++ b/crates/algorithms/src/hash/ffi/sha2.rs @@ -0,0 +1,123 @@ +use crate::ffi::{ref_to_ptr, ref_to_ptr_mut}; + +use super::super::sha2::*; + +#[repr(C)] +#[allow(non_camel_case_types)] +#[allow(unused)] +#[allow(clippy::enum_variant_names)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] +pub enum SHA2Result { + shaSuccess = 0, + shaNull, /* Null pointer parameter */ + shaInputTooLong, /* input data too long */ + shaStateError, /* called Input after Result */ + shaBadArg, /* Bad argument was given to a function */ +} + +#[repr(C)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] +pub struct SHA2Context { + pub intermediate_hash: Digest, + pub length_low: u32, + pub length_high: u32, + pub message_block_index: i16, + pub message_block: [u8; SHA2_256_BLOCK_SIZE], + pub computed: bool, + pub corrupted: bool, +} + +impl SHA2Context { + pub fn new() -> Self { + Self { + intermediate_hash: DIGEST_EMPTY, + length_low: 0, + length_high: 0, + message_block_index: 0, + message_block: [0; SHA2_256_BLOCK_SIZE], + computed: false, + corrupted: false, + } + } +} + +impl Default for SHA2Context { + fn default() -> Self { + Self::new() + } +} + +mod ffi { + use super::*; + unsafe extern "C" { + pub fn sha2_256_oneshot(data: *const u8, len: usize, digest: *mut Digest) -> SHA2Result; + pub fn sha2_256_reset(context: *mut SHA2Context) -> SHA2Result; + pub fn sha2_256_input(context: *mut SHA2Context, data: *const u8, len: usize) + -> SHA2Result; + pub fn sha2_256_result(context: *mut SHA2Context, digest: *mut Digest) -> SHA2Result; + } +} + +#[inline] +pub fn sha2_256_oneshot(data: &[u8]) -> Result { + let mut digest: Digest = DIGEST_EMPTY; + let res = + unsafe { ffi::sha2_256_oneshot(ref_to_ptr(data), data.len(), ref_to_ptr_mut(&mut digest)) }; + to_res(digest, res) +} + +pub fn sha2_256_reset(context: &mut SHA2Context) -> Result<(), SHA2Result> { + let res = unsafe { ffi::sha2_256_reset(ref_to_ptr_mut(context)) }; + to_res((), res) +} + +pub fn sha2_256_input(context: &mut SHA2Context, data: &[u8]) -> Result<(), SHA2Result> { + let res = unsafe { ffi::sha2_256_input(ref_to_ptr_mut(context), ref_to_ptr(data), data.len()) }; + to_res((), res) +} + +pub fn sha2_256_result(context: &mut SHA2Context) -> Result { + let mut digest: Digest = DIGEST_EMPTY; + let res = unsafe { ffi::sha2_256_result(ref_to_ptr_mut(context), ref_to_ptr_mut(&mut digest)) }; + to_res(digest, res) +} + +#[inline] +fn to_res(if_ok: T, res: SHA2Result) -> Result { + if res == SHA2Result::shaSuccess { + Ok(if_ok) + } else { + Err(res) + } +} + +#[cfg(test)] +mod test { + use crate::digest; + use crate::hash::Digest; + use crate::hash::ffi::sha2_256_oneshot; + + const TEST_VALUES: &[(&str, Digest)] = &[ + ( + "AAAA", + digest!( + 0x63c1dd95, 0x1ffedf6f, 0x7fd968ad, 0x4efa39b8, 0xed584f16, 0x2f46e715, 0x114ee184, + 0xf8de9201 + ), + ), + ( + "BAAA", + digest!( + 0x49e3cd45, 0x27c96cdc, 0x010160ff, 0x08520e0c, 0xb63c6ef8, 0xc4e7d486, 0x08995343, + 0x7f83a159 + ), + ), + ]; + + #[test] + fn test_check() { + for (input, expected_output) in TEST_VALUES.iter().copied() { + assert_eq!(sha2_256_oneshot(input.as_bytes()), Ok(expected_output)) + } + } +} diff --git a/crates/algorithms/src/hash/mod.rs b/crates/algorithms/src/hash/mod.rs index a5eac9f..2647f85 100644 --- a/crates/algorithms/src/hash/mod.rs +++ b/crates/algorithms/src/hash/mod.rs @@ -1,4 +1,4 @@ pub mod ffi; -mod sha1; -pub use sha1::*; +mod sha2; +pub use sha2::*; diff --git a/crates/algorithms/src/hash/sha1.rs b/crates/algorithms/src/hash/sha1.rs deleted file mode 100644 index e69de29..0000000 diff --git a/crates/algorithms/src/hash/sha2.rs b/crates/algorithms/src/hash/sha2.rs new file mode 100644 index 0000000..f0bbb9d --- /dev/null +++ b/crates/algorithms/src/hash/sha2.rs @@ -0,0 +1,15 @@ +pub const SHA2_256_HASH_BITS: usize = 256; +pub const SHA2_256_HASH_BYTES: usize = SHA2_256_HASH_BITS / 8; +pub const SHA2_256_HASH_PARTS: usize = SHA2_256_HASH_BYTES / 4 /* storing with u32 */; +pub const SHA2_256_BLOCK_SIZE: usize = 2 * SHA2_256_HASH_BYTES; + +pub type Digest = [u32; SHA2_256_HASH_PARTS]; + +#[macro_export] +macro_rules! digest { + ($($block:literal$(,)?)+) => { + [$($block,)+ ] + }; +} + +pub(crate) const DIGEST_EMPTY: Digest = [0; SHA2_256_HASH_PARTS];