Submitters: Bruce Schneier, Counterpane Systems Doug Whiting, Hi/fn John Kelsey, Counterpane Systems Chris Hall, Counterpane Systems David Wagner, UC Berkeley
Code Author: Doug Whiting, Hi/fn
Version 1.00 April 1998
Copyright 1998, Hi/fn and Counterpane Systems. All rights reserved.
Notes: Pedagogical version (non-optimized) Tab size is set to 4 characters in this file
Definition in file thig_twofish2.c.
#include "thig_aes.h"
#include "thig_table.h"
#include "thig_debug.h"
Go to the source code of this file.
Defines | |
| #define | VALIDATE_PARMS 1 |
| nonzero --> check all parameters | |
| #define | FEISTEL 0 |
| nonzero --> use Feistel version (slow) | |
| #define | P0_USED 0x01 |
| #define | P1_USED 0x02 |
| #define | B0_USED 0x04 |
| #define | B1_USED 0x08 |
| #define | B2_USED 0x10 |
| #define | B3_USED 0x20 |
| #define | ALL_USED 0x3F |
Functions | |
| int | TableOp (int op) |
| int | ParseHexDword (int bits, CONST char *srcTxt, DWORD *d, char *dstTxt) |
| DWORD | f32 (DWORD x, CONST DWORD *k32, int keyLen) |
| DWORD | RS_MDS_Encode (DWORD k0, DWORD k1) |
| int | reKey (keyInstance *key) |
| do key schedule using modified key.keyDwords | |
| int | makeKey (keyInstance *key, BYTE direction, int keyLen, CONST char *keyMaterial) |
| int | cipherInit (cipherInstance *cipher, BYTE mode, CONST char *IV) |
| int | blockEncrypt (cipherInstance *cipher, keyInstance *key, CONST BYTE *input, int inputLen, BYTE *outBuffer) |
| int | blockDecrypt (cipherInstance *cipher, keyInstance *key, CONST BYTE *input, int inputLen, BYTE *outBuffer) |
Variables | |
| int | tabEnable = 0 |
| are we gathering stats? | |
| BYTE | tabUsed [256] |
| one bit per table | |
| CONST char * | moduleDescription = "Pedagogical C code" |
| CONST char * | modeString = "" |
| int | numRounds [4] = {0,ROUNDS_128,ROUNDS_192,ROUNDS_256} |
| number of rounds for various key sizes: 128, 192, 256 | |
| #define VALIDATE_PARMS 1 |
| #define FEISTEL 0 |
nonzero --> use Feistel version (slow)
Definition at line 40 of file thig_twofish2.c.
Referenced by blockEncrypt().
| #define P0_USED 0x01 |
| #define P1_USED 0x02 |
| #define B0_USED 0x04 |
| #define B1_USED 0x08 |
| #define B2_USED 0x10 |
| #define B3_USED 0x20 |
| #define ALL_USED 0x3F |
| int TableOp | ( | int | op | ) |
Definition at line 83 of file thig_twofish2.c.
References ALL_USED, FALSE, TAB_DISABLE, TAB_ENABLE, TAB_MIN_QUERY, TAB_QUERY, TAB_RESET, tabEnable, tabUsed, and TRUE.
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 }
| int ParseHexDword | ( | int | bits, | |
| CONST char * | srcTxt, | |||
| DWORD * | d, | |||
| char * | dstTxt | |||
| ) |
Definition at line 132 of file thig_twofish2.c.
References ADDR_XOR, BAD_ALIGN32, BAD_ENDIAN, and BAD_KEY_MAT.
Referenced by cipherInit(), and makeKey().
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 }
Definition at line 208 of file thig_twofish2.c.
References b0, B0_USED, b1, B1_USED, b2, B2_USED, b3, B3_USED, Bswap, M00, M01, M02, M03, M10, M11, M12, M13, M20, M21, M22, M23, M30, M31, M32, M33, P0_USED, P1_USED, p8, P_00, P_10, P_20, P_30, tabEnable, and tabUsed.
Referenced by blockDecrypt(), blockEncrypt(), and reKey().
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 }
Definition at line 276 of file thig_twofish2.c.
References RS_rem.
Referenced by reKey().
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 }
| int reKey | ( | keyInstance * | key | ) |
do key schedule using modified key.keyDwords
Definition at line 303 of file thig_twofish2.c.
References BAD_ALIGN32, BAD_KEY_INSTANCE, DebugDumpKey, f32(), keyInstance::keyLen, MAX_KEY_BITS, MIN_KEY_BITS, keyInstance::numRounds, ROL, ROUND_SUBKEYS, RS_MDS_Encode(), SK_BUMP, SK_ROTL, SK_STEP, TOTAL_SUBKEYS, and TRUE.
Referenced by makeKey(), and thig_key_and_cipher_init().
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 }
| int makeKey | ( | keyInstance * | key, | |
| BYTE | direction, | |||
| int | keyLen, | |||
| CONST char * | keyMaterial | |||
| ) |
Definition at line 361 of file thig_twofish2.c.
References BAD_ALIGN32, BAD_KEY_DIR, BAD_KEY_INSTANCE, BAD_KEY_MAT, DIR_DECRYPT, DIR_ENCRYPT, if, keyInstance::keySig, MAX_KEY_BITS, MAX_KEY_SIZE, NULL, numRounds, ParseHexDword(), reKey(), TRUE, and VALID_SIG.
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 }
| int cipherInit | ( | cipherInstance * | cipher, | |
| BYTE | mode, | |||
| CONST char * | IV | |||
| ) |
Definition at line 407 of file thig_twofish2.c.
References BAD_ALIGN32, BAD_CIPHER_MODE, BAD_IV_MAT, BAD_PARAMS, BLOCK_SIZE, Bswap, cipherInstance::cipherSig, MODE_CBC, MODE_CFB1, MODE_ECB, NULL, ParseHexDword(), TRUE, and VALID_SIG.
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 }
| int blockEncrypt | ( | cipherInstance * | cipher, | |
| keyInstance * | key, | |||
| CONST BYTE * | input, | |||
| int | inputLen, | |||
| BYTE * | outBuffer | |||
| ) |
Definition at line 453 of file thig_twofish2.c.
References BAD_ALIGN32, BAD_CIPHER_STATE, BAD_INPUT_LEN, BAD_KEY_INSTANCE, BLOCK_SIZE, blockEncrypt(), Bswap, cipherInstance::cipherSig, DebugDump, f32(), FEISTEL, if, INPUT_WHITEN, keyInstance::keySig, MAX_ROUNDS, cipherInstance::mode, MODE_CBC, MODE_CFB1, MODE_ECB, NULL, keyInstance::numRounds, OUTPUT_WHITEN, ROL, ROR, ROUND_SUBKEYS, and VALID_SIG.
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 }
| int blockDecrypt | ( | cipherInstance * | cipher, | |
| keyInstance * | key, | |||
| CONST BYTE * | input, | |||
| int | inputLen, | |||
| BYTE * | outBuffer | |||
| ) |
Definition at line 585 of file thig_twofish2.c.
References BAD_ALIGN32, BAD_CIPHER_STATE, BAD_INPUT_LEN, BAD_KEY_INSTANCE, BLOCK_SIZE, blockEncrypt(), Bswap, cipherInstance::cipherSig, DebugDump, f32(), if, INPUT_WHITEN, keyInstance::keySig, MAX_ROUNDS, cipherInstance::mode, MODE_CBC, MODE_CFB1, MODE_ECB, NULL, keyInstance::numRounds, OUTPUT_WHITEN, ROL, ROR, ROUND_SUBKEYS, and VALID_SIG.
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 }
| int tabEnable = 0 |
| CONST char* moduleDescription = "Pedagogical C code" |
Definition at line 48 of file thig_twofish2.c.
| CONST char* modeString = "" |
Definition at line 50 of file thig_twofish2.c.
| int numRounds[4] = {0,ROUNDS_128,ROUNDS_192,ROUNDS_256} |
number of rounds for various key sizes: 128, 192, 256
Definition at line 61 of file thig_twofish2.c.
Referenced by makeKey().
1.5.2