diff options
| author | Mattias Andrée <maandree@kth.se> | 2017-10-14 01:01:14 +0200 | 
|---|---|---|
| committer | Mattias Andrée <maandree@kth.se> | 2017-10-14 01:01:14 +0200 | 
| commit | 3e1864aa14a33a3c917537a241f6a032cfcacf78 (patch) | |
| tree | 25297b1363fa88c9f45b5102afa5e95d08e986c1 /src | |
| parent | Change style and license (diff) | |
| download | libkeccak-3e1864aa14a33a3c917537a241f6a032cfcacf78.tar.gz libkeccak-3e1864aa14a33a3c917537a241f6a032cfcacf78.tar.bz2 libkeccak-3e1864aa14a33a3c917537a241f6a032cfcacf78.tar.xz | |
General improvements
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'src')
| -rwxr-xr-x | src/benchmark-flags | 116 | ||||
| -rw-r--r-- | src/benchmark.c | 139 | ||||
| -rw-r--r-- | src/libkeccak.h | 13 | ||||
| -rw-r--r-- | src/libkeccak/digest.c | 588 | ||||
| -rw-r--r-- | src/libkeccak/digest.h | 100 | ||||
| -rw-r--r-- | src/libkeccak/files.c | 57 | ||||
| -rw-r--r-- | src/libkeccak/files.h | 115 | ||||
| -rw-r--r-- | src/libkeccak/generalised-spec.c | 111 | ||||
| -rw-r--r-- | src/libkeccak/generalised-spec.h | 142 | ||||
| -rw-r--r-- | src/libkeccak/hex.c | 65 | ||||
| -rw-r--r-- | src/libkeccak/hex.h | 44 | ||||
| -rw-r--r-- | src/libkeccak/internal.h | 26 | ||||
| -rw-r--r-- | src/libkeccak/mac/hmac.c | 418 | ||||
| -rw-r--r-- | src/libkeccak/mac/hmac.h | 393 | ||||
| -rw-r--r-- | src/libkeccak/spec.h | 177 | ||||
| -rw-r--r-- | src/libkeccak/state.c | 175 | ||||
| -rw-r--r-- | src/libkeccak/state.h | 295 | ||||
| -rw-r--r-- | src/test.c | 662 | 
18 files changed, 0 insertions, 3636 deletions
| diff --git a/src/benchmark-flags b/src/benchmark-flags deleted file mode 100755 index 1168ec0..0000000 --- a/src/benchmark-flags +++ /dev/null @@ -1,116 +0,0 @@ -#!/bin/sh -# See LICENSE file for copyright and license details. - -set -e - -export LD_LIBRARY_PATH=bin -if test "${TRIES}" = ""; then -	TRIES=10 -fi - -# List all flags that affect the object files -list_test_flags() { -	cat <<EOF --fdata-sections -fcrossjumping -fexpensive-optimizations -ffunction-sections --fkeep-inline-functions -fomit-frame-pointer -freorder-blocks-and-partition --ftree-ter -falign-functions=0 -fmerge-all-constants -fmerge-constants -EOF -} - -cppflags="-DIGNORE_BEHEXING" -base_flags='-march=native -O0' -test_flags=" $(echo $(list_test_flags)) " - -pass=1 -exec 4>.benchmark.so.far - -while true; do -	exec 3>.benchmarks - -	for _try in $(seq ${TRIES}); do -		for test_flag in "" ${test_flags}; do -			flags="${test_flag} ${base_flags}" -			make -B all COPTIMISE="${flags}" CPPFLAGS="${cppflags} $*" -			make check -			if test "${test_flag}" = ""; then -				test_flag=zzz -			fi -			echo "$(bin/benchmark || echo error) ${test_flag}" >&3 -		done -	done - -	exec 3<&- - -	! grep ^error .benchmarks >/dev/null 2>/dev/null - -	good_flag="$(median < .benchmarks | sort -n | cut -d ' ' -f 2 | sed 1q)" -	if test "${good_flag}" = zzz || test $pass = 2; then -		if test $pass = 1; then -			pass=2 -			base_flags="$(echo "${base_flags}" | sed -e 's/ -O0//')" -			test_flags="-O0 -O1 -O2 -O3 -Ofast -Os" -		else -			if ! test "${good_flag}" = zzz; then -				base_flags="${base_flags} ${good_flag}" -				echo "${good_flag}" >&4 -			fi -			echo -			echo -			echo "Good flags:" -			echo "${base_flags}" -			exec 4<&- -			exit 0 -		fi -	else -		echo "${good_flag}" >&4 -		base_flags="${base_flags} ${good_flag}" -		test_flags="$(echo "${test_flags}" | sed -e "s/ ${good_flag} / /")" -	fi -done - -#    None of these GCC flags affect the object files. -# -faggressive-loop-optimizations -fauto-inc-dec -fbranch-target-load-optimize -# -fbranch-target-load-optimize2 -fbtr-bb-exclusive -fcaller-saves -fcheck-data-deps -# -fcombine-stack-adjustments -fconserve-stack -fcompare-elim -fcprop-registers -# -fcse-follow-jumps -fcse-skip-blocks -fcx-fortran-rules -fcx-limited-range -fdce -# -fdelete-null-pointer-checks -fdevirtualize -fdevirtualize-speculatively -fdse -# -fearly-inlining -fipa-sra  -ffat-lto-objects -fbranch-probabilities -# -fassociative-math -fforward-propagate -ffunction-sections -fforward-propagate -# -ffast-math -ffinite-math-only -ffloat-store -fgcse -fgcse-after-reload -fgcse-las -# -fgcse-lm -fgraphite-identity -fgcse-sm -fhoist-adjacent-loads -fif-conversion -# -fif-conversion2 -findirect-inlining -finline-functions -finline-functions-called-once -# -finline-small-functions -fipa-cp -fipa-cp-clone -fipa-pta -fipa-profile -# -fipa-pure-const -fipa-reference -fira-hoist-pressure -fira-loop-pressure -# -fno-ira-share-save-slots -fno-ira-share-spill-slots -fisolate-erroneous-paths-dereference -# -fisolate-erroneous-paths-attribute -fivopts -fkeep-static-consts -flive-range-shrinkage -# -floop-block -floop-interchange -floop-strip-mine -floop-nest-optimize -# -floop-parallelize-all -fmodulo-sched -fmodulo-sched-allow-regmoves -fmove-loop-invariants -# -fno-branch-count-reg -fno-defer-pop -fno-function-cse -fno-guess-branch-probability -# -fno-defer-pop -fno-function-cse -fno-guess-branch-probability -fno-inline -fno-math-errno -# -fno-peephole -fno-peephole2 -fno-sched-interblock -fno-sched-spec -fno-signed-zeros -# -fno-toplevel-reorder -fno-trapping-math -fno-zero-initialized-in-bss -# -foptimize-sibling-calls -fpartial-inlining -fpeel-loops -fpredictive-commoning -# -fprefetch-loop-arrays -fprofile-report -fprofile-use -fprofile-values -# -fprofile-reorder-functions -freciprocal-math -free -frename-registers -freorder-blocks -# -frerun-cse-after-loop -freschedule-modulo-scheduled-loops -frounding-math -# -fsched2-use-superblocks -fsched-pressure -fsched-spec-load -fsched-spec-load-dangerous -# -fsched-group-heuristic -fsched-critical-path-heuristic -fsched-spec-insn-heuristic -# -fsched-rank-heuristic -fsched-last-insn-heuristic -fsched-dep-count-heuristic -# -fselective-scheduling -fselective-scheduling2 -fsel-sched-pipelining -# -fsel-sched-pipelining-outer-loops -fshrink-wrap -fsignaling-nans -# -fsingle-precision-constant -fstrict-overflow -fthread-jumps -ftracer -ftree-bit-ccp -# -ftree-builtin-call-dce -ftree-ccp -ftree-ch -ftree-copyrename -ftree-dce -# -ftree-dominator-opts -ftree-dse -ftree-forwprop -ftree-fre -ftree-loop-if-convert -# -ftree-loop-if-convert-stores -ftree-loop-im -ftree-phiprop -ftree-loop-distribution -# -ftree-loop-distribute-patterns -ftree-loop-ivcanon -ftree-loop-linear -# -ftree-loop-optimize -ftree-loop-vectorize -ftree-pre -ftree-partial-pre -ftree-pta -# -ftree-reassoc -ftree-sink -ftree-slsr -ftree-sra -ftree-vectorize -ftree-vrp -# -funit-at-a-time -funroll-all-loops -funroll-loops -funsafe-loop-optimizations -# -funsafe-math-optimizations -funswitch-loops -fvariable-expansion-in-unroller -# -fvect-cost-model -fvpt -fweb -fprofile-correction -freorder-functions -# -fschedule-insns -fschedule-insns2 -fsplit-ivs-in-unroller -fsplit-wide-types -# -fstrict-aliasing -ftree-coalesce-vars -ftree-copy-prop -ftree-switch-conversion -# -ftree-switch-conversion -ftree-tail-merge -ftree-coalesce-inlined-vars -# -falign-jumps=0 -falign-labels=0 -falign-loops=0 -ftree-parallelize-loops=10 -# -fsched-stalled-insns-dep=0 -fsched-stalled-insns=0 - diff --git a/src/benchmark.c b/src/benchmark.c deleted file mode 100644 index 1ce7da9..0000000 --- a/src/benchmark.c +++ /dev/null @@ -1,139 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <libkeccak.h> - -#include <fcntl.h> -#include <stdio.h> -#include <string.h> -#include <time.h> -#include <unistd.h> - - -#ifndef MESSAGE_FILE -# define MESSAGE_FILE     "LICENSE" -#endif -#ifndef MESSAGE_LEN -# define MESSAGE_LEN      34520 -#endif - - -#ifndef BITRATE -# define BITRATE           1024 -#endif -#ifndef CAPACITY -# define CAPACITY           576 -#endif -#ifndef OUTPUT -# define OUTPUT             512 -#endif - -#ifndef UPDATE_RUNS -# define UPDATE_RUNS        100 -#endif -#ifndef FAST_SQUEEZE_RUNS -# define FAST_SQUEEZE_RUNS  100 -#endif -#ifndef SLOW_SQUEEZE_RUNS -# define SLOW_SQUEEZE_RUNS  100 -#endif -#ifndef RERUNS -# define RERUNS              50 -#endif - - - -/** - * Benchmark, will print the number of nanoseconds - * spent with hashing algorithms and representation - * conversion from binary to hexadecimal. The latter - * can be compiled out by compiling with -DIGNORE_BEHEXING. - *  - * @return  Zero on success, 1 on error - */ -int -main(void) -{ -	char message[MESSAGE_LEN]; -	libkeccak_spec_t spec; -	libkeccak_state_t state; -	char hashsum[OUTPUT / 8]; -#ifndef IGNORE_BEHEXING -	char hexsum[OUTPUT / 8 * 2 + 1]; -#endif -	struct timespec start, end; -	long i, r; - -	/* Fill message with content from the file. */ -	int fd; -	ssize_t got; -	size_t ptr; -	if (fd = open(MESSAGE_FILE, O_RDONLY), fd < 0) -		return perror("open"), 1; -	for (ptr = 0; ptr < MESSAGE_LEN; ptr += (size_t)got) -		if (got = read(fd, message, MESSAGE_LEN - ptr), got <= 0) -			return perror("read"), close(fd), 1; -	close(fd); - -	/* Initialise state. */ -	spec.bitrate = BITRATE; -	spec.capacity = CAPACITY; -	spec.output = OUTPUT; -	if (libkeccak_state_initialise(&state, &spec)) -		return perror("libkeccak_state_initialise"), 1; - -	/* Get start-time. */ -	if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start) < 0) -		return perror("clock_gettime"), 1; - -	/* Run benchmarking loop. */ -	for (r = 0; r < RERUNS; r++) { -		/* Updates. */ -#if UPDATE_RUNS > 0 -		for (i = 0; i < UPDATE_RUNS; i++) -			if (libkeccak_fast_update(&state, message, MESSAGE_LEN) < 0) -				return perror("libkeccak_update"), 1; -#endif - -		/* Digest. */ -		if (libkeccak_fast_digest(&state, NULL, 0, 0, NULL, hashsum) < 0) -			return perror("libkeccak_digest"), 1; -#ifndef IGNORE_BEHEXING -		libkeccak_behex_lower(hexsum, hashsum, OUTPUT / 8); -#endif - -		/* Fast squeezes. */ -#if FAST_SQUEEZE_RUNS > 0 -		libkeccak_fast_squeeze(&state, FAST_SQUEEZE_RUNS); -#endif - -		/* Slow squeezes. */ -#if SLOW_SQUEEZE_RUNS > 0 -		for (i = 0; i < SLOW_SQUEEZE_RUNS; i++) { -			libkeccak_squeeze(&state, hashsum); -# ifndef IGNORE_BEHEXING -			libkeccak_behex_lower(hexsum, hashsum, OUTPUT / 8); -# endif -		} -#endif -	} - -	/* Get end-time. */ -	if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end) < 0) -		return perror("clock_gettime"), -1; - -	/* Print execution-time. */ -	end.tv_sec -= start.tv_sec; -	end.tv_nsec -= start.tv_nsec; -	if (end.tv_nsec < 0) { -		end.tv_sec--; -		end.tv_nsec += 1000000000L; -	} -	printf("%03li%09li\n", (long)(end.tv_sec), end.tv_nsec); - -	/* Release resources and exit. */ -	libkeccak_state_fast_destroy(&state); -	return 0; - -#if (UPDATE_RUNS == 0) && (SLOW_SQUEEZE_RUNS == 0) -	(void) i; -#endif -} diff --git a/src/libkeccak.h b/src/libkeccak.h deleted file mode 100644 index 7c71801..0000000 --- a/src/libkeccak.h +++ /dev/null @@ -1,13 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#ifndef LIBKECCAK_H -#define LIBKECCAK_H 1 - -#include "libkeccak/spec.h" -#include "libkeccak/generalised-spec.h" -#include "libkeccak/state.h" -#include "libkeccak/digest.h" -#include "libkeccak/hex.h" -#include "libkeccak/files.h" -#include "libkeccak/mac/hmac.h" - -#endif diff --git a/src/libkeccak/digest.c b/src/libkeccak/digest.c deleted file mode 100644 index 5f7a32c..0000000 --- a/src/libkeccak/digest.c +++ /dev/null @@ -1,588 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "digest.h" - -#include "state.h" - - - -/** - * X-macro-enabled listing of all intergers in [0, 4] - */ -#define LIST_5 X(0) X(1) X(2) X(3) X(4) - -/** - * X-macro-enabled listing of all intergers in [0, 7] - */ -#define LIST_8 LIST_5 X(5) X(6) X(7) - -/** - * X-macro-enabled listing of all intergers in [0, 23] - */ -#define LIST_24 LIST_8 X(8) X(9) X(10) X(11) X(12) X(13) X(14) X(15)\ -                X(16) X(17) X(18) X(19) X(20) X(21) X(22) X(23) - -/** - * X-macro-enabled listing of all intergers in [0, 24] - */ -#define LIST_25 LIST_24 X(24)  - - - -#define X(N) (N % 5) * 5 + N / 5, -/** - * The order the lanes should be read when absorbing or squeezing, - * it transposes the lanes in the sponge - */ -static const long LANE_TRANSPOSE_MAP[] = { LIST_25 }; -#undef X - - - -/** - * Keccak-f round constants - */ -static const uint_fast64_t RC[] = { -	0x0000000000000001ULL, 0x0000000000008082ULL, 0x800000000000808AULL, 0x8000000080008000ULL, -	0x000000000000808BULL, 0x0000000080000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL, -	0x000000000000008AULL, 0x0000000000000088ULL, 0x0000000080008009ULL, 0x000000008000000AULL, -	0x000000008000808BULL, 0x800000000000008BULL, 0x8000000000008089ULL, 0x8000000000008003ULL, -	0x8000000000008002ULL, 0x8000000000000080ULL, 0x000000000000800AULL, 0x800000008000000AULL, -	0x8000000080008081ULL, 0x8000000000008080ULL, 0x0000000080000001ULL, 0x8000000080008008ULL -}; - - -/** - * Rotate a word - *  - * @param   x:int_fast64_t     The value to rotate - * @param   n:long             Rotation steps, may be zero mod `w` - * @param   w:long             `state->w` - * @param   wmod:int_fast64_t  `state->wmod` - * @return  :int_fast64_t      The value rotated - */ -#define rotate(x, n, w, wmod) ((((x) >> ((w) - ((n) % (w)))) | ((x) << ((n) % (w)))) & (wmod)) - - -/** - * Rotate a 64-bit word - *  - * @param   x:int_fast64_t  The value to rotate - * @param   n:long          Rotation steps, may not be zero - * @return   :int_fast64_t  The value rotated - */ -#define rotate64(x, n) ((int_fast64_t)(((uint64_t)(x) >> (64L - (n))) | ((uint64_t)(x) << (n)))) - - -/** - * Perform one round of computation - *  - * @param  state  The hashing state - * @param  rc     The round contant for this round - */ -static __attribute__((nonnull, nothrow, hot)) void -libkeccak_f_round(register libkeccak_state_t *restrict state, register int_fast64_t rc) -{ -	int_fast64_t *restrict A = state->S; -	int_fast64_t B[25]; -	int_fast64_t C[5]; -	int_fast64_t da, db, dc, dd, de; -	int_fast64_t wmod = state->wmod; -	long w = state->w; - -	/* θ step (step 1 of 3). */ -#define X(N) C[N] = A[N * 5] ^ A[N * 5 + 1] ^ A[N * 5 + 2] ^ A[N * 5 + 3] ^ A[N * 5 + 4]; -	LIST_5; -#undef X - -	/* θ step (step 2 of 3). */ -	da = C[4] ^ rotate(C[1], 1, w, wmod); -	dd = C[2] ^ rotate(C[4], 1, w, wmod); -	db = C[0] ^ rotate(C[2], 1, w, wmod); -	de = C[3] ^ rotate(C[0], 1, w, wmod); -	dc = C[1] ^ rotate(C[3], 1, w, wmod); - -	/* ρ and π steps, with last two part of θ. */ -#define X(bi, ai, dv, r) B[bi] = rotate(A[ai] ^ dv, r, w, wmod) -	B[0] = A[0] ^ da;   X( 1, 15, dd, 28);  X( 2,  5, db,  1);  X( 3, 20, de, 27);  X( 4, 10, dc, 62); -	X( 5,  6, db, 44);  X( 6, 21, de, 20);  X( 7, 11, dc,  6);  X( 8,  1, da, 36);  X( 9, 16, dd, 55); -	X(10, 12, dc, 43);  X(11,  2, da,  3);  X(12, 17, dd, 25);  X(13,  7, db, 10);  X(14, 22, de, 39); -	X(15, 18, dd, 21);  X(16,  8, db, 45);  X(17, 23, de,  8);  X(18, 13, dc, 15);  X(19,  3, da, 41); -	X(20, 24, de, 14);  X(21, 14, dc, 61);  X(22,  4, da, 18);  X(23, 19, dd, 56);  X(24,  9, db,  2); -#undef X - -	/* ξ step. */ -#define X(N) A[N] = B[N] ^ ((~(B[(N + 5) % 25])) & B[(N + 10) % 25]); -	LIST_25; -#undef X - -	/* ι step. */ -	A[0] ^= rc; -} - - -/** - * 64-bit word version of `libkeccak_f_round` - *  - * @param  state  The hashing state - * @param  rc     The round contant for this round - */ -static __attribute__((nonnull, nothrow, hot)) void -libkeccak_f_round64(register libkeccak_state_t *restrict state, register int_fast64_t rc) -{ -	int_fast64_t *restrict A = state->S; -	int_fast64_t B[25]; -	int_fast64_t C[5]; -	int_fast64_t da, db, dc, dd, de; - -	/* θ step (step 1 of 3). */ -#define X(N) C[N] = A[N * 5] ^ A[N * 5 + 1] ^ A[N * 5 + 2] ^ A[N * 5 + 3] ^ A[N * 5 + 4]; -	LIST_5; -#undef X - -	/* θ step (step 2 of 3). */ -	da = C[4] ^ rotate64(C[1], 1); -	dd = C[2] ^ rotate64(C[4], 1); -	db = C[0] ^ rotate64(C[2], 1); -	de = C[3] ^ rotate64(C[0], 1); -	dc = C[1] ^ rotate64(C[3], 1); - -	/* ρ and π steps, with last two part of θ. */ -#define X(bi, ai, dv, r) B[bi] = rotate64(A[ai] ^ dv, r) -	B[0] = A[0] ^ da;   X( 1, 15, dd, 28);  X( 2,  5, db,  1);  X( 3, 20, de, 27);  X( 4, 10, dc, 62); -	X( 5,  6, db, 44);  X( 6, 21, de, 20);  X( 7, 11, dc,  6);  X( 8,  1, da, 36);  X( 9, 16, dd, 55); -	X(10, 12, dc, 43);  X(11,  2, da,  3);  X(12, 17, dd, 25);  X(13,  7, db, 10);  X(14, 22, de, 39); -	X(15, 18, dd, 21);  X(16,  8, db, 45);  X(17, 23, de,  8);  X(18, 13, dc, 15);  X(19,  3, da, 41); -	X(20, 24, de, 14);  X(21, 14, dc, 61);  X(22,  4, da, 18);  X(23, 19, dd, 56);  X(24,  9, db,  2); -#undef X - -	/* ξ step. */ -#define X(N) A[N] = B[N] ^ ((~(B[(N + 5) % 25])) & B[(N + 10) % 25]); -	LIST_25; -#undef X - -	/* ι step. */ -	A[0] ^= rc; -} - - -/** - * Convert a chunk of bytes to a lane - *  - * @param  state  The hashing state - */ -static inline __attribute__((nonnull, nothrow, gnu_inline)) void -libkeccak_f(register libkeccak_state_t *restrict state) -{ -	register long i = 0; -	register long nr = state->nr; -	register long wmod = state->wmod; -	if (nr == 24) { -		for (; i < nr; i++) -			libkeccak_f_round64(state, (int_fast64_t)(RC[i])); -	} else { -		for (; i < nr; i++) -			libkeccak_f_round(state, (int_fast64_t)(RC[i] & wmod)); -	} -} - - -/** - * Convert a chunk of bytes to a lane - *  - * @param   message  The message - * @param   msglen   The length of the message - * @param   rr       Bitrate in bytes - * @param   ww       Word size in bytes - * @param   off      The offset in the message - * @return           The lane - */ -static inline __attribute__((nonnull, nothrow, pure, warn_unused_result, gnu_inline)) int_fast64_t -libkeccak_to_lane(register const char *restrict message, register size_t msglen, -                  register long rr, register long ww, size_t off) -{ -	register long n = (long)((msglen < (size_t)rr ? msglen : (size_t)rr) - off); -	int_fast64_t rc = 0; -	message += off; -	while (ww--) { -		rc <<= 8; -		rc |= __builtin_expect(ww < n, 1) ? (int_fast64_t)(unsigned char)(message[ww]) : 0L; -	} -	return rc; -} - - -/** - * 64-bit lane version of `libkeccak_to_lane` - *  - * @param   message  The message - * @param   msglen   The length of the message - * @param   rr       Bitrate in bytes - * @param   off      The offset in the message - * @return           The lane - */ -static inline __attribute__((nonnull, nothrow, pure, hot, warn_unused_result, gnu_inline)) int_fast64_t -libkeccak_to_lane64(register const char* restrict message, register size_t msglen, -                    register long rr, size_t off) -{ -	register long n = (long)((msglen < (size_t)rr ? msglen : (size_t)rr) - off); -	int_fast64_t rc = 0; -	message += off; -#define X(N) if (__builtin_expect(N < n, 1)) rc |= (int_fast64_t)(unsigned char)(message[N]) << (N * 8);\ -             else  return rc; -	LIST_8; -#undef X -	return rc; -} - - -/** - * pad 10*1 - *  - * @param  state  The hashing state, `state->M` and `state->mptr` will be updated, - *                `state->M` should have `state->r / 8` bytes left over at the end - * @param  bits   The number of bits in the end of the message that does not make a whole byte - */ -static inline __attribute__((nonnull, nothrow, gnu_inline)) void -libkeccak_pad10star1(register libkeccak_state_t *restrict state, register size_t bits) -{ -	register size_t r = (size_t)(state->r); -	register size_t nrf = state->mptr - !!bits; -	register size_t len = (nrf << 3) | bits; -	register size_t ll = len % r; -	register char b = (char)(bits ? (state->M[nrf] | (1 << bits)) : 1); - -	if (r - 8 <= ll && ll <= r - 2) { -		state->M[nrf] = (char)(b ^ 0x80); -		state->mptr = nrf + 1; -	} else { -		len = ++nrf << 3; -		len = (len - (len % r) + (r - 8)) >> 3; -		state->mptr = len + 1; - -		state->M[nrf - 1] = b; -		__builtin_memset(state->M + nrf, 0, (len - nrf) * sizeof(char)); -		state->M[len] = (char)0x80; -	} -} - - -/** - * Perform the absorption phase - *  - * @param  state  The hashing state - * @param  len    The number of bytes from `state->M` to absorb - */ -static __attribute__((nonnull, nothrow)) void -libkeccak_absorption_phase(register libkeccak_state_t *restrict state, register size_t len) -{ -	register long rr = state->r >> 3; -	register long ww = state->w >> 3; -	register long n = (long)len / rr; -	register const char* restrict message = state->M; -	if (__builtin_expect(ww >= 8, 1)) { /* ww > 8 is impossible, it is just for optimisation possibilities. */ -		while (n--) { -#define X(N) state->S[N] ^= libkeccak_to_lane64(message, len, rr, (size_t)(LANE_TRANSPOSE_MAP[N] * 8)); -			LIST_25; -#undef X -			libkeccak_f(state); -			message += (size_t)rr; -			len -= (size_t)rr; -		} -	} else { -		while (n--) { -#define X(N) state->S[N] ^= libkeccak_to_lane(message, len, rr, ww, (size_t)(LANE_TRANSPOSE_MAP[N] * ww)); -			LIST_25; -#undef X -			libkeccak_f(state); -			message += (size_t)rr; -			len -= (size_t)rr; -		} -	} -} - - -/** - * Perform the squeezing phase - *  - * @param  state    The hashing state - * @param  rr       The bitrate in bytes - * @param  nn       The output size in bytes, rounded up to whole bytes - * @param  ww       The word size in bytes - * @param  hashsum  Output parameter for the hashsum - */ -static __attribute__((nonnull, nothrow, hot)) void -libkeccak_squeezing_phase(register libkeccak_state_t *restrict state, long rr, -                          long nn, long ww, register char *restrict hashsum) -{ -	register int_fast64_t v; -	register long ni = rr / ww; -	auto long olen = state->n; -	auto long i, j = 0; -	register long k; -	while (olen > 0) { -		for (i = 0; i < ni && j < nn; i++) { -			v = state->S[LANE_TRANSPOSE_MAP[i]]; -			for (k = 0; k++ < ww && j++ < nn; v >>= 8) -				*hashsum++ = (char)v; -		} -		if (olen -= state->r, olen > 0) -			libkeccak_f(state); -	} -	if (state->n & 7) -		hashsum[-1] &= (char)((1 << (state->n & 7)) - 1); -} - - -/** - * Absorb more of the message to the Keccak sponge - * without wiping sensitive data when possible - *  - * @param   state   The hashing state - * @param   msg     The partial message - * @param   msglen  The length of the partial message - * @return          Zero on success, -1 on error - */ -int -libkeccak_fast_update(libkeccak_state_t *restrict state, const char *restrict msg, size_t msglen) -{ -	size_t len; -	auto char *restrict new; - -	if (__builtin_expect(state->mptr + msglen > state->mlen, 0)) { -		state->mlen += msglen; -		new = realloc(state->M, state->mlen * sizeof(char)); -		if (!new) -			return state->mlen -= msglen, -1; -		state->M = new; -	} - -	__builtin_memcpy(state->M + state->mptr, msg, msglen * sizeof(char)); -	state->mptr += msglen; -	len = state->mptr; -	len -= state->mptr % (size_t)((state->r * state->b) >> 3); -	state->mptr -= len; - -	libkeccak_absorption_phase(state, len); -	__builtin_memmove(state->M, state->M + len, state->mptr * sizeof(char)); - -	return 0; -} - - -/** - * Absorb more of the message to the Keccak sponge - * and wipe sensitive data when possible - *  - * @param   state   The hashing state - * @param   msg     The partial message - * @param   msglen  The length of the partial message - * @return          Zero on success, -1 on error - */ -int -libkeccak_update(libkeccak_state_t *restrict state, const char *restrict msg, size_t msglen) -{ -	size_t len; -	auto char *restrict new; - -	if (__builtin_expect(state->mptr + msglen > state->mlen, 0)) { -		state->mlen += msglen; -		new = malloc(state->mlen * sizeof(char)); -		if (new == NULL) -			return state->mlen -= msglen, -1; -		libkeccak_state_wipe_message(state); -		free(state->M); -		state->M = new; -	} - -	__builtin_memcpy(state->M + state->mptr, msg, msglen * sizeof(char)); -	state->mptr += msglen; -	len = state->mptr; -	len -= state->mptr % (size_t)((state->r * state->b) >> 3); -	state->mptr -= len; - -	libkeccak_absorption_phase(state, len); -	__builtin_memmove(state->M, state->M + len, state->mptr * sizeof(char)); - -	return 0; -} - - -/** - * Absorb the last part of the message and squeeze the Keccak sponge - * without wiping sensitive data when possible - *  - * @param   state    The hashing state - * @param   msg      The rest of the message, may be `NULL` - * @param   msglen   The length of the partial message - * @param   bits     The number of bits at the end of the message not covered by `msglen` - * @param   suffix   The suffix concatenate to the message, only '1':s and '0':s, and NUL-termination - * @param   hashsum  Output parameter for the hashsum, may be `NULL` - * @return           Zero on success, -1 on error - */ -int -libkeccak_fast_digest(libkeccak_state_t *restrict state, const char *restrict msg, size_t msglen, -                      size_t bits, const char *restrict suffix, char *restrict hashsum) -{ -	auto char *restrict new; -	register long rr = state->r >> 3; -	auto size_t suffix_len = suffix ? __builtin_strlen(suffix) : 0; -	register size_t ext; -	register long i; - -	if (msg == NULL) -		msglen = bits = 0; -	else -		msglen += bits >> 3, bits &= 7; - -	ext = msglen + ((bits + suffix_len + 7) >> 3) + (size_t)rr; -	if (__builtin_expect(state->mptr + ext > state->mlen, 0)) { -		state->mlen += ext; -		new = realloc(state->M, state->mlen * sizeof(char)); -		if (!new) -			return state->mlen -= ext, -1; -		state->M = new; -	} - -	if (msglen) -		__builtin_memcpy(state->M + state->mptr, msg, msglen * sizeof(char)); -	state->mptr += msglen; - -	if (bits) -		state->M[state->mptr] = msg[msglen] & (char)((1 << bits) - 1); -	if (__builtin_expect(!!suffix_len, 1)) { -		if (bits == 0) -			state->M[state->mptr] = 0; -		while (suffix_len--) { -			state->M[state->mptr] |= (char)((*suffix++ & 1) << bits++); -			if (bits == 8) -				bits = 0, state->M[++(state->mptr)] = 0; -		} -	} -	if (bits) -		state->mptr++; - -	libkeccak_pad10star1(state, bits); -	libkeccak_absorption_phase(state, state->mptr); - -	if (hashsum) { -		libkeccak_squeezing_phase(state, rr, (state->n + 7) >> 3, state->w >> 3, hashsum); -	} else { -		for (i = (state->n - 1) / state->r; i--;) -			libkeccak_f(state); -	} - -	return 0; -} - - -/** - * Absorb the last part of the message and squeeze the Keccak sponge - * and wipe sensitive data when possible - *  - * @param   state    The hashing state - * @param   msg      The rest of the message, may be `NULL` - * @param   msglen   The length of the partial message - * @param   bits     The number of bits at the end of the message not covered by `msglen` - * @param   suffix   The suffix concatenate to the message, only '1':s and '0':s, and NUL-termination - * @param   hashsum  Output parameter for the hashsum, may be `NULL` - * @return           Zero on success, -1 on error - */ -int -libkeccak_digest(libkeccak_state_t *restrict state, const char *restrict msg, size_t msglen, -                 size_t bits, const char *restrict suffix, char *restrict hashsum) -{ -	auto char *restrict new; -	register long rr = state->r >> 3; -	auto size_t suffix_len = suffix ? __builtin_strlen(suffix) : 0; -	register size_t ext; -	register long i; - -	if (msg == NULL) -		msglen = bits = 0; -	else -		msglen += bits >> 3, bits &= 7; - -	ext = msglen + ((bits + suffix_len + 7) >> 3) + (size_t)rr; -	if (__builtin_expect(state->mptr + ext > state->mlen, 0)) { -		state->mlen += ext; -		new = malloc(state->mlen * sizeof(char)); -		if (!new) -			return state->mlen -= ext, -1; -		libkeccak_state_wipe_message(state); -		free(state->M); -		state->M = new; -	} - -	if (msglen) -		__builtin_memcpy(state->M + state->mptr, msg, msglen * sizeof(char)); -	state->mptr += msglen; - -	if (bits) -		state->M[state->mptr] = msg[msglen] & (char)((1 << bits) - 1); -	if (__builtin_expect(!!suffix_len, 1)) { -		if (bits == 0) -			state->M[state->mptr] = 0; -		while (suffix_len--) { -			state->M[state->mptr] |= (char)((*suffix++ & 1) << bits++); -			if (bits == 8) -				bits = 0, state->M[++(state->mptr)] = 0; -		} -	} -	if (bits) -		state->mptr++; - -	libkeccak_pad10star1(state, bits); -	libkeccak_absorption_phase(state, state->mptr); - -	if (hashsum) { -		libkeccak_squeezing_phase(state, rr, (state->n + 7) >> 3, state->w >> 3, hashsum); -	} else { -		for (i = (state->n - 1) / state->r; i--;) -			libkeccak_f(state); -	} - -	return 0; -} - - -/** - * Force some rounds of Keccak-f - *  - * @param  state  The hashing state - * @param  times  The number of rounds - */ -void -libkeccak_simple_squeeze(register libkeccak_state_t *restrict state, register long times) -{ -	while (times--) -		libkeccak_f(state); -} - - -/** - * Squeeze as much as is needed to get a digest a number of times - *  - * @param  state  The hashing state - * @param  times  The number of digests - */ -void -libkeccak_fast_squeeze(register libkeccak_state_t *restrict state, register long times) -{ -	times *= (state->n - 1) / state->r + 1; -	while (times--) -		libkeccak_f(state); -} - - -/** - * Squeeze out another digest - *  - * @param  state    The hashing state - * @param  hashsum  Output parameter for the hashsum - */ -void -libkeccak_squeeze(register libkeccak_state_t *restrict state, register char* restrict hashsum) -{ -	libkeccak_f(state); -	libkeccak_squeezing_phase(state, state->r >> 3, (state->n + 7) >> 3, state->w >> 3, hashsum); -} diff --git a/src/libkeccak/digest.h b/src/libkeccak/digest.h deleted file mode 100644 index 832f0c0..0000000 --- a/src/libkeccak/digest.h +++ /dev/null @@ -1,100 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#ifndef LIBKECCAK_DIGEST_H -#define LIBKECCAK_DIGEST_H 1 - -#include "state.h" -#include "internal.h" - - -/** - * Absorb more of the message to the Keccak sponge - * without wiping sensitive data when possible - *  - * @param   state   The hashing state - * @param   msg     The partial message - * @param   msglen  The length of the partial message - * @return          Zero on success, -1 on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull))) -int libkeccak_fast_update(libkeccak_state_t *restrict state, const char* restrict msg, size_t msglen); - - -/** - * Absorb more of the message to the Keccak sponge - * and wipe sensitive data when possible - *  - * @param   state   The hashing state - * @param   msg     The partial message - * @param   msglen  The length of the partial message - * @return          Zero on success, -1 on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull))) -int libkeccak_update(libkeccak_state_t *restrict state, const char *restrict msg, size_t msglen); - - -/** - * Absorb the last part of the message and squeeze the Keccak sponge - * without wiping sensitive data when possible - *  - * @param   state    The hashing state - * @param   msg      The rest of the message, may be `NULL` - * @param   msglen   The length of the partial message - * @param   bits     The number of bits at the end of the message not covered by `msglen` - * @param   suffix   The suffix concatenate to the message, only '1':s and '0':s, and NUL-termination - * @param   hashsum  Output parameter for the hashsum, may be `NULL` - * @return           Zero on success, -1 on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull(1)))) -int libkeccak_fast_digest(libkeccak_state_t *restrict state, const char *restrict msg, size_t msglen, -                          size_t bits, const char *restrict suffix, char *restrict hashsum); - - -/** - * Absorb the last part of the message and squeeze the Keccak sponge - * and wipe sensitive data when possible - *  - * @param   state    The hashing state - * @param   msg      The rest of the message, may be `NULL` - * @param   msglen   The length of the partial message - * @param   bits     The number of bits at the end of the message not covered by `msglen` - * @param   suffix   The suffix concatenate to the message, only '1':s and '0':s, and NUL-termination - * @param   hashsum  Output parameter for the hashsum, may be `NULL` - * @return           Zero on success, -1 on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull(1)))) -int libkeccak_digest(libkeccak_state_t *restrict state, const char *restrict msg, size_t msglen, -                     size_t bits, const char *restrict suffix, char *restrict hashsum); - - -/** - * Force some rounds of Keccak-f - *  - * @param  state  The hashing state - * @param  times  The number of rounds - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull, nothrow))) -void libkeccak_simple_squeeze(register libkeccak_state_t *restrict state, register long times); - - -/** - * Squeeze as much as is needed to get a digest a number of times - *  - * @param  state  The hashing state - * @param  times  The number of digests - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull, nothrow))) -void libkeccak_fast_squeeze(register libkeccak_state_t *restrict state, register long times); - - -/** - * Squeeze out another digest - *  - * @param  state    The hashing state - * @param  hashsum  Output parameter for the hashsum - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull, nothrow))) -void libkeccak_squeeze(register libkeccak_state_t *restrict state, register char* restrict hashsum); - - -#endif - diff --git a/src/libkeccak/files.c b/src/libkeccak/files.c deleted file mode 100644 index 22d12f3..0000000 --- a/src/libkeccak/files.c +++ /dev/null @@ -1,57 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "files.h" - -#include <sys/stat.h> -#include <alloca.h> -#include <errno.h> -#include <stddef.h> -#include <unistd.h> - - - -/** - * Calculate a Keccak-family hashsum of a file, - * the content of the file is assumed non-sensitive - *  - * @param   fd       The file descriptor of the file to hash - * @param   state    The hashing state, should not be initialised (memory leak otherwise) - * @param   spec     Specifications for the hashing algorithm - * @param   suffix   The data suffix, see `libkeccak_digest` - * @param   hashsum  Output array for the hashsum, have an allocation size of - *                   at least `((spec->output + 7) / 8) * sizeof(char)`, may be `NULL` - * @return           Zero on success, -1 on error - */ -int -libkeccak_generalised_sum_fd(int fd, libkeccak_state_t *restrict state, -                             const libkeccak_spec_t *restrict spec, -                             const char *restrict suffix, char *restrict hashsum) -{ -	ssize_t got; -	struct stat attr; -	size_t blksize = 4096; -	char *restrict chunk; - -	if (libkeccak_state_initialise(state, spec) < 0) -		return -1; - -	if (fstat(fd, &attr) == 0) -		if (attr.st_blksize > 0) -			blksize = (size_t)(attr.st_blksize); -   -	chunk = alloca(blksize); - -	for (;;) { -		got = read(fd, chunk, blksize); -		if (got < 0) { -			if (errno == EINTR) -				continue; -			return -1; -		} -		if (got == 0) -			break; -		if (libkeccak_fast_update(state, chunk, (size_t)got) < 0) -			return -1; -	} - -	return libkeccak_fast_digest(state, NULL, 0, 0, suffix, hashsum); -} diff --git a/src/libkeccak/files.h b/src/libkeccak/files.h deleted file mode 100644 index 92038fb..0000000 --- a/src/libkeccak/files.h +++ /dev/null @@ -1,115 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#ifndef LIBKECCAK_FILES_H -#define LIBKECCAK_FILES_H 1 - -#include "../libkeccak.h" -#include "internal.h" - - -/** - * Calculate a Keccak-family hashsum of a file, - * the content of the file is assumed non-sensitive - *  - * @param   fd       The file descriptor of the file to hash - * @param   state    The hashing state, should not be initialised (memory leak otherwise) - * @param   spec     Specifications for the hashing algorithm - * @param   suffix   The data suffix, see `libkeccak_digest` - * @param   hashsum  Output array for the hashsum, have an allocation size of - *                   at least `((spec->output + 7) / 8) * sizeof(char)`, may be `NULL` - * @return           Zero on success, -1 on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull(2, 3)))) -int libkeccak_generalised_sum_fd(int fd, libkeccak_state_t *restrict state, -                                 const libkeccak_spec_t *restrict spec, -                                 const char *restrict suffix, char *restrict hashsum); - - -/** - * Calculate the Keccak hashsum of a file, - * the content of the file is assumed non-sensitive - *  - * @param   fd       The file descriptor of the file to hash - * @param   state    The hashing state, should not be initialised (memory leak otherwise) - * @param   spec     Specifications for the hashing algorithm - * @param   hashsum  Output array for the hashsum, have an allocation size of - *                   at least `((spec->output + 7) / 8) * sizeof(char)`, may be `NULL` - * @return           Zero on success, -1 on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull(2, 3), artificial, gnu_inline))) -static inline int -libkeccak_keccaksum_fd(int fd, libkeccak_state_t *restrict state, -                       const libkeccak_spec_t *restrict spec, char *restrict hashsum) -{ -	return libkeccak_generalised_sum_fd(fd, state, spec, NULL, hashsum); -} - - -/** - * Calculate the SHA3 hashsum of a file, - * the content of the file is assumed non-sensitive - *  - * @param   fd       The file descriptor of the file to hash - * @param   state    The hashing state, should not be initialised (memory leak otherwise) - * @param   output   The output size parameter for the hashing algorithm - * @param   hashsum  Output array for the hashsum, have an allocation size of - *                   at least `((output + 7) / 8) * sizeof(char)`, may be `NULL` - * @return           Zero on success, -1 on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull(2), artificial, gnu_inline))) -static inline int -libkeccak_sha3sum_fd(int fd, libkeccak_state_t *restrict state, -                     long output, char *restrict hashsum) -{ -	libkeccak_spec_t spec; -	libkeccak_spec_sha3(&spec, output); -	return libkeccak_generalised_sum_fd(fd, state, &spec, LIBKECCAK_SHA3_SUFFIX, hashsum); -} - - -/** - * Calculate the RawSHAKE hashsum of a file, - * the content of the file is assumed non-sensitive - *  - * @param   fd            The file descriptor of the file to hash - * @param   state         The hashing state, should not be initialised (memory leak otherwise) - * @param   semicapacity  The semicapacity parameter for the hashing algorithm - * @param   output        The output size parameter for the hashing algorithm - * @param   hashsum       Output array for the hashsum, have an allocation size of - *                        at least `((output + 7) / 8) * sizeof(char)`, may be `NULL` - * @return                Zero on success, -1 on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull(2), artificial, gnu_inline))) -static inline int -libkeccak_rawshakesum_fd(int fd, libkeccak_state_t *restrict state, -                         long semicapacity, long output, char *restrict hashsum) -{ -	libkeccak_spec_t spec; -	libkeccak_spec_rawshake(&spec, semicapacity, output); -	return libkeccak_generalised_sum_fd(fd, state, &spec, LIBKECCAK_RAWSHAKE_SUFFIX, hashsum); -} - - -/** - * Calculate the SHAKE hashsum of a file, - * the content of the file is assumed non-sensitive - *  - * @param   fd            The file descriptor of the file to hash - * @param   state         The hashing state, should not be initialised (memory leak otherwise) - * @param   semicapacity  The semicapacity parameter for the hashing algorithm - * @param   output        The output size parameter for the hashing algorithm - * @param   hashsum       Output array for the hashsum, have an allocation size of - *                        at least `((output + 7) / 8) * sizeof(char)`, may be `NULL` - * @return                Zero on success, -1 on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull(2), artificial, gnu_inline))) -static inline int -libkeccak_shakesum_fd(int fd, libkeccak_state_t *restrict state, -                      long semicapacity, long output, char *restrict hashsum) -{ -	libkeccak_spec_t spec; -	libkeccak_spec_shake(&spec, semicapacity, output); -	return libkeccak_generalised_sum_fd(fd, state, &spec, LIBKECCAK_SHAKE_SUFFIX, hashsum); -} - - -#endif diff --git a/src/libkeccak/generalised-spec.c b/src/libkeccak/generalised-spec.c deleted file mode 100644 index 9dfa918..0000000 --- a/src/libkeccak/generalised-spec.c +++ /dev/null @@ -1,111 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "generalised-spec.h" - -#ifdef __GNUC__ -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wmaybe-uninitialized" -#endif - -#define have(v)     (spec->v != LIBKECCAK_GENERALISED_SPEC_AUTOMATIC) -#define copy(v)     (v = spec->v) -#define deft(v, dv) (have_##v ? v : (dv)) - - - -/** - * Convert a `libkeccak_generalised_spec_t` to a `libkeccak_spec_t` - * - * If you are interrested in finding errors, you should call - * `libkeccak_spec_check(output)` if this function returns zero - *  - * @param   spec         The generalised input specifications, will be update with resolved automatic values - * @param   output_spec  The specification datastructure to fill in - * @return               Zero if `spec` is valid, a `LIBKECCAK_GENERALISED_SPEC_ERROR_*` if an error was found - */ -int -libkeccak_degeneralise_spec(libkeccak_generalised_spec_t *restrict spec, -                            libkeccak_spec_t *restrict output_spec) -{ -	long state_size, word_size, capacity, bitrate, output; -	const int have_state_size = have(state_size); -	const int have_word_size  = have(word_size); -	const int have_capacity   = have(capacity); -	const int have_bitrate    = have(bitrate); -	const int have_output     = have(output); - - -	if (have_state_size) { -		copy(state_size); -		if (state_size <= 0)   return LIBKECCAK_GENERALISED_SPEC_ERROR_STATE_NONPOSITIVE; -		if (state_size > 1600) return LIBKECCAK_GENERALISED_SPEC_ERROR_STATE_TOO_LARGE; -		if (state_size % 25)   return LIBKECCAK_GENERALISED_SPEC_ERROR_STATE_MOD_25; -	} - -	if (have_word_size) { -		copy(word_size); -		if (word_size <= 0) return LIBKECCAK_GENERALISED_SPEC_ERROR_WORD_NONPOSITIVE; -		if (word_size > 64) return LIBKECCAK_GENERALISED_SPEC_ERROR_WORD_TOO_LARGE; -		if (have_state_size && state_size != word_size * 25) -			return LIBKECCAK_GENERALISED_SPEC_ERROR_STATE_WORD_INCOHERENCY; -		else if (!have_state_size) -			spec->state_size = 1, state_size = word_size * 25; -	} - -	if (have_capacity) { -		copy(capacity); -		if (capacity <= 0) return LIBKECCAK_GENERALISED_SPEC_ERROR_CAPACITY_NONPOSITIVE; -		if (capacity & 7)  return LIBKECCAK_GENERALISED_SPEC_ERROR_CAPACITY_MOD_8; -	} - -	if (have_bitrate) { -		copy(bitrate); -		if (bitrate <= 0) return LIBKECCAK_GENERALISED_SPEC_ERROR_BITRATE_NONPOSITIVE; -		if (bitrate & 7)  return LIBKECCAK_GENERALISED_SPEC_ERROR_BITRATE_MOD_8; -	} - -	if (have_output) { -		copy(output); -		if (output <= 0) return LIBKECCAK_GENERALISED_SPEC_ERROR_OUTPUT_NONPOSITIVE; -	} - - -	if (!have_bitrate && !have_capacity && !have_output) { -		state_size = deft(state_size, 1600L); -		output = ((state_size << 5) / 100L + 7L) & ~0x07L; -		bitrate = output << 1; -		capacity = state_size - bitrate; -		output = output >= 8 ? output : 8; -	} else if (!have_bitrate && !have_capacity) { -		bitrate = 1024; -		capacity = 1600 - 1024; -		state_size = deft(state_size, bitrate + capacity); -	} else if (!have_bitrate) { -		state_size = deft(state_size, 1600L); -		bitrate = state_size - capacity; -		output = deft(output, capacity == 8 ? 8 : (capacity << 1)); -	} else if (!have_capacity) { -		state_size = deft(state_size, 1600L); -		capacity = state_size - bitrate; -		output = deft(output, capacity == 8 ? 8 : (capacity << 1)); -	} else { -		state_size = deft(state_size, bitrate + capacity); -		output = deft(output, capacity == 8 ? 8 : (capacity << 1)); -	} - -	spec->capacity   = output_spec->capacity = capacity; -	spec->bitrate    = output_spec->bitrate  = bitrate; -	spec->output     = output_spec->output   = output; -	spec->state_size = state_size; -	spec->word_size  = state_size / 25; - -	return 0; -} - - -#undef deft -#undef copy -#undef have - -#ifdef __GNUC__ -# pragma GCC diagnostic pop -#endif diff --git a/src/libkeccak/generalised-spec.h b/src/libkeccak/generalised-spec.h deleted file mode 100644 index 2725961..0000000 --- a/src/libkeccak/generalised-spec.h +++ /dev/null @@ -1,142 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#ifndef LIBKECCAK_GENERALISED_SPEC_H -#define LIBKECCAK_GENERALISED_SPEC_H 1 - -#include "spec.h" -#include "internal.h" - -#include <inttypes.h> - - - -/** - * Value for `libkeccak_generalised_spec_t` member that - * is used to automatically select the value - */ -#define LIBKECCAK_GENERALISED_SPEC_AUTOMATIC (-65536L) - - -/** - * Invalid `libkeccak_generalised_spec_t.state_size`: non-positive - */ -#define LIBKECCAK_GENERALISED_SPEC_ERROR_STATE_NONPOSITIVE 1 - -/** - * Invalid `libkeccak_generalised_spec_t.state_size`: larger than 1600 - */ -#define LIBKECCAK_GENERALISED_SPEC_ERROR_STATE_TOO_LARGE 2 - -/** - * Invalid `libkeccak_generalised_spec_t.state_size`: not a multiple of 25 - */ -#define LIBKECCAK_GENERALISED_SPEC_ERROR_STATE_MOD_25 3 - -/** - * Invalid `libkeccak_generalised_spec_t.word_size`: non-positive - */ -#define LIBKECCAK_GENERALISED_SPEC_ERROR_WORD_NONPOSITIVE 4 - -/** - * Invalid `libkeccak_generalised_spec_t.word_size`: larger than 1600 / 25 - */ -#define LIBKECCAK_GENERALISED_SPEC_ERROR_WORD_TOO_LARGE 5 - -/** - * Invalid `libkeccak_generalised_spec_t.word_size` and - * `libkeccak_generalised_spec_t.state_size`: `.word_size * 25 != .state_size` - */ -#define LIBKECCAK_GENERALISED_SPEC_ERROR_STATE_WORD_INCOHERENCY 6 - -/** - * Invalid `libkeccak_generalised_spec_t.capacity`: non-positive - */ -#define LIBKECCAK_GENERALISED_SPEC_ERROR_CAPACITY_NONPOSITIVE 7 - -/** - * Invalid `libkeccak_generalised_spec_t.capacity`: not a multiple of 8 - */ -#define LIBKECCAK_GENERALISED_SPEC_ERROR_CAPACITY_MOD_8 8 - -/** - * Invalid `libkeccak_generalised_spec_t.bitrate`: non-positive - */ -#define LIBKECCAK_GENERALISED_SPEC_ERROR_BITRATE_NONPOSITIVE 9 - -/** - * Invalid `libkeccak_generalised_spec_t.bitrate`: not a multiple of 8 - */ -#define LIBKECCAK_GENERALISED_SPEC_ERROR_BITRATE_MOD_8 10 - -/** - * Invalid `libkeccak_generalised_spec_t.output`: non-positive - */ -#define LIBKECCAK_GENERALISED_SPEC_ERROR_OUTPUT_NONPOSITIVE 11 - - - -/** - * Generalised datastructure that describes the - * parameters that should be used when hashing - */ -typedef struct libkeccak_generalised_spec -{ -	/** -	 * The bitrate -	 */ -	long bitrate; - -	/** -	 * The capacity -	 */ -	long capacity; - -	/** -	 * The output size -	 */ -	long output; - -	/** -	 * The state size -	 */ -	long state_size; - -	/** -	 * The word size -	 */ -	long word_size; - -} libkeccak_generalised_spec_t; - - - -/** - * Set all specification parameters to automatic - *  - * @param  spec  The specification datastructure to fill in - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull, nothrow, unused))) -static inline void -libkeccak_generalised_spec_initialise(libkeccak_generalised_spec_t *restrict spec) -{ -	spec->bitrate    = LIBKECCAK_GENERALISED_SPEC_AUTOMATIC; -	spec->capacity   = LIBKECCAK_GENERALISED_SPEC_AUTOMATIC; -	spec->output     = LIBKECCAK_GENERALISED_SPEC_AUTOMATIC; -	spec->state_size = LIBKECCAK_GENERALISED_SPEC_AUTOMATIC; -	spec->word_size  = LIBKECCAK_GENERALISED_SPEC_AUTOMATIC; -} - - -/** - * Convert a `libkeccak_generalised_spec_t` to a `libkeccak_spec_t` - *  - * @param   spec         The generalised input specifications, will be update with resolved automatic values - * @param   output_spec  The specification datastructure to fill in - * @return               Zero if `spec` is valid, a `LIBKECCAK_GENERALISED_SPEC_ERROR_*` if an error was found - */ -LIBKECCAK_GCC_ONLY(__attribute__((leaf, nonnull, nothrow))) -int libkeccak_degeneralise_spec(libkeccak_generalised_spec_t *restrict spec, -                                libkeccak_spec_t *restrict output_spec); - - -#endif - diff --git a/src/libkeccak/hex.c b/src/libkeccak/hex.c deleted file mode 100644 index 7531223..0000000 --- a/src/libkeccak/hex.c +++ /dev/null @@ -1,65 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "hex.h" - -#include <string.h> - - - -/** - * Convert a binary hashsum to lower case hexadecimal representation - *  - * @param  output   Output array, should have an allocation size of at least `2 * n + 1` - * @param  hashsum  The hashsum to convert - * @param  n        The size of `hashsum` - */ -void -libkeccak_behex_lower(char *restrict output, const char *restrict hashsum, size_t n) -{ -	output[2 * n] = '\0'; -	while (n--) { -		output[2 * n + 0] = "0123456789abcdef"[(hashsum[n] >> 4) & 15]; -		output[2 * n + 1] = "0123456789abcdef"[(hashsum[n] >> 0) & 15]; -	} -} - - -/** - * Convert a binary hashsum to upper case hexadecimal representation - *  - * @param  output   Output array, should have an allocation size of at least `2 * n + 1` - * @param  hashsum  The hashsum to convert - * @param  n        The size of `hashsum` - */ -void -libkeccak_behex_upper(char *restrict output, const char *restrict hashsum, size_t n) -{ -	output[2 * n] = '\0'; -	while (n--) { -		output[2 * n + 0] = "0123456789ABCDEF"[(hashsum[n] >> 4) & 15]; -		output[2 * n + 1] = "0123456789ABCDEF"[(hashsum[n] >> 0) & 15]; -	} -} - - -/** - * Convert a hexadecimal hashsum (both lower case, upper - * case and mixed is supported) to binary representation - *  - * @param  output   Output array, should have an allocation size of at least `strlen(hashsum) / 2` - * @param  hashsum  The hashsum to convert - */ -void -libkeccak_unhex(char *restrict output, const char *restrict hashsum) -{ -	size_t n = strlen(hashsum) / 2; -	char a, b; -	while (n--) { -		a = hashsum[2 * n + 0]; -		b = hashsum[2 * n + 1]; - -		a = (char)((a & 15) + (a > '9' ? 9 : 0)); -		b = (char)((b & 15) + (b > '9' ? 9 : 0)); - -		output[n] = (char)((a << 4) | b); -	} -} diff --git a/src/libkeccak/hex.h b/src/libkeccak/hex.h deleted file mode 100644 index 25375d5..0000000 --- a/src/libkeccak/hex.h +++ /dev/null @@ -1,44 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#ifndef LIBKECCAK_HEX_H -#define LIBKECCAK_HEX_H 1 - -#include "internal.h" - -#include <stddef.h> - - -/** - * Convert a binary hashsum to lower case hexadecimal representation - *  - * @param  output   Output array, should have an allocation size of at least `2 * n + 1` - * @param  hashsum  The hashsum to convert - * @param  n        The size of `hashsum` - */ -LIBKECCAK_GCC_ONLY(__attribute__((leaf, nonnull, nothrow))) -void libkeccak_behex_lower(char *restrict output, const char *restrict hashsum, size_t n); - - -/** - * Convert a binary hashsum to upper case hexadecimal representation - *  - * @param  output   Output array, should have an allocation size of at least `2 * n + 1` - * @param  hashsum  The hashsum to convert - * @param  n        The size of `hashsum` - */ -LIBKECCAK_GCC_ONLY(__attribute__((leaf, nonnull, nothrow))) -void libkeccak_behex_upper(char *restrict output, const char *restrict hashsum, size_t n); - - -/** - * Convert a hexadecimal hashsum (both lower case, upper - * case and mixed is supported) to binary representation - *  - * @param  output   Output array, should have an allocation size of at least `strlen(hashsum) / 2` - * @param  hashsum  The hashsum to convert - */ -LIBKECCAK_GCC_ONLY(__attribute__((leaf, nonnull, nothrow))) -void libkeccak_unhex(char *restrict output, const char *restrict hashsum); - - -#endif - diff --git a/src/libkeccak/internal.h b/src/libkeccak/internal.h deleted file mode 100644 index 466abf9..0000000 --- a/src/libkeccak/internal.h +++ /dev/null @@ -1,26 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#ifndef LIBKECCAK_INTERNAL_H -#define LIBKECCAK_INTERNAL_H 1 - - -/** - * Only include some C code (not for CPP directives) - * if compiling with GCC. - */ -#ifdef __GNUC__ -# define LIBKECCAK_GCC_ONLY(x) x -#else -# define LIBKECCAK_GCC_ONLY(x) -#endif - - -/* Use built in functions and branching optimisation if available */ -#ifndef __GNUC__ -# define __builtin_expect(expression, expect) expression -# define __builtin_memset(dest, c, n) memset(dest, c, n) -# define __builtin_memcpy(dest, src, n) memcpy(dest, src, n) -# define __builtin_memmove(dest, src, n) memmove(dest, src, n) -#endif - - -#endif diff --git a/src/libkeccak/mac/hmac.c b/src/libkeccak/mac/hmac.c deleted file mode 100644 index ee3bc6a..0000000 --- a/src/libkeccak/mac/hmac.c +++ /dev/null @@ -1,418 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "hmac.h" - -#include "../digest.h" - - - -/** - * The outer pad pattern - */ -#define OUTER_PAD 0x5C - -/** - * The inner pad pattern - */ -#define INNER_PAD 0x36 - - - -static void *(*volatile my_explicit_memset)(void *, int, size_t) = memset; -static __attribute__((optimize("-O0"))) void -my_explicit_bzero(void *ptr, size_t size) -{ -	(*my_explicit_memset)(ptr, 0, size); -} - - -/** - * Change the HMAC-hashing key on the state - *  - * @param   state       The state that should be reset - * @param   key         The new key - * @param   key_length  The length of key, in bits - * @return              Zero on success, -1 on error - */ -int -libkeccak_hmac_set_key(libkeccak_hmac_state_t *restrict state, const char *restrict key, size_t key_length) -{ -	size_t i, size, new_key_length, key_bytes; -	char *old; - -	size = (size_t)(state->sponge.r) > key_length ? (size_t)(state->sponge.r) : key_length; -	new_key_length = size; -	size = (size + 7) >> 3; -	key_bytes = (key_length + 7) >> 3; - -	if (size != key_bytes) { -		state->key_opad = realloc(old = state->key_opad, 2 * size); -		if (!state->key_opad) -			return state->key_opad = old, -1; -		state->key_ipad = state->key_opad + size / sizeof(char); -	} - -	memcpy(state->key_opad, key, key_bytes); -	if (key_length & 7) -		state->key_opad[(key_bytes >> 3) - 1] &= (1 << (key_length & 7)) - 1; - -	if ((size_t)(state->sponge.r) > key_length) -		__builtin_memset(state->key_opad + key_bytes / sizeof(char), 0, size - key_bytes); - -	for (i = 0; i < size; i++) { -		state->key_ipad[i] = state->key_opad[i] ^ INNER_PAD; -		state->key_opad[i] ^= OUTER_PAD; -	} - -	state->key_length = new_key_length; - -	return 0; -} - - -/** - * Wipe sensitive data wihout freeing any data - *  - * @param  state  The state that should be wipe - */ -void -libkeccak_hmac_wipe(volatile libkeccak_hmac_state_t *restrict state) -{ -	volatile char *restrict key_pads; -	size_t i, size; -	key_pads = state->key_opad; -	size = 2 * ((state->key_length + 7) >> 3); -	libkeccak_state_wipe(&state->sponge); -	for (i = 0; i < size; i++) -		key_pads[i] = 0; -	state->leftover = 0; -	__builtin_memset(state->buffer, 0, state->buffer_size); -} - - -/** - * Make a copy of an HMAC hashing-state - *  - * @param   dest  The slot for the duplicate, must not be initialised (memory leak otherwise) - * @param   src   The state to duplicate - * @return        Zero on success, -1 on error - */ -int -libkeccak_hmac_copy(libkeccak_hmac_state_t *restrict dest, const libkeccak_hmac_state_t *restrict src) -{ -	size_t size; - -	dest->key_opad = NULL; -	dest->key_ipad = NULL; - -	if (libkeccak_state_copy(&dest->sponge, &src->sponge) < 0) -		return -1; - -	dest->key_length = src->key_length; -	dest->leftover = src->leftover; - -	size = (src->key_length + 7) >> 3; -	dest->key_opad = malloc(2 * size); -	if (dest->key_opad == NULL) -		return libkeccak_state_destroy(&dest->sponge), -1; -	dest->key_ipad = dest->key_opad + size / sizeof(char); - -	memcpy(dest->key_opad, src->key_opad, size); -	memcpy(dest->key_ipad, src->key_ipad, size); - -	return 0; -} - - -/** - * Unmarshal a `libkeccak_hmac_state_t` from a buffer - *  - * @param   state  The slot for the unmarshalled state, must not be initialised (memory leak otherwise) - * @param   data   The input buffer - * @return         The number of bytes read from `data`, 0 on error - */ -size_t -libkeccak_hmac_unmarshal(libkeccak_hmac_state_t *restrict state, const char *restrict data) -{ -	size_t parsed, size, i; - -	state->key_opad = NULL; -	state->key_ipad = NULL; - -	parsed = libkeccak_state_unmarshal(&state->sponge, data); -	if (parsed == 0) -		return 0; - -	data += parsed / sizeof(char); -	state->key_length = *(const size_t *)data; -	data += sizeof(size_t) / sizeof(char); -	size = (state->key_length + 7) >> 3; - -	state->key_opad = malloc(2 * size); -	if (state->key_opad == NULL) -		return libkeccak_state_destroy(&state->sponge), -1; -	memcpy(state->key_opad, data, size); -	data += size / sizeof(char); - -	if (data[0]) { -		state->key_ipad = state->key_opad + size / sizeof(char); -		memcpy(state->key_ipad, state->key_opad, size); -		for (i = 0; i < size / sizeof(char); i++) -			state->key_ipad[i] ^= (char)(OUTER_PAD ^ INNER_PAD); -	} - -	state->leftover = data[1]; -	state->buffer = NULL; -	state->buffer_size = 0; - -	return parsed + sizeof(size_t) + size + 2 * sizeof(char); -} - - -/** - * Absorb more, or the first part, of the message - * without wiping sensitive data when possible - *  - * @param   state   The hashing state - * @param   msg     The partial message - * @param   msglen  The length of the partial message, in bytes - * @return          Zero on success, -1 on error - */ -int -libkeccak_hmac_fast_update(libkeccak_hmac_state_t *restrict state, const char *restrict msg, size_t msglen) -{ -	char *old; -	size_t i; -	int n, cn; - -	if (state->key_ipad) { -		if (libkeccak_fast_update(&state->sponge, state->key_ipad, state->key_length >> 3) < 0) -			return -1; -		if (state->key_length & 7) -			state->leftover = state->key_ipad[state->key_length >> 3]; -		state->key_ipad = NULL; -	} - -	if (!msg || !msglen) -		return 0; - -	if (!(state->key_length & 7)) -		return libkeccak_fast_update(&state->sponge, msg, msglen); - -	if (msglen != state->buffer_size) { -		state->buffer = realloc(old = state->buffer, msglen); -		if (!state->buffer) -			return state->buffer = old, -1; -		state->buffer_size = msglen; -	} - -	n = (int)(state->key_length & 7); -	cn = 8 - n; -	for (i = 1; i < msglen; i++) -		state->buffer[i] = (((unsigned char)(msg[i - 1])) >> cn) | (msg[i] << n); -	state->buffer[0] = (state->leftover & ((1 << n) - 1)) | (msg[0] << n); -	state->leftover = ((unsigned char)(msg[msglen - 1])) >> cn; - -	return libkeccak_fast_update(&state->sponge, state->buffer, msglen); -} - - -/** - * Absorb more, or the first part, of the message - * and wipe sensitive data when possible - *  - * @param   state   The hashing state - * @param   msg     The partial message - * @param   msglen  The length of the partial message, in bytes - * @return          Zero on success, -1 on error - */ -int -libkeccak_hmac_update(libkeccak_hmac_state_t *restrict state, const char *restrict msg, size_t msglen) -{ -	size_t i; -	int n, cn, r; - -	if (state->key_ipad) { -		if (libkeccak_update(&state->sponge, state->key_ipad, state->key_length >> 3) < 0) -			return -1; -		if (state->key_length & 7) -			state->leftover = state->key_ipad[state->key_length >> 3]; -		state->key_ipad = NULL; -	} - -	if (!msg || !msglen) -		return 0; - -	if (!(state->key_length & 7)) -		return libkeccak_update(&state->sponge, msg, msglen); - -	if (msglen != state->buffer_size) { -		free(state->buffer); -		state->buffer = malloc(state->buffer_size = msglen); -		if (!state->buffer) -			return -1; -	} - -	n = (int)(state->key_length & 7); -	cn = 8 - n; -	for (i = 1; i < msglen; i++) -		state->buffer[i] = (((unsigned char)(msg[i - 1])) >> cn) | (msg[i] << n); -	state->buffer[0] = (state->leftover & ((1 << n) - 1)) | (msg[0] << n); -	state->leftover = ((unsigned char)(msg[msglen - 1])) >> cn; - -	r = libkeccak_update(&state->sponge, state->buffer, msglen); -	my_explicit_bzero(state->buffer, msglen); -	return r; -} - - -/** - * Absorb the last part of the message and fetch the hash - * without wiping sensitive data when possible - *  - * You may use `&state->sponge` for continued squeezing - *  - * @param   state    The hashing state - * @param   msg      The rest of the message, may be `NULL`, may be modified - * @param   msglen   The length of the partial message - * @param   bits     The number of bits at the end of the message not covered by `msglen` - * @param   suffix   The suffix concatenate to the message, only '1':s and '0':s, and NUL-termination - * @param   hashsum  Output parameter for the hashsum, may be `NULL` - * @return           Zero on success, -1 on error - */ -int -libkeccak_hmac_fast_digest(libkeccak_hmac_state_t *restrict state, const char *restrict msg, size_t msglen, -                           size_t bits, const char *restrict suffix, char *restrict hashsum) -{ -	size_t hashsize = state->sponge.n >> 3; -	char *tmp = malloc(((state->sponge.n + 7) >> 3) * sizeof(char)); -	char leftover[2]; -	size_t newlen; - -	if (!tmp) -		return -1; - -	if (!(state->key_length & 7)) { -		if (libkeccak_fast_digest(&state->sponge, msg, msglen, bits, suffix, tmp) < 0) -			goto fail; -		goto stage_2; -	} - -	if (libkeccak_hmac_fast_update(state, msg, msglen) < 0) -		goto fail; -	leftover[0] = state->leftover; -	if (bits) { -		leftover[0] |= msg[msglen] >> (state->key_length & 7); -		leftover[1] = ((unsigned char)(msg[msglen])) << (8 - (state->key_length & 7)); -	} -	newlen = (state->key_length & 7) + bits; -	if (libkeccak_fast_digest(&state->sponge, leftover, newlen >> 3, newlen & 7, suffix, tmp) < 0) -		goto fail; - -stage_2: -	bits = state->sponge.n & 7; -	state->key_ipad = state->key_opad; -	if (libkeccak_hmac_fast_update(state, NULL, 0) < 0) -		goto fail; - -	if (!(state->key_length & 7)) { -		if (libkeccak_fast_digest(&state->sponge, tmp, hashsize, bits, suffix, hashsum) < 0) -			goto fail; -		goto stage_3; -	} - -	if (libkeccak_hmac_fast_update(state, tmp, hashsize) < 0) -		goto fail; -	leftover[0] = state->leftover; -	if (bits) { -		leftover[0] |= tmp[hashsize] >> (state->key_length & 7); -		leftover[1] = ((unsigned char)(tmp[hashsize])) << (8 - (state->key_length & 7)); -	} -	newlen = (state->key_length & 7) + bits; -	if (libkeccak_fast_digest(&state->sponge, leftover, newlen >> 3, newlen & 7, suffix, tmp) < 0) -		goto fail; - -stage_3: -	free(tmp); -	return 0; -fail: -	free(tmp); -	return -1; -} - - -/** - * Absorb the last part of the message and fetch the hash - * and wipe sensitive data when possible - *  - * You may use `&state->sponge` for continued squeezing - *  - * @param   state    The hashing state - * @param   msg      The rest of the message, may be `NULL`, may be modified - * @param   msglen   The length of the partial message - * @param   bits     The number of bits at the end of the message not covered by `msglen` - * @param   suffix   The suffix concatenate to the message, only '1':s and '0':s, and NUL-termination - * @param   hashsum  Output parameter for the hashsum, may be `NULL` - * @return           Zero on success, -1 on error - */ -int -libkeccak_hmac_digest(libkeccak_hmac_state_t *restrict state, const char *restrict msg, size_t msglen, -                      size_t bits, const char *restrict suffix, char *restrict hashsum) -{ -	size_t hashsize = state->sponge.n >> 3; -	char *tmp = malloc(((state->sponge.n + 7) >> 3) * sizeof(char)); -	char leftover[2]; -	size_t newlen; - -	if (!tmp) -		return -1; - -	if (!(state->key_length & 7)) { -		if (libkeccak_digest(&state->sponge, msg, msglen, bits, suffix, tmp) < 0) -			goto fail; -		goto stage_2; -	} - -	if (libkeccak_hmac_update(state, msg, msglen) < 0) -		goto fail; -	leftover[0] = state->leftover; -	if (bits) { -		leftover[0] |= msg[msglen] >> (state->key_length & 7); -		leftover[1] = ((unsigned char)(msg[msglen])) << (8 - (state->key_length & 7)); -	} -	newlen = (state->key_length & 7) + bits; -	if (libkeccak_digest(&state->sponge, leftover, newlen >> 3, newlen & 7, suffix, tmp) < 0) -		goto fail; - -stage_2: -	bits = state->sponge.n & 7; -	state->key_ipad = state->key_opad; -	if (libkeccak_hmac_update(state, NULL, 0) < 0) -		goto fail; - -	if (!(state->key_length & 7)) { -		if (libkeccak_digest(&state->sponge, tmp, hashsize, bits, suffix, hashsum) < 0) -			goto fail; -		goto stage_3; -	} - -	if (libkeccak_hmac_update(state, tmp, hashsize) < 0) -		goto fail; -	leftover[0] = state->leftover; -	if (bits) { -		leftover[0] |= tmp[hashsize] >> (state->key_length & 7); -		leftover[1] = ((unsigned char)(tmp[hashsize])) << (8 - (state->key_length & 7)); -	} -	newlen = (state->key_length & 7) + bits; -	if (libkeccak_digest(&state->sponge, leftover, newlen >> 3, newlen & 7, suffix, tmp) < 0) -		goto fail; - -stage_3: -	my_explicit_bzero(tmp, ((state->sponge.n + 7) >> 3) * sizeof(char)); -	free(tmp); -	return 0; - fail: -	my_explicit_bzero(tmp, ((state->sponge.n + 7) >> 3) * sizeof(char)); -	free(tmp); -	return -1; -} - diff --git a/src/libkeccak/mac/hmac.h b/src/libkeccak/mac/hmac.h deleted file mode 100644 index 2681e61..0000000 --- a/src/libkeccak/mac/hmac.h +++ /dev/null @@ -1,393 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#ifndef LIBKECCAK_MAC_HMAC_H -#define LIBKECCAK_MAC_HMAC_H 1 - -/* - * The Keccak hash-function, that was selected by NIST as the SHA-3 competition winner, - * doesn't need this nested approach and can be used to generate a MAC by simply prepending - * the key to the message. [http://keccak.noekeon.org] - */ - -#include "../spec.h" -#include "../state.h" -#include "../internal.h" - -#include <stddef.h> -#include <stdint.h> -#include <stdlib.h> -#include <errno.h> -#include <string.h> - - - -/** - * Datastructure that describes the state of an HMAC-hashing process - */ -typedef struct libkeccak_hmac_state -{ -	/** -	 * The key right-padded and XOR:ed with the outer pad -	 */ -	char *restrict key_opad; - -	/** -	 * The key right-padded and XOR:ed with the inner pad -	 */ -	char *restrict key_ipad; -	/* Not marshalled, implicitly unmarshalled using `key_opad`. */ -	/* Shares allocation with `key_opad`, do not `free`. */ - -	/** -	 * The length of key, but at least the input block size, in bits -	 */ -	size_t key_length; - -	/** -	 * The state of the underlaying hash-algorithm -	 */ -	libkeccak_state_t sponge; - -	/** -	 * Buffer used to temporarily store bit shift message if -	 * `.key_length` is not zero modulus 8 -	 */ -	char *restrict buffer; - -	/** -	 * The allocation size of `.buffer` -	 */ -	size_t buffer_size; - -	/** -	 * Part of feed key, message or digest that have not been passed yet -	 */ -	char leftover; - -	char __pad[sizeof(void*) / sizeof(char) - 1]; - -} libkeccak_hmac_state_t; - - - -/** - * Change the HMAC-hashing key on the state - *  - * @param   state       The state that should be reset - * @param   key         The new key - * @param   key_length  The length of key, in bits - * @return              Zero on success, -1 on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull(1), unused))) -int libkeccak_hmac_set_key(libkeccak_hmac_state_t *restrict state, const char *restrict key, size_t key_length); - - -/** - * Initialise an HMAC hashing-state according to hashing specifications - *  - * @param   state       The state that should be initialised - * @param   spec        The specifications for the state - * @param   key         The key - * @param   key_length  The length of key, in bits - * @return              Zero on success, -1 on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull))) -static inline int -libkeccak_hmac_initialise(libkeccak_hmac_state_t *restrict state, const libkeccak_spec_t *restrict spec, -                          const char *restrict key, size_t key_length) -{ -	if (libkeccak_state_initialise(&state->sponge, spec) < 0) -		return -1; -	if (libkeccak_hmac_set_key(state, key, key_length) < 0) -		return libkeccak_state_destroy(&state->sponge), -1; -	state->leftover = 0; -	state->buffer = NULL; -	state->buffer_size = 0; -	return 0; -} - - -/** - * Wrapper for `libkeccak_hmac_initialise` that also allocates the states - *  - * @param   spec        The specifications for the state - * @param   key         The key - * @param   key_length  The length of key, in bits - * @return              The state, `NULL` on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull, unused, warn_unused_result, malloc))) -static inline libkeccak_hmac_state_t * -libkeccak_hmac_create(const libkeccak_spec_t *restrict spec, -                      const char *restrict key, size_t key_length) -{ -	libkeccak_hmac_state_t *restrict state = malloc(sizeof(libkeccak_hmac_state_t)); -	if (!state || libkeccak_hmac_initialise(state, spec, key, key_length)) -		return free(state), NULL; -	return state; -} - - -/** - * Reset an HMAC-hashing state according to hashing specifications, - * you can choose whether to change the key - *  - * @param   state       The state that should be reset - * @param   key         The new key, `NULL` to keep the old key - * @param   key_length  The length of key, in bits, ignored if `key == NULL` - * @return              Zero on success, -1 on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull(1), unused))) -static inline int -libkeccak_hmac_reset(libkeccak_hmac_state_t *restrict state, const char *restrict key, size_t key_length) -{ -	libkeccak_state_reset(&state->sponge); -	return key ? libkeccak_hmac_set_key(state, key, key_length) : 0; -} - - -/** - * Wipe sensitive data wihout freeing any data - *  - * @param  state  The state that should be wipe - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull, nothrow, optimize("-O0")))) -void libkeccak_hmac_wipe(volatile libkeccak_hmac_state_t *restrict state); - - -/** - * Release resources allocation for an HMAC hashing-state without wiping sensitive data - *  - * @param  state  The state that should be destroyed - */ -static inline void -libkeccak_hmac_fast_destroy(libkeccak_hmac_state_t *restrict state) -{ -	if (!state) -		return; -	free(state->key_opad); -	state->key_opad = NULL; -	state->key_ipad = NULL; -	state->key_length = 0; -	free(state->buffer); -	state->buffer = NULL; -	state->buffer_size = 0; -} - - -/** - * Release resources allocation for an HMAC hasing-state and wipe sensitive data - *  - * @param  state  The state that should be destroyed - */ -LIBKECCAK_GCC_ONLY(__attribute__((unused, optimize("-O0")))) -static inline void -libkeccak_hmac_destroy(volatile libkeccak_hmac_state_t *restrict state) -{ -	if (!state) -	  return; -	libkeccak_hmac_wipe(state); -	free(state->key_opad); -	state->key_opad = NULL; -	state->key_ipad = NULL; -	state->key_length = 0; -	state->leftover = 0; -	free(state->buffer); -	state->buffer = NULL; -	state->buffer_size = 0; -} - - -/** - * Wrapper for `libkeccak_fast_destroy` that also frees the allocation of the state - *  - * @param  state  The state that should be freed - */ -LIBKECCAK_GCC_ONLY(__attribute__((unused))) -static inline void -libkeccak_hmac_fast_free(libkeccak_hmac_state_t *restrict state) -{ -	libkeccak_hmac_fast_destroy(state); -	free(state); -} - - -/** - * Wrapper for `libkeccak_hmac_destroy` that also frees the allocation of the state - *  - * @param  state  The state that should be freed - */ -LIBKECCAK_GCC_ONLY(__attribute__((unused, optimize("-O0")))) -static inline void -libkeccak_hmac_free(volatile libkeccak_hmac_state_t *restrict state) -{ -#ifdef __GNUC__ -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wcast-qual" -#endif -	libkeccak_hmac_destroy(state); -	free((libkeccak_hmac_state_t*)state); -#ifdef __GNUC__ -# pragma GCC diagnostic pop -#endif -} - - -/** - * Make a copy of an HMAC hashing-state - *  - * @param   dest  The slot for the duplicate, must not be initialised (memory leak otherwise) - * @param   src   The state to duplicate - * @return        Zero on success, -1 on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull))) -int libkeccak_hmac_copy(libkeccak_hmac_state_t *restrict dest, const libkeccak_hmac_state_t *restrict src); - - -/** - * A wrapper for `libkeccak_hmac_copy` that also allocates the duplicate - *  - * @param   src  The state to duplicate - * @return       The duplicate, `NULL` on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull, unused, warn_unused_result, malloc))) -static inline libkeccak_hmac_state_t * -libkeccak_hmac_duplicate(const libkeccak_hmac_state_t *restrict src) -{ -	libkeccak_hmac_state_t* restrict dest = malloc(sizeof(libkeccak_hmac_state_t)); -	if (!dest || libkeccak_hmac_copy(dest, src)) -		return libkeccak_hmac_free(dest), NULL; -	return dest; -} - - -/** - * Calculates the allocation size required for the second argument - * of `libkeccak_hmac_marshal` (`char* restrict data)`) - *  - * @param   state  The state as it will be marshalled by a subsequent call to `libkeccak_hamc_marshal` - * @return         The allocation size needed for the buffer to which the state will be marshalled - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull, nothrow, unused, warn_unused_result, pure))) -static inline size_t -libkeccak_hmac_marshal_size(const libkeccak_hmac_state_t *restrict state) -{ -	return libkeccak_state_marshal_size(&state->sponge) + sizeof(size_t) + -	       ((state->key_length + 7) >> 3) + 2 * sizeof(char); -} - - -/** - * Marshal a `libkeccak_hmac_state_t` into a buffer - *  - * @param   state  The state to marshal - * @param   data   The output buffer - * @return         The number of bytes stored to `data` - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull, nothrow))) -static inline size_t -libkeccak_hmac_marshal(const libkeccak_hmac_state_t *restrict state, char *restrict data) -{ -	size_t written = libkeccak_state_marshal(&state->sponge, data); -	data += written / sizeof(char); -	*(size_t *)data = state->key_length; -	data += sizeof(size_t) / sizeof(char); -	memcpy(data, state->key_opad, (state->key_length + 7) >> 3); -	data += ((state->key_length + 7) >> 3) / sizeof(char); -	data[0] = (char)!!state->key_ipad; -	data[1] = state->leftover; -	return written + sizeof(size_t) + ((state->key_length + 7) >> 3) + 2 * sizeof(char); -} - - -/** - * Unmarshal a `libkeccak_hmac_state_t` from a buffer - *  - * @param   state  The slot for the unmarshalled state, must not be initialised (memory leak otherwise) - * @param   data   The input buffer - * @return         The number of bytes read from `data`, 0 on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull))) -size_t libkeccak_hmac_unmarshal(libkeccak_hmac_state_t *restrict state, const char *restrict data); - - -/** - * Gets the number of bytes the `libkeccak_hmac_state_t` stored - * at the beginning of `data` occupies - *  - * @param   data  The data buffer - * @return        The byte size of the stored state - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull, nothrow, warn_unused_result, pure))) -static inline size_t -libkeccak_hmac_unmarshal_skip(const char *restrict data) -{ -	size_t skip = libkeccak_state_unmarshal_skip(data); -	data += skip / sizeof(char); -	return skip + sizeof(size_t) + *(const size_t *)data + 2 * sizeof(char); -} - - -/** - * Absorb more, or the first part, of the message - * without wiping sensitive data when possible - *  - * @param   state   The hashing state - * @param   msg     The partial message - * @param   msglen  The length of the partial message, in bytes - * @return          Zero on success, -1 on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull(1)))) -int libkeccak_hmac_fast_update(libkeccak_hmac_state_t *restrict state, const char *restrict msg, size_t msglen); - - -/** - * Absorb more, or the first part, of the message - * and wipe sensitive data when possible - *  - * @param   state   The hashing state - * @param   msg     The partial message - * @param   msglen  The length of the partial message, in bytes - * @return          Zero on success, -1 on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull(1)))) -int libkeccak_hmac_update(libkeccak_hmac_state_t *restrict state, const char *restrict msg, size_t msglen); - - -/** - * Absorb the last part of the message and fetch the hash - * without wiping sensitive data when possible - *  - * You may use `&state->sponge` for continued squeezing - *  - * @param   state    The hashing state - * @param   msg      The rest of the message, may be `NULL`, may be modified - * @param   msglen   The length of the partial message - * @param   bits     The number of bits at the end of the message not covered by `msglen` - * @param   suffix   The suffix concatenate to the message, only '1':s and '0':s, and NUL-termination - * @param   hashsum  Output parameter for the hashsum, may be `NULL` - * @return           Zero on success, -1 on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull(1)))) -int libkeccak_hmac_fast_digest(libkeccak_hmac_state_t *restrict state, const char *restrict msg, size_t msglen, -                               size_t bits, const char *restrict suffix, char *restrict hashsum); - - -/** - * Absorb the last part of the message and fetch the hash - * and wipe sensitive data when possible - *  - * You may use `&state->sponge` for continued squeezing - *  - * @param   state    The hashing state - * @param   msg      The rest of the message, may be `NULL`, may be modified - * @param   msglen   The length of the partial message - * @param   bits     The number of bits at the end of the message not covered by `msglen` - * @param   suffix   The suffix concatenate to the message, only '1':s and '0':s, and NUL-termination - * @param   hashsum  Output parameter for the hashsum, may be `NULL` - * @return           Zero on success, -1 on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull(1)))) -int libkeccak_hmac_digest(libkeccak_hmac_state_t *restrict state, const char *restrict msg, size_t msglen, -                          size_t bits, const char *restrict suffix, char *restrict hashsum); - - -#endif diff --git a/src/libkeccak/spec.h b/src/libkeccak/spec.h deleted file mode 100644 index 8d73c52..0000000 --- a/src/libkeccak/spec.h +++ /dev/null @@ -1,177 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#ifndef LIBKECCAK_SPEC_H -#define LIBKECCAK_SPEC_H 1 - -#include "internal.h" - -#include <stdint.h> -#include <limits.h> - - -/** - * Message suffix for SHA3 hashing - */ -#define LIBKECCAK_SHA3_SUFFIX "01" - -/** - * Message suffix for RawSHAKE hashing - */ -#define LIBKECCAK_RAWSHAKE_SUFFIX "11" - -/** - * Message suffix for SHAKE hashing - */ -#define LIBKECCAK_SHAKE_SUFFIX "1111" - - -/** - * Invalid `libkeccak_spec_t.bitrate`: non-positive - */ -#define LIBKECCAK_SPEC_ERROR_BITRATE_NONPOSITIVE 1 - -/** - * Invalid `libkeccak_spec_t.bitrate`: not a multiple of 8 - */ -#define LIBKECCAK_SPEC_ERROR_BITRATE_MOD_8 2 - -/** - * Invalid `libkeccak_spec_t.capacity`: non-positive - */ -#define LIBKECCAK_SPEC_ERROR_CAPACITY_NONPOSITIVE 3 - -/** - * Invalid `libkeccak_spec_t.capacity`: not a multiple of 8 - */ -#define LIBKECCAK_SPEC_ERROR_CAPACITY_MOD_8 4 - -/** - * Invalid `libkeccak_spec_t.output`: non-positive - */ -#define LIBKECCAK_SPEC_ERROR_OUTPUT_NONPOSITIVE 5 - -/** - * Invalid `libkeccak_spec_t` values: `.bitrate + `.capacity` - * is greater 1600 which is the largest supported state size - */ -#define LIBKECCAK_SPEC_ERROR_STATE_TOO_LARGE 6 - -/** - * Invalid `libkeccak_spec_t` values: - * `.bitrate + `.capacity` is not a multiple of 25 - */ -#define LIBKECCAK_SPEC_ERROR_STATE_MOD_25 7 - -/** - * Invalid `libkeccak_spec_t` values: `.bitrate + `.capacity` - * is a not a 2-potent multiple of 25 - */ -#define LIBKECCAK_SPEC_ERROR_WORD_NON_2_POTENT 8 - -/** - * Invalid `libkeccak_spec_t` values: `.bitrate + `.capacity` - * is a not multiple of 100, and thus the word size is not - * a multiple of 8 - */ -#define LIBKECCAK_SPEC_ERROR_WORD_MOD_8 9 - - - -/** - * Datastructure that describes the parameters - * that should be used when hashing - */ -typedef struct libkeccak_spec { -	/** -	 * The bitrate -	 */ -	long bitrate; - -	/** -	 * The capacity -	 */ -	long capacity; - -	/** -	 * The output size -	 */ -	long output; - -} libkeccak_spec_t; - - - -/** - * Fill in a `libkeccak_spec_t` for a SHA3-x hashing - *  - * @param  spec  The specifications datastructure to fill in - * @param  x     The value of x in `SHA3-x`, the output size - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull, nothrow))) -static inline void -libkeccak_spec_sha3(libkeccak_spec_t *restrict spec, long x) -{ -	spec->bitrate = 1600 - 2 * x; -	spec->capacity = 2 * x; -	spec->output = x; -} - - -/** - * Fill in a `libkeccak_spec_t` for a RawSHAKEx hashing - *  - * @param  spec  The specifications datastructure to fill in - * @param  x     The value of x in `RawSHAKEx`, half the capacity - * @param  d     The output size - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull, nothrow))) -static inline void -libkeccak_spec_rawshake(libkeccak_spec_t *restrict spec, long x, long d) -{ -	spec->bitrate = 1600 - 2 * x; -	spec->capacity = 2 * x; -	spec->output = d; -} - - -/** - * Fill in a `libkeccak_spec_t` for a SHAKEx hashing - *  - * @param  spec:libkeccak_spec_t*  The specifications datastructure to fill in - * @param  x:long                  The value of x in `SHAKEx`, half the capacity - * @param  d:long                  The output size - */ -#define libkeccak_spec_shake libkeccak_spec_rawshake - - -/** - * Check for errors in a `libkeccak_spec_t` - *  - * @param   spec  The specifications datastructure to check - * @return        Zero if error free, a `LIBKECCAK_SPEC_ERROR_*` if an error was found - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull, nothrow, unused, warn_unused_result, pure))) -static inline int -libkeccak_spec_check(const libkeccak_spec_t *restrict spec) -{ -	long state_size = spec->capacity + spec->bitrate; -	int32_t word_size = (int32_t)(state_size / 25); -	if (spec->bitrate <= 0)   return LIBKECCAK_SPEC_ERROR_BITRATE_NONPOSITIVE; -	if (spec->bitrate % 8)    return LIBKECCAK_SPEC_ERROR_BITRATE_MOD_8; -	if (spec->capacity <= 0)  return LIBKECCAK_SPEC_ERROR_CAPACITY_NONPOSITIVE; -	if (spec->capacity % 8)   return LIBKECCAK_SPEC_ERROR_CAPACITY_MOD_8; -	if (spec->output <= 0)    return LIBKECCAK_SPEC_ERROR_OUTPUT_NONPOSITIVE; -	if (state_size > 1600)    return LIBKECCAK_SPEC_ERROR_STATE_TOO_LARGE; -	if (state_size % 25)      return LIBKECCAK_SPEC_ERROR_STATE_MOD_25; -	if (word_size % 8)        return LIBKECCAK_SPEC_ERROR_WORD_MOD_8; - -	/* `(x & -x) != x` assumes two's complement, which of course is always -	 * satisfied by GCC, however C99 guarantees that `int32_t` exists, -	 * and it is basically the same thing as `long int`; with one important -	 * difference: it is guaranteed to use two's complement. */ -	if ((word_size & -word_size) != word_size) -		return LIBKECCAK_SPEC_ERROR_WORD_NON_2_POTENT; - -	return 0; -} - -#endif diff --git a/src/libkeccak/state.c b/src/libkeccak/state.c deleted file mode 100644 index c6360b7..0000000 --- a/src/libkeccak/state.c +++ /dev/null @@ -1,175 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include "state.h" - -#include <string.h> - - - -/** - * Initialise a state according to hashing specifications - *  - * @param   state  The state that should be initialised - * @param   spec   The specifications for the state - * @return         Zero on success, -1 on error - */ -int -libkeccak_state_initialise(libkeccak_state_t *restrict state, const libkeccak_spec_t *restrict spec) -{ -	long x; -	state->r = spec->bitrate; -	state->n = spec->output; -	state->c = spec->capacity; -	state->b = state->r + state->c; -	state->w = x = state->b / 25; -	state->l = 0; -	if (x & 0xF0L) state->l |= 4, x >>= 4; -	if (x & 0x0CL) state->l |= 2, x >>= 2; -	if (x & 0x02L) state->l |= 1; -	state->nr = 12 + (state->l << 1); -	state->wmod = (state->w == 64) ? ~0LL : (int64_t)((1ULL << state->w) - 1); -	for (x = 0; x < 25; x++) -		state->S[x] = 0; -	state->mptr = 0; -	state->mlen = (size_t)(state->r * state->b) >> 2; -	state->M = malloc(state->mlen * sizeof(char)); -	return state->M == NULL ? -1 : 0; -} - - -/** - * Wipe data in the state's message wihout freeing any data - *  - * @param  state  The state that should be wipe - */ -void -libkeccak_state_wipe_message(volatile libkeccak_state_t *restrict state) -{ -	volatile char *restrict M = state->M; -	size_t i; -	for (i = 0; i < state->mptr; i++) -		M[i] = 0; -} - -/** - * Wipe data in the state's sponge wihout freeing any data - *  - * @param  state  The state that should be wipe - */ -void -libkeccak_state_wipe_sponge(volatile libkeccak_state_t *restrict state) -{ -	volatile int64_t *restrict S = state->S; -	size_t i; -	for (i = 0; i < 25; i++) -		S[i] = 0; -} - -/** - * Wipe sensitive data wihout freeing any data - *  - * @param  state  The state that should be wipe - */ -void -libkeccak_state_wipe(volatile libkeccak_state_t *restrict state) -{ -	libkeccak_state_wipe_message(state); -	libkeccak_state_wipe_sponge(state); -} - - -/** - * Make a copy of a state - *  - * @param   dest  The slot for the duplicate, must not be initialised (memory leak otherwise) - * @param   src   The state to duplicate - * @return        Zero on success, -1 on error - */ -int -libkeccak_state_copy(libkeccak_state_t *restrict dest, const libkeccak_state_t *restrict src) -{ -	memcpy(dest, src, sizeof(libkeccak_state_t)); -	dest->M = malloc(src->mlen * sizeof(char)); -	if (!dest->M) -		return -1; -	memcpy(dest->M, src->M, src->mptr * sizeof(char)); -	return 0; -} - - -/** - * Marshal a `libkeccak_state_t` into a buffer - *  - * @param   state  The state to marshal - * @param   data   The output buffer - * @return         The number of bytes stored to `data` - */ -size_t -libkeccak_state_marshal(const libkeccak_state_t *restrict state, char *restrict data) -{ -#define set(type, var) *((type *)data) = state->var, data += sizeof(type) / sizeof(char) -	set(long, r); -	set(long, c); -	set(long, n); -	set(long, b); -	set(long, w); -	set(int64_t, wmod); -	set(long, l); -	set(long, nr); -	memcpy(data, state->S, sizeof(state->S)); -	data += sizeof(state->S) / sizeof(char); -	set(size_t, mptr); -	set(size_t, mlen); -	memcpy(data, state->M, state->mptr * sizeof(char)); -	data += state->mptr; -	return sizeof(libkeccak_state_t) - sizeof(char *) + state->mptr * sizeof(char); -#undef set -} - - -/** - * Unmarshal a `libkeccak_state_t` from a buffer - *  - * @param   state  The slot for the unmarshalled state, must not be initialised (memory leak otherwise) - * @param   data   The input buffer - * @return         The number of bytes read from `data`, 0 on error - */ -size_t -libkeccak_state_unmarshal(libkeccak_state_t *restrict state, const char *restrict data) -{ -#define get(type, var) state->var = *((const type *)data), data += sizeof(type) / sizeof(char) -	get(long, r); -	get(long, c); -	get(long, n); -	get(long, b); -	get(long, w); -	get(int64_t, wmod); -	get(long, l); -	get(long, nr); -	memcpy(state->S, data, sizeof(state->S)); -	data += sizeof(state->S) / sizeof(char); -	get(size_t, mptr); -	get(size_t, mlen); -	state->M = malloc(state->mptr * sizeof(char)); -	if (!state->M) -		return 0; -	memcpy(state->M, data, state->mptr * sizeof(char)); -	data += state->mptr; -	return sizeof(libkeccak_state_t) - sizeof(char *) + state->mptr * sizeof(char); -#undef get -} - - -/** - * Gets the number of bytes the `libkeccak_state_t` stored - * at the beginning of `data` occupies - *  - * @param   data  The data buffer - * @return        The byte size of the stored state - */ -size_t -libkeccak_state_unmarshal_skip(const char *restrict data) -{ -	data += (7 * sizeof(long) + 26 * sizeof(int64_t)) / sizeof(char); -	return sizeof(libkeccak_state_t) - sizeof(char *) + *(const size_t *)data * sizeof(char); -} - diff --git a/src/libkeccak/state.h b/src/libkeccak/state.h deleted file mode 100644 index 1c4b24e..0000000 --- a/src/libkeccak/state.h +++ /dev/null @@ -1,295 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#ifndef LIBKECCAK_STATE_H -#define LIBKECCAK_STATE_H 1 - -#include "spec.h" -#include "internal.h" - -#include <errno.h> -#include <stddef.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> - - - -/** - * Datastructure that describes the state of a hashing process - *  - * The `char`-size of the output hashsum is calculated by `(.n + 7) / 8` - */ -typedef struct libkeccak_state { -	/** -	 * The lanes (state/sponge) -	 */ -	int64_t S[25]; - -	/** -	 * The bitrate -	 */ -	long r; - -	/** -	 * The capacity -	 */ -	long c; - -	/** -	 * The output size -	 */ -	long n; - -	/** -	 * The state size -	 */ -	long b; - -	/** -	 * The word size -	 */ -	long w; - -	/** -	 * The word mask -	 */ -	int64_t wmod; - -	/** -	 * ℓ, the binary logarithm of the word size -	 */ -	long l; - -	/** -	 * 12 + 2ℓ, the number of rounds -	 */ -	long nr; - -	/** -	 * Pointer for `M` -	 */ -	size_t mptr; - -	/** -	 * Size of `M` -	 */ -	size_t mlen; - -	/** -	 * Left over water to fill the sponge with at next update -	 */ -	char *M; - -} libkeccak_state_t; - - - -/** - * Initialise a state according to hashing specifications - *  - * @param   state  The state that should be initialised - * @param   spec   The specifications for the state - * @return         Zero on success, -1 on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((leaf, nonnull))) -int libkeccak_state_initialise(libkeccak_state_t *restrict state, const libkeccak_spec_t *restrict spec); - - -/** - * Reset a state according to hashing specifications - *  - * @param  state  The state that should be reset - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull, nothrow, unused))) -static inline void -libkeccak_state_reset(libkeccak_state_t *restrict state) -{ -	state->mptr = 0; -	memset(state->S, 0, sizeof(state->S)); -} - - -/** - * Release resources allocation for a state without wiping sensitive data - *  - * @param  state  The state that should be destroyed - */ -static inline void -libkeccak_state_fast_destroy(libkeccak_state_t *restrict state) -{ -	if (state == NULL) -		return; -	free(state->M); -	state->M = NULL; -} - - -/** - * Wipe data in the state's message wihout freeing any data - *  - * @param  state  The state that should be wipe - */ -LIBKECCAK_GCC_ONLY(__attribute__((leaf, nonnull, nothrow, optimize("-O0")))) -void libkeccak_state_wipe_message(volatile libkeccak_state_t *restrict state); - -/** - * Wipe data in the state's sponge wihout freeing any data - *  - * @param  state  The state that should be wipe - */ -LIBKECCAK_GCC_ONLY(__attribute__((leaf, nonnull, nothrow, optimize("-O0")))) -void libkeccak_state_wipe_sponge(volatile libkeccak_state_t *restrict state); - -/** - * Wipe sensitive data wihout freeing any data - *  - * @param  state  The state that should be wipe - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull, nothrow, optimize("-O0")))) -void libkeccak_state_wipe(volatile libkeccak_state_t *restrict state); - - -/** - * Release resources allocation for a state and wipe sensitive data - *  - * @param  state  The state that should be destroyed - */ -LIBKECCAK_GCC_ONLY(__attribute__((unused, optimize("-O0")))) -static inline void -libkeccak_state_destroy(volatile libkeccak_state_t *restrict state) -{ -	if (!state) -		return; -	libkeccak_state_wipe(state); -	free(state->M); -	state->M = NULL; -} - - -/** - * Wrapper for `libkeccak_state_initialise` that also allocates the states - *  - * @param   spec  The specifications for the state - * @return        The state, `NULL` on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull, unused, warn_unused_result, malloc))) -static inline libkeccak_state_t * -libkeccak_state_create(const libkeccak_spec_t *restrict spec) -{ -	libkeccak_state_t *restrict state = malloc(sizeof(libkeccak_state_t)); -	if (!state || libkeccak_state_initialise(state, spec)) -		return free(state), NULL; -	return state; -} - - -/** - * Wrapper for `libkeccak_state_fast_destroy` that also frees the allocation of the state - *  - * @param  state  The state that should be freed - */ -LIBKECCAK_GCC_ONLY(__attribute__((unused))) -static inline void -libkeccak_state_fast_free(libkeccak_state_t *restrict state) -{ -	libkeccak_state_fast_destroy(state); -	free(state); -} - - -/** - * Wrapper for `libkeccak_state_destroy` that also frees the allocation of the state - *  - * @param  state  The state that should be freed - */ -LIBKECCAK_GCC_ONLY(__attribute__((unused, optimize("-O0")))) -static inline void -libkeccak_state_free(volatile libkeccak_state_t *restrict state) -{ -#ifdef __GNUC__ -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wcast-qual" -#endif -	libkeccak_state_destroy(state); -	free((libkeccak_state_t *)state); -#ifdef __GNUC__ -# pragma GCC diagnostic pop -#endif -} - - -/** - * Make a copy of a state - *  - * @param   dest  The slot for the duplicate, must not be initialised (memory leak otherwise) - * @param   src   The state to duplicate - * @return        Zero on success, -1 on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((leaf, nonnull))) -int libkeccak_state_copy(libkeccak_state_t *restrict dest, const libkeccak_state_t *restrict src); - - -/** - * A wrapper for `libkeccak_state_copy` that also allocates the duplicate - *  - * @param   src  The state to duplicate - * @return       The duplicate, `NULL` on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull, unused, warn_unused_result, malloc))) -static inline libkeccak_state_t * -libkeccak_state_duplicate(const libkeccak_state_t *restrict src) -{ -	libkeccak_state_t *restrict dest = malloc(sizeof(libkeccak_state_t)); -	if (!dest || libkeccak_state_copy(dest, src)) -		return libkeccak_state_free(dest), NULL; -	return dest; -} - - -/** - * Calculates the allocation size required for the second argument - * of `libkeccak_state_marshal` (`char* restrict data)`) - *  - * @param   state  The state as it will be marshalled by a subsequent call to `libkeccak_state_marshal` - * @return         The allocation size needed for the buffer to which the state will be marshalled - */ -LIBKECCAK_GCC_ONLY(__attribute__((nonnull, nothrow, unused, warn_unused_result, pure))) -static inline size_t -libkeccak_state_marshal_size(const libkeccak_state_t *restrict state) -{ -	return sizeof(libkeccak_state_t) - sizeof(char*) + state->mptr * sizeof(char); -} - - -/** - * Marshal a `libkeccak_state_t` into a buffer - *  - * @param   state  The state to marshal - * @param   data   The output buffer - * @return         The number of bytes stored to `data` - */ -LIBKECCAK_GCC_ONLY(__attribute__((leaf, nonnull, nothrow))) -size_t libkeccak_state_marshal(const libkeccak_state_t *restrict state, char *restrict data); - - -/** - * Unmarshal a `libkeccak_state_t` from a buffer - *  - * @param   state  The slot for the unmarshalled state, must not be initialised (memory leak otherwise) - * @param   data   The input buffer - * @return         The number of bytes read from `data`, 0 on error - */ -LIBKECCAK_GCC_ONLY(__attribute__((leaf, nonnull))) -size_t libkeccak_state_unmarshal(libkeccak_state_t *restrict state, const char *restrict data); - - -/** - * Gets the number of bytes the `libkeccak_state_t` stored - * at the beginning of `data` occupies - *  - * @param   data  The data buffer - * @return        The byte size of the stored state - */ -LIBKECCAK_GCC_ONLY(__attribute__((leaf, nonnull, nothrow, warn_unused_result, pure))) -size_t libkeccak_state_unmarshal_skip(const char *restrict data); - -#endif diff --git a/src/test.c b/src/test.c deleted file mode 100644 index 8394568..0000000 --- a/src/test.c +++ /dev/null @@ -1,662 +0,0 @@ -/* See LICENSE file for copyright and license details. */ -#include <libkeccak.h> - -#include <fcntl.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> - - -/** - * Test functions in <libkeccak/hex.h> - *  - * @return  Zero on success, -1 on error - */ -static int -test_hex(void) -{ -	const unsigned char bindata[] = {0x04, 0x2F, 0x12, 0x83, 0xFF, 0x80, 0xA3, 0x00}; -	const char hexdata_upper[] = "042F1283FF80A300"; -	const char hexdata_lower[] = "042f1283ff80a300"; -	char hextest[2 * 8 + 1]; - -	printf("Testing libkeccak_behex_lower: "); -	libkeccak_behex_lower(hextest, (const char*)bindata, 8); -	if (!strcmp(hextest, hexdata_lower)) -		printf("OK\n"); -	else -		return printf("Fail\n"), -1; - -	printf("Testing libkeccak_behex_upper: "); -	libkeccak_behex_upper(hextest, (const char*)bindata, 8); -	if (!strcmp(hextest, hexdata_upper)) -		printf("OK\n"); -	else -		return printf("Fail\n"), -1; - -	printf("Testing libkeccak_unhex on uppercase: "); -	libkeccak_unhex(hextest, hexdata_upper); -	if (!memcmp(bindata, hextest, 8 * sizeof(char))) -		printf("OK\n"); -	else -		return printf("Fail\n"), -1; - -	printf("Testing libkeccak_unhex on lowercase: "); -	libkeccak_unhex(hextest, hexdata_lower); -	if (!memcmp(bindata, hextest, 8 * sizeof(char))) -		printf("OK\n"); -	else -		return printf("Fail\n"), -1; - -	printf("\n"); -	return 0; -} - - -/** - * Test functions in <libkeccak/state.h> - *  - * @param   spec  The specifications for the state - * @return        Zero on success, -1 on error - */ -static int -test_state(libkeccak_spec_t *restrict spec) -{ -	libkeccak_state_t *restrict state; -	libkeccak_state_t *restrict state2; -	size_t marshal_size, marshalled_size, i, n; -	char *restrict marshalled_data; - -	if (state = libkeccak_state_create(spec), state == NULL) -		return perror("libkeccak_state_initialise"), -1; - -	n = state->mlen / 2; -	for (i = 0; i < n; i++) -		state->M[state->mptr++] = (char)(i & 255); - -	if (state2 = libkeccak_state_duplicate(state), state2 == NULL) -		return perror("libkeccak_state_duplicate"), -1; - -	if (state->M[state->mptr - 1] != state2->M[state2->mptr - 1]) -		return printf("Inconsistency found between original state and duplicate state.\n"), -1; - -	marshal_size = libkeccak_state_marshal_size(state2); -	if (marshalled_data = malloc(marshal_size), marshalled_data == NULL) -		return perror("malloc"), -1; - -	marshalled_size = libkeccak_state_marshal(state2, marshalled_data); -	if (marshalled_size != marshal_size) -		return printf("libkeccak_state_marshal returned an unexpected value.\n"), -1; - -	libkeccak_state_free(state); - -	if (state = malloc(sizeof(libkeccak_state_t)), state == NULL) -		return perror("malloc"), -1; -	marshalled_size = libkeccak_state_unmarshal(state, marshalled_data); -	if (marshalled_size == 0) -		return perror("libkeccak_state_unmarshal"), -1; -	if (marshalled_size != marshal_size) -		return printf("libkeccak_state_unmarshal returned an unexpected value.\n"), -1; - -	if (libkeccak_state_unmarshal_skip(marshalled_data) != marshal_size) -		return printf("libkeccak_state_unmarshal_skip returned an unexpected value.\n"), -1; - -	if (state->M[state->mptr - 1] != state2->M[state2->mptr - 1]) -		return printf("Inconsistency found between original state and unmarshalled state.\n"), -1; - -	free(marshalled_data); -	libkeccak_state_free(state); -	libkeccak_state_free(state2); -	return 0; -} - - -/** - * Run a test case for `libkeccak_digest` - *  - * @param   spec             The specification for the hashing - * @param   suffix           The message suffix (padding prefix) - * @param   msg              The message to digest - * @param   bits             Bits at the end of `message` that does not make up a whole byte - * @param   expected_answer  The expected answer, must be lowercase - * @return                   Zero on success, -1 on error - */ -static int -test_digest_case(const libkeccak_spec_t *restrict spec, const char *restrict suffix, -                 const char *restrict msg, long bits, const char *restrict expected_answer) -{ -	libkeccak_state_t state; -	char *restrict hashsum; -	char *restrict hexsum; -	int ok; - -	if (libkeccak_state_initialise(&state, spec)) -		return perror("libkeccak_state_initialise"), -1; -	if (hashsum = malloc((spec->output + 7) / 8), hashsum == NULL) -		return perror("malloc"), -1; -	if (hexsum = malloc((spec->output + 7) / 8 * 2 + 1), hexsum == NULL) -		return perror("malloc"), -1; - -	if (libkeccak_digest(&state, msg, strlen(msg) - !!bits, bits, suffix, hashsum)) -		return perror("libkeccak_digest"), -1; -	libkeccak_state_fast_destroy(&state); - -	libkeccak_behex_lower(hexsum, hashsum, (spec->output + 7) / 8); -	ok = !strcmp(hexsum, expected_answer); -	printf("%s%s\n", ok ? "OK" : "Fail: ", ok ? "" : hexsum); -	if (!ok) -		printf("  r, c, n = %li, %li, %li\n", spec->bitrate, spec->capacity, spec->output); - -	free(hashsum); -	free(hexsum); - -	return ok - 1; -} - - -/** - * Run test cases for `libkeccak_digest` - *  - * @return  Zero on success, -1 on error - */ -static int test_digest(void) -{ -#define sha3(output, message)\ -	(printf("  Testing SHA3-"#output"(%s): ", #message),\ -	 libkeccak_spec_sha3(&spec, output),\ -	 test_digest_case(&spec, LIBKECCAK_SHA3_SUFFIX, message, 0, answer)) - -#define keccak(output, message)\ -	(printf("  Testing Keccak-"#output"(%s): ", #message),\ -	 libkeccak_spec_sha3(&spec, output) /* sic! */,\ -	 test_digest_case(&spec, "", message, 0, answer)) - -#define keccak_bits(output, message, bits)\ -	(printf("  Testing Keccak-"#output"(%s-%i): ", #message, bits),\ -	 libkeccak_spec_sha3(&spec, output) /* sic! */,\ -	 test_digest_case(&spec, "", message, bits, answer)) - -#define rawshake(semicapacity, output, message)\ -	(printf("  Testing RawSHAKE-"#semicapacity"(%s, %i): ", #message, output),\ -	 libkeccak_spec_rawshake(&spec, semicapacity, output),\ -	 test_digest_case(&spec, LIBKECCAK_RAWSHAKE_SUFFIX, message, 0, answer)) - -#define rawshake_bits(semicapacity, output, message, bits)\ -	(printf("  Testing RawSHAKE-"#semicapacity"(%s-%i, %i): ", #message, bits, output),\ -	 libkeccak_spec_rawshake(&spec, semicapacity, output),\ -	 test_digest_case(&spec, LIBKECCAK_RAWSHAKE_SUFFIX, message, bits, answer)) - -#define shake(semicapacity, output, message)\ -	(printf("  Testing SHAKE-"#semicapacity"(%s, %i): ", #message, output),\ -	 libkeccak_spec_shake(&spec, semicapacity, output),\ -	 test_digest_case(&spec, LIBKECCAK_SHAKE_SUFFIX, message, 0, answer)) - -#define keccak_g(b, c, o, message)\ -	(printf("  Testing Keccak[%i,%i,%i](%s): ", b, c, o, #message),\ -	 spec.bitrate = b, spec.capacity = c, spec.output = o,\ -	 test_digest_case(&spec, "", message, 0, answer)) - - -	libkeccak_spec_t spec; -	const char *answer; - -	printf("Testing libkeccak_digest:\n"); - - -	answer = "6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7"; -	if (sha3(224, ""))  return -1; - -	answer = "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"; -	if (sha3(256, ""))  return -1; - -	answer = "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004"; -	if (sha3(384, ""))  return -1; - -	answer = "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a6" -		"15b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26"; -	if (sha3(512, ""))  return -1; - - -	answer = "f71837502ba8e10837bdd8d365adb85591895602fc552b48b7390abd"; -	if (keccak(224, ""))  return -1; - -	answer = "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"; -	if (keccak(256, ""))  return -1; - -	answer = "2c23146a63a29acf99e73b88f8c24eaa7dc60aa771780ccc006afbfa8fe2479b2dd2b21362337441ac12b515911957ff"; -	if (keccak(384, ""))  return -1; - -	answer = "0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304" -		"c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e"; -	if (keccak(512, ""))  return -1; - - -	answer = "22c8017ac8bcf65f59d1b7e92c9d4c6739d25e34ce5cb608b24ff096"; -	if (sha3(224, "withdrew hypothesis snakebird qmc2"))  return -1; - -	answer = "43808dde2662143dc4eed5dac5e98c74b06711829f02a3b121bd74f3"; -	if (sha3(224, "intensifierat sturdiness perl-image-exiftool vingla"))  return -1; - -	answer = "d32b4ac86065774dee5eb5cdd2f67b4e86501086d7373884e8b20a36"; -	if (sha3(224, "timjan avogadro uppdriven lib32-llvm-amdgpu-snapshot"))  return -1; - -	answer = "efbd76d45bfa952485148f8ad46143897f17c27ffdc8eb7287f9353b"; -	if (sha3(224, "grilo-plugins auditorium tull dissimilarity's"))  return -1; - -	answer = "6705aa36ecf58f333e0e6364ac1d0b7931d402e13282127cfd6f876c"; -	if (sha3(224, "royalty tt yellowstone deficiencies"))  return -1; - -	answer = "803a0ff09dda0df306e483a9f91b20a3dbbf9c2ebb8d0a3b28f3b9e0"; -	if (sha3(224, "kdegames-kdiamond tunisisk occurrence's outtalad"))  return -1; - -	answer = "a64779aca943a6aef1d2e7c9a0f4e997f4dabd1f77112a22121d3ed5"; -	if (sha3(224, "chevalier slat's spindel representations"))  return -1; - -	answer = "f0a3e0587af7723f0aa4719059d3f5107115a5b3667cd5209cc4d867"; -	if (sha3(224, "archery lexicographical equine veered"))  return -1; - -	answer = "312e7e3c6403ab1a086155fb9a52b22a3d0d257876afd2b93fb7272e"; -	if (sha3(224, "splay washbasin opposing there"))  return -1; - -	answer = "270ba05b764221ff5b5d94adfb4fdb1f36f07fe7c438904a5f3df071"; -	if (sha3(224, "faktum desist thundered klen"))  return -1; - - -	answer = "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"; -	if (keccak_bits(256, "\x02", 2))  return -1; - -	answer = "3a1108d4a90a31b85a10bdce77f4bfbdcc5b1d70dd405686f8bbde834aa1a410"; -	if (keccak_bits(256, "\x03", 2))  return -1; - -	answer = "46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762f"; -	if (keccak_bits(256, "\x0F", 4))  return -1; - - -	answer = "3a1108d4a90a31b85a10bdce77f4bfbd"; -	if (rawshake(256, 128, ""))  return -1; - -	answer = "46b9dd2b0ba88d13233b3feb743eeb24"; -	if (rawshake_bits(256, 128, "\x03", 2))  return -1; - -	answer = "46b9dd2b0ba88d13233b3feb743eeb24"; -	if (shake(256, 128, ""))  return -1; - - -	answer = "65070cdd6f91c0aadcfc470895a2606c828bce7ce3fa723418c9013de92253515713cce8" -	         "d2098be1c82df40b40e375549c0eeb655f92d718f01f147ba1c7c67844c7ba8b11492cd6"; -	if (keccak_g(1024, 1600 - 1024, 576, "capitol's kvistfri broadly raping"))  return -1; - -	answer = "65070cdd6f91c0aadcfc470895a2606c828bce7ce3fa723418c9013de92253515713cce8" -	         "d2098be1c82df40b40e375549c0eeb655f92d718f01f147ba1c7c67844c7ba8b11492cd6" -	         "143466958504c110522f772fe746573b1dc905f943ed1ec6ecf858575798596beeca4eb6" -	         "bb7bea635bcea6331315728fb57866370bf1ad5d"; -	if (keccak_g(1024, 1600 - 1024, 1024, "capitol's kvistfri broadly raping"))  return -1; - -	answer = "65070cdd6f91c0aadcfc470895a2606c828bce7ce3fa723418c9013de92253515713cce8" -	         "d2098be1c82df40b40e375549c0eeb655f92d718f01f147ba1c7c67844c7ba8b11492cd6" -	         "143466958504c110522f772fe746573b1dc905f943ed1ec6ecf858575798596beeca4eb6" -	         "bb7bea635bcea6331315728fb57866370bf1ad5decbc56d28d47ce53f18376d9f5531551" -	         "7a976d52dd3f98b7025e0b3c513c6d17d40462cddb5406d693bbe859a136af5375b5dd6e" -	         "3478934b00aa6cd44aa7ae2cd0271d83fbab699b"; -	if (keccak_g(1024, 1600 - 1024, 1600, "capitol's kvistfri broadly raping"))  return -1; - -	answer = "65070cdd6f91c0aadcfc470895a2606c828bce7ce3fa723418c9013de92253515713cce8" -	         "d2098be1c82df40b40e375549c0eeb655f92d718f01f147ba1c7c67844c7ba8b11492cd6" -	         "143466958504c110522f772fe746573b1dc905f943ed1ec6ecf858575798596beeca4eb6" -	         "bb7bea635bcea6331315728fb57866370bf1ad5decbc56d28d47ce53f18376d9f5531551" -	         "7a976d52dd3f98b7025e0b3c513c6d17d40462cddb5406d693bbe859a136af5375b5dd6e" -	         "3478934b00aa6cd44aa7ae2cd0271d83fbab699b9c"; -	if (keccak_g(1024, 1600 - 1024, 1608, "capitol's kvistfri broadly raping"))  return -1; - -	answer = "65070cdd6f91c0aadcfc470895a2606c828bce7ce3fa723418c9013de92253515713cce8" -	         "d2098be1c82df40b40e375549c0eeb655f92d718f01f147ba1c7c67844c7ba8b11492cd6" -	         "143466958504c110522f772fe746573b1dc905f943ed1ec6ecf858575798596beeca4eb6" -	         "bb7bea635bcea6331315728fb57866370bf1ad5decbc56d28d47ce53f18376d9f5531551" -	         "7a976d52dd3f98b7025e0b3c513c6d17d40462cddb5406d693bbe859a136af5375b5dd6e" -	         "3478934b00aa6cd44aa7ae2cd0271d83fbab699b9c58351bf7d26586b9c32282f1ac6356" -	         "1981b79791d7ab2b6e01f5b8e6cf0cab8b2076fd82bd99df015a602cdda5684162fea982" -	         "0f5a441c4620f549fbaf4e818201f292dbf4f6c9f82af8aa80b4124984da6f65b2874e0e" -	         "f01d042c08e9aedbb6ce4c10526e38c1a4e8b108c4f14b066f9d42640687b55124b081da" -	         "a9f9ae4232f313740b4fb787545dc19e7778f7082b3fa5824d2400c012be1a6c5ade7149" -	         "e452d310752fa9ebb964ab36fde0c8f46f47a0e2c9b20f24e3cca904bbedaa7ea176f662" -	         "33cd2d95"; -	if (keccak_g(1024, 1600 - 1024, 3200, "capitol's kvistfri broadly raping"))  return -1; - -	answer = "65070cdd6f91c0aadcfc470895a2606c828bce7ce3fa723418c9013de9225351"; -	if (keccak_g(1024, 1600 - 1024, 256, "capitol's kvistfri broadly raping"))  return -1; - -	answer = "e6f86ebc15b962f73f36f36fc8a84c3ae84b1c1023bfd4c5f1829389135aecc3"; -	if (keccak_g(512, 1600 - 512, 256, "capitol's kvistfri broadly raping"))  return -1; - -	answer = "420b97fc88962c87ec2adaa8f48d74d9ff4ea7ae7d691f9c33b8713ca1d3d573"; -	if (keccak_g(256, 1600 - 256, 256, "capitol's kvistfri broadly raping"))  return -1; - -	answer = "524790afbe4706d938b6f753e14104f556890e2a415e211b0564d60499db0333"; -	if (keccak_g(512, 800 - 512, 256, "capitol's kvistfri broadly raping"))  return -1; - -	answer = "04a6b4ad08b3018eefba0fb756272d949ac0f71c26f836d31dd13b28b884aa0f"; -	if (keccak_g(256, 800 - 256, 256, "capitol's kvistfri broadly raping"))  return -1; - -	answer = "d56f547791225e54460e6274ed31e57b7085820c11d65f1f322a16a3352c85ed"; -	if (keccak_g(256, 400 - 256, 256, "capitol's kvistfri broadly raping"))  return -1; - -	answer = "ceec066a57b9b31a5a0661df7bafec4183a26d0ed81e50bc958471f84fa347a7"; -	if (keccak_g(128, 400 - 128, 256, "capitol's kvistfri broadly raping"))  return -1; - -	answer = "b18f679c7105a72a993f70fa5adb3f17ef7ccffaffb4dc0f6fed74aa2f565194"; -	if (keccak_g(128, 200 - 128, 256, "capitol's kvistfri broadly raping"))  return -1; - -	answer = "9b845c1ecc2b1b3a48ba42ef29ccc4b348da8ab15074a870d8e799ca33c15e4b"; -	if (keccak_g(64, 200 - 64, 256, "capitol's kvistfri broadly raping"))  return -1; - - -	printf("\n"); -	return 0; - -#undef keccak_g -#undef shake -#undef rawshake_bits -#undef rawshake -#undef keccak_bits -#undef keccak -#undef sha3 -} - - -/** - * Run a test case for `libkeccak_update` - *  - * @param   spec             The specification for the hashing - * @param   suffix           The message suffix (padding prefix) - * @param   msg              The message to digest - * @param   expected_answer  The expected answer, must be lowercase - * @return                   Zero on success, -1 on error - */ -static int -test_update_case(const libkeccak_spec_t *restrict spec, const char *restrict suffix, -                 const char *restrict msg, const char *restrict expected_answer) -{ -	libkeccak_state_t state; -	char *restrict hashsum; -	char *restrict hexsum; -	int ok; - -	if (libkeccak_state_initialise(&state, spec)) -		return perror("libkeccak_state_initialise"), -1; -	if (hashsum = malloc((spec->output + 7) / 8), hashsum == NULL) -		return perror("malloc"), -1; -	if (hexsum = malloc((spec->output + 7) / 8 * 2 + 1), hexsum == NULL) -		return perror("malloc"), -1; - -	if (libkeccak_update(&state, msg, strlen(msg))) -		return perror("libkeccak_update"), -1; -	if (libkeccak_digest(&state, NULL, 0, 0, suffix, hashsum)) -		return perror("libkeccak_digest"), -1; -	libkeccak_state_fast_destroy(&state); - -	libkeccak_behex_lower(hexsum, hashsum, (spec->output + 7) / 8); -	ok = !strcmp(hexsum, expected_answer); -	printf("%s%s\n", ok ? "OK" : "Fail: ", ok ? "" : hexsum); -	if (!ok) -		printf("  r, c, n = %li, %li, %li\n", spec->bitrate, spec->capacity, spec->output); - -	free(hashsum); -	free(hexsum); - -	return ok - 1; -} - - -/** - * Run test cases for `libkeccak_update` - *  - * @return  Zero on success, -1 on error - */ -static int test_update(void) -{ -#define sha3(output, message)\ -	(printf("  Testing SHA3-"#output"(%s): ", #message),\ -	 libkeccak_spec_sha3(&spec, output),\ -	 test_update_case(&spec, LIBKECCAK_SHA3_SUFFIX, message, answer)) - -	libkeccak_spec_t spec; -	const char* answer; - -	printf("Testing libkeccak_update:\n"); - - -	answer = "22c8017ac8bcf65f59d1b7e92c9d4c6739d25e34ce5cb608b24ff096"; -	if (sha3(224, "withdrew hypothesis snakebird qmc2"))  return -1; - -	answer = "43808dde2662143dc4eed5dac5e98c74b06711829f02a3b121bd74f3"; -	if (sha3(224, "intensifierat sturdiness perl-image-exiftool vingla"))  return -1; - -	answer = "d32b4ac86065774dee5eb5cdd2f67b4e86501086d7373884e8b20a36"; -	if (sha3(224, "timjan avogadro uppdriven lib32-llvm-amdgpu-snapshot"))  return -1; - -	answer = "efbd76d45bfa952485148f8ad46143897f17c27ffdc8eb7287f9353b"; -	if (sha3(224, "grilo-plugins auditorium tull dissimilarity's"))  return -1; - -	answer = "6705aa36ecf58f333e0e6364ac1d0b7931d402e13282127cfd6f876c"; -	if (sha3(224, "royalty tt yellowstone deficiencies"))  return -1; - -	answer = "803a0ff09dda0df306e483a9f91b20a3dbbf9c2ebb8d0a3b28f3b9e0"; -	if (sha3(224, "kdegames-kdiamond tunisisk occurrence's outtalad"))  return -1; - -	answer = "a64779aca943a6aef1d2e7c9a0f4e997f4dabd1f77112a22121d3ed5"; -	if (sha3(224, "chevalier slat's spindel representations"))  return -1; - -	answer = "f0a3e0587af7723f0aa4719059d3f5107115a5b3667cd5209cc4d867"; -	if (sha3(224, "archery lexicographical equine veered"))  return -1; - -	answer = "312e7e3c6403ab1a086155fb9a52b22a3d0d257876afd2b93fb7272e"; -	if (sha3(224, "splay washbasin opposing there"))  return -1; - -	answer = "270ba05b764221ff5b5d94adfb4fdb1f36f07fe7c438904a5f3df071"; -	if (sha3(224, "faktum desist thundered klen"))  return -1; - - -	printf("\n"); -	return 0; - -#undef sha3 -} - - -/** - * Run a test for `libkeccak_*squeeze` functions - *  - * @param   state            The state whould should use, we will reset it - * @param   spec             The specification for the hashing - * @param   fast_squeezes    The number of fast squeezes to perform - * @param   squeezes         The number of extra squeezes to perform in total - * @param   fast_digest      Whether `libkeccak_digest` should do a fast squeeze rather than a slow squeeze - * @param   hashsum          A buffer in which we can used to store the binary hashsum - * @param   hexsum           A buffer in which we can used to store the hexadecimal hashsum - * @param   expected_answer  The hashum we expect, must be in lowercase hexadecimal - * @return                   Zero on success, -1 on error - */ -static int test_squeeze_case(libkeccak_state_t *restrict state, const libkeccak_spec_t *restrict spec, -                             long fast_squeezes, long squeezes, int fast_digest, char* restrict hashsum, -                             char *restrict hexsum, const char *restrict expected_answer) -{ -#define message "withdrew hypothesis snakebird qmc2" -	long i; -	int ok; - -	libkeccak_state_reset(state); -	if (libkeccak_digest(state, message, strlen(message), 0, LIBKECCAK_SHA3_SUFFIX, fast_digest ? NULL : hashsum)) -		return perror("libkeccak_digest"), -1; - -	libkeccak_fast_squeeze(state, fast_squeezes); -	for (i = fast_squeezes; i < squeezes; i++) -		libkeccak_squeeze(state, hashsum); - -	libkeccak_behex_lower(hexsum, hashsum, (spec->output + 7) / 8); -	ok = !strcmp(hexsum, expected_answer); -	printf("%s%s\n", ok ? "OK" : "Fail: ", ok ? "" : hexsum); -	if (!ok) -		printf("  r, c, n = %li, %li, %li\n", spec->bitrate, spec->capacity, spec->output); - -	return ok - 1; -#undef message -} - - -/** - * Test `libkeccak_*squeeze` functions - *  - * @return  Zero on success, -1 on error - */ -static int -test_squeeze(void) -{ -#define answer1 "03fe12b4b51d56d96377d927e5cd498fc4bc3aee389b2f2ff8393aa5" -#define answer2 "0b8fb64ee5d8836956f49cbe4577afbc638c855c1d553452fc1eceb8" -#define answer3 "1e03b4cd9eef3892a7b5e865fce393c4bc90120d9aea84d0a0dff3b8" -#define answer4 "aac92fbfd22ce62e83ddaf2e61bd7bf696326e46d1327defa4530e20" - -#define run_test(fast_squeezes, squeezes, fast_digest)\ -	test_squeeze_case(&state, &spec, fast_squeezes, squeezes, fast_digest, hashsum, hexsum, answer##squeezes) - -	libkeccak_spec_t spec; -	libkeccak_state_t state; -	char *restrict hashsum; -	char *restrict hexsum; - -	libkeccak_spec_sha3(&spec, 224); -	if (hashsum = malloc((spec.output + 7) / 8), hashsum == NULL) -		return perror("malloc"), -1; -	if (hexsum = malloc((spec.output + 7) / 8 * 2 + 1), hexsum == NULL) -		return perror("malloc"), -1; -	if (libkeccak_state_initialise(&state, &spec)) -		return perror("libkeccak_state_initialise"), -1; - -	printf("Testing squeeze functions with slow initial digest:\n"); -	printf("  1 extra squeeze,  including 0 fast squeezes: "), run_test(0, 1, 0); -	printf("  2 extra squeezes, including 0 fast squeezes: "), run_test(0, 2, 0); -	printf("  2 extra squeezes, including 1 fast squeeze:  "), run_test(1, 2, 0); -	printf("  3 extra squeezes, including 0 fast squeezes: "), run_test(0, 3, 0); -	printf("  3 extra squeezes, including 1 fast squeeze:  "), run_test(1, 3, 0); -	printf("  3 extra squeezes, including 2 fast squeezes: "), run_test(2, 3, 0); -	printf("  4 extra squeezes, including 0 fast squeezes: "), run_test(0, 4, 0); -	printf("  4 extra squeezes, including 1 fast squeeze:  "), run_test(1, 4, 0); -	printf("  4 extra squeezes, including 2 fast squeezes: "), run_test(2, 4, 0); -	printf("  4 extra squeezes, including 3 fast squeezes: "), run_test(3, 4, 0); -	printf("\n"); - -	printf("Testing squeeze functions with fast initial digest:\n"); -	printf("  1 extra squeeze,  including 0 fast squeezes: "), run_test(0, 1, 1); -	printf("  2 extra squeezes, including 0 fast squeezes: "), run_test(0, 2, 1); -	printf("  2 extra squeezes, including 1 fast squeeze:  "), run_test(1, 2, 1); -	printf("  3 extra squeezes, including 0 fast squeezes: "), run_test(0, 3, 1); -	printf("  3 extra squeezes, including 1 fast squeeze:  "), run_test(1, 3, 1); -	printf("  3 extra squeezes, including 2 fast squeezes: "), run_test(2, 3, 1); -	printf("  4 extra squeezes, including 0 fast squeezes: "), run_test(0, 4, 1); -	printf("  4 extra squeezes, including 1 fast squeeze:  "), run_test(1, 4, 1); -	printf("  4 extra squeezes, including 2 fast squeezes: "), run_test(2, 4, 1); -	printf("  4 extra squeezes, including 3 fast squeezes: "), run_test(3, 4, 1); -	printf("\n"); - -	libkeccak_state_fast_destroy(&state); -	free(hashsum); -	free(hexsum); -	return 0; - -#undef run_test -#undef answer4 -#undef answer3 -#undef answer2 -#undef answer1 -} - - - -/** - * Run a test for `libkeccak_generalised_sum_fd` - *  - * @param   spec             The specification for the hashing - * @param   suffix           The message suffix (padding prefix) - * @param   filename         The name of the file we should hash - * @param   expected_answer  The hashum we expect, must be in lowercase hexadecimal - * @return                   Zero on success, -1 on error - */ -static int -test_file(const libkeccak_spec_t *restrict spec, const char *restrict suffix, -          const char *restrict filename, const char *restrict expected_answer) -{ -	libkeccak_state_t state; -	char *restrict hashsum; -	char *restrict hexsum; -	int ok, fd; - -	printf("Testing libkeccak_generalised_sum_fd on %s: ", filename); - -	if (hashsum = malloc((spec->output + 7) / 8), hashsum == NULL) -		return perror("malloc"), -1; -	if (hexsum = malloc((spec->output + 7) / 8 * 2 + 1), hexsum == NULL) -		return perror("malloc"), -1; - -	if (fd = open(filename, O_RDONLY), fd < 0) -		return perror("open"), -1; - -	if (libkeccak_generalised_sum_fd(fd, &state, spec, suffix, hashsum)) -		return perror("libkeccak_generalised_sum_fd"), close(fd), -1; - -	libkeccak_behex_lower(hexsum, hashsum, (spec->output + 7) / 8); -	ok = !strcmp(hexsum, expected_answer); -	printf("%s%s\n", ok ? "OK" : "Fail: ", ok ? "" : hexsum); -	if (!ok) -		printf("  r, c, n = %li, %li, %li\n", spec->bitrate, spec->capacity, spec->output); - -	close(fd); -	free(hashsum); -	free(hexsum); -	libkeccak_state_fast_destroy(&state); -	return ok - 1; -} - - -/** - * Basically, verify the correctness of the library. - * The current working path must be the root directory - * of the repository (the project directory). - *  - * @return  Zero on success, 1 on failure or incorrectness - */ -int -main(void) -{ -	libkeccak_generalised_spec_t gspec; -	libkeccak_spec_t spec; - -	libkeccak_generalised_spec_initialise(&gspec); -	if (libkeccak_degeneralise_spec(&gspec, &spec)) -		return printf("libkeccak_degeneralise_spec failed with all members at automatic.\n"), 1; - -	printf("Resolution of default specification:\n"); -	printf("  bitrate:    %li\n", gspec.bitrate); -	printf("  capacity:   %li\n", gspec.capacity); -	printf("  output:     %li\n", gspec.output); -	printf("  state size: %li\n", gspec.state_size); -	printf("  word size:  %li\n", gspec.word_size); -	if (gspec.word_size * 25 != gspec.state_size)            return printf("Invalid information\n"), 1; -	if (gspec.bitrate + gspec.capacity != gspec.state_size)  return printf("Invalid information\n"), 1; -	if (gspec.state_size != 1600)                            return printf("Incorrect information\n"), 1; -	if (gspec.bitrate != gspec.output * 2)                   return printf("Incorrect information\n"), 1; -	if (gspec.output != 512)                                 return printf("Incorrect information\n"), 1; -	printf("\n"); - -	if (test_hex())         return 1; -	if (test_state(&spec))  return 1; -	if (test_digest())      return 1; -	if (test_update())      return 1; -	if (test_squeeze())     return 1; - -	if (test_file(&spec, LIBKECCAK_SHA3_SUFFIX, ".testfile", -	              "a95484492e9ade0f1d28f872d197ff45d891e85e78f918643f41d524c5d6ab0f" -	              "17974dc08ec82870b132612dcbeb062213bf594881dc764d6078865a7c694c57")) -		return 1; -   -	return 0; -} | 
