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