Skip to content

Commit ab8ac0d

Browse files
committed
blake2: extract State types into modules
Clearing out the `blake2b` and `blake2s` modules in order to add the primary user-facing types there.
1 parent 23dd0b2 commit ab8ac0d

10 files changed

Lines changed: 438 additions & 436 deletions

File tree

blake2/src/blake2b.rs

Lines changed: 4 additions & 211 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,15 @@
2525
2626
pub(crate) mod backend;
2727
pub mod many;
28+
pub(crate) mod state;
2829

2930
mod params;
30-
3131
#[cfg(test)]
3232
mod test;
3333

34-
pub use self::params::Params;
34+
pub use self::{params::Params, state::State};
3535

36-
use arrayref::mut_array_refs;
37-
use core::{cmp, fmt, mem::size_of};
36+
use core::{fmt, mem::size_of};
3837

3938
pub(crate) type Word = u64;
4039
pub(crate) type Count = u128;
@@ -97,212 +96,6 @@ pub fn blake2b(input: &[u8]) -> Hash {
9796
Params::new().hash(input)
9897
}
9998

100-
/// An incremental hasher for BLAKE2b.
101-
///
102-
/// To construct a `State` with non-default parameters, see `Params::to_state`.
103-
///
104-
/// # Example
105-
///
106-
/// ```
107-
/// use blake2::blake2b::{blake2b, State};
108-
///
109-
/// let mut state = State::new();
110-
///
111-
/// state.update(b"foo");
112-
/// assert_eq!(blake2b(b"foo"), state.finalize());
113-
///
114-
/// state.update(b"bar");
115-
/// assert_eq!(blake2b(b"foobar"), state.finalize());
116-
/// ```
117-
#[derive(Clone)]
118-
pub struct State {
119-
words: [Word; 8],
120-
count: Count,
121-
buf: [u8; BLOCKBYTES],
122-
buflen: u8,
123-
last_node: backend::LastNode,
124-
hash_length: u8,
125-
implementation: backend::Implementation,
126-
is_keyed: bool,
127-
}
128-
129-
impl State {
130-
/// Equivalent to `State::default()` or `Params::default().to_state()`.
131-
pub fn new() -> Self {
132-
Self::with_params(&Params::default())
133-
}
134-
135-
fn with_params(params: &Params) -> Self {
136-
let mut state = Self {
137-
words: params.to_words(),
138-
count: 0,
139-
buf: [0; BLOCKBYTES],
140-
buflen: 0,
141-
last_node: params.last_node,
142-
hash_length: params.hash_length,
143-
implementation: params.implementation,
144-
is_keyed: params.key_length > 0,
145-
};
146-
if state.is_keyed {
147-
state.buf = params.key_block;
148-
state.buflen = state.buf.len() as u8;
149-
}
150-
state
151-
}
152-
153-
fn fill_buf(&mut self, input: &mut &[u8]) {
154-
let take = cmp::min(BLOCKBYTES - self.buflen as usize, input.len());
155-
self.buf[self.buflen as usize..self.buflen as usize + take].copy_from_slice(&input[..take]);
156-
self.buflen += take as u8;
157-
*input = &input[take..];
158-
}
159-
160-
// If the state already has some input in its buffer, try to fill the buffer and perform a
161-
// compression. However, only do the compression if there's more input coming, otherwise it
162-
// will give the wrong hash it the caller finalizes immediately after.
163-
fn compress_buffer_if_possible(&mut self, input: &mut &[u8]) {
164-
if self.buflen > 0 {
165-
self.fill_buf(input);
166-
if !input.is_empty() {
167-
self.implementation.compress1_loop(
168-
&self.buf,
169-
&mut self.words,
170-
self.count,
171-
self.last_node,
172-
backend::Finalize::No,
173-
backend::Stride::Serial,
174-
);
175-
self.count = self.count.wrapping_add(BLOCKBYTES as Count);
176-
self.buflen = 0;
177-
}
178-
}
179-
}
180-
181-
/// Add input to the hash. You can call `update` any number of times.
182-
pub fn update(&mut self, mut input: &[u8]) -> &mut Self {
183-
// If we have a partial buffer, try to complete it.
184-
self.compress_buffer_if_possible(&mut input);
185-
// While there's more than a block of input left (which also means we cleared the buffer
186-
// above), compress blocks directly without copying.
187-
let mut end = input.len().saturating_sub(1);
188-
end -= end % BLOCKBYTES;
189-
if end > 0 {
190-
self.implementation.compress1_loop(
191-
&input[..end],
192-
&mut self.words,
193-
self.count,
194-
self.last_node,
195-
backend::Finalize::No,
196-
backend::Stride::Serial,
197-
);
198-
self.count = self.count.wrapping_add(end as Count);
199-
input = &input[end..];
200-
}
201-
// Buffer any remaining input, to be either compressed or finalized in a subsequent call.
202-
// Note that this represents some copying overhead, which in theory we could avoid in
203-
// all-at-once setting. A function hardcoded for exactly BLOCKSIZE input bytes is about 10%
204-
// faster than using this implementation for the same input.
205-
self.fill_buf(&mut input);
206-
self
207-
}
208-
209-
/// Finalize the state and return a `Hash`. This method is idempotent, and calling it multiple
210-
/// times will give the same result. It's also possible to `update` with more input in between.
211-
pub fn finalize(&self) -> Hash {
212-
let mut words_copy = self.words;
213-
self.implementation.compress1_loop(
214-
&self.buf[..self.buflen as usize],
215-
&mut words_copy,
216-
self.count,
217-
self.last_node,
218-
backend::Finalize::Yes,
219-
backend::Stride::Serial,
220-
);
221-
Hash {
222-
bytes: state_words_to_bytes(&words_copy),
223-
len: self.hash_length,
224-
}
225-
}
226-
227-
/// Set a flag indicating that this is the last node of its level in a tree hash. This is
228-
/// equivalent to [`Params::last_node`], except that it can be set at any time before calling
229-
/// `finalize`. That allows callers to begin hashing a node without knowing ahead of time
230-
/// whether it's the last in its level. For more details about the intended use of this flag
231-
/// [the BLAKE2 spec].
232-
///
233-
/// [`Params::last_node`]: struct.Params.html#method.last_node
234-
/// [the BLAKE2 spec]: https://blake2.net/blake2.pdf
235-
pub fn set_last_node(&mut self, last_node: bool) -> &mut Self {
236-
self.last_node = if last_node {
237-
backend::LastNode::Yes
238-
} else {
239-
backend::LastNode::No
240-
};
241-
self
242-
}
243-
244-
/// Return the total number of bytes input so far.
245-
///
246-
/// Note that `count` doesn't include the bytes of the key block, if any.
247-
/// It's exactly the total number of input bytes fed to `update`.
248-
pub fn count(&self) -> Count {
249-
let mut ret = self.count.wrapping_add(self.buflen as Count);
250-
if self.is_keyed {
251-
ret -= BLOCKBYTES as Count;
252-
}
253-
ret
254-
}
255-
}
256-
257-
#[inline(always)]
258-
pub(crate) fn state_words_to_bytes(state_words: &[Word; 8]) -> [u8; OUTBYTES] {
259-
let mut bytes = [0; OUTBYTES];
260-
{
261-
const W: usize = size_of::<Word>();
262-
let refs = mut_array_refs!(&mut bytes, W, W, W, W, W, W, W, W);
263-
*refs.0 = state_words[0].to_le_bytes();
264-
*refs.1 = state_words[1].to_le_bytes();
265-
*refs.2 = state_words[2].to_le_bytes();
266-
*refs.3 = state_words[3].to_le_bytes();
267-
*refs.4 = state_words[4].to_le_bytes();
268-
*refs.5 = state_words[5].to_le_bytes();
269-
*refs.6 = state_words[6].to_le_bytes();
270-
*refs.7 = state_words[7].to_le_bytes();
271-
}
272-
bytes
273-
}
274-
275-
#[cfg(feature = "std")]
276-
impl std::io::Write for State {
277-
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
278-
self.update(buf);
279-
Ok(buf.len())
280-
}
281-
282-
fn flush(&mut self) -> std::io::Result<()> {
283-
Ok(())
284-
}
285-
}
286-
287-
impl fmt::Debug for State {
288-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
289-
// NB: Don't print the words. Leaking them would allow length extension.
290-
write!(
291-
f,
292-
"State {{ count: {}, hash_length: {}, last_node: {} }}",
293-
self.count(),
294-
self.hash_length,
295-
self.last_node.yes(),
296-
)
297-
}
298-
}
299-
300-
impl Default for State {
301-
fn default() -> Self {
302-
Self::with_params(&Params::default())
303-
}
304-
}
305-
30699
type HexString = arrayvec::ArrayString<[u8; 2 * OUTBYTES]>;
307100

