Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/Crypto/7zAES/7zAES.cpp')
-rwxr-xr-xCPP/7zip/Crypto/7zAES/7zAES.cpp305
1 files changed, 305 insertions, 0 deletions
diff --git a/CPP/7zip/Crypto/7zAES/7zAES.cpp b/CPP/7zip/Crypto/7zAES/7zAES.cpp
new file mode 100755
index 00000000..843d9027
--- /dev/null
+++ b/CPP/7zip/Crypto/7zAES/7zAES.cpp
@@ -0,0 +1,305 @@
+// 7z_AES.cpp
+
+#include "StdAfx.h"
+
+#include "Windows/Defs.h"
+#include "Windows/Synchronization.h"
+#include "../../Common/StreamObjects.h"
+#include "../../Common/StreamUtils.h"
+
+#include "7zAES.h"
+// #include "../../Hash/Common/CryptoHashInterface.h"
+
+#ifdef CRYPTO_AES
+#include "../AES/MyAES.h"
+#endif
+
+#include "../Hash/Sha256.h"
+
+using namespace NWindows;
+
+#ifndef CRYPTO_AES
+extern HINSTANCE g_hInstance;
+#endif
+
+namespace NCrypto {
+namespace NSevenZ {
+
+bool CKeyInfo::IsEqualTo(const CKeyInfo &a) const
+{
+ if (SaltSize != a.SaltSize || NumCyclesPower != a.NumCyclesPower)
+ return false;
+ for (UInt32 i = 0; i < SaltSize; i++)
+ if (Salt[i] != a.Salt[i])
+ return false;
+ return (Password == a.Password);
+}
+
+void CKeyInfo::CalculateDigest()
+{
+ if (NumCyclesPower == 0x3F)
+ {
+ UInt32 pos;
+ for (pos = 0; pos < SaltSize; pos++)
+ Key[pos] = Salt[pos];
+ for (UInt32 i = 0; i < Password.GetCapacity() && pos < kKeySize; i++)
+ Key[pos++] = Password[i];
+ for (; pos < kKeySize; pos++)
+ Key[pos] = 0;
+ }
+ else
+ {
+ NCrypto::NSha256::CContext sha;
+ const UInt64 numRounds = UInt64(1) << (NumCyclesPower);
+ Byte temp[8] = { 0,0,0,0,0,0,0,0 };
+ for (UInt64 round = 0; round < numRounds; round++)
+ {
+ sha.Update(Salt, SaltSize);
+ sha.Update(Password, Password.GetCapacity());
+ sha.Update(temp, 8);
+ for (int i = 0; i < 8; i++)
+ if (++(temp[i]) != 0)
+ break;
+ }
+ sha.Final(Key);
+ }
+}
+
+bool CKeyInfoCache::Find(CKeyInfo &key)
+{
+ for (int i = 0; i < Keys.Size(); i++)
+ {
+ const CKeyInfo &cached = Keys[i];
+ if (key.IsEqualTo(cached))
+ {
+ for (int j = 0; j < kKeySize; j++)
+ key.Key[j] = cached.Key[j];
+ if (i != 0)
+ {
+ Keys.Insert(0, cached);
+ Keys.Delete(i+1);
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+void CKeyInfoCache::Add(CKeyInfo &key)
+{
+ if (Find(key))
+ return;
+ if (Keys.Size() >= Size)
+ Keys.DeleteBack();
+ Keys.Insert(0, key);
+}
+
+static CKeyInfoCache g_GlobalKeyCache(32);
+static NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection;
+
+CBase::CBase():
+ _cachedKeys(16)
+{
+ for (int i = 0; i < sizeof(_iv); i++)
+ _iv[i] = 0;
+}
+
+void CBase::CalculateDigest()
+{
+ NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection);
+ if (_cachedKeys.Find(_key))
+ g_GlobalKeyCache.Add(_key);
+ else
+ {
+ if (!g_GlobalKeyCache.Find(_key))
+ {
+ _key.CalculateDigest();
+ g_GlobalKeyCache.Add(_key);
+ }
+ _cachedKeys.Add(_key);
+ }
+}
+
+
+/*
+static void GetRandomData(Byte *data)
+{
+ // probably we don't need truly random.
+ // it's enough to prevent dictionary attack;
+ // but it gives some info about time when compressing
+ // was made.
+ UInt64 tempValue;
+ SYSTEMTIME systemTime;
+ FILETIME fileTime;
+ ::GetSystemTime(&systemTime);
+ ::SystemTimeToFileTime(&systemTime, &fileTime);
+ tempValue = *(const UInt64 *)&fileTime;
+ LARGE_INTEGER counter;
+ ::QueryPerformanceCounter(&counter);
+ tempValue += *(const UInt64 *)&counter;
+ tempValue += (UInt64)(GetTickCount()) << 32;
+ *(UInt64 *)data = tempValue;
+}
+*/
+
+STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
+{
+ _key.Init();
+ for (UInt32 i = 0; i < sizeof(_iv); i++)
+ _iv[i] = 0;
+
+ _key.SaltSize = 0;
+
+ // _key.SaltSize = 8;
+ // GetRandomData(_key.Salt);
+
+ int ivSize = 0;
+
+ // _key.NumCyclesPower = 0x3F;
+ _key.NumCyclesPower = 18;
+
+ Byte firstByte = (Byte)(_key.NumCyclesPower |
+ (((_key.SaltSize == 0) ? 0 : 1) << 7) |
+ (((ivSize == 0) ? 0 : 1) << 6));
+ RINOK(outStream->Write(&firstByte, 1, NULL));
+ if (_key.SaltSize == 0 && ivSize == 0)
+ return S_OK;
+ Byte saltSizeSpec = (Byte)((_key.SaltSize == 0) ? 0 : (_key.SaltSize - 1));
+ Byte ivSizeSpec = (Byte)((ivSize == 0) ? 0 : (ivSize - 1));
+ Byte secondByte = (Byte)(((saltSizeSpec) << 4) | ivSizeSpec);
+ RINOK(outStream->Write(&secondByte, 1, NULL));
+ if (_key.SaltSize > 0)
+ {
+ RINOK(WriteStream(outStream, _key.Salt, _key.SaltSize, NULL));
+ }
+ if (ivSize > 0)
+ {
+ RINOK(WriteStream(outStream, _iv, ivSize, NULL));
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
+{
+ _key.Init();
+ UInt32 i;
+ for (i = 0; i < sizeof(_iv); i++)
+ _iv[i] = 0;
+ if (size == 0)
+ return S_OK;
+ UInt32 pos = 0;
+ Byte firstByte = data[pos++];
+
+ _key.NumCyclesPower = firstByte & 0x3F;
+ if ((firstByte & 0xC0) == 0)
+ return S_OK;
+ _key.SaltSize = (firstByte >> 7) & 1;
+ UInt32 ivSize = (firstByte >> 6) & 1;
+
+ if (pos >= size)
+ return E_INVALIDARG;
+ Byte secondByte = data[pos++];
+
+ _key.SaltSize += (secondByte >> 4);
+ ivSize += (secondByte & 0x0F);
+
+ if (pos + _key.SaltSize + ivSize > size)
+ return E_INVALIDARG;
+ for (i = 0; i < _key.SaltSize; i++)
+ _key.Salt[i] = data[pos++];
+ for (i = 0; i < ivSize; i++)
+ _iv[i] = data[pos++];
+ return S_OK;
+}
+
+STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size)
+{
+ _key.Password.SetCapacity(size);
+ memcpy(_key.Password, data, size);
+ return S_OK;
+}
+
+/*
+static Byte *WideToRaw(const wchar_t *src, Byte *dest, int destSize=0x10000000)
+{
+ for (int i = 0; i < destSize; i++, src++)
+ {
+ dest[i * 2] = (Byte)*src;
+ dest[i * 2 + 1]= (Byte)(*src >> 8);
+ if (*src == 0)
+ break;
+ }
+ return(dest);
+}
+*/
+
+#ifndef CRYPTO_AES
+bool GetAESLibPath(TCHAR *path)
+{
+ TCHAR fullPath[MAX_PATH + 1];
+ if (::GetModuleFileName(g_hInstance, fullPath, MAX_PATH) == 0)
+ return false;
+ LPTSTR fileNamePointer;
+ DWORD needLength = ::GetFullPathName(fullPath, MAX_PATH + 1,
+ path, &fileNamePointer);
+ if (needLength == 0 || needLength >= MAX_PATH)
+ return false;
+ lstrcpy(fileNamePointer, TEXT("AES.dll"));
+ return true;
+}
+#endif
+
+STDMETHODIMP CBaseCoder::Init()
+{
+ CalculateDigest();
+ if (_aesFilter == 0)
+ {
+ RINOK(CreateFilter());
+ }
+ CMyComPtr<ICryptoProperties> cp;
+ RINOK(_aesFilter.QueryInterface(IID_ICryptoProperties, &cp));
+ RINOK(cp->SetKey(_key.Key, sizeof(_key.Key)));
+ RINOK(cp->SetInitVector(_iv, sizeof(_iv)));
+ return S_OK;
+}
+
+STDMETHODIMP_(UInt32) CBaseCoder::Filter(Byte *data, UInt32 size)
+{
+ return _aesFilter->Filter(data, size);
+}
+
+#ifndef CRYPTO_AES
+HRESULT CBaseCoder::CreateFilterFromDLL(REFCLSID clsID)
+{
+ if (!_aesLibrary)
+ {
+ TCHAR filePath[MAX_PATH + 2];
+ if (!GetAESLibPath(filePath))
+ return ::GetLastError();
+ return _aesLibrary.LoadAndCreateFilter(filePath, clsID, &_aesFilter);
+ }
+ return S_OK;
+}
+#endif
+
+HRESULT CEncoder::CreateFilter()
+{
+ #ifdef CRYPTO_AES
+ _aesFilter = new CAES_CBC_Encoder;
+ return S_OK;
+ #else
+ return CreateFilterFromDLL(CLSID_CCrypto_AES_CBC_Encoder);
+ #endif
+}
+
+HRESULT CDecoder::CreateFilter()
+{
+ #ifdef CRYPTO_AES
+ _aesFilter = new CAES_CBC_Decoder;
+ return S_OK;
+ #else
+ return CreateFilterFromDLL(CLSID_CCrypto_AES_CBC_Decoder);
+ #endif
+}
+
+}}