Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion blake2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ categories = ["cryptography", "no-std"]
[dependencies]
digest = "0.8"
byte-tools = "0.3"
byteorder = { version = "1", default-features = false }
crypto-mac = "0.7"
opaque-debug = "0.2"

Expand All @@ -22,7 +23,7 @@ hex-literal = "0.1"

[features]
default = ["std"]
std = ["digest/std", "crypto-mac/std"]
std = ["digest/std", "byteorder/std", "crypto-mac/std"]
simd = []
simd_opt = ["simd"]
simd_asm = ["simd_opt"]
Expand Down
65 changes: 52 additions & 13 deletions blake2/src/blake2.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
macro_rules! blake2_impl {
(
$state:ident, $fix_state:ident, $word:ident, $vec:ident, $bytes:ident,
$state:ident, $fix_state:ident, $word:ident, $vec:ident, $pack:ident, $bytes:ident,
$block_size:ident, $R1:expr, $R2:expr, $R3:expr, $R4:expr, $IV:expr,
$vardoc:expr, $doc:expr,
) => {

use $crate::as_bytes::AsBytes;
use $crate::simd::{Vector4, $vec};

use byteorder::{ByteOrder, LittleEndian};
use digest::{Input, BlockInput, FixedOutput, VariableOutput, Reset};
use digest::InvalidOutputSize;
use digest::generic_array::GenericArray;
use digest::generic_array::typenum::Unsigned;
use digest::generic_array::typenum::{U4, Unsigned};
use core::cmp;
use core::ops::Div;
use byte_tools::{copy, zero};
use crypto_mac::{Mac, MacResult, InvalidKeyLength};

Expand Down Expand Up @@ -80,23 +82,52 @@ macro_rules! blake2_impl {
/// make sure to compare codes in constant time! It can be done
/// for example by using `subtle` crate.
pub fn new_keyed(key: &[u8], output_size: usize) -> Self {
Self::with_params(key, &[], &[], output_size)
}

/// Creates a new hashing context with the full set of sequential-mode parameters.
pub fn with_params(key: &[u8], salt: &[u8], persona: &[u8], output_size: usize) -> Self {
let kk = key.len();
assert!(kk <= $bytes::to_usize());
assert!(output_size <= $bytes::to_usize());

let p0 = 0x0101_0000 ^ ((kk as $word) << 8) ^
// The number of bytes needed to express two words.
let length = $bytes::to_usize()/4;
assert!(salt.len() <= length);
assert!(persona.len() <= length);

// Build a parameter block
let mut p = [0 as $word; 8];
p[0] = 0x0101_0000 ^ ((kk as $word) << 8) ^
(output_size as $word);
let h0 = [iv0() ^ $vec::new(p0, 0, 0, 0), iv1()];
let mut state = $state {
m: [0; 16],
h: h0,
t: 0,
n: output_size,

t0: 0,
m0: [0; 16],
h0: h0,
};
// salt is two words long
if salt.len() < length {
let mut padded_salt = GenericArray::<u8, <$bytes as Div<U4>>::Output>::default();
for i in 0..salt.len() {
padded_salt[i] = salt[i];
}
p[4] = LittleEndian::$pack(&padded_salt[0 .. length/2]);
p[5] = LittleEndian::$pack(&padded_salt[length/2 .. padded_salt.len()]);
} else {
p[4] = LittleEndian::$pack(&salt[0 .. salt.len()/2]);
p[5] = LittleEndian::$pack(&salt[salt.len()/2 .. salt.len()]);
}

// persona is also two words long
if persona.len() < length {
let mut padded_persona = GenericArray::<u8, <$bytes as Div<U4>>::Output>::default();
for i in 0..persona.len() {
padded_persona[i] = persona[i];
}
p[6] = LittleEndian::$pack(&padded_persona[0 .. length/2]);
p[7] = LittleEndian::$pack(&padded_persona[length/2 .. padded_persona.len()]);
} else {
p[6] = LittleEndian::$pack(&persona[0 .. length/2]);
p[7] = LittleEndian::$pack(&persona[length/2 .. persona.len()]);
}

let mut state = Self::with_parameter_block(&p);

if kk > 0 {
copy(key, state.m.as_mut_bytes());
Expand Down Expand Up @@ -283,6 +314,14 @@ macro_rules! blake2_impl {
state: $state,
}

impl $fix_state {
/// Creates a new hashing context with the full set of sequential-mode parameters.
pub fn with_params(key: &[u8], salt: &[u8], persona: &[u8]) -> Self {
let state = $state::with_params(key, salt, persona, $bytes::to_usize());
Self { state }
}
}

impl Default for $fix_state {
fn default() -> Self {
let state = $state::new_keyed(&[], $bytes::to_usize());
Expand Down
2 changes: 1 addition & 1 deletion blake2/src/blake2b.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use digest::generic_array::typenum::{U64, U128};
use consts::BLAKE2B_IV;

blake2_impl!(VarBlake2b, Blake2b, u64, u64x4, U64, U128,
blake2_impl!(VarBlake2b, Blake2b, u64, u64x4, read_u64, U64, U128,
32, 24, 16, 63, BLAKE2B_IV,
"Blake2b instance with a variable output.",
"Blake2b instance with a fixed output.",
Expand Down
2 changes: 1 addition & 1 deletion blake2/src/blake2s.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use digest::generic_array::typenum::{U32, U64};
use consts::BLAKE2S_IV;

blake2_impl!(VarBlake2s, Blake2s, u32, u32x4, U32, U64,
blake2_impl!(VarBlake2s, Blake2s, u32, u32x4, read_u32, U32, U64,
16, 12, 8, 7, BLAKE2S_IV,
"Blake2s instance with a variable output.",
"Blake2s instance with a fixed output.",
Expand Down
1 change: 1 addition & 0 deletions blake2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
#[macro_use] extern crate opaque_debug;
#[macro_use] pub extern crate digest;
extern crate byte_tools;
extern crate byteorder;
pub extern crate crypto_mac;

#[cfg(feature = "std")]
Expand Down
24 changes: 24 additions & 0 deletions blake2/tests/persona.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#[macro_use]
extern crate hex_literal;

extern crate blake2;

use blake2::{Blake2b, Blake2s, Digest};

#[test]
fn blake2s_persona() {
let key_bytes = hex!("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
let persona = "personal";
let persona_bytes = persona.as_bytes();
let ctx = Blake2s::with_params(&key_bytes, &[], persona_bytes);
assert_eq!(ctx.result().as_slice(), &hex!("25a4ee63b594aed3f88a971e1877ef7099534f9097291f88fb86c79b5e70d022")[..]);
}

#[test]
fn blake2b_persona() {
let key_bytes = hex!("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
let persona = "personal";
let persona_bytes = persona.as_bytes();
let ctx = Blake2b::with_params(&key_bytes, &[], persona_bytes);
assert_eq!(ctx.result().as_slice(), &hex!("03de3b295dcfc3b25b05abb09bc95fe3e9ff3073638badc68101d1e42019d0771dd07525a3aae8318e92c5e5d967ba92e4810d0021d7bf3b49da0b4b4a8a4e1f")[..]);
}