KeccakSponge.inc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  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. For more information, feedback or questions, please refer to our websites:
  6. http://keccak.noekeon.org/
  7. http://keyak.noekeon.org/
  8. http://ketje.noekeon.org/
  9. To the extent possible under law, the implementer has waived all copyright
  10. and related or neighboring rights to the source code in this file.
  11. http://creativecommons.org/publicdomain/zero/1.0/
  12. */
  13. #define JOIN0(a, b) a ## b
  14. #define JOIN(a, b) JOIN0(a, b)
  15. #define Sponge JOIN(prefix, _Sponge)
  16. #define SpongeInstance JOIN(prefix, _SpongeInstance)
  17. #define SpongeInitialize JOIN(prefix, _SpongeInitialize)
  18. #define SpongeAbsorb JOIN(prefix, _SpongeAbsorb)
  19. #define SpongeAbsorbLastFewBits JOIN(prefix, _SpongeAbsorbLastFewBits)
  20. #define SpongeSqueeze JOIN(prefix, _SpongeSqueeze)
  21. #define SnP_stateSizeInBytes JOIN(SnP, _stateSizeInBytes)
  22. #define SnP_stateAlignment JOIN(SnP, _stateAlignment)
  23. #define SnP_StaticInitialize JOIN(SnP, _StaticInitialize)
  24. #define SnP_Initialize JOIN(SnP, _Initialize)
  25. #define SnP_AddByte JOIN(SnP, _AddByte)
  26. #define SnP_AddBytes JOIN(SnP, _AddBytes)
  27. #define SnP_ExtractBytes JOIN(SnP, _ExtractBytes)
  28. int Sponge(unsigned int rate, unsigned int capacity, const unsigned char *input, size_t inputByteLen, unsigned char suffix, unsigned char *output, size_t outputByteLen)
  29. {
  30. ALIGN(SnP_stateAlignment) unsigned char state[SnP_stateSizeInBytes];
  31. unsigned int partialBlock;
  32. const unsigned char *curInput = input;
  33. unsigned char *curOutput = output;
  34. unsigned int rateInBytes = rate/8;
  35. if (rate+capacity != SnP_width)
  36. return 1;
  37. if ((rate <= 0) || (rate > SnP_width) || ((rate % 8) != 0))
  38. return 1;
  39. if (suffix == 0)
  40. return 1;
  41. /* Initialize the state */
  42. SnP_StaticInitialize();
  43. SnP_Initialize(state);
  44. /* First, absorb whole blocks */
  45. #ifdef SnP_FastLoop_Absorb
  46. if (((rateInBytes % (SnP_width/200)) == 0) && (inputByteLen >= rateInBytes)) {
  47. /* fast lane: whole lane rate */
  48. size_t j;
  49. j = SnP_FastLoop_Absorb(state, rateInBytes/(SnP_width/200), curInput, inputByteLen);
  50. curInput += j;
  51. inputByteLen -= j;
  52. }
  53. #endif
  54. while(inputByteLen >= (size_t)rateInBytes) {
  55. #ifdef KeccakReference
  56. displayBytes(1, "Block to be absorbed", curInput, rateInBytes);
  57. #endif
  58. SnP_AddBytes(state, curInput, 0, rateInBytes);
  59. SnP_Permute(state);
  60. curInput += rateInBytes;
  61. inputByteLen -= rateInBytes;
  62. }
  63. /* Then, absorb what remains */
  64. partialBlock = (unsigned int)inputByteLen;
  65. #ifdef KeccakReference
  66. displayBytes(1, "Block to be absorbed (part)", curInput, partialBlock);
  67. #endif
  68. SnP_AddBytes(state, curInput, 0, partialBlock);
  69. /* Finally, absorb the suffix */
  70. #ifdef KeccakReference
  71. {
  72. unsigned char delimitedData1[1];
  73. delimitedData1[0] = suffix;
  74. displayBytes(1, "Block to be absorbed (last few bits + first bit of padding)", delimitedData1, 1);
  75. }
  76. #endif
  77. /* Last few bits, whose delimiter coincides with first bit of padding */
  78. SnP_AddByte(state, suffix, partialBlock);
  79. /* If the first bit of padding is at position rate-1, we need a whole new block for the second bit of padding */
  80. if ((suffix >= 0x80) && (partialBlock == (rateInBytes-1)))
  81. SnP_Permute(state);
  82. /* Second bit of padding */
  83. SnP_AddByte(state, 0x80, rateInBytes-1);
  84. #ifdef KeccakReference
  85. {
  86. unsigned char block[SnP_width/8];
  87. memset(block, 0, SnP_width/8);
  88. block[rateInBytes-1] = 0x80;
  89. displayBytes(1, "Second bit of padding", block, rateInBytes);
  90. }
  91. #endif
  92. SnP_Permute(state);
  93. #ifdef KeccakReference
  94. displayText(1, "--- Switching to squeezing phase ---");
  95. #endif
  96. /* First, output whole blocks */
  97. while(outputByteLen > (size_t)rateInBytes) {
  98. SnP_ExtractBytes(state, curOutput, 0, rateInBytes);
  99. SnP_Permute(state);
  100. #ifdef KeccakReference
  101. displayBytes(1, "Squeezed block", curOutput, rateInBytes);
  102. #endif
  103. curOutput += rateInBytes;
  104. outputByteLen -= rateInBytes;
  105. }
  106. /* Finally, output what remains */
  107. partialBlock = (unsigned int)outputByteLen;
  108. SnP_ExtractBytes(state, curOutput, 0, partialBlock);
  109. #ifdef KeccakReference
  110. displayBytes(1, "Squeezed block (part)", curOutput, partialBlock);
  111. #endif
  112. return 0;
  113. }
  114. /* ---------------------------------------------------------------- */
  115. /* ---------------------------------------------------------------- */
  116. /* ---------------------------------------------------------------- */
  117. int SpongeInitialize(SpongeInstance *instance, unsigned int rate, unsigned int capacity)
  118. {
  119. if (rate+capacity != SnP_width)
  120. return 1;
  121. if ((rate <= 0) || (rate > SnP_width) || ((rate % 8) != 0))
  122. return 1;
  123. SnP_StaticInitialize();
  124. SnP_Initialize(instance->state);
  125. instance->rate = rate;
  126. instance->byteIOIndex = 0;
  127. instance->squeezing = 0;
  128. return 0;
  129. }
  130. /* ---------------------------------------------------------------- */
  131. int SpongeAbsorb(SpongeInstance *instance, const unsigned char *data, size_t dataByteLen)
  132. {
  133. size_t i, j;
  134. unsigned int partialBlock;
  135. const unsigned char *curData;
  136. unsigned int rateInBytes = instance->rate/8;
  137. if (instance->squeezing)
  138. return 1; /* Too late for additional input */
  139. i = 0;
  140. curData = data;
  141. while(i < dataByteLen) {
  142. if ((instance->byteIOIndex == 0) && (dataByteLen-i >= rateInBytes)) {
  143. #ifdef SnP_FastLoop_Absorb
  144. /* processing full blocks first */
  145. if ((rateInBytes % (SnP_width/200)) == 0) {
  146. /* fast lane: whole lane rate */
  147. j = SnP_FastLoop_Absorb(instance->state, rateInBytes/(SnP_width/200), curData, dataByteLen - i);
  148. i += j;
  149. curData += j;
  150. }
  151. else {
  152. #endif
  153. for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) {
  154. #ifdef KeccakReference
  155. displayBytes(1, "Block to be absorbed", curData, rateInBytes);
  156. #endif
  157. SnP_AddBytes(instance->state, curData, 0, rateInBytes);
  158. SnP_Permute(instance->state);
  159. curData+=rateInBytes;
  160. }
  161. i = dataByteLen - j;
  162. #ifdef SnP_FastLoop_Absorb
  163. }
  164. #endif
  165. }
  166. else {
  167. /* normal lane: using the message queue */
  168. if (dataByteLen-i > rateInBytes-instance->byteIOIndex)
  169. partialBlock = rateInBytes-instance->byteIOIndex;
  170. else
  171. partialBlock = (unsigned int)(dataByteLen - i);
  172. #ifdef KeccakReference
  173. displayBytes(1, "Block to be absorbed (part)", curData, partialBlock);
  174. #endif
  175. i += partialBlock;
  176. SnP_AddBytes(instance->state, curData, instance->byteIOIndex, partialBlock);
  177. curData += partialBlock;
  178. instance->byteIOIndex += partialBlock;
  179. if (instance->byteIOIndex == rateInBytes) {
  180. SnP_Permute(instance->state);
  181. instance->byteIOIndex = 0;
  182. }
  183. }
  184. }
  185. return 0;
  186. }
  187. /* ---------------------------------------------------------------- */
  188. int SpongeAbsorbLastFewBits(SpongeInstance *instance, unsigned char delimitedData)
  189. {
  190. unsigned int rateInBytes = instance->rate/8;
  191. if (delimitedData == 0)
  192. return 1;
  193. if (instance->squeezing)
  194. return 1; /* Too late for additional input */
  195. #ifdef KeccakReference
  196. {
  197. unsigned char delimitedData1[1];
  198. delimitedData1[0] = delimitedData;
  199. displayBytes(1, "Block to be absorbed (last few bits + first bit of padding)", delimitedData1, 1);
  200. }
  201. #endif
  202. /* Last few bits, whose delimiter coincides with first bit of padding */
  203. SnP_AddByte(instance->state, delimitedData, instance->byteIOIndex);
  204. /* If the first bit of padding is at position rate-1, we need a whole new block for the second bit of padding */
  205. if ((delimitedData >= 0x80) && (instance->byteIOIndex == (rateInBytes-1)))
  206. SnP_Permute(instance->state);
  207. /* Second bit of padding */
  208. SnP_AddByte(instance->state, 0x80, rateInBytes-1);
  209. #ifdef KeccakReference
  210. {
  211. unsigned char block[SnP_width/8];
  212. memset(block, 0, SnP_width/8);
  213. block[rateInBytes-1] = 0x80;
  214. displayBytes(1, "Second bit of padding", block, rateInBytes);
  215. }
  216. #endif
  217. SnP_Permute(instance->state);
  218. instance->byteIOIndex = 0;
  219. instance->squeezing = 1;
  220. #ifdef KeccakReference
  221. displayText(1, "--- Switching to squeezing phase ---");
  222. #endif
  223. return 0;
  224. }
  225. /* ---------------------------------------------------------------- */
  226. int SpongeSqueeze(SpongeInstance *instance, unsigned char *data, size_t dataByteLen)
  227. {
  228. size_t i, j;
  229. unsigned int partialBlock;
  230. unsigned int rateInBytes = instance->rate/8;
  231. unsigned char *curData;
  232. if (!instance->squeezing)
  233. SpongeAbsorbLastFewBits(instance, 0x01);
  234. i = 0;
  235. curData = data;
  236. while(i < dataByteLen) {
  237. if ((instance->byteIOIndex == rateInBytes) && (dataByteLen-i >= rateInBytes)) {
  238. for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) {
  239. SnP_Permute(instance->state);
  240. SnP_ExtractBytes(instance->state, curData, 0, rateInBytes);
  241. #ifdef KeccakReference
  242. displayBytes(1, "Squeezed block", curData, rateInBytes);
  243. #endif
  244. curData+=rateInBytes;
  245. }
  246. i = dataByteLen - j;
  247. }
  248. else {
  249. /* normal lane: using the message queue */
  250. if (instance->byteIOIndex == rateInBytes) {
  251. SnP_Permute(instance->state);
  252. instance->byteIOIndex = 0;
  253. }
  254. if (dataByteLen-i > rateInBytes-instance->byteIOIndex)
  255. partialBlock = rateInBytes-instance->byteIOIndex;
  256. else
  257. partialBlock = (unsigned int)(dataByteLen - i);
  258. i += partialBlock;
  259. SnP_ExtractBytes(instance->state, curData, instance->byteIOIndex, partialBlock);
  260. #ifdef KeccakReference
  261. displayBytes(1, "Squeezed block (part)", curData, partialBlock);
  262. #endif
  263. curData += partialBlock;
  264. instance->byteIOIndex += partialBlock;
  265. }
  266. }
  267. return 0;
  268. }
  269. /* ---------------------------------------------------------------- */
  270. #undef Sponge
  271. #undef SpongeInstance
  272. #undef SpongeInitialize
  273. #undef SpongeAbsorb
  274. #undef SpongeAbsorbLastFewBits
  275. #undef SpongeSqueeze
  276. #undef SnP_stateSizeInBytes
  277. #undef SnP_stateAlignment
  278. #undef SnP_StaticInitialize
  279. #undef SnP_Initialize
  280. #undef SnP_AddByte
  281. #undef SnP_AddBytes
  282. #undef SnP_ExtractBytes