thig_twofish2.c

Go to the documentation of this file.
00001 
00031 #include    "thig_aes.h"
00032 #include    "thig_table.h"
00033 
00034 /*
00035 +*****************************************************************************
00036 *           Constants/Macros/Tables
00037 -****************************************************************************/
00038 
00039 #define     VALIDATE_PARMS  1       
00040 #define     FEISTEL         0       
00042 int  tabEnable=0;                   
00043 BYTE tabUsed[256];                  
00045 #if FEISTEL
00046 CONST       char *moduleDescription="Pedagogical C code (Feistel)";
00047 #else
00048 CONST       char *moduleDescription="Pedagogical C code";
00049 #endif
00050 CONST       char *modeString = "";
00051 
00052 #define P0_USED     0x01
00053 #define P1_USED     0x02
00054 #define B0_USED     0x04
00055 #define B1_USED     0x08
00056 #define B2_USED     0x10
00057 #define B3_USED     0x20
00058 #define ALL_USED    0x3F
00059 
00061 int         numRounds[4]= {0,ROUNDS_128,ROUNDS_192,ROUNDS_256};
00062 
00063 #ifndef DEBUG
00064 #ifdef GetCodeSize
00065 #define DEBUG   1                   
00066 #endif
00067 #endif
00068 #include    "thig_debug.h"              
00070 #ifdef GetCodeSize
00071 extern DWORD Here(DWORD x);         
00072 DWORD TwofishCodeStart(void) { return Here(0); };
00073 #endif
00074 
00075 /******************************************************************************
00076 * Function:         Handle table use checking
00077 * Notes: This routine is for use in generating the tables KAT file.
00078 * 
00079 * @param op - what to do    (see TAB_* defns in AES.H)
00080 * @returns  TRUE --> done (for TAB_QUERY)       
00081 * 
00082 ****************************************************************************/
00083 int TableOp(int op)
00084     {
00085     static int queryCnt=0;
00086     int i;
00087     switch (op)
00088         {
00089         case TAB_DISABLE:
00090             tabEnable=0;
00091             break;
00092         case TAB_ENABLE:
00093             tabEnable=1;
00094             break;
00095         case TAB_RESET:
00096             queryCnt=0;
00097             for (i=0;i<256;i++)
00098                 tabUsed[i]=0;
00099             break;
00100         case TAB_QUERY:
00101             queryCnt++;
00102             for (i=0;i<256;i++)
00103                 if (tabUsed[i] != ALL_USED)
00104                     return FALSE;
00105             if (queryCnt < TAB_MIN_QUERY)   /* do a certain minimum number */
00106                 return FALSE;
00107             break;
00108         }
00109     return TRUE;
00110     }
00111 
00112 
00113 /******************************************************************************
00114 *
00115 * Parse ASCII hex nibbles and fill in key/iv dwords
00116 * Notes:  
00117 *   This routine is coded to work both for little-endian and big-endian
00118 *   architectures.  The character stream is interpreted as a LITTLE-ENDIAN
00119 *   byte stream, since that is how the Pentium works, but the conversion
00120 *   happens automatically below. 
00121 * 
00122 * @param bit    - # bits to read
00123 * @param scrTxt - ASCII source
00124 * @param d      - ptr to dwords to fill in
00125 *                 Note that the parameter d is a DWORD array, not a byte array.
00126 * @param dstTxt - where to make a copy of ASCII source (NULL ok)
00127 *
00128 * @returns  Zero if no error.  Nonzero --> invalid hex or length
00129 *
00130 *
00131 ****************************************************************************/
00132 int ParseHexDword(int bits,CONST char *srcTxt,DWORD *d,char *dstTxt)
00133     {
00134     int i;
00135     DWORD b;
00136     char c;
00137 //#if ALIGN32
00138     //char alignDummy[3];   /* keep dword alignment */
00139 //#endif
00140 
00141     union   /* make sure LittleEndian is defined correctly */
00142         {
00143         BYTE  b[4];
00144         DWORD d[1];
00145         } v;
00146     v.d[0]=1;
00147     if (v.b[0 ^ ADDR_XOR] != 1) /* sanity check on compile-time switch */
00148         return BAD_ENDIAN;
00149 
00150 #if VALIDATE_PARMS
00151   #if ALIGN32
00152     if (((int)d) & 3)
00153         return BAD_ALIGN32;
00154   #endif
00155 #endif
00156 
00157     for (i=0;i*32<bits;i++)
00158         d[i]=0;                 /* first, zero the field */
00159 
00160     for (i=0;i*4<bits;i++)      /* parse one nibble at a time */
00161         {                       /* case out the hexadecimal characters */
00162         c=srcTxt[i];
00163         if (dstTxt) dstTxt[i]=c;
00164         if ((c >= '0') && (c <= '9'))
00165             b=c-'0';
00166         else if ((c >= 'a') && (c <= 'f'))
00167             b=c-'a'+10;
00168         else if ((c >= 'A') && (c <= 'F'))
00169             b=c-'A'+10;
00170         else
00171             return BAD_KEY_MAT; /* invalid hex character */
00172         /* works for big and little endian! */
00173         d[i/8] |= b << (4*((i^1)&7));       
00174         }
00175 
00176     return 0;                   /* no error */
00177     }
00178 
00179 
00180 /******************************************************************************
00181 *
00182 *
00183 * Run four bytes through keyed S-boxes and apply MDS matrix
00184 * Notes:
00185 *   This function is a keyed 32-bit permutation.  It is the major building
00186 *   block for the Twofish round function, including the four keyed 8x8 
00187 *   permutations and the 4x4 MDS matrix multiply.  This function is used
00188 *   both for generating round subkeys and within the round function on the
00189 *   block being encrypted.  
00190 *
00191 *   This version is fairly slow and pedagogical, although a smartcard would
00192 *   probably perform the operation exactly this way in firmware.   For
00193 *   ultimate performance, the entire operation can be completed with four
00194 *   lookups into four 256x32-bit tables, with three dword xors.
00195 *
00196 *   The MDS matrix is defined in TABLE.H.  To multiply by Mij, just use the
00197 *   macro Mij(x).
00198 * 
00199 * @param x      - input to f function
00200 * @param k32    - pointer to key dwords
00201 * @param keyLen - total key length (k32 --> keyLey/2 bits)
00202 *
00203 * @returns The output of the keyed permutation applied to x.
00204 *
00205 * 
00206 *
00207 -****************************************************************************/
00208 DWORD f32(DWORD x,CONST DWORD *k32,int keyLen)
00209     {
00210     BYTE  b[4];
00211     
00212     /* Run each byte thru 8x8 S-boxes, xoring with key byte at each stage. */
00213     /* Note that each byte goes through a different combination of S-boxes.*/
00214 
00215     *((DWORD *)b) = Bswap(x);   /* make b[0] = LSB, b[3] = MSB */
00216     switch (((keyLen + 63)/64) & 3)
00217         {
00218         case 0:     /* 256 bits of key */
00219             b[0] = p8(04)[b[0]] ^ b0(k32[3]);
00220             b[1] = p8(14)[b[1]] ^ b1(k32[3]);
00221             b[2] = p8(24)[b[2]] ^ b2(k32[3]);
00222             b[3] = p8(34)[b[3]] ^ b3(k32[3]);
00223             /* fall thru, having pre-processed b[0]..b[3] with k32[3] */
00224         case 3:     /* 192 bits of key */
00225             b[0] = p8(03)[b[0]] ^ b0(k32[2]);
00226             b[1] = p8(13)[b[1]] ^ b1(k32[2]);
00227             b[2] = p8(23)[b[2]] ^ b2(k32[2]);
00228             b[3] = p8(33)[b[3]] ^ b3(k32[2]);
00229             /* fall thru, having pre-processed b[0]..b[3] with k32[2] */
00230         case 2:     /* 128 bits of key */
00231             b[0] = p8(00)[p8(01)[p8(02)[b[0]] ^ b0(k32[1])] ^ b0(k32[0])];
00232             b[1] = p8(10)[p8(11)[p8(12)[b[1]] ^ b1(k32[1])] ^ b1(k32[0])];
00233             b[2] = p8(20)[p8(21)[p8(22)[b[2]] ^ b2(k32[1])] ^ b2(k32[0])];
00234             b[3] = p8(30)[p8(31)[p8(32)[b[3]] ^ b3(k32[1])] ^ b3(k32[0])];
00235         }
00236 
00237     if (tabEnable)
00238         {   /* we could give a "tighter" bound, but this works acceptably well */
00239         tabUsed[b0(x)] |= (P_00 == 0) ? P0_USED : P1_USED;
00240         tabUsed[b1(x)] |= (P_10 == 0) ? P0_USED : P1_USED;
00241         tabUsed[b2(x)] |= (P_20 == 0) ? P0_USED : P1_USED;
00242         tabUsed[b3(x)] |= (P_30 == 0) ? P0_USED : P1_USED;
00243 
00244         tabUsed[b[0] ] |= B0_USED;
00245         tabUsed[b[1] ] |= B1_USED;
00246         tabUsed[b[2] ] |= B2_USED;
00247         tabUsed[b[3] ] |= B3_USED;
00248         }
00249 
00250     /* Now perform the MDS matrix multiply inline. */
00251     return  ((M00(b[0]) ^ M01(b[1]) ^ M02(b[2]) ^ M03(b[3]))      ) ^
00252             ((M10(b[0]) ^ M11(b[1]) ^ M12(b[2]) ^ M13(b[3])) <<  8) ^
00253             ((M20(b[0]) ^ M21(b[1]) ^ M22(b[2]) ^ M23(b[3])) << 16) ^
00254             ((M30(b[0]) ^ M31(b[1]) ^ M32(b[2]) ^ M33(b[3])) << 24) ;
00255     }
00256 
00257 /******************************************************************************
00258 *
00259 *
00260 * Use (12,8) Reed-Solomon code over GF(256) to produce
00261 * a key S-box dword from two key material dwords.
00262 * Notes:
00263 *   Since this computation is done only once per reKey per 64 bits of key,
00264 *   the performance impact of this routine is imperceptible. The RS code
00265 *   chosen has "simple" coefficients to allow smartcard/hardware implementation
00266 *   without lookup tables.
00267 *
00268 * @param k0 - 1st dword
00269 * @param k1 - 2nd dword
00270 *
00271 * @returns Remainder polynomial generated using RS code
00272 *
00273 * 
00274 *
00275 -****************************************************************************/
00276 DWORD RS_MDS_Encode(DWORD k0,DWORD k1)
00277     {
00278     int i,j;
00279     DWORD r;
00280 
00281     for (i=r=0;i<2;i++)
00282         {
00283         r ^= (i) ? k0 : k1;         /* merge in 32 more key bits */
00284         for (j=0;j<4;j++)           /* shift one byte at a time */
00285             RS_rem(r);              
00286         }
00287     return r;
00288     }
00289 
00290 /******************************************************************************
00291 *
00292 *  Initialize the Twofish key schedule from key32
00293 *  Notes:
00294 *   Here we precompute all the round subkeys, although that is not actually
00295 *   required.  For example, on a smartcard, the round subkeys can 
00296 *   be generated on-the-fly using f32()
00297 *
00298 * @param key - ptr to keyInstance to be initialized
00299 *
00300 * @returns - TRUE on success
00301 *
00302 *****************************************************************************/
00303 int reKey(keyInstance *key)
00304     {
00305     int     i,k64Cnt;
00306     int     keyLen    = key->keyLen;
00307     int     subkeyCnt = ROUND_SUBKEYS + 2*key->numRounds;
00308     DWORD   A,B;
00309     DWORD   k32e[MAX_KEY_BITS/64],k32o[MAX_KEY_BITS/64]; /* even/odd key dwords */
00310 
00311 #if VALIDATE_PARMS
00312   #if ALIGN32
00313     if ((((int)key) & 3) || (((int)key->key32) & 3))
00314         return BAD_ALIGN32;
00315   #endif
00316     if ((key->keyLen % 64) || (key->keyLen < MIN_KEY_BITS))
00317         return BAD_KEY_INSTANCE;
00318     if (subkeyCnt > TOTAL_SUBKEYS)
00319         return BAD_KEY_INSTANCE;
00320 #endif
00321 
00322     k64Cnt=(keyLen+63)/64;      /* round up to next multiple of 64 bits */
00323     for (i=0;i<k64Cnt;i++)
00324         {                       /* split into even/odd key dwords */
00325         k32e[i]=key->key32[2*i  ];
00326         k32o[i]=key->key32[2*i+1];
00327         /* compute S-box keys using (12,8) Reed-Solomon code over GF(256) */
00328         key->sboxKeys[k64Cnt-1-i]=RS_MDS_Encode(k32e[i],k32o[i]); /* reverse order */
00329         }
00330 
00331     for (i=0;i<subkeyCnt/2;i++)                 /* compute round subkeys for PHT */
00332         {
00333         A = f32(i*SK_STEP        ,k32e,keyLen); /* A uses even key dwords */
00334         B = f32(i*SK_STEP+SK_BUMP,k32o,keyLen); /* B uses odd  key dwords */
00335         B = ROL(B,8);
00336         key->subKeys[2*i  ] = A+  B;            /* combine with a PHT */
00337         key->subKeys[2*i+1] = ROL(A+2*B,SK_ROTL);
00338         }
00339 
00340     DebugDumpKey(key);
00341 
00342     return TRUE;
00343     }
00344 /******************************************************************************
00345 *
00346 *Initialize the Twofish key schedule
00347 *Notes:
00348 *   This parses the key bits from keyMaterial.  No crypto stuff happens here.
00349 *   The function reKey() is called to actually build the key schedule after
00350 *   the keyMaterial has been parsed.
00351 * 
00352 * @param key            - ptr to keyInstance to be initialized
00353 * @param direction      - DIR_ENCRYPT or DIR_DECRYPT
00354 * @param keyLen         - # bits of key text at *keyMaterial
00355 * @param keyMaterial    - ptr to hex ASCII chars representing key bits
00356 *
00357 * @returns -            TRUE on success else error code (e.g., BAD_KEY_DIR)
00358 *
00359 * 
00360 *****************************************************************************/
00361 int makeKey(keyInstance *key, BYTE direction, int keyLen,CONST char *keyMaterial)
00362     {
00363     int i;
00364 
00365 #if VALIDATE_PARMS              /* first, sanity check on parameters */
00366     if (key == NULL)            
00367         return BAD_KEY_INSTANCE;/* must have a keyInstance to initialize */
00368     if ((direction != DIR_ENCRYPT) && (direction != DIR_DECRYPT))
00369         return BAD_KEY_DIR;     /* must have valid direction */
00370     if ((keyLen > MAX_KEY_BITS) || (keyLen < 8))    
00371         return BAD_KEY_MAT;     /* length must be valid */
00372     key->keySig = VALID_SIG;    /* show that we are initialized */
00373   #if ALIGN32
00374     if ((((int)key) & 3) || (((int)key->key32) & 3))
00375         return BAD_ALIGN32;
00376   #endif
00377 #endif
00378 
00379     key->direction  = direction;    /* set our cipher direction */
00380     key->keyLen     = (keyLen+63) & ~63;        /* round up to multiple of 64 */
00381     key->numRounds  = numRounds[(keyLen-1)/64];
00382     for (i=0;i<MAX_KEY_BITS/32;i++) /* zero unused bits */
00383            key->key32[i]=0;
00384     key->keyMaterial[MAX_KEY_SIZE]=0;   /* terminate ASCII string */
00385 
00386     if ((keyMaterial == NULL) || (keyMaterial[0]==0))
00387         return TRUE;            /* allow a "dummy" call */
00388         
00389     if (ParseHexDword(keyLen,keyMaterial,key->key32,key->keyMaterial))
00390         return BAD_KEY_MAT; 
00391 
00392     return reKey(key);          /* generate round subkeys */
00393     }
00394 
00395 
00396 /******************************************************************************
00397 *
00398 * Initialize the Twofish cipher in a given mode
00399 *
00400 * @param cipher - ptr to cipherInstance to be initialized
00401 * @param mode   - MODE_ECB, MODE_CBC, or MODE_CFB1
00402 * @param IV     - ptr to hex ASCII test representing IV bytes
00403 *
00404 * @returns - TRUE on success else error code (e.g., BAD_CIPHER_MODE)
00405 *
00406 -****************************************************************************/
00407 int cipherInit(cipherInstance *cipher, BYTE mode,CONST char *IV)
00408     {
00409     int i;
00410 #if VALIDATE_PARMS              /* first, sanity check on parameters */
00411     if (cipher == NULL)         
00412         return BAD_PARAMS;      /* must have a cipherInstance to initialize */
00413     if ((mode != MODE_ECB) && (mode != MODE_CBC) && (mode != MODE_CFB1))
00414         return BAD_CIPHER_MODE; /* must have valid cipher mode */
00415     cipher->cipherSig   =   VALID_SIG;
00416   #if ALIGN32
00417     if ((((int)cipher) & 3) || (((int)cipher->IV) & 3) || (((int)cipher->iv32) & 3))
00418         return BAD_ALIGN32;
00419   #endif
00420 #endif
00421 
00422     if ((mode != MODE_ECB) && (IV)) /* parse the IV */
00423         {
00424         if (ParseHexDword(BLOCK_SIZE,IV,cipher->iv32,NULL))
00425             return BAD_IV_MAT;
00426         for (i=0;i<BLOCK_SIZE/32;i++)   /* make byte-oriented copy for CFB1 */
00427             ((DWORD *)cipher->IV)[i] = Bswap(cipher->iv32[i]);
00428         }
00429 
00430     cipher->mode        =   mode;
00431 
00432     return TRUE;
00433     }
00434 
00435 /******************************************************************************
00436 *Encrypt block(s) of data using Twofish
00437 * Notes: The only supported block size for ECB/CBC modes is BLOCK_SIZE bits.
00438 *        If inputLen is not a multiple of BLOCK_SIZE bits in those modes,
00439 *        an error BAD_INPUT_LEN is returned.  In CFB1 mode, all block 
00440 *        sizes can be supported.
00441 *
00442 * @param cipher     - ptr to already initialized cipherInstance
00443 * @param key        - ptr to already initialized keyInstance
00444 * @param input      - ptr to data blocks to be encrypted
00445 * @param inputLen   - # bits to encrypt (multiple of blockSize)
00446 *                   outBuffer   =   ptr to where to put encrypted blocks
00447 *
00448 * @returns          # bits ciphered (>= 0)
00449 *                   else error code (e.g., BAD_CIPHER_STATE, BAD_KEY_MATERIAL)
00450 *
00451 *
00452 -****************************************************************************/
00453 int blockEncrypt(cipherInstance *cipher, keyInstance *key,CONST BYTE *input,
00454                 int inputLen, BYTE *outBuffer)
00455     {
00456     int   i,n,r;                    /* loop variables */
00457     DWORD x[BLOCK_SIZE/32];         /* block being encrypted */
00458     DWORD t0,t1,tmp;                /* temp variables */
00459     int   rounds=key->numRounds;    /* number of rounds */
00460     BYTE  bit,ctBit,carry;          /* temps for CFB */
00461 //#if ALIGN32
00462     //BYTE alignDummy;              /* keep 32-bit variable alignment on stack */
00463 //#endif
00464 
00465 #if VALIDATE_PARMS
00466     if ((cipher == NULL) || (cipher->cipherSig != VALID_SIG))
00467         return BAD_CIPHER_STATE;
00468     if ((key == NULL) || (key->keySig != VALID_SIG))
00469         return BAD_KEY_INSTANCE;
00470     if ((rounds < 2) || (rounds > MAX_ROUNDS) || (rounds&1))
00471         return BAD_KEY_INSTANCE;
00472     if ((cipher->mode != MODE_CFB1) && (inputLen % BLOCK_SIZE))
00473         return BAD_INPUT_LEN;
00474   #if ALIGN32
00475     if ( (((int)cipher) & 3) || (((int)key      ) & 3) ||
00476          (((int)input ) & 3) || (((int)outBuffer) & 3))
00477         return BAD_ALIGN32;
00478   #endif
00479 #endif
00480 
00481     if (cipher->mode == MODE_CFB1)
00482         {   /* use recursion here to handle CFB, one block at a time */
00483         cipher->mode = MODE_ECB;    /* do encryption in ECB */
00484         for (n=0;n<inputLen;n++)
00485             {
00486             blockEncrypt(cipher,key,cipher->IV,BLOCK_SIZE,(BYTE *)x);
00487             bit   = 0x80 >> (n & 7);/* which bit position in byte */
00488             ctBit = (input[n/8] & bit) ^ ((((BYTE *) x)[0] & 0x80) >> (n&7));
00489             outBuffer[n/8] = (outBuffer[n/8] & ~ bit) | ctBit;
00490             carry = ctBit >> (7 - (n&7));
00491             for (i=BLOCK_SIZE/8-1;i>=0;i--)
00492                 {
00493                 bit = cipher->IV[i] >> 7;   /* save next "carry" from shift */
00494                 cipher->IV[i] = (cipher->IV[i] << 1) ^ carry;
00495                 carry = bit;
00496                 }
00497             }
00498         cipher->mode = MODE_CFB1;   /* restore mode for next time */
00499         return inputLen;
00500         }
00501 
00502     /* here for ECB, CBC modes */
00503     for (n=0;n<inputLen;n+=BLOCK_SIZE,input+=BLOCK_SIZE/8,outBuffer+=BLOCK_SIZE/8)
00504         {
00505 #ifdef DEBUG
00506         DebugDump(input,"\n",-1,0,0,0,1);
00507         if (cipher->mode == MODE_CBC)
00508             DebugDump(cipher->iv32,"",IV_ROUND,0,0,0,0);
00509 #endif
00510         for (i=0;i<BLOCK_SIZE/32;i++)   /* copy in the block, add whitening */
00511             {
00512             x[i]=Bswap(((DWORD *)input)[i]) ^ key->subKeys[INPUT_WHITEN+i];
00513             if (cipher->mode == MODE_CBC)
00514                 x[i] ^= cipher->iv32[i];
00515             }
00516 
00517         DebugDump(x,"",0,0,0,0,0);
00518         for (r=0;r<rounds;r++)          /* main Twofish encryption loop */
00519             {   
00520 #if FEISTEL
00521             t0   = f32(ROR(x[0],  (r+1)/2),key->sboxKeys,key->keyLen);
00522             t1   = f32(ROL(x[1],8+(r+1)/2),key->sboxKeys,key->keyLen);
00523                                         /* PHT, round keys */
00524             x[2]^= ROL(t0 +   t1 + key->subKeys[ROUND_SUBKEYS+2*r  ], r    /2);
00525             x[3]^= ROR(t0 + 2*t1 + key->subKeys[ROUND_SUBKEYS+2*r+1],(r+2) /2);
00526 
00527             DebugDump(x,"",r+1,2*(r&1),1,1,0);
00528 #else
00529             t0   = f32(    x[0]   ,key->sboxKeys,key->keyLen);
00530             t1   = f32(ROL(x[1],8),key->sboxKeys,key->keyLen);
00531 
00532             x[3] = ROL(x[3],1);
00533             x[2]^= t0 +   t1 + key->subKeys[ROUND_SUBKEYS+2*r  ]; /* PHT, round keys */
00534             x[3]^= t0 + 2*t1 + key->subKeys[ROUND_SUBKEYS+2*r+1];
00535             x[2] = ROR(x[2],1);
00536 
00537             DebugDump(x,"",r+1,2*(r&1),0,1,0);/* make format compatible with optimized code */
00538 #endif
00539             if (r < rounds-1)                       /* swap for next round */
00540                 {
00541                 tmp = x[0]; x[0]= x[2]; x[2] = tmp;
00542                 tmp = x[1]; x[1]= x[3]; x[3] = tmp;
00543                 }
00544             }
00545 #if FEISTEL
00546         x[0] = ROR(x[0],8);                     /* "final permutation" */
00547         x[1] = ROL(x[1],8);
00548         x[2] = ROR(x[2],8);
00549         x[3] = ROL(x[3],8);
00550 #endif
00551         for (i=0;i<BLOCK_SIZE/32;i++)   /* copy out, with whitening */
00552             {
00553             ((DWORD *)outBuffer)[i] = Bswap(x[i] ^ key->subKeys[OUTPUT_WHITEN+i]);
00554             if (cipher->mode == MODE_CBC)
00555                 cipher->iv32[i] = Bswap(((DWORD *)outBuffer)[i]);
00556             }
00557 #ifdef DEBUG
00558         DebugDump(outBuffer,"",rounds+1,0,0,0,1);
00559         if (cipher->mode == MODE_CBC)
00560             DebugDump(cipher->iv32,"",IV_ROUND,0,0,0,0);
00561 #endif
00562         }
00563 
00564     return inputLen;
00565     }
00566 
00567 /******************************************************************************
00568 *
00569 * Decrypt block(s) of data using Twofish
00570 * Notes: The only supported block size for ECB/CBC modes is BLOCK_SIZE bits.
00571 *        If inputLen is not a multiple of BLOCK_SIZE bits in those modes,
00572 *        an error BAD_INPUT_LEN is returned.  In CFB1 mode, all block 
00573 *        sizes can be supported.
00574 *
00575 * @param cipher     - ptr to already initialized cipherInstance
00576 * @param key        - ptr to already initialized keyInstance
00577 * @param input      - ptr to data blocks to be decrypted
00578 * @param inputLen   - # bits to encrypt (multiple of blockSize)
00579 * @param outBuffer  - ptr to where to put decrypted blocks
00580 *
00581 * @returns          # bits ciphered (>= 0)
00582 *                   else error code (e.g., BAD_CIPHER_STATE, BAD_KEY_MATERIAL)
00583 *
00584 *****************************************************************************/
00585 int blockDecrypt(cipherInstance *cipher, keyInstance *key,CONST BYTE *input,
00586                 int inputLen, BYTE *outBuffer)
00587     {
00588     int   i,n,r;                    /* loop counters */
00589     DWORD x[BLOCK_SIZE/32];         /* block being encrypted */
00590     DWORD t0,t1;                    /* temp variables */
00591     int   rounds=key->numRounds;    /* number of rounds */
00592     BYTE  bit,ctBit,carry;          /* temps for CFB */
00593 //#if ALIGN32
00594     //BYTE alignDummy;              /* keep 32-bit variable alignment on stack */
00595 //#endif
00596 
00597 #if VALIDATE_PARMS
00598     if ((cipher == NULL) || (cipher->cipherSig != VALID_SIG))
00599         return BAD_CIPHER_STATE;
00600     if ((key == NULL) || (key->keySig != VALID_SIG))
00601         return BAD_KEY_INSTANCE;
00602     if ((rounds < 2) || (rounds > MAX_ROUNDS) || (rounds&1))
00603         return BAD_KEY_INSTANCE;
00604     if ((cipher->mode != MODE_CFB1) && (inputLen % BLOCK_SIZE))
00605         return BAD_INPUT_LEN;
00606   #if ALIGN32
00607     if ( (((int)cipher) & 3) || (((int)key      ) & 3) ||
00608          (((int)input)  & 3) || (((int)outBuffer) & 3))
00609         return BAD_ALIGN32;
00610   #endif
00611 #endif
00612 
00613     if (cipher->mode == MODE_CFB1)
00614         {   /* use blockEncrypt here to handle CFB, one block at a time */
00615         cipher->mode = MODE_ECB;    /* do encryption in ECB */
00616         for (n=0;n<inputLen;n++)
00617             {
00618             blockEncrypt(cipher,key,cipher->IV,BLOCK_SIZE,(BYTE *)x);
00619             bit   = 0x80 >> (n & 7);
00620             ctBit = input[n/8] & bit;
00621             outBuffer[n/8] = (outBuffer[n/8] & ~ bit) |
00622                              (ctBit ^ ((((BYTE *) x)[0] & 0x80) >> (n&7)));
00623             carry = ctBit >> (7 - (n&7));
00624             for (i=BLOCK_SIZE/8-1;i>=0;i--)
00625                 {
00626                 bit = cipher->IV[i] >> 7;   /* save next "carry" from shift */
00627                 cipher->IV[i] = (cipher->IV[i] << 1) ^ carry;
00628                 carry = bit;
00629                 }
00630             }
00631         cipher->mode = MODE_CFB1;   /* restore mode for next time */
00632         return inputLen;
00633         }
00634 
00635     /* here for ECB, CBC modes */
00636     for (n=0;n<inputLen;n+=BLOCK_SIZE,input+=BLOCK_SIZE/8,outBuffer+=BLOCK_SIZE/8)
00637         {
00638         DebugDump(input,"\n",rounds+1,0,0,0,1);
00639 
00640         for (i=0;i<BLOCK_SIZE/32;i++)   /* copy in the block, add whitening */
00641             x[i]=Bswap(((DWORD *)input)[i]) ^ key->subKeys[OUTPUT_WHITEN+i];
00642 
00643         for (r=rounds-1;r>=0;r--)           /* main Twofish decryption loop */
00644             {
00645             t0   = f32(    x[0]   ,key->sboxKeys,key->keyLen);
00646             t1   = f32(ROL(x[1],8),key->sboxKeys,key->keyLen);
00647 
00648             DebugDump(x,"",r+1,2*(r&1),0,1,0);/* make format compatible with optimized code */
00649             x[2] = ROL(x[2],1);
00650             x[2]^= t0 +   t1 + key->subKeys[ROUND_SUBKEYS+2*r  ]; /* PHT, round keys */
00651             x[3]^= t0 + 2*t1 + key->subKeys[ROUND_SUBKEYS+2*r+1];
00652             x[3] = ROR(x[3],1);
00653 
00654             if (r)                                  /* unswap, except for last round */
00655                 {
00656                 t0   = x[0]; x[0]= x[2]; x[2] = t0; 
00657                 t1   = x[1]; x[1]= x[3]; x[3] = t1;
00658                 }
00659             }
00660         DebugDump(x,"",0,0,0,0,0);/* make final output match encrypt initial output */
00661 
00662         for (i=0;i<BLOCK_SIZE/32;i++)   /* copy out, with whitening */
00663             {
00664             x[i] ^= key->subKeys[INPUT_WHITEN+i];
00665             if (cipher->mode == MODE_CBC)
00666                 {
00667                 x[i] ^= cipher->iv32[i];
00668                 cipher->iv32[i] = Bswap(((DWORD *)input)[i]);
00669                 }
00670             ((DWORD *)outBuffer)[i] = Bswap(x[i]);
00671             }
00672         DebugDump(outBuffer,"",-1,0,0,0,1);
00673         }
00674 
00675     return inputLen;
00676     }
00677 
00678 
00679 #ifdef GetCodeSize
00680 DWORD TwofishCodeSize(void) { return Here(0)-TwofishCodeStart(); };
00681 #endif

Generated on Thu Oct 23 04:14:38 2008 for Open IMS Core CSCFs by  doxygen 1.5.2