📄 twofish2.c
字号:
* IV = ptr to hex ASCII test representing IV bytes
*
* Return: TRUE on success
* else error code (e.g., BAD_CIPHER_MODE)
*
-****************************************************************************/
int cipherInit(cipherInstance *cipher, BYTE mode,CONST char *IV)
{
int i;
#if VALIDATE_PARMS /* first, sanity check on parameters */
if (cipher == NULL)
return BAD_PARAMS; /* must have a cipherInstance to initialize */
if ((mode != MODE_ECB) && (mode != MODE_CBC) && (mode != MODE_CFB1))
return BAD_CIPHER_MODE; /* must have valid cipher mode */
if ((mode != MODE_ECB) && (IV == NULL))
return BAD_PARAMS; /* must have IV for CBC and CFB modes */
cipher->cipherSig = VALID_SIG;
#if ALIGN32
if ((((int)cipher) & 3) || (((int)cipher->IV) & 3) || (((int)cipher->iv32) & 3))
return BAD_ALIGN32;
#endif
#endif
if (mode != MODE_ECB) /* parse the IV */
{
if (ParseHexDword(BLOCK_SIZE,IV,cipher->iv32,NULL))
return BAD_IV_MAT;
for (i=0;i<BLOCK_SIZE/32;i++) /* make byte-oriented copy for CFB1 */
((DWORD *)cipher->IV)[i] = Bswap(cipher->iv32[i]);
}
cipher->mode = mode;
return TRUE;
}
/*
+*****************************************************************************
*
* Function Name: blockEncrypt
*
* Function: Encrypt block(s) of data using Twofish
*
* Arguments: cipher = ptr to already initialized cipherInstance
* key = ptr to already initialized keyInstance
* input = ptr to data blocks to be encrypted
* inputLen = # bits to encrypt (multiple of blockSize)
* outBuffer = ptr to where to put encrypted blocks
*
* Return: # bits ciphered (>= 0)
* else error code (e.g., BAD_CIPHER_STATE, BAD_KEY_MATERIAL)
*
* Notes: The only supported block size for ECB/CBC modes is BLOCK_SIZE bits.
* If inputLen is not a multiple of BLOCK_SIZE bits in those modes,
* an error BAD_INPUT_LEN is returned. In CFB1 mode, all block
* sizes can be supported.
*
-****************************************************************************/
int blockEncrypt(cipherInstance *cipher, keyInstance *key,CONST BYTE *input,
int inputLen, BYTE *outBuffer)
{
int i,n; /* loop counters */
DWORD x[BLOCK_SIZE/32]; /* block being encrypted */
DWORD t0,t1; /* temp variables */
int rounds=key->numRounds; /* number of rounds */
BYTE bit,ctBit,carry; /* temps for CFB */
#if ALIGN32
BYTE dummyAlign; /* keep dword alignment on stack */
#endif
/* make local copies of things for faster access */
int mode = cipher->mode;
DWORD sk[TOTAL_SUBKEYS];
DWORD IV[BLOCK_SIZE/32];
GetSboxKey;
#if VALIDATE_PARMS
if ((cipher == NULL) || (cipher->cipherSig != VALID_SIG))
return BAD_CIPHER_STATE;
if ((key == NULL) || (key->keySig != VALID_SIG))
return BAD_KEY_INSTANCE;
if ((rounds < 2) || (rounds > MAX_ROUNDS) || (rounds&1))
return BAD_KEY_INSTANCE;
if ((mode != MODE_CFB1) && (inputLen % BLOCK_SIZE))
return BAD_INPUT_LEN;
#if ALIGN32
if ( (((int)cipher) & 3) || (((int)key ) & 3) ||
(((int)input ) & 3) || (((int)outBuffer) & 3))
return BAD_ALIGN32;
#endif
#endif
if (mode == MODE_CFB1)
{ /* use recursion here to handle CFB, one block at a time */
cipher->mode = MODE_ECB; /* do encryption in ECB */
for (n=0;n<inputLen;n++)
{
blockEncrypt(cipher,key,cipher->IV,BLOCK_SIZE,(BYTE *)x);
bit = 0x80 >> (n & 7);/* which bit position in byte */
ctBit = (input[n/8] & bit) ^ ((((BYTE *) x)[0] & 0x80) >> (n&7));
outBuffer[n/8] = (outBuffer[n/8] & ~ bit) | ctBit;
carry = ctBit >> (7 - (n&7));
for (i=BLOCK_SIZE/8-1;i>=0;i--)
{
bit = cipher->IV[i] >> 7; /* save next "carry" from shift */
cipher->IV[i] = (cipher->IV[i] << 1) ^ carry;
carry = bit;
}
}
cipher->mode = MODE_CFB1; /* restore mode for next time */
return inputLen;
}
/* here for ECB, CBC modes */
if (key->direction != DIR_ENCRYPT)
ReverseRoundSubkeys(key,DIR_ENCRYPT); /* reverse the round subkey order */
#ifdef USE_ASM
if ((useAsm & 1) && (inputLen))
#ifdef COMPILE_KEY
if (key->keySig == VALID_SIG)
return ((CipherProc *)(key->encryptFuncPtr))(cipher,key,input,inputLen,outBuffer);
#else
return (*blockEncrypt_86)(cipher,key,input,inputLen,outBuffer);
#endif
#endif
/* make local copy of subkeys for speed */
memcpy(sk,key->subKeys,sizeof(DWORD)*(ROUND_SUBKEYS+2*rounds));
if (mode == MODE_CBC)
BlockCopy(IV,cipher->iv32)
else
IV[0]=IV[1]=IV[2]=IV[3]=0;
for (n=0;n<inputLen;n+=BLOCK_SIZE,input+=BLOCK_SIZE/8,outBuffer+=BLOCK_SIZE/8)
{
#ifdef DEBUG
DebugDump(input,"\n",-1,0,0,0,1);
if (cipher->mode == MODE_CBC)
DebugDump(cipher->iv32,"",IV_ROUND,0,0,0,0);
#endif
#define LoadBlockE(N) x[N]=Bswap(((DWORD *)input)[N]) ^ sk[INPUT_WHITEN+N] ^ IV[N]
LoadBlockE(0); LoadBlockE(1); LoadBlockE(2); LoadBlockE(3);
DebugDump(x,"",0,0,0,0,0);
#define EncryptRound(K,R,id) \
t0 = Fe32##id(x[K ],0); \
t1 = Fe32##id(x[K^1],3); \
x[K^3] = ROL(x[K^3],1); \
x[K^2]^= t0 + t1 + sk[ROUND_SUBKEYS+2*(R) ]; \
x[K^3]^= t0 + 2*t1 + sk[ROUND_SUBKEYS+2*(R)+1]; \
x[K^2] = ROR(x[K^2],1); \
DebugDump(x,"",rounds-(R),0,0,1,0);
#define Encrypt2(R,id) { EncryptRound(0,R+1,id); EncryptRound(2,R,id); }
#if defined(ZERO_KEY)
switch (key->keyLen)
{
case 128:
for (i=rounds-2;i>=0;i-=2)
Encrypt2(i,_128);
break;
case 192:
for (i=rounds-2;i>=0;i-=2)
Encrypt2(i,_192);
break;
case 256:
for (i=rounds-2;i>=0;i-=2)
Encrypt2(i,_256);
break;
}
#else
Encrypt2(14,_);
Encrypt2(12,_);
Encrypt2(10,_);
Encrypt2( 8,_);
Encrypt2( 6,_);
Encrypt2( 4,_);
Encrypt2( 2,_);
Encrypt2( 0,_);
#endif
/* need to do (or undo, depending on your point of view) final swap */
#if LittleEndian
#define StoreBlockE(N) ((DWORD *)outBuffer)[N]=x[N^2] ^ sk[OUTPUT_WHITEN+N]
#else
#define StoreBlockE(N) { t0=x[N^2] ^ sk[OUTPUT_WHITEN+N]; ((DWORD *)outBuffer)[N]=Bswap(t0); }
#endif
StoreBlockE(0); StoreBlockE(1); StoreBlockE(2); StoreBlockE(3);
if (mode == MODE_CBC)
{
IV[0]=Bswap(((DWORD *)outBuffer)[0]);
IV[1]=Bswap(((DWORD *)outBuffer)[1]);
IV[2]=Bswap(((DWORD *)outBuffer)[2]);
IV[3]=Bswap(((DWORD *)outBuffer)[3]);
}
#ifdef DEBUG
DebugDump(outBuffer,"",rounds+1,0,0,0,1);
if (cipher->mode == MODE_CBC)
DebugDump(cipher->iv32,"",IV_ROUND,0,0,0,0);
#endif
}
if (mode == MODE_CBC)
BlockCopy(cipher->iv32,IV);
return inputLen;
}
/*
+*****************************************************************************
*
* Function Name: blockDecrypt
*
* Function: Decrypt block(s) of data using Twofish
*
* Arguments: cipher = ptr to already initialized cipherInstance
* key = ptr to already initialized keyInstance
* input = ptr to data blocks to be decrypted
* inputLen = # bits to encrypt (multiple of blockSize)
* outBuffer = ptr to where to put decrypted blocks
*
* Return: # bits ciphered (>= 0)
* else error code (e.g., BAD_CIPHER_STATE, BAD_KEY_MATERIAL)
*
* Notes: The only supported block size for ECB/CBC modes is BLOCK_SIZE bits.
* If inputLen is not a multiple of BLOCK_SIZE bits in those modes,
* an error BAD_INPUT_LEN is returned. In CFB1 mode, all block
* sizes can be supported.
*
-****************************************************************************/
int blockDecrypt(cipherInstance *cipher, keyInstance *key,CONST BYTE *input,
int inputLen, BYTE *outBuffer)
{
int i,n; /* loop counters */
DWORD x[BLOCK_SIZE/32]; /* block being encrypted */
DWORD t0,t1; /* temp variables */
int rounds=key->numRounds; /* number of rounds */
BYTE bit,ctBit,carry; /* temps for CFB */
#if ALIGN32
BYTE dummyAlign; /* keep dword alignment on stack */
#endif
/* make local copies of things for faster access */
int mode = cipher->mode;
DWORD sk[TOTAL_SUBKEYS];
DWORD IV[BLOCK_SIZE/32];
GetSboxKey;
#if VALIDATE_PARMS
if ((cipher == NULL) || (cipher->cipherSig != VALID_SIG))
return BAD_CIPHER_STATE;
if ((key == NULL) || (key->keySig != VALID_SIG))
return BAD_KEY_INSTANCE;
if ((rounds < 2) || (rounds > MAX_ROUNDS) || (rounds&1))
return BAD_KEY_INSTANCE;
if ((cipher->mode != MODE_CFB1) && (inputLen % BLOCK_SIZE))
return BAD_INPUT_LEN;
#if ALIGN32
if ( (((int)cipher) & 3) || (((int)key ) & 3) ||
(((int)input) & 3) || (((int)outBuffer) & 3))
return BAD_ALIGN32;
#endif
#endif
if (cipher->mode == MODE_CFB1)
{ /* use blockEncrypt here to handle CFB, one block at a time */
cipher->mode = MODE_ECB; /* do encryption in ECB */
for (n=0;n<inputLen;n++)
{
blockEncrypt(cipher,key,cipher->IV,BLOCK_SIZE,(BYTE *)x);
bit = 0x80 >> (n & 7);
ctBit = input[n/8] & bit;
outBuffer[n/8] = (outBuffer[n/8] & ~ bit) |
(ctBit ^ ((((BYTE *) x)[0] & 0x80) >> (n&7)));
carry = ctBit >> (7 - (n&7));
for (i=BLOCK_SIZE/8-1;i>=0;i--)
{
bit = cipher->IV[i] >> 7; /* save next "carry" from shift */
cipher->IV[i] = (cipher->IV[i] << 1) ^ carry;
carry = bit;
}
}
cipher->mode = MODE_CFB1; /* restore mode for next time */
return inputLen;
}
/* here for ECB, CBC modes */
if (key->direction != DIR_DECRYPT)
ReverseRoundSubkeys(key,DIR_DECRYPT); /* reverse the round subkey order */
#ifdef USE_ASM
if ((useAsm & 2) && (inputLen))
#ifdef COMPILE_KEY
if (key->keySig == VALID_SIG)
return ((CipherProc *)(key->decryptFuncPtr))(cipher,key,input,inputLen,outBuffer);
#else
return (*blockDecrypt_86)(cipher,key,input,inputLen,outBuffer);
#endif
#endif
/* make local copy of subkeys for speed */
memcpy(sk,key->subKeys,sizeof(DWORD)*(ROUND_SUBKEYS+2*rounds));
if (mode == MODE_CBC)
BlockCopy(IV,cipher->iv32)
else
IV[0]=IV[1]=IV[2]=IV[3]=0;
for (n=0;n<inputLen;n+=BLOCK_SIZE,input+=BLOCK_SIZE/8,outBuffer+=BLOCK_SIZE/8)
{
DebugDump(input,"\n",rounds+1,0,0,0,1);
#define LoadBlockD(N) x[N^2]=Bswap(((DWORD *)input)[N]) ^ sk[OUTPUT_WHITEN+N]
LoadBlockD(0); LoadBlockD(1); LoadBlockD(2); LoadBlockD(3);
#define DecryptRound(K,R,id) \
t0 = Fe32##id(x[K ],0); \
t1 = Fe32##id(x[K^1],3); \
DebugDump(x,"",(R)+1,0,0,1,0); \
x[K^2] = ROL (x[K^2],1); \
x[K^2]^= t0 + t1 + sk[ROUND_SUBKEYS+2*(R) ]; \
x[K^3]^= t0 + 2*t1 + sk[ROUND_SUBKEYS+2*(R)+1]; \
x[K^3] = ROR (x[K^3],1); \
#define Decrypt2(R,id) { DecryptRound(2,R+1,id); DecryptRound(0,R,id); }
#if defined(ZERO_KEY)
switch (key->keyLen)
{
case 128:
for (i=rounds-2;i>=0;i-=2)
Decrypt2(i,_128);
break;
case 192:
for (i=rounds-2;i>=0;i-=2)
Decrypt2(i,_192);
break;
case 256:
for (i=rounds-2;i>=0;i-=2)
Decrypt2(i,_256);
break;
}
#else
{
Decrypt2(14,_);
Decrypt2(12,_);
Decrypt2(10,_);
Decrypt2( 8,_);
Decrypt2( 6,_);
Decrypt2( 4,_);
Decrypt2( 2,_);
Decrypt2( 0,_);
}
#endif
DebugDump(x,"",0,0,0,0,0);
if (cipher->mode == MODE_ECB)
{
#if LittleEndian
#define StoreBlockD(N) ((DWORD *)outBuffer)[N] = x[N] ^ sk[INPUT_WHITEN+N]
#else
#define StoreBlockD(N) { t0=x[N]^sk[INPUT_WHITEN+N]; ((DWORD *)outBuffer)[N] = Bswap(t0); }
#endif
StoreBlockD(0); StoreBlockD(1); StoreBlockD(2); StoreBlockD(3);
#undef StoreBlockD
DebugDump(outBuffer,"",-1,0,0,0,1);
continue;
}
else
{
#define StoreBlockD(N) x[N] ^= sk[INPUT_WHITEN+N] ^ IV[N]; \
IV[N] = Bswap(((DWORD *)input)[N]); \
((DWORD *)outBuffer)[N] = Bswap(x[N]);
StoreBlockD(0); StoreBlockD(1); StoreBlockD(2); StoreBlockD(3);
#undef StoreBlockD
DebugDump(outBuffer,"",-1,0,0,0,1);
}
}
return inputLen;
}
DWORD TwofishCodeSize(void)
{
DWORD x= Here(0);
#ifdef USE_ASM
if (useAsm & 3)
return TwofishAsmCodeSize();
#endif
return x - TwofishCodeStart();
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -