blake3/
ffi_sse41.rs

1use crate::{CVWords, IncrementCounter, BLOCK_LEN, OUT_LEN};
2
3// Unsafe because this may only be called on platforms supporting SSE4.1.
4pub unsafe fn compress_in_place(
5    cv: &mut CVWords,
6    block: &[u8; BLOCK_LEN],
7    block_len: u8,
8    counter: u64,
9    flags: u8,
10) {
11    unsafe {
12        ffi::blake3_compress_in_place_sse41(
13            cv.as_mut_ptr(),
14            block.as_ptr(),
15            block_len,
16            counter,
17            flags,
18        )
19    }
20}
21
22// Unsafe because this may only be called on platforms supporting SSE4.1.
23pub unsafe fn compress_xof(
24    cv: &CVWords,
25    block: &[u8; BLOCK_LEN],
26    block_len: u8,
27    counter: u64,
28    flags: u8,
29) -> [u8; 64] {
30    unsafe {
31        let mut out = [0u8; 64];
32        ffi::blake3_compress_xof_sse41(
33            cv.as_ptr(),
34            block.as_ptr(),
35            block_len,
36            counter,
37            flags,
38            out.as_mut_ptr(),
39        );
40        out
41    }
42}
43
44// Unsafe because this may only be called on platforms supporting SSE4.1.
45pub unsafe fn hash_many<const N: usize>(
46    inputs: &[&[u8; N]],
47    key: &CVWords,
48    counter: u64,
49    increment_counter: IncrementCounter,
50    flags: u8,
51    flags_start: u8,
52    flags_end: u8,
53    out: &mut [u8],
54) {
55    unsafe {
56        // The Rust hash_many implementations do bounds checking on the `out`
57        // array, but the C implementations don't. Even though this is an unsafe
58        // function, assert the bounds here.
59        assert!(out.len() >= inputs.len() * OUT_LEN);
60        ffi::blake3_hash_many_sse41(
61            inputs.as_ptr() as *const *const u8,
62            inputs.len(),
63            N / BLOCK_LEN,
64            key.as_ptr(),
65            counter,
66            increment_counter.yes(),
67            flags,
68            flags_start,
69            flags_end,
70            out.as_mut_ptr(),
71        )
72    }
73}
74
75pub mod ffi {
76    extern "C" {
77        pub fn blake3_compress_in_place_sse41(
78            cv: *mut u32,
79            block: *const u8,
80            block_len: u8,
81            counter: u64,
82            flags: u8,
83        );
84        pub fn blake3_compress_xof_sse41(
85            cv: *const u32,
86            block: *const u8,
87            block_len: u8,
88            counter: u64,
89            flags: u8,
90            out: *mut u8,
91        );
92        pub fn blake3_hash_many_sse41(
93            inputs: *const *const u8,
94            num_inputs: usize,
95            blocks: usize,
96            key: *const u32,
97            counter: u64,
98            increment_counter: bool,
99            flags: u8,
100            flags_start: u8,
101            flags_end: u8,
102            out: *mut u8,
103        );
104    }
105}
106
107#[cfg(test)]
108mod test {
109    use super::*;
110
111    #[test]
112    fn test_compress() {
113        if !crate::platform::sse41_detected() {
114            return;
115        }
116        crate::test::test_compress_fn(compress_in_place, compress_xof);
117    }
118
119    #[test]
120    fn test_hash_many() {
121        if !crate::platform::sse41_detected() {
122            return;
123        }
124        crate::test::test_hash_many_fn(hash_many, hash_many);
125    }
126}