sph_cubehash.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
  1. /* $Id: cubehash.c 227 2010-06-16 17:28:38Z tp $ */
  2. /*
  3. * CubeHash implementation.
  4. *
  5. * ==========================(LICENSE BEGIN)============================
  6. *
  7. * Copyright (c) 2007-2010 Projet RNRT SAPHIR
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining
  10. * a copy of this software and associated documentation files (the
  11. * "Software"), to deal in the Software without restriction, including
  12. * without limitation the rights to use, copy, modify, merge, publish,
  13. * distribute, sublicense, and/or sell copies of the Software, and to
  14. * permit persons to whom the Software is furnished to do so, subject to
  15. * the following conditions:
  16. *
  17. * The above copyright notice and this permission notice shall be
  18. * included in all copies or substantial portions of the Software.
  19. *
  20. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  23. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  24. * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  25. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  26. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27. *
  28. * ===========================(LICENSE END)=============================
  29. *
  30. * @author Thomas Pornin <thomas.pornin@cryptolog.com>
  31. */
  32. #include <stddef.h>
  33. #include <string.h>
  34. #include <limits.h>
  35. #include "sph_cubehash.h"
  36. #ifdef __cplusplus
  37. extern "C"{
  38. #endif
  39. #if SPH_SMALL_FOOTPRINT && !defined SPH_SMALL_FOOTPRINT_CUBEHASH
  40. #define SPH_SMALL_FOOTPRINT_CUBEHASH 1
  41. #endif
  42. /*
  43. * Some tests were conducted on an Intel Core2 Q6600 (32-bit and 64-bit
  44. * mode), a PowerPC G3, and a MIPS-compatible CPU (Broadcom BCM3302).
  45. * It appears that the optimal settings are:
  46. * -- full unroll, no state copy on the "big" systems (x86, PowerPC)
  47. * -- unroll to 4 or 8, state copy on the "small" system (MIPS)
  48. */
  49. #if SPH_SMALL_FOOTPRINT_CUBEHASH
  50. #if !defined SPH_CUBEHASH_UNROLL
  51. #define SPH_CUBEHASH_UNROLL 4
  52. #endif
  53. #if !defined SPH_CUBEHASH_NOCOPY
  54. #define SPH_CUBEHASH_NOCOPY 1
  55. #endif
  56. #else
  57. #if !defined SPH_CUBEHASH_UNROLL
  58. #define SPH_CUBEHASH_UNROLL 0
  59. #endif
  60. #if !defined SPH_CUBEHASH_NOCOPY
  61. #define SPH_CUBEHASH_NOCOPY 0
  62. #endif
  63. #endif
  64. #ifdef _MSC_VER
  65. #pragma warning (disable: 4146)
  66. #endif
  67. static const sph_u32 IV224[] = {
  68. SPH_C32(0xB0FC8217), SPH_C32(0x1BEE1A90), SPH_C32(0x829E1A22),
  69. SPH_C32(0x6362C342), SPH_C32(0x24D91C30), SPH_C32(0x03A7AA24),
  70. SPH_C32(0xA63721C8), SPH_C32(0x85B0E2EF), SPH_C32(0xF35D13F3),
  71. SPH_C32(0x41DA807D), SPH_C32(0x21A70CA6), SPH_C32(0x1F4E9774),
  72. SPH_C32(0xB3E1C932), SPH_C32(0xEB0A79A8), SPH_C32(0xCDDAAA66),
  73. SPH_C32(0xE2F6ECAA), SPH_C32(0x0A713362), SPH_C32(0xAA3080E0),
  74. SPH_C32(0xD8F23A32), SPH_C32(0xCEF15E28), SPH_C32(0xDB086314),
  75. SPH_C32(0x7F709DF7), SPH_C32(0xACD228A4), SPH_C32(0x704D6ECE),
  76. SPH_C32(0xAA3EC95F), SPH_C32(0xE387C214), SPH_C32(0x3A6445FF),
  77. SPH_C32(0x9CAB81C3), SPH_C32(0xC73D4B98), SPH_C32(0xD277AEBE),
  78. SPH_C32(0xFD20151C), SPH_C32(0x00CB573E)
  79. };
  80. static const sph_u32 IV256[] = {
  81. SPH_C32(0xEA2BD4B4), SPH_C32(0xCCD6F29F), SPH_C32(0x63117E71),
  82. SPH_C32(0x35481EAE), SPH_C32(0x22512D5B), SPH_C32(0xE5D94E63),
  83. SPH_C32(0x7E624131), SPH_C32(0xF4CC12BE), SPH_C32(0xC2D0B696),
  84. SPH_C32(0x42AF2070), SPH_C32(0xD0720C35), SPH_C32(0x3361DA8C),
  85. SPH_C32(0x28CCECA4), SPH_C32(0x8EF8AD83), SPH_C32(0x4680AC00),
  86. SPH_C32(0x40E5FBAB), SPH_C32(0xD89041C3), SPH_C32(0x6107FBD5),
  87. SPH_C32(0x6C859D41), SPH_C32(0xF0B26679), SPH_C32(0x09392549),
  88. SPH_C32(0x5FA25603), SPH_C32(0x65C892FD), SPH_C32(0x93CB6285),
  89. SPH_C32(0x2AF2B5AE), SPH_C32(0x9E4B4E60), SPH_C32(0x774ABFDD),
  90. SPH_C32(0x85254725), SPH_C32(0x15815AEB), SPH_C32(0x4AB6AAD6),
  91. SPH_C32(0x9CDAF8AF), SPH_C32(0xD6032C0A)
  92. };
  93. static const sph_u32 IV384[] = {
  94. SPH_C32(0xE623087E), SPH_C32(0x04C00C87), SPH_C32(0x5EF46453),
  95. SPH_C32(0x69524B13), SPH_C32(0x1A05C7A9), SPH_C32(0x3528DF88),
  96. SPH_C32(0x6BDD01B5), SPH_C32(0x5057B792), SPH_C32(0x6AA7A922),
  97. SPH_C32(0x649C7EEE), SPH_C32(0xF426309F), SPH_C32(0xCB629052),
  98. SPH_C32(0xFC8E20ED), SPH_C32(0xB3482BAB), SPH_C32(0xF89E5E7E),
  99. SPH_C32(0xD83D4DE4), SPH_C32(0x44BFC10D), SPH_C32(0x5FC1E63D),
  100. SPH_C32(0x2104E6CB), SPH_C32(0x17958F7F), SPH_C32(0xDBEAEF70),
  101. SPH_C32(0xB4B97E1E), SPH_C32(0x32C195F6), SPH_C32(0x6184A8E4),
  102. SPH_C32(0x796C2543), SPH_C32(0x23DE176D), SPH_C32(0xD33BBAEC),
  103. SPH_C32(0x0C12E5D2), SPH_C32(0x4EB95A7B), SPH_C32(0x2D18BA01),
  104. SPH_C32(0x04EE475F), SPH_C32(0x1FC5F22E)
  105. };
  106. static const sph_u32 IV512[] = {
  107. SPH_C32(0x2AEA2A61), SPH_C32(0x50F494D4), SPH_C32(0x2D538B8B),
  108. SPH_C32(0x4167D83E), SPH_C32(0x3FEE2313), SPH_C32(0xC701CF8C),
  109. SPH_C32(0xCC39968E), SPH_C32(0x50AC5695), SPH_C32(0x4D42C787),
  110. SPH_C32(0xA647A8B3), SPH_C32(0x97CF0BEF), SPH_C32(0x825B4537),
  111. SPH_C32(0xEEF864D2), SPH_C32(0xF22090C4), SPH_C32(0xD0E5CD33),
  112. SPH_C32(0xA23911AE), SPH_C32(0xFCD398D9), SPH_C32(0x148FE485),
  113. SPH_C32(0x1B017BEF), SPH_C32(0xB6444532), SPH_C32(0x6A536159),
  114. SPH_C32(0x2FF5781C), SPH_C32(0x91FA7934), SPH_C32(0x0DBADEA9),
  115. SPH_C32(0xD65C8A2B), SPH_C32(0xA5A70E75), SPH_C32(0xB1C62456),
  116. SPH_C32(0xBC796576), SPH_C32(0x1921C8F7), SPH_C32(0xE7989AF1),
  117. SPH_C32(0x7795D246), SPH_C32(0xD43E3B44)
  118. };
  119. #define T32 SPH_T32
  120. #define ROTL32 SPH_ROTL32
  121. #if SPH_CUBEHASH_NOCOPY
  122. #define DECL_STATE
  123. #define READ_STATE(cc)
  124. #define WRITE_STATE(cc)
  125. #define x0 ((sc)->state[ 0])
  126. #define x1 ((sc)->state[ 1])
  127. #define x2 ((sc)->state[ 2])
  128. #define x3 ((sc)->state[ 3])
  129. #define x4 ((sc)->state[ 4])
  130. #define x5 ((sc)->state[ 5])
  131. #define x6 ((sc)->state[ 6])
  132. #define x7 ((sc)->state[ 7])
  133. #define x8 ((sc)->state[ 8])
  134. #define x9 ((sc)->state[ 9])
  135. #define xa ((sc)->state[10])
  136. #define xb ((sc)->state[11])
  137. #define xc ((sc)->state[12])
  138. #define xd ((sc)->state[13])
  139. #define xe ((sc)->state[14])
  140. #define xf ((sc)->state[15])
  141. #define xg ((sc)->state[16])
  142. #define xh ((sc)->state[17])
  143. #define xi ((sc)->state[18])
  144. #define xj ((sc)->state[19])
  145. #define xk ((sc)->state[20])
  146. #define xl ((sc)->state[21])
  147. #define xm ((sc)->state[22])
  148. #define xn ((sc)->state[23])
  149. #define xo ((sc)->state[24])
  150. #define xp ((sc)->state[25])
  151. #define xq ((sc)->state[26])
  152. #define xr ((sc)->state[27])
  153. #define xs ((sc)->state[28])
  154. #define xt ((sc)->state[29])
  155. #define xu ((sc)->state[30])
  156. #define xv ((sc)->state[31])
  157. #else
  158. #define DECL_STATE \
  159. sph_u32 x0, x1, x2, x3, x4, x5, x6, x7; \
  160. sph_u32 x8, x9, xa, xb, xc, xd, xe, xf; \
  161. sph_u32 xg, xh, xi, xj, xk, xl, xm, xn; \
  162. sph_u32 xo, xp, xq, xr, xs, xt, xu, xv;
  163. #define READ_STATE(cc) do { \
  164. x0 = (cc)->state[ 0]; \
  165. x1 = (cc)->state[ 1]; \
  166. x2 = (cc)->state[ 2]; \
  167. x3 = (cc)->state[ 3]; \
  168. x4 = (cc)->state[ 4]; \
  169. x5 = (cc)->state[ 5]; \
  170. x6 = (cc)->state[ 6]; \
  171. x7 = (cc)->state[ 7]; \
  172. x8 = (cc)->state[ 8]; \
  173. x9 = (cc)->state[ 9]; \
  174. xa = (cc)->state[10]; \
  175. xb = (cc)->state[11]; \
  176. xc = (cc)->state[12]; \
  177. xd = (cc)->state[13]; \
  178. xe = (cc)->state[14]; \
  179. xf = (cc)->state[15]; \
  180. xg = (cc)->state[16]; \
  181. xh = (cc)->state[17]; \
  182. xi = (cc)->state[18]; \
  183. xj = (cc)->state[19]; \
  184. xk = (cc)->state[20]; \
  185. xl = (cc)->state[21]; \
  186. xm = (cc)->state[22]; \
  187. xn = (cc)->state[23]; \
  188. xo = (cc)->state[24]; \
  189. xp = (cc)->state[25]; \
  190. xq = (cc)->state[26]; \
  191. xr = (cc)->state[27]; \
  192. xs = (cc)->state[28]; \
  193. xt = (cc)->state[29]; \
  194. xu = (cc)->state[30]; \
  195. xv = (cc)->state[31]; \
  196. } while (0)
  197. #define WRITE_STATE(cc) do { \
  198. (cc)->state[ 0] = x0; \
  199. (cc)->state[ 1] = x1; \
  200. (cc)->state[ 2] = x2; \
  201. (cc)->state[ 3] = x3; \
  202. (cc)->state[ 4] = x4; \
  203. (cc)->state[ 5] = x5; \
  204. (cc)->state[ 6] = x6; \
  205. (cc)->state[ 7] = x7; \
  206. (cc)->state[ 8] = x8; \
  207. (cc)->state[ 9] = x9; \
  208. (cc)->state[10] = xa; \
  209. (cc)->state[11] = xb; \
  210. (cc)->state[12] = xc; \
  211. (cc)->state[13] = xd; \
  212. (cc)->state[14] = xe; \
  213. (cc)->state[15] = xf; \
  214. (cc)->state[16] = xg; \
  215. (cc)->state[17] = xh; \
  216. (cc)->state[18] = xi; \
  217. (cc)->state[19] = xj; \
  218. (cc)->state[20] = xk; \
  219. (cc)->state[21] = xl; \
  220. (cc)->state[22] = xm; \
  221. (cc)->state[23] = xn; \
  222. (cc)->state[24] = xo; \
  223. (cc)->state[25] = xp; \
  224. (cc)->state[26] = xq; \
  225. (cc)->state[27] = xr; \
  226. (cc)->state[28] = xs; \
  227. (cc)->state[29] = xt; \
  228. (cc)->state[30] = xu; \
  229. (cc)->state[31] = xv; \
  230. } while (0)
  231. #endif
  232. #define INPUT_BLOCK do { \
  233. x0 ^= sph_dec32le_aligned(buf + 0); \
  234. x1 ^= sph_dec32le_aligned(buf + 4); \
  235. x2 ^= sph_dec32le_aligned(buf + 8); \
  236. x3 ^= sph_dec32le_aligned(buf + 12); \
  237. x4 ^= sph_dec32le_aligned(buf + 16); \
  238. x5 ^= sph_dec32le_aligned(buf + 20); \
  239. x6 ^= sph_dec32le_aligned(buf + 24); \
  240. x7 ^= sph_dec32le_aligned(buf + 28); \
  241. } while (0)
  242. #define ROUND_EVEN do { \
  243. xg = T32(x0 + xg); \
  244. x0 = ROTL32(x0, 7); \
  245. xh = T32(x1 + xh); \
  246. x1 = ROTL32(x1, 7); \
  247. xi = T32(x2 + xi); \
  248. x2 = ROTL32(x2, 7); \
  249. xj = T32(x3 + xj); \
  250. x3 = ROTL32(x3, 7); \
  251. xk = T32(x4 + xk); \
  252. x4 = ROTL32(x4, 7); \
  253. xl = T32(x5 + xl); \
  254. x5 = ROTL32(x5, 7); \
  255. xm = T32(x6 + xm); \
  256. x6 = ROTL32(x6, 7); \
  257. xn = T32(x7 + xn); \
  258. x7 = ROTL32(x7, 7); \
  259. xo = T32(x8 + xo); \
  260. x8 = ROTL32(x8, 7); \
  261. xp = T32(x9 + xp); \
  262. x9 = ROTL32(x9, 7); \
  263. xq = T32(xa + xq); \
  264. xa = ROTL32(xa, 7); \
  265. xr = T32(xb + xr); \
  266. xb = ROTL32(xb, 7); \
  267. xs = T32(xc + xs); \
  268. xc = ROTL32(xc, 7); \
  269. xt = T32(xd + xt); \
  270. xd = ROTL32(xd, 7); \
  271. xu = T32(xe + xu); \
  272. xe = ROTL32(xe, 7); \
  273. xv = T32(xf + xv); \
  274. xf = ROTL32(xf, 7); \
  275. x8 ^= xg; \
  276. x9 ^= xh; \
  277. xa ^= xi; \
  278. xb ^= xj; \
  279. xc ^= xk; \
  280. xd ^= xl; \
  281. xe ^= xm; \
  282. xf ^= xn; \
  283. x0 ^= xo; \
  284. x1 ^= xp; \
  285. x2 ^= xq; \
  286. x3 ^= xr; \
  287. x4 ^= xs; \
  288. x5 ^= xt; \
  289. x6 ^= xu; \
  290. x7 ^= xv; \
  291. xi = T32(x8 + xi); \
  292. x8 = ROTL32(x8, 11); \
  293. xj = T32(x9 + xj); \
  294. x9 = ROTL32(x9, 11); \
  295. xg = T32(xa + xg); \
  296. xa = ROTL32(xa, 11); \
  297. xh = T32(xb + xh); \
  298. xb = ROTL32(xb, 11); \
  299. xm = T32(xc + xm); \
  300. xc = ROTL32(xc, 11); \
  301. xn = T32(xd + xn); \
  302. xd = ROTL32(xd, 11); \
  303. xk = T32(xe + xk); \
  304. xe = ROTL32(xe, 11); \
  305. xl = T32(xf + xl); \
  306. xf = ROTL32(xf, 11); \
  307. xq = T32(x0 + xq); \
  308. x0 = ROTL32(x0, 11); \
  309. xr = T32(x1 + xr); \
  310. x1 = ROTL32(x1, 11); \
  311. xo = T32(x2 + xo); \
  312. x2 = ROTL32(x2, 11); \
  313. xp = T32(x3 + xp); \
  314. x3 = ROTL32(x3, 11); \
  315. xu = T32(x4 + xu); \
  316. x4 = ROTL32(x4, 11); \
  317. xv = T32(x5 + xv); \
  318. x5 = ROTL32(x5, 11); \
  319. xs = T32(x6 + xs); \
  320. x6 = ROTL32(x6, 11); \
  321. xt = T32(x7 + xt); \
  322. x7 = ROTL32(x7, 11); \
  323. xc ^= xi; \
  324. xd ^= xj; \
  325. xe ^= xg; \
  326. xf ^= xh; \
  327. x8 ^= xm; \
  328. x9 ^= xn; \
  329. xa ^= xk; \
  330. xb ^= xl; \
  331. x4 ^= xq; \
  332. x5 ^= xr; \
  333. x6 ^= xo; \
  334. x7 ^= xp; \
  335. x0 ^= xu; \
  336. x1 ^= xv; \
  337. x2 ^= xs; \
  338. x3 ^= xt; \
  339. } while (0)
  340. #define ROUND_ODD do { \
  341. xj = T32(xc + xj); \
  342. xc = ROTL32(xc, 7); \
  343. xi = T32(xd + xi); \
  344. xd = ROTL32(xd, 7); \
  345. xh = T32(xe + xh); \
  346. xe = ROTL32(xe, 7); \
  347. xg = T32(xf + xg); \
  348. xf = ROTL32(xf, 7); \
  349. xn = T32(x8 + xn); \
  350. x8 = ROTL32(x8, 7); \
  351. xm = T32(x9 + xm); \
  352. x9 = ROTL32(x9, 7); \
  353. xl = T32(xa + xl); \
  354. xa = ROTL32(xa, 7); \
  355. xk = T32(xb + xk); \
  356. xb = ROTL32(xb, 7); \
  357. xr = T32(x4 + xr); \
  358. x4 = ROTL32(x4, 7); \
  359. xq = T32(x5 + xq); \
  360. x5 = ROTL32(x5, 7); \
  361. xp = T32(x6 + xp); \
  362. x6 = ROTL32(x6, 7); \
  363. xo = T32(x7 + xo); \
  364. x7 = ROTL32(x7, 7); \
  365. xv = T32(x0 + xv); \
  366. x0 = ROTL32(x0, 7); \
  367. xu = T32(x1 + xu); \
  368. x1 = ROTL32(x1, 7); \
  369. xt = T32(x2 + xt); \
  370. x2 = ROTL32(x2, 7); \
  371. xs = T32(x3 + xs); \
  372. x3 = ROTL32(x3, 7); \
  373. x4 ^= xj; \
  374. x5 ^= xi; \
  375. x6 ^= xh; \
  376. x7 ^= xg; \
  377. x0 ^= xn; \
  378. x1 ^= xm; \
  379. x2 ^= xl; \
  380. x3 ^= xk; \
  381. xc ^= xr; \
  382. xd ^= xq; \
  383. xe ^= xp; \
  384. xf ^= xo; \
  385. x8 ^= xv; \
  386. x9 ^= xu; \
  387. xa ^= xt; \
  388. xb ^= xs; \
  389. xh = T32(x4 + xh); \
  390. x4 = ROTL32(x4, 11); \
  391. xg = T32(x5 + xg); \
  392. x5 = ROTL32(x5, 11); \
  393. xj = T32(x6 + xj); \
  394. x6 = ROTL32(x6, 11); \
  395. xi = T32(x7 + xi); \
  396. x7 = ROTL32(x7, 11); \
  397. xl = T32(x0 + xl); \
  398. x0 = ROTL32(x0, 11); \
  399. xk = T32(x1 + xk); \
  400. x1 = ROTL32(x1, 11); \
  401. xn = T32(x2 + xn); \
  402. x2 = ROTL32(x2, 11); \
  403. xm = T32(x3 + xm); \
  404. x3 = ROTL32(x3, 11); \
  405. xp = T32(xc + xp); \
  406. xc = ROTL32(xc, 11); \
  407. xo = T32(xd + xo); \
  408. xd = ROTL32(xd, 11); \
  409. xr = T32(xe + xr); \
  410. xe = ROTL32(xe, 11); \
  411. xq = T32(xf + xq); \
  412. xf = ROTL32(xf, 11); \
  413. xt = T32(x8 + xt); \
  414. x8 = ROTL32(x8, 11); \
  415. xs = T32(x9 + xs); \
  416. x9 = ROTL32(x9, 11); \
  417. xv = T32(xa + xv); \
  418. xa = ROTL32(xa, 11); \
  419. xu = T32(xb + xu); \
  420. xb = ROTL32(xb, 11); \
  421. x0 ^= xh; \
  422. x1 ^= xg; \
  423. x2 ^= xj; \
  424. x3 ^= xi; \
  425. x4 ^= xl; \
  426. x5 ^= xk; \
  427. x6 ^= xn; \
  428. x7 ^= xm; \
  429. x8 ^= xp; \
  430. x9 ^= xo; \
  431. xa ^= xr; \
  432. xb ^= xq; \
  433. xc ^= xt; \
  434. xd ^= xs; \
  435. xe ^= xv; \
  436. xf ^= xu; \
  437. } while (0)
  438. /*
  439. * There is no need to unroll all 16 rounds. The word-swapping permutation
  440. * is an involution, so we need to unroll an even number of rounds. On
  441. * "big" systems, unrolling 4 rounds yields about 97% of the speed
  442. * achieved with full unrolling; and it keeps the code more compact
  443. * for small architectures.
  444. */
  445. #if SPH_CUBEHASH_UNROLL == 2
  446. #define SIXTEEN_ROUNDS do { \
  447. int j; \
  448. for (j = 0; j < 8; j ++) { \
  449. ROUND_EVEN; \
  450. ROUND_ODD; \
  451. } \
  452. } while (0)
  453. #elif SPH_CUBEHASH_UNROLL == 4
  454. #define SIXTEEN_ROUNDS do { \
  455. int j; \
  456. for (j = 0; j < 4; j ++) { \
  457. ROUND_EVEN; \
  458. ROUND_ODD; \
  459. ROUND_EVEN; \
  460. ROUND_ODD; \
  461. } \
  462. } while (0)
  463. #elif SPH_CUBEHASH_UNROLL == 8
  464. #define SIXTEEN_ROUNDS do { \
  465. int j; \
  466. for (j = 0; j < 2; j ++) { \
  467. ROUND_EVEN; \
  468. ROUND_ODD; \
  469. ROUND_EVEN; \
  470. ROUND_ODD; \
  471. ROUND_EVEN; \
  472. ROUND_ODD; \
  473. ROUND_EVEN; \
  474. ROUND_ODD; \
  475. } \
  476. } while (0)
  477. #else
  478. #define SIXTEEN_ROUNDS do { \
  479. ROUND_EVEN; \
  480. ROUND_ODD; \
  481. ROUND_EVEN; \
  482. ROUND_ODD; \
  483. ROUND_EVEN; \
  484. ROUND_ODD; \
  485. ROUND_EVEN; \
  486. ROUND_ODD; \
  487. ROUND_EVEN; \
  488. ROUND_ODD; \
  489. ROUND_EVEN; \
  490. ROUND_ODD; \
  491. ROUND_EVEN; \
  492. ROUND_ODD; \
  493. ROUND_EVEN; \
  494. ROUND_ODD; \
  495. } while (0)
  496. #endif
  497. static void
  498. cubehash_init(sph_cubehash_context *sc, const sph_u32 *iv)
  499. {
  500. memcpy(sc->state, iv, sizeof sc->state);
  501. sc->ptr = 0;
  502. }
  503. static void
  504. cubehash_core(sph_cubehash_context *sc, const void *data, size_t len)
  505. {
  506. unsigned char *buf;
  507. size_t ptr;
  508. DECL_STATE
  509. buf = sc->buf;
  510. ptr = sc->ptr;
  511. if (len < (sizeof sc->buf) - ptr) {
  512. memcpy(buf + ptr, data, len);
  513. ptr += len;
  514. sc->ptr = ptr;
  515. return;
  516. }
  517. READ_STATE(sc);
  518. while (len > 0) {
  519. size_t clen;
  520. clen = (sizeof sc->buf) - ptr;
  521. if (clen > len)
  522. clen = len;
  523. memcpy(buf + ptr, data, clen);
  524. ptr += clen;
  525. data = (const unsigned char *)data + clen;
  526. len -= clen;
  527. if (ptr == sizeof sc->buf) {
  528. INPUT_BLOCK;
  529. SIXTEEN_ROUNDS;
  530. ptr = 0;
  531. }
  532. }
  533. WRITE_STATE(sc);
  534. sc->ptr = ptr;
  535. }
  536. static void
  537. cubehash_close(sph_cubehash_context *sc, unsigned ub, unsigned n,
  538. void *dst, size_t out_size_w32)
  539. {
  540. unsigned char *buf, *out;
  541. size_t ptr;
  542. unsigned z;
  543. int i;
  544. DECL_STATE
  545. buf = sc->buf;
  546. ptr = sc->ptr;
  547. z = 0x80 >> n;
  548. buf[ptr ++] = ((ub & -z) | z) & 0xFF;
  549. memset(buf + ptr, 0, (sizeof sc->buf) - ptr);
  550. READ_STATE(sc);
  551. INPUT_BLOCK;
  552. for (i = 0; i < 11; i ++) {
  553. SIXTEEN_ROUNDS;
  554. if (i == 0)
  555. xv ^= SPH_C32(1);
  556. }
  557. WRITE_STATE(sc);
  558. out = dst;
  559. for (z = 0; z < out_size_w32; z ++)
  560. sph_enc32le(out + (z << 2), sc->state[z]);
  561. }
  562. /* see sph_cubehash.h */
  563. void
  564. sph_cubehash224_init(void *cc)
  565. {
  566. cubehash_init(cc, IV224);
  567. }
  568. /* see sph_cubehash.h */
  569. void
  570. sph_cubehash224(void *cc, const void *data, size_t len)
  571. {
  572. cubehash_core(cc, data, len);
  573. }
  574. /* see sph_cubehash.h */
  575. void
  576. sph_cubehash224_close(void *cc, void *dst)
  577. {
  578. sph_cubehash224_addbits_and_close(cc, 0, 0, dst);
  579. }
  580. /* see sph_cubehash.h */
  581. void
  582. sph_cubehash224_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst)
  583. {
  584. cubehash_close(cc, ub, n, dst, 7);
  585. sph_cubehash224_init(cc);
  586. }
  587. /* see sph_cubehash.h */
  588. void
  589. sph_cubehash256_init(void *cc)
  590. {
  591. cubehash_init(cc, IV256);
  592. }
  593. /* see sph_cubehash.h */
  594. void
  595. sph_cubehash256(void *cc, const void *data, size_t len)
  596. {
  597. cubehash_core(cc, data, len);
  598. }
  599. /* see sph_cubehash.h */
  600. void
  601. sph_cubehash256_close(void *cc, void *dst)
  602. {
  603. sph_cubehash256_addbits_and_close(cc, 0, 0, dst);
  604. }
  605. /* see sph_cubehash.h */
  606. void
  607. sph_cubehash256_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst)
  608. {
  609. cubehash_close(cc, ub, n, dst, 8);
  610. sph_cubehash256_init(cc);
  611. }
  612. /* see sph_cubehash.h */
  613. void
  614. sph_cubehash384_init(void *cc)
  615. {
  616. cubehash_init(cc, IV384);
  617. }
  618. /* see sph_cubehash.h */
  619. void
  620. sph_cubehash384(void *cc, const void *data, size_t len)
  621. {
  622. cubehash_core(cc, data, len);
  623. }
  624. /* see sph_cubehash.h */
  625. void
  626. sph_cubehash384_close(void *cc, void *dst)
  627. {
  628. sph_cubehash384_addbits_and_close(cc, 0, 0, dst);
  629. }
  630. /* see sph_cubehash.h */
  631. void
  632. sph_cubehash384_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst)
  633. {
  634. cubehash_close(cc, ub, n, dst, 12);
  635. sph_cubehash384_init(cc);
  636. }
  637. /* see sph_cubehash.h */
  638. void
  639. sph_cubehash512_init(void *cc)
  640. {
  641. cubehash_init(cc, IV512);
  642. }
  643. /* see sph_cubehash.h */
  644. void
  645. sph_cubehash512(void *cc, const void *data, size_t len)
  646. {
  647. cubehash_core(cc, data, len);
  648. }
  649. /* see sph_cubehash.h */
  650. void
  651. sph_cubehash512_close(void *cc, void *dst)
  652. {
  653. sph_cubehash512_addbits_and_close(cc, 0, 0, dst);
  654. }
  655. /* see sph_cubehash.h */
  656. void
  657. sph_cubehash512_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst)
  658. {
  659. cubehash_close(cc, ub, n, dst, 16);
  660. sph_cubehash512_init(cc);
  661. }
  662. #ifdef __cplusplus
  663. }
  664. #endif