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

1.1.1.2 ! root        1: /*     idea.c - C source code for IDEA block cipher.
        !             2:  *     IDEA (International Data Encryption Algorithm), formerly known as 
        !             3:  *     IPES (Improved Proposed Encryption Standard).
        !             4:  *     Algorithm developed by Xuejia Lai and James L. Massey, of ETH Zurich.
        !             5:  *     This implementation modified and derived from original C code 
        !             6:  *     developed by Xuejia Lai.  
        !             7:  *     Zero-based indexing added, names changed from IPES to IDEA.
        !             8:  *     CFB functions added.  Random number routines added.
        !             9:  *
        !            10:  *  Optimized for speed 21 Oct 92 by Colin Plumb <[email protected]>
        !            11:  *
        !            12:  *     There are two adjustments that can be made to this code to
        !            13:  *     speed it up.  Defaults may be used for PCs.  Only the -DIDEA32
        !            14:  *     pays off significantly if selectively set or not set.  
        !            15:  *     Experiment to see what works better for you.
        !            16:  *
        !            17:  *     Multiplication: default is inline, -DAVOID_JUMPS uses a
        !            18:  *             different version that does not do any conditional
        !            19:  *             jumps (a few percent worse on a SPARC), while
        !            20:  *             -DSMALL_CACHE takes it out of line to stay
        !            21:  *             within a small on-chip code cache.
        !            22:  *     Variables: normally, 16-bit variables are used, but some
        !            23:  *             machines (notably RISCs) do not have 16-bit registers,
        !            24:  *             so they do a great deal of masking.  -DIDEA32 uses "int"
        !            25:  *             register variables and masks explicitly only where
        !            26:  *             necessary.  On a SPARC, for example, this boosts
        !            27:  *             performace by 30%.
        !            28:  *
        !            29:  *     The IDEA(tm) block cipher is covered by a patent held by ETH and a
        !            30:  *     Swiss company called Ascom-Tech AG.  The Swiss patent number is
        !            31:  *     PCT/CH91/00117.  International patents are pending. IDEA(tm) is a
        !            32:  *     trademark of Ascom-Tech AG.  There is no license fee required for
        !            33:  *     noncommercial use.  Commercial users may obtain licensing details
        !            34:  *     from Dieter Profos, Ascom Tech AG, Solothurn Lab, Postfach 151, 4502
        !            35:  *     Solothurn, Switzerland, Tel +41 65 242885, Fax +41 65 235761.
        !            36:  *
        !            37:  *     The IDEA block cipher uses a 64-bit block size, and a 128-bit key 
        !            38:  *     size.  It breaks the 64-bit cipher block into four 16-bit words
        !            39:  *     because all of the primitive inner operations are done with 16-bit 
        !            40:  *     arithmetic.  It likewise breaks the 128-bit cipher key into eight 
        !            41:  *     16-bit words.
        !            42:  *
        !            43:  *     For further information on the IDEA cipher, see these papers:
        !            44:  *     1) Xuejia Lai, "Detailed Description and a Software Implementation of 
        !            45:  *        the IPES Cipher", Institute for Signal and Information
        !            46:  *        Processing, ETH-Zentrum, Zurich, Switzerland, 1991
        !            47:  *     2) Xuejia Lai, James L. Massey, Sean Murphy, "Markov Ciphers and 
        !            48:  *        Differential Cryptanalysis", Advances in Cryptology- EUROCRYPT'91
        !            49:  *
        !            50:  *     This code assumes that each pair of 8-bit bytes comprising a 16-bit 
        !            51:  *     word in the key and in the cipher block are externally represented 
        !            52:  *     with the Most Significant Byte (MSB) first, regardless of the
        !            53:  *     internal native byte order of the target CPU.
        !            54:  */
        !            55: 
        !            56: #include "idea.h"
        !            57: 
        !            58: #ifdef TEST
        !            59: #include <stdio.h>
        !            60: #include <time.h>
        !            61: #endif
        !            62: 
        !            63: #define ROUNDS 8               /* Don't change this value, should be 8 */
        !            64: #define KEYLEN (6*ROUNDS+4)    /* length of key schedule */
        !            65: 
        !            66: typedef word16 IDEAkey[KEYLEN];
        !            67: 
        !            68: #ifdef IDEA32  /* Use >16-bit temporaries */
        !            69: #define low16(x) ((x) & 0xFFFF)
        !            70: typedef unsigned int uint16;   /* at LEAST 16 bits, maybe more */
        !            71: #else
        !            72: #define low16(x) (x)   /* this is only ever applied to uint16's */
        !            73: typedef word16 uint16;
        !            74: #endif
        !            75: 
        !            76: #ifdef _GNUC_
        !            77: /* __const__ simply means there are no side effects for this function,
        !            78:  * which is useful info for the gcc optimizer */
        !            79: #define CONST __const__
        !            80: #else
        !            81: #define CONST
        !            82: #endif
        !            83: 
        !            84: static void en_key_idea(word16 userkey[8], IDEAkey Z);
        !            85: static void de_key_idea(IDEAkey Z, IDEAkey DK);
        !            86: static void cipher_idea(word16 in[4], word16 out[4], CONST IDEAkey Z);
        !            87: 
        !            88: /*
        !            89:  *     Multiplication, modulo (2**16)+1
        !            90:  * Note that this code is structured like this on the assumption that
        !            91:  * untaken branches are cheaper than taken branches, and the compiler
        !            92:  * doesn't schedule branches.
        !            93:  */
        !            94: #ifdef SMALL_CACHE
        !            95: CONST static uint16 mul(register uint16 a, register uint16 b)
        !            96: {
        !            97:        register word32 p;
        !            98: 
        !            99:        if (a)
        !           100:        {       if (b)
        !           101:                {       p = (word32)a * b;
        !           102:                        b = low16(p);
        !           103:                        a = p>>16;
        !           104:                        return b - a + (b < a);
        !           105:                }
        !           106:                else
        !           107:                {       return 1-a;
        !           108:                }
        !           109:        }
        !           110:        else
        !           111:        {       return 1-b;
        !           112:        }
        !           113: }        /* mul */
        !           114: #endif /* SMALL_CACHE */
        !           115: 
        !           116: /*
        !           117:  *     Compute multiplicative inverse of x, modulo (2**16)+1,
        !           118:  *     using Euclid's GCD algorithm.  It is unrolled twice to
        !           119:  *     avoid swapping the meaning of the registers each iteration,
        !           120:  *     and some subtracts of t have been changed to adds.
        !           121:  */
        !           122: CONST static uint16 inv(uint16 x)     
        !           123: {
        !           124:        uint16 t0, t1;
        !           125:        uint16 q, y;
        !           126: 
        !           127:        if (x <= 1)
        !           128:                return x;       /* 0 and 1 are self-inverse */
        !           129:        t1 = 0x10001 / x;       /* Since x >= 2, this fits into 16 bits */
        !           130:        y = 0x10001 % x;
        !           131:        if (y == 1)
        !           132:                return low16(1-t1);
        !           133:        t0 = 1;
        !           134:        do
        !           135:        {       q = x / y;
        !           136:                x = x % y;
        !           137:                t0 += q * t1;
        !           138:                if (x == 1)
        !           139:                        return t0;
        !           140:                q = y / x;
        !           141:                y = y % x;
        !           142:                t1 += q * t0;
        !           143:        } while (y != 1);
        !           144:        return low16(1-t1);
        !           145: } /* inv */
        !           146: 
        !           147: /*     Compute IDEA encryption subkeys Z */
        !           148: static void en_key_idea(word16 *userkey, word16 *Z)
        !           149: {
        !           150:        int i,j;
        !           151: 
        !           152:        /*
        !           153:         * shifts
        !           154:         */
        !           155:        for (j=0; j<8; j++)
        !           156:                Z[j] = *userkey++;
        !           157: 
        !           158:        for (i=0; j<KEYLEN; j++)
        !           159:        {       i++;
        !           160:                Z[i+7] = Z[i & 7] << 9 | Z[i+1 & 7] >> 7;
        !           161:                Z += i & 8;
        !           162:                i &= 7;
        !           163:        }
        !           164: }        /* en_key_idea */
        !           165: 
        !           166: /*     Compute IDEA decryption subkeys DK from encryption subkeys Z */
        !           167: /* Note: these buffers *may* overlap! */
        !           168: static void de_key_idea(IDEAkey Z, IDEAkey DK)
        !           169: {
        !           170:        int j;
        !           171:        uint16 t1, t2, t3;
        !           172:        IDEAkey T;
        !           173:        word16 *p = T + KEYLEN;
        !           174: 
        !           175:        t1 = inv(*Z++);
        !           176:        t2 = -*Z++;
        !           177:        t3 = -*Z++;
        !           178:        *--p = inv(*Z++);
        !           179:        *--p = t3;
        !           180:        *--p = t2;
        !           181:        *--p = t1;
        !           182: 
        !           183:        for (j = 1; j < ROUNDS; j++)
        !           184:        {
        !           185:                t1 = *Z++;
        !           186:                *--p = *Z++;
        !           187:                *--p = t1;
        !           188: 
        !           189:                t1 = inv(*Z++);
        !           190:                t2 = -*Z++;
        !           191:                t3 = -*Z++;
        !           192:                *--p = inv(*Z++);
        !           193:                *--p = t2;
        !           194:                *--p = t3;
        !           195:                *--p = t1;
        !           196:        }
        !           197:        t1 = *Z++;
        !           198:        *--p = *Z++;
        !           199:        *--p = t1;
        !           200: 
        !           201:        t1 = inv(*Z++);
        !           202:        t2 = -*Z++;
        !           203:        t3 = -*Z++;
        !           204:        *--p = inv(*Z++);
        !           205:        *--p = t3;
        !           206:        *--p = t2;
        !           207:        *--p = t1;
        !           208: /* Copy and destroy temp copy */
        !           209:        for (j = 0, p = T; j < KEYLEN; j++)
        !           210:        {
        !           211:                *DK++ = *p;
        !           212:                *p++ = 0;
        !           213:        }
        !           214: } /* de_key_idea */
        !           215: 
        !           216: /*
        !           217:  * MUL(x,y) computes x = x*y, modulo 0x10001.  Requires two temps, 
        !           218:  * t16 and t32.  x must me a side-effect-free lvalue.  y may be 
        !           219:  * anything, but unlike x, must be strictly 16 bits even if low16() 
        !           220:  * is #defined.
        !           221:  * All of these are equivalent - see which is faster on your machine
        !           222:  */
        !           223: #ifdef SMALL_CACHE
        !           224: #define MUL(x,y) (x = mul(low16(x),y))
        !           225: #else
        !           226: #ifdef AVOID_JUMPS
        !           227: #define MUL(x,y) (x = low16(x-1), t16 = low16((y)-1), \
        !           228:                t32 = (word32)x*t16+x+t16+1, x = low16(t32), \
        !           229:                t16 = t32>>16, x = x-t16+(x<t16) )
        !           230: #else
        !           231: #define MUL(x,y) ((t16 = (y)) ? (x=low16(x)) ? \
        !           232:         t32 = (word32)x*t16, x = low16(t32), t16 = t32>>16, \
        !           233:         x = x-t16+(x<t16) : \
        !           234:         (x = 1-t16) : (x = 1-x))
        !           235: #endif
        !           236: #endif
        !           237: 
        !           238: /*     IDEA encryption/decryption algorithm */
        !           239: /* Note that in and out can be the same buffer */ 
        !           240: static void cipher_idea(word16 in[4], word16 out[4], register CONST IDEAkey Z)
        !           241: {
        !           242:        register uint16 x1, x2, x3, x4, t1, t2;
        !           243:        register uint16 t16;
        !           244:        register word32 t32;
        !           245: 
        !           246:        int r = ROUNDS;
        !           247: 
        !           248:        x1 = *in++;  x2 = *in++;
        !           249:        x3 = *in++;  x4 = *in;
        !           250:        do
        !           251:        {
        !           252:                MUL(x1,*Z++);
        !           253:                x2 += *Z++;
        !           254:                x3 += *Z++;
        !           255:                MUL(x4, *Z++);
        !           256: 
        !           257:                t2 = x1^x3;
        !           258:                MUL(t2, *Z++);
        !           259:                t1 = t2 + (x2^x4);
        !           260:                MUL(t1, *Z++);
        !           261:                t2 = t1+t2;
        !           262: 
        !           263:                x1 ^= t1;
        !           264:                x4 ^= t2; 
        !           265: 
        !           266:                t2 ^= x2;
        !           267:                x2 = x3^t1;
        !           268:                x3 = t2;
        !           269:        } while (--r);
        !           270:        MUL(x1, *Z++);
        !           271:        *out++ = x1;
        !           272:        *out++ = x3 + *Z++;
        !           273:        *out++ = x2 + *Z++;
        !           274:        MUL(x4, *Z);
        !           275:        *out = x4;
        !           276: } /* cipher_idea */
        !           277: 
        !           278: /*-------------------------------------------------------------*/
        !           279: 
        !           280: #ifdef TEST
        !           281: /*
        !           282:  * This is the number of Kbytes of test data to encrypt.
        !           283:  * It defaults to 1 MByte.
        !           284:  */
        !           285: #ifndef KBYTES
        !           286: #define KBYTES 1024
        !           287: #endif
        !           288: 
        !           289: void main(void)
        !           290: {      /* Test driver for IDEA cipher */ 
        !           291:        int i, j, k; 
        !           292:        IDEAkey Z, DK;
        !           293:        word16 XX[4], TT[4], YY[4];     
        !           294:        word16 userkey[8];
        !           295:        clock_t start, end;
        !           296:        long l;
        !           297: 
        !           298:        /* Make a sample user key for testing... */
        !           299:        for(i=0; i<8; i++)
        !           300:                userkey[i] = i+1;
        !           301: 
        !           302:        /* Compute encryption subkeys from user key... */
        !           303:        en_key_idea(userkey,Z);
        !           304:        printf("\nEncryption key subblocks: ");
        !           305:        for(j=0; j<ROUNDS+1; j++)
        !           306:        {
        !           307:                printf("\nround %d:   ", j+1);
        !           308:                if (j==ROUNDS)
        !           309:                        for(i=0; i<4; i++)
        !           310:                                printf(" %6u", Z[j*6+i]);
        !           311:                else
        !           312:                        for(i=0; i<6; i++)
        !           313:                                printf(" %6u", Z[j*6+i]);
        !           314:        }
        !           315: 
        !           316:        /* Compute decryption subkeys from encryption subkeys... */
        !           317:        de_key_idea(Z,DK);
        !           318:        printf("\nDecryption key subblocks: ");
        !           319:        for(j=0; j<ROUNDS+1; j++)
        !           320:        {
        !           321:                printf("\nround %d:   ", j+1);
        !           322:                if (j==ROUNDS)
        !           323:                        for(i=0; i<4; i++)
        !           324:                                printf(" %6u", DK[j*6+i]);
        !           325:                else
        !           326:                        for(i=0; i<6; i++)
        !           327:                                printf(" %6u", DK[j*6+i]);
        !           328:        }
        !           329: 
        !           330:        /* Make a sample plaintext pattern for testing... */
        !           331:        for (k=0; k<4; k++)
        !           332:                XX[k] = k;
        !           333: 
        !           334:        printf("\n Encrypting %d KBytes (%ld blocks)...", KBYTES, KBYTES*64l);
        !           335:        fflush(stdout);
        !           336:        start = clock();
        !           337:        cipher_idea(XX,YY,Z);       /* encrypt plaintext XX, making YY */ 
        !           338:        for (l = 1; l < 64*KBYTES; l++)
        !           339:                cipher_idea(YY,YY,Z);   /* repeated encryption */
        !           340:        cipher_idea(YY,TT,DK);      /* decrypt ciphertext YY, making TT */ 
        !           341:        for (l = 1; l < 64*KBYTES; l++)
        !           342:                cipher_idea(TT,TT,DK);  /* repeated decryption */
        !           343:        end = clock() - start;
        !           344:        l = end * 1000. / CLOCKS_PER_SEC + 1;
        !           345:        i = l/1000;
        !           346:        j = l%1000;
        !           347:        l = KBYTES * 1024. * CLOCKS_PER_SEC / end;
        !           348:        printf("%d.%03d seconds = %ld bytes per second\n", i, j, l);
        !           349: 
        !           350:        printf("\nX %6u   %6u  %6u  %6u \n",    
        !           351:          XX[0], XX[1],  XX[2], XX[3]);
        !           352:        printf("Y %6u   %6u  %6u  %6u \n",
        !           353:          YY[0], YY[1],  YY[2], YY[3]);
        !           354:        printf("T %6u   %6u  %6u  %6u \n",
        !           355:          TT[0], TT[1],  TT[2], TT[3]);
        !           356: 
        !           357:        /* Now decrypted TT should be same as original XX */
        !           358:        for (k=0; k<4; k++)
        !           359:                if (TT[k] != XX[k])
        !           360:                {
        !           361:                        printf("\n\07Error!  Noninvertable encryption.\n");
        !           362:                        exit(-1);       /* error exit */ 
        !           363:                }
        !           364:        printf("\nNormal exit.\n");
        !           365:        exit(0);        /* normal exit */ 
        !           366: }        /* main */
        !           367: 
        !           368: 
        !           369: #endif         /* TEST */
        !           370: 
        !           371: 
        !           372: /*************************************************************************/
        !           373: 
        !           374: 
        !           375: /*
        !           376:  *     xorbuf - change buffer via xor with random mask block
        !           377:  *     Used for Cipher Feedback (CFB) or Cipher Block Chaining
        !           378:  *     (CBC) modes of encryption.
        !           379:  *     Can be applied for any block encryption algorithm,
        !           380:  *     with any block size, such as the DES or the IDEA cipher.
        !           381:  */
        !           382: static void xorbuf(register byteptr buf, register byteptr mask, 
        !           383:        register int count)
        !           384: /*     count must be > 0 */
        !           385: {
        !           386:        if (count) 
        !           387:                do
        !           388:                        *buf++ ^= *mask++;
        !           389:                while (--count);
        !           390: }      /* xorbuf */
        !           391: 
        !           392: 
        !           393: /*
        !           394:  *     cfbshift - shift bytes into IV for CFB input
        !           395:  *     Used only for Cipher Feedback (CFB) mode of encryption.
        !           396:  *     Can be applied for any block encryption algorithm with any 
        !           397:  *     block size, such as the DES or the IDEA cipher.
        !           398:  */
        !           399: static void cfbshift(register byteptr iv, register byteptr buf, 
        !           400:                register int count, int blocksize)
        !           401: /*     iv is the initialization vector.
        !           402:  *     buf is the buffer pointer.
        !           403:  *     count is the number of bytes to shift in...must be > 0.
        !           404:  *     blocksize is 8 bytes for DES or IDEA ciphers.
        !           405:  */
        !           406: {
        !           407:        int retained;
        !           408:        if (count)
        !           409:        {
        !           410:                retained = blocksize-count;     /* number bytes in iv to retain */
        !           411:                /* left-shift retained bytes of IV over by count bytes to make room */
        !           412:                while (retained--)
        !           413:                {
        !           414:                        *iv = *(iv+count);
        !           415:                        iv++;
        !           416:                }
        !           417:                /* now copy count bytes from buf to shifted tail of IV */
        !           418:                do      *iv++ = *buf++;
        !           419:                while (--count);
        !           420:        }
        !           421: }      /* cfbshift */
        !           422: 
        !           423: 
        !           424: 
        !           425: /* Key schedules for IDEA encryption and decryption */
        !           426: static IDEAkey Z, DK;
        !           427: static word16 *iv_idea;                /* pointer to IV for CFB or CBC */
        !           428: static boolean cfb_dc_idea; /* TRUE iff CFB decrypting */
        !           429: 
        !           430: 
        !           431: /* initkey_idea initializes IDEA for ECB mode operations */
        !           432: void initkey_idea(byte key[16], boolean decryp)
        !           433: {
        !           434:        word16 userkey[8];      /* IDEA key is 16 bytes long */
        !           435:        int i;
        !           436:        /* Assume each pair of bytes comprising a word is ordered MSB-first. */
        !           437:        for (i=0; i<8; i++)
        !           438:        {
        !           439:                userkey[i] = (key[0]<<8) + key[1];
        !           440:                key++; key++;
        !           441:        }
        !           442:        en_key_idea(userkey,Z);
        !           443:        if (decryp)
        !           444:        {
        !           445:                de_key_idea(Z,Z);       /* compute inverse key schedule DK */
        !           446:        }
        !           447:        for (i=0; i<8; i++)     /* Erase dangerous traces */
        !           448:                userkey[i] = 0;
        !           449: } /* initkey_idea */
        !           450: 
        !           451: 
        !           452: /*     Run a 64-bit block thru IDEA in ECB (Electronic Code Book) mode,
        !           453:        using the currently selected key schedule.
        !           454: */
        !           455: void idea_ecb(word16 *inbuf, word16 *outbuf)
        !           456: {
        !           457:        /* Assume each pair of bytes comprising a word is ordered MSB-first. */
        !           458: #ifndef HIGHFIRST      /* If this is a least-significant-byte-first CPU */
        !           459:        word16 x;
        !           460: 
        !           461:        /* Invert the byte order for each 16-bit word for internal use. */
        !           462:        x = inbuf[0]; outbuf[0] = x >> 8 | x << 8;
        !           463:        x = inbuf[1]; outbuf[1] = x >> 8 | x << 8;
        !           464:        x = inbuf[2]; outbuf[2] = x >> 8 | x << 8;
        !           465:        x = inbuf[3]; outbuf[3] = x >> 8 | x << 8;
        !           466:        cipher_idea(outbuf, outbuf, Z);
        !           467:        x = outbuf[0]; outbuf[0] = x >> 8 | x << 8;
        !           468:        x = outbuf[1]; outbuf[1] = x >> 8 | x << 8;
        !           469:        x = outbuf[2]; outbuf[2] = x >> 8 | x << 8;
        !           470:        x = outbuf[3]; outbuf[3] = x >> 8 | x << 8;
        !           471: #else  /* HIGHFIRST */
        !           472:        /* Byte order for internal and external representations is the same. */
        !           473:        cipher_idea(inbuf, outbuf, Z);
        !           474: #endif /* HIGHFIRST */
        !           475: } /* idea_ecb */
        !           476: 
        !           477: 
        !           478: /*
        !           479:  *     initcfb - Initializes the IDEA key schedule tables via key,
        !           480:  *     and initializes the Cipher Feedback mode IV.
        !           481:  *     References context variables cfb_dc_idea and iv_idea.
        !           482:  */
        !           483: void initcfb_idea(word16 iv0[4], byte key[16], boolean decryp)
        !           484: /*     iv0 is copied to global iv_idea, buffer will be destroyed by ideacfb.
        !           485:        key is pointer to key buffer.
        !           486:        decryp is TRUE if decrypting, FALSE if encrypting.
        !           487: */
        !           488: {
        !           489:        iv_idea = iv0;
        !           490:        cfb_dc_idea = decryp;
        !           491:        initkey_idea(key,FALSE);
        !           492: } /* initcfb_idea */
        !           493: 
        !           494: 
        !           495: /*
        !           496:  *     ideacfb - encipher a buffer with IDEA enciphering algorithm,
        !           497:  *             using Cipher Feedback (CFB) mode.
        !           498:  *
        !           499:  *     Assumes initcfb_idea has already been called.
        !           500:  *     References context variables cfb_dc_idea and iv_idea.
        !           501:  */
        !           502: void ideacfb(byteptr buf, int count)
        !           503: /*     buf is input, output buffer, may be more than 1 block.
        !           504:  *     count is byte count of buffer.  May be > IDEABLOCKSIZE.
        !           505:  */
        !           506: {
        !           507:        int chunksize;  /* smaller of count, IDEABLOCKSIZE */
        !           508:        word16 temp[IDEABLOCKSIZE/2];
        !           509: 
        !           510:        while ((chunksize = min(count,IDEABLOCKSIZE)) > 0)
        !           511:        {
        !           512:                idea_ecb(iv_idea,temp);  /* encrypt iv_idea, making temp. */ 
        !           513: 
        !           514:                if (cfb_dc_idea)        /* buf is ciphertext */
        !           515:                        /* shift in ciphertext to IV... */
        !           516:                        cfbshift((byte *)iv_idea,buf,chunksize,IDEABLOCKSIZE);
        !           517: 
        !           518:                /* convert buf via xor */
        !           519:                xorbuf(buf,(byte *)temp,chunksize); /* buf now has enciphered output */
        !           520: 
        !           521:                if (!cfb_dc_idea)       /* buf was plaintext, is now ciphertext */
        !           522:                        /* shift in ciphertext to IV... */
        !           523:                        cfbshift((byte *)iv_idea,buf,chunksize,IDEABLOCKSIZE);
        !           524: 
        !           525:                count -= chunksize;
        !           526:                buf += chunksize;
        !           527:        }
        !           528: } /* ideacfb */
        !           529: 
        !           530: 
        !           531: /*
        !           532:        close_idea function erases all the key schedule information when 
        !           533:        we are all done with a set of operations for a particular IDEA key 
        !           534:        context.  This is to prevent any sensitive data from being left 
        !           535:        around in memory.
        !           536: */
        !           537: void close_idea(void)  /* erase current key schedule tables */
        !           538: {
        !           539:        short i;
        !           540:        for (i = 0; i < KEYLEN; i++)
        !           541:                Z[i] = 0;
        !           542: }      /* close_idea() */
        !           543: 
        !           544: /********************************************************************/
        !           545: 
        !           546: /*
        !           547:  *     These buffers are used by init_idearand, idearand, and close_idearand.
        !           548:  */
        !           549: static word16 dtbuf_idea[4] = {0}; /* buffer for enciphered timestamp */
        !           550: static word16 randseed_idea[4] = {0}; /* seed for IDEA random # generator */
        !           551: static word16 randbuf_idea[4] = {0}; /* buffer for IDEA random # generator */
        !           552: static byte randbuf_idea_counter = 0;  /* # of random bytes left in randbuf_idea */
        !           553: 
        !           554: /*
        !           555:  *     init_idearand - initialize idearand, IDEA random number generator.
        !           556:  *             Used for generating cryptographically strong random numbers.
        !           557:  *             Much of the design comes from Appendix C of ANSI X9.17.
        !           558:  *             key is pointer to IDEA key buffer.
        !           559:  *             seed is pointer to random number seed buffer.
        !           560:  *             tstamp is a 32-bit timestamp
        !           561:  */
        !           562: void init_idearand(byte key[16], byte seed[8], word32 tstamp)
        !           563: {
        !           564:        int i;
        !           565:        initkey_idea(key, FALSE);       /* initialize IDEA */
        !           566: 
        !           567:        for (i=0; i<4; i++)             /* capture timestamp material */
        !           568:        {       dtbuf_idea[i] = tstamp; /* get bottom word */
        !           569:                tstamp = tstamp >> 16;  /* drop bottom word */
        !           570:                /* tstamp has only 4 bytes-- last 4 bytes will always be 0 */
        !           571:        }
        !           572:        /* Start with enciphered timestamp: */
        !           573:        idea_ecb(dtbuf_idea,dtbuf_idea);
        !           574: 
        !           575:        /* initialize seed material */
        !           576:        for (i=0; i<8; i++)
        !           577:                ((byte *)randseed_idea)[i] = seed[i];
        !           578: 
        !           579:        randbuf_idea_counter = 0;       /* # of random bytes left in randbuf_idea */
        !           580: 
        !           581: } /* init_idearand */
        !           582: 
        !           583: 
        !           584: /*
        !           585:  *     idearand - IDEA pseudo-random number generator
        !           586:  *             Used for generating cryptographically strong random numbers.
        !           587:  *             Much of the design comes from Appendix C of ANSI X9.17.
        !           588:  */
        !           589: byte idearand(void)
        !           590: {
        !           591:        int i;
        !           592:        if (randbuf_idea_counter==0)    /* if random buffer is spent...*/
        !           593:        {       /* Combine enciphered timestamp with seed material: */
        !           594:                for (i=0; i<4; i++)
        !           595:                        randseed_idea[i] ^= dtbuf_idea[i];
        !           596:                idea_ecb(randseed_idea,randbuf_idea); /* fill new block */
        !           597: 
        !           598:                /* Compute new seed vector: */
        !           599:                for (i=0; i<4; i++)
        !           600:                        randseed_idea[i] = randbuf_idea[i] ^ dtbuf_idea[i];
        !           601:                idea_ecb(randseed_idea,randseed_idea); /* fill new seed */
        !           602: 
        !           603:                randbuf_idea_counter = 8;       /* reset counter for full buffer */
        !           604:        }
        !           605:        /* Take a byte from randbuf_idea: */
        !           606:        return(((byte *)randbuf_idea)[--randbuf_idea_counter]);
        !           607: } /* idearand */
        !           608: 
        !           609: 
        !           610: void close_idearand(void)
        !           611: {      /* Erase random IDEA buffers and wipe out IDEA key info */
        !           612:        int i;
        !           613:        for (i=0; i<4; i++)
        !           614:        {       randbuf_idea[i] = 0;
        !           615:                randseed_idea[i] = 0;
        !           616:                dtbuf_idea[i] = 0;
        !           617:        }
        !           618:        close_idea();   /* erase current key schedule tables */
        !           619: }      /* close_idearand */
        !           620: 
        !           621: /* end of idea.c */
        !           622: 

unix.superglobalmegacorp.com

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