PageRenderTime 27ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/runtime/ext/hash/hash_whirlpool.cpp

https://github.com/zsj888/hiphop-php
C++ | 450 lines | 325 code | 18 blank | 107 comment | 20 complexity | 30724b8f754526590a0b056f98ba06d1 MD5 | raw file
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2010 Facebook, Inc. (http://www.facebook.com) |
  6. | Copyright (c) 1997-2010 The PHP Group |
  7. +----------------------------------------------------------------------+
  8. | This source file is subject to version 3.01 of the PHP license, |
  9. | that is bundled with this package in the file LICENSE, and is |
  10. | available through the world-wide-web at the following url: |
  11. | http://www.php.net/license/3_01.txt |
  12. | If you did not receive a copy of the PHP license and are unable to |
  13. | obtain it through the world-wide-web, please send a note to |
  14. | license@php.net so we can mail you a copy immediately. |
  15. +----------------------------------------------------------------------+
  16. */
  17. #include <runtime/ext/hash/hash_whirlpool.h>
  18. #include <runtime/ext/hash/php_hash_whirlpool_tables.h>
  19. namespace HPHP {
  20. ///////////////////////////////////////////////////////////////////////////////
  21. typedef struct {
  22. uint64 state[8];
  23. unsigned char bitlength[32];
  24. struct {
  25. int pos;
  26. int bits;
  27. unsigned char data[64];
  28. } buffer;
  29. } PHP_WHIRLPOOL_CTX;
  30. hash_whirlpool::hash_whirlpool() :
  31. HashEngine(64, 64, sizeof(PHP_WHIRLPOOL_CTX)) {
  32. };
  33. #define DIGESTBYTES 64
  34. #define DIGESTBITS (8*DIGESTBYTES) /* 512 */
  35. #define WBLOCKBYTES 64
  36. #define WBLOCKBITS (8*WBLOCKBYTES) /* 512 */
  37. #define LENGTHBYTES 32
  38. #define LENGTHBITS (8*LENGTHBYTES) /* 256 */
  39. static void WhirlpoolTransform(PHP_WHIRLPOOL_CTX *context) {
  40. int i, r;
  41. unsigned long K[8]; /* the round key */
  42. unsigned long block[8]; /* mu(buffer) */
  43. unsigned long state[8]; /* the cipher state */
  44. unsigned long L[8];
  45. unsigned char *buffer = context->buffer.data;
  46. /*
  47. * map the buffer to a block:
  48. */
  49. for (i = 0; i < 8; i++, buffer += 8) {
  50. block[i] =
  51. (((unsigned long)buffer[0] ) << 56) ^
  52. (((unsigned long)buffer[1] & 0xffL) << 48) ^
  53. (((unsigned long)buffer[2] & 0xffL) << 40) ^
  54. (((unsigned long)buffer[3] & 0xffL) << 32) ^
  55. (((unsigned long)buffer[4] & 0xffL) << 24) ^
  56. (((unsigned long)buffer[5] & 0xffL) << 16) ^
  57. (((unsigned long)buffer[6] & 0xffL) << 8) ^
  58. (((unsigned long)buffer[7] & 0xffL) );
  59. }
  60. /*
  61. * compute and apply K^0 to the cipher state:
  62. */
  63. state[0] = block[0] ^ (K[0] = context->state[0]);
  64. state[1] = block[1] ^ (K[1] = context->state[1]);
  65. state[2] = block[2] ^ (K[2] = context->state[2]);
  66. state[3] = block[3] ^ (K[3] = context->state[3]);
  67. state[4] = block[4] ^ (K[4] = context->state[4]);
  68. state[5] = block[5] ^ (K[5] = context->state[5]);
  69. state[6] = block[6] ^ (K[6] = context->state[6]);
  70. state[7] = block[7] ^ (K[7] = context->state[7]);
  71. /*
  72. * iterate over all rounds:
  73. */
  74. for (r = 1; r <= R; r++) {
  75. /*
  76. * compute K^r from K^{r-1}:
  77. */
  78. L[0] =
  79. C0[(int)(K[0] >> 56) ] ^
  80. C1[(int)(K[7] >> 48) & 0xff] ^
  81. C2[(int)(K[6] >> 40) & 0xff] ^
  82. C3[(int)(K[5] >> 32) & 0xff] ^
  83. C4[(int)(K[4] >> 24) & 0xff] ^
  84. C5[(int)(K[3] >> 16) & 0xff] ^
  85. C6[(int)(K[2] >> 8) & 0xff] ^
  86. C7[(int)(K[1] ) & 0xff] ^
  87. rc[r];
  88. L[1] =
  89. C0[(int)(K[1] >> 56) ] ^
  90. C1[(int)(K[0] >> 48) & 0xff] ^
  91. C2[(int)(K[7] >> 40) & 0xff] ^
  92. C3[(int)(K[6] >> 32) & 0xff] ^
  93. C4[(int)(K[5] >> 24) & 0xff] ^
  94. C5[(int)(K[4] >> 16) & 0xff] ^
  95. C6[(int)(K[3] >> 8) & 0xff] ^
  96. C7[(int)(K[2] ) & 0xff];
  97. L[2] =
  98. C0[(int)(K[2] >> 56) ] ^
  99. C1[(int)(K[1] >> 48) & 0xff] ^
  100. C2[(int)(K[0] >> 40) & 0xff] ^
  101. C3[(int)(K[7] >> 32) & 0xff] ^
  102. C4[(int)(K[6] >> 24) & 0xff] ^
  103. C5[(int)(K[5] >> 16) & 0xff] ^
  104. C6[(int)(K[4] >> 8) & 0xff] ^
  105. C7[(int)(K[3] ) & 0xff];
  106. L[3] =
  107. C0[(int)(K[3] >> 56) ] ^
  108. C1[(int)(K[2] >> 48) & 0xff] ^
  109. C2[(int)(K[1] >> 40) & 0xff] ^
  110. C3[(int)(K[0] >> 32) & 0xff] ^
  111. C4[(int)(K[7] >> 24) & 0xff] ^
  112. C5[(int)(K[6] >> 16) & 0xff] ^
  113. C6[(int)(K[5] >> 8) & 0xff] ^
  114. C7[(int)(K[4] ) & 0xff];
  115. L[4] =
  116. C0[(int)(K[4] >> 56) ] ^
  117. C1[(int)(K[3] >> 48) & 0xff] ^
  118. C2[(int)(K[2] >> 40) & 0xff] ^
  119. C3[(int)(K[1] >> 32) & 0xff] ^
  120. C4[(int)(K[0] >> 24) & 0xff] ^
  121. C5[(int)(K[7] >> 16) & 0xff] ^
  122. C6[(int)(K[6] >> 8) & 0xff] ^
  123. C7[(int)(K[5] ) & 0xff];
  124. L[5] =
  125. C0[(int)(K[5] >> 56) ] ^
  126. C1[(int)(K[4] >> 48) & 0xff] ^
  127. C2[(int)(K[3] >> 40) & 0xff] ^
  128. C3[(int)(K[2] >> 32) & 0xff] ^
  129. C4[(int)(K[1] >> 24) & 0xff] ^
  130. C5[(int)(K[0] >> 16) & 0xff] ^
  131. C6[(int)(K[7] >> 8) & 0xff] ^
  132. C7[(int)(K[6] ) & 0xff];
  133. L[6] =
  134. C0[(int)(K[6] >> 56) ] ^
  135. C1[(int)(K[5] >> 48) & 0xff] ^
  136. C2[(int)(K[4] >> 40) & 0xff] ^
  137. C3[(int)(K[3] >> 32) & 0xff] ^
  138. C4[(int)(K[2] >> 24) & 0xff] ^
  139. C5[(int)(K[1] >> 16) & 0xff] ^
  140. C6[(int)(K[0] >> 8) & 0xff] ^
  141. C7[(int)(K[7] ) & 0xff];
  142. L[7] =
  143. C0[(int)(K[7] >> 56) ] ^
  144. C1[(int)(K[6] >> 48) & 0xff] ^
  145. C2[(int)(K[5] >> 40) & 0xff] ^
  146. C3[(int)(K[4] >> 32) & 0xff] ^
  147. C4[(int)(K[3] >> 24) & 0xff] ^
  148. C5[(int)(K[2] >> 16) & 0xff] ^
  149. C6[(int)(K[1] >> 8) & 0xff] ^
  150. C7[(int)(K[0] ) & 0xff];
  151. K[0] = L[0];
  152. K[1] = L[1];
  153. K[2] = L[2];
  154. K[3] = L[3];
  155. K[4] = L[4];
  156. K[5] = L[5];
  157. K[6] = L[6];
  158. K[7] = L[7];
  159. /*
  160. * apply the r-th round transformation:
  161. */
  162. L[0] =
  163. C0[(int)(state[0] >> 56) ] ^
  164. C1[(int)(state[7] >> 48) & 0xff] ^
  165. C2[(int)(state[6] >> 40) & 0xff] ^
  166. C3[(int)(state[5] >> 32) & 0xff] ^
  167. C4[(int)(state[4] >> 24) & 0xff] ^
  168. C5[(int)(state[3] >> 16) & 0xff] ^
  169. C6[(int)(state[2] >> 8) & 0xff] ^
  170. C7[(int)(state[1] ) & 0xff] ^
  171. K[0];
  172. L[1] =
  173. C0[(int)(state[1] >> 56) ] ^
  174. C1[(int)(state[0] >> 48) & 0xff] ^
  175. C2[(int)(state[7] >> 40) & 0xff] ^
  176. C3[(int)(state[6] >> 32) & 0xff] ^
  177. C4[(int)(state[5] >> 24) & 0xff] ^
  178. C5[(int)(state[4] >> 16) & 0xff] ^
  179. C6[(int)(state[3] >> 8) & 0xff] ^
  180. C7[(int)(state[2] ) & 0xff] ^
  181. K[1];
  182. L[2] =
  183. C0[(int)(state[2] >> 56) ] ^
  184. C1[(int)(state[1] >> 48) & 0xff] ^
  185. C2[(int)(state[0] >> 40) & 0xff] ^
  186. C3[(int)(state[7] >> 32) & 0xff] ^
  187. C4[(int)(state[6] >> 24) & 0xff] ^
  188. C5[(int)(state[5] >> 16) & 0xff] ^
  189. C6[(int)(state[4] >> 8) & 0xff] ^
  190. C7[(int)(state[3] ) & 0xff] ^
  191. K[2];
  192. L[3] =
  193. C0[(int)(state[3] >> 56) ] ^
  194. C1[(int)(state[2] >> 48) & 0xff] ^
  195. C2[(int)(state[1] >> 40) & 0xff] ^
  196. C3[(int)(state[0] >> 32) & 0xff] ^
  197. C4[(int)(state[7] >> 24) & 0xff] ^
  198. C5[(int)(state[6] >> 16) & 0xff] ^
  199. C6[(int)(state[5] >> 8) & 0xff] ^
  200. C7[(int)(state[4] ) & 0xff] ^
  201. K[3];
  202. L[4] =
  203. C0[(int)(state[4] >> 56) ] ^
  204. C1[(int)(state[3] >> 48) & 0xff] ^
  205. C2[(int)(state[2] >> 40) & 0xff] ^
  206. C3[(int)(state[1] >> 32) & 0xff] ^
  207. C4[(int)(state[0] >> 24) & 0xff] ^
  208. C5[(int)(state[7] >> 16) & 0xff] ^
  209. C6[(int)(state[6] >> 8) & 0xff] ^
  210. C7[(int)(state[5] ) & 0xff] ^
  211. K[4];
  212. L[5] =
  213. C0[(int)(state[5] >> 56) ] ^
  214. C1[(int)(state[4] >> 48) & 0xff] ^
  215. C2[(int)(state[3] >> 40) & 0xff] ^
  216. C3[(int)(state[2] >> 32) & 0xff] ^
  217. C4[(int)(state[1] >> 24) & 0xff] ^
  218. C5[(int)(state[0] >> 16) & 0xff] ^
  219. C6[(int)(state[7] >> 8) & 0xff] ^
  220. C7[(int)(state[6] ) & 0xff] ^
  221. K[5];
  222. L[6] =
  223. C0[(int)(state[6] >> 56) ] ^
  224. C1[(int)(state[5] >> 48) & 0xff] ^
  225. C2[(int)(state[4] >> 40) & 0xff] ^
  226. C3[(int)(state[3] >> 32) & 0xff] ^
  227. C4[(int)(state[2] >> 24) & 0xff] ^
  228. C5[(int)(state[1] >> 16) & 0xff] ^
  229. C6[(int)(state[0] >> 8) & 0xff] ^
  230. C7[(int)(state[7] ) & 0xff] ^
  231. K[6];
  232. L[7] =
  233. C0[(int)(state[7] >> 56) ] ^
  234. C1[(int)(state[6] >> 48) & 0xff] ^
  235. C2[(int)(state[5] >> 40) & 0xff] ^
  236. C3[(int)(state[4] >> 32) & 0xff] ^
  237. C4[(int)(state[3] >> 24) & 0xff] ^
  238. C5[(int)(state[2] >> 16) & 0xff] ^
  239. C6[(int)(state[1] >> 8) & 0xff] ^
  240. C7[(int)(state[0] ) & 0xff] ^
  241. K[7];
  242. state[0] = L[0];
  243. state[1] = L[1];
  244. state[2] = L[2];
  245. state[3] = L[3];
  246. state[4] = L[4];
  247. state[5] = L[5];
  248. state[6] = L[6];
  249. state[7] = L[7];
  250. }
  251. /*
  252. * apply the Miyaguchi-Preneel compression function:
  253. */
  254. context->state[0] ^= state[0] ^ block[0];
  255. context->state[1] ^= state[1] ^ block[1];
  256. context->state[2] ^= state[2] ^ block[2];
  257. context->state[3] ^= state[3] ^ block[3];
  258. context->state[4] ^= state[4] ^ block[4];
  259. context->state[5] ^= state[5] ^ block[5];
  260. context->state[6] ^= state[6] ^ block[6];
  261. context->state[7] ^= state[7] ^ block[7];
  262. memset(state, 0, sizeof(state));
  263. }
  264. void hash_whirlpool::hash_init(void *context_) {
  265. PHP_WHIRLPOOL_CTX *context = (PHP_WHIRLPOOL_CTX*)context_;
  266. memset(context, 0, sizeof(*context));
  267. }
  268. void hash_whirlpool::hash_update(void *context_, const unsigned char *input,
  269. unsigned int len) {
  270. PHP_WHIRLPOOL_CTX *context = (PHP_WHIRLPOOL_CTX*)context_;
  271. unsigned long sourceBits = len * 8;
  272. /* index of leftmost source unsigned char containing data (1 to 8 bits). */
  273. int sourcePos = 0;
  274. /* space on source[sourcePos]. */
  275. int sourceGap = (8 - ((int)sourceBits & 7)) & 7;
  276. /* occupied bits on buffer[bufferPos]. */
  277. int bufferRem = context->buffer.bits & 7;
  278. const unsigned char *source = input;
  279. unsigned char *buffer = context->buffer.data;
  280. unsigned char *bitLength = context->bitlength;
  281. int bufferBits = context->buffer.bits;
  282. int bufferPos = context->buffer.pos;
  283. unsigned int b, carry;
  284. int i;
  285. /*
  286. * tally the length of the added data:
  287. */
  288. unsigned long value = sourceBits;
  289. for (i = 31, carry = 0; i >= 0 && (carry != 0 || value != L64(0)); i--) {
  290. carry += bitLength[i] + ((unsigned int)value & 0xff);
  291. bitLength[i] = (unsigned char)carry;
  292. carry >>= 8;
  293. value >>= 8;
  294. }
  295. /*
  296. * process data in chunks of 8 bits (a more efficient approach would be to
  297. * take whole-word chunks):
  298. */
  299. while (sourceBits > 8) {
  300. /* N.B. at least source[sourcePos] and source[sourcePos+1] contain data. */
  301. /*
  302. * take a byte from the source:
  303. */
  304. b = ((source[sourcePos] << sourceGap) & 0xff) |
  305. ((source[sourcePos + 1] & 0xff) >> (8 - sourceGap));
  306. /*
  307. * process this byte:
  308. */
  309. buffer[bufferPos++] |= (unsigned char)(b >> bufferRem);
  310. bufferBits += 8 - bufferRem; /* bufferBits = 8*bufferPos; */
  311. if (bufferBits == DIGESTBITS) {
  312. /*
  313. * process data block:
  314. */
  315. WhirlpoolTransform(context);
  316. /*
  317. * reset buffer:
  318. */
  319. bufferBits = bufferPos = 0;
  320. }
  321. buffer[bufferPos] = (unsigned char) (b << (8 - bufferRem));
  322. bufferBits += bufferRem;
  323. /*
  324. * proceed to remaining data:
  325. */
  326. sourceBits -= 8;
  327. sourcePos++;
  328. }
  329. /* now 0 <= sourceBits <= 8;
  330. * furthermore, all data (if any is left) is in source[sourcePos].
  331. */
  332. if (sourceBits > 0) {
  333. /* bits are left-justified on b. */
  334. b = (source[sourcePos] << sourceGap) & 0xff;
  335. /*
  336. * process the remaining bits:
  337. */
  338. buffer[bufferPos] |= b >> bufferRem;
  339. } else {
  340. b = 0;
  341. }
  342. if (bufferRem + sourceBits < 8) {
  343. /*
  344. * all remaining data fits on buffer[bufferPos],
  345. * and there still remains some space.
  346. */
  347. bufferBits += (int) sourceBits;
  348. } else {
  349. /*
  350. * buffer[bufferPos] is full:
  351. */
  352. bufferPos++;
  353. bufferBits += 8 - bufferRem; /* bufferBits = 8*bufferPos; */
  354. sourceBits -= 8 - bufferRem;
  355. /* now 0 <= sourceBits < 8;
  356. * furthermore, all data (if any is left) is in source[sourcePos].
  357. */
  358. if (bufferBits == DIGESTBITS) {
  359. /*
  360. * process data block:
  361. */
  362. WhirlpoolTransform(context);
  363. /*
  364. * reset buffer:
  365. */
  366. bufferBits = bufferPos = 0;
  367. }
  368. buffer[bufferPos] = (unsigned char) (b << (8 - bufferRem));
  369. bufferBits += (int)sourceBits;
  370. }
  371. context->buffer.bits = bufferBits;
  372. context->buffer.pos = bufferPos;
  373. }
  374. void hash_whirlpool::hash_final(unsigned char *digest, void *context_) {
  375. PHP_WHIRLPOOL_CTX *context = (PHP_WHIRLPOOL_CTX*)context_;
  376. int i;
  377. unsigned char *buffer = context->buffer.data;
  378. unsigned char *bitLength = context->bitlength;
  379. int bufferBits = context->buffer.bits;
  380. int bufferPos = context->buffer.pos;
  381. /*
  382. * append a '1'-bit:
  383. */
  384. buffer[bufferPos] |= 0x80U >> (bufferBits & 7);
  385. /* all remaining bits on the current unsigned char are set to zero. */
  386. bufferPos++;
  387. /*
  388. * pad with zero bits to complete (N*WBLOCKBITS - LENGTHBITS) bits:
  389. */
  390. if (bufferPos > WBLOCKBYTES - LENGTHBYTES) {
  391. if (bufferPos < WBLOCKBYTES) {
  392. memset(&buffer[bufferPos], 0, WBLOCKBYTES - bufferPos);
  393. }
  394. /*
  395. * process data block:
  396. */
  397. WhirlpoolTransform(context);
  398. /*
  399. * reset buffer:
  400. */
  401. bufferPos = 0;
  402. }
  403. if (bufferPos < WBLOCKBYTES - LENGTHBYTES) {
  404. memset(&buffer[bufferPos], 0, (WBLOCKBYTES - LENGTHBYTES) - bufferPos);
  405. }
  406. bufferPos = WBLOCKBYTES - LENGTHBYTES;
  407. /*
  408. * append bit length of hashed data:
  409. */
  410. memcpy(&buffer[WBLOCKBYTES - LENGTHBYTES], bitLength, LENGTHBYTES);
  411. /*
  412. * process data block:
  413. */
  414. WhirlpoolTransform(context);
  415. /*
  416. * return the completed message digest:
  417. */
  418. for (i = 0; i < DIGESTBYTES/8; i++) {
  419. digest[0] = (unsigned char)(context->state[i] >> 56);
  420. digest[1] = (unsigned char)(context->state[i] >> 48);
  421. digest[2] = (unsigned char)(context->state[i] >> 40);
  422. digest[3] = (unsigned char)(context->state[i] >> 32);
  423. digest[4] = (unsigned char)(context->state[i] >> 24);
  424. digest[5] = (unsigned char)(context->state[i] >> 16);
  425. digest[6] = (unsigned char)(context->state[i] >> 8);
  426. digest[7] = (unsigned char)(context->state[i] );
  427. digest += 8;
  428. }
  429. memset(context, 0, sizeof(*context));
  430. }
  431. ///////////////////////////////////////////////////////////////////////////////
  432. }