1
0
Fork 0
mirror of https://github.com/BLAKE3-team/BLAKE3 synced 2024-05-04 10:56:08 +02:00

add blake3_hasher_finalize_seek to the C API

This commit is contained in:
Jack O'Connor 2020-03-25 15:53:20 -04:00
parent 4feadee6bb
commit a4ceef3932
4 changed files with 51 additions and 9 deletions

View File

@ -84,23 +84,26 @@ INLINE void output_chaining_value(const output_t *self, uint8_t cv[32]) {
memcpy(cv, cv_words, 32);
}
INLINE void output_root_bytes(const output_t *self, uint8_t *out,
INLINE void output_root_bytes(const output_t *self, uint64_t seek, uint8_t *out,
size_t out_len) {
uint64_t output_block_counter = 0;
uint64_t output_block_counter = seek / 64;
size_t offset_within_block = seek % 64;
uint8_t wide_buf[64];
while (out_len > 0) {
blake3_compress_xof(self->input_cv, self->block, self->block_len,
output_block_counter, self->flags | ROOT, wide_buf);
size_t available_bytes = 64 - offset_within_block;
size_t memcpy_len;
if (out_len > 64) {
memcpy_len = 64;
if (out_len > available_bytes) {
memcpy_len = available_bytes;
} else {
memcpy_len = out_len;
}
memcpy(out, wide_buf, memcpy_len);
memcpy(out, wide_buf + offset_within_block, memcpy_len);
out += memcpy_len;
out_len -= memcpy_len;
output_block_counter += 1;
offset_within_block = 0;
}
}
@ -546,6 +549,11 @@ void blake3_hasher_update(blake3_hasher *self, const void *input,
void blake3_hasher_finalize(const blake3_hasher *self, uint8_t *out,
size_t out_len) {
blake3_hasher_finalize_seek(self, 0, out, out_len);
}
void blake3_hasher_finalize_seek(const blake3_hasher *self, uint64_t seek,
uint8_t *out, size_t out_len) {
// Explicitly checking for zero avoids causing UB by passing a null pointer
// to memcpy. This comes up in practice with things like:
// std::vector<uint8_t> v;
@ -557,7 +565,7 @@ void blake3_hasher_finalize(const blake3_hasher *self, uint8_t *out,
// If the subtree stack is empty, then the current chunk is the root.
if (self->cv_stack_len == 0) {
output_t output = chunk_state_output(&self->chunk);
output_root_bytes(&output, out, out_len);
output_root_bytes(&output, seek, out, out_len);
return;
}
// If there are any bytes in the chunk state, finalize that chunk and do a
@ -585,5 +593,5 @@ void blake3_hasher_finalize(const blake3_hasher *self, uint8_t *out,
output_chaining_value(&output, &parent_block[32]);
output = parent_output(parent_block, self->key, self->chunk.flags);
}
output_root_bytes(&output, out, out_len);
output_root_bytes(&output, seek, out, out_len);
}

View File

@ -4,7 +4,7 @@
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
#ifdef __cplusplus
extern "C" {
#endif
@ -46,8 +46,10 @@ void blake3_hasher_update(blake3_hasher *self, const void *input,
size_t input_len);
void blake3_hasher_finalize(const blake3_hasher *self, uint8_t *out,
size_t out_len);
void blake3_hasher_finalize_seek(const blake3_hasher *self, uint64_t seek,
uint8_t *out, size_t out_len);
#ifdef __cplusplus
#ifdef __cplusplus
}
#endif

View File

@ -70,6 +70,12 @@ impl Hasher {
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 mod ffi {
@ -107,6 +113,12 @@ pub mod ffi {
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,
);
// portable low-level functions
pub fn blake3_compress_in_place_portable(

View File

@ -444,3 +444,23 @@ fn test_fuzz_hasher() {
assert_eq!(expected, test_out);
}
}
#[test]
fn test_finalize_seek() {
let mut expected = [0; 1000];
{
let mut reference_hasher = reference_impl::Hasher::new();
reference_hasher.update(b"foobarbaz");
reference_hasher.finalize(&mut expected);
}
let mut test_hasher = crate::Hasher::new();
test_hasher.update(b"foobarbaz");
let mut out = [0; 103];
for &seek in &[0, 1, 7, 59, 63, 64, 65, 501, expected.len() - out.len()] {
dbg!(seek);
test_hasher.finalize_seek(seek as u64, &mut out);
assert_eq!(&expected[seek..][..out.len()], &out[..]);
}
}