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

1.1.1.5   root        1: /*
1.1.1.6 ! root        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.
1.1.1.5   root       10:  *
1.1.1.6 ! root       11:  *      Extensively optimized and restructured by Colin Plumb.
1.1.1.5   root       12:  *
1.1.1.6 ! root       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.
1.1.1.5   root       17:  *
1.1.1.6 ! root       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%.
1.1.1.5   root       29:  *
1.1.1.6 ! root       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.
1.1.1.5   root       38:  *
1.1.1.6 ! root       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.
1.1.1.5   root       44:  *
1.1.1.6 ! root       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.
1.1.1.5   root       50:  *
1.1.1.6 ! root       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.
1.1.1.5   root       55:  */
                     56: 
                     57: #include "idea.h"
                     58: #include "randpool.h"
                     59: 
1.1.1.6 ! root       60: #ifdef IDEA32                  /* Use >16-bit temporaries */
1.1.1.5   root       61: #define low16(x) ((x) & 0xFFFF)
                     62: typedef unsigned int uint16;   /* at LEAST 16 bits, maybe more */
                     63: #else
1.1.1.6 ! root       64: #define low16(x) (x)           /* this is only ever applied to uint16's */
1.1.1.5   root       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: /*
1.1.1.6 ! root       78:  * Multiplication, modulo (2**16)+1
1.1.1.5   root       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
1.1.1.6 ! root       85:  mul(register uint16 a, register uint16 b)
1.1.1.5   root       86: {
1.1.1.6 ! root       87:     register word32 p;
1.1.1.5   root       88: 
1.1.1.6 ! root       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 */
1.1.1.5   root      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
1.1.1.6 ! root      108:  mulInv(uint16 x)
1.1.1.5   root      109: {
1.1.1.6 ! root      110:     uint16 t0, t1;
        !           111:     uint16 q, y;
1.1.1.5   root      112: 
1.1.1.6 ! root      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 */
1.1.1.5   root      132: 
                    133: /*
                    134:  * Expand a 128-bit user key to a working encryption key EK
                    135:  */
1.1.1.6 ! root      136: static void ideaExpandKey(byte const *userkey, word16 * EK)
1.1.1.5   root      137: {
1.1.1.6 ! root      138:     int i, j;
1.1.1.5   root      139: 
1.1.1.6 ! root      140:     for (j = 0; j < 8; j++) {
        !           141:        EK[j] = (userkey[0] << 8) + userkey[1];
        !           142:        userkey += 2;
        !           143:     }
        !           144:     for (i = 0; j < IDEAKEYLEN; j++) {
        !           145:        i++;
        !           146:        EK[i + 7] = EK[i & 7] << 9 | EK[i + 1 & 7] >> 7;
        !           147:        EK += i & 8;
        !           148:        i &= 7;
        !           149:     }
        !           150: }                              /* ideaExpandKey */
1.1.1.5   root      151: 
                    152: /*
                    153:  * Compute IDEA decryption key DK from an expanded IDEA encryption key EK
                    154:  * Note that the input and output may be the same.  Thus, the key is
                    155:  * inverted into an internal buffer, and then copied to the output.
                    156:  */
1.1.1.6 ! root      157: static void ideaInvertKey(word16 const *EK, word16 DK[IDEAKEYLEN])
1.1.1.5   root      158: {
1.1.1.6 ! root      159:     int i;
        !           160:     uint16 t1, t2, t3;
        !           161:     word16 temp[IDEAKEYLEN];
        !           162:     word16 *p = temp + IDEAKEYLEN;
        !           163: 
        !           164:     t1 = mulInv(*EK++);
        !           165:     t2 = -*EK++;
        !           166:     t3 = -*EK++;
        !           167:     *--p = mulInv(*EK++);
        !           168:     *--p = t3;
        !           169:     *--p = t2;
        !           170:     *--p = t1;
1.1.1.5   root      171: 
1.1.1.6 ! root      172:     for (i = 0; i < IDEAROUNDS - 1; i++) {
1.1.1.5   root      173:        t1 = *EK++;
                    174:        *--p = *EK++;
                    175:        *--p = t1;
                    176: 
                    177:        t1 = mulInv(*EK++);
                    178:        t2 = -*EK++;
                    179:        t3 = -*EK++;
                    180:        *--p = mulInv(*EK++);
                    181:        *--p = t2;
1.1.1.6 ! root      182:        *--p = t3;
1.1.1.5   root      183:        *--p = t1;
1.1.1.6 ! root      184:     }
        !           185:     t1 = *EK++;
        !           186:     *--p = *EK++;
        !           187:     *--p = t1;
        !           188: 
        !           189:     t1 = mulInv(*EK++);
        !           190:     t2 = -*EK++;
        !           191:     t3 = -*EK++;
        !           192:     *--p = mulInv(*EK++);
        !           193:     *--p = t3;
        !           194:     *--p = t2;
        !           195:     *--p = t1;
1.1.1.5   root      196: /* Copy and destroy temp copy */
1.1.1.6 ! root      197:     memcpy(DK, temp, sizeof(temp));
        !           198:     burn(temp);
        !           199: }                              /* ideaInvertKey */
1.1.1.5   root      200: 
                    201: /*
                    202:  * MUL(x,y) computes x = x*y, modulo 0x10001.  Requires two temps, 
                    203:  * t16 and t32.  x is modified, and must me a side-effect-free lvalue.
                    204:  * y may be anything, but unlike x, must be strictly 16 bits even if
                    205:  * low16() is #defined.
                    206:  * All of these are equivalent - see which is faster on your machine
                    207:  */
                    208: #ifdef SMALL_CACHE
                    209: #define MUL(x,y) (x = mul(low16(x),y))
1.1.1.6 ! root      210: #else                          /* !SMALL_CACHE */
1.1.1.5   root      211: #ifdef AVOID_JUMPS
                    212: #define MUL(x,y) (x = low16(x-1), t16 = low16((y)-1), \
                    213:                t32 = (word32)x*t16 + x + t16 + 1, x = low16(t32), \
                    214:                t16 = t32>>16, x = (x-t16) + (x<t16) )
