📄 ctwofishcipher.cpp
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
$Id: CTwofishCipher.cpp,v 1.6 2002/08/06 20:10:19 dallen Exp $
____________________________________________________________________________*/
#include "pgpClassesConfig.h"
#include "CCRC32.h"
#include "CTwofishCipher.h"
_USING_PGP
// Externs
// For table verification only.
extern "C" BYTE P8x8[2][256];
// Class CTwofishCipher member functions
CTwofishCipher::CTwofishCipher(PGPdiskEncryptionAlgorithm algorithm)
: CCipher(algorithm), mIsKeyAttached(FALSE), mPCurKeyInfo(NULL)
{
pgpAssert(algorithm == kPGPdiskTwoFishAlgorithm);
#if !PGP_EXCEPTIONS
if (Status().IsntError())
Status() = CCipher::Status();
if (Status().IsntError())
Status() = mKeyInfo1.Status();
if (Status().IsntError())
Status() = mKeyInfo2.Status();
#endif // !PGP_EXCEPTIONS
}
SMART_ERROR
CTwofishCipher::Validate() const
{
SMART_ERROR_DECLARE
if (!IsKeyAttached())
#if PGP_EXCEPTIONS
THROW_PGPERROR(kPGPError_BadParams);
#else // !PGP_EXCEPTIONS
error.pgpErr = kPGPError_BadParams;
if (error.IsntError())
#endif // PGP_EXCEPTIONS
{
CCRC32 crc;
crc.Continue(reinterpret_cast<const PGPUInt32 *>(P8x8),
sizeof(P8x8) / sizeof(PGPUInt32));
if (crc.GetCRC() != ValidationCRC)
#if PGP_EXCEPTIONS
THROW_PGPERROR(kPGPError_CorruptData);
#else // !PGP_EXCEPTIONS
error.pgpErr = kPGPError_CorruptData;
#endif // PGP_EXCEPTIONS
}
SMART_ERROR_RETURN
}
void
CTwofishCipher::AttachKey(
const Crypto::SymmetricKey& key,
const Crypto::PassphraseSalt& salt)
{
mKeyInfo1.Wipe();
mKeyInfo2.Wipe();
mKeyInfo1->key = key;
mKeyInfo1->salt = salt;
// Initialize Twofish key instance.
mKeyInfo1->keyInstance.direction = DIR_ENCRYPT;
mKeyInfo1->keyInstance.keyLen = NumKeyBits();
mKeyInfo1->keyInstance.numRounds = TwofishGetNumRounds(NumKeyBits());
pgpCopyMemory(key.bytes, mKeyInfo1->keyInstance.key32, NumKeyBytes());
// Generate round subkeys.
reKey(&mKeyInfo1->keyInstance);
// Setup key 2.
*mKeyInfo2 = *mKeyInfo1;
mKeyInfo2.FlipBytes();
mTrueIfUsingKey1 = TRUE;
mPCurKeyInfo = mKeyInfo1.Get();
mIsKeyAttached = TRUE;
}
void
CTwofishCipher::FlipKeyBytes()
{
pgpAssert(IsKeyAttached());
mKeyInfo1.FlipBytes();
mKeyInfo2.FlipBytes();
if (mTrueIfUsingKey1)
{
mPCurKeyInfo = mKeyInfo2.Get();
mTrueIfUsingKey1 = FALSE;
}
else
{
mPCurKeyInfo = mKeyInfo1.Get();
mTrueIfUsingKey1 = TRUE;
}
}
void
CTwofishCipher::Encrypt(const void *in, void *out, PGPUInt32 numBlocks) const
{
pgpAssert(IsKeyAttached());
pgpAssertAddrValid(in, VoidAlign);
pgpAssertAddrValid(out, VoidAlign);
PGPUInt8 *dataIn = static_cast<PGPUInt8 *>(const_cast<void *>(in));
PGPUInt8 *dataOut = static_cast<PGPUInt8 *>(out);
cipherInstance cipher;
pgpClearMemory(&cipher, sizeof(cipher));
cipher.mode = MODE_ECB;
// BLOCK_SIZE is Twofish block size, not PGPdisk block size (duh).
for (PGPUInt32 i = 0; i < numBlocks; i++)
{
blockEncrypt(&cipher, &mPCurKeyInfo->keyInstance,
dataIn + (i*NumEncryptBytes()), BLOCK_SIZE,
dataOut + (i*NumEncryptBytes()));
}
}
void
CTwofishCipher::Decrypt(const void *in, void *out, PGPUInt32 numBlocks) const
{
pgpAssert(IsKeyAttached());
pgpAssertAddrValid(in, VoidAlign);
pgpAssertAddrValid(out, VoidAlign);
PGPUInt8 *dataIn = static_cast<PGPUInt8 *>(const_cast<void *>(in));
PGPUInt8 *dataOut = static_cast<PGPUInt8 *>(out);
cipherInstance cipher;
pgpClearMemory(&cipher, sizeof(cipher));
cipher.mode = MODE_ECB;
// BLOCK_SIZE is Twofish block size, not PGPdisk block size (duh).
for (PGPUInt32 i = 0; i < numBlocks; i++)
{
blockDecrypt(&cipher, &mPCurKeyInfo->keyInstance,
dataIn + (i*NumDecryptBytes()), BLOCK_SIZE,
dataOut + (i*NumDecryptBytes()));
}
}
void
CTwofishCipher::EncryptCFBdbl(
PGPUInt32 ivs[],
const PGPUInt32* src,
PGPUInt32* dest,
PGPUInt32 len) const
{
pgpAssert(IsKeyAttached());
pgpAssertAddrValid(src, PGPUIn32);
pgpAssertAddrValid(dest, PGPUIn32);
while (len--)
{
Encrypt(ivs, ivs);
*dest++ = ivs[0] ^= *src++;
*dest++ = ivs[1] ^= *src++;
*dest++ = ivs[2] ^= *src++;
*dest++ = ivs[3] ^= *src++;
Encrypt(ivs + 4, ivs + 4);
*dest++ = ivs[4] ^= *src++;
*dest++ = ivs[5] ^= *src++;
*dest++ = ivs[6] ^= *src++;
*dest++ = ivs[7] ^= *src++;
}
}
void
CTwofishCipher::DecryptCFBdbl(
PGPUInt32 ivs[],
const PGPUInt32* src,
PGPUInt32* dest,
PGPUInt32 len) const
{
pgpAssert(IsKeyAttached());
pgpAssertAddrValid(src, PGPUIn32);
pgpAssertAddrValid(dest, PGPUIn32);
PGPUInt32 out[8];
while (len--)
{
Encrypt(ivs, out);
*dest++ = out[0] ^ (ivs[0] = *src++);
*dest++ = out[1] ^ (ivs[1] = *src++);
*dest++ = out[2] ^ (ivs[2] = *src++);
*dest++ = out[3] ^ (ivs[3] = *src++);
Encrypt(ivs + 4, out + 4);
*dest++ = out[4] ^ (ivs[4] = *src++);
*dest++ = out[5] ^ (ivs[5] = *src++);
*dest++ = out[6] ^ (ivs[6] = *src++);
*dest++ = out[7] ^ (ivs[7] = *src++);
}
}
SMART_ERROR
CTwofishCipher::ExportCipher(void *buffer, PGPUInt32 sizeBuffer) const
{
pgpAssert(IsKeyAttached());
pgpAssertAddrValid(buffer, VoidAlign);
SMART_ERROR_DECLARE
if (sizeBuffer < SizeExportedCipher())
#if PGP_EXCEPTIONS
THROW_PGPERROR(kPGPError_BufferTooSmall);
#else // !PGP_EXCEPTIONS
error.pgpErr = kPGPError_BufferTooSmall;
if (error.IsntError())
#endif // PGP_EXCEPTIONS
{
ExportedCipher *pEC = static_cast<ExportedCipher *>(buffer);
pEC->key = mPCurKeyInfo->key;
pEC->salt = mPCurKeyInfo->salt;
}
SMART_ERROR_RETURN
}
SMART_ERROR
CTwofishCipher::ImportCipher(const void *buffer, PGPUInt32 sizeBuffer)
{
pgpAssert(!IsKeyAttached());
pgpAssertAddrValid(buffer, VoidAlign);
SMART_ERROR_DECLARE
if (sizeBuffer < SizeExportedCipher())
#if PGP_EXCEPTIONS
THROW_PGPERROR(kPGPError_BufferTooSmall);
#else // !PGP_EXCEPTIONS
error.pgpErr = kPGPError_BufferTooSmall;
if (error.IsntError())
#endif // PGP_EXCEPTIONS
{
const ExportedCipher *pEC =
static_cast<const ExportedCipher *>(buffer);
AttachKey(pEC->key, pEC->salt);
}
SMART_ERROR_RETURN
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -