Remove the Keccak C library and use the pure Rust impl (#8657)

* Add license and readme

* Use pure rust implementation

* Bump version to 0.1.1

* Don't use C, prefer the pure Rust implementation

* Add test for `write_keccak`

* Bump version

* Add benchmarks

* Add benchmarks

* Add keccak_256, keccak_512, keccak_256_unchecked and keccak_512_unchecked – mostly for compatibility with ethash

* Remove failed git merge attempt from external git repo
Cargo.lock updates

* whitespace

* Mark unsafe function unsafe

* Unsafe calls in unsafe block

* Document unsafety invariants

* Revert unintended changes to Cargo.lock
This commit is contained in:
David 2018-05-20 06:27:59 +02:00 committed by Marek Kotewicz
parent 6552256981
commit 9e719f088f
7 changed files with 119 additions and 259 deletions

53
Cargo.lock generated
View File

@ -251,7 +251,7 @@ dependencies = [
"ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ethjson 0.1.0",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
"rlp 0.2.1",
"rlp_derive 0.1.0",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -487,7 +487,7 @@ version = "1.12.0"
dependencies = [
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
@ -541,7 +541,7 @@ dependencies = [
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
"journaldb 0.1.0",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
"kvdb 0.1.0",
"kvdb-memorydb 0.1.0",
"kvdb-rocksdb 0.1.0",
@ -633,7 +633,7 @@ dependencies = [
"hashdb 0.1.1",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
"kvdb 0.1.0",
"kvdb-memorydb 0.1.0",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
@ -685,7 +685,7 @@ dependencies = [
"futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
"linked-hash-map 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-reactor 0.1.0",
@ -730,7 +730,7 @@ dependencies = [
"ethkey 0.3.0",
"igd 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)",
@ -769,7 +769,7 @@ dependencies = [
"ethkey 0.3.0",
"fetch 0.1.0",
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
"patricia-trie 0.1.0",
@ -803,7 +803,7 @@ dependencies = [
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
"kvdb 0.1.0",
"kvdb-rocksdb 0.1.0",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -851,7 +851,7 @@ dependencies = [
"jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
"jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
"jsonrpc-tcp-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
@ -875,7 +875,7 @@ dependencies = [
"ethkey 0.3.0",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
"kvdb 0.1.0",
"kvdb-memorydb 0.1.0",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
@ -900,7 +900,7 @@ dependencies = [
"ethkey 0.3.0",
"evm 0.1.0",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
"rlp 0.2.1",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unexpected 0.1.0",
@ -1021,7 +1021,7 @@ dependencies = [
"bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"memory-cache 0.1.0",
@ -1345,7 +1345,7 @@ dependencies = [
"ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"hashdb 0.1.1",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
"kvdb 0.1.0",
"kvdb-memorydb 0.1.0",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1454,9 +1454,8 @@ dependencies = [
[[package]]
name = "keccak-hash"
version = "0.1.0"
version = "0.1.2"
dependencies = [
"cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
"ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1648,7 +1647,7 @@ dependencies = [
"ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"hashdb 0.1.1",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
"plain_hasher 0.1.0",
"rlp 0.2.1",
]
@ -1987,7 +1986,7 @@ dependencies = [
"ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)",
"journaldb 0.1.0",
"jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
"kvdb 0.1.0",
"kvdb-rocksdb 0.1.0",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2051,7 +2050,7 @@ dependencies = [
"itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
"jsonrpc-http-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
"linked-hash-map 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"mime_guess 2.0.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2115,7 +2114,7 @@ dependencies = [
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"mime_guess 2.0.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2208,7 +2207,7 @@ dependencies = [
"jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
"jsonrpc-pubsub 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
"jsonrpc-ws-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
"kvdb-memorydb 0.1.0",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"macros 0.1.0",
@ -2244,7 +2243,7 @@ dependencies = [
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
"jsonrpc-ws-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-rpc 1.12.0",
@ -2332,7 +2331,7 @@ dependencies = [
"ethcore-bytes 0.1.0",
"ethcore-sync 1.12.0",
"ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2440,7 +2439,7 @@ dependencies = [
"ethcore-logger 1.12.0",
"ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"hashdb 0.1.1",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"memorydb 0.1.1",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2736,7 +2735,7 @@ dependencies = [
"ethabi-contract 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi-derive 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
]
[[package]]
@ -3472,7 +3471,7 @@ version = "0.1.0"
dependencies = [
"ethcore-bytes 0.1.0",
"ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
"rlp 0.2.1",
]
@ -3482,7 +3481,7 @@ version = "0.1.0"
dependencies = [
"elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
"rlp 0.2.1",
"trie-standardmap 0.1.0",
]
@ -3630,7 +3629,7 @@ dependencies = [
"ethcore-bytes 0.1.0",
"ethereum-types 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ethjson 0.1.0",
"keccak-hash 0.1.0",
"keccak-hash 0.1.2",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"patricia-trie 0.1.0",
"rlp 0.2.1",

View File

@ -21,32 +21,36 @@ pub type H256 = [u8; 32];
pub mod keccak_512 {
use super::hash;
pub use self::hash::keccak_512 as unchecked;
pub use self::hash::keccak_512_unchecked as unchecked;
pub fn write(input: &[u8], output: &mut [u8]) {
unsafe { hash::keccak_512(output.as_mut_ptr(), output.len(), input.as_ptr(), input.len()) };
hash::keccak_512(input, output);
}
pub fn inplace(input: &mut [u8]) {
// This is safe since `sha3_*` uses an internal buffer and copies the result to the output. This
// This is safe since `keccak_*` uses an internal buffer and copies the result to the output. This
// means that we can reuse the input buffer for both input and output.
unsafe { hash::keccak_512(input.as_mut_ptr(), input.len(), input.as_ptr(), input.len()) };
unsafe {
hash::keccak_512_unchecked(input.as_mut_ptr(), input.len(), input.as_ptr(), input.len());
}
}
}
pub mod keccak_256 {
use super::hash;
pub use self::hash::keccak_256 as unchecked;
pub use self::hash::keccak_256_unchecked as unchecked;
#[allow(dead_code)]
pub fn write(input: &[u8], output: &mut [u8]) {
unsafe { hash::keccak_256(output.as_mut_ptr(), output.len(), input.as_ptr(), input.len()) };
hash::keccak_256(input, output);
}
pub fn inplace(input: &mut [u8]) {
// This is safe since `sha3_*` uses an internal buffer and copies the result to the output. This
// This is safe since `keccak_*` uses an internal buffer and copies the result to the output. This
// means that we can reuse the input buffer for both input and output.
unsafe { hash::keccak_256(input.as_mut_ptr(), input.len(), input.as_ptr(), input.len()) };
unsafe {
hash::keccak_256_unchecked(input.as_mut_ptr(), input.len(), input.as_ptr(), input.len());
}
}
}

View File

@ -1,18 +1,15 @@
[package]
description = "Rust bindings for tinykeccak C library"
homepage = "http://parity.io"
homepage = "https://github.com/paritytech/keccak-hash"
readme = "README.md"
license = "GPL-3.0"
name = "keccak-hash"
version = "0.1.0"
version = "0.1.2"
authors = ["Parity Technologies <admin@parity.io>"]
build = "build.rs"
[dependencies]
ethereum-types = "0.3"
tiny-keccak = "1.3"
[build-dependencies]
cc = "1.0"
tiny-keccak = "1.4.1"
[dev-dependencies]
tempdir = "0.3"

View File

@ -0,0 +1,36 @@
#![feature(test)]
extern crate test;
extern crate ethereum_types;
extern crate keccak_hash;
use keccak_hash::{keccak, write_keccak};
use test::Bencher;
#[bench]
fn bench_keccak_256_with_empty_input(b: &mut Bencher) {
let empty = [0u8;0];
b.bytes = empty.len() as u64;
b.iter(|| {
let _out = keccak(empty);
})
}
#[bench]
fn bench_keccak_256_with_typical_input(b: &mut Bencher) {
let data: Vec<u8> = From::from("some medum length string with important information");
b.bytes = data.len() as u64;
b.iter(|| {
let _out = keccak(&data);
})
}
#[bench]
fn bench_keccak_256_with_large_input(b: &mut Bencher) {
// 4096 chars
let data: Vec<u8> = From::from("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");
b.bytes = data.len() as u64;
b.iter(|| {
let _out = keccak(&data);
})
}

View File

@ -1,26 +0,0 @@
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
// build.rs
// Bring in a dependency on an externally maintained `cc` package which manages
// invoking the C compiler.
extern crate cc;
fn main() {
cc::Build::new().file("src/tinykeccak.c").compile("libtinykeccak.a");
}

View File

@ -18,7 +18,9 @@ extern crate ethereum_types;
extern crate tiny_keccak;
use std::io;
use std::slice;
use tiny_keccak::Keccak;
pub use ethereum_types::H256;
/// Get the KECCAK (i.e. Keccak) hash of the empty bytes string.
@ -30,12 +32,6 @@ pub const KECCAK_NULL_RLP: H256 = H256( [0x56, 0xe8, 0x1f, 0x17, 0x1b, 0xcc, 0x5
/// The KECCAK of the RLP encoding of empty list.
pub const KECCAK_EMPTY_LIST_RLP: H256 = H256( [0x1d, 0xcc, 0x4d, 0xe8, 0xde, 0xc7, 0x5d, 0x7a, 0xab, 0x85, 0xb5, 0x67, 0xb6, 0xcc, 0xd4, 0x1a, 0xd3, 0x12, 0x45, 0x1b, 0x94, 0x8a, 0x74, 0x13, 0xf0, 0xa1, 0x42, 0xfd, 0x40, 0xd4, 0x93, 0x47] );
extern {
/// Hashes input. Returns -1 if either out or input does not exist. Otherwise returns 0.
pub fn keccak_256(out: *mut u8, outlen: usize, input: *const u8, inputlen: usize) -> i32;
/// Hashes input. Returns -1 if either out or input does not exist. Otherwise returns 0.
pub fn keccak_512(out: *mut u8, outlen: usize, input: *const u8, inputlen: usize) -> i32;
}
pub fn keccak<T: AsRef<[u8]>>(s: T) -> H256 {
let mut result = [0u8; 32];
@ -43,15 +39,30 @@ pub fn keccak<T: AsRef<[u8]>>(s: T) -> H256 {
H256(result)
}
pub fn write_keccak<T: AsRef<[u8]>>(s: T, dest: &mut [u8]) {
let input = s.as_ref();
unsafe {
// we can safely ignore keccak_256 output, cause we know that both input
// and dest are properly allocated
keccak_256(dest.as_mut_ptr(), dest.len(), input.as_ptr(), input.len());
}
pub unsafe fn keccak_256_unchecked(out: *mut u8, outlen: usize, input: *const u8, inputlen: usize) {
// This is safe since `keccak_*` uses an internal buffer and copies the result to the output. This
// means that we can reuse the input buffer for both input and output.
Keccak::keccak256(
slice::from_raw_parts(input, inputlen),
slice::from_raw_parts_mut(out, outlen)
);
}
pub unsafe fn keccak_512_unchecked(out: *mut u8, outlen: usize, input: *const u8, inputlen: usize) {
// This is safe since `keccak_*` uses an internal buffer and copies the result to the output. This
// means that we can reuse the input buffer for both input and output.
Keccak::keccak512(
slice::from_raw_parts(input, inputlen),
slice::from_raw_parts_mut(out, outlen)
);
}
pub fn keccak_256(input: &[u8], mut output: &mut [u8]) { Keccak::keccak256(input, &mut output); }
pub fn keccak_512(input: &[u8], mut output: &mut [u8]) { Keccak::keccak512(input, &mut output); }
pub fn write_keccak<T: AsRef<[u8]>>(s: T, dest: &mut [u8]) { Keccak::keccak256(s.as_ref(), dest); }
pub fn keccak_pipe(r: &mut io::BufRead, w: &mut io::Write) -> Result<H256, io::Error> {
let mut output = [0u8; 32];
let mut input = [0u8; 1024];
@ -82,17 +93,33 @@ mod tests {
use std::fs;
use std::io::{Write, BufReader};
use self::tempdir::TempDir;
use super::{keccak, keccak_buffer, KECCAK_EMPTY};
use super::{keccak, write_keccak, keccak_buffer, KECCAK_EMPTY};
#[test]
fn keccak_empty() {
assert_eq!(keccak([0u8; 0]), KECCAK_EMPTY);
}
#[test]
fn keccak_as() {
assert_eq!(keccak([0x41u8; 32]), From::from("59cad5948673622c1d64e2322488bf01619f7ff45789741b15a9f782ce9290a8"));
}
#[test]
fn write_keccak_with_content() {
let data: Vec<u8> = From::from("hello world");
let expected = vec![
0x47, 0x17, 0x32, 0x85, 0xa8, 0xd7, 0x34, 0x1e,
0x5e, 0x97, 0x2f, 0xc6, 0x77, 0x28, 0x63, 0x84,
0xf8, 0x02, 0xf8, 0xef, 0x42, 0xa5, 0xec, 0x5f,
0x03, 0xbb, 0xfa, 0x25, 0x4c, 0xb0, 0x1f, 0xad
];
let mut dest = [0u8;32];
write_keccak(data, &mut dest);
assert_eq!(dest, expected.as_ref());
}
#[test]
fn should_keccak_a_file() {
// given

View File

@ -1,177 +0,0 @@
#include <stdint.h>
#include <string.h>
/** libkeccak-tiny
*
* A single-file implementation of SHA-3 and SHAKE.
*
* Implementor: David Leon Gil
* License: CC0, attribution kindly requested. Blame taken too,
* but not liability.
*/
#define decshake(bits) \
int shake##bits(uint8_t*, size_t, const uint8_t*, size_t);
#define deckeccak(bits) \
int keccak_##bits(uint8_t*, size_t, const uint8_t*, size_t);
decshake(128)
decshake(256)
deckeccak(224)
deckeccak(256)
deckeccak(384)
deckeccak(512)
/******** The Keccak-f[1600] permutation ********/
/*** Constants. ***/
static const uint8_t rho[24] = \
{ 1, 3, 6, 10, 15, 21,
28, 36, 45, 55, 2, 14,
27, 41, 56, 8, 25, 43,
62, 18, 39, 61, 20, 44};
static const uint8_t pi[24] = \
{10, 7, 11, 17, 18, 3,
5, 16, 8, 21, 24, 4,
15, 23, 19, 13, 12, 2,
20, 14, 22, 9, 6, 1};
static const uint64_t RC[24] = \
{1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL,
0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL,
0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL,
0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL,
0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL,
0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL};
/*** Helper macros to unroll the permutation. ***/
#define rol(x, s) (((x) << s) | ((x) >> (64 - s)))
#define REPEAT6(e) e e e e e e
#define REPEAT24(e) REPEAT6(e e e e)
#define REPEAT5(e) e e e e e
#define FOR5(v, s, e) \
v = 0; \
REPEAT5(e; v += s;)
/*** Keccak-f[1600] ***/
static inline void keccakf(void* state) {
uint64_t* a = (uint64_t*)state;
uint64_t b[5] = {0};
uint64_t t = 0;
uint8_t x, y;
int i;
for (i = 0; i < 24; i++) {
// Theta
FOR5(x, 1,
b[x] = 0;
FOR5(y, 5,
b[x] ^= a[x + y]; ))
FOR5(x, 1,
FOR5(y, 5,
a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); ))
// Rho and pi
t = a[1];
x = 0;
REPEAT24(b[0] = a[pi[x]];
a[pi[x]] = rol(t, rho[x]);
t = b[0];
x++; )
// Chi
FOR5(y,
5,
FOR5(x, 1,
b[x] = a[y + x];)
FOR5(x, 1,
a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); ))
// Iota
a[0] ^= RC[i];
}
}
/******** The FIPS202-defined functions. ********/
/*** Some helper macros. ***/
#define _(S) do { S } while (0)
#define FOR(i, ST, L, S) \
_({size_t i; for (i = 0; i < L; i += ST) { S; }})
#define mkapply_ds(NAME, S) \
static inline void NAME(uint8_t* dst, \
const uint8_t* src, \
size_t len) { \
FOR(i, 1, len, S); \
}
#define mkapply_sd(NAME, S) \
static inline void NAME(const uint8_t* src, \
uint8_t* dst, \
size_t len) { \
FOR(i, 1, len, S); \
}
mkapply_ds(xorin, dst[i] ^= src[i]) // xorin
mkapply_sd(setout, dst[i] = src[i]) // setout
#define P keccakf
#define Plen 200
// Fold P*F over the full blocks of an input.
#define foldP(I, L, F) \
while (L >= rate) { \
F(a, I, rate); \
P(a); \
I += rate; \
L -= rate; \
}
/** The sponge-based hash construction. **/
static inline int hash(uint8_t* out, size_t outlen,
const uint8_t* in, size_t inlen,
size_t rate, uint8_t delim) {
if ((out == NULL) || ((in == NULL) && inlen != 0) || (rate >= Plen)) {
return -1;
}
uint8_t a[Plen] = {0};
// Absorb input.
foldP(in, inlen, xorin);
// Xor in the DS and pad frame.
a[inlen] ^= delim;
a[rate - 1] ^= 0x80;
// Xor in the last block.
xorin(a, in, inlen);
// Apply P
P(a);
// Squeeze output.
foldP(out, outlen, setout);
setout(a, out, outlen);
memset(a, 0, 200);
return 0;
}
/*** Helper macros to define SHA3 and SHAKE instances. ***/
#define defshake(bits) \
int shake##bits(uint8_t* out, size_t outlen, \
const uint8_t* in, size_t inlen) { \
return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x1f); \
}
#define defkeccak(bits) \
int keccak_##bits(uint8_t* out, size_t outlen, \
const uint8_t* in, size_t inlen) { \
if (outlen > (bits/8)) { \
return -1; \
} \
return hash(out, outlen, in, inlen, 200 - (bits / 4), 0x01); \
}
/*** FIPS202 SHAKE VOFs ***/
defshake(128)
defshake(256)
/*** FIPS202 SHA3 FOFs ***/
defkeccak(224)
defkeccak(256)
defkeccak(384)
defkeccak(512)