1.1.1.6 ! root      215: #else                          /* !AVOID_JUMPS (default) */
1.1.1.5   root      216: #define MUL(x,y) \
                    217:        ((t16 = (y)) ? \
                    218:                (x=low16(x)) ? \
                    219:                        t32 = (word32)x*t16, \
                    220:                        x = low16(t32), \
                    221:                        t16 = t32>>16, \
                    222:                        x = (x-t16)+(x<t16) \
                    223:                : \
                    224:                        (x = 1-t16) \
                    225:        : \
                    226:                (x = 1-x))
                    227: #endif
                    228: #endif
                    229: 
1.1.1.6 ! root      230: /*      IDEA encryption/decryption algorithm */
1.1.1.5   root      231: /* Note that in and out can be the same buffer */
1.1.1.6 ! root      232: static void ideaCipher(byte const inbuf[8], byte outbuf[8],
        !           233:                       word16 const *key)
1.1.1.5   root      234: {
1.1.1.6 ! root      235:     register uint16 x1, x2, x3, x4, s2, s3;
        !           236:     word16 *in, *out;
1.1.1.5   root      237: #ifndef SMALL_CACHE
1.1.1.6 ! root      238:     register uint16 t16;       /* Temporaries needed by MUL macro */
        !           239:     register word32 t32;
1.1.1.5   root      240: #endif
1.1.1.6 ! root      241:     int r = IDEAROUNDS;
1.1.1.5   root      242: 
1.1.1.6 ! root      243:     in = (word16 *) inbuf;
        !           244:     x1 = *in++;
        !           245:     x2 = *in++;
        !           246:     x3 = *in++;
        !           247:     x4 = *in;
1.1.1.5   root      248: #ifndef HIGHFIRST
1.1.1.6 ! root      249:     x1 = (x1 >> 8) | (x1 << 8);
        !           250:     x2 = (x2 >> 8) | (x2 << 8);
        !           251:     x3 = (x3 >> 8) | (x3 << 8);
        !           252:     x4 = (x4 >> 8) | (x4 << 8);
1.1.1.5   root      253: #endif
1.1.1.6 ! root      254:     do {
1.1.1.5   root      255:        MUL(x1, *key++);
                    256:        x2 += *key++;
1.1.1.6 ! root      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;
        !           270:        x4 ^= x3;
        !           271: 
        !           272:        x2 ^= s3;
        !           273:        x3 ^= s2;
        !           274:     } while (--r);
        !           275:     MUL(x1, *key++);
        !           276:     x3 += *key++;
        !           277:     x2 += *key++;
        !           278:     MUL(x4, *key);
1.1.1.5   root      279: 
1.1.1.6 ! root      280:     out = (word16 *) outbuf;
1.1.1.5   root      281: #ifdef HIGHFIRST
1.1.1.6 ! root      282:     *out++ = x1;
        !           283:     *out++ = x3;
        !           284:     *out++ = x2;
        !           285:     *out = x4;
        !           286: #else                          /* !HIGHFIRST */
        !           287:     x1 = low16(x1);
        !           288:     x2 = low16(x2);
        !           289:     x3 = low16(x3);
        !           290:     x4 = low16(x4);
        !           291:     *out++ = (x1 >> 8) | (x1 << 8);
        !           292:     *out++ = (x3 >> 8) | (x3 << 8);
        !           293:     *out++ = (x2 >> 8) | (x2 << 8);
        !           294:     *out = (x4 >> 8) | (x4 << 8);
1.1.1.5   root      295: #endif
1.1.1.6 ! root      296: }                              /* ideaCipher */
1.1.1.5   root      297: 
                    298: /*-------------------------------------------------------------*/
                    299: 
                    300: #ifdef TEST
                    301: 
                    302: #include <stdio.h>
                    303: #include <time.h>
                    304: /*
                    305:  * This is the number of Kbytes of test data to encrypt.
                    306:  * It defaults to 1 MByte.
                    307:  */
                    308: #ifndef BLOCKS
                    309: #ifndef KBYTES
                    310: #define KBYTES 1024
                    311: #endif
                    312: #define BLOCKS (64*KBYTES)
                    313: #endif
                    314: 
