Skip to content

Commit

Permalink
Add state changes
Browse files Browse the repository at this point in the history
  • Loading branch information
joshuajbouw committed Jun 2, 2021
1 parent cebb7df commit 0a21d37
Show file tree
Hide file tree
Showing 6 changed files with 187 additions and 92 deletions.
152 changes: 74 additions & 78 deletions src/blake2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ macro_rules! blake2_impl {
$vardoc:expr, $doc:expr,
) => {
use $crate::as_bytes::AsBytes;
use $crate::error::Error;
use $crate::simd::{$vec, Vector4};

use core::{cmp, convert::TryInto, ops::Div};
Expand All @@ -27,6 +28,17 @@ macro_rules! blake2_impl {
h0: [$vec; 2],
m0: [$word; 16],
t0: u64,

rounds: u32,
}

// Can't make this a const, else it would be great as that.
fn max_rounds() -> u32 {
if $bytes::to_u8() == 64 {
12
} else {
10
}
}

#[inline(always)]
Expand Down Expand Up @@ -71,42 +83,6 @@ macro_rules! blake2_impl {
unshuffle(v);
}

/// The compression function of the blake2 algorithm.
///
/// Takes as an argument the state vector "h", message block vector "m"
/// (the last block is padded with zeros to full block size, if
/// required), 2w-bit offset counter "t", and final block indicator flag
/// "f". Local vector v[0..15] is used in processing. F returns a new
/// state vector. The number of rounds, "r", is 12 for BLAKE2b and 10
/// for BLAKE2s. Rounds are numbered from 0 to r - 1.
pub fn f(rounds: u32, h: [$word; 8], m: [$word; 16], t: [$word; 2], f: bool) -> Output {
use $crate::consts::SIGMA;
let mut h: [$vec; 2] = [
$vec::new(h[0], h[1], h[2], h[3]),
$vec::new(h[4], h[5], h[6], h[7]),
];

let (f0, f1) = if f { (!0, 0) } else { (0, 0) };

let (t0, t1) = (t[0], t[1]);

let mut v = [h[0], h[1], iv0(), iv1() ^ $vec::new(t0, t1, f0, f1)];

for x in 1..rounds + 1 {
let x = if x > 10 { x - 11 } else { x - 1 };
round(&mut v, &m, &SIGMA[x as usize]);
}

h[0] = h[0] ^ (v[0] ^ v[2]);
h[1] = h[1] ^ (v[1] ^ v[3]);

let buf = [h[0].to_le(), h[1].to_le()];
let mut out = GenericArray::default();
copy(buf.as_bytes(), &mut out);

out
}

impl $state {
/// Creates a new hashing context with a key.
///
Expand Down Expand Up @@ -146,9 +122,7 @@ macro_rules! blake2_impl {
}
p[4] = $word::from_le_bytes(padded_salt[0..length / 2].try_into().unwrap());
p[5] = $word::from_le_bytes(
padded_salt[length / 2..padded_salt.len()]
.try_into()
.unwrap(),
padded_salt[length / 2..padded_salt.len()].try_into().unwrap(),
);
} else {
p[4] = $word::from_le_bytes(salt[0..salt.len() / 2].try_into().unwrap());
Expand All @@ -165,9 +139,7 @@ macro_rules! blake2_impl {
}
p[6] = $word::from_le_bytes(padded_persona[0..length / 2].try_into().unwrap());
p[7] = $word::from_le_bytes(
padded_persona[length / 2..padded_persona.len()]
.try_into()
.unwrap(),
padded_persona[length / 2..padded_persona.len()].try_into().unwrap(),
);
} else {
p[6] = $word::from_le_bytes(persona[0..length / 2].try_into().unwrap());
Expand Down Expand Up @@ -209,11 +181,33 @@ macro_rules! blake2_impl {
t0: 0,
m0: [0; 16],
h0,

rounds: max_rounds(),
}
}

/// Constructs a new hashing context with a given state.
///
/// This enables continued hashing of a pre-hashed state.
///
/// **Warning**: The user of this method is responsible for the
/// initialization of the vectors for the first round.
pub fn with_state(rounds: u32, state: [$word; 8], t: u64) -> Result<Self, Error> {
if rounds > 12 {
return Err(Error::TooManyRounds { max: max_rounds(), actual: rounds });
}

let h0 = [
$vec::new(state[0], state[1], state[2], state[3]),
$vec::new(state[4], state[5], state[6], state[7]),
];
let nn = $bytes::to_u8() as usize;

Ok($state { m: [0; 16], h: h0, t, n: nn, t0: t, m0: [0; 16], h0, rounds })
}

/// Updates the hashing context with more data.
fn update(&mut self, data: &[u8]) {
pub fn update_inner(&mut self, data: &[u8]) -> Result<(), Error> {
let mut rest = data;

let block = 2 * $bytes::to_usize();
Expand All @@ -226,10 +220,10 @@ macro_rules! blake2_impl {
rest = &rest[part.len()..];

copy(part, &mut self.m.as_mut_bytes()[off..]);
self.t = self
.t
.checked_add(part.len() as u64)
.expect("hash data length overflow");
self.t = match self.t.checked_add(part.len() as u64) {
Some(v) => v,
None => return Err(Error::HashDataOverflow),
}
}

while rest.len() >= block {
Expand All @@ -239,22 +233,24 @@ macro_rules! blake2_impl {
rest = &rest[part.len()..];

copy(part, &mut self.m.as_mut_bytes());
self.t = self
.t
.checked_add(part.len() as u64)
.expect("hash data length overflow");
self.t = match self.t.checked_add(part.len() as u64) {
Some(v) => v,
None => return Err(Error::HashDataOverflow),
}
}

let n = rest.len();
if n > 0 {
self.compress(0, 0);

copy(rest, &mut self.m.as_mut_bytes());
self.t = self
.t
.checked_add(rest.len() as u64)
.expect("hash data length overflow");
self.t = match self.t.checked_add(rest.len() as u64) {
Some(v) => v,
None => return Err(Error::HashDataOverflow),
}
}

Ok(())
}

#[doc(hidden)]
Expand All @@ -270,14 +266,11 @@ macro_rules! blake2_impl {

self.compress(!0, f1);

let buf = [self.h[0].to_le(), self.h[1].to_le()];

let mut out = GenericArray::default();
copy(buf.as_bytes(), &mut out);
out
self.output()
}

fn compress(&mut self, f0: $word, f1: $word) {
/// Compression `F` function.
pub fn compress(&mut self, f0: $word, f1: $word) {
use $crate::consts::SIGMA;

let m = &self.m;
Expand All @@ -292,25 +285,28 @@ macro_rules! blake2_impl {

let mut v = [h[0], h[1], iv0(), iv1() ^ $vec::new(t0, t1, f0, f1)];

round(&mut v, m, &SIGMA[0]);
round(&mut v, m, &SIGMA[1]);
round(&mut v, m, &SIGMA[2]);
round(&mut v, m, &SIGMA[3]);
round(&mut v, m, &SIGMA[4]);
round(&mut v, m, &SIGMA[5]);
round(&mut v, m, &SIGMA[6]);
round(&mut v, m, &SIGMA[7]);
round(&mut v, m, &SIGMA[8]);
round(&mut v, m, &SIGMA[9]);

if $bytes::to_u8() == 64 {
round(&mut v, m, &SIGMA[0]);
round(&mut v, m, &SIGMA[1]);
for x in 1..=self.rounds {
let x = if x > 10 { x - 11 } else { x - 1 };
round(&mut v, &m, &SIGMA[x as usize]);
}

h[0] = h[0] ^ (v[0] ^ v[2]);
h[1] = h[1] ^ (v[1] ^ v[3]);
}

/// Returns the current count value `t`.
pub fn counter(&self) -> u64 {
self.t
}

/// Returns the current hashed state.
pub fn output(&self) -> Output {
let buf = [self.h[0].to_le(), self.h[1].to_le()];

let mut out = GenericArray::default();
copy(buf.as_bytes(), &mut out);
out
}
}

impl Default for $state {
Expand All @@ -325,7 +321,7 @@ macro_rules! blake2_impl {

impl Update for $state {
fn update(&mut self, data: impl AsRef<[u8]>) {
self.update(data.as_ref());
self.update_inner(data.as_ref()).unwrap();
}
}

Expand Down Expand Up @@ -386,7 +382,7 @@ macro_rules! blake2_impl {

impl Update for $fix_state {
fn update(&mut self, data: impl AsRef<[u8]>) {
self.state.update(data.as_ref());
self.state.update_inner(data.as_ref()).unwrap();
}
}

Expand Down Expand Up @@ -426,7 +422,7 @@ macro_rules! blake2_impl {
type OutputSize = $bytes;

fn update(&mut self, data: &[u8]) {
self.state.update(data);
self.state.update_inner(data).unwrap();
}

fn reset(&mut self) {
Expand Down
3 changes: 3 additions & 0 deletions src/consts.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![allow(clippy::unreadable_literal)]

/// Message word permutations.
pub static SIGMA: [[usize; 16]; 12] = [
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
[14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3],
Expand All @@ -15,6 +16,7 @@ pub static SIGMA: [[usize; 16]; 12] = [
[14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3],
];

/// Blake2b initialization vector.
pub static BLAKE2B_IV: [u64; 8] = [
0x6a09e667f3bcc908,
0xbb67ae8584caa73b,
Expand All @@ -34,6 +36,7 @@ pub const BLAKE2B_SALTBYTES : usize = 16;
pub const BLAKE2B_PERSONALBYTES : usize = 16;
*/

/// Blake2s initialization vector.
pub static BLAKE2S_IV: [u32; 8] = [
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19,
];
Expand Down
41 changes: 41 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use core::fmt;

/// An error that occurred during parsing or hashing.
#[derive(Clone, PartialEq)]
#[non_exhaustive]
pub enum Error {
/// A data overflow error.
HashDataOverflow,
/// Too many rounds error.
TooManyRounds {
/// Max rounds allowed.
max: u32,
/// Actual round value.
actual: u32,
},
}

// This prints better looking error messages if `unwrap` is called.
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use Error::*;
match *self {
HashDataOverflow => f.debug_tuple("HashDataOverflow").finish(),
TooManyRounds { ref max, ref actual } => {
f.debug_struct("TooManyRounds").field("max", max).field("actual", actual).finish()
}
}
}
}

impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use Error::*;
match *self {
HashDataOverflow => write!(f, "Hash data length overflow."),
TooManyRounds { ref max, ref actual } => {
write!(f, "Too many rounds. Expected fewer than {}, got {}.", max, actual)
}
}
}
}
7 changes: 5 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,12 @@ mod blake2;

mod blake2b;
mod blake2s;
mod error;

pub use crypto_mac;
pub use digest::{self, Digest};

pub use crate::blake2b::{f as blake2b_f, Blake2b, VarBlake2b};
pub use crate::blake2s::{f as blake2s_f, Blake2s, VarBlake2s};
pub use crate::blake2b::{Blake2b, VarBlake2b};
pub use crate::blake2s::{Blake2s, VarBlake2s};
pub use crate::consts::{BLAKE2B_IV, BLAKE2S_IV, SIGMA};
pub use crate::error::Error;
14 changes: 2 additions & 12 deletions src/simd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,22 +78,12 @@ macro_rules! impl_vector4 {
#[cfg(not(target_endian = "little"))]
#[inline(always)]
fn to_le(self) -> Self {
$vec::new(
self.0.to_le(),
self.1.to_le(),
self.2.to_le(),
self.3.to_le(),
)
$vec::new(self.0.to_le(), self.1.to_le(), self.2.to_le(), self.3.to_le())
}

#[inline(always)]
fn to_be(self) -> Self {
$vec::new(
self.0.to_be(),
self.1.to_be(),
self.2.to_be(),
self.3.to_be(),
)
$vec::new(self.0.to_be(), self.1.to_be(), self.2.to_be(), self.3.to_be())
}

#[inline(always)]
Expand Down
Loading

0 comments on commit 0a21d37

Please sign in to comment.