ab_blake3/
single_block.rs

1//! BLAKE3 functions that process at most a single block.
2//!
3//! This module and submodules are copied with modifications from the official [`blake3`] crate, but
4//! is unlikely to be upstreamed.
5
6#[cfg(test)]
7mod tests;
8
9#[cfg(not(target_arch = "spirv"))]
10use crate::platform::{le_bytes_from_words_32, words_from_le_bytes_32};
11#[cfg(not(target_arch = "spirv"))]
12use crate::{BLOCK_LEN, DERIVE_KEY_CONTEXT, DERIVE_KEY_MATERIAL, KEY_LEN, KEYED_HASH, OUT_LEN};
13use crate::{BlockWords, CHUNK_END, CHUNK_START, CVWords, IV, ROOT, portable};
14// TODO: Workaround for https://github.com/Rust-GPU/rust-gpu/issues/312
15#[cfg(not(target_arch = "spirv"))]
16use blake3::platform::Platform;
17
18// Hash a single block worth of values
19// TODO: Workaround for https://github.com/Rust-GPU/rust-gpu/issues/312
20#[cfg(not(target_arch = "spirv"))]
21#[inline(always)]
22fn hash_block(input: &[u8], key: CVWords, flags: u8) -> Option<[u8; OUT_LEN]> {
23    // If the whole subtree is one block, hash it directly with a ChunkState.
24    if input.len() > BLOCK_LEN {
25        return None;
26    }
27
28    let mut cv = key;
29
30    let mut block = [0; BLOCK_LEN];
31    block[..input.len()].copy_from_slice(input);
32    Platform::detect().compress_in_place(
33        &mut cv,
34        &block,
35        input.len() as u8,
36        0,
37        flags | CHUNK_START | CHUNK_END | ROOT,
38    );
39
40    Some(*le_bytes_from_words_32(&cv))
41}
42
43/// Hashing function for at most a single block worth of bytes.
44///
45/// Returns `None` if input length exceeds one block.
46// TODO: Workaround for https://github.com/Rust-GPU/rust-gpu/issues/312
47#[cfg(not(target_arch = "spirv"))]
48#[inline]
49#[cfg_attr(feature = "no-panic", no_panic::no_panic)]
50pub fn single_block_hash(input: &[u8]) -> Option<[u8; OUT_LEN]> {
51    hash_block(input, *IV, 0)
52}
53
54/// The keyed hash function for at most a single block worth of bytes.
55///
56/// Returns `None` if input length exceeds one block.
57// TODO: Workaround for https://github.com/Rust-GPU/rust-gpu/issues/312
58#[cfg(not(target_arch = "spirv"))]
59#[inline]
60#[cfg_attr(feature = "no-panic", no_panic::no_panic)]
61pub fn single_block_keyed_hash(key: &[u8; KEY_LEN], input: &[u8]) -> Option<[u8; OUT_LEN]> {
62    let key_words = words_from_le_bytes_32(key);
63    hash_block(input, key_words, KEYED_HASH)
64}
65
66// The key derivation function for at most a single block worth of bytes.
67//
68// Returns `None` if either context or key material length exceed one block.
69// TODO: Workaround for https://github.com/Rust-GPU/rust-gpu/issues/312
70#[cfg(not(target_arch = "spirv"))]
71#[inline]
72#[cfg_attr(feature = "no-panic", no_panic::no_panic)]
73pub fn single_block_derive_key(context: &str, key_material: &[u8]) -> Option<[u8; OUT_LEN]> {
74    let context_key = hash_block(context.as_bytes(), *IV, DERIVE_KEY_CONTEXT)?;
75    let context_key_words = words_from_le_bytes_32(&context_key);
76    hash_block(key_material, context_key_words, DERIVE_KEY_MATERIAL)
77}
78
79/// Hashing function for at most a single block worth of words using portable implementation.
80///
81/// This API operates on words and is GPU-friendly.
82///
83/// `num_bytes` specifies how many actual bytes are occupied by useful value in `input`. Bytes
84/// outside that must be set to `0`.
85///
86/// NOTE: If unused bytes are not set to `0` or invalid number of bytes is specified, it'll simply
87/// result in invalid hash.
88///
89/// [`words_from_le_bytes_32()`], [`words_from_le_bytes_64()`] and [`le_bytes_from_words_32()`] can
90/// be used to convert bytes to words and back if necessary.
91///
92/// [`words_from_le_bytes_64()`]: crate::words_from_le_bytes_64
93#[inline]
94#[cfg_attr(feature = "no-panic", no_panic::no_panic)]
95pub fn single_block_hash_portable_words(input: &BlockWords, num_bytes: u32) -> CVWords {
96    let mut cv = *IV;
97
98    portable::compress_in_place_u32(
99        &mut cv,
100        input,
101        num_bytes,
102        0,
103        (CHUNK_START | CHUNK_END | ROOT) as u32,
104    );
105
106    cv
107}