1.1.1.6 ! root      315: int main(void)
        !           316: {                              /* Test driver for IDEA cipher */
        !           317:     int i, j, k;
        !           318:     byte userkey[16];
        !           319:     word16 EK[IDEAKEYLEN], DK[IDEAKEYLEN];
        !           320:     byte XX[8], YY[8], ZZ[8];
        !           321:     clock_t start, end;
        !           322:     long l;
        !           323: 
        !           324:     /* Make a sample user key for testing... */
        !           325:     for (i = 0; i < 16; i++)
        !           326:        userkey[i] = i + 1;
        !           327: 
        !           328:     /* Compute encryption subkeys from user key... */
        !           329:     ideaExpandKey(userkey, EK);
        !           330:     printf("\nEncryption key subblocks: ");
        !           331:     for (j = 0; j < IDEAROUNDS + 1; j++) {
        !           332:        printf("\nround %d:   ", j + 1);
        !           333:        if (j < IDEAROUNDS)
        !           334:            for (i = 0; i < 6; i++)
        !           335:                printf(" %6u", EK[j * 6 + i]);
        !           336:        else
        !           337:            for (i = 0; i < 4; i++)
        !           338:                printf(" %6u", EK[j * 6 + i]);
        !           339:     }
        !           340: 
        !           341:     /* Compute decryption subkeys from encryption subkeys... */
        !           342:     ideaInvertKey(EK, DK);
        !           343:     printf("\nDecryption key subblocks: ");
        !           344:     for (j = 0; j < IDEAROUNDS + 1; j++) {
        !           345:        printf("\nround %d:   ", j + 1);
        !           346:        if (j < IDEAROUNDS)
        !           347:            for (i = 0; i < 6; i++)
        !           348:                printf(" %6u", DK[j * 6 + i]);
        !           349:        else
        !           350:            for (i = 0; i < 4; i++)
        !           351:                printf(" %6u", DK[j * 6 + i]);
        !           352:     }
        !           353: 
        !           354:     /* Make a sample plaintext pattern for testing... */
        !           355:     for (k = 0; k < 8; k++)
        !           356:        XX[k] = k;
        !           357: 
        !           358:     printf("\n Encrypting %d bytes (%ld blocks)...", BLOCKS * 16, BLOCKS);
        !           359:     fflush(stdout);
        !           360:     start = clock();
        !           361:     memcpy(YY, XX, 8);
        !           362:     for (l = 0; l < BLOCKS; l++)
        !           363:        ideaCipher(YY, YY, EK); /* repeated encryption */
        !           364:     memcpy(ZZ, YY, 8);
        !           365:     for (l = 0; l < BLOCKS; l++)
        !           366:        ideaCipher(ZZ, ZZ, DK); /* repeated decryption */
        !           367:     end = clock() - start;
        !           368:     l = end / (CLOCKS_PER_SEC / 1000) + 1;
        !           369:     i = l / 1000;
        !           370:     j = l % 1000;
        !           371:     l = (16 * BLOCKS * (CLOCKS_PER_SEC / 1000)) / (end / 1000);
        !           372:     printf("%d.%03d seconds = %ld bytes per second\n", i, j, l);
        !           373: 
        !           374:     printf("\nX %3u  %3u  %3u  %3u  %3u  %3u  %3u %3u\n",
        !           375:           XX[0], XX[1], XX[2], XX[3], XX[4], XX[5], XX[6], XX[7]);
        !           376:     printf("\nY %3u  %3u  %3u  %3u  %3u  %3u  %3u %3u\n",
        !           377:           YY[0], YY[1], YY[2], YY[3], YY[4], YY[5], YY[6], YY[7]);
        !           378:     printf("\nZ %3u  %3u  %3u  %3u  %3u  %3u  %3u %3u\n",
        !           379:           ZZ[0], ZZ[1], ZZ[2], ZZ[3], ZZ[4], ZZ[5], ZZ[6], ZZ[7]);
        !           380: 
        !           381:     /* Now decrypted ZZ should be same as original XX */
        !           382:     for (k = 0; k < 8; k++)
        !           383:        if (XX[k] != ZZ[k]) {
        !           384:            printf("\n\07Error!  Noninvertable encryption.\n");
        !           385:            exit(-1);           /* error exit */
        !           386:        }
        !           387:     printf("\nNormal exit.\n");
        !           388:     return 0;                  /* normal exit */
        !           389: }                              /* main */
