1 /* 2 Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni, 3 Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby 4 denoted as "the implementer". 5 6 For more information, feedback or questions, please refer to our websites: 7 http://keccak.noekeon.org/ 8 http://keyak.noekeon.org/ 9 http://ketje.noekeon.org/ 10 11 To the extent possible under law, the implementer has waived all copyright 12 and related or neighboring rights to the source code in this file. 13 http://creativecommons.org/publicdomain/zero/1.0/ 14 */ 15 16 #include <string.h> 17 #include "KeccakHash.h" 18 19 /* ---------------------------------------------------------------- */ 20 21 HashReturn Keccak_HashInitialize(Keccak_HashInstance *instance, unsigned int rate, unsigned int capacity, unsigned int hashbitlen, unsigned char delimitedSuffix) 22 { 23 HashReturn result; 24 25 if (delimitedSuffix == 0) 26 return FAIL; 27 result = (HashReturn)KeccakWidth1600_SpongeInitialize(&instance->sponge, rate, capacity); 28 if (result != SUCCESS) 29 return result; 30 instance->fixedOutputLength = hashbitlen; 31 instance->delimitedSuffix = delimitedSuffix; 32 return SUCCESS; 33 } 34 35 /* ---------------------------------------------------------------- */ 36 37 HashReturn Keccak_HashUpdate(Keccak_HashInstance *instance, const BitSequence *data, DataLength databitlen) 38 { 39 if ((databitlen % 8) == 0) 40 return (HashReturn)KeccakWidth1600_SpongeAbsorb(&instance->sponge, data, databitlen/8); 41 else { 42 HashReturn ret = (HashReturn)KeccakWidth1600_SpongeAbsorb(&instance->sponge, data, databitlen/8); 43 if (ret == SUCCESS) { 44 /* The last partial byte is assumed to be aligned on the least significant bits */ 45 46 unsigned char lastByte = data[databitlen/8]; 47 /* Concatenate the last few bits provided here with those of the suffix */ 48 49 unsigned short delimitedLastBytes = (unsigned short)((unsigned short)lastByte | ((unsigned short)instance->delimitedSuffix << (databitlen % 8))); 50 if ((delimitedLastBytes & 0xFF00) == 0x0000) { 51 instance->delimitedSuffix = delimitedLastBytes & 0xFF; 52 } 53 else { 54 unsigned char oneByte[1]; 55 oneByte[0] = delimitedLastBytes & 0xFF; 56 ret = (HashReturn)KeccakWidth1600_SpongeAbsorb(&instance->sponge, oneByte, 1); 57 instance->delimitedSuffix = (delimitedLastBytes >> 8) & 0xFF; 58 } 59 } 60 return ret; 61 } 62 } 63 64 /* ---------------------------------------------------------------- */ 65 66 HashReturn Keccak_HashFinal(Keccak_HashInstance *instance, BitSequence *hashval) 67 { 68 HashReturn ret = (HashReturn)KeccakWidth1600_SpongeAbsorbLastFewBits(&instance->sponge, instance->delimitedSuffix); 69 if (ret == SUCCESS) 70 return (HashReturn)KeccakWidth1600_SpongeSqueeze(&instance->sponge, hashval, instance->fixedOutputLength/8); 71 else 72 return ret; 73 } 74 75 /* ---------------------------------------------------------------- */ 76 77 HashReturn Keccak_HashSqueeze(Keccak_HashInstance *instance, BitSequence *data, DataLength databitlen) 78 { 79 if ((databitlen % 8) != 0) 80 return FAIL; 81 return (HashReturn)KeccakWidth1600_SpongeSqueeze(&instance->sponge, data, databitlen/8); 82 } 83