use super::{HashError, HashInit};
use ledger_secure_sdk_sys::{
CX_OK, cx_blake2b_init_no_throw, cx_blake2b_init2_no_throw, cx_blake2b_t, cx_hash_t,
};
use super::impl_hash;
impl_hash!(Blake2b_256, cx_blake2b_t, cx_blake2b_init_no_throw, 256);
impl_hash!(Blake2b_384, cx_blake2b_t, cx_blake2b_init_no_throw, 384);
impl_hash!(Blake2b_512, cx_blake2b_t, cx_blake2b_init_no_throw, 512);
pub trait Blake2bWithPerso: HashInit {
fn new_with_salt_and_perso(
salt: Option<&mut [u8]>,
perso: Option<&mut [u8]>,
) -> Result<Self, HashError>;
}
macro_rules! impl_blake2b_with_perso {
($type:ident, $bits:expr) => {
impl Blake2bWithPerso for $type {
fn new_with_salt_and_perso(
salt: Option<&mut [u8]>,
perso: Option<&mut [u8]>,
) -> Result<Self, HashError> {
let (salt_ptr, salt_len) = match salt {
Some(s) => (s.as_mut_ptr(), s.len()),
None => (::core::ptr::null_mut(), 0),
};
let (perso_ptr, perso_len) = match perso {
Some(p) => (p.as_mut_ptr(), p.len()),
None => (::core::ptr::null_mut(), 0),
};
let mut ctx: $type = Default::default();
let err = unsafe {
cx_blake2b_init2_no_throw(
&mut ctx.ctx,
$bits,
salt_ptr,
salt_len,
perso_ptr,
perso_len,
)
};
if err != CX_OK {
return Err(HashError::from(err));
}
Ok(ctx)
}
}
};
}
impl_blake2b_with_perso!(Blake2b_256, 256);
impl_blake2b_with_perso!(Blake2b_384, 384);
impl_blake2b_with_perso!(Blake2b_512, 512);
#[cfg(test)]
mod tests {
use crate::assert_eq_err as assert_eq;
use crate::hash::blake2::*;
use crate::testing::TestType;
use testmacro::test_item as test;
const TEST_HASH: &[u8; 29] = b"Not your keys, not your coins";
#[test]
fn test_hash_blake2b256() {
let mut blake2 = Blake2b_256::new();
let mut output: [u8; 32] = [0u8; 32];
let ouput_size = blake2.get_size();
assert_eq!(ouput_size, 32);
let _ = blake2.hash(TEST_HASH, &mut output);
let expected = [
0xcd, 0xa6, 0x49, 0x8e, 0x2f, 0x89, 0x71, 0xe8, 0x4e, 0xd5, 0x68, 0x2e, 0x3d, 0x47,
0x9c, 0xcc, 0x2c, 0xce, 0x7f, 0x37, 0xac, 0x92, 0x9c, 0xa0, 0xb0, 0x41, 0xb2, 0xdd,
0x06, 0xa9, 0xf3, 0xcb,
];
assert_eq!(&output, &expected);
}
#[test]
fn test_hash_blake2b384() {
let mut blake2 = Blake2b_384::new();
let mut output: [u8; 48] = [0u8; 48];
let ouput_size = blake2.get_size();
assert_eq!(ouput_size, 48);
let _ = blake2.hash(TEST_HASH, &mut output);
let expected = [
0x5f, 0x03, 0x04, 0x77, 0x92, 0x5e, 0x91, 0x29, 0xf9, 0xb8, 0xef, 0xf9, 0x88, 0x29,
0x04, 0xf4, 0x4f, 0x65, 0x3b, 0xef, 0xf8, 0x21, 0xca, 0x48, 0x68, 0xa7, 0xbe, 0x46,
0x1c, 0x45, 0x82, 0xb3, 0x3d, 0xd7, 0x7b, 0x9e, 0x91, 0x9a, 0xfe, 0x1c, 0x3b, 0xed,
0x4b, 0x8f, 0x3c, 0x5d, 0xde, 0x53,
];
assert_eq!(&output, &expected);
}
#[test]
fn test_hash_blake2b512() {
let mut blake2 = Blake2b_512::new();
let mut output: [u8; 64] = [0u8; 64];
let ouput_size = blake2.get_size();
assert_eq!(ouput_size, 64);
let _ = blake2.hash(TEST_HASH, &mut output);
let expected = [
0xc2, 0xe0, 0xfe, 0x8c, 0xb7, 0x83, 0x43, 0x7c, 0x8f, 0x36, 0x89, 0x48, 0xc4, 0x7a,
0x9c, 0x7c, 0x27, 0xa3, 0xb5, 0x98, 0x7a, 0x2d, 0x1b, 0x3b, 0xab, 0x48, 0x3d, 0xd6,
0xf6, 0x4c, 0xd1, 0x20, 0x7d, 0x72, 0x62, 0xb5, 0x35, 0xfe, 0x3f, 0x86, 0xad, 0x0c,
0x5f, 0x33, 0x4e, 0x55, 0x07, 0x64, 0x49, 0x7c, 0x11, 0xd5, 0xbd, 0x6a, 0x44, 0x2a,
0x9c, 0x2e, 0x6a, 0xab, 0xf9, 0x31, 0xc0, 0xab,
];
assert_eq!(&output, &expected);
}
#[test]
fn test_blake2b256_with_no_salt_no_perso() {
let mut blake2 = Blake2b_256::new_with_salt_and_perso(None, None).unwrap();
let mut output = [0u8; 32];
let _ = blake2.hash(TEST_HASH, &mut output);
let expected = [
0xcd, 0xa6, 0x49, 0x8e, 0x2f, 0x89, 0x71, 0xe8, 0x4e, 0xd5, 0x68, 0x2e, 0x3d, 0x47,
0x9c, 0xcc, 0x2c, 0xce, 0x7f, 0x37, 0xac, 0x92, 0x9c, 0xa0, 0xb0, 0x41, 0xb2, 0xdd,
0x06, 0xa9, 0xf3, 0xcb,
];
assert_eq!(&output, &expected);
}
#[test]
fn test_blake2b384_with_no_salt_no_perso() {
let mut blake2 = Blake2b_384::new_with_salt_and_perso(None, None).unwrap();
let mut output = [0u8; 48];
let _ = blake2.hash(TEST_HASH, &mut output);
let expected = [
0x5f, 0x03, 0x04, 0x77, 0x92, 0x5e, 0x91, 0x29, 0xf9, 0xb8, 0xef, 0xf9, 0x88, 0x29,
0x04, 0xf4, 0x4f, 0x65, 0x3b, 0xef, 0xf8, 0x21, 0xca, 0x48, 0x68, 0xa7, 0xbe, 0x46,
0x1c, 0x45, 0x82, 0xb3, 0x3d, 0xd7, 0x7b, 0x9e, 0x91, 0x9a, 0xfe, 0x1c, 0x3b, 0xed,
0x4b, 0x8f, 0x3c, 0x5d, 0xde, 0x53,
];
assert_eq!(&output, &expected);
}
#[test]
fn test_blake2b512_with_no_salt_no_perso() {
let mut blake2 = Blake2b_512::new_with_salt_and_perso(None, None).unwrap();
let mut output = [0u8; 64];
let _ = blake2.hash(TEST_HASH, &mut output);
let expected = [
0xc2, 0xe0, 0xfe, 0x8c, 0xb7, 0x83, 0x43, 0x7c, 0x8f, 0x36, 0x89, 0x48, 0xc4, 0x7a,
0x9c, 0x7c, 0x27, 0xa3, 0xb5, 0x98, 0x7a, 0x2d, 0x1b, 0x3b, 0xab, 0x48, 0x3d, 0xd6,
0xf6, 0x4c, 0xd1, 0x20, 0x7d, 0x72, 0x62, 0xb5, 0x35, 0xfe, 0x3f, 0x86, 0xad, 0x0c,
0x5f, 0x33, 0x4e, 0x55, 0x07, 0x64, 0x49, 0x7c, 0x11, 0xd5, 0xbd, 0x6a, 0x44, 0x2a,
0x9c, 0x2e, 0x6a, 0xab, 0xf9, 0x31, 0xc0, 0xab,
];
assert_eq!(&output, &expected);
}
#[test]
fn test_blake2b256_with_salt_and_perso() {
let mut salt = [0x01u8; 16];
let mut perso = [0x02u8; 16];
let mut blake2 =
Blake2b_256::new_with_salt_and_perso(Some(&mut salt), Some(&mut perso)).unwrap();
let mut output = [0u8; 32];
let _ = blake2.hash(TEST_HASH, &mut output);
let plain_expected = [
0xcd, 0xa6, 0x49, 0x8e, 0x2f, 0x89, 0x71, 0xe8, 0x4e, 0xd5, 0x68, 0x2e, 0x3d, 0x47,
0x9c, 0xcc, 0x2c, 0xce, 0x7f, 0x37, 0xac, 0x92, 0x9c, 0xa0, 0xb0, 0x41, 0xb2, 0xdd,
0x06, 0xa9, 0xf3, 0xcb,
];
assert_eq!(output != plain_expected, true);
}
#[test]
fn test_blake2b256_with_salt_and_perso_deterministic() {
let mut salt = [0x01u8; 16];
let mut perso = [0x02u8; 16];
let mut blake2 =
Blake2b_256::new_with_salt_and_perso(Some(&mut salt), Some(&mut perso)).unwrap();
let mut output1 = [0u8; 32];
let _ = blake2.hash(TEST_HASH, &mut output1);
let mut salt2 = [0x01u8; 16];
let mut perso2 = [0x02u8; 16];
let mut blake2_2 =
Blake2b_256::new_with_salt_and_perso(Some(&mut salt2), Some(&mut perso2)).unwrap();
let mut output2 = [0u8; 32];
let _ = blake2_2.hash(TEST_HASH, &mut output2);
assert_eq!(&output1, &output2);
}
}