1.1.1.5   root      390: 
1.1.1.6 ! root      391: #endif                         /* TEST */
1.1.1.5   root      392: 
                    393: 
                    394: /*************************************************************************/
                    395: 
1.1.1.6 ! root      396: void ideaCfbReinit(struct IdeaCfbContext *context, byte const *iv)
1.1.1.5   root      397: {
1.1.1.6 ! root      398:     if (iv)
        !           399:        memcpy(context->iv, iv, 8);
        !           400:     else
        !           401:        fill0(context->iv, 8);
        !           402:     context->bufleft = 0;
1.1.1.5   root      403: }
                    404: 
1.1.1.6 ! root      405: void ideaCfbInit(struct IdeaCfbContext *context, byte const key[16])
1.1.1.5   root      406: {
1.1.1.6 ! root      407:     ideaExpandKey(key, context->key);
        !           408:     ideaCfbReinit(context, 0);
1.1.1.5   root      409: }
                    410: 
1.1.1.6 ! root      411: void ideaCfbDestroy(struct IdeaCfbContext *context)
1.1.1.5   root      412: {
1.1.1.6 ! root      413:     burn(*context);
1.1.1.5   root      414: }
                    415: 
                    416: /*
                    417:  * Okay, explanation time:
                    418:  * Phil invented a unique way of doing CFB that's sensitive to semantic
                    419:  * boundaries within the data being encrypted.  One way to phrase
                    420:  * CFB en/decryption is to say that you XOR the current 8 bytes with
                    421:  * IDEA(previous 8 bytes of ciphertext).  Normally, you repeat this
                    422:  * at 8-byte intervals, but Phil decided to resync things on the
                    423:  * boundaries between elements in the stream being encrypted.
                    424:  *
                    425:  * That is, the last 4 bytes of a 12-byte field are en/decrypted using
                    426:  * the first 4 bytes of IDEA(previous 8 bytes of ciphertext), but then
                    427:  * the last 4 bytes of that IDEA computation are thrown away, and the
                    428:  * first 8 bytes of the next field are en/decrypted using
                    429:  * IDEA(last 8 bytes of ciphertext).  This is equivalent to using a
                    430:  * shorter feedback length (if you're familiar with the general CFB
                    431:  * technique) briefly, and doesn't weaken the cipher any (using shorter
                    432:  * CFB lengths makes it stronger, actually), it just makes it a bit unusual.
                    433:  *
                    434:  * Anyway, to accomodate this behaviour, every time we do an IDEA
                    435:  * encrpytion of 8 bytes of ciphertext to get 8 bytes of XOR mask,
                    436:  * we remember the ciphertext.  Then if we have to resync things
                    437:  * after having processed, say, 2 bytes, we refill the iv buffer
                    438:  * with the last 6 bytes of the old ciphertext followed by the
                    439:  * 2 bytes of new ciphertext stored in the front of the iv buffer.
                    440:  */
