xref: /PHP-7.4/ext/hash/sha3/generic64lc/KeccakHash.c (revision 91663a92)
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 
Keccak_HashInitialize(Keccak_HashInstance * instance,unsigned int rate,unsigned int capacity,unsigned int hashbitlen,unsigned char delimitedSuffix)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 
Keccak_HashUpdate(Keccak_HashInstance * instance,const BitSequence * data,DataLength databitlen)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             unsigned char lastByte = data[databitlen/8];
46             /* Concatenate the last few bits provided here with those of the suffix */
47             unsigned short delimitedLastBytes = (unsigned short)((unsigned short)lastByte | ((unsigned short)instance->delimitedSuffix << (databitlen % 8)));
48             if ((delimitedLastBytes & 0xFF00) == 0x0000) {
49                 instance->delimitedSuffix = delimitedLastBytes & 0xFF;
50             }
51             else {
52                 unsigned char oneByte[1];
53                 oneByte[0] = delimitedLastBytes & 0xFF;
54                 ret = (HashReturn)KeccakWidth1600_SpongeAbsorb(&instance->sponge, oneByte, 1);
55                 instance->delimitedSuffix = (delimitedLastBytes >> 8) & 0xFF;
56             }
57         }
58         return ret;
59     }
60 }
61 
62 /* ---------------------------------------------------------------- */
63 
Keccak_HashFinal(Keccak_HashInstance * instance,BitSequence * hashval)64 HashReturn Keccak_HashFinal(Keccak_HashInstance *instance, BitSequence *hashval)
65 {
66     HashReturn ret = (HashReturn)KeccakWidth1600_SpongeAbsorbLastFewBits(&instance->sponge, instance->delimitedSuffix);
67     if (ret == SUCCESS)
68         return (HashReturn)KeccakWidth1600_SpongeSqueeze(&instance->sponge, hashval, instance->fixedOutputLength/8);
69     else
70         return ret;
71 }
72 
73 /* ---------------------------------------------------------------- */
74 
Keccak_HashSqueeze(Keccak_HashInstance * instance,BitSequence * data,DataLength databitlen)75 HashReturn Keccak_HashSqueeze(Keccak_HashInstance *instance, BitSequence *data, DataLength databitlen)
76 {
77     if ((databitlen % 8) != 0)
78         return FAIL;
79     return (HashReturn)KeccakWidth1600_SpongeSqueeze(&instance->sponge, data, databitlen/8);
80 }
81