use crypto::utils::secmem;
use libc::{c_int, c_uchar, c_ulonglong, size_t};
use SSError::{self, HASH};
pub const SHA512_BYTES: usize = 64;
pub const SHA256_BYTES: usize = 32;
extern "C" {
fn crypto_hash_sha256_statebytes() -> size_t;
fn crypto_hash_sha256(out: *mut c_uchar,
in_: *const c_uchar,
inlen: c_ulonglong) -> c_int;
fn crypto_hash_sha256_init(state: *mut c_uchar) -> c_int;
fn crypto_hash_sha256_update(state: *mut c_uchar,
in_: *const c_uchar,
inlen: c_ulonglong) -> c_int;
fn crypto_hash_sha256_final(state: *mut c_uchar,
out: *mut c_uchar) -> c_int;
fn crypto_hash_sha512_statebytes() -> size_t;
fn crypto_hash_sha512(out: *mut c_uchar,
in_: *const c_uchar,
inlen: c_ulonglong) -> c_int;
fn crypto_hash_sha512_init(state: *mut c_uchar) -> c_int;
fn crypto_hash_sha512_update(state: *mut c_uchar,
in_: *const c_uchar,
inlen: c_ulonglong) -> c_int;
fn crypto_hash_sha512_final(state: *mut c_uchar,
out: *mut c_uchar) -> c_int;
}
pub fn hash256<'a>(message: &'a [u8]) -> Result<&'a [u8], SSError> {
let mut out = secmem::malloc(SHA256_BYTES);
let res: i32;
unsafe {
res = crypto_hash_sha256(out.as_mut_ptr(),
message.as_ptr(),
message.len() as c_ulonglong);
}
if res == 0 {
Ok(out)
} else {
Err(HASH("Unable to hash message"))
}
}
pub fn state_size_256() -> Result<usize, SSError> {
let res: size_t;
unsafe {
res = crypto_hash_sha256_statebytes();
}
if res > 0 {
Ok(res as usize)
} else {
Err(HASH("Unable to determind state size"))
}
}
pub fn state_size_512() -> Result<usize, SSError> {
let res: size_t;
unsafe {
res = crypto_hash_sha512_statebytes();
}
if res > 0 {
Ok(res as usize)
} else {
Err(HASH("Unable to determind state size"))
}
}
pub fn init256<'a>(state: &'a mut [u8]) -> Result<(), SSError> {
let res: i32;
unsafe {
res = crypto_hash_sha256_init(state.as_mut_ptr());
}
if res == 0 {
Ok(())
} else {
Err(HASH("Unable to initialize hash state"))
}
}
pub fn update256<'a>(state: &'a mut [u8], in_: &[u8]) -> Result<(), SSError> {
let res: i32;
unsafe {
res = crypto_hash_sha256_update(state.as_mut_ptr(),
in_.as_ptr(),
in_.len() as c_ulonglong);
}
if res == 0 {
Ok(())
} else {
Err(HASH("Unable to update hash state"))
}
}
pub fn finalize256<'a>(state: &'a mut [u8]) -> Result<&'a [u8], SSError> {
let out = secmem::malloc(SHA256_BYTES);
let res: i32;
unsafe {
res = crypto_hash_sha256_final(state.as_mut_ptr(), out.as_mut_ptr());
}
if res == 0 {
secmem::mprotect_readonly(out);
Ok(out)
} else {
Err(HASH("Unable to update hash state"))
}
}
pub fn hash512<'a>(message: &'a [u8]) -> Result<&'a [u8], SSError> {
let mut out = secmem::malloc(SHA512_BYTES);
let res: i32;
unsafe {
res = crypto_hash_sha512(out.as_mut_ptr(),
message.as_ptr(),
message.len() as c_ulonglong);
}
if res == 0 {
Ok(out)
} else {
Err(HASH("Unable to hash message"))
}
}
pub fn init512<'a>(state: &'a mut [u8]) -> Result<(), SSError> {
let res: i32;
unsafe {
res = crypto_hash_sha512_init(state.as_mut_ptr());
}
if res == 0 {
Ok(())
} else {
Err(HASH("Unable to initialize hash state"))
}
}
pub fn update512<'a>(state: &'a mut [u8], in_: &[u8]) -> Result<(), SSError> {
let res: i32;
unsafe {
res = crypto_hash_sha512_update(state.as_mut_ptr(),
in_.as_ptr(),
in_.len() as c_ulonglong);
}
if res == 0 {
Ok(())
} else {
Err(HASH("Unable to update hash state"))
}
}
pub fn finalize512<'a>(state: &'a mut [u8]) -> Result<&'a [u8], SSError> {
let out = secmem::malloc(SHA512_BYTES);
let res: i32;
unsafe {
res = crypto_hash_sha512_final(state.as_mut_ptr(), out.as_mut_ptr());
}
if res == 0 {
secmem::mprotect_readonly(out);
Ok(out)
} else {
Err(HASH("Unable to update hash state"))
}
}