1.1.1.6 ! root      441: void ideaCfbSync(struct IdeaCfbContext *context)
1.1.1.5   root      442: {
1.1.1.6 ! root      443:     int bufleft = context->bufleft;
1.1.1.5   root      444: 
1.1.1.6 ! root      445:     if (bufleft) {
        !           446:        memmove(context->iv + bufleft, context->iv, 8 - bufleft);
        !           447:        memcpy(context->iv, context->oldcipher + 8 - bufleft, bufleft);
        !           448:        context->bufleft = 0;
        !           449:     }
1.1.1.5   root      450: }
                    451: 
                    452: /*
                    453:  * Encrypt a buffer of data, using IDEA in CFB mode.
                    454:  * There are more compact ways of writing this, but this is
                    455:  * written for speed.
                    456:  */
1.1.1.6 ! root      457: void ideaCfbEncrypt(struct IdeaCfbContext *context, byte const *src,
        !           458:                    byte * dest, int count)
        !           459: {
        !           460:     int bufleft = context->bufleft;
        !           461:     byte *bufptr = context->iv + 8 - bufleft;
        !           462: 
        !           463:     /* If there are no more bytes to encrypt that there are bytes
        !           464:      * in the buffer, XOR them in and return.
        !           465:      */
        !           466:     if (count <= bufleft) {
        !           467:        context->bufleft = bufleft - count;
        !           468:        while (count--) {
        !           469:            *dest++ = *bufptr++ ^= *src++;
        !           470:        }
        !           471:        return;
        !           472:     }
        !           473:     count -= bufleft;
        !           474:     /* Encrypt the first bufleft (0 to 7) bytes of the input by XOR
        !           475:      * with the last bufleft bytes in the iv buffer.
        !           476:      */
        !           477:     while (bufleft--) {
        !           478:        *dest++ = (*bufptr++ ^= *src++);
        !           479:     }
        !           480:     /* Encrypt middle blocks of the input by cranking the cipher,
        !           481:      * XORing 8-byte blocks, and repeating until the count
        !           482:      * is 8 or less.
        !           483:      */
        !           484:     while (count > 8) {
1.1.1.5   root      485:        bufptr = context->iv;
                    486:        memcpy(context->oldcipher, bufptr, 8);
                    487:        ideaCipher(bufptr, bufptr, context->key);
1.1.1.6 ! root      488:        bufleft = 8;
        !           489:        count -= 8;
        !           490:        do {
        !           491:            *dest++ = (*bufptr++ ^= *src++);
        !           492:        } while (--bufleft);
        !           493:     }
        !           494:     /* Do the last 1 to 8 bytes */
        !           495:     bufptr = context->iv;
        !           496:     memcpy(context->oldcipher, bufptr, 8);
        !           497:     ideaCipher(bufptr, bufptr, context->key);
        !           498:     context->bufleft = 8 - count;
        !           499:     do {
        !           500:        *dest++ = (*bufptr++ ^= *src++);
        !           501:     } while (--count);
1.1.1.5   root      502: }
                    503: 
                    504: 
                    505: /*
                    506:  * Decrypt a buffer of data, using IDEA in CFB mode.
                    507:  * There are more compact ways of writing this, but this is
                    508:  * written for speed.
                    509:  */
1.1.1.6 ! root      510: void ideaCfbDecrypt(struct IdeaCfbContext *context, byte const *src,
        !           511:                    byte * dest, int count)
        !           512: {
        !           513:     int bufleft = context->bufleft;
        !           514:     static byte *bufptr;
        !           515:     byte t;
        !           516: 
        !           517:     bufptr = context->iv + (8 - bufleft);
        !           518:     if (count <= bufleft) {
        !           519:        context->bufleft = bufleft - count;
        !           520:        while (count--) {
        !           521:            t = *bufptr;
        !           522:            *dest++ = t ^ (*bufptr++ = *src++);
        !           523:        }
        !           524:        return;
        !           525:     }
        !           526:     count -= bufleft;
        !           527:     while (bufleft--) {
        !           528:        t = *bufptr;
        !           529:        *dest++ = t ^ (*bufptr++ = *src++);
        !           530:     }
        !           531:     while (count > 8) {
1.1.1.5   root      532:        bufptr = context->iv;
                    533:        memcpy(context->oldcipher, bufptr, 8);
                    534:        ideaCipher(bufptr, bufptr, context->key);
1.1.1.6 ! root      535:        bufleft = 8;
        !           536:        count -= 8;
1.1.1.5   root      537:        do {
1.1.1.6 ! root      538:            t = *bufptr;
        !           539:            *dest++ = t ^ (*bufptr++ = *src++);
        !           540:        } while (--bufleft);
        !           541:     }
        !           542:     bufptr = context->iv;
        !           543:     memcpy(context->oldcipher, bufptr, 8);
        !           544:     ideaCipher(bufptr, bufptr, context->key);
        !           545:     context->bufleft = 8 - count;
        !           546:     do {
        !           547:        t = *bufptr;
        !           548:        *dest++ = t ^ (*bufptr++ = *src++);
        !           549:     } while (--count);
1.1.1.5   root      550: }
                    551: 
                    552: /********************************************************************/
                    553: 
                    554: /*
                    555:  * Cryptographically strong pseudo-random-number generator.
                    556:  * The design is from Appendix C of ANSI X9.17, "Financial
                    557:  * Institution Key Management (Wholesale)", with IDEA
                    558:  * substituted for the DES.
                    559:  */
                    560: 
                    561: /*
                    562:  * Initialize a cryptographic random-number generator.
                    563:  * key and seed should be arbitrary.
                    564:  */
