diff --git a/Cargo.toml b/Cargo.toml index a74e834..6821f21 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,14 +1,19 @@ [package] name = "khash" description = "Kana hashes" -version = "1.2.0" +version = "2.0.0" authors = ["Avril "] edition = "2018" license = "GPL-3.0-or-later" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] -crate-type = ["cdylib", "staticlib"] +crate-type = ["rlib", "cdylib", "staticlib"] + +[features] +default = ["ffi"] + +ffi = [] [profile.release] opt-level = 3 diff --git a/src/c.rs b/src/c.rs new file mode 100644 index 0000000..2b9df6f --- /dev/null +++ b/src/c.rs @@ -0,0 +1,166 @@ +//! FFI exported functions +use super::*; + + +/// Calculate the length in bytes of a kana hash output. +/// +/// # Note +/// Does not consume `salt` +#[no_mangle] +pub unsafe extern "C" fn khash_length(context: *const c_void, bin: *const c_void, sz: size_t, out_len: *mut size_t) -> i32 +{ + let context = context as *const ctx::CContext; + no_unwind!{ + try error::Error::Unknown; + let context = ctx::Context::clone_from_raw(context); + let bin = HeapArray::::from_raw_copied(bin as *const u8, usize::from(sz)); + let string = c_try!(generate(&context, &bin)); + *out_len = string.bytes().len().into(); + + GENERIC_SUCCESS + } +} + +/// Compute and write a kana hash output to a string. +/// +/// # Note +/// Consumes `salt` +#[no_mangle] +pub unsafe extern "C" fn khash_do(context: *mut c_void, bin: *const c_void, sz: size_t, out_str: *mut c_char, str_len: size_t) -> i32 +{ + let context = context as *mut ctx::CContext; + no_unwind!{ + try error::Error::Unknown; + + let context = ctx::Context::from_raw(context); + let bin = HeapArray::::from_raw_copied(bin as *const u8, usize::from(sz)); + let string: Vec = c_try!(generate(&context, &bin)).bytes().collect(); + + libc::memcpy(out_str as *mut c_void, &string[0] as *const u8 as *const c_void, std::cmp::min(str_len, string.len())); + + GENERIC_SUCCESS + } +} + +/// Free a context +#[no_mangle] +pub unsafe extern "C" fn khash_free_context(context: *mut c_void) -> i32 +{ + let context = context as *mut ctx::CContext; + no_unwind!{ + drop(ctx::Context::from_raw(context)); + GENERIC_SUCCESS + } +} + +/// Create a new context +#[no_mangle] +pub unsafe extern "C" fn khash_new_context(algo: u8, salt_type: u8, bin: *const c_void, sz: size_t, nptr: *mut c_void) -> i32 +{ + let nptr = nptr as *mut ctx::CContext; + no_unwind!{ + try error::Error::Unknown; + let salt = match salt_type { + salt::SALT_TYPE_SPECIFIC => { + let bin = HeapArray::::from_raw_copied(bin as *const u8, usize::from(sz)); + salt::Salt::unfixed(&bin[..]) + }, + salt::SALT_TYPE_DEFAULT => { + salt::Salt::default() + }, + salt::SALT_TYPE_RANDOM => { + match salt::Salt::random() { + Ok(v) => v, + Err(e) => return i32::from(error::Error::RNG(e)), + } + }, + _ => { + salt::Salt::None + }, + }; + let context = ctx::Context::new(algo.into(), salt); + *nptr = context.into_raw(); + GENERIC_SUCCESS + } +} + + +/// Clone a context +#[no_mangle] +pub unsafe extern "C" fn khash_clone_context(raw: *const c_void, out: *mut c_void) -> i32 +{ + let raw = raw as *const ctx::CContext; + let out = out as *mut ctx::CContext; + no_unwind!{ + *out = ctx::Context::clone_from_raw(raw).into_raw(); + GENERIC_SUCCESS + } +} + +/// Free a salt allocated with `khash_new_salt` +#[no_mangle] +pub unsafe extern "C" fn khash_free_salt(salt: *mut c_void) -> i32 +{ + let salt = salt as *mut salt::FFI; + no_unwind!{ + drop(salt::from_raw(salt)); + GENERIC_SUCCESS + } +} + +/// Create a new salt +#[no_mangle] +pub unsafe extern "C" fn khash_new_salt(salt_type: u8, bin: *const c_void, sz: size_t, nptr: *mut c_void) -> i32 +{ + let nptr = nptr as *mut salt::FFI; + no_unwind!{ + try error::Error::Unknown; + match salt_type { + salt::SALT_TYPE_SPECIFIC => { + let bin = HeapArray::::from_raw_copied(bin as *const u8, usize::from(sz)); + *nptr = salt::into_raw(salt::Salt::unfixed(&bin[..])); + }, + salt::SALT_TYPE_DEFAULT => { + *nptr = salt::into_raw(salt::Salt::default()); + }, + salt::SALT_TYPE_RANDOM => { + *nptr = salt::into_raw(match salt::Salt::random() { + Ok(v) => v, + Err(e) => return i32::from(error::Error::RNG(e)), + }) + }, + _ => { + *nptr = salt::into_raw(salt::Salt::None); + }, + } + GENERIC_SUCCESS + } +} + +/// Clone a salt +#[no_mangle] +pub unsafe extern "C" fn khash_clone_salt(salt: *const c_void, out: *mut c_void) -> i32 +{ + let salt = salt as *const salt::FFI; + let out = out as *mut salt::FFI; + no_unwind!{ + *out = salt::into_raw(salt::clone_from_raw(salt)); + GENERIC_SUCCESS + } +} + +/// Find the maximum length possible for a given algorithm's output. +#[no_mangle] +pub unsafe extern "C" fn khash_max_length(algo: u8, _input_sz: libc::size_t, max_len: *mut libc::size_t) -> i32 +{ + no_unwind!{ + let hash_sz = match ctx::Algorithm::from(algo) { + ctx::Algorithm::Crc32 => std::mem::size_of::(), + ctx::Algorithm::Crc64 => std::mem::size_of::(), + ctx::Algorithm::Sha256 => std::mem::size_of::(), + ctx::Algorithm::Sha256Truncated => std::mem::size_of::(), + }; + *max_len = std::mem::size_of::() * hash_sz; + GENERIC_SUCCESS + } +} diff --git a/src/ctx.rs b/src/ctx.rs index 4b59224..5752a3c 100644 --- a/src/ctx.rs +++ b/src/ctx.rs @@ -1,3 +1,4 @@ +//! Contains contexts used for algorithms use crate::*; use std::{ io::{ @@ -17,7 +18,7 @@ pub enum Algorithm impl Default for Algorithm { - fn default() -> Self + #[inline] fn default() -> Self { Self::Sha256Truncated } @@ -52,7 +53,6 @@ impl Context { &self.salt } - pub(crate) fn compute(&self, mut from: R) -> Result<(usize, Box<[u8]>), error::Error> { diff --git a/src/error.rs b/src/error.rs index 0a80d31..966861e 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,3 +1,4 @@ +//! Error for kana-hash functions use std::{ fmt, io, @@ -6,6 +7,7 @@ use std::{ /// An error value used by all kana-hash functions. #[derive(Debug)] +#[non_exhaustive] pub enum Error { /// There was an IO error reading or writing a buffer. diff --git a/src/lib.rs b/src/lib.rs index 18aef01..9ec827e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,8 @@ -//#![feature(const_generics)] +#![cfg_attr(nightly, feature(test))] #![allow(dead_code)] + +#[cfg(nightly)] extern crate test; + use std::{ io::{ Read, @@ -13,6 +16,7 @@ type HASHER = hash::Crc64Checksum; mod tests { use super::*; use std::collections::HashMap; + #[cfg(nightly)] use test::{Bencher, black_box,}; #[test] fn distrubution() @@ -223,6 +227,12 @@ pub fn generate>(context: &ctx::Context, bytes: T) -> Result(context: &ctx::Context, from: &mut T) -> Result<(usize, String), error::Error> +{ + compute(context, from) +} + use std::ffi::c_void; use libc::{ size_t, @@ -237,165 +247,7 @@ use malloc_array::{ // FFI section -/// Calculate the length in bytes of a kana hash output. -/// -/// # Note -/// Does not consume `salt` -#[no_mangle] -pub unsafe extern "C" fn khash_length(context: *const c_void, bin: *const c_void, sz: size_t, out_len: *mut size_t) -> i32 -{ - let context = context as *const ctx::CContext; - no_unwind!{ - try error::Error::Unknown; - let context = ctx::Context::clone_from_raw(context); - let bin = HeapArray::::from_raw_copied(bin as *const u8, usize::from(sz)); - let string = c_try!(generate(&context, &bin)); - *out_len = string.bytes().len().into(); - - GENERIC_SUCCESS - } -} - -/// Compute and write a kana hash output to a string. -/// -/// # Note -/// Consumes `salt` -#[no_mangle] -pub unsafe extern "C" fn khash_do(context: *mut c_void, bin: *const c_void, sz: size_t, out_str: *mut c_char, str_len: size_t) -> i32 -{ - let context = context as *mut ctx::CContext; - no_unwind!{ - try error::Error::Unknown; - - let context = ctx::Context::from_raw(context); - let bin = HeapArray::::from_raw_copied(bin as *const u8, usize::from(sz)); - let string: Vec = c_try!(generate(&context, &bin)).bytes().collect(); - - libc::memcpy(out_str as *mut c_void, &string[0] as *const u8 as *const c_void, std::cmp::min(str_len, string.len())); - - GENERIC_SUCCESS - } -} - -/// Free a context -#[no_mangle] -pub unsafe extern "C" fn khash_free_context(context: *mut c_void) -> i32 -{ - let context = context as *mut ctx::CContext; - no_unwind!{ - drop(ctx::Context::from_raw(context)); - GENERIC_SUCCESS - } -} - -/// Create a new context -#[no_mangle] -pub unsafe extern "C" fn khash_new_context(algo: u8, salt_type: u8, bin: *const c_void, sz: size_t, nptr: *mut c_void) -> i32 -{ - let nptr = nptr as *mut ctx::CContext; - no_unwind!{ - try error::Error::Unknown; - let salt = match salt_type { - salt::SALT_TYPE_SPECIFIC => { - let bin = HeapArray::::from_raw_copied(bin as *const u8, usize::from(sz)); - salt::Salt::unfixed(&bin[..]) - }, - salt::SALT_TYPE_DEFAULT => { - salt::Salt::default() - }, - salt::SALT_TYPE_RANDOM => { - match salt::Salt::random() { - Ok(v) => v, - Err(e) => return i32::from(error::Error::RNG(e)), - } - }, - _ => { - salt::Salt::None - }, - }; - let context = ctx::Context::new(algo.into(), salt); - *nptr = context.into_raw(); - GENERIC_SUCCESS - } -} - - -/// Clone a context -#[no_mangle] -pub unsafe extern "C" fn khash_clone_context(raw: *const c_void, out: *mut c_void) -> i32 -{ - let raw = raw as *const ctx::CContext; - let out = out as *mut ctx::CContext; - no_unwind!{ - *out = ctx::Context::clone_from_raw(raw).into_raw(); - GENERIC_SUCCESS - } -} - -/// Free a salt allocated with `khash_new_salt` -#[no_mangle] -pub unsafe extern "C" fn khash_free_salt(salt: *mut c_void) -> i32 -{ - let salt = salt as *mut salt::FFI; - no_unwind!{ - drop(salt::from_raw(salt)); - GENERIC_SUCCESS - } -} - -/// Create a new salt -#[no_mangle] -pub unsafe extern "C" fn khash_new_salt(salt_type: u8, bin: *const c_void, sz: size_t, nptr: *mut c_void) -> i32 -{ - let nptr = nptr as *mut salt::FFI; - no_unwind!{ - try error::Error::Unknown; - match salt_type { - salt::SALT_TYPE_SPECIFIC => { - let bin = HeapArray::::from_raw_copied(bin as *const u8, usize::from(sz)); - *nptr = salt::into_raw(salt::Salt::unfixed(&bin[..])); - }, - salt::SALT_TYPE_DEFAULT => { - *nptr = salt::into_raw(salt::Salt::default()); - }, - salt::SALT_TYPE_RANDOM => { - *nptr = salt::into_raw(match salt::Salt::random() { - Ok(v) => v, - Err(e) => return i32::from(error::Error::RNG(e)), - }) - }, - _ => { - *nptr = salt::into_raw(salt::Salt::None); - }, - } - GENERIC_SUCCESS - } -} - -/// Clone a salt -#[no_mangle] -pub unsafe extern "C" fn khash_clone_salt(salt: *const c_void, out: *mut c_void) -> i32 -{ - let salt = salt as *const salt::FFI; - let out = out as *mut salt::FFI; - no_unwind!{ - *out = salt::into_raw(salt::clone_from_raw(salt)); - GENERIC_SUCCESS - } -} - -/// Find the maximum length possible for a given algorithm's output. -#[no_mangle] -pub unsafe extern "C" fn khash_max_length(algo: u8, _input_sz: libc::size_t, max_len: *mut libc::size_t) -> i32 -{ - no_unwind!{ - let hash_sz = match ctx::Algorithm::from(algo) { - ctx::Algorithm::Crc32 => std::mem::size_of::(), - ctx::Algorithm::Crc64 => std::mem::size_of::(), - ctx::Algorithm::Sha256 => std::mem::size_of::(), - ctx::Algorithm::Sha256Truncated => std::mem::size_of::(), - }; - *max_len = std::mem::size_of::() * hash_sz; - GENERIC_SUCCESS - } -} +#[cfg(feature="ffi")] +mod c; +#[cfg(feature="ffi")] +pub use c::*; diff --git a/src/mnemonic.rs b/src/mnemonic.rs index 80de6ad..c8861c3 100644 --- a/src/mnemonic.rs +++ b/src/mnemonic.rs @@ -20,6 +20,7 @@ impl Digest { return d; } + let sign0 = from[0] & 0x80 != 0;//unsafe { *reinterpret::value::(from) < 0 }; let range = &map::KANA_SIGN[sign0 as usize]; let kana = &map::KANA[range.clone()]; @@ -34,6 +35,7 @@ impl Digest { Some(_) if xor & 8 == 0 && map::KANA_SWAP2[range.start() + oneesan].is_some() => map::KANA_SWAP2[range.start()+oneesan].unwrap(), _ => kana[oneesan], }); + if from.len() > 1 { if let Some(imoutos) = map::sub(range.start()+oneesan) { if let Some(imouto) = imoutos[usize::from(from[1]) % map::KANA_SUB.len()]