mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-08 02:07:06 -06:00
21.02
This commit is contained in:
@@ -2,9 +2,11 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/CpuArch.h"
|
||||
#include "../../../C/Sha256.h"
|
||||
|
||||
#include "../../Common/ComTry.h"
|
||||
#include "../../Common/MyBuffer2.h"
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
#include "../../Windows/Synchronization.h"
|
||||
@@ -48,31 +50,65 @@ void CKeyInfo::CalcKey()
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t bufSize = 8 + SaltSize + Password.Size();
|
||||
CObjArray<Byte> buf(bufSize);
|
||||
const unsigned kUnrPow = 6;
|
||||
const UInt32 numUnroll = (UInt32)1 << (NumCyclesPower <= kUnrPow ? (unsigned)NumCyclesPower : kUnrPow);
|
||||
|
||||
const size_t bufSize = 8 + SaltSize + Password.Size();
|
||||
const size_t unrollSize = bufSize * numUnroll;
|
||||
|
||||
// MY_ALIGN (16)
|
||||
// CSha256 sha;
|
||||
CAlignedBuffer sha(sizeof(CSha256) + unrollSize + bufSize * 2);
|
||||
Byte *buf = sha + sizeof(CSha256);
|
||||
|
||||
memcpy(buf, Salt, SaltSize);
|
||||
memcpy(buf + SaltSize, Password, Password.Size());
|
||||
memset(buf + bufSize - 8, 0, 8);
|
||||
|
||||
CSha256 sha;
|
||||
Sha256_Init(&sha);
|
||||
|
||||
Byte *ctr = buf + SaltSize + Password.Size();
|
||||
|
||||
for (unsigned i = 0; i < 8; i++)
|
||||
ctr[i] = 0;
|
||||
Sha256_Init((CSha256 *)(void *)(Byte *)sha);
|
||||
|
||||
{
|
||||
{
|
||||
Byte *dest = buf;
|
||||
for (UInt32 i = 1; i < numUnroll; i++)
|
||||
{
|
||||
dest += bufSize;
|
||||
memcpy(dest, buf, bufSize);
|
||||
}
|
||||
}
|
||||
|
||||
const UInt32 numRounds = (UInt32)1 << NumCyclesPower;
|
||||
UInt32 r = 0;
|
||||
do
|
||||
{
|
||||
Byte *dest = buf + bufSize - 8;
|
||||
UInt32 i = r;
|
||||
r += numUnroll;
|
||||
do
|
||||
{
|
||||
SetUi32(dest, i); i++; dest += bufSize;
|
||||
// SetUi32(dest, i); i++; dest += bufSize;
|
||||
}
|
||||
while (i < r);
|
||||
Sha256_Update((CSha256 *)(void *)(Byte *)sha, buf, unrollSize);
|
||||
}
|
||||
while (r < numRounds);
|
||||
}
|
||||
/*
|
||||
UInt64 numRounds = (UInt64)1 << NumCyclesPower;
|
||||
|
||||
do
|
||||
{
|
||||
Sha256_Update(&sha, buf, bufSize);
|
||||
Sha256_Update((CSha256 *)(Byte *)sha, buf, bufSize);
|
||||
for (unsigned i = 0; i < 8; i++)
|
||||
if (++(ctr[i]) != 0)
|
||||
break;
|
||||
}
|
||||
while (--numRounds != 0);
|
||||
*/
|
||||
|
||||
Sha256_Final(&sha, Key);
|
||||
Sha256_Final((CSha256 *)(void *)(Byte *)sha, Key);
|
||||
memset(sha, 0, sha.Size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,6 +286,7 @@ STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
_key.Password.Wipe();
|
||||
_key.Password.CopyFrom(data, (size_t)size);
|
||||
return S_OK;
|
||||
|
||||
|
||||
@@ -37,6 +37,17 @@ public:
|
||||
for (unsigned i = 0; i < sizeof(Salt); i++)
|
||||
Salt[i] = 0;
|
||||
}
|
||||
|
||||
void Wipe()
|
||||
{
|
||||
Password.Wipe();
|
||||
NumCyclesPower = 0;
|
||||
SaltSize = 0;
|
||||
MY_memset_0_ARRAY(Salt);
|
||||
MY_memset_0_ARRAY(Key);
|
||||
}
|
||||
|
||||
~CKeyInfo() { Wipe(); }
|
||||
};
|
||||
|
||||
class CKeyInfoCache
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
namespace NCrypto {
|
||||
namespace N7z {
|
||||
|
||||
REGISTER_FILTER_E(7zAES,
|
||||
CDecoder(),
|
||||
CEncoder(),
|
||||
REGISTER_FILTER_E(_7zAES,
|
||||
CDecoder,
|
||||
CEncoder,
|
||||
0x6F10701, "7zAES")
|
||||
|
||||
}}
|
||||
|
||||
@@ -11,110 +11,82 @@ namespace NSha1 {
|
||||
|
||||
void CHmac::SetKey(const Byte *key, size_t keySize)
|
||||
{
|
||||
Byte keyTemp[kBlockSize];
|
||||
MY_ALIGN (16)
|
||||
UInt32 temp[SHA1_NUM_BLOCK_WORDS];
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < kBlockSize; i++)
|
||||
keyTemp[i] = 0;
|
||||
for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i++)
|
||||
temp[i] = 0;
|
||||
|
||||
if (keySize > kBlockSize)
|
||||
{
|
||||
_sha.Init();
|
||||
_sha.Update(key, keySize);
|
||||
_sha.Final(keyTemp);
|
||||
_sha.Final((Byte *)temp);
|
||||
}
|
||||
else
|
||||
for (i = 0; i < keySize; i++)
|
||||
keyTemp[i] = key[i];
|
||||
memcpy(temp, key, keySize);
|
||||
|
||||
for (i = 0; i < kBlockSize; i++)
|
||||
keyTemp[i] ^= 0x36;
|
||||
for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i++)
|
||||
temp[i] ^= 0x36363636;
|
||||
|
||||
_sha.Init();
|
||||
_sha.Update(keyTemp, kBlockSize);
|
||||
_sha.Update((const Byte *)temp, kBlockSize);
|
||||
|
||||
for (i = 0; i < kBlockSize; i++)
|
||||
keyTemp[i] ^= 0x36 ^ 0x5C;
|
||||
for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i++)
|
||||
temp[i] ^= 0x36363636 ^ 0x5C5C5C5C;
|
||||
|
||||
_sha2.Init();
|
||||
_sha2.Update(keyTemp, kBlockSize);
|
||||
}
|
||||
|
||||
void CHmac::Final(Byte *mac, size_t macSize)
|
||||
{
|
||||
Byte digest[kDigestSize];
|
||||
_sha.Final(digest);
|
||||
_sha2.Update(digest, kDigestSize);
|
||||
_sha2.Final(digest);
|
||||
for (size_t i = 0; i < macSize; i++)
|
||||
mac[i] = digest[i];
|
||||
_sha2.Update((const Byte *)temp, kBlockSize);
|
||||
}
|
||||
|
||||
|
||||
void CHmac32::SetKey(const Byte *key, size_t keySize)
|
||||
void CHmac::Final(Byte *mac)
|
||||
{
|
||||
UInt32 keyTemp[kNumBlockWords];
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < kNumBlockWords; i++)
|
||||
keyTemp[i] = 0;
|
||||
|
||||
if (keySize > kBlockSize)
|
||||
{
|
||||
CContext sha;
|
||||
sha.Init();
|
||||
sha.Update(key, keySize);
|
||||
Byte digest[kDigestSize];
|
||||
sha.Final(digest);
|
||||
|
||||
for (i = 0 ; i < kNumDigestWords; i++)
|
||||
keyTemp[i] = GetBe32(digest + i * 4 + 0);
|
||||
}
|
||||
else
|
||||
for (i = 0; i < keySize; i++)
|
||||
keyTemp[i / 4] |= (key[i] << (24 - 8 * (i & 3)));
|
||||
|
||||
for (i = 0; i < kNumBlockWords; i++)
|
||||
keyTemp[i] ^= 0x36363636;
|
||||
|
||||
_sha.Init();
|
||||
_sha.Update(keyTemp, kNumBlockWords);
|
||||
|
||||
for (i = 0; i < kNumBlockWords; i++)
|
||||
keyTemp[i] ^= 0x36363636 ^ 0x5C5C5C5C;
|
||||
|
||||
_sha2.Init();
|
||||
_sha2.Update(keyTemp, kNumBlockWords);
|
||||
_sha.Final(mac);
|
||||
_sha2.Update(mac, kDigestSize);
|
||||
_sha2.Final(mac);
|
||||
}
|
||||
|
||||
void CHmac32::Final(UInt32 *mac, size_t macSize)
|
||||
{
|
||||
UInt32 digest[kNumDigestWords];
|
||||
_sha.Final(digest);
|
||||
_sha2.Update(digest, kNumDigestWords);
|
||||
_sha2.Final(digest);
|
||||
for (size_t i = 0; i < macSize; i++)
|
||||
mac[i] = digest[i];
|
||||
}
|
||||
|
||||
void CHmac32::GetLoopXorDigest(UInt32 *mac, UInt32 numIteration)
|
||||
void CHmac::GetLoopXorDigest1(void *mac, UInt32 numIteration)
|
||||
{
|
||||
UInt32 block[kNumBlockWords];
|
||||
UInt32 block2[kNumBlockWords];
|
||||
MY_ALIGN (16) UInt32 block [SHA1_NUM_BLOCK_WORDS];
|
||||
MY_ALIGN (16) UInt32 block2[SHA1_NUM_BLOCK_WORDS];
|
||||
MY_ALIGN (16) UInt32 mac2 [SHA1_NUM_BLOCK_WORDS];
|
||||
|
||||
_sha.PrepareBlock(block, kNumDigestWords);
|
||||
_sha2.PrepareBlock(block2, kNumDigestWords);
|
||||
_sha. PrepareBlock((Byte *)block, SHA1_DIGEST_SIZE);
|
||||
_sha2.PrepareBlock((Byte *)block2, SHA1_DIGEST_SIZE);
|
||||
|
||||
block[0] = ((const UInt32 *)mac)[0];
|
||||
block[1] = ((const UInt32 *)mac)[1];
|
||||
block[2] = ((const UInt32 *)mac)[2];
|
||||
block[3] = ((const UInt32 *)mac)[3];
|
||||
block[4] = ((const UInt32 *)mac)[4];
|
||||
|
||||
mac2[0] = block[0];
|
||||
mac2[1] = block[1];
|
||||
mac2[2] = block[2];
|
||||
mac2[3] = block[3];
|
||||
mac2[4] = block[4];
|
||||
|
||||
for (unsigned s = 0; s < kNumDigestWords; s++)
|
||||
block[s] = mac[s];
|
||||
|
||||
for (UInt32 i = 0; i < numIteration; i++)
|
||||
{
|
||||
_sha.GetBlockDigest(block, block2);
|
||||
_sha2.GetBlockDigest(block2, block);
|
||||
for (unsigned s = 0; s < kNumDigestWords; s++)
|
||||
mac[s] ^= block[s];
|
||||
_sha. GetBlockDigest((const Byte *)block, (Byte *)block2);
|
||||
_sha2.GetBlockDigest((const Byte *)block2, (Byte *)block);
|
||||
|
||||
mac2[0] ^= block[0];
|
||||
mac2[1] ^= block[1];
|
||||
mac2[2] ^= block[2];
|
||||
mac2[3] ^= block[3];
|
||||
mac2[4] ^= block[4];
|
||||
}
|
||||
|
||||
((UInt32 *)mac)[0] = mac2[0];
|
||||
((UInt32 *)mac)[1] = mac2[1];
|
||||
((UInt32 *)mac)[2] = mac2[2];
|
||||
((UInt32 *)mac)[3] = mac2[3];
|
||||
((UInt32 *)mac)[4] = mac2[4];
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
namespace NCrypto {
|
||||
namespace NSha1 {
|
||||
|
||||
// Use: SetKey(key, keySize); for () Update(data, size); Final(mac, macSize);
|
||||
// Use: SetKey(key, keySize); for () Update(data, size); FinalFull(mac);
|
||||
|
||||
class CHmac
|
||||
{
|
||||
@@ -18,20 +18,12 @@ class CHmac
|
||||
public:
|
||||
void SetKey(const Byte *key, size_t keySize);
|
||||
void Update(const Byte *data, size_t dataSize) { _sha.Update(data, dataSize); }
|
||||
void Final(Byte *mac, size_t macSize = kDigestSize);
|
||||
};
|
||||
|
||||
class CHmac32
|
||||
{
|
||||
CContext32 _sha;
|
||||
CContext32 _sha2;
|
||||
public:
|
||||
void SetKey(const Byte *key, size_t keySize);
|
||||
void Update(const UInt32 *data, size_t dataSize) { _sha.Update(data, dataSize); }
|
||||
void Final(UInt32 *mac, size_t macSize = kNumDigestWords);
|
||||
|
||||
// It'sa for hmac function. in,out: mac[kNumDigestWords].
|
||||
void GetLoopXorDigest(UInt32 *mac, UInt32 numIteration);
|
||||
// Final() : mac is recommended to be aligned for 4 bytes
|
||||
// GetLoopXorDigest1() : mac is required to be aligned for 4 bytes
|
||||
// The caller can use: UInt32 mac[NSha1::kNumDigestWords] and typecast to (Byte *) and (void *);
|
||||
void Final(Byte *mac);
|
||||
void GetLoopXorDigest1(void *mac, UInt32 numIteration);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -9,39 +9,38 @@
|
||||
namespace NCrypto {
|
||||
namespace NSha256 {
|
||||
|
||||
static const unsigned kBlockSize = 64;
|
||||
|
||||
void CHmac::SetKey(const Byte *key, size_t keySize)
|
||||
{
|
||||
Byte temp[kBlockSize];
|
||||
MY_ALIGN (16)
|
||||
UInt32 temp[SHA256_NUM_BLOCK_WORDS];
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < kBlockSize; i++)
|
||||
for (i = 0; i < SHA256_NUM_BLOCK_WORDS; i++)
|
||||
temp[i] = 0;
|
||||
|
||||
if (keySize > kBlockSize)
|
||||
{
|
||||
Sha256_Init(&_sha);
|
||||
Sha256_Update(&_sha, key, keySize);
|
||||
Sha256_Final(&_sha, temp);
|
||||
Sha256_Final(&_sha, (Byte *)temp);
|
||||
}
|
||||
else
|
||||
for (i = 0; i < keySize; i++)
|
||||
temp[i] = key[i];
|
||||
memcpy(temp, key, keySize);
|
||||
|
||||
for (i = 0; i < kBlockSize; i++)
|
||||
temp[i] ^= 0x36;
|
||||
for (i = 0; i < SHA256_NUM_BLOCK_WORDS; i++)
|
||||
temp[i] ^= 0x36363636;
|
||||
|
||||
Sha256_Init(&_sha);
|
||||
Sha256_Update(&_sha, temp, kBlockSize);
|
||||
Sha256_Update(&_sha, (const Byte *)temp, kBlockSize);
|
||||
|
||||
for (i = 0; i < kBlockSize; i++)
|
||||
temp[i] ^= 0x36 ^ 0x5C;
|
||||
for (i = 0; i < SHA256_NUM_BLOCK_WORDS; i++)
|
||||
temp[i] ^= 0x36363636 ^ 0x5C5C5C5C;
|
||||
|
||||
Sha256_Init(&_sha2);
|
||||
Sha256_Update(&_sha2, temp, kBlockSize);
|
||||
Sha256_Update(&_sha2, (const Byte *)temp, kBlockSize);
|
||||
}
|
||||
|
||||
|
||||
void CHmac::Final(Byte *mac)
|
||||
{
|
||||
Sha256_Final(&_sha, mac);
|
||||
@@ -49,14 +48,4 @@ void CHmac::Final(Byte *mac)
|
||||
Sha256_Final(&_sha2, mac);
|
||||
}
|
||||
|
||||
/*
|
||||
void CHmac::Final(Byte *mac, size_t macSize)
|
||||
{
|
||||
Byte digest[SHA256_DIGEST_SIZE];
|
||||
Final(digest);
|
||||
for (size_t i = 0; i < macSize; i++)
|
||||
mac[i] = digest[i];
|
||||
}
|
||||
*/
|
||||
|
||||
}}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
namespace NCrypto {
|
||||
namespace NSha256 {
|
||||
|
||||
const unsigned kBlockSize = SHA256_BLOCK_SIZE;
|
||||
const unsigned kDigestSize = SHA256_DIGEST_SIZE;
|
||||
|
||||
class CHmac
|
||||
@@ -19,7 +20,6 @@ public:
|
||||
void SetKey(const Byte *key, size_t keySize);
|
||||
void Update(const Byte *data, size_t dataSize) { Sha256_Update(&_sha, data, dataSize); }
|
||||
void Final(Byte *mac);
|
||||
// void Final(Byte *mac, size_t macSize);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -10,91 +10,179 @@ namespace NCrypto {
|
||||
|
||||
static struct CAesTabInit { CAesTabInit() { AesGenTables();} } g_AesTabInit;
|
||||
|
||||
CAesCbcCoder::CAesCbcCoder(bool encodeMode, unsigned keySize):
|
||||
CAesCoder::CAesCoder(bool encodeMode, unsigned keySize, bool ctrMode):
|
||||
_keySize(keySize),
|
||||
_keyIsSet(false),
|
||||
_encodeMode(encodeMode)
|
||||
_encodeMode(encodeMode),
|
||||
_ctrMode(ctrMode),
|
||||
_aes(AES_NUM_IVMRK_WORDS * 4 + AES_BLOCK_SIZE * 2)
|
||||
{
|
||||
_offset = ((0 - (unsigned)(ptrdiff_t)_aes) & 0xF) / sizeof(UInt32);
|
||||
// _offset = ((0 - (unsigned)(ptrdiff_t)_aes) & 0xF) / sizeof(UInt32);
|
||||
memset(_iv, 0, AES_BLOCK_SIZE);
|
||||
/*
|
||||
// we can use the following code to test 32-bit overflow case for AES-CTR
|
||||
for (unsigned i = 0; i < 16; i++) _iv[i] = (Byte)(i + 1);
|
||||
_iv[0] = 0xFE; _iv[1] = _iv[2] = _iv[3] = 0xFF;
|
||||
*/
|
||||
SetFunctions(0);
|
||||
}
|
||||
|
||||
STDMETHODIMP CAesCbcCoder::Init()
|
||||
STDMETHODIMP CAesCoder::Init()
|
||||
{
|
||||
AesCbc_Init(_aes + _offset, _iv);
|
||||
return _keyIsSet ? S_OK : E_FAIL;
|
||||
AesCbc_Init(Aes(), _iv);
|
||||
return _keyIsSet ? S_OK : E_NOTIMPL; // E_FAIL
|
||||
}
|
||||
|
||||
STDMETHODIMP_(UInt32) CAesCbcCoder::Filter(Byte *data, UInt32 size)
|
||||
STDMETHODIMP_(UInt32) CAesCoder::Filter(Byte *data, UInt32 size)
|
||||
{
|
||||
if (!_keyIsSet)
|
||||
return 0;
|
||||
if (size == 0)
|
||||
return 0;
|
||||
if (size < AES_BLOCK_SIZE)
|
||||
{
|
||||
#ifndef _SFX
|
||||
if (_ctrMode)
|
||||
{
|
||||
// use that code only for last block !!!
|
||||
Byte *ctr = (Byte *)(Aes() + AES_NUM_IVMRK_WORDS);
|
||||
memset(ctr, 0, AES_BLOCK_SIZE);
|
||||
memcpy(ctr, data, size);
|
||||
_codeFunc(Aes(), ctr, 1);
|
||||
memcpy(data, ctr, size);
|
||||
return size;
|
||||
}
|
||||
#endif
|
||||
return AES_BLOCK_SIZE;
|
||||
}
|
||||
size >>= 4;
|
||||
_codeFunc(_aes + _offset, data, size);
|
||||
_codeFunc(Aes(), data, size);
|
||||
return size << 4;
|
||||
}
|
||||
|
||||
STDMETHODIMP CAesCbcCoder::SetKey(const Byte *data, UInt32 size)
|
||||
STDMETHODIMP CAesCoder::SetKey(const Byte *data, UInt32 size)
|
||||
{
|
||||
if ((size & 0x7) != 0 || size < 16 || size > 32)
|
||||
return E_INVALIDARG;
|
||||
if (_keySize != 0 && size != _keySize)
|
||||
return E_INVALIDARG;
|
||||
AES_SET_KEY_FUNC setKeyFunc = _encodeMode ? Aes_SetKey_Enc : Aes_SetKey_Dec;
|
||||
setKeyFunc(_aes + _offset + 4, data, size);
|
||||
AES_SET_KEY_FUNC setKeyFunc = (_ctrMode | _encodeMode) ? Aes_SetKey_Enc : Aes_SetKey_Dec;
|
||||
setKeyFunc(Aes() + 4, data, size);
|
||||
_keyIsSet = true;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CAesCbcCoder::SetInitVector(const Byte *data, UInt32 size)
|
||||
STDMETHODIMP CAesCoder::SetInitVector(const Byte *data, UInt32 size)
|
||||
{
|
||||
if (size != AES_BLOCK_SIZE)
|
||||
return E_INVALIDARG;
|
||||
memcpy(_iv, data, size);
|
||||
CAesCbcCoder::Init(); // don't call virtual function here !!!
|
||||
CAesCoder::Init(); // don't call virtual function here !!!
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
#ifndef _SFX
|
||||
|
||||
void MY_FAST_CALL AesCbc_Encode(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||
void MY_FAST_CALL AesCbc_Decode(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||
void MY_FAST_CALL AesCtr_Code(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
#define USE_HW_AES
|
||||
#elif defined(MY_CPU_ARM_OR_ARM64) && defined(MY_CPU_LE)
|
||||
#if defined(__clang__)
|
||||
#if (__clang_major__ >= 8) // fix that check
|
||||
#define USE_HW_AES
|
||||
#endif
|
||||
#elif defined(__GNUC__)
|
||||
#if (__GNUC__ >= 6) // fix that check
|
||||
#define USE_HW_AES
|
||||
#endif
|
||||
#elif defined(_MSC_VER)
|
||||
#if _MSC_VER >= 1910
|
||||
#define USE_HW_AES
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void MY_FAST_CALL AesCbc_Encode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||
void MY_FAST_CALL AesCbc_Decode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||
void MY_FAST_CALL AesCtr_Code_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);
|
||||
#endif
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
bool CAesCbcCoder::SetFunctions(UInt32 algo)
|
||||
bool CAesCoder::SetFunctions(UInt32
|
||||
#ifndef _SFX
|
||||
algo
|
||||
#endif
|
||||
)
|
||||
{
|
||||
_codeFunc = _encodeMode ?
|
||||
g_AesCbc_Encode :
|
||||
g_AesCbc_Decode;
|
||||
_codeFunc = g_AesCbc_Decode;
|
||||
|
||||
#ifdef _SFX
|
||||
|
||||
return true;
|
||||
|
||||
#else
|
||||
|
||||
if (_ctrMode)
|
||||
_codeFunc = g_AesCtr_Code;
|
||||
else if (_encodeMode)
|
||||
_codeFunc = g_AesCbc_Encode;
|
||||
|
||||
if (algo < 1)
|
||||
return true;
|
||||
|
||||
if (algo == 1)
|
||||
{
|
||||
_codeFunc = _encodeMode ?
|
||||
AesCbc_Encode:
|
||||
AesCbc_Decode;
|
||||
}
|
||||
if (algo == 2)
|
||||
{
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
if (g_AesCbc_Encode != AesCbc_Encode_Intel)
|
||||
_codeFunc = AesCbc_Decode;
|
||||
|
||||
#ifndef _SFX
|
||||
if (_ctrMode)
|
||||
_codeFunc = AesCtr_Code;
|
||||
else if (_encodeMode)
|
||||
_codeFunc = AesCbc_Encode;
|
||||
#endif
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
|
||||
#ifdef USE_HW_AES
|
||||
// if (CPU_IsSupported_AES())
|
||||
{
|
||||
if (algo == 2)
|
||||
if (g_Aes_SupportedFunctions_Flags & k_Aes_SupportedFunctions_HW)
|
||||
{
|
||||
_codeFunc = AesCbc_Decode_HW;
|
||||
#ifndef _SFX
|
||||
if (_ctrMode)
|
||||
_codeFunc = AesCtr_Code_HW;
|
||||
else if (_encodeMode)
|
||||
_codeFunc = AesCbc_Encode_HW;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(MY_CPU_X86_OR_AMD64)
|
||||
if (algo == 3)
|
||||
if (g_Aes_SupportedFunctions_Flags & k_Aes_SupportedFunctions_HW_256)
|
||||
{
|
||||
_codeFunc = AesCbc_Decode_HW_256;
|
||||
#ifndef _SFX
|
||||
if (_ctrMode)
|
||||
_codeFunc = AesCtr_Code_HW_256;
|
||||
else if (_encodeMode)
|
||||
_codeFunc = AesCbc_Encode_HW;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
STDMETHODIMP CAesCbcCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)
|
||||
|
||||
#ifndef _SFX
|
||||
|
||||
STDMETHODIMP CAesCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)
|
||||
{
|
||||
UInt32 algo = 0;
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
const PROPVARIANT &prop = coderProps[i];
|
||||
@@ -102,11 +190,16 @@ STDMETHODIMP CAesCbcCoder::SetCoderProperties(const PROPID *propIDs, const PROPV
|
||||
{
|
||||
if (prop.vt != VT_UI4)
|
||||
return E_INVALIDARG;
|
||||
if (!SetFunctions(prop.ulVal))
|
||||
if (prop.ulVal > 3)
|
||||
return E_NOTIMPL;
|
||||
algo = prop.ulVal;
|
||||
}
|
||||
}
|
||||
if (!SetFunctions(algo))
|
||||
return E_NOTIMPL;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -5,51 +5,73 @@
|
||||
|
||||
#include "../../../C/Aes.h"
|
||||
|
||||
#include "../../Common/MyBuffer2.h"
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#include "../ICoder.h"
|
||||
|
||||
namespace NCrypto {
|
||||
|
||||
class CAesCbcCoder:
|
||||
class CAesCoder:
|
||||
public ICompressFilter,
|
||||
public ICryptoProperties,
|
||||
#ifndef _SFX
|
||||
public ICompressSetCoderProperties,
|
||||
#endif
|
||||
public CMyUnknownImp
|
||||
{
|
||||
AES_CODE_FUNC _codeFunc;
|
||||
unsigned _offset;
|
||||
// unsigned _offset;
|
||||
unsigned _keySize;
|
||||
bool _keyIsSet;
|
||||
bool _encodeMode;
|
||||
UInt32 _aes[AES_NUM_IVMRK_WORDS + 3];
|
||||
bool _ctrMode;
|
||||
|
||||
// UInt32 _aes[AES_NUM_IVMRK_WORDS + 3];
|
||||
CAlignedBuffer _aes;
|
||||
|
||||
Byte _iv[AES_BLOCK_SIZE];
|
||||
|
||||
// UInt32 *Aes() { return _aes + _offset; }
|
||||
UInt32 *Aes() { return (UInt32 *)(void *)(Byte *)_aes; }
|
||||
|
||||
bool SetFunctions(UInt32 algo);
|
||||
|
||||
public:
|
||||
CAesCbcCoder(bool encodeMode, unsigned keySize);
|
||||
CAesCoder(bool encodeMode, unsigned keySize, bool ctrMode);
|
||||
|
||||
virtual ~CAesCbcCoder() {}; // we need virtual destructor for derived classes
|
||||
virtual ~CAesCoder() {}; // we need virtual destructor for derived classes
|
||||
|
||||
MY_UNKNOWN_IMP3(ICompressFilter, ICryptoProperties, ICompressSetCoderProperties)
|
||||
MY_QUERYINTERFACE_BEGIN2(ICompressFilter)
|
||||
MY_QUERYINTERFACE_ENTRY(ICryptoProperties)
|
||||
#ifndef _SFX
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetCoderProperties)
|
||||
#endif
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
|
||||
INTERFACE_ICompressFilter(;)
|
||||
|
||||
void SetKeySize(unsigned size) { _keySize = size; }
|
||||
|
||||
STDMETHOD(SetKey)(const Byte *data, UInt32 size);
|
||||
STDMETHOD(SetInitVector)(const Byte *data, UInt32 size);
|
||||
|
||||
#ifndef _SFX
|
||||
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
|
||||
#endif
|
||||
};
|
||||
|
||||
struct CAesCbcEncoder: public CAesCbcCoder
|
||||
#ifndef _SFX
|
||||
struct CAesCbcEncoder: public CAesCoder
|
||||
{
|
||||
CAesCbcEncoder(unsigned keySize = 0): CAesCbcCoder(true, keySize) {}
|
||||
CAesCbcEncoder(unsigned keySize = 0): CAesCoder(true, keySize, false) {}
|
||||
};
|
||||
#endif
|
||||
|
||||
struct CAesCbcDecoder: public CAesCbcCoder
|
||||
struct CAesCbcDecoder: public CAesCoder
|
||||
{
|
||||
CAesCbcDecoder(unsigned keySize = 0): CAesCbcCoder(false, keySize) {}
|
||||
CAesCbcDecoder(unsigned keySize = 0): CAesCoder(false, keySize, false) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -8,9 +8,23 @@
|
||||
|
||||
namespace NCrypto {
|
||||
|
||||
REGISTER_FILTER_E(AES256CBC,
|
||||
CAesCbcDecoder(32),
|
||||
CAesCbcEncoder(32),
|
||||
0x6F00181, "AES256CBC")
|
||||
#ifndef _SFX
|
||||
|
||||
#define REGISTER_AES_2(name, nameString, keySize, isCtr) \
|
||||
REGISTER_FILTER_E(name, \
|
||||
CAesCoder(false, keySize, isCtr), \
|
||||
CAesCoder(true , keySize, isCtr), \
|
||||
0x6F00100 | ((keySize - 16) * 8) | (isCtr ? 4 : 1), \
|
||||
nameString) \
|
||||
|
||||
#define REGISTER_AES(name, nameString, isCtr) \
|
||||
/* REGISTER_AES_2(AES128 ## name, "AES128" nameString, 16, isCtr) */ \
|
||||
/* REGISTER_AES_2(AES192 ## name, "AES192" nameString, 24, isCtr) */ \
|
||||
REGISTER_AES_2(AES256 ## name, "AES256" nameString, 32, isCtr) \
|
||||
|
||||
REGISTER_AES(CBC, "CBC", false)
|
||||
// REGISTER_AES(CTR, "CTR", true)
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "../../../C/CpuArch.h"
|
||||
|
||||
#include "HmacSha1.h"
|
||||
#include "Pbkdf2HmacSha1.h"
|
||||
|
||||
namespace NCrypto {
|
||||
namespace NSha1 {
|
||||
@@ -14,81 +15,29 @@ void Pbkdf2Hmac(const Byte *pwd, size_t pwdSize,
|
||||
UInt32 numIterations,
|
||||
Byte *key, size_t keySize)
|
||||
{
|
||||
MY_ALIGN (16)
|
||||
CHmac baseCtx;
|
||||
baseCtx.SetKey(pwd, pwdSize);
|
||||
|
||||
for (UInt32 i = 1; keySize != 0; i++)
|
||||
{
|
||||
CHmac ctx = baseCtx;
|
||||
MY_ALIGN (16)
|
||||
CHmac ctx;
|
||||
ctx = baseCtx;
|
||||
ctx.Update(salt, saltSize);
|
||||
|
||||
Byte u[kDigestSize];
|
||||
MY_ALIGN (16)
|
||||
UInt32 u[kNumDigestWords];
|
||||
SetBe32(u, i);
|
||||
|
||||
ctx.Update(u, 4);
|
||||
ctx.Final(u, kDigestSize);
|
||||
ctx.Update((const Byte *)u, 4);
|
||||
ctx.Final((Byte *)u);
|
||||
|
||||
const unsigned curSize = (keySize < kDigestSize) ? (unsigned)keySize : kDigestSize;
|
||||
unsigned s;
|
||||
for (s = 0; s < curSize; s++)
|
||||
key[s] = u[s];
|
||||
|
||||
for (UInt32 j = numIterations; j > 1; j--)
|
||||
{
|
||||
ctx = baseCtx;
|
||||
ctx.Update(u, kDigestSize);
|
||||
ctx.Final(u, kDigestSize);
|
||||
for (s = 0; s < curSize; s++)
|
||||
key[s] ^= u[s];
|
||||
}
|
||||
|
||||
key += curSize;
|
||||
keySize -= curSize;
|
||||
}
|
||||
}
|
||||
|
||||
void Pbkdf2Hmac32(const Byte *pwd, size_t pwdSize,
|
||||
const UInt32 *salt, size_t saltSize,
|
||||
UInt32 numIterations,
|
||||
UInt32 *key, size_t keySize)
|
||||
{
|
||||
CHmac32 baseCtx;
|
||||
baseCtx.SetKey(pwd, pwdSize);
|
||||
|
||||
for (UInt32 i = 1; keySize != 0; i++)
|
||||
{
|
||||
CHmac32 ctx = baseCtx;
|
||||
ctx.Update(salt, saltSize);
|
||||
|
||||
UInt32 u[kNumDigestWords];
|
||||
u[0] = i;
|
||||
|
||||
ctx.Update(u, 1);
|
||||
ctx.Final(u, kNumDigestWords);
|
||||
|
||||
// Speed-optimized code start
|
||||
ctx = baseCtx;
|
||||
ctx.GetLoopXorDigest(u, numIterations - 1);
|
||||
// Speed-optimized code end
|
||||
|
||||
const unsigned curSize = (keySize < kNumDigestWords) ? (unsigned)keySize : kNumDigestWords;
|
||||
unsigned s;
|
||||
for (s = 0; s < curSize; s++)
|
||||
key[s] = u[s];
|
||||
|
||||
/*
|
||||
// Default code start
|
||||
for (UInt32 j = numIterations; j > 1; j--)
|
||||
{
|
||||
ctx = baseCtx;
|
||||
ctx.Update(u, kNumDigestWords);
|
||||
ctx.Final(u, kNumDigestWords);
|
||||
for (s = 0; s < curSize; s++)
|
||||
key[s] ^= u[s];
|
||||
}
|
||||
// Default code end
|
||||
*/
|
||||
ctx.GetLoopXorDigest1((void *)u, numIterations - 1);
|
||||
|
||||
const unsigned curSize = (keySize < kDigestSize) ? (unsigned)keySize : kDigestSize;;
|
||||
memcpy(key, (const Byte *)u, curSize);
|
||||
key += curSize;
|
||||
keySize -= curSize;
|
||||
}
|
||||
|
||||
@@ -14,9 +14,6 @@ namespace NSha1 {
|
||||
void Pbkdf2Hmac(const Byte *pwd, size_t pwdSize, const Byte *salt, size_t saltSize,
|
||||
UInt32 numIterations, Byte *key, size_t keySize);
|
||||
|
||||
void Pbkdf2Hmac32(const Byte *pwd, size_t pwdSize, const UInt32 *salt, size_t saltSize,
|
||||
UInt32 numIterations, UInt32 *key, size_t keySize);
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#ifdef USE_STATIC_RtlGenRandom
|
||||
|
||||
#include <ntsecapi.h>
|
||||
// #include <NTSecAPI.h>
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
#ifndef RtlGenRandom
|
||||
@@ -59,6 +59,7 @@ EXTERN_C_END
|
||||
|
||||
void CRandomGenerator::Init()
|
||||
{
|
||||
MY_ALIGN (16)
|
||||
CSha256 hash;
|
||||
Sha256_Init(&hash);
|
||||
|
||||
@@ -68,6 +69,7 @@ void CRandomGenerator::Init()
|
||||
#ifndef UNDER_CE
|
||||
const unsigned kNumIterations_Small = 100;
|
||||
const unsigned kBufSize = 32;
|
||||
MY_ALIGN (16)
|
||||
Byte buf[kBufSize];
|
||||
#endif
|
||||
|
||||
@@ -98,7 +100,7 @@ void CRandomGenerator::Init()
|
||||
if (hModule)
|
||||
{
|
||||
// SystemFunction036() is real name of RtlGenRandom() function
|
||||
Func_RtlGenRandom my_RtlGenRandom = (Func_RtlGenRandom)GetProcAddress(hModule, "SystemFunction036");
|
||||
Func_RtlGenRandom my_RtlGenRandom = (Func_RtlGenRandom)(void *)GetProcAddress(hModule, "SystemFunction036");
|
||||
if (my_RtlGenRandom)
|
||||
{
|
||||
if (my_RtlGenRandom(buf, kBufSize))
|
||||
@@ -126,11 +128,11 @@ void CRandomGenerator::Init()
|
||||
{
|
||||
do
|
||||
{
|
||||
int n = read(f, buf, numBytes);
|
||||
ssize_t n = read(f, buf, numBytes);
|
||||
if (n <= 0)
|
||||
break;
|
||||
Sha256_Update(&hash, buf, n);
|
||||
numBytes -= n;
|
||||
Sha256_Update(&hash, buf, (size_t)n);
|
||||
numBytes -= (unsigned)n;
|
||||
}
|
||||
while (numBytes);
|
||||
close(f);
|
||||
@@ -211,6 +213,7 @@ void CRandomGenerator::Generate(Byte *data, unsigned size)
|
||||
Init();
|
||||
while (size != 0)
|
||||
{
|
||||
MY_ALIGN (16)
|
||||
CSha256 hash;
|
||||
|
||||
Sha256_Init(&hash);
|
||||
@@ -221,6 +224,7 @@ void CRandomGenerator::Generate(Byte *data, unsigned size)
|
||||
UInt32 salt = 0xF672ABD1;
|
||||
HASH_UPD(salt);
|
||||
Sha256_Update(&hash, _buff, SHA256_DIGEST_SIZE);
|
||||
MY_ALIGN (16)
|
||||
Byte buff[SHA256_DIGEST_SIZE];
|
||||
Sha256_Final(&hash, buff);
|
||||
for (unsigned i = 0; i < SHA256_DIGEST_SIZE && size != 0; i++, size--)
|
||||
|
||||
@@ -54,7 +54,7 @@ void CData::SetPassword(const Byte *data, unsigned size)
|
||||
Keys[3] = 0xA4E7F123L;
|
||||
|
||||
Byte psw[128];
|
||||
memset(psw, 0, sizeof(psw));
|
||||
MY_memset_0_ARRAY(psw);
|
||||
if (size != 0)
|
||||
{
|
||||
if (size >= sizeof(psw))
|
||||
|
||||
@@ -28,6 +28,13 @@ class CData
|
||||
void UpdateKeys(const Byte *data);
|
||||
void CryptBlock(Byte *buf, bool encrypt);
|
||||
public:
|
||||
~CData() { Wipe(); }
|
||||
void Wipe()
|
||||
{
|
||||
MY_memset_0_ARRAY(SubstTable);
|
||||
MY_memset_0_ARRAY(Keys);
|
||||
}
|
||||
|
||||
void EncryptBlock(Byte *buf) { CryptBlock(buf, true); }
|
||||
void DecryptBlock(Byte *buf) { CryptBlock(buf, false); }
|
||||
void SetPassword(const Byte *password, unsigned passwordLen);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#endif
|
||||
|
||||
#include "Rar5Aes.h"
|
||||
#include "HmacSha256.h"
|
||||
|
||||
namespace NCrypto {
|
||||
namespace NRar5 {
|
||||
@@ -122,6 +123,7 @@ void CDecoder::SetPassword(const Byte *data, size_t size)
|
||||
if (size != _password.Size() || memcmp(data, _password, size) != 0)
|
||||
{
|
||||
_needCalc = true;
|
||||
_password.Wipe();
|
||||
_password.CopyFrom(data, size);
|
||||
}
|
||||
}
|
||||
@@ -132,28 +134,31 @@ STDMETHODIMP CDecoder::Init()
|
||||
CalcKey_and_CheckPassword();
|
||||
RINOK(SetKey(_key, kAesKeySize));
|
||||
RINOK(SetInitVector(_iv, AES_BLOCK_SIZE));
|
||||
return CAesCbcCoder::Init();
|
||||
return CAesCoder::Init();
|
||||
}
|
||||
|
||||
|
||||
UInt32 CDecoder::Hmac_Convert_Crc32(UInt32 crc) const
|
||||
{
|
||||
MY_ALIGN (16)
|
||||
NSha256::CHmac ctx;
|
||||
ctx.SetKey(_hashKey, NSha256::kDigestSize);
|
||||
Byte v[4];
|
||||
SetUi32(v, crc);
|
||||
ctx.Update(v, 4);
|
||||
Byte h[NSha256::kDigestSize];
|
||||
ctx.Final(h);
|
||||
UInt32 v;
|
||||
SetUi32(&v, crc);
|
||||
ctx.Update((const Byte *)&v, 4);
|
||||
MY_ALIGN (16)
|
||||
UInt32 h[SHA256_NUM_DIGEST_WORDS];
|
||||
ctx.Final((Byte *)h);
|
||||
crc = 0;
|
||||
for (unsigned i = 0; i < NSha256::kDigestSize; i++)
|
||||
crc ^= (UInt32)h[i] << ((i & 3) * 8);
|
||||
for (unsigned i = 0; i < SHA256_NUM_DIGEST_WORDS; i++)
|
||||
crc ^= (UInt32)GetUi32(h + i);
|
||||
return crc;
|
||||
};
|
||||
|
||||
|
||||
void CDecoder::Hmac_Convert_32Bytes(Byte *data) const
|
||||
{
|
||||
MY_ALIGN (16)
|
||||
NSha256::CHmac ctx;
|
||||
ctx.SetKey(_hashKey, NSha256::kDigestSize);
|
||||
ctx.Update(data, NSha256::kDigestSize);
|
||||
@@ -190,13 +195,16 @@ bool CDecoder::CalcKey_and_CheckPassword()
|
||||
{
|
||||
// Pbkdf HMAC-SHA-256
|
||||
|
||||
MY_ALIGN (16)
|
||||
NSha256::CHmac baseCtx;
|
||||
baseCtx.SetKey(_password, _password.Size());
|
||||
|
||||
NSha256::CHmac ctx = baseCtx;
|
||||
ctx.Update(_salt, sizeof(_salt));
|
||||
|
||||
MY_ALIGN (16)
|
||||
Byte u[NSha256::kDigestSize];
|
||||
MY_ALIGN (16)
|
||||
Byte key[NSha256::kDigestSize];
|
||||
|
||||
u[0] = 0;
|
||||
|
||||
@@ -3,11 +3,10 @@
|
||||
#ifndef __CRYPTO_RAR5_AES_H
|
||||
#define __CRYPTO_RAR5_AES_H
|
||||
|
||||
#include "../../../C/Aes.h"
|
||||
#include "../../../C/Sha256.h"
|
||||
|
||||
#include "../../Common/MyBuffer.h"
|
||||
|
||||
#include "HmacSha256.h"
|
||||
#include "MyAes.h"
|
||||
|
||||
namespace NCrypto {
|
||||
@@ -50,6 +49,17 @@ struct CKey
|
||||
}
|
||||
|
||||
CKey();
|
||||
|
||||
void Wipe()
|
||||
{
|
||||
_password.Wipe();
|
||||
MY_memset_0_ARRAY(_salt);
|
||||
MY_memset_0_ARRAY(_key);
|
||||
MY_memset_0_ARRAY(_check_Calced);
|
||||
MY_memset_0_ARRAY(_hashKey);
|
||||
}
|
||||
|
||||
~CKey() { Wipe(); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/CpuArch.h"
|
||||
#include "../../../C/RotateDefs.h"
|
||||
|
||||
#include "RarAes.h"
|
||||
#include "Sha1Cls.h"
|
||||
|
||||
@@ -71,6 +74,7 @@ void CDecoder::SetPassword(const Byte *data, unsigned size)
|
||||
}
|
||||
if (!_needCalc && !same)
|
||||
_needCalc = true;
|
||||
_password.Wipe();
|
||||
_password.CopyFrom(data, (size_t)size);
|
||||
}
|
||||
|
||||
@@ -79,9 +83,44 @@ STDMETHODIMP CDecoder::Init()
|
||||
CalcKey();
|
||||
RINOK(SetKey(_key, kAesKeySize));
|
||||
RINOK(SetInitVector(_iv, AES_BLOCK_SIZE));
|
||||
return CAesCbcCoder::Init();
|
||||
return CAesCoder::Init();
|
||||
}
|
||||
|
||||
|
||||
// if (password_size_in_bytes + SaltSize > 64),
|
||||
// the original rar code updates password_with_salt buffer
|
||||
// with some generated data from SHA1 code.
|
||||
|
||||
// #define RAR_SHA1_REDUCE
|
||||
|
||||
#ifdef RAR_SHA1_REDUCE
|
||||
#define kNumW 16
|
||||
#define WW(i) W[(i)&15]
|
||||
#else
|
||||
#define kNumW 80
|
||||
#define WW(i) W[i]
|
||||
#endif
|
||||
|
||||
static void UpdatePswDataSha1(Byte *data)
|
||||
{
|
||||
UInt32 W[kNumW];
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i++)
|
||||
W[i] = GetBe32(data + i * 4);
|
||||
|
||||
for (i = 16; i < 80; i++)
|
||||
{
|
||||
WW(i) = rotlFixed(WW((i)-3) ^ WW((i)-8) ^ WW((i)-14) ^ WW((i)-16), 1);
|
||||
}
|
||||
|
||||
for (i = 0; i < SHA1_NUM_BLOCK_WORDS; i++)
|
||||
{
|
||||
SetUi32(data + i * 4, W[kNumW - SHA1_NUM_BLOCK_WORDS + i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CDecoder::CalcKey()
|
||||
{
|
||||
if (!_needCalc)
|
||||
@@ -102,20 +141,42 @@ void CDecoder::CalcKey()
|
||||
rawSize += kSaltSize;
|
||||
}
|
||||
|
||||
MY_ALIGN (16)
|
||||
NSha1::CContext sha;
|
||||
sha.Init();
|
||||
|
||||
MY_ALIGN (16)
|
||||
Byte digest[NSha1::kDigestSize];
|
||||
// rar reverts hash for sha.
|
||||
const UInt32 kNumRounds = ((UInt32)1 << 18);
|
||||
UInt32 pos = 0;
|
||||
UInt32 i;
|
||||
for (i = 0; i < kNumRounds; i++)
|
||||
{
|
||||
sha.UpdateRar(buf, rawSize /* , _rar350Mode */);
|
||||
sha.Update(buf, rawSize);
|
||||
// if (_rar350Mode)
|
||||
{
|
||||
const UInt32 kBlockSize = 64;
|
||||
const UInt32 endPos = (pos + (UInt32)rawSize) & ~(kBlockSize - 1);
|
||||
if (endPos > pos + kBlockSize)
|
||||
{
|
||||
UInt32 curPos = pos & ~(kBlockSize - 1);
|
||||
curPos += kBlockSize;
|
||||
do
|
||||
{
|
||||
UpdatePswDataSha1(buf + (curPos - pos));
|
||||
curPos += kBlockSize;
|
||||
}
|
||||
while (curPos != endPos);
|
||||
}
|
||||
}
|
||||
pos += (UInt32)rawSize;
|
||||
Byte pswNum[3] = { (Byte)i, (Byte)(i >> 8), (Byte)(i >> 16) };
|
||||
sha.UpdateRar(pswNum, 3 /* , _rar350Mode */);
|
||||
sha.Update(pswNum, 3);
|
||||
pos += 3;
|
||||
if (i % (kNumRounds / 16) == 0)
|
||||
{
|
||||
MY_ALIGN (16)
|
||||
NSha1::CContext shaTemp = sha;
|
||||
shaTemp.Final(digest);
|
||||
_iv[i / (kNumRounds / 16)] = (Byte)digest[4 * 4 + 3];
|
||||
|
||||
@@ -44,6 +44,15 @@ public:
|
||||
HRESULT SetDecoderProperties2(const Byte *data, UInt32 size);
|
||||
|
||||
CDecoder();
|
||||
|
||||
~CDecoder() { Wipe(); }
|
||||
void Wipe()
|
||||
{
|
||||
_password.Wipe();
|
||||
MY_memset_0_ARRAY(_salt);
|
||||
MY_memset_0_ARRAY(_key);
|
||||
MY_memset_0_ARRAY(_iv);
|
||||
}
|
||||
// void SetRar350Mode(bool rar350Mode) { _rar350Mode = rar350Mode; }
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Crypto/Sha1.h
|
||||
// Crypto/Sha1Cls.h
|
||||
|
||||
#ifndef __CRYPTO_SHA1_H
|
||||
#define __CRYPTO_SHA1_H
|
||||
#ifndef __CRYPTO_SHA1_CLS_H
|
||||
#define __CRYPTO_SHA1_CLS_H
|
||||
|
||||
#include "../../../C/Sha1.h"
|
||||
|
||||
@@ -14,35 +14,21 @@ const unsigned kNumDigestWords = SHA1_NUM_DIGEST_WORDS;
|
||||
const unsigned kBlockSize = SHA1_BLOCK_SIZE;
|
||||
const unsigned kDigestSize = SHA1_DIGEST_SIZE;
|
||||
|
||||
class CContextBase
|
||||
class CContext
|
||||
{
|
||||
protected:
|
||||
CSha1 _s;
|
||||
|
||||
public:
|
||||
void Init() throw() { Sha1_Init(&_s); }
|
||||
void GetBlockDigest(const UInt32 *blockData, UInt32 *destDigest) throw() { Sha1_GetBlockDigest(&_s, blockData, destDigest); }
|
||||
};
|
||||
|
||||
class CContext: public CContextBase
|
||||
{
|
||||
public:
|
||||
void Update(const Byte *data, size_t size) throw() { Sha1_Update(&_s, data, size); }
|
||||
void UpdateRar(Byte *data, size_t size /* , bool rar350Mode */) throw() { Sha1_Update_Rar(&_s, data, size /* , rar350Mode ? 1 : 0 */); }
|
||||
void Final(Byte *digest) throw() { Sha1_Final(&_s, digest); }
|
||||
};
|
||||
|
||||
class CContext32: public CContextBase
|
||||
{
|
||||
public:
|
||||
void Update(const UInt32 *data, size_t size) throw() { Sha1_32_Update(&_s, data, size); }
|
||||
void Final(UInt32 *digest) throw() { Sha1_32_Final(&_s, digest); }
|
||||
|
||||
/* PrepareBlock can be used only when size <= 13. size in Words
|
||||
_buffer must be empty (_count & 0xF) == 0) */
|
||||
void PrepareBlock(UInt32 *block, unsigned size) const throw()
|
||||
void PrepareBlock(Byte *block, unsigned size) const throw()
|
||||
{
|
||||
Sha1_32_PrepareBlock(&_s, block, size);
|
||||
Sha1_PrepareBlock(&_s, block, size);
|
||||
}
|
||||
void GetBlockDigest(const Byte *blockData, Byte *destDigest) const throw()
|
||||
{
|
||||
Sha1_GetBlockDigest(&_s, blockData, destDigest);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -16,9 +16,6 @@ Note: you must include MyAes.cpp to project to initialize AES tables
|
||||
#include "RandGen.h"
|
||||
#include "WzAes.h"
|
||||
|
||||
// define it if you don't want to use speed-optimized version of NSha1::Pbkdf2Hmac
|
||||
// #define _NO_WZAES_OPTIMIZATIONS
|
||||
|
||||
namespace NCrypto {
|
||||
namespace NWzAes {
|
||||
|
||||
@@ -30,6 +27,7 @@ STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size)
|
||||
{
|
||||
if (size > kPasswordSizeMax)
|
||||
return E_INVALIDARG;
|
||||
_key.Password.Wipe();
|
||||
_key.Password.CopyFrom(data, (size_t)size);
|
||||
return S_OK;
|
||||
}
|
||||
@@ -40,52 +38,25 @@ void CBaseCoder::Init2()
|
||||
Byte dk[dkSizeMax32 * 4];
|
||||
|
||||
const unsigned keySize = _key.GetKeySize();
|
||||
const unsigned dkSize = 2 * keySize + kPwdVerifSize;
|
||||
const unsigned dkSize = 2 * keySize + ((kPwdVerifSize + 3) & ~(unsigned)3);
|
||||
|
||||
// for (unsigned ii = 0; ii < 1000; ii++)
|
||||
{
|
||||
#ifdef _NO_WZAES_OPTIMIZATIONS
|
||||
|
||||
NSha1::Pbkdf2Hmac(
|
||||
_key.Password, _key.Password.Size(),
|
||||
_key.Salt, _key.GetSaltSize(),
|
||||
kNumKeyGenIterations,
|
||||
dk, dkSize);
|
||||
|
||||
#else
|
||||
|
||||
UInt32 dk32[dkSizeMax32];
|
||||
const unsigned dkSize32 = (dkSize + 3) / 4;
|
||||
UInt32 salt[kSaltSizeMax / 4];
|
||||
unsigned numSaltWords = _key.GetNumSaltWords();
|
||||
|
||||
for (unsigned i = 0; i < numSaltWords; i++)
|
||||
{
|
||||
const Byte *src = _key.Salt + i * 4;
|
||||
salt[i] = GetBe32(src);
|
||||
}
|
||||
|
||||
NSha1::Pbkdf2Hmac32(
|
||||
_key.Password, _key.Password.Size(),
|
||||
salt, numSaltWords,
|
||||
kNumKeyGenIterations,
|
||||
dk32, dkSize32);
|
||||
|
||||
/*
|
||||
for (unsigned j = 0; j < dkSize; j++)
|
||||
dk[j] = (Byte)(dk32[j / 4] >> (24 - 8 * (j & 3)));
|
||||
*/
|
||||
for (unsigned j = 0; j < dkSize32; j++)
|
||||
SetBe32(dk + j * 4, dk32[j]);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
_hmac.SetKey(dk + keySize, keySize);
|
||||
Hmac()->SetKey(dk + keySize, keySize);
|
||||
memcpy(_key.PwdVerifComputed, dk + 2 * keySize, kPwdVerifSize);
|
||||
|
||||
Aes_SetKey_Enc(_aes.aes + _aes.offset + 8, dk, keySize);
|
||||
AesCtr2_Init(&_aes);
|
||||
// Aes_SetKey_Enc(_aes.Aes() + 8, dk, keySize);
|
||||
// AesCtr2_Init(&_aes);
|
||||
_aesCoderSpec->SetKeySize(keySize);
|
||||
if (_aesCoderSpec->SetKey(dk, keySize) != S_OK) throw 2;
|
||||
if (_aesCoderSpec->Init() != S_OK) throw 3;
|
||||
}
|
||||
|
||||
STDMETHODIMP CBaseCoder::Init()
|
||||
@@ -104,8 +75,9 @@ HRESULT CEncoder::WriteHeader(ISequentialOutStream *outStream)
|
||||
|
||||
HRESULT CEncoder::WriteFooter(ISequentialOutStream *outStream)
|
||||
{
|
||||
Byte mac[kMacSize];
|
||||
_hmac.Final(mac, kMacSize);
|
||||
MY_ALIGN (16)
|
||||
UInt32 mac[NSha1::kNumDigestWords];
|
||||
Hmac()->Final((Byte *)mac);
|
||||
return WriteStream(outStream, mac, kMacSize);
|
||||
}
|
||||
|
||||
@@ -150,34 +122,41 @@ bool CDecoder::Init_and_CheckPassword()
|
||||
HRESULT CDecoder::CheckMac(ISequentialInStream *inStream, bool &isOK)
|
||||
{
|
||||
isOK = false;
|
||||
MY_ALIGN (16)
|
||||
Byte mac1[kMacSize];
|
||||
RINOK(ReadStream_FAIL(inStream, mac1, kMacSize));
|
||||
Byte mac2[kMacSize];
|
||||
_hmac.Final(mac2, kMacSize);
|
||||
isOK = CompareArrays(mac1, mac2, kMacSize);
|
||||
MY_ALIGN (16)
|
||||
UInt32 mac2[NSha1::kNumDigestWords];
|
||||
Hmac()->Final((Byte *)mac2);
|
||||
isOK = CompareArrays(mac1, (const Byte *)mac2, kMacSize);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
CAesCtr2::CAesCtr2()
|
||||
/*
|
||||
|
||||
CAesCtr2::CAesCtr2():
|
||||
aes((4 + AES_NUM_IVMRK_WORDS) * 4)
|
||||
{
|
||||
offset = ((0 - (unsigned)(ptrdiff_t)aes) & 0xF) / sizeof(UInt32);
|
||||
// offset = ((0 - (unsigned)(ptrdiff_t)aes) & 0xF) / sizeof(UInt32);
|
||||
// first 16 bytes are buffer for last block data.
|
||||
// so the ivAES is aligned for (Align + 16).
|
||||
}
|
||||
|
||||
void AesCtr2_Init(CAesCtr2 *p)
|
||||
{
|
||||
UInt32 *ctr = p->aes + p->offset + 4;
|
||||
UInt32 *ctr = p->Aes() + 4;
|
||||
unsigned i;
|
||||
for (i = 0; i < 4; i++)
|
||||
ctr[i] = 0;
|
||||
p->pos = AES_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
/* (size != 16 * N) is allowed only for last call */
|
||||
// (size != 16 * N) is allowed only for last call
|
||||
|
||||
void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size)
|
||||
{
|
||||
unsigned pos = p->pos;
|
||||
UInt32 *buf32 = p->aes + p->offset;
|
||||
UInt32 *buf32 = p->Aes();
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
@@ -188,6 +167,8 @@ void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size)
|
||||
*data++ ^= buf[pos++];
|
||||
while (--size != 0 && pos != AES_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
// (size == 0 || pos == AES_BLOCK_SIZE)
|
||||
|
||||
if (size >= 16)
|
||||
{
|
||||
@@ -196,8 +177,10 @@ void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size)
|
||||
size2 <<= 4;
|
||||
data += size2;
|
||||
size -= size2;
|
||||
pos = AES_BLOCK_SIZE;
|
||||
// (pos == AES_BLOCK_SIZE)
|
||||
}
|
||||
|
||||
// (size < 16)
|
||||
|
||||
if (size != 0)
|
||||
{
|
||||
@@ -215,20 +198,26 @@ void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size)
|
||||
|
||||
p->pos = pos;
|
||||
}
|
||||
*/
|
||||
|
||||
/* (size != 16 * N) is allowed only for last Filter() call */
|
||||
|
||||
STDMETHODIMP_(UInt32) CEncoder::Filter(Byte *data, UInt32 size)
|
||||
{
|
||||
AesCtr2_Code(&_aes, data, size);
|
||||
_hmac.Update(data, size);
|
||||
// AesCtr2_Code(&_aes, data, size);
|
||||
size = _aesCoder->Filter(data, size);
|
||||
Hmac()->Update(data, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size)
|
||||
{
|
||||
_hmac.Update(data, size);
|
||||
AesCtr2_Code(&_aes, data, size);
|
||||
if (size >= 16)
|
||||
size &= ~(UInt32)15;
|
||||
|
||||
Hmac()->Update(data, size);
|
||||
// AesCtr2_Code(&_aes, data, size);
|
||||
size = _aesCoder->Filter(data, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,15 +12,12 @@ specified in "A Password Based File Encryption Utility":
|
||||
#ifndef __CRYPTO_WZ_AES_H
|
||||
#define __CRYPTO_WZ_AES_H
|
||||
|
||||
#include "../../../C/Aes.h"
|
||||
|
||||
#include "../../Common/MyBuffer.h"
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#include "../ICoder.h"
|
||||
#include "../IPassword.h"
|
||||
|
||||
#include "HmacSha1.h"
|
||||
#include "MyAes.h"
|
||||
|
||||
namespace NCrypto {
|
||||
namespace NWzAes {
|
||||
@@ -64,18 +61,33 @@ struct CKeyInfo
|
||||
unsigned GetNumSaltWords() const { return (KeySizeMode + 1); }
|
||||
|
||||
CKeyInfo(): KeySizeMode(kKeySizeMode_AES256) {}
|
||||
|
||||
void Wipe()
|
||||
{
|
||||
Password.Wipe();
|
||||
MY_memset_0_ARRAY(Salt);
|
||||
MY_memset_0_ARRAY(PwdVerifComputed);
|
||||
}
|
||||
|
||||
~CKeyInfo() { Wipe(); }
|
||||
};
|
||||
|
||||
/*
|
||||
struct CAesCtr2
|
||||
{
|
||||
unsigned pos;
|
||||
unsigned offset;
|
||||
UInt32 aes[4 + AES_NUM_IVMRK_WORDS + 3];
|
||||
CAlignedBuffer aes;
|
||||
UInt32 *Aes() { return (UInt32 *)(Byte *)aes; }
|
||||
|
||||
// unsigned offset;
|
||||
// UInt32 aes[4 + AES_NUM_IVMRK_WORDS + 3];
|
||||
// UInt32 *Aes() { return aes + offset; }
|
||||
CAesCtr2();
|
||||
};
|
||||
|
||||
void AesCtr2_Init(CAesCtr2 *p);
|
||||
void AesCtr2_Code(CAesCtr2 *p, Byte *data, SizeT size);
|
||||
*/
|
||||
|
||||
class CBaseCoder:
|
||||
public ICompressFilter,
|
||||
@@ -84,8 +96,21 @@ class CBaseCoder:
|
||||
{
|
||||
protected:
|
||||
CKeyInfo _key;
|
||||
NSha1::CHmac _hmac;
|
||||
CAesCtr2 _aes;
|
||||
|
||||
// NSha1::CHmac _hmac;
|
||||
// NSha1::CHmac *Hmac() { return &_hmac; }
|
||||
CAlignedBuffer _hmacBuf;
|
||||
NSha1::CHmac *Hmac() { return (NSha1::CHmac *)(void *)(Byte *)_hmacBuf; }
|
||||
|
||||
// CAesCtr2 _aes;
|
||||
CAesCoder *_aesCoderSpec;
|
||||
CMyComPtr<ICompressFilter> _aesCoder;
|
||||
CBaseCoder():
|
||||
_hmacBuf(sizeof(NSha1::CHmac))
|
||||
{
|
||||
_aesCoderSpec = new CAesCoder(true, 32, true);
|
||||
_aesCoder = _aesCoderSpec;
|
||||
}
|
||||
|
||||
void Init2();
|
||||
public:
|
||||
|
||||
@@ -51,7 +51,12 @@ public:
|
||||
STDMETHOD(Init)();
|
||||
STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
|
||||
|
||||
virtual ~CCipher() {}
|
||||
virtual ~CCipher()
|
||||
{
|
||||
Key0 = KeyMem0 =
|
||||
Key1 = KeyMem1 =
|
||||
Key2 = KeyMem2 = 0;
|
||||
}
|
||||
};
|
||||
|
||||
class CEncoder: public CCipher
|
||||
|
||||
@@ -26,10 +26,12 @@ static const UInt16 kAES128 = 0x660E;
|
||||
|
||||
static void DeriveKey2(const Byte *digest, Byte c, Byte *dest)
|
||||
{
|
||||
MY_ALIGN (16)
|
||||
Byte buf[64];
|
||||
memset(buf, c, 64);
|
||||
for (unsigned i = 0; i < NSha1::kDigestSize; i++)
|
||||
buf[i] ^= digest[i];
|
||||
MY_ALIGN (16)
|
||||
NSha1::CContext sha;
|
||||
sha.Init();
|
||||
sha.Update(buf, 64);
|
||||
@@ -38,8 +40,10 @@ static void DeriveKey2(const Byte *digest, Byte c, Byte *dest)
|
||||
|
||||
static void DeriveKey(NSha1::CContext &sha, Byte *key)
|
||||
{
|
||||
MY_ALIGN (16)
|
||||
Byte digest[NSha1::kDigestSize];
|
||||
sha.Final(digest);
|
||||
MY_ALIGN (16)
|
||||
Byte temp[NSha1::kDigestSize * 2];
|
||||
DeriveKey2(digest, 0x36, temp);
|
||||
DeriveKey2(digest, 0x5C, temp + NSha1::kDigestSize);
|
||||
@@ -48,6 +52,7 @@ static void DeriveKey(NSha1::CContext &sha, Byte *key)
|
||||
|
||||
void CKeyInfo::SetPassword(const Byte *data, UInt32 size)
|
||||
{
|
||||
MY_ALIGN (16)
|
||||
NSha1::CContext sha;
|
||||
sha.Init();
|
||||
sha.Update(data, size);
|
||||
@@ -103,21 +108,21 @@ HRESULT CDecoder::Init_and_CheckPassword(bool &passwOK)
|
||||
if (_remSize < 16)
|
||||
return E_NOTIMPL;
|
||||
Byte *p = _bufAligned;
|
||||
UInt16 format = GetUi16(p);
|
||||
const unsigned format = GetUi16(p);
|
||||
if (format != 3)
|
||||
return E_NOTIMPL;
|
||||
UInt16 algId = GetUi16(p + 2);
|
||||
unsigned algId = GetUi16(p + 2);
|
||||
if (algId < kAES128)
|
||||
return E_NOTIMPL;
|
||||
algId -= kAES128;
|
||||
if (algId > 2)
|
||||
return E_NOTIMPL;
|
||||
UInt16 bitLen = GetUi16(p + 4);
|
||||
UInt16 flags = GetUi16(p + 6);
|
||||
const unsigned bitLen = GetUi16(p + 4);
|
||||
const unsigned flags = GetUi16(p + 6);
|
||||
if (algId * 64 + 128 != bitLen)
|
||||
return E_NOTIMPL;
|
||||
_key.KeySize = 16 + algId * 8;
|
||||
bool cert = ((flags & 2) != 0);
|
||||
const bool cert = ((flags & 2) != 0);
|
||||
|
||||
if ((flags & 0x4000) != 0)
|
||||
{
|
||||
@@ -198,7 +203,7 @@ HRESULT CDecoder::Init_and_CheckPassword(bool &passwOK)
|
||||
|
||||
UInt32 validSize = GetUi16(p2);
|
||||
p2 += 2;
|
||||
const size_t validOffset = p2 - p;
|
||||
const size_t validOffset = (size_t)(p2 - p);
|
||||
if ((validSize & 0xF) != 0 || validOffset + validSize != _remSize)
|
||||
return E_NOTIMPL;
|
||||
|
||||
@@ -214,7 +219,9 @@ HRESULT CDecoder::Init_and_CheckPassword(bool &passwOK)
|
||||
return S_OK; // passwOK = false;
|
||||
}
|
||||
|
||||
MY_ALIGN (16)
|
||||
Byte fileKey[32];
|
||||
MY_ALIGN (16)
|
||||
NSha1::CContext sha;
|
||||
sha.Init();
|
||||
sha.Update(_iv, _ivSize);
|
||||
|
||||
@@ -27,6 +27,12 @@ struct CKeyInfo
|
||||
UInt32 KeySize;
|
||||
|
||||
void SetPassword(const Byte *data, UInt32 size);
|
||||
|
||||
~CKeyInfo() { Wipe(); }
|
||||
void Wipe()
|
||||
{
|
||||
MY_memset_0_ARRAY(MasterKey);
|
||||
}
|
||||
};
|
||||
|
||||
class CBaseCoder:
|
||||
@@ -58,6 +64,12 @@ public:
|
||||
// Change it, if is not AES
|
||||
return kAesPadAllign - (packSize32 & (kAesPadAllign - 1));
|
||||
}
|
||||
|
||||
~CDecoder() { Wipe(); }
|
||||
void Wipe()
|
||||
{
|
||||
MY_memset_0_ARRAY(_iv);
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user