mirror of
https://github.com/aaru-dps/Aaru.Compression.Native.git
synced 2025-12-16 19:24:31 +00:00
Move placement of lzma.
This commit is contained in:
317
3rdparty/lzma/CPP/7zip/Crypto/7zAes.cpp
vendored
Normal file
317
3rdparty/lzma/CPP/7zip/Crypto/7zAes.cpp
vendored
Normal file
@@ -0,0 +1,317 @@
|
||||
// 7zAes.cpp
|
||||
|
||||
#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"
|
||||
#endif
|
||||
|
||||
#include "../Common/StreamUtils.h"
|
||||
|
||||
#include "7zAes.h"
|
||||
#include "MyAes.h"
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
#include "RandGen.h"
|
||||
#endif
|
||||
|
||||
namespace NCrypto {
|
||||
namespace N7z {
|
||||
|
||||
static const unsigned k_NumCyclesPower_Supported_MAX = 24;
|
||||
|
||||
bool CKeyInfo::IsEqualTo(const CKeyInfo &a) const
|
||||
{
|
||||
if (SaltSize != a.SaltSize || NumCyclesPower != a.NumCyclesPower)
|
||||
return false;
|
||||
for (unsigned i = 0; i < SaltSize; i++)
|
||||
if (Salt[i] != a.Salt[i])
|
||||
return false;
|
||||
return (Password == a.Password);
|
||||
}
|
||||
|
||||
void CKeyInfo::CalcKey()
|
||||
{
|
||||
if (NumCyclesPower == 0x3F)
|
||||
{
|
||||
unsigned pos;
|
||||
for (pos = 0; pos < SaltSize; pos++)
|
||||
Key[pos] = Salt[pos];
|
||||
for (unsigned i = 0; i < Password.Size() && pos < kKeySize; i++)
|
||||
Key[pos++] = Password[i];
|
||||
for (; pos < kKeySize; pos++)
|
||||
Key[pos] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
|
||||
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((CSha256 *)(Byte *)sha, buf, bufSize);
|
||||
for (unsigned i = 0; i < 8; i++)
|
||||
if (++(ctr[i]) != 0)
|
||||
break;
|
||||
}
|
||||
while (--numRounds != 0);
|
||||
*/
|
||||
|
||||
Sha256_Final((CSha256 *)(void *)(Byte *)sha, Key);
|
||||
memset(sha, 0, sha.Size());
|
||||
}
|
||||
}
|
||||
|
||||
bool CKeyInfoCache::GetKey(CKeyInfo &key)
|
||||
{
|
||||
FOR_VECTOR (i, Keys)
|
||||
{
|
||||
const CKeyInfo &cached = Keys[i];
|
||||
if (key.IsEqualTo(cached))
|
||||
{
|
||||
for (unsigned j = 0; j < kKeySize; j++)
|
||||
key.Key[j] = cached.Key[j];
|
||||
if (i != 0)
|
||||
Keys.MoveToFront(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CKeyInfoCache::FindAndAdd(const CKeyInfo &key)
|
||||
{
|
||||
FOR_VECTOR (i, Keys)
|
||||
{
|
||||
const CKeyInfo &cached = Keys[i];
|
||||
if (key.IsEqualTo(cached))
|
||||
{
|
||||
if (i != 0)
|
||||
Keys.MoveToFront(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Add(key);
|
||||
}
|
||||
|
||||
void CKeyInfoCache::Add(const CKeyInfo &key)
|
||||
{
|
||||
if (Keys.Size() >= Size)
|
||||
Keys.DeleteBack();
|
||||
Keys.Insert(0, key);
|
||||
}
|
||||
|
||||
static CKeyInfoCache g_GlobalKeyCache(32);
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
static NWindows::NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection;
|
||||
#define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection);
|
||||
#else
|
||||
#define MT_LOCK
|
||||
#endif
|
||||
|
||||
CBase::CBase():
|
||||
_cachedKeys(16),
|
||||
_ivSize(0)
|
||||
{
|
||||
for (unsigned i = 0; i < sizeof(_iv); i++)
|
||||
_iv[i] = 0;
|
||||
}
|
||||
|
||||
void CBase::PrepareKey()
|
||||
{
|
||||
// BCJ2 threads use same password. So we use long lock.
|
||||
MT_LOCK
|
||||
|
||||
bool finded = false;
|
||||
if (!_cachedKeys.GetKey(_key))
|
||||
{
|
||||
finded = g_GlobalKeyCache.GetKey(_key);
|
||||
if (!finded)
|
||||
_key.CalcKey();
|
||||
_cachedKeys.Add(_key);
|
||||
}
|
||||
if (!finded)
|
||||
g_GlobalKeyCache.FindAndAdd(_key);
|
||||
}
|
||||
|
||||
#ifndef EXTRACT_ONLY
|
||||
|
||||
/*
|
||||
STDMETHODIMP CEncoder::ResetSalt()
|
||||
{
|
||||
_key.SaltSize = 4;
|
||||
g_RandomGenerator.Generate(_key.Salt, _key.SaltSize);
|
||||
return S_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
STDMETHODIMP CEncoder::ResetInitVector()
|
||||
{
|
||||
for (unsigned i = 0; i < sizeof(_iv); i++)
|
||||
_iv[i] = 0;
|
||||
_ivSize = 16;
|
||||
MY_RAND_GEN(_iv, _ivSize);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
|
||||
{
|
||||
Byte props[2 + sizeof(_key.Salt) + sizeof(_iv)];
|
||||
unsigned propsSize = 1;
|
||||
|
||||
props[0] = (Byte)(_key.NumCyclesPower
|
||||
| (_key.SaltSize == 0 ? 0 : (1 << 7))
|
||||
| (_ivSize == 0 ? 0 : (1 << 6)));
|
||||
|
||||
if (_key.SaltSize != 0 || _ivSize != 0)
|
||||
{
|
||||
props[1] = (Byte)(
|
||||
((_key.SaltSize == 0 ? 0 : _key.SaltSize - 1) << 4)
|
||||
| (_ivSize == 0 ? 0 : _ivSize - 1));
|
||||
memcpy(props + 2, _key.Salt, _key.SaltSize);
|
||||
propsSize = 2 + _key.SaltSize;
|
||||
memcpy(props + propsSize, _iv, _ivSize);
|
||||
propsSize += _ivSize;
|
||||
}
|
||||
|
||||
return WriteStream(outStream, props, propsSize);
|
||||
}
|
||||
|
||||
CEncoder::CEncoder()
|
||||
{
|
||||
// _key.SaltSize = 4; g_RandomGenerator.Generate(_key.Salt, _key.SaltSize);
|
||||
// _key.NumCyclesPower = 0x3F;
|
||||
_key.NumCyclesPower = 19;
|
||||
_aesFilter = new CAesCbcEncoder(kKeySize);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
CDecoder::CDecoder()
|
||||
{
|
||||
_aesFilter = new CAesCbcDecoder(kKeySize);
|
||||
}
|
||||
|
||||
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
|
||||
{
|
||||
_key.ClearProps();
|
||||
|
||||
_ivSize = 0;
|
||||
unsigned i;
|
||||
for (i = 0; i < sizeof(_iv); i++)
|
||||
_iv[i] = 0;
|
||||
|
||||
if (size == 0)
|
||||
return S_OK;
|
||||
|
||||
Byte b0 = data[0];
|
||||
|
||||
_key.NumCyclesPower = b0 & 0x3F;
|
||||
if ((b0 & 0xC0) == 0)
|
||||
return size == 1 ? S_OK : E_INVALIDARG;
|
||||
|
||||
if (size <= 1)
|
||||
return E_INVALIDARG;
|
||||
|
||||
Byte b1 = data[1];
|
||||
|
||||
unsigned saltSize = ((b0 >> 7) & 1) + (b1 >> 4);
|
||||
unsigned ivSize = ((b0 >> 6) & 1) + (b1 & 0x0F);
|
||||
|
||||
if (size != 2 + saltSize + ivSize)
|
||||
return E_INVALIDARG;
|
||||
_key.SaltSize = saltSize;
|
||||
data += 2;
|
||||
for (i = 0; i < saltSize; i++)
|
||||
_key.Salt[i] = *data++;
|
||||
for (i = 0; i < ivSize; i++)
|
||||
_iv[i] = *data++;
|
||||
return (_key.NumCyclesPower <= k_NumCyclesPower_Supported_MAX
|
||||
|| _key.NumCyclesPower == 0x3F) ? S_OK : E_NOTIMPL;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size)
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
_key.Password.Wipe();
|
||||
_key.Password.CopyFrom(data, (size_t)size);
|
||||
return S_OK;
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CBaseCoder::Init()
|
||||
{
|
||||
COM_TRY_BEGIN
|
||||
|
||||
PrepareKey();
|
||||
CMyComPtr<ICryptoProperties> cp;
|
||||
RINOK(_aesFilter.QueryInterface(IID_ICryptoProperties, &cp));
|
||||
if (!cp)
|
||||
return E_FAIL;
|
||||
RINOK(cp->SetKey(_key.Key, kKeySize));
|
||||
RINOK(cp->SetInitVector(_iv, sizeof(_iv)));
|
||||
return _aesFilter->Init();
|
||||
|
||||
COM_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP_(UInt32) CBaseCoder::Filter(Byte *data, UInt32 size)
|
||||
{
|
||||
return _aesFilter->Filter(data, size);
|
||||
}
|
||||
|
||||
}}
|
||||
Reference in New Issue
Block a user