mirror of
https://github.com/BLAKE3-team/BLAKE3
synced 2024-05-04 19:16:27 +02:00
307 lines
8.9 KiB
Rust
307 lines
8.9 KiB
Rust
//! These are Rust bindings for the C implementation of BLAKE3. As there is a
|
|
//! native (and faster) Rust implementation of BLAKE3 provided in this same
|
|
//! repo, these bindings are not expected to be used in production. They're
|
|
//! intended for testing and benchmarking.
|
|
|
|
use std::ffi::{c_void, CString};
|
|
use std::mem::MaybeUninit;
|
|
|
|
#[cfg(test)]
|
|
mod test;
|
|
|
|
pub const BLOCK_LEN: usize = 64;
|
|
pub const CHUNK_LEN: usize = 1024;
|
|
pub const OUT_LEN: usize = 32;
|
|
|
|
// Feature detection functions for tests and benchmarks. Note that the C code
|
|
// does its own feature detection in blake3_dispatch.c.
|
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
|
pub fn sse2_detected() -> bool {
|
|
is_x86_feature_detected!("sse2")
|
|
}
|
|
|
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
|
pub fn sse41_detected() -> bool {
|
|
is_x86_feature_detected!("sse4.1")
|
|
}
|
|
|
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
|
pub fn avx2_detected() -> bool {
|
|
is_x86_feature_detected!("avx2")
|
|
}
|
|
|
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
|
pub fn avx512_detected() -> bool {
|
|
is_x86_feature_detected!("avx512f") && is_x86_feature_detected!("avx512vl")
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct Hasher(ffi::blake3_hasher);
|
|
|
|
impl Hasher {
|
|
pub fn new() -> Self {
|
|
let mut c_state = MaybeUninit::uninit();
|
|
unsafe {
|
|
ffi::blake3_hasher_init(c_state.as_mut_ptr());
|
|
Self(c_state.assume_init())
|
|
}
|
|
}
|
|
|
|
pub fn new_keyed(key: &[u8; 32]) -> Self {
|
|
let mut c_state = MaybeUninit::uninit();
|
|
unsafe {
|
|
ffi::blake3_hasher_init_keyed(c_state.as_mut_ptr(), key.as_ptr());
|
|
Self(c_state.assume_init())
|
|
}
|
|
}
|
|
|
|
pub fn new_derive_key(context: &str) -> Self {
|
|
let mut c_state = MaybeUninit::uninit();
|
|
let context_c_string = CString::new(context).expect("valid C string, no null bytes");
|
|
unsafe {
|
|
ffi::blake3_hasher_init_derive_key(c_state.as_mut_ptr(), context_c_string.as_ptr());
|
|
Self(c_state.assume_init())
|
|
}
|
|
}
|
|
|
|
pub fn new_derive_key_raw(context: &[u8]) -> Self {
|
|
let mut c_state = MaybeUninit::uninit();
|
|
unsafe {
|
|
ffi::blake3_hasher_init_derive_key_raw(
|
|
c_state.as_mut_ptr(),
|
|
context.as_ptr() as *const _,
|
|
context.len(),
|
|
);
|
|
Self(c_state.assume_init())
|
|
}
|
|
}
|
|
|
|
pub fn update(&mut self, input: &[u8]) {
|
|
unsafe {
|
|
ffi::blake3_hasher_update(&mut self.0, input.as_ptr() as *const c_void, input.len());
|
|
}
|
|
}
|
|
|
|
pub fn finalize(&self, output: &mut [u8]) {
|
|
unsafe {
|
|
ffi::blake3_hasher_finalize(&self.0, output.as_mut_ptr(), output.len());
|
|
}
|
|
}
|
|
|
|
pub fn finalize_seek(&self, seek: u64, output: &mut [u8]) {
|
|
unsafe {
|
|
ffi::blake3_hasher_finalize_seek(&self.0, seek, output.as_mut_ptr(), output.len());
|
|
}
|
|
}
|
|
|
|
pub fn reset(&mut self) {
|
|
unsafe {
|
|
ffi::blake3_hasher_reset(&mut self.0);
|
|
}
|
|
}
|
|
}
|
|
|
|
pub mod ffi {
|
|
#[repr(C)]
|
|
#[derive(Copy, Clone)]
|
|
pub struct blake3_chunk_state {
|
|
pub cv: [u32; 8usize],
|
|
pub chunk_counter: u64,
|
|
pub buf: [u8; 64usize],
|
|
pub buf_len: u8,
|
|
pub blocks_compressed: u8,
|
|
pub flags: u8,
|
|
}
|
|
|
|
#[repr(C)]
|
|
#[derive(Copy, Clone)]
|
|
pub struct blake3_hasher {
|
|
pub key: [u32; 8usize],
|
|
pub chunk: blake3_chunk_state,
|
|
pub cv_stack_len: u8,
|
|
pub cv_stack: [u8; 1728usize],
|
|
}
|
|
|
|
extern "C" {
|
|
// public interface
|
|
pub fn blake3_hasher_init(self_: *mut blake3_hasher);
|
|
pub fn blake3_hasher_init_keyed(self_: *mut blake3_hasher, key: *const u8);
|
|
pub fn blake3_hasher_init_derive_key(
|
|
self_: *mut blake3_hasher,
|
|
context: *const ::std::os::raw::c_char,
|
|
);
|
|
pub fn blake3_hasher_init_derive_key_raw(
|
|
self_: *mut blake3_hasher,
|
|
context: *const ::std::os::raw::c_void,
|
|
context_len: usize,
|
|
);
|
|
pub fn blake3_hasher_update(
|
|
self_: *mut blake3_hasher,
|
|
input: *const ::std::os::raw::c_void,
|
|
input_len: usize,
|
|
);
|
|
pub fn blake3_hasher_finalize(self_: *const blake3_hasher, out: *mut u8, out_len: usize);
|
|
pub fn blake3_hasher_finalize_seek(
|
|
self_: *const blake3_hasher,
|
|
seek: u64,
|
|
out: *mut u8,
|
|
out_len: usize,
|
|
);
|
|
pub fn blake3_hasher_reset(self_: *mut blake3_hasher);
|
|
|
|
// portable low-level functions
|
|
pub fn blake3_compress_in_place_portable(
|
|
cv: *mut u32,
|
|
block: *const u8,
|
|
block_len: u8,
|
|
counter: u64,
|
|
flags: u8,
|
|
);
|
|
pub fn blake3_compress_xof_portable(
|
|
cv: *const u32,
|
|
block: *const u8,
|
|
block_len: u8,
|
|
counter: u64,
|
|
flags: u8,
|
|
out: *mut u8,
|
|
);
|
|
pub fn blake3_hash_many_portable(
|
|
inputs: *const *const u8,
|
|
num_inputs: usize,
|
|
blocks: usize,
|
|
key: *const u32,
|
|
counter: u64,
|
|
increment_counter: bool,
|
|
flags: u8,
|
|
flags_start: u8,
|
|
flags_end: u8,
|
|
out: *mut u8,
|
|
);
|
|
}
|
|
|
|
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
|
pub mod x86 {
|
|
extern "C" {
|
|
// SSE2 low level functions
|
|
pub fn blake3_compress_in_place_sse2(
|
|
cv: *mut u32,
|
|
block: *const u8,
|
|
block_len: u8,
|
|
counter: u64,
|
|
flags: u8,
|
|
);
|
|
pub fn blake3_compress_xof_sse2(
|
|
cv: *const u32,
|
|
block: *const u8,
|
|
block_len: u8,
|
|
counter: u64,
|
|
flags: u8,
|
|
out: *mut u8,
|
|
);
|
|
pub fn blake3_hash_many_sse2(
|
|
inputs: *const *const u8,
|
|
num_inputs: usize,
|
|
blocks: usize,
|
|
key: *const u32,
|
|
counter: u64,
|
|
increment_counter: bool,
|
|
flags: u8,
|
|
flags_start: u8,
|
|
flags_end: u8,
|
|
out: *mut u8,
|
|
);
|
|
|
|
// SSE4.1 low level functions
|
|
pub fn blake3_compress_in_place_sse41(
|
|
cv: *mut u32,
|
|
block: *const u8,
|
|
block_len: u8,
|
|
counter: u64,
|
|
flags: u8,
|
|
);
|
|
pub fn blake3_compress_xof_sse41(
|
|
cv: *const u32,
|
|
block: *const u8,
|
|
block_len: u8,
|
|
counter: u64,
|
|
flags: u8,
|
|
out: *mut u8,
|
|
);
|
|
pub fn blake3_hash_many_sse41(
|
|
inputs: *const *const u8,
|
|
num_inputs: usize,
|
|
blocks: usize,
|
|
key: *const u32,
|
|
counter: u64,
|
|
increment_counter: bool,
|
|
flags: u8,
|
|
flags_start: u8,
|
|
flags_end: u8,
|
|
out: *mut u8,
|
|
);
|
|
|
|
// AVX2 low level functions
|
|
pub fn blake3_hash_many_avx2(
|
|
inputs: *const *const u8,
|
|
num_inputs: usize,
|
|
blocks: usize,
|
|
key: *const u32,
|
|
counter: u64,
|
|
increment_counter: bool,
|
|
flags: u8,
|
|
flags_start: u8,
|
|
flags_end: u8,
|
|
out: *mut u8,
|
|
);
|
|
|
|
// AVX-512 low level functions
|
|
pub fn blake3_compress_xof_avx512(
|
|
cv: *const u32,
|
|
block: *const u8,
|
|
block_len: u8,
|
|
counter: u64,
|
|
flags: u8,
|
|
out: *mut u8,
|
|
);
|
|
pub fn blake3_compress_in_place_avx512(
|
|
cv: *mut u32,
|
|
block: *const u8,
|
|
block_len: u8,
|
|
counter: u64,
|
|
flags: u8,
|
|
);
|
|
pub fn blake3_hash_many_avx512(
|
|
inputs: *const *const u8,
|
|
num_inputs: usize,
|
|
blocks: usize,
|
|
key: *const u32,
|
|
counter: u64,
|
|
increment_counter: bool,
|
|
flags: u8,
|
|
flags_start: u8,
|
|
flags_end: u8,
|
|
out: *mut u8,
|
|
);
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "neon")]
|
|
pub mod neon {
|
|
extern "C" {
|
|
// NEON low level functions
|
|
pub fn blake3_hash_many_neon(
|
|
inputs: *const *const u8,
|
|
num_inputs: usize,
|
|
blocks: usize,
|
|
key: *const u32,
|
|
counter: u64,
|
|
increment_counter: bool,
|
|
flags: u8,
|
|
flags_start: u8,
|
|
flags_end: u8,
|
|
out: *mut u8,
|
|
);
|
|
}
|
|
}
|
|
}
|