?? serpent.c
字號:
k_set(18,a,b,c,d);sb1(a,b,c,d,e,f,g,h);k_get(18,e,f,g,h);
k_set(19,a,b,c,d);sb0(a,b,c,d,e,f,g,h);k_get(19,e,f,g,h);
k_set(20,a,b,c,d);sb7(a,b,c,d,e,f,g,h);k_get(20,e,f,g,h);
k_set(21,a,b,c,d);sb6(a,b,c,d,e,f,g,h);k_get(21,e,f,g,h);
k_set(22,a,b,c,d);sb5(a,b,c,d,e,f,g,h);k_get(22,e,f,g,h);
k_set(23,a,b,c,d);sb4(a,b,c,d,e,f,g,h);k_get(23,e,f,g,h);
k_set(24,a,b,c,d);sb3(a,b,c,d,e,f,g,h);k_get(24,e,f,g,h);
k_set(25,a,b,c,d);sb2(a,b,c,d,e,f,g,h);k_get(25,e,f,g,h);
k_set(26,a,b,c,d);sb1(a,b,c,d,e,f,g,h);k_get(26,e,f,g,h);
k_set(27,a,b,c,d);sb0(a,b,c,d,e,f,g,h);k_get(27,e,f,g,h);
k_set(28,a,b,c,d);sb7(a,b,c,d,e,f,g,h);k_get(28,e,f,g,h);
k_set(29,a,b,c,d);sb6(a,b,c,d,e,f,g,h);k_get(29,e,f,g,h);
k_set(30,a,b,c,d);sb5(a,b,c,d,e,f,g,h);k_get(30,e,f,g,h);
k_set(31,a,b,c,d);sb4(a,b,c,d,e,f,g,h);k_get(31,e,f,g,h);
k_set(32,a,b,c,d);sb3(a,b,c,d,e,f,g,h);k_get(32,e,f,g,h);
}
void serpentEncrypt(SERPENTCTX* pCtx,
const WORD32* pInBlock,
WORD32* pOutBlock)
{
WORD32 a,b,c,d,e,f,g,h;
WORD32 t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16;
WORD32* l_key = pCtx->l_key;
a = pInBlock[0];
b = pInBlock[1];
c = pInBlock[2];
d = pInBlock[3];
// perform 32 rounds of encryption
k_xor( 0,a,b,c,d); sb0(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor( 1,e,f,g,h); sb1(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor( 2,a,b,c,d); sb2(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor( 3,e,f,g,h); sb3(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor( 4,a,b,c,d); sb4(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor( 5,e,f,g,h); sb5(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor( 6,a,b,c,d); sb6(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor( 7,e,f,g,h); sb7(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor( 8,a,b,c,d); sb0(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor( 9,e,f,g,h); sb1(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor(10,a,b,c,d); sb2(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor(11,e,f,g,h); sb3(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor(12,a,b,c,d); sb4(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor(13,e,f,g,h); sb5(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor(14,a,b,c,d); sb6(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor(15,e,f,g,h); sb7(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor(16,a,b,c,d); sb0(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor(17,e,f,g,h); sb1(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor(18,a,b,c,d); sb2(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor(19,e,f,g,h); sb3(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor(20,a,b,c,d); sb4(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor(21,e,f,g,h); sb5(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor(22,a,b,c,d); sb6(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor(23,e,f,g,h); sb7(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor(24,a,b,c,d); sb0(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor(25,e,f,g,h); sb1(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor(26,a,b,c,d); sb2(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor(27,e,f,g,h); sb3(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor(28,a,b,c,d); sb4(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor(29,e,f,g,h); sb5(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor(30,a,b,c,d); sb6(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor(31,e,f,g,h); sb7(e,f,g,h,a,b,c,d); k_xor(32,a,b,c,d);
pOutBlock[0] = a;
pOutBlock[1] = b;
pOutBlock[2] = c;
pOutBlock[3] = d;
}
void serpentDecrypt(SERPENTCTX* pCtx,
const WORD32* pInBlock,
WORD32* pOutBlock)
{
WORD32 a,b,c,d,e,f,g,h;
WORD32 t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16;
WORD32* l_key = pCtx->l_key;
a = pInBlock[0];
b = pInBlock[1];
c = pInBlock[2];
d = pInBlock[3];
k_xor(32,a,b,c,d); ib7(a,b,c,d,e,f,g,h); k_xor(31,e,f,g,h);
irot(e,f,g,h); ib6(e,f,g,h,a,b,c,d); k_xor(30,a,b,c,d);
irot(a,b,c,d); ib5(a,b,c,d,e,f,g,h); k_xor(29,e,f,g,h);
irot(e,f,g,h); ib4(e,f,g,h,a,b,c,d); k_xor(28,a,b,c,d);
irot(a,b,c,d); ib3(a,b,c,d,e,f,g,h); k_xor(27,e,f,g,h);
irot(e,f,g,h); ib2(e,f,g,h,a,b,c,d); k_xor(26,a,b,c,d);
irot(a,b,c,d); ib1(a,b,c,d,e,f,g,h); k_xor(25,e,f,g,h);
irot(e,f,g,h); ib0(e,f,g,h,a,b,c,d); k_xor(24,a,b,c,d);
irot(a,b,c,d); ib7(a,b,c,d,e,f,g,h); k_xor(23,e,f,g,h);
irot(e,f,g,h); ib6(e,f,g,h,a,b,c,d); k_xor(22,a,b,c,d);
irot(a,b,c,d); ib5(a,b,c,d,e,f,g,h); k_xor(21,e,f,g,h);
irot(e,f,g,h); ib4(e,f,g,h,a,b,c,d); k_xor(20,a,b,c,d);
irot(a,b,c,d); ib3(a,b,c,d,e,f,g,h); k_xor(19,e,f,g,h);
irot(e,f,g,h); ib2(e,f,g,h,a,b,c,d); k_xor(18,a,b,c,d);
irot(a,b,c,d); ib1(a,b,c,d,e,f,g,h); k_xor(17,e,f,g,h);
irot(e,f,g,h); ib0(e,f,g,h,a,b,c,d); k_xor(16,a,b,c,d);
irot(a,b,c,d); ib7(a,b,c,d,e,f,g,h); k_xor(15,e,f,g,h);
irot(e,f,g,h); ib6(e,f,g,h,a,b,c,d); k_xor(14,a,b,c,d);
irot(a,b,c,d); ib5(a,b,c,d,e,f,g,h); k_xor(13,e,f,g,h);
irot(e,f,g,h); ib4(e,f,g,h,a,b,c,d); k_xor(12,a,b,c,d);
irot(a,b,c,d); ib3(a,b,c,d,e,f,g,h); k_xor(11,e,f,g,h);
irot(e,f,g,h); ib2(e,f,g,h,a,b,c,d); k_xor(10,a,b,c,d);
irot(a,b,c,d); ib1(a,b,c,d,e,f,g,h); k_xor( 9,e,f,g,h);
irot(e,f,g,h); ib0(e,f,g,h,a,b,c,d); k_xor( 8,a,b,c,d);
irot(a,b,c,d); ib7(a,b,c,d,e,f,g,h); k_xor( 7,e,f,g,h);
irot(e,f,g,h); ib6(e,f,g,h,a,b,c,d); k_xor( 6,a,b,c,d);
irot(a,b,c,d); ib5(a,b,c,d,e,f,g,h); k_xor( 5,e,f,g,h);
irot(e,f,g,h); ib4(e,f,g,h,a,b,c,d); k_xor( 4,a,b,c,d);
irot(a,b,c,d); ib3(a,b,c,d,e,f,g,h); k_xor( 3,e,f,g,h);
irot(e,f,g,h); ib2(e,f,g,h,a,b,c,d); k_xor( 2,a,b,c,d);
irot(a,b,c,d); ib1(a,b,c,d,e,f,g,h); k_xor( 1,e,f,g,h);
irot(e,f,g,h); ib0(e,f,g,h,a,b,c,d); k_xor( 0,a,b,c,d);
pOutBlock[0] = a;
pOutBlock[1] = b;
pOutBlock[2] = c;
pOutBlock[3] = d;
}
// public functions
WORD32 Serpent_GetCipherInfo(CIPHERINFOBLOCK* pInfo)
{
WORD32 lI;
WORD8* pSrc;
WORD8* pDst;
CIPHERINFOBLOCK tmpInfo;
tmpInfo.lSizeOf = pInfo->lSizeOf;
tmpInfo.lBlockSize = SERPENT_BLOCKSIZE;
tmpInfo.lKeySize = SERPENT_KEYSIZE;
tmpInfo.blOwnHasher = BOOL_FALSE;
tmpInfo.lInitDataSize = SERPENT_BLOCKSIZE;
tmpInfo.lContextSize = sizeof(SERPENTCTX);
tmpInfo.bCipherIs = CIPHER_IS_BLOCKLINK;
// copy as many bytes of the information block as possible
pSrc = (WORD8*) &tmpInfo;
pDst = (WORD8*) pInfo;
for (lI = 0; lI < tmpInfo.lSizeOf; lI++)
*pDst++ = *pSrc++;
return CIPHER_ERROR_NOERROR;
}
WORD32 Serpent_SelfTest(void* pTestContext)
{
/*
* NOTE: These test vectors are NOT official test vectors.
* I tested this implementation by comparing it with the outputs given
* in ecb_e_m.txt (see the Serpent package for more details). The official
* test implementation encrypts the plaintext vector 10,000 times, which
* makes it fairly slow. That's why I decided to use my own test vectors.
* However, this implementation was throughly tested and should work fine.
*/
const WORD8 testkey[32] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 };
const WORD32 plaintext[4] =
{ 0x01234567, 0xABCDEF01, 0xA0B1C2D3, 0xE4F58899 };
const WORD32 cipher_must[4] =
{ 0xB633567F, 0x52776204, 0x8D761E99, 0x6701200B };
WORD32 testbuf[4];
// Addition: test vector of the NIST reference, KEYSIZE=256
const int NIST_LOOPS = 10000;
// I=0
// KEY=0000000000000000000000000000000000000000000000000000000000000000
// PT=00000000000000000000000000000000
// CT=92efa3ca9477794d31f4df7bce23e60a
const WORD8 testKeyNist[SERPENT_KEYSIZE] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
const WORD32 plaintextNist[4] = {
0x00000000, 0x00000000, 0x00000000, 0x00000000 };
const WORD32 cipherMustNist[4] = {
0xce23e60a, 0x31f4df7b, 0x9477794d, 0x92efa3ca };
SERPENTCTX* pCtx = (SERPENTCTX*) pTestContext;
int nI;
// initialize the cipher
serpentSetKey(pCtx, testkey, 32);
// encrypt the test vector
serpentEncrypt(pCtx, plaintext, testbuf);
// did it work correctly?
for (nI = 0; nI < 4; nI++)
{
if (testbuf[nI] != cipher_must[nI])
return CIPHER_ERROR_INVALID;
}
// test the decryption
serpentDecrypt(pCtx, testbuf, testbuf);
for (nI = 0; nI < 4; nI++)
{
if (testbuf[nI] != plaintext[nI])
return CIPHER_ERROR_INVALID;
}
// now for the NIST vector (Monte Carlo test)
serpentSetKey(pCtx, testKeyNist, sizeof(testKeyNist));
testbuf[0] = plaintextNist[0];
testbuf[1] = plaintextNist[1];
testbuf[2] = plaintextNist[2];
testbuf[3] = plaintextNist[3];
for (nI = 0; nI < NIST_LOOPS; nI++)
serpentEncrypt(pCtx, testbuf, testbuf);
// did it work correctly?
for (nI = 0; nI < 4; nI++)
if (testbuf[nI] != cipherMustNist[nI])
return CIPHER_ERROR_INVALID;
return CIPHER_ERROR_NOERROR;
}
WORD32 Serpent_CreateWorkContext(void* pContext,
const WORD8* pKey,
WORD32 lKeyLen,
WORD32 lMode,
void* pInitData,
Cipher_RandomGenerator GetRndBytes,
const void* pRandGenData)
{
SERPENTCTX* pCtx = (SERPENTCTX*) pContext;
WORD8* pbInit;
// legacy or standard?
pCtx->blLegacy = (CIPHER_GETFLAGS(lMode) & CIPHER_MODE_FLAG_LEGACY) ? BOOL_TRUE : BOOL_FALSE;
// do the key setup
serpentSetKey(pCtx, pKey, lKeyLen);
pbInit = (WORD8*) pInitData;
if (CIPHER_GETMODE(lMode) == CIPHER_MODE_ENCRYPT)
GetRndBytes(pbInit, SERPENT_BLOCKSIZE, pRandGenData);
// set the CBC IV
if (pCtx->blLegacy)
{
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);
}
else
{
pCtx->cbc_iv[0] = BYTES_TO_WORD32(pbInit);
pCtx->cbc_iv[1] = BYTES_TO_WORD32(pbInit + 4);
pCtx->cbc_iv[2] = BYTES_TO_WORD32(pbInit + 8);
pCtx->cbc_iv[3] = BYTES_TO_WORD32(pbInit + 12);
}
return CIPHER_ERROR_NOERROR;
}
void Serpent_ResetWorkContext(void* pContext,
WORD32 lMode,
void* pInitData,
Cipher_RandomGenerator GetRndBytes,
const void* pRandGenData)
{
SERPENTCTX* pCtx = (SERPENTCTX*) pContext;
WORD8* pbInit = (WORD8*) pInitData;
if (CIPHER_GETMODE(lMode) == CIPHER_MODE_ENCRYPT)
GetRndBytes(pbInit, SERPENT_BLOCKSIZE, pRandGenData);
if (pCtx->blLegacy)
{
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);
}
else
{
pCtx->cbc_iv[0] = BYTES_TO_WORD32(pbInit);
pCtx->cbc_iv[1] = BYTES_TO_WORD32(pbInit + 4);
pCtx->cbc_iv[2] = BYTES_TO_WORD32(pbInit + 8);
pCtx->cbc_iv[3] = BYTES_TO_WORD32(pbInit + 12);
}
}
WORD32 Serpent_DestroyWorkContext(void *pContext)
{
int nI;
WORD8* pCtxBuf = (WORD8*) pContext;
for (nI = 0; nI < sizeof(SERPENTCTX); nI++)
pCtxBuf[nI] = 0x00;
return CIPHER_ERROR_NOERROR;
}
void Serpent_EncryptBuffer(void* pContext,
const void* pSource,
void* pTarget,
WORD32 lNumOfBytes)
{
WORD32 lNumOfBlocks;
WORD32 blk[SERPENT_BLOCKSIZE / 4];
WORD8* pbIn = (WORD8*) pSource;
WORD8* pbOut = (WORD8*) pTarget;
SERPENTCTX* pCtx = (SERPENTCTX*) pContext;
lNumOfBlocks = lNumOfBytes / SERPENT_BLOCKSIZE;
while (lNumOfBlocks--)
{
if (pCtx->blLegacy)
{
blk[0] = BYTES_TO_WORD32_X86(pbIn);
blk[1] = BYTES_TO_WORD32_X86(pbIn + 4);
blk[2] = BYTES_TO_WORD32_X86(pbIn + 8);
blk[3] = BYTES_TO_WORD32_X86(pbIn + 12);
}
else
{
blk[0] = BYTES_TO_WORD32(pbIn);
blk[1] = BYTES_TO_WORD32(pbIn + 4);
blk[2] = BYTES_TO_WORD32(pbIn + 8);
blk[3] = BYTES_TO_WORD32(pbIn + 12);
}
blk[0] ^= pCtx->cbc_iv[0];
blk[1] ^= pCtx->cbc_iv[1];
blk[2] ^= pCtx->cbc_iv[2];
blk[3] ^= pCtx->cbc_iv[3];
// encrypt the buffer
serpentEncrypt(pCtx, blk, blk);
// store the encrypted block
if (pCtx->blLegacy)
{
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)
}
else
{
WORD32_TO_BYTES(blk[0], pbOut)
WORD32_TO_BYTES(blk[1], pbOut + 4)
WORD32_TO_BYTES(blk[2], pbOut + 8)
WORD32_TO_BYTES(blk[3], pbOut + 12)
}
// set the new IV
pCtx->cbc_iv[0] = blk[0];
pCtx->cbc_iv[1] = blk[1];
pCtx->cbc_iv[2] = blk[2];
pCtx->cbc_iv[3] = blk[3];
pbIn += SERPENT_BLOCKSIZE;
pbOut += SERPENT_BLOCKSIZE;
}
}
void Serpent_DecryptBuffer(void* pContext,
const void* pSource,
void* pTarget,
WORD32 lNumOfBytes,
const void* pPreviousBlock)
{
WORD32 lNumOfBlocks;
WORD8* pbIn = (WORD8*) pSource;
WORD8* pbOut = (WORD8*) pTarget;
WORD8* pbPrev = (WORD8*) pPreviousBlock;
WORD32 blk[4];
WORD32 save_cbc_iv[4];
SERPENTCTX* pCtx = (SERPENTCTX*) pContext;
// load a new IV, if necessary
if (pbPrev != CIPHER_NULL)
{
if (pCtx->blLegacy)
{
pCtx->cbc_iv[0] = BYTES_TO_WORD32_X86(pbPrev);
pCtx->cbc_iv[1] = BYTES_TO_WORD32_X86(pbPrev + 4);
pCtx->cbc_iv[2] = BYTES_TO_WORD32_X86(pbPrev + 8);
pCtx->cbc_iv[3] = BYTES_TO_WORD32_X86(pbPrev + 12);
}
else
{
pCtx->cbc_iv[0] = BYTES_TO_WORD32(pbPrev);
pCtx->cbc_iv[1] = BYTES_TO_WORD32(pbPrev + 4);
pCtx->cbc_iv[2] = BYTES_TO_WORD32(pbPrev + 8);
pCtx->cbc_iv[3] = BYTES_TO_WORD32(pbPrev + 12);
}
}
lNumOfBlocks = lNumOfBytes / SERPENT_BLOCKSIZE;
while (lNumOfBlocks--)
{
// load the block
if (pCtx->blLegacy)
{
blk[0] = BYTES_TO_WORD32_X86(pbIn);
blk[1] = BYTES_TO_WORD32_X86(pbIn + 4);
blk[2] = BYTES_TO_WORD32_X86(pbIn + 8);
blk[3] = BYTES_TO_WORD32_X86(pbIn + 12);
}
else
{
blk[0] = BYTES_TO_WORD32(pbIn);
blk[1] = BYTES_TO_WORD32(pbIn + 4);
blk[2] = BYTES_TO_WORD32(pbIn + 8);
blk[3] = BYTES_TO_WORD32(pbIn + 12);
}
// save the current block for later
save_cbc_iv[0] = blk[0];
save_cbc_iv[1] = blk[1];
save_cbc_iv[2] = blk[2];
save_cbc_iv[3] = blk[3];
// decrypt the block
serpentDecrypt(pCtx, blk, blk);
// unchain the block
blk[0] ^= pCtx->cbc_iv[0];
blk[1] ^= pCtx->cbc_iv[1];
blk[2] ^= pCtx->cbc_iv[2];
blk[3] ^= pCtx->cbc_iv[3];
// and safe it
if (pCtx->blLegacy)
{
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)
}
else
{
WORD32_TO_BYTES(blk[0], pbOut)
WORD32_TO_BYTES(blk[1], pbOut + 4)
WORD32_TO_BYTES(blk[2], pbOut + 8)
WORD32_TO_BYTES(blk[3], pbOut + 12)
}
// set the new IV
pCtx->cbc_iv[0] = save_cbc_iv[0];
pCtx->cbc_iv[1] = save_cbc_iv[1];
pCtx->cbc_iv[2] = save_cbc_iv[2];
pCtx->cbc_iv[3] = save_cbc_iv[3];
pbIn += SERPENT_BLOCKSIZE;
pbOut += SERPENT_BLOCKSIZE;
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -