📄 unativecryptomodule.cpp
字号:
}
#if !PGP_EXCEPTIONS
if (error.IsntError())
#endif // !PGP_EXCEPTIONS
{
// Encrypt the session key with the key derived from passphrase.
pgpClearMemory(pKeyInfo->encryptedKey.bytes,
sizeof(pKeyInfo->encryptedKey.bytes));
pPassCipher->Encrypt(pCipher->Key().bytes,
pKeyInfo->encryptedKey.bytes,
pCipher->NumKeyBytes() / pCipher->NumEncryptBytes());
// Construct the checkbytes.
pgpClearMemory(pKeyInfo->checkBytes.bytes,
sizeof(pKeyInfo->checkBytes.bytes));
pPassCipher->Encrypt(pPassCipher->Key().bytes,
pKeyInfo->checkBytes.bytes);
}
}
#if PGP_EXCEPTIONS
catch (CComboError& caughtErr)
{
error = caughtErr;
}
#endif // PGP_EXCEPTIONS
return error;
}
CComboError
DecryptPassphraseKey(
Crypto::KeyHandle keyHandle,
const char *passphrase,
const Crypto::PassphraseSalt *pSalt,
const Crypto::PassphraseKeyInfo *pKeyInfo)
{
pgpAssertStrValid(passphrase);
pgpAssertAddrValid(pSalt, Crypto::PassphraseSalt);
pgpAssertAddrValid(pKeyInfo, Crypto::PassphraseKeyInfo);
CComboError error;
EXTRACT_CIPHER(keyHandle)
#if PGP_EXCEPTIONS
try
#endif // PGP_EXCEPTIONS
{
// Create new cipher out of passphrase.
CCipherWrapper pPassCipher(pCipher->Algorithm());
#if !PGP_EXCEPTIONS
error = pPassCipher.Status();
if (error.IsntError())
#endif // !PGP_EXCEPTIONS
{
PGPUInt16 hashReps = pKeyInfo->hashReps;
#if PGP_EXCEPTIONS
HashSaltSchedulePassphrase(passphrase, pSalt, pPassCipher,
hashReps, FALSE);
#else // !PGP_EXCEPTIONS
error = HashSaltSchedulePassphrase(passphrase, pSalt,
pPassCipher, hashReps, FALSE);
#endif // PGP_EXCEPTIONS
}
#if !PGP_EXCEPTIONS
if (error.IsntError())
#endif // !PGP_EXCEPTIONS
{
// Verify that the passphrase is valid by examining check bytes.
Crypto::CheckBytes checkBytes;
pgpClearMemory(checkBytes.bytes, sizeof(checkBytes.bytes));
pPassCipher->Encrypt(pPassCipher->Key().bytes, checkBytes.bytes);
if (!pgpMemoryEqual(checkBytes.bytes,
pKeyInfo->checkBytes.bytes, pCipher->NumEncryptBytes()))
{
#if PGP_EXCEPTIONS
THROW_PGPERROR(kPGPClientError_BadDiskPassphrase);
#else // !PGP_EXCEPTIONS
error.pgpErr = kPGPClientError_BadDiskPassphrase;
#endif // PGP_EXCEPTIONS
}
}
#if !PGP_EXCEPTIONS
if (error.IsntError())
#endif // !PGP_EXCEPTIONS
{
// Decrypt the encrypted session key.
CSecureObject<Crypto::SymmetricKey> pSessionKey;
#if !PGP_EXCEPTIONS
error = pSessionKey.Status();
if (error.IsntError())
#endif // !PGP_EXCEPTIONS
{
pPassCipher->Decrypt(pKeyInfo->encryptedKey.bytes,
pSessionKey->bytes, pCipher->NumKeyBytes() /
pCipher->NumDecryptBytes());
// Assign the final session key and salt to the keyholder.
pCipher->AttachKey(*pSessionKey, *pSalt);
}
}
}
#if PGP_EXCEPTIONS
catch (CComboError& caughtErr)
{
error = caughtErr;
}
#endif // PGP_EXCEPTIONS
return error;
}
CComboError
GenerateNewSymmetricKey(
Crypto::KeyHandle keyHandle,
PGPUInt8 *randomData1,
PGPUInt8 *randomData2,
PGPUInt32 bytesRandomData,
const Crypto::PassphraseSalt *pSalt)
{
CComboError error;
EXTRACT_CIPHER(keyHandle)
pgpAssertAddrValid(randomData1, PGPUInt8);
pgpAssertAddrValid(randomData2, PGPUInt8);
pgpAssertAddrValid(pSalt, Crypto::PassphraseSalt);
#if PGP_EXCEPTIONS
try
#endif // PGP_EXCEPTIONS
{
// Make sure we have enough random data.
if (bytesRandomData < pCipher->NumKeyBytes())
{
#if PGP_EXCEPTIONS
THROW_PGPERROR(kPGPError_BufferTooSmall);
#else // !PGP_EXCEPTIONS
error.pgpErr = kPGPError_BufferTooSmall;
return error;
#endif // PGP_EXCEPTIONS
}
#if !PGP_EXCEPTIONS
if (error.IsntError())
#endif // !PGP_EXCEPTIONS
{
// Get buffer for keys.
CSecureObject<Crypto::SymmetricKey> pSymKey;
#if !PGP_EXCEPTIONS
error = pSymKey.Status();
if (error.IsntError())
#endif // !PGP_EXCEPTIONS
{
// Create new cipher out of randomData2 to munge randomData1
CCipherWrapper pMungeCipher(pCipher->Algorithm());
#if !PGP_EXCEPTIONS
error = pMungeCipher.Status();
if (error.IsntError())
#endif // !PGP_EXCEPTIONS
{
// Copy data for munge key.
pgpCopyMemory(randomData2, pSymKey->bytes,
pMungeCipher->NumKeyBytes());
pMungeCipher->AttachKey(*pSymKey, *pSalt);
// Generate new session key using randomData1.
pgpCopyMemory(randomData1, pSymKey->bytes,
pCipher->NumKeyBytes());
// Munge the new session key.
for (PGPUInt32 i = 0; i < 2; i++)
{
pMungeCipher->Encrypt(pSymKey->bytes,
pSymKey->bytes, pCipher->NumKeyBytes() /
pCipher->NumEncryptBytes());
}
// Assign the final session key and salt.
pCipher->AttachKey(*pSymKey, *pSalt);
}
}
}
}
#if PGP_EXCEPTIONS
catch (CComboError& caughtErr)
{
error = caughtErr;
}
#endif // PGP_EXCEPTIONS
return error;
}
CComboError
Export(
Crypto::KeyHandle keyHandle,
void *buffer,
PGPUInt32 sizeBuffer)
{
CComboError error;
EXTRACT_CIPHER(keyHandle);
#if PGP_EXCEPTIONS
try
{
pCipher->ExportCipher(buffer, sizeBuffer);
}
catch (CComboError& caughtErr)
{
error = caughtErr;
}
#else // !PGP_EXCEPTIONS
error = pCipher->ExportCipher(buffer, sizeBuffer);
#endif // PGP_EXCEPTIONS
return error;
}
CComboError
Import(
Crypto::KeyHandle keyHandle,
const void *buffer,
PGPUInt32 sizeBuffer)
{
CComboError error;
EXTRACT_CIPHER(keyHandle);
#if PGP_EXCEPTIONS
try
{
pCipher->ImportCipher(buffer, sizeBuffer);
}
catch (CComboError& caughtErr)
{
error = caughtErr;
}
#else // !PGP_EXCEPTIONS
error = pCipher->ImportCipher(buffer, sizeBuffer);
#endif // PGP_EXCEPTIONS
return error;
}
void
EncryptBlock(
const CCipher *pCipher,
PGPUInt64 blockNumber,
const PGPUInt32 *inBlock,
PGPUInt32 *outBlock)
{
pgpAssertAddrValid(pCipher, CCipher);
pgpAssert(pCipher->IsKeyAttached());
pgpAssertAddrValid(inBlock, PGPUInt32);
pgpAssertAddrValid(outBlock, PGPUInt32);
pgpAssert(pCipher->NumIvsNeeded()%2 == 0);
PGPInt32 i, j;
PGPInt32 halfIvs = pCipher->NumIvsNeeded() / 2;
PGPUInt32 ivs[8], sums[4];
pgpAssert(halfIvs <= 4); // if not so, bump up size of above arrays
for (i = 0; i < halfIvs; i++)
{
sums[i] = pCipher->Salt().dwords[i] +
UMath::GetHighDWord(blockNumber) +
UMath::GetLowDWord(blockNumber);
}
for (i = 0; i < kBlockSizeIn32 - halfIvs; i++)
{
// simple Fletcher checksum of block
sums[halfIvs - 1] += inBlock[i];
for (j = halfIvs - 2; j >= 0; j--)
{
sums[j] += sums[j+1];
}
}
for (i = 0; i < halfIvs; i++)
{
ivs[i] = sums[i] ^ inBlock[kBlockSizeIn32 - halfIvs + i];
}
for (i = 0; i < halfIvs; i++)
{
ivs[i + halfIvs] = ~ivs[i];
}
pCipher->EncryptCFBdbl(ivs, inBlock, outBlock,
Crypto::kCipherBlockSize/(pCipher->NumEncryptBytes()*2));
for (i = 0; i < halfIvs; i++)
{
outBlock[kBlockSizeIn32 - halfIvs + i] ^= sums[i];
}
}
void
DecryptBlock(
const CCipher *pCipher,
PGPUInt64 blockNumber,
const PGPUInt32 *inBlock,
PGPUInt32 *outBlock)
{
pgpAssertAddrValid(pCipher, CCipher);
pgpAssert(pCipher->IsKeyAttached());
pgpAssertAddrValid(inBlock, PGPUInt32);
pgpAssertAddrValid(outBlock, PGPUInt32);
pgpAssert(pCipher->NumIvsNeeded()%2 == 0);
PGPInt32 i, j;
PGPInt32 halfIvs = pCipher->NumIvsNeeded() / 2;
PGPUInt32 ivs[8];
pgpAssert(halfIvs <= 4); // if not so, bump up size of above arrays
PGPUInt32 kSplitPointIn32;
size_t kBytesBeforeSplit;
size_t kBytesAfterSplit;
kSplitPointIn32 = kBlockSizeIn32 / 2;
kBytesBeforeSplit = kSplitPointIn32 * sizeof(PGPUInt32);
kBytesAfterSplit = (kBlockSizeIn32 - kSplitPointIn32) *
sizeof(PGPUInt32);
// This must be done in two halves to recover the IV.
for (i = 0; i < halfIvs*2; i++)
{
ivs[i] = inBlock[kSplitPointIn32 - halfIvs*2 + i];
}
pCipher->DecryptCFBdbl(ivs, inBlock + kSplitPointIn32,
outBlock + kSplitPointIn32,
kBytesAfterSplit/(pCipher->NumDecryptBytes()*2));
for (i = 0; i < halfIvs; i++)
{
ivs[i] = outBlock[kBlockSizeIn32 - halfIvs + i];
}
for (i = 0; i < halfIvs; i++)
{
ivs[i + halfIvs] = ~ivs[i];
}
pCipher->DecryptCFBdbl(ivs, inBlock, outBlock,
kBytesBeforeSplit/(pCipher->NumDecryptBytes()*2));
// Undo the checksum.
for (i = 0; i < halfIvs; i++)
{
ivs[i] = pCipher->Salt().dwords[i] +
UMath::GetHighDWord(blockNumber) +
UMath::GetLowDWord(blockNumber);
}
for (i = 0; i < kBlockSizeIn32 - halfIvs; i++)
{
// simple Fletcher checksum of block
ivs[halfIvs - 1] += outBlock[i];
for (j = halfIvs - 2; j >= 0; j--)
{
ivs[j] += ivs[j+1];
}
}
for (i = 0; i < halfIvs; i++)
{
outBlock[kBlockSizeIn32 - halfIvs + i] ^= ivs[i];
}
}
SMART_ERROR
HashSaltSchedulePassphrase(
const char *passphrase,
const Crypto::PassphraseSalt *pSalt,
CCipher *pCipher,
PGPUInt16& hashReps,
PGPBoolean generateNewHashReps)
{
pgpAssertStrValid(passphrase);
pgpAssertAddrValid(pSalt, Crypto::PassphraseSalt);
pgpAssertAddrValid(pCipher, CCipher);
SMART_ERROR_DECLARE
// Get secure objects.
CSecureObject<CSHA> pHasher;
CSecureObject<Crypto::SymmetricKey> pNewKey;
CSecureObject<CSHA::Digest> pHashResult;
#if !PGP_EXCEPTIONS
error = pHasher.Status();
if (error.IsntError())
error = pNewKey.Status();
if (error.IsntError())
error = pHashResult.Status();
if (error.IsntError())
#endif // !PGP_EXCEPTIONS
{
// Generate key material.
PGPUInt32 bytesNeeded = pCipher->NumKeyBytes();
PGPUInt32 offset = 0; // offset into output buffer
while (bytesNeeded > 0)
{
// # bytes key material we need this iteration.
PGPUInt32 bytesThisTime = pgpMin(
sizeof(pHashResult->bytes), bytesNeeded);
// Init hash for this new round.
pHasher->Init();
// Update with previous hash result if not on first hash.
if (offset > 0)
{
pHasher->Update(pHashResult->bytes,
sizeof(pHashResult->bytes));
}
// Update with the bare passphrase.
pHasher->Update(reinterpret_cast<const PGPUInt8 *>(passphrase),
strlen(passphrase));
// Save the hashed passphrase for use below.
pHasher->Final(pHashResult.Get());
// Re-initialize the hash and update with the salt.
pHasher->Init();
pHasher->Update(pSalt->bytes, pCipher->NumSaltBytes());
// Hash in the hashed passphrase a number of times.
PGPUInt8 j;
PGPUInt16 i;
if (generateNewHashReps && (offset == 0))
{
// We need to calculate how many times.
PGPUInt64 endTicks = UTime::GetSystemTicks() +
kMaxMsTimeForHash;
for (i = 0, j = 0; (UTime::GetSystemTicks() <
endTicks) && (i < kMaxHashReps); i++, j++)
{
pHasher->Update(pHashResult->bytes, bytesThisTime);
pHasher->Update(&j, 1);
}
hashReps = i;
}
else
{
// We already know how many times.
for (i = 0, j = 0; i < hashReps; i++, j++)
{
pHasher->Update(pHashResult->bytes, bytesThisTime);
pHasher->Update(&j, 1);
}
}
// Finalize the hash.
pHasher->Final(pHashResult.Get());
// Copy the newly generated key bytes to the output buffer.
pgpCopyMemory(pHashResult->bytes, pNewKey->bytes + offset,
bytesThisTime);
bytesNeeded -= bytesThisTime;
offset += bytesThisTime;
}
// Initialize the cipher with the final key.
pCipher->AttachKey(*pNewKey, *pSalt);
}
SMART_ERROR_RETURN
}
_UNNAMED_END
// UNativeCryptoModule functions
void
UNativeCryptoModule::GetVTable(Crypto::CipherVTable& vTable)
{
vTable.pfnGetAlgorithmIdString = GetAlgorithmIdString;
vTable.pfnGetEncryptSize = GetEncryptSize;
vTable.pfnGetDecryptSize = GetDecryptSize;
vTable.pfnGetKeySize = GetKeySize;
vTable.pfnGetNeededRandomDataSize = GetNeededRandomDataSize;
vTable.pfnGetSizeForExport = GetSizeForExport;
vTable.pfnValidate = Validate;
vTable.pfnInit = Init;
vTable.pfnCleanup = Cleanup;
vTable.pfnAttachSymmetricKey = AttachSymmetricKey;
vTable.pfnGetSymmetricKey = GetSymmetricKey;
vTable.pfnGetSalt = GetSalt;
vTable.pfnFlipKeyBytes = FlipKeyBytes;
vTable.pfnEncrypt = Encrypt;
vTable.pfnDecrypt = Decrypt;
vTable.pfnEncryptCFB = EncryptCFB;
vTable.pfnDecryptCFB = DecryptCFB;
vTable.pfnEncryptPassphraseKey = EncryptPassphraseKey;
vTable.pfnGenerateNewSymmetricKey = GenerateNewSymmetricKey;
vTable.pfnDecryptPassphraseKey = DecryptPassphraseKey;
vTable.pfnExport = Export;
vTable.pfnImport = Import;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -