annotate src/win32/7zip/7z/CPP/7zip/Crypto/7zAes.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
rev   line source
rlm@1 1 // 7zAes.cpp
rlm@1 2
rlm@1 3 #include "StdAfx.h"
rlm@1 4
rlm@1 5 extern "C"
rlm@1 6 {
rlm@1 7 #include "../../../C/Sha256.h"
rlm@1 8 }
rlm@1 9
rlm@1 10 #include "Windows/Synchronization.h"
rlm@1 11 #include "../Common/StreamObjects.h"
rlm@1 12 #include "../Common/StreamUtils.h"
rlm@1 13 #include "7zAes.h"
rlm@1 14 #include "MyAes.h"
rlm@1 15
rlm@1 16 #ifndef EXTRACT_ONLY
rlm@1 17 #include "RandGen.h"
rlm@1 18 #endif
rlm@1 19
rlm@1 20 using namespace NWindows;
rlm@1 21
rlm@1 22 namespace NCrypto {
rlm@1 23 namespace NSevenZ {
rlm@1 24
rlm@1 25 bool CKeyInfo::IsEqualTo(const CKeyInfo &a) const
rlm@1 26 {
rlm@1 27 if (SaltSize != a.SaltSize || NumCyclesPower != a.NumCyclesPower)
rlm@1 28 return false;
rlm@1 29 for (UInt32 i = 0; i < SaltSize; i++)
rlm@1 30 if (Salt[i] != a.Salt[i])
rlm@1 31 return false;
rlm@1 32 return (Password == a.Password);
rlm@1 33 }
rlm@1 34
rlm@1 35 void CKeyInfo::CalculateDigest()
rlm@1 36 {
rlm@1 37 if (NumCyclesPower == 0x3F)
rlm@1 38 {
rlm@1 39 UInt32 pos;
rlm@1 40 for (pos = 0; pos < SaltSize; pos++)
rlm@1 41 Key[pos] = Salt[pos];
rlm@1 42 for (UInt32 i = 0; i < Password.GetCapacity() && pos < kKeySize; i++)
rlm@1 43 Key[pos++] = Password[i];
rlm@1 44 for (; pos < kKeySize; pos++)
rlm@1 45 Key[pos] = 0;
rlm@1 46 }
rlm@1 47 else
rlm@1 48 {
rlm@1 49 CSha256 sha;
rlm@1 50 Sha256_Init(&sha);
rlm@1 51 const UInt64 numRounds = UInt64(1) << (NumCyclesPower);
rlm@1 52 Byte temp[8] = { 0,0,0,0,0,0,0,0 };
rlm@1 53 for (UInt64 round = 0; round < numRounds; round++)
rlm@1 54 {
rlm@1 55 Sha256_Update(&sha, Salt, (size_t)SaltSize);
rlm@1 56 Sha256_Update(&sha, Password, Password.GetCapacity());
rlm@1 57 Sha256_Update(&sha, temp, 8);
rlm@1 58 for (int i = 0; i < 8; i++)
rlm@1 59 if (++(temp[i]) != 0)
rlm@1 60 break;
rlm@1 61 }
rlm@1 62 Sha256_Final(&sha, Key);
rlm@1 63 }
rlm@1 64 }
rlm@1 65
rlm@1 66 bool CKeyInfoCache::Find(CKeyInfo &key)
rlm@1 67 {
rlm@1 68 for (int i = 0; i < Keys.Size(); i++)
rlm@1 69 {
rlm@1 70 const CKeyInfo &cached = Keys[i];
rlm@1 71 if (key.IsEqualTo(cached))
rlm@1 72 {
rlm@1 73 for (int j = 0; j < kKeySize; j++)
rlm@1 74 key.Key[j] = cached.Key[j];
rlm@1 75 if (i != 0)
rlm@1 76 {
rlm@1 77 Keys.Insert(0, cached);
rlm@1 78 Keys.Delete(i+1);
rlm@1 79 }
rlm@1 80 return true;
rlm@1 81 }
rlm@1 82 }
rlm@1 83 return false;
rlm@1 84 }
rlm@1 85
rlm@1 86 void CKeyInfoCache::Add(CKeyInfo &key)
rlm@1 87 {
rlm@1 88 if (Find(key))
rlm@1 89 return;
rlm@1 90 if (Keys.Size() >= Size)
rlm@1 91 Keys.DeleteBack();
rlm@1 92 Keys.Insert(0, key);
rlm@1 93 }
rlm@1 94
rlm@1 95 static CKeyInfoCache g_GlobalKeyCache(32);
rlm@1 96 static NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection;
rlm@1 97
rlm@1 98 CBase::CBase():
rlm@1 99 _cachedKeys(16),
rlm@1 100 _ivSize(0)
rlm@1 101 {
rlm@1 102 for (int i = 0; i < sizeof(_iv); i++)
rlm@1 103 _iv[i] = 0;
rlm@1 104 }
rlm@1 105
rlm@1 106 void CBase::CalculateDigest()
rlm@1 107 {
rlm@1 108 NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection);
rlm@1 109 if (_cachedKeys.Find(_key))
rlm@1 110 g_GlobalKeyCache.Add(_key);
rlm@1 111 else
rlm@1 112 {
rlm@1 113 if (!g_GlobalKeyCache.Find(_key))
rlm@1 114 {
rlm@1 115 _key.CalculateDigest();
rlm@1 116 g_GlobalKeyCache.Add(_key);
rlm@1 117 }
rlm@1 118 _cachedKeys.Add(_key);
rlm@1 119 }
rlm@1 120 }
rlm@1 121
rlm@1 122 #ifndef EXTRACT_ONLY
rlm@1 123
rlm@1 124 /*
rlm@1 125 STDMETHODIMP CEncoder::ResetSalt()
rlm@1 126 {
rlm@1 127 _key.SaltSize = 4;
rlm@1 128 g_RandomGenerator.Generate(_key.Salt, _key.SaltSize);
rlm@1 129 return S_OK;
rlm@1 130 }
rlm@1 131 */
rlm@1 132
rlm@1 133 STDMETHODIMP CEncoder::ResetInitVector()
rlm@1 134 {
rlm@1 135 _ivSize = 8;
rlm@1 136 g_RandomGenerator.Generate(_iv, (unsigned)_ivSize);
rlm@1 137 return S_OK;
rlm@1 138 }
rlm@1 139
rlm@1 140 STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
rlm@1 141 {
rlm@1 142 // _key.Init();
rlm@1 143 for (UInt32 i = _ivSize; i < sizeof(_iv); i++)
rlm@1 144 _iv[i] = 0;
rlm@1 145
rlm@1 146 UInt32 ivSize = _ivSize;
rlm@1 147
rlm@1 148 // _key.NumCyclesPower = 0x3F;
rlm@1 149 _key.NumCyclesPower = 19;
rlm@1 150
rlm@1 151 Byte firstByte = (Byte)(_key.NumCyclesPower |
rlm@1 152 (((_key.SaltSize == 0) ? 0 : 1) << 7) |
rlm@1 153 (((ivSize == 0) ? 0 : 1) << 6));
rlm@1 154 RINOK(outStream->Write(&firstByte, 1, NULL));
rlm@1 155 if (_key.SaltSize == 0 && ivSize == 0)
rlm@1 156 return S_OK;
rlm@1 157 Byte saltSizeSpec = (Byte)((_key.SaltSize == 0) ? 0 : (_key.SaltSize - 1));
rlm@1 158 Byte ivSizeSpec = (Byte)((ivSize == 0) ? 0 : (ivSize - 1));
rlm@1 159 Byte secondByte = (Byte)(((saltSizeSpec) << 4) | ivSizeSpec);
rlm@1 160 RINOK(outStream->Write(&secondByte, 1, NULL));
rlm@1 161 if (_key.SaltSize > 0)
rlm@1 162 {
rlm@1 163 RINOK(WriteStream(outStream, _key.Salt, _key.SaltSize));
rlm@1 164 }
rlm@1 165 if (ivSize > 0)
rlm@1 166 {
rlm@1 167 RINOK(WriteStream(outStream, _iv, ivSize));
rlm@1 168 }
rlm@1 169 return S_OK;
rlm@1 170 }
rlm@1 171
rlm@1 172 HRESULT CEncoder::CreateFilter()
rlm@1 173 {
rlm@1 174 _aesFilter = new CAesCbcEncoder;
rlm@1 175 return S_OK;
rlm@1 176 }
rlm@1 177
rlm@1 178 #endif
rlm@1 179
rlm@1 180 STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
rlm@1 181 {
rlm@1 182 _key.Init();
rlm@1 183 UInt32 i;
rlm@1 184 for (i = 0; i < sizeof(_iv); i++)
rlm@1 185 _iv[i] = 0;
rlm@1 186 if (size == 0)
rlm@1 187 return S_OK;
rlm@1 188 UInt32 pos = 0;
rlm@1 189 Byte firstByte = data[pos++];
rlm@1 190
rlm@1 191 _key.NumCyclesPower = firstByte & 0x3F;
rlm@1 192 if ((firstByte & 0xC0) == 0)
rlm@1 193 return S_OK;
rlm@1 194 _key.SaltSize = (firstByte >> 7) & 1;
rlm@1 195 UInt32 ivSize = (firstByte >> 6) & 1;
rlm@1 196
rlm@1 197 if (pos >= size)
rlm@1 198 return E_INVALIDARG;
rlm@1 199 Byte secondByte = data[pos++];
rlm@1 200
rlm@1 201 _key.SaltSize += (secondByte >> 4);
rlm@1 202 ivSize += (secondByte & 0x0F);
rlm@1 203
rlm@1 204 if (pos + _key.SaltSize + ivSize > size)
rlm@1 205 return E_INVALIDARG;
rlm@1 206 for (i = 0; i < _key.SaltSize; i++)
rlm@1 207 _key.Salt[i] = data[pos++];
rlm@1 208 for (i = 0; i < ivSize; i++)
rlm@1 209 _iv[i] = data[pos++];
rlm@1 210 return S_OK;
rlm@1 211 }
rlm@1 212
rlm@1 213 STDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size)
rlm@1 214 {
rlm@1 215 _key.Password.SetCapacity((size_t)size);
rlm@1 216 memcpy(_key.Password, data, (size_t)size);
rlm@1 217 return S_OK;
rlm@1 218 }
rlm@1 219
rlm@1 220 STDMETHODIMP CBaseCoder::Init()
rlm@1 221 {
rlm@1 222 CalculateDigest();
rlm@1 223 if (_aesFilter == 0)
rlm@1 224 {
rlm@1 225 RINOK(CreateFilter());
rlm@1 226 }
rlm@1 227 CMyComPtr<ICryptoProperties> cp;
rlm@1 228 RINOK(_aesFilter.QueryInterface(IID_ICryptoProperties, &cp));
rlm@1 229 RINOK(cp->SetKey(_key.Key, sizeof(_key.Key)));
rlm@1 230 RINOK(cp->SetInitVector(_iv, sizeof(_iv)));
rlm@1 231 return S_OK;
rlm@1 232 }
rlm@1 233
rlm@1 234 STDMETHODIMP_(UInt32) CBaseCoder::Filter(Byte *data, UInt32 size)
rlm@1 235 {
rlm@1 236 return _aesFilter->Filter(data, size);
rlm@1 237 }
rlm@1 238
rlm@1 239 HRESULT CDecoder::CreateFilter()
rlm@1 240 {
rlm@1 241 _aesFilter = new CAesCbcDecoder;
rlm@1 242 return S_OK;
rlm@1 243 }
rlm@1 244
rlm@1 245 }}