Skip to content
This repository has been archived by the owner on Sep 4, 2022. It is now read-only.

Commit

Permalink
Initial bindings for crypto_generichash
Browse files Browse the repository at this point in the history
  • Loading branch information
cynecx committed May 31, 2018
1 parent 289ec70 commit 3849072
Show file tree
Hide file tree
Showing 3 changed files with 211 additions and 0 deletions.
124 changes: 124 additions & 0 deletions src/crypto/generichash/digest.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
use ffi::crypto_generichash_BYTES_MAX;

#[derive(Clone)]
pub struct Digest {
pub(super) len: usize,
pub(super) data: [u8; crypto_generichash_BYTES_MAX],
}

impl ::std::cmp::PartialEq for Digest {
fn eq(&self, other: &Digest) -> bool {
use utils::memcmp;
if other.len != self.len {
return false;
}
memcmp(self.as_ref(), self.as_ref())
}
}

impl ::std::cmp::Eq for Digest {}

impl AsRef<[u8]> for Digest {
#[inline]
fn as_ref(&self) -> &[u8] {
&self.data[0..self.len]
}
}

impl ::std::cmp::PartialOrd for Digest {
#[inline]
fn partial_cmp(&self, other: &Digest) -> Option<::std::cmp::Ordering> {
::std::cmp::PartialOrd::partial_cmp(self.as_ref(), other.as_ref())
}

#[inline]
fn lt(&self, other: &Digest) -> bool {
::std::cmp::PartialOrd::lt(self.as_ref(), other.as_ref())
}

#[inline]
fn le(&self, other: &Digest) -> bool {
::std::cmp::PartialOrd::le(self.as_ref(), other.as_ref())
}

#[inline]
fn ge(&self, other: &Digest) -> bool {
::std::cmp::PartialOrd::ge(self.as_ref(), other.as_ref())
}

#[inline]
fn gt(&self, other: &Digest) -> bool {
::std::cmp::PartialOrd::gt(self.as_ref(), other.as_ref())
}
}

impl ::std::cmp::Ord for Digest {
#[inline]
fn cmp(&self, other: &Digest) -> ::std::cmp::Ordering {
::std::cmp::Ord::cmp(self.as_ref(), other.as_ref())
}
}

impl ::std::hash::Hash for Digest {
fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
::std::hash::Hash::hash(self.as_ref(), state)
}
}

/// Allows a user to access the byte contents of an object as a slice.
///
/// WARNING: it might be tempting to do comparisons on objects
/// by using `x[a..b] == y[a..b]`. This will open up for timing attacks
/// when comparing for example authenticator tags. Because of this only
/// use the comparison functions exposed by the sodiumoxide API.
impl ::std::ops::Index<::std::ops::Range<usize>> for Digest {
type Output = [u8];
fn index(&self, _index: ::std::ops::Range<usize>) -> &[u8] {
self.as_ref().index(_index)
}
}

/// Allows a user to access the byte contents of an object as a slice.
///
/// WARNING: it might be tempting to do comparisons on objects
/// by using `x[..b] == y[..b]`. This will open up for timing attacks
/// when comparing for example authenticator tags. Because of this only
/// use the comparison functions exposed by the sodiumoxide API.
impl ::std::ops::Index<::std::ops::RangeTo<usize>> for Digest {
type Output = [u8];
fn index(&self, _index: ::std::ops::RangeTo<usize>) -> &[u8] {
self.as_ref().index(_index)
}
}

/// Allows a user to access the byte contents of an object as a slice.
///
/// WARNING: it might be tempting to do comparisons on objects
/// by using `x[a..] == y[a..]`. This will open up for timing attacks
/// when comparing for example authenticator tags. Because of this only
/// use the comparison functions exposed by the sodiumoxide API.
impl ::std::ops::Index<::std::ops::RangeFrom<usize>> for Digest {
type Output = [u8];
fn index(&self, _index: ::std::ops::RangeFrom<usize>) -> &[u8] {
self.as_ref().index(_index)
}
}

/// Allows a user to access the byte contents of an object as a slice.
///
/// WARNING: it might be tempting to do comparisons on objects
/// by using `x[] == y[]`. This will open up for timing attacks
/// when comparing for example authenticator tags. Because of this only
/// use the comparison functions exposed by the sodiumoxide API.
impl ::std::ops::Index<::std::ops::RangeFull> for Digest {
type Output = [u8];
fn index(&self, _index: ::std::ops::RangeFull) -> &[u8] {
self.as_ref().index(_index)
}
}

impl ::std::fmt::Debug for Digest {
fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(formatter, "Digest({:?})", &self[..])
}
}
86 changes: 86 additions & 0 deletions src/crypto/generichash/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use ffi::{crypto_generichash_final, crypto_generichash_init,
crypto_generichash_statebytes, crypto_generichash_update,
crypto_generichash_BYTES_MAX, crypto_generichash_BYTES_MIN,
crypto_generichash_KEYBYTES_MAX, crypto_generichash_KEYBYTES_MIN};

use libc::c_ulonglong;
use std::ptr;

mod digest;
pub use self::digest::Digest;

pub struct State {
out_len: usize,
state: Vec<u8>,
}

impl State {
fn new(out_len: usize, key: Option<&[u8]>) -> Option<State> {
if out_len < crypto_generichash_BYTES_MIN
|| out_len > crypto_generichash_BYTES_MAX
{
return None;
}

if let Some(key) = key {
let len = key.len();
if len < crypto_generichash_KEYBYTES_MIN
|| len > crypto_generichash_KEYBYTES_MAX
{
return None;
}
}

let mut state = Vec::<u8>::new();
let result = unsafe {
state.reserve_exact(crypto_generichash_statebytes());
let state_ptr = state.as_mut_slice().as_mut_ptr() as *mut _;
if let Some(key) = key {
crypto_generichash_init(
state_ptr,
key.as_ptr(),
key.len(),
out_len,
)
} else {
crypto_generichash_init(state_ptr, ptr::null(), 0, out_len)
}
};

if result == 0 {
Some(State {
out_len: out_len,
state: state,
})
} else {
None
}
}

pub fn update(&mut self, data: &[u8]) {
unsafe {
let state_ptr = self.state.as_mut_slice().as_mut_ptr() as *mut _;
crypto_generichash_update(
state_ptr,
data.as_ptr(),
data.len() as c_ulonglong,
);
}
}

pub fn finalize(mut self) -> Digest {
let state_ptr = self.state.as_mut_slice().as_mut_ptr() as *mut _;
let mut result = Digest {
len: self.out_len,
data: [0u8; crypto_generichash_BYTES_MAX],
};
unsafe {
crypto_generichash_final(
state_ptr,
result.data.as_mut_ptr(),
result.len,
);
}
result
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ pub mod crypto {
pub mod scalarmult;
pub mod auth;
pub mod hash;
pub mod generichash;
pub mod secretbox;
pub mod onetimeauth;
pub mod pwhash;
Expand Down

0 comments on commit 3849072

Please # to comment.