Annotation of pgp/src/idea.c, revision 1.1.1.5

1.1.1.5 ! root        1: /*
        !             2:  *     idea.c - C source code for IDEA block cipher.
        !             3:  *     IDEA (International Data Encryption Algorithm), formerly known as 
        !             4:  *     IPES (Improved Proposed Encryption Standard).
        !             5:  *     Algorithm developed by Xuejia Lai and James L. Massey, of ETH Zurich.
        !             6:  *     This implementation modified and derived from original C code 
        !             7:  *     developed by Xuejia Lai.  
        !             8:  *     Zero-based indexing added, names changed from IPES to IDEA.
        !             9:  *     CFB functions added.  Random number routines added.
        !            10:  *
        !            11:  *     Extensively optimized and restructured by Colin Plumb.
        !            12:  *
        !            13:  *     There are two adjustments that can be made to this code to
        !            14:  *     speed it up.  Defaults may be used for PCs.  Only the -DIDEA32
        !            15:  *     pays off significantly if selectively set or not set.
        !            16:  *     Experiment to see what works best for your machine.
        !            17:  *
        !            18:  *     Multiplication: default is inline, -DAVOID_JUMPS uses a
        !            19:  *             different version that does not do any conditional
        !            20:  *             jumps (a few percent worse on a SPARC), while
        !            21:  *             -DSMALL_CACHE takes it out of line to stay
        !            22:  *             within a small on-chip code cache.
        !            23:  *     Variables: normally, 16-bit variables are used, but some
        !            24:  *             machines (notably RISCs) do not have 16-bit registers,
        !            25:  *             so they do a great deal of masking.  -DIDEA32 uses "int"
        !            26:  *             register variables and masks explicitly only where
        !            27:  *             necessary.  On a SPARC, for example, this boosts
        !            28:  *             performace by 30%.
        !            29:  *
        !            30:  *     The IDEA(tm) block cipher is covered by patents held by ETH and a
        !            31:  *     Swiss company called Ascom-Tech AG.  The Swiss patent number is
        !            32:  *     PCT/CH91/00117, the European patent number is EP 0 482 154 B1, and
        !            33:  *     the U.S. patent number is US005214703.  IDEA(tm) is a trademark of
        !            34:  *     Ascom-Tech AG.  There is no license fee required for noncommercial
        !            35:  *     use.  Commercial users may obtain licensing details from Dieter
        !            36:  *     Profos, Ascom Tech AG, Solothurn Lab, Postfach 151, 4502 Solothurn,
        !            37:  *     Switzerland, Tel +41 65 242885, Fax +41 65 235761.
        !            38:  *
        !            39:  *     The IDEA block cipher uses a 64-bit block size, and a 128-bit key 
        !            40:  *     size.  It breaks the 64-bit cipher block into four 16-bit words
        !            41:  *     because all of the primitive inner operations are done with 16-bit 
        !            42:  *     arithmetic.  It likewise breaks the 128-bit cipher key into eight 
        !            43:  *     16-bit words.
        !            44:  *
        !            45:  *     For further information on the IDEA cipher, see the book:
        !            46:  *       Xuejia Lai, "On the Design and Security of Block Ciphers",
        !            47:  *       ETH Series on Information Processing (ed. J.L. Massey) Vol 1,
        !            48:  *       Hartung-Gorre Verlag, Konstanz, Switzerland, 1992.  ISBN
        !            49:  *       3-89191-573-X.
        !            50:  *
        !            51:  *     This code runs on arrays of bytes by taking pairs in big-endian
        !            52:  *     order to make the 16-bit words that IDEA uses internally.  This
        !            53:  *     produces the same result regardless of the byte order of the
        !            54:  *     native CPU.
        !            55:  */
        !            56: 
        !            57: #include "idea.h"
        !            58: #include "randpool.h"
        !            59: 
        !            60: #ifdef IDEA32  /* Use >16-bit temporaries */
        !            61: #define low16(x) ((x) & 0xFFFF)
        !            62: typedef unsigned int uint16;   /* at LEAST 16 bits, maybe more */
        !            63: #else
        !            64: #define low16(x) (x)   /* this is only ever applied to uint16's */
        !            65: typedef word16 uint16;
        !            66: #endif
        !            67: 
        !            68: #ifdef _GNUC_
        !            69: /* __const__ simply means there are no side effects for this function,
        !            70:  * which is useful info for the gcc optimizer
        !            71:  */
        !            72: #define CONST __const__
        !            73: #else
        !            74: #define CONST
        !            75: #endif
        !            76: 
        !            77: /*
        !            78:  *     Multiplication, modulo (2**16)+1
        !            79:  * Note that this code is structured on the assumption that
        !            80:  * untaken branches are cheaper than taken branches, and the
        !            81:  * compiler doesn't schedule branches.
        !            82:  */
        !            83: #ifdef SMALL_CACHE
        !            84: CONST static uint16
        !            85: mul(register uint16 a, register uint16 b)
        !            86: {
        !            87:        register word32 p;
        !            88: 
        !            89:        p = (word32)a * b;
        !            90:        if (p) {
        !            91:                b = low16(p);
        !            92:                a = p>>16;
        !            93:                return (b - a) + (b < a);
        !            94:        } else if (a) {
        !            95:                return 1-b;
        !            96:        } else {
        !            97:                return 1-a;
        !            98:        }
        !            99: } /* mul */
        !           100: #endif /* SMALL_CACHE */
        !           101: 
        !           102: /*
        !           103:  * Compute the multiplicative inverse of x, modulo 65537, using Euclid's
        !           104:  * algorithm. It is unrolled twice to avoid swapping the registers each
        !           105:  * iteration, and some subtracts of t have been changed to adds.
        !           106:  */
        !           107: CONST static uint16
        !           108: mulInv(uint16 x)     
        !           109: {
        !           110:        uint16 t0, t1;
        !           111:        uint16 q, y;
        !           112: 
        !           113:        if (x <= 1)
        !           114:                return x;       /* 0 and 1 are self-inverse */
        !           115:        t1 = 0x10001L / x;      /* Since x >= 2, this fits into 16 bits */
        !           116:        y = 0x10001L % x;
        !           117:        if (y == 1)
        !           118:                return low16(1-t1);
        !           119:        t0 = 1;
        !           120:        do {
        !           121:                q = x / y;
        !           122:                x = x % y;
        !           123:                t0 += q * t1;
        !           124:                if (x == 1)
        !           125:                        return t0;
        !           126:                q = y / x;
        !           127:                y = y % x;
        !           128:                t1 += q * t0;
        !           129:        } while (y != 1);
        !           130:        return low16(1-t1);
        !           131: } /* mukInv */
        !           132: 
        !           133: /*
        !           134:  * Expand a 128-bit user key to a working encryption key EK
        !           135:  */
        !           136: static void
        !           137: ideaExpandKey(byte const *userkey, word16 *EK)
        !           138: {
        !           139:        int i,j;
        !           140: 
        !           141:        for (j=0; j<8; j++) {
        !           142:                EK[j] = (userkey[0]<<8) + userkey[1];
        !           143:                userkey += 2;
        !           144:        }
        !           145:        for (i=0; j < IDEAKEYLEN; j++) {
        !           146:                i++;
        !           147:                EK[i+7] = EK[i & 7] << 9 | EK[i+1 & 7] >> 7;
        !           148:                EK += i & 8;
        !           149:                i &= 7;
        !           150:        }
        !           151: } /* ideaExpandKey */
        !           152: 
        !           153: /*
        !           154:  * Compute IDEA decryption key DK from an expanded IDEA encryption key EK
        !           155:  * Note that the input and output may be the same.  Thus, the key is
        !           156:  * inverted into an internal buffer, and then copied to the output.
        !           157:  */
        !           158: static void
        !           159: ideaInvertKey(word16 const *EK, word16 DK[IDEAKEYLEN])
        !           160: {
        !           161:        int i;
        !           162:        uint16 t1, t2, t3;
        !           163:        word16 temp[IDEAKEYLEN];
        !           164:        word16 *p = temp + IDEAKEYLEN;
        !           165: 
        !           166:        t1 = mulInv(*EK++);
        !           167:        t2 = -*EK++;
        !           168:        t3 = -*EK++;
        !           169:        *--p = mulInv(*EK++);
        !           170:        *--p = t3;
        !           171:        *--p = t2;
        !           172:        *--p = t1;
        !           173: 
        !           174:        for (i = 0; i < IDEAROUNDS-1; i++) {
        !           175:                t1 = *EK++;
        !           176:                *--p = *EK++;
        !           177:                *--p = t1;
        !           178: 
        !           179:                t1 = mulInv(*EK++);
        !           180:                t2 = -*EK++;
        !           181:                t3 = -*EK++;
        !           182:                *--p = mulInv(*EK++);
        !           183:                *--p = t2;
        !           184:                *--p = t3;
        !           185:                *--p = t1;
        !           186:        }
        !           187:        t1 = *EK++;
        !           188:        *--p = *EK++;
        !           189:        *--p = t1;
        !           190: 
        !           191:        t1 = mulInv(*EK++);
        !           192:        t2 = -*EK++;
        !           193:        t3 = -*EK++;
        !           194:        *--p = mulInv(*EK++);
        !           195:        *--p = t3;
        !           196:        *--p = t2;
        !           197:        *--p = t1;
        !           198: /* Copy and destroy temp copy */
        !           199:        memcpy(DK, temp, sizeof(temp));
        !           200:        burn(temp);
        !           201: } /* ideaInvertKey */
        !           202: 
        !           203: /*
        !           204:  * MUL(x,y) computes x = x*y, modulo 0x10001.  Requires two temps, 
        !           205:  * t16 and t32.  x is modified, and must me a side-effect-free lvalue.
        !           206:  * y may be anything, but unlike x, must be strictly 16 bits even if
        !           207:  * low16() is #defined.
        !           208:  * All of these are equivalent - see which is faster on your machine
        !           209:  */
        !           210: #ifdef SMALL_CACHE
        !           211: #define MUL(x,y) (x = mul(low16(x),y))
        !           212: #else /* !SMALL_CACHE */
        !           213: #ifdef AVOID_JUMPS
        !           214: #define MUL(x,y) (x = low16(x-1), t16 = low16((y)-1), \
        !           215:                t32 = (word32)x*t16 + x + t16 + 1, x = low16(t32), \
        !           216:                t16 = t32>>16, x = (x-t16) + (x<t16) )
        !           217: #else /* !AVOID_JUMPS (default) */
        !           218: #define MUL(x,y) \
        !           219:        ((t16 = (y)) ? \
        !           220:                (x=low16(x)) ? \
        !           221:                        t32 = (word32)x*t16, \
        !           222:                        x = low16(t32), \
        !           223:                        t16 = t32>>16, \
        !           224:                        x = (x-t16)+(x<t16) \
        !           225:                : \
        !           226:                        (x = 1-t16) \
        !           227:        : \
        !           228:                (x = 1-x))
        !           229: #endif
        !           230: #endif
        !           231: 
        !           232: /*     IDEA encryption/decryption algorithm */
        !           233: /* Note that in and out can be the same buffer */
        !           234: static void
        !           235: ideaCipher(byte const (inbuf[8]), byte (outbuf[8]), word16 const *key)
        !           236: {
        !           237:        register uint16 x1, x2, x3, x4, s2, s3;
        !           238:        word16 *in, *out;
        !           239: #ifndef SMALL_CACHE
        !           240:        register uint16 t16;    /* Temporaries needed by MUL macro */
        !           241:        register word32 t32;
        !           242: #endif
        !           243:        int r = IDEAROUNDS;
        !           244: 
        !           245:        in = (word16 *)inbuf;
        !           246:        x1 = *in++;  x2 = *in++;
        !           247:        x3 = *in++;  x4 = *in;
        !           248: #ifndef HIGHFIRST
        !           249:        x1 = (x1>>8) | (x1<<8);
        !           250:        x2 = (x2>>8) | (x2<<8);
        !           251:        x3 = (x3>>8) | (x3<<8);
        !           252:        x4 = (x4>>8) | (x4<<8);
        !           253: #endif
        !           254:        do {
        !           255:                MUL(x1,*key++);
        !           256:                x2 += *key++;
        !           257:                x3 += *key++;
        !           258:                MUL(x4, *key++);
        !           259: 
        !           260:                s3 = x3;
        !           261:                x3 ^= x1;
        !           262:                MUL(x3, *key++);
        !           263:                s2 = x2;
        !           264:                x2 ^= x4;
        !           265:                x2 += x3;
        !           266:                MUL(x2, *key++);
        !           267:                x3 += x2;
        !           268: 
        !           269:                x1 ^= x2;  x4 ^= x3;
        !           270: 
        !           271:                x2 ^= s3;  x3 ^= s2;
        !           272:        } while (--r);
        !           273:        MUL(x1, *key++);
        !           274:        x3 += *key++;
        !           275:        x2 += *key++;
        !           276:        MUL(x4, *key);
        !           277: 
        !           278:        out = (word16 *)outbuf;
        !           279: #ifdef HIGHFIRST
        !           280:        *out++ = x1;
        !           281:        *out++ = x3;
        !           282:        *out++ = x2;
        !           283:        *out = x4;
        !           284: #else /* !HIGHFIRST */
        !           285:        x1 = low16(x1);
        !           286:        x2 = low16(x2);
        !           287:        x3 = low16(x3);
        !           288:        x4 = low16(x4);
        !           289:        *out++ = (x1>>8) | (x1<<8);
        !           290:        *out++ = (x3>>8) | (x3<<8);
        !           291:        *out++ = (x2>>8) | (x2<<8);
        !           292:        *out   = (x4>>8) | (x4<<8);
        !           293: #endif
        !           294: } /* ideaCipher */
        !           295: 
        !           296: /*-------------------------------------------------------------*/
        !           297: 
        !           298: #ifdef TEST
        !           299: 
        !           300: #include <stdio.h>
        !           301: #include <time.h>
        !           302: /*
        !           303:  * This is the number of Kbytes of test data to encrypt.
        !           304:  * It defaults to 1 MByte.
        !           305:  */
        !           306: #ifndef BLOCKS
        !           307: #ifndef KBYTES
        !           308: #define KBYTES 1024
        !           309: #endif
        !           310: #define BLOCKS (64*KBYTES)
        !           311: #endif
        !           312: 
        !           313: int
        !           314: main(void)
        !           315: {      /* Test driver for IDEA cipher */
        !           316:        int i, j, k;
        !           317:        byte userkey[16];
        !           318:        word16 EK[IDEAKEYLEN], DK[IDEAKEYLEN];
        !           319:        byte XX[8], YY[8], ZZ[8];
        !           320:        clock_t start, end;
        !           321:        long l;
        !           322: 
        !           323:        /* Make a sample user key for testing... */
        !           324:        for(i=0; i<16; i++)
        !           325:                userkey[i] = i+1;
        !           326: 
        !           327:        /* Compute encryption subkeys from user key... */
        !           328:        ideaExpandKey(userkey, EK);
        !           329:        printf("\nEncryption key subblocks: ");
        !           330:        for (j=0; j<IDEAROUNDS+1; j++) {
        !           331:                printf("\nround %d:   ", j+1);
        !           332:                if (j < IDEAROUNDS)
        !           333:                        for(i=0; i<6; i++)
        !           334:                                printf(" %6u", EK[j*6+i]);
        !           335:                else
        !           336:                        for(i=0; i<4; i++)
        !           337:                                printf(" %6u", EK[j*6+i]);
        !           338:        }
        !           339: 
        !           340:        /* Compute decryption subkeys from encryption subkeys... */
        !           341:        ideaInvertKey(EK, DK);
        !           342:        printf("\nDecryption key subblocks: ");
        !           343:        for (j=0; j<IDEAROUNDS+1; j++) {
        !           344:                printf("\nround %d:   ", j+1);
        !           345:                if (j < IDEAROUNDS)
        !           346:                        for(i=0; i<6; i++)
        !           347:                                printf(" %6u", DK[j*6+i]);
        !           348:                else
        !           349:                        for(i=0; i<4; i++)
        !           350:                                printf(" %6u", DK[j*6+i]);
        !           351:        }
        !           352: 
        !           353:        /* Make a sample plaintext pattern for testing... */
        !           354:        for (k=0; k<8; k++)
        !           355:                XX[k] = k;
        !           356: 
        !           357:        printf("\n Encrypting %d bytes (%ld blocks)...", BLOCKS*16, BLOCKS);
        !           358:        fflush(stdout);
        !           359:        start = clock();
        !           360:        memcpy(YY, XX, 8);
        !           361:        for (l = 0; l < BLOCKS; l++)
        !           362:                ideaCipher(YY, YY, EK); /* repeated encryption */
        !           363:        memcpy(ZZ, YY, 8);
        !           364:        for (l = 0; l < BLOCKS; l++)
        !           365:                ideaCipher(ZZ, ZZ, DK); /* repeated decryption */
        !           366:        end = clock() - start;
        !           367:        l = end  / (CLOCKS_PER_SEC/1000) + 1;
        !           368:        i = l/1000;
        !           369:        j = l%1000;
        !           370:        l = (16 * BLOCKS * (CLOCKS_PER_SEC/1000)) / (end/1000);
        !           371:        printf("%d.%03d seconds = %ld bytes per second\n", i, j, l);
        !           372: 
        !           373:        printf("\nX %3u  %3u  %3u  %3u  %3u  %3u  %3u %3u\n",
        !           374:          XX[0], XX[1],  XX[2], XX[3], XX[4], XX[5],  XX[6], XX[7]);
        !           375:        printf("\nY %3u  %3u  %3u  %3u  %3u  %3u  %3u %3u\n",
        !           376:          YY[0], YY[1],  YY[2], YY[3], YY[4], YY[5],  YY[6], YY[7]);
        !           377:        printf("\nZ %3u  %3u  %3u  %3u  %3u  %3u  %3u %3u\n",    
        !           378:          ZZ[0], ZZ[1],  ZZ[2], ZZ[3], ZZ[4], ZZ[5],  ZZ[6], ZZ[7]);
        !           379: 
        !           380:        /* Now decrypted ZZ should be same as original XX */
        !           381:        for (k=0; k<8; k++)
        !           382:                if (XX[k] != ZZ[k]) {
        !           383:                        printf("\n\07Error!  Noninvertable encryption.\n");
        !           384:                        exit(-1);       /* error exit */ 
        !           385:                }
        !           386:        printf("\nNormal exit.\n");
        !           387:        return 0;       /* normal exit */
        !           388: } /* main */
        !           389: 
        !           390: #endif /* TEST */
        !           391: 
        !           392: 
        !           393: /*************************************************************************/
        !           394: 
        !           395: void
        !           396: ideaCfbReinit(struct IdeaCfbContext *context, byte const *iv)
        !           397: {
        !           398:        if (iv)
        !           399:                memcpy(context->iv, iv, 8);
        !           400:        else
        !           401:                fill0(context->iv, 8);
        !           402:        context->bufleft = 0;
        !           403: }
        !           404: 
        !           405: void
        !           406: ideaCfbInit(struct IdeaCfbContext *context, byte const (key[16]))
        !           407: {
        !           408:        ideaExpandKey(key, context->key);
        !           409:        ideaCfbReinit(context,0);
        !           410: }
        !           411: 
        !           412: void
        !           413: ideaCfbDestroy(struct IdeaCfbContext *context)
        !           414: {
        !           415:        burn(*context);
        !           416: }
        !           417: 
        !           418: /*
        !           419:  * Okay, explanation time:
        !           420:  * Phil invented a unique way of doing CFB that's sensitive to semantic
        !           421:  * boundaries within the data being encrypted.  One way to phrase
        !           422:  * CFB en/decryption is to say that you XOR the current 8 bytes with
        !           423:  * IDEA(previous 8 bytes of ciphertext).  Normally, you repeat this
        !           424:  * at 8-byte intervals, but Phil decided to resync things on the
        !           425:  * boundaries between elements in the stream being encrypted.
        !           426:  *
        !           427:  * That is, the last 4 bytes of a 12-byte field are en/decrypted using
        !           428:  * the first 4 bytes of IDEA(previous 8 bytes of ciphertext), but then
        !           429:  * the last 4 bytes of that IDEA computation are thrown away, and the
        !           430:  * first 8 bytes of the next field are en/decrypted using
        !           431:  * IDEA(last 8 bytes of ciphertext).  This is equivalent to using a
        !           432:  * shorter feedback length (if you're familiar with the general CFB
        !           433:  * technique) briefly, and doesn't weaken the cipher any (using shorter
        !           434:  * CFB lengths makes it stronger, actually), it just makes it a bit unusual.
        !           435:  *
        !           436:  * Anyway, to accomodate this behaviour, every time we do an IDEA
        !           437:  * encrpytion of 8 bytes of ciphertext to get 8 bytes of XOR mask,
        !           438:  * we remember the ciphertext.  Then if we have to resync things
        !           439:  * after having processed, say, 2 bytes, we refill the iv buffer
        !           440:  * with the last 6 bytes of the old ciphertext followed by the
        !           441:  * 2 bytes of new ciphertext stored in the front of the iv buffer.
        !           442:  */
        !           443: void
        !           444: ideaCfbSync(struct IdeaCfbContext *context)
        !           445: {
        !           446:        int bufleft = context->bufleft;
        !           447: 
        !           448:        if (bufleft) {
        !           449:                memmove(context->iv+bufleft, context->iv, 8-bufleft);
        !           450:                memcpy(context->iv, context->oldcipher+8-bufleft, bufleft);
        !           451:                context->bufleft = 0;
        !           452:        }
        !           453: }
        !           454: 
        !           455: /*
        !           456:  * Encrypt a buffer of data, using IDEA in CFB mode.
        !           457:  * There are more compact ways of writing this, but this is
        !           458:  * written for speed.
        !           459:  */
        !           460: void
        !           461: ideaCfbEncrypt(struct IdeaCfbContext *context, byte const *src,
        !           462:               byte *dest, int count)
        !           463: {
        !           464:        int bufleft = context->bufleft;
        !           465:        byte *bufptr = context->iv + 8-bufleft;
        !           466: 
        !           467:        /* If there are no more bytes to encrypt that there are bytes
        !           468:         * in the buffer, XOR them in and return.
        !           469:         */
        !           470:        if (count <= bufleft) {
        !           471:                context->bufleft = bufleft - count;
        !           472:                while (count--) {
        !           473:                        *dest++ = *bufptr++ ^= *src++;
        !           474:                }
        !           475:                return;
        !           476:        }
        !           477:        count -= bufleft;
        !           478:        /* Encrypt the first bufleft (0 to 7) bytes of the input by XOR
        !           479:         * with the last bufleft bytes in the iv buffer.
        !           480:         */
        !           481:        while (bufleft--) {
        !           482:                *dest++ = (*bufptr++ ^= *src++);
        !           483:        }
        !           484:        /* Encrypt middle blocks of the input by cranking the cipher,
        !           485:         * XORing 8-byte blocks, and repeating until the count
        !           486:         * is 8 or less.
        !           487:         */
        !           488:        while (count > 8) {
        !           489:                bufptr = context->iv;
        !           490:                memcpy(context->oldcipher, bufptr, 8);
        !           491:                ideaCipher(bufptr, bufptr, context->key);
        !           492:                bufleft = 8;
        !           493:                count -= 8;
        !           494:                do {
        !           495:                        *dest++ = (*bufptr++ ^= *src++);
        !           496:                } while (--bufleft);
        !           497:        }
        !           498:        /* Do the last 1 to 8 bytes */
        !           499:        bufptr = context->iv;
        !           500:        memcpy(context->oldcipher, bufptr, 8);
        !           501:        ideaCipher(bufptr, bufptr, context->key);
        !           502:        context->bufleft = 8-count;
        !           503:        do  {
        !           504:                *dest++ = (*bufptr++ ^= *src++);
        !           505:        } while (--count);
        !           506: }
        !           507: 
        !           508: 
        !           509: /*
        !           510:  * Decrypt a buffer of data, using IDEA in CFB mode.
        !           511:  * There are more compact ways of writing this, but this is
        !           512:  * written for speed.
        !           513:  */
        !           514: void
        !           515: ideaCfbDecrypt(struct IdeaCfbContext *context, byte const *src,
        !           516:               byte *dest, int count)
        !           517: {
        !           518:        int bufleft = context->bufleft;
        !           519:        static byte *bufptr;
        !           520:        byte t;
        !           521: 
        !           522:        bufptr = context->iv + (8-bufleft);
        !           523:        if (count <= bufleft) {
        !           524:                context->bufleft = bufleft - count;
        !           525:                while (count--) {
        !           526:                        t = *bufptr;
        !           527:                        *dest++ = t ^ (*bufptr++ = *src++);
        !           528:                }
        !           529:                return;
        !           530:        }
        !           531:        count -= bufleft;
        !           532:        while (bufleft--) {
        !           533:                t = *bufptr;
        !           534:                *dest++ = t ^ (*bufptr++ = *src++);
        !           535:        }
        !           536:        while (count > 8) {
        !           537:                bufptr = context->iv;
        !           538:                memcpy(context->oldcipher, bufptr, 8);
        !           539:                ideaCipher(bufptr, bufptr, context->key);
        !           540:                bufleft = 8;
        !           541:                count -= 8;
        !           542:                do {
        !           543:                        t = *bufptr;
        !           544:                        *dest++ = t ^ (*bufptr++ = *src++);
        !           545:                } while (--bufleft);
        !           546:        }
        !           547:        bufptr = context->iv;
        !           548:        memcpy(context->oldcipher, bufptr, 8);
        !           549:        ideaCipher(bufptr, bufptr, context->key);
        !           550:        context->bufleft = 8-count;
        !           551:        do {
        !           552:                t = *bufptr;
        !           553:                *dest++ = t ^ (*bufptr++ = *src++);
        !           554:        } while (--count);
        !           555: }
        !           556: 
        !           557: /********************************************************************/
        !           558: 
        !           559: /*
        !           560:  * Cryptographically strong pseudo-random-number generator.
        !           561:  * The design is from Appendix C of ANSI X9.17, "Financial
        !           562:  * Institution Key Management (Wholesale)", with IDEA
        !           563:  * substituted for the DES.
        !           564:  */
        !           565: 
        !           566: /*
        !           567:  * Initialize a cryptographic random-number generator.
        !           568:  * key and seed should be arbitrary.
        !           569:  */
        !           570: void
        !           571: ideaRandInit(struct IdeaRandContext *context, byte const (key[16]),
        !           572:             byte const (seed[8]))
        !           573: {
        !           574:        int i;
        !           575: 
        !           576:        ideaExpandKey(key, context->key);
        !           577:        context->bufleft = 0;
        !           578:        memcpy(context->internalbuf, seed, 8);
        !           579: }
        !           580: 
        !           581: 
        !           582: /*
        !           583:  * Read out the RNG's state.
        !           584:  */
        !           585: void
        !           586: ideaRandState(struct IdeaRandContext *context, byte key[16], byte seed[8])
        !           587: {
        !           588:        int i;
        !           589: 
        !           590:        memcpy(seed, context->internalbuf, 8);
        !           591:        for (i = 0; i < 8; i++) {
        !           592:                key[2*i] = context->key[i] >> 8;
        !           593:                key[2*i+1] = context->key[i];
        !           594:        }
        !           595: 
        !           596: }
        !           597: 
        !           598: /*
        !           599:  * Encrypt the RNG's state with the given CFB encryptor.
        !           600:  */
        !           601: void
        !           602: ideaRandWash(struct IdeaRandContext *context, struct IdeaCfbContext *cfb)
        !           603: {
        !           604:        byte keyseed[16+8];
        !           605:        int i;
        !           606: 
        !           607:        ideaRandState(context, keyseed, keyseed+16);
        !           608:        ideaCfbEncrypt(cfb, keyseed, keyseed, 16+8);
        !           609:        ideaRandInit(context, keyseed, keyseed+16);
        !           610: 
        !           611:        memset(keyseed, 0, 16+8);
        !           612: }
        !           613: 
        !           614: /*
        !           615:  * Cryptographic pseudo-random-number generator, used for generating
        !           616:  * session keys.
        !           617:  */
        !           618: byte
        !           619: ideaRandByte(struct IdeaRandContext *c)
        !           620: {
        !           621:        int i;
        !           622: 
        !           623:        if (!c->bufleft) {
        !           624:                byte timestamp[8];
        !           625:        
        !           626:                /* Get some true-random noise to help */
        !           627:                randPoolGetBytes(timestamp, sizeof(timestamp));
        !           628: 
        !           629:                /* Compute next 8 bytes of output */
        !           630:                for (i=0; i<8; i++)
        !           631:                        c->outbuf[i] = c->internalbuf[i] ^ timestamp[i];
        !           632:                ideaCipher(c->outbuf, c->outbuf, c->key);
        !           633:                /* Compute new seed vector */
        !           634:                for (i=0; i<8; i++)
        !           635:                        c->internalbuf[i] = c->outbuf[i] ^ timestamp[i];
        !           636:                ideaCipher(c->internalbuf, c->internalbuf, c->key);
        !           637:                burn(timestamp);
        !           638:                c->bufleft = 8;
        !           639:        }
        !           640:        return c->outbuf[--c->bufleft];
        !           641: }
        !           642: 
        !           643: /* end of idea.c */
        !           644: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.