Annotation of embedaddon/php/ext/hash/hash_whirlpool.c, revision 1.1.1.3

1.1       misho       1: /*
                      2:   +----------------------------------------------------------------------+
                      3:   | PHP Version 5                                                        |
                      4:   +----------------------------------------------------------------------+
1.1.1.3 ! misho       5:   | Copyright (c) 1997-2013 The PHP Group                                |
1.1       misho       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: 
1.1.1.2   misho      20: /* $Id$ */
1.1       misho      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>