308101
/// A finalized BLAKE2 hash, with constant-time equality.
@@ -381,7 +174,7 @@ pub(crate) fn paint_test_input(buf: &mut [u8]) {
381174
let mut counter: u32 = 1;
382175
while offset < buf.len() {
383176
let bytes = counter.to_le_bytes();
384-
let take = cmp::min(bytes.len(), buf.len() - offset);
177+
let take = core::cmp::min(bytes.len(), buf.len() - offset);
385178
buf[offset..][..take].copy_from_slice(&bytes[..take]);
386179
counter += 1;
387180
offset += take;

blake2/src/blake2b/many.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
4545
use super::{
4646
backend::{self, Finalize, Implementation, Job, LastNode, Stride},
47-
state_words_to_bytes, Count, Hash, Params, State, Word, BLOCKBYTES,
47+
state, Count, Hash, Params, State, Word, BLOCKBYTES,
4848
};
4949
use arrayref::array_mut_ref;
5050
use arrayvec::ArrayVec;
@@ -317,7 +317,7 @@ impl<'a> HashManyJob<'a> {
317317
pub fn to_hash(&self) -> Hash {
318318
debug_assert!(self.finished, "job hasn't been run yet");
319319
Hash {
320-
bytes: state_words_to_bytes(&self.words),
320+
bytes: state::words_to_bytes(&self.words),
321321
len: self.hash_length,
322322
}
323323
}

blake2/src/blake2b/params.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use super::{
2-
backend, state_words_to_bytes, Hash, State, Word, BLOCKBYTES, IV, KEYBYTES, OUTBYTES,
3-
PERSONALBYTES, SALTBYTES,
2+
backend, state, Hash, State, Word, BLOCKBYTES, IV, KEYBYTES, OUTBYTES, PERSONALBYTES, SALTBYTES,
43
};
54
use arrayref::array_refs;
65
use core::fmt;
@@ -107,7 +106,7 @@ impl Params {
107106
backend::Stride::Serial,
108107
);
109108
Hash {
110-
bytes: state_words_to_bytes(&words),
109+
bytes: state::words_to_bytes(&words),
111110
len: self.hash_length,
112111
}
113112
}

0 commit comments

Comments
 (0)