📄 twofish.c
字号:
WORD32 lX2 = pBlock[0] ^ pCtx->subKeys[OUTPUTWHITEN];
WORD32 lX3 = pBlock[1] ^ pCtx->subKeys[OUTPUTWHITEN + 1];
WORD32 lX0 = pBlock[2] ^ pCtx->subKeys[OUTPUTWHITEN + 2];
WORD32 lX1 = pBlock[3] ^ pCtx->subKeys[OUTPUTWHITEN + 3];
// decryption loop (unrolled)
WORD32 lT0;
WORD32 lT1;
dec_loop(lX0, lX1, lX2, lX3, 31)
dec_loop(lX2, lX3, lX0, lX1, 29)
dec_loop(lX0, lX1, lX2, lX3, 27)
dec_loop(lX2, lX3, lX0, lX1, 25)
dec_loop(lX0, lX1, lX2, lX3, 23)
dec_loop(lX2, lX3, lX0, lX1, 21)
dec_loop(lX0, lX1, lX2, lX3, 19)
dec_loop(lX2, lX3, lX0, lX1, 17)
dec_loop(lX0, lX1, lX2, lX3, 15)
dec_loop(lX2, lX3, lX0, lX1, 13)
dec_loop(lX0, lX1, lX2, lX3, 11)
dec_loop(lX2, lX3, lX0, lX1, 9)
dec_loop(lX0, lX1, lX2, lX3, 7)
dec_loop(lX2, lX3, lX0, lX1, 5)
dec_loop(lX0, lX1, lX2, lX3, 3)
dec_loop(lX2, lX3, lX0, lX1, 1)
// final rewhitening and back copy
pBlock[0] = lX0 ^ pCtx->subKeys[INPUTWHITEN];
pBlock[1] = lX1 ^ pCtx->subKeys[INPUTWHITEN + 1];
pBlock[2] = lX2 ^ pCtx->subKeys[INPUTWHITEN + 2];
pBlock[3] = lX3 ^ pCtx->subKeys[INPUTWHITEN + 3];
}
// interface implementation
WORD32 Twofish_GetCipherInfo
(CIPHERINFOBLOCK *pInfo)
{
WORD8* pSrc;
WORD8* pDst;
CIPHERINFOBLOCK tempinfo;
WORD32 lI;
// prepare the information context
tempinfo.lSizeOf = pInfo->lSizeOf;
tempinfo.lBlockSize = TWOFISH_BLOCKSIZE;
tempinfo.lKeySize = TWOFISH_KEYSIZE;
tempinfo.blOwnHasher = BOOL_FALSE;
tempinfo.lInitDataSize = TWOFISH_BLOCKSIZE;
tempinfo.lContextSize = sizeof(TWOFISHCTX);
tempinfo.bCipherIs = CIPHER_IS_BLOCKLINK;
// copy as many bytes of the information block as possible
pSrc = (WORD8*) &tempinfo;
pDst = (WORD8*) pInfo;
for (lI = 0; lI < tempinfo.lSizeOf; lI++)
*pDst++ = *pSrc++;
return CIPHER_ERROR_NOERROR;
}
WORD32 Twofish_SelfTest
(void* pCtx)
{
// encrypt, decrypt and check an official test vector
WORD8 testkey[32] =
{
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
};
WORD8 plaintext[16] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
WORD8 cipher_must[16] =
{
0x37, 0x52, 0x7B, 0xE0, 0x05, 0x23, 0x34, 0xB8,
0x9F, 0x0C, 0xFC, 0xCA, 0xE8, 0x7C, 0xFA, 0x20
};
WORD8 ciphertext[16];
WORD8 finaltext[16];
WORD8 initdata[16];
WORD32 blk[4];
int nI;
for (nI = 0; nI < 16; nI++) initdata[nI] = 0;
// create a context (used for en- and decryption,
// because CBC isn't used and we init. in decryption
// mode we don't need a random number generator)
Twofish_CreateWorkContext(pCtx,
testkey,
32,
CIPHER_MODE_DECRYPT,
initdata,
0,
0);
// (just to be sure)
for (nI = 0; nI < 16; nI++)
ciphertext[nI] = finaltext[nI] = 0xfe;
// test the encryption
blk[0] = BYTES_TO_WORD32_X86(plaintext);
blk[1] = BYTES_TO_WORD32_X86(plaintext + 4);
blk[2] = BYTES_TO_WORD32_X86(plaintext + 8);
blk[3] = BYTES_TO_WORD32_X86(plaintext + 12);
twofish_blockEncrypt((TWOFISHCTX*)pCtx, blk);
WORD32_TO_BYTES_X86(blk[0], ciphertext)
WORD32_TO_BYTES_X86(blk[1], ciphertext + 4)
WORD32_TO_BYTES_X86(blk[2], ciphertext + 8)
WORD32_TO_BYTES_X86(blk[3], ciphertext + 12)
for (nI = 0; nI < 16; nI++)
if (ciphertext[nI] != cipher_must[nI])
return CIPHER_ERROR_INVALID;
// test the decryption
twofish_blockDecrypt((TWOFISHCTX*)pCtx, blk);
WORD32_TO_BYTES_X86(blk[0], finaltext)
WORD32_TO_BYTES_X86(blk[1], finaltext + 4)
WORD32_TO_BYTES_X86(blk[2], finaltext + 8)
WORD32_TO_BYTES_X86(blk[3], finaltext + 12)
for (nI = 0; nI < 16; nI++)
if (plaintext[nI] != finaltext[nI])
return CIPHER_ERROR_INVALID;
// tests passed
return CIPHER_ERROR_NOERROR;
}
WORD32 Twofish_CreateWorkContext
(void* pContext,
const WORD8* pKey,
WORD32 lKeyLen,
WORD32 lMode,
void* pInitData,
Cipher_RandomGenerator GetRndBytes,
const void* pRndGenData)
{
WORD8* pbInit;
int nI, nJ, nQ;
WORD32 lA;
WORD32 lB;
TWOFISHCTX* pCtx = (TWOFISHCTX*) pContext;
WORD32 lK0, lK1, lK2, lK3;
WORD32 lB0, lB1, lB2, lB3;
WORD32 key32[TWOFISH_KEYSIZE / 4];
WORD32 sboxKeys[TWOFISH_KEYSIZE / 8];
// even and odd key dwords
WORD32 k32e[TWOFISH_KEYSIZE / 8];
WORD32 k32o[TWOFISH_KEYSIZE / 8];
// copy the key material, depends on a fixed key size(!)
// (direct copy is possible here)
for (nI = 0; nI < (TWOFISH_KEYSIZE / 4); nI++, pKey += 4)
key32[nI] = BYTES_TO_WORD32_X86(pKey);
// calculate the subkeys, pass #1
nJ = (TWOFISH_KEYSIZE / 8) - 1;
for (nI = 0; nI < (TWOFISH_KEYSIZE / 8); nI++)
{
// split into even/odd key dwords
k32e[nI] = key32[nI << 1];
k32o[nI] = key32[(nI << 1) + 1];
// compute S-box keys using (12,8) Reed-Solomon code over GF(256),
// in reversed order
sboxKeys[nJ--] = RS_MDS_Encode(k32e[nI], k32o[nI]);
}
// compute round subkeys for PHT
nQ = 0;
for (nI = 0; nI < (TOTALSUBKEYS / 2); nI++, nQ += SK_STEP)
{
lA = f32(nQ, k32e); // lA uses even key dwords
lB = f32(nQ + SK_BUMP, k32o); // lB uses odd key dwords
lB = ROL(lB, 8);
// combine with a PHT
pCtx->subKeys[nI << 1] = lA + lB;
lB = lA + (lB << 1);
pCtx->subKeys[(nI << 1) + 1] = ROL(lB, SK_ROTL);
}
// fully expand the table (subkeys calc., pass #2)
lK0 = sboxKeys[0];
lK1 = sboxKeys[1];
lK2 = sboxKeys[2];
lK3 = sboxKeys[3];
for (nI = 0; nI < 256; nI++)
{
lB0 = p8(04)[nI] ^ b0(lK3);
lB1 = p8(14)[nI] ^ b1(lK3);
lB2 = p8(24)[nI] ^ b2(lK3);
lB3 = p8(34)[nI] ^ b3(lK3);
lB0 = p8(03)[lB0] ^ b0(lK2);
lB1 = p8(13)[lB1] ^ b1(lK2);
lB2 = p8(23)[lB2] ^ b2(lK2);
lB3 = p8(33)[lB3] ^ b3(lK2);
pCtx->sbox[ (nI << 1)] = mds[0][p8(01)[p8(02)[lB0] ^ b0(lK1)] ^ b0(lK0)];
pCtx->sbox[ 1 + (nI << 1)] = mds[1][p8(11)[p8(12)[lB1] ^ b1(lK1)] ^ b1(lK0)];
pCtx->sbox[0x200 + (nI << 1)] = mds[2][p8(21)[p8(22)[lB2] ^ b2(lK1)] ^ b2(lK0)];
pCtx->sbox[0x201 + (nI << 1)] = mds[3][p8(31)[p8(32)[lB3] ^ b3(lK1)] ^ b3(lK0)];
}
// clear all the local buffers now
for (nI = 0; nI < (TWOFISH_KEYSIZE / 4); nI++)
key32[nI] = 0;
for (nI = 0; nI < (TWOFISH_KEYSIZE / 8); nI++)
{
k32e[nI] = k32o[nI] = 0;
sboxKeys[nI] = 0;
}
// create and save the CBC iv or get it for decryption
pbInit = (WORD8*) pInitData;
if (CIPHER_GETMODE(lMode) == CIPHER_MODE_ENCRYPT)
{
GetRndBytes(pbInit, TWOFISH_BLOCKSIZE, pRndGenData);
}
pCtx->cbc_iv[0] = BYTES_TO_WORD32_X86(pbInit);
pCtx->cbc_iv[1] = BYTES_TO_WORD32_X86(pbInit + 4);
pCtx->cbc_iv[2] = BYTES_TO_WORD32_X86(pbInit + 8);
pCtx->cbc_iv[3] = BYTES_TO_WORD32_X86(pbInit + 12);
return CIPHER_ERROR_NOERROR;
}
void Twofish_ResetWorkContext
(void* pContext,
WORD32 lMode,
void* pInitData,
Cipher_RandomGenerator GetRndBytes,
const void* pRndGenData)
{
WORD8* pbInit;
TWOFISHCTX* pCtx = (TWOFISHCTX*) pContext;
// create and save the CBC iv or get it for decryption
pbInit = (WORD8*) pInitData;
if (CIPHER_GETMODE(lMode) == CIPHER_MODE_ENCRYPT)
{
GetRndBytes(pbInit, 16, pRndGenData);
}
pCtx->cbc_iv[0] = BYTES_TO_WORD32_X86(pbInit);
pCtx->cbc_iv[1] = BYTES_TO_WORD32_X86(pbInit + 4);
pCtx->cbc_iv[2] = BYTES_TO_WORD32_X86(pbInit + 8);
pCtx->cbc_iv[3] = BYTES_TO_WORD32_X86(pbInit + 12);
}
WORD32 Twofish_DestroyWorkContext
(void* pContext)
{
WORD8* pDel = (WORD8*) pContext;
int nI;
// just clear the context
for (nI = 0; nI < sizeof(TWOFISHCTX); nI++) *pDel++ = 0;
return CIPHER_ERROR_NOERROR;
}
void Twofish_EncryptBuffer
(void* pContext,
const void* pSource,
void* pTarget,
WORD32 lNumOfBytes)
{
WORD32 lI, lJ;
WORD32 blk[4];
WORD8* pbIn = (WORD8*) pSource;
WORD8* pbOut = (WORD8*) pTarget;
TWOFISHCTX* pCtx = (TWOFISHCTX*) pContext;
// work through all blocks
for (lI = 0; lI < (lNumOfBytes / TWOFISH_BLOCKSIZE); lI++)
{
// get and and chain the actual block
blk[0] = BYTES_TO_WORD32_X86(pbIn ) ^ pCtx->cbc_iv[0];
blk[1] = BYTES_TO_WORD32_X86(pbIn + 4) ^ pCtx->cbc_iv[1];
blk[2] = BYTES_TO_WORD32_X86(pbIn + 8) ^ pCtx->cbc_iv[2];
blk[3] = BYTES_TO_WORD32_X86(pbIn + 12) ^ pCtx->cbc_iv[3];
// encrypt the block
twofish_blockEncrypt(pCtx, blk);
// set the new cbc iv
for (lJ = 0; lJ < 4; lJ++)
pCtx->cbc_iv[lJ] = blk[lJ];
// copy the block back
WORD32_TO_BYTES_X86(blk[0], pbOut)
WORD32_TO_BYTES_X86(blk[1], pbOut + 4)
WORD32_TO_BYTES_X86(blk[2], pbOut + 8)
WORD32_TO_BYTES_X86(blk[3], pbOut + 12)
// next block
pbIn += TWOFISH_BLOCKSIZE;
pbOut += TWOFISH_BLOCKSIZE;
}
}
void Twofish_DecryptBuffer
(void* pContext,
const void* pSource,
void* pTarget,
WORD32 lNumOfBytes,
const void* pPreviousBlock)
{
WORD32 lI, lJ;
WORD8* pbIn = (WORD8*) pSource;
WORD8* pbOut = (WORD8*) pTarget;
WORD32 blk[4];
WORD32 save_iv[4];
TWOFISHCTX* pCtx = (TWOFISHCTX*) pContext;
// load a new CBC IV, if necessary
if (pPreviousBlock != CIPHER_NULL)
{
for (lI = 0; lI < 4; lI++)
pCtx->cbc_iv[lI] = ((WORD32*)pPreviousBlock)[lI];
}
// work through all blocks
for (lI = 0; lI < (lNumOfBytes / TWOFISH_BLOCKSIZE); lI++)
{
// get and save the block
save_iv[0] = blk[0] = BYTES_TO_WORD32_X86(pbIn);
save_iv[1] = blk[1] = BYTES_TO_WORD32_X86(pbIn + 4);
save_iv[2] = blk[2] = BYTES_TO_WORD32_X86(pbIn + 8);
save_iv[3] = blk[3] = BYTES_TO_WORD32_X86(pbIn + 12);
// decrypt the block
twofish_blockDecrypt(pCtx, blk);
// unchain the block
for (lJ = 0; lJ < 4; lJ++)
{
blk[lJ] ^= pCtx->cbc_iv[lJ];
}
// save it and set the new IV
WORD32_TO_BYTES_X86(blk[0], pbOut)
WORD32_TO_BYTES_X86(blk[1], pbOut + 4)
WORD32_TO_BYTES_X86(blk[2], pbOut + 8)
WORD32_TO_BYTES_X86(blk[3], pbOut + 12)
for (lJ = 0; lJ < 4; lJ++)
{
pCtx->cbc_iv[lJ] = save_iv[lJ];
}
// next block
pbIn += TWOFISH_BLOCKSIZE;
pbOut += TWOFISH_BLOCKSIZE;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -