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>