feat(alg): ffi for sha2 of algc

This commit is contained in:
cscherr 2025-07-18 10:32:11 +02:00
parent 3331e89179
commit 1b582ba202
Signed by: cscherrNT
GPG key ID: 8E2B45BC51A27EA7
13 changed files with 159 additions and 29 deletions

View file

@ -1,8 +1,8 @@
[target.thumbv6m-none-eabi] [target.thumbv6m-none-eabi]
runner = 'probe-rs run --chip STM32L053R8' runner = 'probe-rs run --chip STM32L053R8'
[build] # [build]
target = "thumbv6m-none-eabi" # target = "thumbv6m-none-eabi"
[alias] [alias]
arun = "run --target thumbv6m-none-eabi" arun = "run --target thumbv6m-none-eabi"

View file

@ -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

View file

@ -401,7 +401,7 @@ SHA2Result sha2_256_result(SHA2Context *context, SHA2Digest digest) {
return shaSuccess; 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) { SHA2Digest digest) {
SHA2Context context; SHA2Context context;
SHA2Result res; SHA2Result res;

View file

@ -43,7 +43,7 @@ typedef struct SHA2Context {
} SHA2Context; } SHA2Context;
/** data should always be null terminated */ /** 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); SHA2Digest digest);
extern SHA2Result sha2_256_reset(SHA2Context *context); extern SHA2Result sha2_256_reset(SHA2Context *context);
extern SHA2Result sha2_256_input(SHA2Context *context, const uint8_t data[], extern SHA2Result sha2_256_input(SHA2Context *context, const uint8_t data[],

View file

@ -14,10 +14,12 @@ void tearDown(void) {}
#define SAMPLE(INPUT, HASH) \ #define SAMPLE(INPUT, HASH) \
{(uint8_t[]){INPUT "\0"}, (uint8_t *)(uint32_t[])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] = { uint8_t *test_values[TEST_VALUES_LEN][2] = {
SAMPLE("AAAA", HASH(0x63c1dd95, 0x1ffedf6f, 0x7fd968ad, 0x4efa39b8, SAMPLE("AAAA", HASH(0x63c1dd95, 0x1ffedf6f, 0x7fd968ad, 0x4efa39b8,
0xed584f16, 0x2f46e715, 0x114ee184, 0xf8de9201)), 0xed584f16, 0x2f46e715, 0x114ee184, 0xf8de9201)),
SAMPLE("BAAA", HASH(0x49e3cd45, 0x27c96cdc, 0x010160ff, 0x08520e0c,
0xb63c6ef8, 0xc4e7d486, 0x08995343, 0x7f83a159)),
}; };
void test_sha2_check(void) { void test_sha2_check(void) {

View file

@ -1,6 +1,4 @@
use core::ffi::c_void; use crate::{crc::Crc, ffi::ref_to_ptr};
use crate::{crc::Crc, ffi::ref_to_voidptr};
pub type ChecksumCrc32 = u32; // uint32_t in C pub type ChecksumCrc32 = u32; // uint32_t in C
@ -28,7 +26,7 @@ impl Crc for Crc32 {
#[inline] #[inline]
fn process(&mut self, data: &Self::Input) { 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] #[inline]
@ -38,7 +36,7 @@ impl Crc for Crc32 {
#[inline] #[inline]
fn checksum(data: &Self::Input) -> Self::Checksum { 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) }
} }
} }

View file

@ -10,8 +10,13 @@ pub fn ffi_is_loaded() -> bool {
} }
#[inline] #[inline]
pub(crate) fn ref_to_voidptr<T: ?Sized>(r: &T) -> *const c_void { pub(crate) fn ref_to_ptr<T: ?Sized, P>(r: &T) -> *const P {
r as *const T as *const c_void r as *const T as *const P
}
#[inline]
pub(crate) fn ref_to_ptr_mut<T: ?Sized, P>(r: &mut T) -> *mut P {
r as *mut T as *mut P
} }
#[cfg(test)] #[cfg(test)]

View file

@ -1,2 +1,2 @@
mod sha1; mod sha2;
pub use sha1::*; pub use sha2::*;

View file

@ -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<Digest, SHA2Result> {
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<Digest, SHA2Result> {
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<T>(if_ok: T, res: SHA2Result) -> Result<T, SHA2Result> {
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))
}
}
}

View file

@ -1,4 +1,4 @@
pub mod ffi; pub mod ffi;
mod sha1; mod sha2;
pub use sha1::*; pub use sha2::*;

View file

@ -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];