aboutsummaryrefslogtreecommitdiff
path: root/c
diff options
context:
space:
mode:
Diffstat (limited to 'c')
-rw-r--r--c/blake3.c3
-rw-r--r--c/blake3_c_rust_bindings/src/lib.rs18
-rw-r--r--c/blake3_c_rust_bindings/src/test.rs75
-rw-r--r--c/blake3_impl.h11
4 files changed, 101 insertions, 6 deletions
diff --git a/c/blake3.c b/c/blake3.c
index b6768d2..7e6d01e 100644
--- a/c/blake3.c
+++ b/c/blake3.c
@@ -88,6 +88,9 @@ INLINE void output_chaining_value(const output_t *self, uint8_t cv[32]) {
INLINE void output_root_bytes(const output_t *self, uint64_t seek, uint8_t *out,
size_t out_len) {
+ if (out_len == 0) {
+ return;
+ }
uint64_t output_block_counter = seek / 64;
size_t offset_within_block = seek % 64;
uint8_t wide_buf[64];
diff --git a/c/blake3_c_rust_bindings/src/lib.rs b/c/blake3_c_rust_bindings/src/lib.rs
index 41e4938..ac7880a 100644
--- a/c/blake3_c_rust_bindings/src/lib.rs
+++ b/c/blake3_c_rust_bindings/src/lib.rs
@@ -177,6 +177,15 @@ pub mod ffi {
flags_end: u8,
out: *mut u8,
);
+ pub fn blake3_xof_many_portable(
+ cv: *const u32,
+ block: *const u8,
+ block_len: u8,
+ counter: u64,
+ flags: u8,
+ out: *mut u8,
+ outblocks: usize,
+ );
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
@@ -282,6 +291,15 @@ pub mod ffi {
flags_end: u8,
out: *mut u8,
);
+ pub fn blake3_xof_many_avx512(
+ cv: *const u32,
+ block: *const u8,
+ block_len: u8,
+ counter: u64,
+ flags: u8,
+ out: *mut u8,
+ outblocks: usize,
+ );
}
}
diff --git a/c/blake3_c_rust_bindings/src/test.rs b/c/blake3_c_rust_bindings/src/test.rs
index 0730d93..e6baff1 100644
--- a/c/blake3_c_rust_bindings/src/test.rs
+++ b/c/blake3_c_rust_bindings/src/test.rs
@@ -359,6 +359,81 @@ fn test_hash_many_neon() {
test_hash_many_fn(crate::ffi::neon::blake3_hash_many_neon);
}
+type XofManyFunction = unsafe extern "C" fn(
+ cv: *const u32,
+ block: *const u8,
+ block_len: u8,
+ counter: u64,
+ flags: u8,
+ out: *mut u8,
+ outblocks: usize,
+);
+
+// A shared helper function for platform-specific tests.
+pub fn test_xof_many_fn(xof_many_function: XofManyFunction) {
+ // Test a few different initial counter values.
+ // - 0: The base case.
+ // - u32::MAX: The low word of the counter overflows for all inputs except the first.
+ // - i32::MAX: *No* overflow. But carry bugs in tricky SIMD code can screw this up, if you XOR
+ // when you're supposed to ANDNOT...
+ let initial_counters = [0, u32::MAX as u64, i32::MAX as u64];
+ for counter in initial_counters {
+ #[cfg(feature = "std")]
+ dbg!(counter);
+
+ let mut block = [0; BLOCK_LEN];
+ let block_len = 42;
+ crate::test::paint_test_input(&mut block[..block_len]);
+ let cv = [40, 41, 42, 43, 44, 45, 46, 47];
+ let flags = KEYED_HASH;
+ // 31 (16 + 8 + 4 + 2 + 1) outputs
+ const OUTPUT_SIZE: usize = 31 * BLOCK_LEN;
+
+ let mut portable_out = [0u8; OUTPUT_SIZE];
+ unsafe {
+ crate::ffi::blake3_xof_many_portable(
+ cv.as_ptr(),
+ block.as_ptr(),
+ block_len as u8,
+ counter,
+ flags,
+ portable_out.as_mut_ptr(),
+ OUTPUT_SIZE / BLOCK_LEN,
+ );
+ }
+
+ let mut test_out = [0u8; OUTPUT_SIZE];
+ unsafe {
+ xof_many_function(
+ cv.as_ptr(),
+ block.as_ptr(),
+ block_len as u8,
+ counter,
+ flags,
+ test_out.as_mut_ptr(),
+ OUTPUT_SIZE / BLOCK_LEN,
+ );
+ }
+
+ assert_eq!(portable_out, test_out);
+ }
+}
+
+// Testing the portable implementation against itself is circular, but why not.
+#[test]
+fn test_xof_many_portable() {
+ test_xof_many_fn(crate::ffi::blake3_xof_many_portable);
+}
+
+#[test]
+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+fn test_xof_many_avx512() {
+ if !crate::avx512_detected() {
+ return;
+ }
+ test_xof_many_fn(crate::ffi::x86::blake3_xof_many_avx512);
+}
+
#[test]
fn test_compare_reference_impl() {
const OUT: usize = 303; // more than 64, not a multiple of 4
diff --git a/c/blake3_impl.h b/c/blake3_impl.h
index b3abce2..66a1707 100644
--- a/c/blake3_impl.h
+++ b/c/blake3_impl.h
@@ -282,17 +282,16 @@ void blake3_compress_xof_avx512(const uint32_t cv[8],
uint8_t block_len, uint64_t counter,
uint8_t flags, uint8_t out[64]);
-
-void blake3_xof_many_avx512(const uint32_t cv[8],
- const uint8_t block[BLAKE3_BLOCK_LEN],
- uint8_t block_len, uint64_t counter, uint8_t flags,
- uint8_t* out, size_t outblocks);
-
void blake3_hash_many_avx512(const uint8_t *const *inputs, size_t num_inputs,
size_t blocks, const uint32_t key[8],
uint64_t counter, bool increment_counter,
uint8_t flags, uint8_t flags_start,
uint8_t flags_end, uint8_t *out);
+
+void blake3_xof_many_avx512(const uint32_t cv[8],
+ const uint8_t block[BLAKE3_BLOCK_LEN],
+ uint8_t block_len, uint64_t counter, uint8_t flags,
+ uint8_t* out, size_t outblocks);
#endif
#endif