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

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 - a;
1.1.1.7 ! root       96:     } else {
        !            97:        return 1 - b;
1.1.1.6   root       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, 
1.1.1.7 ! root      203:  * t16 and t32.  x is modified, and must be a side-effect-free lvalue.
        !           204:  * y may be anything, but unlike x, must be strictly less than 65536 
        !           205:  * even if low16() is #defined.
1.1.1.5   root      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), \
1.1.1.7 ! root      213:                t32 = (word32)x*t16 + x + t16, x = low16(t32), \
        !           214:                t16 = t32>>16, x = (x-t16) + (x<t16) + 1)
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.