1.1.1.6 ! root      565: void ideaRandInit(struct IdeaRandContext *context, byte const key[16],
        !           566:                  byte const seed[8])
1.1.1.5   root      567: {
1.1.1.6 ! root      568:     int i;
1.1.1.5   root      569: 
1.1.1.6 ! root      570:     ideaExpandKey(key, context->key);
        !           571:     context->bufleft = 0;
        !           572:     memcpy(context->internalbuf, seed, 8);
1.1.1.5   root      573: }
                    574: 
                    575: 
                    576: /*
                    577:  * Read out the RNG's state.
                    578:  */
1.1.1.6 ! root      579: void ideaRandState(struct IdeaRandContext *context, byte key[16], byte seed[8])
1.1.1.5   root      580: {
1.1.1.6 ! root      581:     int i;
1.1.1.5   root      582: 
1.1.1.6 ! root      583:     memcpy(seed, context->internalbuf, 8);
        !           584:     for (i = 0; i < 8; i++) {
        !           585:        key[2 * i] = context->key[i] >> 8;
        !           586:        key[2 * i + 1] = context->key[i];
        !           587:     }
1.1.1.5   root      588: 
                    589: }
                    590: 
                    591: /*
                    592:  * Encrypt the RNG's state with the given CFB encryptor.
                    593:  */
1.1.1.6 ! root      594: void ideaRandWash(struct IdeaRandContext *context, struct IdeaCfbContext *cfb)
1.1.1.5   root      595: {
1.1.1.6 ! root      596:     byte keyseed[16 + 8];
        !           597:     int i;
1.1.1.5   root      598: 
1.1.1.6 ! root      599:     ideaRandState(context, keyseed, keyseed + 16);
        !           600:     ideaCfbEncrypt(cfb, keyseed, keyseed, 16 + 8);
        !           601:     ideaRandInit(context, keyseed, keyseed + 16);
1.1.1.5   root      602: 
1.1.1.6 ! root      603:     memset(keyseed, 0, 16 + 8);
1.1.1.5   root      604: }
                    605: 
                    606: /*
                    607:  * Cryptographic pseudo-random-number generator, used for generating
                    608:  * session keys.
                    609:  */
                    610: byte
                    611: ideaRandByte(struct IdeaRandContext *c)
                    612: {
1.1.1.6 ! root      613:     int i;
1.1.1.5   root      614: 
1.1.1.6 ! root      615:     if (!c->bufleft) {
        !           616:        byte timestamp[8];
        !           617: 
        !           618:        /* Get some true-random noise to help */
        !           619:        randPoolGetBytes(timestamp, sizeof(timestamp));
        !           620: 
        !           621:        /* Compute next 8 bytes of output */
        !           622:        for (i = 0; i < 8; i++)
        !           623:            c->outbuf[i] = c->internalbuf[i] ^ timestamp[i];
        !           624:        ideaCipher(c->outbuf, c->outbuf, c->key);
        !           625:        /* Compute new seed vector */
        !           626:        for (i = 0; i < 8; i++)
        !           627:            c->internalbuf[i] = c->outbuf[i] ^ timestamp[i];
        !           628:        ideaCipher(c->internalbuf, c->internalbuf, c->key);
        !           629:        burn(timestamp);
        !           630:        c->bufleft = 8;
        !           631:     }
        !           632:     return c->outbuf[--c->bufleft];
1.1.1.5   root      633: }
                    634: 
                    635: /* end of idea.c */

unix.superglobalmegacorp.com

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