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

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