?? tripledes.c
字號(hào):
/*
* Copyright 1997-2005 Markus Hahn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "TripleDES.h"
// internal constants
#define KEYSETUP_ENCRYPTION 0
#define KEYSETUP_DECRYPTION 1
// prototypes of the support routines
void _expandPureDESKey(const WORD8*, WORD8*);
void _keysetup(WORD8*, int, WORD32*);
void _processBlock(WORD8*, WORD8*, WORD32*);
void _blkcpy(WORD8*, WORD8*);
void _blkcpy_r(WORD8*, WORD8*);
WORD32 TripleDES_GetCipherInfo
(CIPHERINFOBLOCK* pInfo)
{
WORD8* pSrc;
WORD8* pDst;
CIPHERINFOBLOCK tempinfo;
WORD32 lI;
// prepare the information context
tempinfo.lSizeOf = pInfo->lSizeOf;
tempinfo.lBlockSize = TRIPLEDES_BLOCKSIZE;
tempinfo.lKeySize = TRIPLEDES_KEYSIZE;
tempinfo.blOwnHasher = BOOL_FALSE;
tempinfo.lInitDataSize = TRIPLEDES_BLOCKSIZE;
tempinfo.lContextSize = sizeof(TRIPLEDESCTX);
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 TripleDES_SelfTest
(void* pTestContext)
{
// test the cipher for correct encrypting and decrypting
// (we test only a single DES stage with the original validation sets)
static WORD8 refkey[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
static WORD8 plainBlock[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 };
static WORD8 cipherBlock[8] = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d };
WORD8 workBlock[8];
WORD32 k[32];
int nI;
// encrypt the test block
_keysetup(refkey, KEYSETUP_ENCRYPTION, k);
_processBlock(plainBlock, workBlock, k);
// equal ciphertexts?
for (nI = 0; nI < 8; nI++)
if (workBlock[nI] != cipherBlock[nI]) return CIPHER_ERROR_INVALID;
// decrypt the test block
_keysetup(refkey, KEYSETUP_DECRYPTION, k);
_processBlock(workBlock, workBlock, k);
// equal plaintexts?
for (nI = 0; nI < 8; nI++)
{
if (plainBlock[nI] != workBlock[nI]) return CIPHER_ERROR_INVALID;
}
return CIPHER_ERROR_NOERROR;
}
WORD32 TripleDES_CreateWorkContext
(void* pContext,
const WORD8* pKey,
WORD32 lKeyLen,
WORD32 lMode,
void* pInitData,
Cipher_RandomGenerator GetRndBytes,
const void* pRndGenData)
{
int nI;
WORD8* pbInit;
WORD8 deskey1[8];
WORD8 deskey2[8];
WORD8 deskey3[8];
TRIPLEDESCTX* pCtx;
pCtx = (TRIPLEDESCTX*) pContext;
pCtx->blLegacy = (CIPHER_GETFLAGS(lMode) & CIPHER_MODE_FLAG_LEGACY) ? BOOL_TRUE : BOOL_FALSE;
// create three DES keys from the "pure" key, ignoring the parity
_expandPureDESKey(pKey, deskey1);
_expandPureDESKey(pKey + 7, deskey2);
_expandPureDESKey(pKey + 14, deskey3);
// run the key setups
if (CIPHER_GETMODE(lMode) == CIPHER_MODE_ENCRYPT)
{
_keysetup(deskey1, KEYSETUP_ENCRYPTION, pCtx->k1);
_keysetup(deskey2, KEYSETUP_DECRYPTION, pCtx->k2);
_keysetup(deskey3, KEYSETUP_ENCRYPTION, pCtx->k3);
}
else
{
_keysetup(deskey1, KEYSETUP_DECRYPTION, pCtx->k1);
_keysetup(deskey2, KEYSETUP_ENCRYPTION, pCtx->k2);
_keysetup(deskey3, KEYSETUP_DECRYPTION, pCtx->k3);
}
// delete the DES keys
for (nI = 0; nI < 8; nI++)
{
deskey1[nI] = 0;
deskey2[nI] = 0;
deskey3[nI] = 0;
}
// for encryption create a CBC IV
pbInit = (WORD8*) pInitData;
if (lMode == CIPHER_MODE_ENCRYPT)
{
GetRndBytes(pbInit, TRIPLEDES_BLOCKSIZE, pRndGenData);
}
if (pCtx->blLegacy)
{
// the old code stored everything completely reversed
_blkcpy_r(pbInit, pCtx->cbciv);
}
else
{
_blkcpy(pbInit, pCtx->cbciv);
}
// FIXME: weak keys in triple-DES?
return CIPHER_ERROR_NOERROR;
}
void TripleDES_ResetWorkContext
(void* pContext,
WORD32 lMode,
void* pInitData,
Cipher_RandomGenerator GetRndBytes,
const void* pRndGenData)
{
TRIPLEDESCTX* pCtx = (TRIPLEDESCTX*) pContext;
// just reset the CBC IV
WORD8* pbInit = (WORD8*) pInitData;
if (CIPHER_GETMODE(lMode) == CIPHER_MODE_ENCRYPT)
GetRndBytes(pbInit, TRIPLEDES_BLOCKSIZE, pRndGenData);
if (pCtx->blLegacy)
{
_blkcpy_r(pbInit, pCtx->cbciv);
}
else
{
_blkcpy(pbInit, pCtx->cbciv);
}
}
WORD32 TripleDES_DestroyWorkContext
(void* pContext)
{
// clear the context
int nI;
WORD8* pClearIt = (WORD8*) pContext;
for (nI = 0; nI < sizeof(TRIPLEDESCTX); nI++)
pClearIt[nI] = 0x00;
return CIPHER_ERROR_NOERROR;
}
void TripleDES_EncryptBuffer
(void* pContext,
const void* pSource,
void* pTarget,
WORD32 lNumOfBytes)
{
WORD32 lI, lJ;
WORD8* pbIn = (WORD8*) pSource;
WORD8* pbOut = (WORD8*) pTarget;
TRIPLEDESCTX* pCtx = (TRIPLEDESCTX*) pContext;
lNumOfBytes &= ~(TRIPLEDES_BLOCKSIZE - 1);
// work through all blocks...
for (lI = 0; lI < lNumOfBytes; lI += TRIPLEDES_BLOCKSIZE)
{
// copy and chain the recent block
if (pCtx->blLegacy)
{
// (we have to bring back the CBC IV into 64bit little endian)
for (lJ = 0; lJ < TRIPLEDES_BLOCKSIZE; lJ++)
pbOut[lI + lJ] = pbIn[lI + lJ] ^ pCtx->cbciv[(TRIPLEDES_BLOCKSIZE - 1) - lJ];
}
else
{
for (lJ = 0; lJ < TRIPLEDES_BLOCKSIZE; lJ++)
pbOut[lI + lJ] = pbIn[lI + lJ] ^ pCtx->cbciv[lJ];
}
// encrypt the block
_processBlock(&pbOut[lI], &pbOut[lI], pCtx->k1);
_processBlock(&pbOut[lI], &pbOut[lI], pCtx->k2);
_processBlock(&pbOut[lI], &pbOut[lI], pCtx->k3);
// set the new CBC IV (same as above)
if (pCtx->blLegacy)
{
_blkcpy_r(&pbOut[lI], pCtx->cbciv);
}
else
{
_blkcpy(&pbOut[lI], pCtx->cbciv);
}
}
}
void TripleDES_DecryptBuffer
(void* pContext,
const void* pSource,
void* pTarget,
WORD32 lNumOfBytes,
const void* pPreviousBlock)
{
WORD32 lI, lJ;
WORD8 saveiv[TRIPLEDES_BLOCKSIZE];
WORD8* pbIn = (WORD8*) pSource;
WORD8* pbOut = (WORD8*) pTarget;
WORD8* pbPrev;
TRIPLEDESCTX* pCtx = (TRIPLEDESCTX*) pContext;
lNumOfBytes &= ~(TRIPLEDES_BLOCKSIZE - 1);
// load a new CBC IV, if necessary
if (pPreviousBlock != CIPHER_NULL)
{
pbPrev = (WORD8*)pPreviousBlock;
if (pCtx->blLegacy)
{
_blkcpy_r(pbPrev, pCtx->cbciv);
}
else
{
_blkcpy(pbPrev, pCtx->cbciv);
}
}
// work through all blocks...
for (lI = 0; lI < lNumOfBytes; lI += 8)
{
// save the recent CBC IV (don't care for the layout right now)
_blkcpy(&pbIn[lI], saveiv);
// decrypt the block
_processBlock(&pbIn [lI], &pbOut[lI], pCtx->k3);
_processBlock(&pbOut[lI], &pbOut[lI], pCtx->k2);
_processBlock(&pbOut[lI], &pbOut[lI], pCtx->k1);
// dechain the recent block
if (pCtx->blLegacy)
{
// same as above: bring back the IV into the old format
for (lJ = 0; lJ < TRIPLEDES_BLOCKSIZE; lJ++)
pbOut[lI + lJ] ^= pCtx->cbciv[(TRIPLEDES_BLOCKSIZE - 1) - lJ];
}
else
{
for (lJ = 0; lJ < TRIPLEDES_BLOCKSIZE; lJ++)
pbOut[lI + lJ] ^= pCtx->cbciv[lJ];
}
// set the new CBC IV (normalized)
if (pCtx->blLegacy)
{
_blkcpy_r(saveiv, pCtx->cbciv);
}
else
{
_blkcpy(saveiv, pCtx->cbciv);
}
}
}
//////////////////////////////////////////////////////////////////////////////
// support routines implementation...
// constant stuff...
static WORD8 pc1[56] =
{
56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3
};
static WORD8 totrot[16] =
{
1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
};
static WORD8 pc2[48] =
{
13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
};
static WORD16 bytebit[8] =
{
0200, 0100, 040, 020, 010, 04, 02, 01
};
static WORD32 bigbyte[24] =
{
0x800000L, 0x400000L, 0x200000L, 0x100000L,
0x80000L, 0x40000L, 0x20000L, 0x10000L,
0x8000L, 0x4000L, 0x2000L, 0x1000L,
0x800L, 0x400L, 0x200L, 0x100L,
0x80L, 0x40L, 0x20L, 0x10L,
0x8L, 0x4L, 0x2L, 0x1L
};
static unsigned long SP1[64] =
{
0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -