On Tue, 09 Jan 2018 16:47:18 +0100, Daniel Loebenberger wrote: > Changes have been made to libc, and a suite of sha3 checksum tools > were added (sha3-224, sha3-256, sha3-384, sha-512), extending the > existing md5(1) checksum tool. > > The SHA3 implementation itself was taken from the reference code written > by the Keccak Team (https://keccak.team/) which is available under public > domain (CC0). > > We'd be happy to see this in OpenBSD and appreciate any comments.
Looks good in general, some comments inline. - todd > Index: include/sha3.h > =================================================================== > RCS file: include/sha3.h > diff -N include/sha3.h > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ include/sha3.h 9 Jan 2018 15:17:42 -0000 > @@ -0,0 +1,76 @@ > +#ifndef _SHA3_H > +#define _SHA3_H > + > +#define SHA3_224_DIGEST_LENGTH 28 > +#define SHA3_224_DIGEST_STRING_LENGTH (SHA3_224_DIGEST_LENGTH * 2 + 1 > ) > + > +#define SHA3_256_DIGEST_LENGTH 32 > +#define SHA3_256_DIGEST_STRING_LENGTH (SHA3_256_DIGEST_LENGTH * 2 + 1 > ) > + > +#define SHA3_384_DIGEST_LENGTH 48 > +#define SHA3_384_DIGEST_STRING_LENGTH (SHA3_384_DIGEST_LENGTH * 2 + 1 > ) > + > +#define SHA3_512_DIGEST_LENGTH 64 > +#define SHA3_512_DIGEST_STRING_LENGTH (SHA3_512_DIGEST_LENGTH * 2 + 1 > ) > + > +#define SHA3_STATE_SIZE 1600 / 8 This should be parenthesized, i.e. (1600 / 8) > + > + > +typedef struct _SHA3_CTX { > + unsigned char state[SHA3_STATE_SIZE]; > + unsigned int rate; > + unsigned int byteIOIndex; > + unsigned int fixedOutputLength; > +} SHA3_CTX; > + > + > +void SHA3_224Init(SHA3_CTX *); > +char *SHA3_224End(SHA3_CTX *, char *) > + __attribute__((__bounded__(__minbytes__,2,SHA3_224_DIGEST_STRING_LENGTH > ))); > +char *SHA3_224File(const char *, char *) > + __attribute__((__bounded__(__minbytes__,2,SHA3_224_DIGEST_STRING_LENGTH > ))); > +char *SHA3_224FileChunk(const char *, char *, off_t, off_t) > + __attribute__((__bounded__(__minbytes__,2,SHA3_224_DIGEST_STRING_LENGTH > ))); > +char *SHA3_224Data(const u_int8_t *, size_t, char *) > + __attribute__((__bounded__(__string__,1,2))) > + __attribute__((__bounded__(__minbytes__,3,SHA3_224_DIGEST_STRING_LENGTH > ))); > + > +void SHA3_256Init(SHA3_CTX *); > +char *SHA3_256End(SHA3_CTX *, char *) > + __attribute__((__bounded__(__minbytes__,2,SHA3_256_DIGEST_STRING_LENGTH > ))); > +char *SHA3_256File(const char *, char *) > + __attribute__((__bounded__(__minbytes__,2,SHA3_256_DIGEST_STRING_LENGTH > ))); > +char *SHA3_256FileChunk(const char *, char *, off_t, off_t) > + __attribute__((__bounded__(__minbytes__,2,SHA3_256_DIGEST_STRING_LENGTH > ))); > +char *SHA3_256Data(const u_int8_t *, size_t, char *) > + __attribute__((__bounded__(__string__,1,2))) > + __attribute__((__bounded__(__minbytes__,3,SHA3_256_DIGEST_STRING_LENGTH > ))); > + > +void SHA3_384Init(SHA3_CTX *); > +char *SHA3_384End(SHA3_CTX *, char *) > + __attribute__((__bounded__(__minbytes__,2,SHA3_384_DIGEST_STRING_LENGTH > ))); > +char *SHA3_384File(const char *, char *) > + __attribute__((__bounded__(__minbytes__,2,SHA3_384_DIGEST_STRING_LENGTH > ))); > +char *SHA3_384FileChunk(const char *, char *, off_t, off_t) > + __attribute__((__bounded__(__minbytes__,2,SHA3_384_DIGEST_STRING_LENGTH > ))); > +char *SHA3_384Data(const u_int8_t *, size_t, char *) > + __attribute__((__bounded__(__string__,1,2))) > + __attribute__((__bounded__(__minbytes__,3,SHA3_384_DIGEST_STRING_LENGTH > ))); > + > +void SHA3_512Init(SHA3_CTX *); > +char *SHA3_512End(SHA3_CTX *, char *) > + __attribute__((__bounded__(__minbytes__,2,SHA3_512_DIGEST_STRING_LENGTH > ))); > +char *SHA3_512File(const char *, char *) > + __attribute__((__bounded__(__minbytes__,2,SHA3_512_DIGEST_STRING_LENGTH > ))); > +char *SHA3_512FileChunk(const char *, char *, off_t, off_t) > + __attribute__((__bounded__(__minbytes__,2,SHA3_512_DIGEST_STRING_LENGTH > ))); > +char *SHA3_512Data(const u_int8_t *, size_t, char *) > + __attribute__((__bounded__(__string__,1,2))) > + __attribute__((__bounded__(__minbytes__,3,SHA3_512_DIGEST_STRING_LENGTH > ))); > + > +void SHA3_Update(SHA3_CTX *, const u_int8_t *, size_t) > + __attribute__((__bounded__(__string__,2,3))); > +void SHA3_Final(u_int8_t [SHA3_224_DIGEST_LENGTH], SHA3_CTX *) > + __attribute__((__bounded__(__minbytes__,1,SHA3_224_DIGEST_LENGTH))); > + > +#endif /* _SHA3_H */ > Index: lib/libc/hash/sha3.c > =================================================================== > RCS file: lib/libc/hash/sha3.c > diff -N lib/libc/hash/sha3.c > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ lib/libc/hash/sha3.c 9 Jan 2018 15:17:42 -0000 > @@ -0,0 +1,756 @@ > +/* > + * Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido > Bertoni, > + * Joan Daemen, Micha�l Peeters, Gilles Van Assche and Ronny Van Keer, > hereby > + * denoted as "the implementer". > + * > + * For more information, feedback or questions, please refer to our > websites: > + * http://keccak.noekeon.org/ > + * http://keyak.noekeon.org/ > + * http://ketje.noekeon.org/ > + * > + * Adaptation to OpenBSD in 2017/18 by > + * Alexander von Gernler, Daniel Loebenberger and Stefan-Lukas Gazdag > + * https://www.genua.de/ > + * also denoted as "the implementer" > + * > + * To the extent possible under law, the implementer has waived all > copyright > + * and related or neighboring rights to the source code in this file. > + * http://creativecommons.org/publicdomain/zero/1.0/ > + */ > + > +#include <assert.h> > +#include <sys/types.h> > +#include <string.h> > +#include <strings.h> > +#include <sha3.h> > + > +typedef unsigned long long tKeccakLane; > + > +#define SHA3_NRROUNDS 24 > +#define SHA3_NRLANES 25 > +#define SHA3_DELIMITER 0x06 > + > +#define index(x, y) (((x)%5)+5*((y)%5)) > + > +const tKeccakLane KeccakRoundConstants[SHA3_NRROUNDS] = > +{ > + 0x0000000000000001, > + 0x0000000000008082, > + 0x800000000000808a, > + 0x8000000080008000, > + 0x000000000000808b, > + 0x0000000080000001, > + 0x8000000080008081, > + 0x8000000000008009, > + 0x000000000000008a, > + 0x0000000000000088, > + 0x0000000080008009, > + 0x000000008000000a, > + 0x000000008000808b, > + 0x800000000000008b, > + 0x8000000000008089, > + 0x8000000000008003, > + 0x8000000000008002, > + 0x8000000000000080, > + 0x000000000000800a, > + 0x800000008000000a, > + 0x8000000080008081, > + 0x8000000000008080, > + 0x0000000080000001, > + 0x8000000080008008, > +}; > + > +const unsigned int KeccakRhoOffsets[SHA3_NRLANES] = > +{ > + 0, 1, 62, 28, 27, 36, 44, 6, 55, 20, 3, 10, 43, > + 25, 39, 41, 45, 15, 21, 8, 18, 2, 61, 56, 14 > +}; > + > +/* > + * unused, but these constance denote the one implementation out of the > + * Keccak Code Package that was taken here > + */ > +#define KeccakP1600_implementation "64-bit reference implementation" > +#define KeccakP1600_stateSizeInBytes 200 > +#define KeccakP1600_stateAlignment 8 > + > +/* prototypes for local functions */ > +static void KeccakP1600_AddByte(void *state, unsigned char data, > + unsigned int offset); > +static void KeccakP1600_AddBytes(void *state, const unsigned char *data, > + unsigned int offset, unsigned int length); > +static void KeccakP1600_Permute_24rounds(void *state); > +static void KeccakP1600_ExtractBytes(const void *state, unsigned char *data, > + unsigned int offset, unsigned int length); > +static void Keccak_HashInitialize(SHA3_CTX *, unsigned int, unsigned int); > + > + > +/* > + * interface functions external use > + * (rate + capacity) = 1600, > + * thus the rate specifies the capacity > + */ > +void > +SHA3_224Init(SHA3_CTX *context) > +{ > + /* rate = 1152, output width 224 bit */ > + Keccak_HashInitialize(context, 1152, 224); > +} > + > +void > +SHA3_256Init(SHA3_CTX *context) > +{ > + /* rate = 1088, output width 256 bit */ > + Keccak_HashInitialize(context, 1088, 256); > +} > + > +void > +SHA3_384Init(SHA3_CTX *context) > +{ > + /* rate = 832, output width 384 bit */ > + Keccak_HashInitialize(context, 832, 384); > +} > + > +void > +SHA3_512Init(SHA3_CTX *context) > +{ > + /* rate = 576, output width 512 bit */ > + Keccak_HashInitialize(context, 576, 512); > +} > + > + > +void > +SHA3_Update(SHA3_CTX *context, const u_int8_t *data, size_t len) > +{ > + size_t i, j; > + unsigned int partialBlock; > + const unsigned char *curData; > + unsigned int rateInBytes; > + rateInBytes = context->rate/8; > + > + i = 0; > + curData = data; > + while(i < len) { > + if ((context->byteIOIndex == 0) && (len >= (i + rateInBytes))) > { > +#ifdef SnP_FastLoop_Absorb > + /* processing full blocks first */ > + if ((rateInBytes % (KeccakP1600_width/200)) == 0) { > + /* fast lane: whole lane rate */ > + j = KeccakP1600_FastLoop_Absorb(context->state, > + rateInBytes/(KeccakP1600_width/200), curDat > a, len - i); > + i += j; > + curData += j; > + } > + else { > +#endif > + for(j=len-i; j>=rateInBytes; j-=rateInBytes) { > + #ifdef KeccakReference > + displayBytes(1, "Block to be absorbed", > curData, rateInBytes); > + #endif The '#' for the #ifdef/#endif should be at the start of the line. > + KeccakP1600_AddBytes(context->state, cu > rData, 0, rateInBytes); > + KeccakP1600_Permute_24rounds(context->s > tate); > + curData+=rateInBytes; > + } > + i = len - j; > +#ifdef SnP_FastLoop_Absorb > + } > +#endif > + } > + else { > + /* normal lane: using the message queue */ > + partialBlock = (unsigned int)(len - i); > + if (partialBlock+context->byteIOIndex > rateInBytes) > + partialBlock = rateInBytes-context->byteIOIndex > ; > + #ifdef KeccakReference > + displayBytes(1, "Block to be absorbed (part)", curData, > partialBlock); > + #endif The '#' for the #ifdef/#endif should be at the start of the line. > + i += partialBlock; > + > + KeccakP1600_AddBytes(context->state, curData, context-> > byteIOIndex, > partialBlock); > + curData += partialBlock; > + context->byteIOIndex += partialBlock; > + if (context->byteIOIndex == rateInBytes) { > + KeccakP1600_Permute_24rounds(context->state); > + context->byteIOIndex = 0; > + } > + } > + } > +} > + > +void > +SHA3_Final(u_int8_t* digest, SHA3_CTX *context) > +{ > + size_t i, j; > + unsigned int partialBlock; > + unsigned char *curData; > + unsigned int rateInBytes; > + size_t dataByteLen; > + > + rateInBytes = context->rate/8; > + dataByteLen = context->fixedOutputLength/8; > + > + /* Last few bits, whose delimiter coincides with first bit of padding * > / > + KeccakP1600_AddByte(context->state, SHA3_DELIMITER, context->byteIOInde > x); > + > + /* > + * If the first bit of padding is at position rate-1, we need a whole > + * new block for the second bit of padding > + */ > + /* Second bit of padding */ > + KeccakP1600_AddByte(context->state, 0x80, rateInBytes-1); > + > + KeccakP1600_Permute_24rounds(context->state); > + context->byteIOIndex = 0; > + > + /* SQUEEZE */ > + i = 0; > + curData = digest; > + while(i < dataByteLen) { > + if ((context->byteIOIndex == rateInBytes) && (dataByteLen >= (i > + > rateInBytes))) { > + for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) { > + KeccakP1600_Permute_24rounds(context->state); > + KeccakP1600_ExtractBytes(context->state, curDat > a, 0, rateInBytes); > + curData+=rateInBytes; > + } > + i = dataByteLen - j; > + } > + else { > + /* normal lane: using the message queue */ > + if (context->byteIOIndex == rateInBytes) { > + KeccakP1600_Permute_24rounds(context->state); > + context->byteIOIndex = 0; > + } > + partialBlock = (unsigned int)(dataByteLen - i); > + if (partialBlock+context->byteIOIndex > rateInBytes) > + partialBlock = rateInBytes-context->byteIOIndex > ; > + i += partialBlock; > + > + KeccakP1600_ExtractBytes(context->state, curData, conte > xt->byteIOIndex, > partialBlock); > + curData += partialBlock; > + context->byteIOIndex += partialBlock; > + } > + } > +} > + > +/* > + * internal functions > + */ > +static void > +Keccak_HashInitialize(SHA3_CTX *context, unsigned int rate, > + unsigned int hashbitlen) > +{ > + bzero(context->state, SHA3_STATE_SIZE); > + context->rate = rate; > + context->byteIOIndex = 0; > + context->fixedOutputLength = hashbitlen; > +} > + > +static void > +KeccakP1600_AddByte(void *state, unsigned char byte, unsigned int offset) > +{ > + assert(offset < 200); > + ((unsigned char *)state)[offset] ^= byte; > +} > + > +static void > +KeccakP1600_AddBytes(void *state, const unsigned char *data, unsigned int > offset, unsigned int length) > +{ > + unsigned int i; > + > + assert(offset < 200); > + assert(offset+length <= 200); > + for(i=0; i<length; i++) > + ((unsigned char *)state)[offset+i] ^= data[i]; > +} > + > +#if BYTE_ORDER == BIG_ENDIAN > +static void fromBytesToWords(tKeccakLane *stateAsWords, const unsigned char > *state); > +static void fromWordsToBytes(unsigned char *state, const tKeccakLane > *stateAsWords); > +#endif > +static void KeccakP1600OnWords(tKeccakLane *state); > +#if BYTE_ORDER == LITTLE_ENDIAN > +static void KeccakP1600QuadRound(tKeccakLane *state, unsigned int > indexRound); > +#else > +static void KeccakP1600RoundSlow(tKeccakLane *state, unsigned int > indexRound); > +static void theta(tKeccakLane *A); > +static void rho(tKeccakLane *A); > +static void pi(tKeccakLane *A); > +static void chi(tKeccakLane *A); > +static void iota(tKeccakLane *A, unsigned int indexRound); > +#endif > + > +static void > +KeccakP1600_Permute_24rounds(void *state) > +{ > +#if BYTE_ORDER == LITTLE_ENDIAN > + KeccakP1600OnWords((tKeccakLane*)state); > +#else > + tKeccakLane stateAsWords[1600/64]; > + > + fromBytesToWords(stateAsWords, (const unsigned char *)state); > + KeccakP1600OnWords(stateAsWords); > + fromWordsToBytes((unsigned char *)state, stateAsWords); > +#endif > +} > + > +#if BYTE_ORDER == BIG_ENDIAN > +static void > +fromBytesToWords(tKeccakLane *stateAsWords, const unsigned char *state) > +{ > + unsigned int i, j; > + > + for(i=0; i<SHA3_NRLANES; i++) { > + stateAsWords[i] = 0; > + for(j=0; j<(64/8); j++) > + stateAsWords[i] |= (tKeccakLane)(state[i*(64/8)+j]) << > (8*j); > + } > +} > + > +static void > +fromWordsToBytes(unsigned char *state, const tKeccakLane *stateAsWords) > +{ > + unsigned int i, j; > + > + for(i=0; i<SHA3_NRLANES; i++) > + for(j=0; j<(64/8); j++) > + state[i*(64/8)+j] = (unsigned char)((stateAsWords[i] >> > (8*j)) & 0xFF); > +} > +#endif > + > +static void > +KeccakP1600OnWords(tKeccakLane *state) > +{ > + unsigned int i; > + > + > +#if BYTE_ORDER == BIG_ENDIAN > + /* > + * Use the unoptimized reference implementation when > + * on big endian machines > + */ > + for(i=0; i<SHA3_NRROUNDS; i++) > + KeccakP1600RoundSlow(state, i); > +#else > + /* > + * Use the inplace version from the Keccak optimized reference > + * code of KeccakP1600 on little endian machines > + * Note that this routine does four rounds in one call. > + * */ > + for(i=0; i<SHA3_NRROUNDS; i+=4) > + KeccakP1600QuadRound(state, i); > +#endif > +} > + > +#define ROL64(a, offset) ((offset != 0) ? ((((tKeccakLane)a) << offset) ^ > (((tKeccakLane)a) >> (64-offset))) : a) > + > +#if BYTE_ORDER == LITTLE_ENDIAN > +static void > +KeccakP1600QuadRound(tKeccakLane *state, unsigned int indexRound) > +{ > + /* > + * Inplace implementation by Ronny Van Keer and the designers > + * of Keccak from the optimized Keccak reference code > + */ > + > + tKeccakLane Ba, Be, Bi, Bo, Bu; > + tKeccakLane Ca, Ce, Ci, Co, Cu; > + tKeccakLane Da, De, Di, Do, Du; > + > + #define Aba state[ 0] > + #define Abe state[ 1] > + #define Abi state[ 2] > + #define Abo state[ 3] > + #define Abu state[ 4] > + #define Aga state[ 5] > + #define Age state[ 6] > + #define Agi state[ 7] > + #define Ago state[ 8] > + #define Agu state[ 9] > + #define Aka state[10] > + #define Ake state[11] > + #define Aki state[12] > + #define Ako state[13] > + #define Aku state[14] > + #define Ama state[15] > + #define Ame state[16] > + #define Ami state[17] > + #define Amo state[18] > + #define Amu state[19] > + #define Asa state[20] > + #define Ase state[21] > + #define Asi state[22] > + #define Aso state[23] > + #define Asu state[24] The '#' for the #defines should be at the start of the line. > + > + > + Ca = Aba^Aga^Aka^Ama^Asa; > + Ce = Abe^Age^Ake^Ame^Ase; > + Ci = Abi^Agi^Aki^Ami^Asi; > + Co = Abo^Ago^Ako^Amo^Aso; > + Cu = Abu^Agu^Aku^Amu^Asu; > + Da = Cu^ROL64(Ce, 1); > + De = Ca^ROL64(Ci, 1); > + Di = Ce^ROL64(Co, 1); > + Do = Ci^ROL64(Cu, 1); > + Du = Co^ROL64(Ca, 1); > + > + Ba = (Aba^Da); > + Be = ROL64((Age^De), 44); > + Bi = ROL64((Aki^Di), 43); > + Bo = ROL64((Amo^Do), 21); > + Bu = ROL64((Asu^Du), 14); > + Aba = Ba ^((~Be)& Bi ); > + Aba ^= KeccakRoundConstants[indexRound]; > + Age = Be ^((~Bi)& Bo ); > + Aki = Bi ^((~Bo)& Bu ); > + Amo = Bo ^((~Bu)& Ba ); > + Asu = Bu ^((~Ba)& Be ); > + > + Bi = ROL64((Aka^Da), 3); > + Bo = ROL64((Ame^De), 45); > + Bu = ROL64((Asi^Di), 61); > + Ba = ROL64((Abo^Do), 28); > + Be = ROL64((Agu^Du), 20); > + Aka = Ba ^((~Be)& Bi ); > + Ame = Be ^((~Bi)& Bo ); > + Asi = Bi ^((~Bo)& Bu ); > + Abo = Bo ^((~Bu)& Ba ); > + Agu = Bu ^((~Ba)& Be ); > + > + Bu = ROL64((Asa^Da), 18); > + Ba = ROL64((Abe^De), 1); > + Be = ROL64((Agi^Di), 6); > + Bi = ROL64((Ako^Do), 25); > + Bo = ROL64((Amu^Du), 8); > + Asa = Ba ^((~Be)& Bi ); > + Abe = Be ^((~Bi)& Bo ); > + Agi = Bi ^((~Bo)& Bu ); > + Ako = Bo ^((~Bu)& Ba ); > + Amu = Bu ^((~Ba)& Be ); > + > + Be = ROL64((Aga^Da), 36); > + Bi = ROL64((Ake^De), 10); > + Bo = ROL64((Ami^Di), 15); > + Bu = ROL64((Aso^Do), 56); > + Ba = ROL64((Abu^Du), 27); > + Aga = Ba ^((~Be)& Bi ); > + Ake = Be ^((~Bi)& Bo ); > + Ami = Bi ^((~Bo)& Bu ); > + Aso = Bo ^((~Bu)& Ba ); > + Abu = Bu ^((~Ba)& Be ); > + > + Bo = ROL64((Ama^Da), 41); > + Bu = ROL64((Ase^De), 2); > + Ba = ROL64((Abi^Di), 62); > + Be = ROL64((Ago^Do), 55); > + Bi = ROL64((Aku^Du), 39); > + Ama = Ba ^((~Be)& Bi ); > + Ase = Be ^((~Bi)& Bo ); > + Abi = Bi ^((~Bo)& Bu ); > + Ago = Bo ^((~Bu)& Ba ); > + Aku = Bu ^((~Ba)& Be ); > + > + Ca = Aba^Aka^Asa^Aga^Ama; > + Ce = Age^Ame^Abe^Ake^Ase; > + Ci = Aki^Asi^Agi^Ami^Abi; > + Co = Amo^Abo^Ako^Aso^Ago; > + Cu = Asu^Agu^Amu^Abu^Aku; > + Da = Cu^ROL64(Ce, 1); > + De = Ca^ROL64(Ci, 1); > + Di = Ce^ROL64(Co, 1); > + Do = Ci^ROL64(Cu, 1); > + Du = Co^ROL64(Ca, 1); > + > + Ba = (Aba^Da); > + Be = ROL64((Ame^De), 44); > + Bi = ROL64((Agi^Di), 43); > + Bo = ROL64((Aso^Do), 21); > + Bu = ROL64((Aku^Du), 14); > + Aba = Ba ^((~Be)& Bi ); > + Aba ^= KeccakRoundConstants[indexRound+1]; > + Ame = Be ^((~Bi)& Bo ); > + Agi = Bi ^((~Bo)& Bu ); > + Aso = Bo ^((~Bu)& Ba ); > + Aku = Bu ^((~Ba)& Be ); > + > + Bi = ROL64((Asa^Da), 3); > + Bo = ROL64((Ake^De), 45); > + Bu = ROL64((Abi^Di), 61); > + Ba = ROL64((Amo^Do), 28); > + Be = ROL64((Agu^Du), 20); > + Asa = Ba ^((~Be)& Bi ); > + Ake = Be ^((~Bi)& Bo ); > + Abi = Bi ^((~Bo)& Bu ); > + Amo = Bo ^((~Bu)& Ba ); > + Agu = Bu ^((~Ba)& Be ); > + > + Bu = ROL64((Ama^Da), 18); > + Ba = ROL64((Age^De), 1); > + Be = ROL64((Asi^Di), 6); > + Bi = ROL64((Ako^Do), 25); > + Bo = ROL64((Abu^Du), 8); > + Ama = Ba ^((~Be)& Bi ); > + Age = Be ^((~Bi)& Bo ); > + Asi = Bi ^((~Bo)& Bu ); > + Ako = Bo ^((~Bu)& Ba ); > + Abu = Bu ^((~Ba)& Be ); > + > + Be = ROL64((Aka^Da), 36); > + Bi = ROL64((Abe^De), 10); > + Bo = ROL64((Ami^Di), 15); > + Bu = ROL64((Ago^Do), 56); > + Ba = ROL64((Asu^Du), 27); > + Aka = Ba ^((~Be)& Bi ); > + Abe = Be ^((~Bi)& Bo ); > + Ami = Bi ^((~Bo)& Bu ); > + Ago = Bo ^((~Bu)& Ba ); > + Asu = Bu ^((~Ba)& Be ); > + > + Bo = ROL64((Aga^Da), 41); > + Bu = ROL64((Ase^De), 2); > + Ba = ROL64((Aki^Di), 62); > + Be = ROL64((Abo^Do), 55); > + Bi = ROL64((Amu^Du), 39); > + Aga = Ba ^((~Be)& Bi ); > + Ase = Be ^((~Bi)& Bo ); > + Aki = Bi ^((~Bo)& Bu ); > + Abo = Bo ^((~Bu)& Ba ); > + Amu = Bu ^((~Ba)& Be ); > + > + Ca = Aba^Asa^Ama^Aka^Aga; > + Ce = Ame^Ake^Age^Abe^Ase; > + Ci = Agi^Abi^Asi^Ami^Aki; > + Co = Aso^Amo^Ako^Ago^Abo; > + Cu = Aku^Agu^Abu^Asu^Amu; > + Da = Cu^ROL64(Ce, 1); > + De = Ca^ROL64(Ci, 1); > + Di = Ce^ROL64(Co, 1); > + Do = Ci^ROL64(Cu, 1); > + Du = Co^ROL64(Ca, 1); > + > + Ba = (Aba^Da); > + Be = ROL64((Ake^De), 44); > + Bi = ROL64((Asi^Di), 43); > + Bo = ROL64((Ago^Do), 21); > + Bu = ROL64((Amu^Du), 14); > + Aba = Ba ^((~Be)& Bi ); > + Aba ^= KeccakRoundConstants[indexRound+2]; > + Ake = Be ^((~Bi)& Bo ); > + Asi = Bi ^((~Bo)& Bu ); > + Ago = Bo ^((~Bu)& Ba ); > + Amu = Bu ^((~Ba)& Be ); > + > + Bi = ROL64((Ama^Da), 3); > + Bo = ROL64((Abe^De), 45); > + Bu = ROL64((Aki^Di), 61); > + Ba = ROL64((Aso^Do), 28); > + Be = ROL64((Agu^Du), 20); > + Ama = Ba ^((~Be)& Bi ); > + Abe = Be ^((~Bi)& Bo ); > + Aki = Bi ^((~Bo)& Bu ); > + Aso = Bo ^((~Bu)& Ba ); > + Agu = Bu ^((~Ba)& Be ); > + > + Bu = ROL64((Aga^Da), 18); > + Ba = ROL64((Ame^De), 1); > + Be = ROL64((Abi^Di), 6); > + Bi = ROL64((Ako^Do), 25); > + Bo = ROL64((Asu^Du), 8); > + Aga = Ba ^((~Be)& Bi ); > + Ame = Be ^((~Bi)& Bo ); > + Abi = Bi ^((~Bo)& Bu ); > + Ako = Bo ^((~Bu)& Ba ); > + Asu = Bu ^((~Ba)& Be ); > + > + Be = ROL64((Asa^Da), 36); > + Bi = ROL64((Age^De), 10); > + Bo = ROL64((Ami^Di), 15); > + Bu = ROL64((Abo^Do), 56); > + Ba = ROL64((Aku^Du), 27); > + Asa = Ba ^((~Be)& Bi ); > + Age = Be ^((~Bi)& Bo ); > + Ami = Bi ^((~Bo)& Bu ); > + Abo = Bo ^((~Bu)& Ba ); > + Aku = Bu ^((~Ba)& Be ); > + > + Bo = ROL64((Aka^Da), 41); > + Bu = ROL64((Ase^De), 2); > + Ba = ROL64((Agi^Di), 62); > + Be = ROL64((Amo^Do), 55); > + Bi = ROL64((Abu^Du), 39); > + Aka = Ba ^((~Be)& Bi ); > + Ase = Be ^((~Bi)& Bo ); > + Agi = Bi ^((~Bo)& Bu ); > + Amo = Bo ^((~Bu)& Ba ); > + Abu = Bu ^((~Ba)& Be ); > + > + Ca = Aba^Ama^Aga^Asa^Aka; > + Ce = Ake^Abe^Ame^Age^Ase; > + Ci = Asi^Aki^Abi^Ami^Agi; > + Co = Ago^Aso^Ako^Abo^Amo; > + Cu = Amu^Agu^Asu^Aku^Abu; > + Da = Cu^ROL64(Ce, 1); > + De = Ca^ROL64(Ci, 1); > + Di = Ce^ROL64(Co, 1); > + Do = Ci^ROL64(Cu, 1); > + Du = Co^ROL64(Ca, 1); > + > + Ba = (Aba^Da); > + Be = ROL64((Abe^De), 44); > + Bi = ROL64((Abi^Di), 43); > + Bo = ROL64((Abo^Do), 21); > + Bu = ROL64((Abu^Du), 14); > + Aba = Ba ^((~Be)& Bi ); > + Aba ^= KeccakRoundConstants[indexRound+3]; > + Abe = Be ^((~Bi)& Bo ); > + Abi = Bi ^((~Bo)& Bu ); > + Abo = Bo ^((~Bu)& Ba ); > + Abu = Bu ^((~Ba)& Be ); > + > + Bi = ROL64((Aga^Da), 3); > + Bo = ROL64((Age^De), 45); > + Bu = ROL64((Agi^Di), 61); > + Ba = ROL64((Ago^Do), 28); > + Be = ROL64((Agu^Du), 20); > + Aga = Ba ^((~Be)& Bi ); > + Age = Be ^((~Bi)& Bo ); > + Agi = Bi ^((~Bo)& Bu ); > + Ago = Bo ^((~Bu)& Ba ); > + Agu = Bu ^((~Ba)& Be ); > + > + Bu = ROL64((Aka^Da), 18); > + Ba = ROL64((Ake^De), 1); > + Be = ROL64((Aki^Di), 6); > + Bi = ROL64((Ako^Do), 25); > + Bo = ROL64((Aku^Du), 8); > + Aka = Ba ^((~Be)& Bi ); > + Ake = Be ^((~Bi)& Bo ); > + Aki = Bi ^((~Bo)& Bu ); > + Ako = Bo ^((~Bu)& Ba ); > + Aku = Bu ^((~Ba)& Be ); > + > + Be = ROL64((Ama^Da), 36); > + Bi = ROL64((Ame^De), 10); > + Bo = ROL64((Ami^Di), 15); > + Bu = ROL64((Amo^Do), 56); > + Ba = ROL64((Amu^Du), 27); > + Ama = Ba ^((~Be)& Bi ); > + Ame = Be ^((~Bi)& Bo ); > + Ami = Bi ^((~Bo)& Bu ); > + Amo = Bo ^((~Bu)& Ba ); > + Amu = Bu ^((~Ba)& Be ); > + > + Bo = ROL64((Asa^Da), 41); > + Bu = ROL64((Ase^De), 2); > + Ba = ROL64((Asi^Di), 62); > + Be = ROL64((Aso^Do), 55); > + Bi = ROL64((Asu^Du), 39); > + Asa = Ba ^((~Be)& Bi ); > + Ase = Be ^((~Bi)& Bo ); > + Asi = Bi ^((~Bo)& Bu ); > + Aso = Bo ^((~Bu)& Ba ); > + Asu = Bu ^((~Ba)& Be ); > + > + #undef Aba > + #undef Abe > + #undef Abi > + #undef Abo > + #undef Abu > + #undef Aga > + #undef Age > + #undef Agi > + #undef Ago > + #undef Agu > + #undef Aka > + #undef Ake > + #undef Aki > + #undef Ako > + #undef Aku > + #undef Ama > + #undef Ame > + #undef Ami > + #undef Amo > + #undef Amu > + #undef Asa > + #undef Ase > + #undef Asi > + #undef Aso > + #undef Asu The '#' for the #undefs should be at the start of the line. > +} > + > +#else /* BYTE_ORDER != BIG_ENDIAN */ > +void > +KeccakP1600RoundSlow(tKeccakLane *state, unsigned int indexRound) > +{ > + theta(state); > + rho(state); > + pi(state); > + chi(state); > + iota(state, indexRound); > +} > + > +#define ROL64(a, offset) ((offset != 0) ? ((((tKeccakLane)a) << offset) ^ > (((tKeccakLane)a) >> (64-offset))) : a) > + > +static void theta(tKeccakLane *A) > +{ > + unsigned int x, y; > + tKeccakLane C[5], D[5]; > + > + for(x=0; x<5; x++) { > + C[x] = 0; > + for(y=0; y<5; y++) > + C[x] ^= A[index(x, y)]; > + } > + for(x=0; x<5; x++) > + D[x] = ROL64(C[(x+1)%5], 1) ^ C[(x+4)%5]; > + for(x=0; x<5; x++) > + for(y=0; y<5; y++) > + A[index(x, y)] ^= D[x]; > +} > + > +static void rho(tKeccakLane *A) > +{ > + unsigned int x, y; > + > + for(x=0; x<5; x++) for(y=0; y<5; y++) > + A[index(x, y)] = ROL64(A[index(x, y)], KeccakRhoOffsets[index(x > , y)]); > +} > + > +static void pi(tKeccakLane *A) > +{ > + unsigned int x, y; > + tKeccakLane tempA[25]; > + > + for(x=0; x<5; x++) for(y=0; y<5; y++) > + tempA[index(x, y)] = A[index(x, y)]; > + for(x=0; x<5; x++) for(y=0; y<5; y++) > + A[index(0*x+1*y, 2*x+3*y)] = tempA[index(x, y)]; > +} > + > +static void chi(tKeccakLane *A) > +{ > + unsigned int x, y; > + tKeccakLane C[5]; > + > + for(y=0; y<5; y++) { > + for(x=0; x<5; x++) > + C[x] = A[index(x, y)] ^ ((~A[index(x+1, y)]) & A[index( > x+2, y)]); > + for(x=0; x<5; x++) > + A[index(x, y)] = C[x]; > + } > +} > + > +static void iota(tKeccakLane *A, unsigned int indexRound) > +{ > + A[index(0, 0)] ^= KeccakRoundConstants[indexRound]; > +} > +#endif /* BYTE_ORDER != BIG_ENDIAN */ > + > +static void > +KeccakP1600_ExtractBytes(const void *state, unsigned char *data, unsigned in > t > offset, unsigned int length) > +{ > + assert(offset < 200); > + assert(offset+length <= 200); > + memcpy(data, (unsigned char*)state+offset, length); > +} > + > Index: lib/libc/hidden/sha3.h > =================================================================== > RCS file: lib/libc/hidden/sha3.h > diff -N lib/libc/hidden/sha3.h > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ lib/libc/hidden/sha3.h 9 Jan 2018 15:17:42 -0000 > @@ -0,0 +1,76 @@ > +#ifndef _SHA3_H > +#define _SHA3_H > + > +#define SHA3_224_DIGEST_LENGTH 28 > +#define SHA3_224_DIGEST_STRING_LENGTH (SHA3_224_DIGEST_LENGTH * 2 + 1 > ) > + > +#define SHA3_256_DIGEST_LENGTH 32 > +#define SHA3_256_DIGEST_STRING_LENGTH (SHA3_256_DIGEST_LENGTH * 2 + 1 > ) > + > +#define SHA3_384_DIGEST_LENGTH 48 > +#define SHA3_384_DIGEST_STRING_LENGTH (SHA3_384_DIGEST_LENGTH * 2 + 1 > ) > + > +#define SHA3_512_DIGEST_LENGTH 64 > +#define SHA3_512_DIGEST_STRING_LENGTH (SHA3_512_DIGEST_LENGTH * 2 + 1 > ) > + > +#define SHA3_STATE_SIZE 1600 / 8 > + > + > +typedef struct _SHA3_CTX { > + unsigned char state[SHA3_STATE_SIZE]; > + unsigned int rate; > + unsigned int byteIOIndex; > + unsigned int fixedOutputLength; > +} SHA3_CTX; > + > + > +void SHA3_224Init(SHA3_CTX *); > +char *SHA3_224End(SHA3_CTX *, char *) > + __attribute__((__bounded__(__minbytes__,2,SHA3_224_DIGEST_STRING_LENGTH > ))); > +char *SHA3_224File(const char *, char *) > + __attribute__((__bounded__(__minbytes__,2,SHA3_224_DIGEST_STRING_LENGTH > ))); > +char *SHA3_224FileChunk(const char *, char *, off_t, off_t) > + __attribute__((__bounded__(__minbytes__,2,SHA3_224_DIGEST_STRING_LENGTH > ))); > +char *SHA3_224Data(const u_int8_t *, size_t, char *) > + __attribute__((__bounded__(__string__,1,2))) > + __attribute__((__bounded__(__minbytes__,3,SHA3_224_DIGEST_STRING_LENGTH > ))); > + > +void SHA3_256Init(SHA3_CTX *); > +char *SHA3_256End(SHA3_CTX *, char *) > + __attribute__((__bounded__(__minbytes__,2,SHA3_256_DIGEST_STRING_LENGTH > ))); > +char *SHA3_256File(const char *, char *) > + __attribute__((__bounded__(__minbytes__,2,SHA3_256_DIGEST_STRING_LENGTH > ))); > +char *SHA3_256FileChunk(const char *, char *, off_t, off_t) > + __attribute__((__bounded__(__minbytes__,2,SHA3_256_DIGEST_STRING_LENGTH > ))); > +char *SHA3_256Data(const u_int8_t *, size_t, char *) > + __attribute__((__bounded__(__string__,1,2))) > + __attribute__((__bounded__(__minbytes__,3,SHA3_256_DIGEST_STRING_LENGTH > ))); > + > +void SHA3_384Init(SHA3_CTX *); > +char *SHA3_384End(SHA3_CTX *, char *) > + __attribute__((__bounded__(__minbytes__,2,SHA3_384_DIGEST_STRING_LENGTH > ))); > +char *SHA3_384File(const char *, char *) > + __attribute__((__bounded__(__minbytes__,2,SHA3_384_DIGEST_STRING_LENGTH > ))); > +char *SHA3_384FileChunk(const char *, char *, off_t, off_t) > + __attribute__((__bounded__(__minbytes__,2,SHA3_384_DIGEST_STRING_LENGTH > ))); > +char *SHA3_384Data(const u_int8_t *, size_t, char *) > + __attribute__((__bounded__(__string__,1,2))) > + __attribute__((__bounded__(__minbytes__,3,SHA3_384_DIGEST_STRING_LENGTH > ))); > + > +void SHA3_512Init(SHA3_CTX *); > +char *SHA3_512End(SHA3_CTX *, char *) > + __attribute__((__bounded__(__minbytes__,2,SHA3_512_DIGEST_STRING_LENGTH > ))); > +char *SHA3_512File(const char *, char *) > + __attribute__((__bounded__(__minbytes__,2,SHA3_512_DIGEST_STRING_LENGTH > ))); > +char *SHA3_512FileChunk(const char *, char *, off_t, off_t) > + __attribute__((__bounded__(__minbytes__,2,SHA3_512_DIGEST_STRING_LENGTH > ))); > +char *SHA3_512Data(const u_int8_t *, size_t, char *) > + __attribute__((__bounded__(__string__,1,2))) > + __attribute__((__bounded__(__minbytes__,3,SHA3_512_DIGEST_STRING_LENGTH > ))); > + > +void SHA3_Update(SHA3_CTX *, const u_int8_t *, size_t) > + __attribute__((__bounded__(__string__,2,3))); > +void SHA3_Final(u_int8_t [SHA3_224_DIGEST_LENGTH], SHA3_CTX *) > + __attribute__((__bounded__(__minbytes__,1,SHA3_224_DIGEST_LENGTH))); > + > +#endif /* _SHA3_H */ The hidden version of sha3.h should include the real sha3.h and use the PROTO_NORMAL macro for each exported function. - todd