1cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky// 7zAes.cpp
2cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
3cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#include "StdAfx.h"
4cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
5cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#include "../../../C/Sha256.h"
6cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
7f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka#include "../../Common/ComTry.h"
8f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
9f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka#ifndef _7ZIP_ST
10cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#include "../../Windows/Synchronization.h"
11f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka#endif
12cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
13cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#include "../Common/StreamUtils.h"
14cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
15cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#include "7zAes.h"
16cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#include "MyAes.h"
17cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
18cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#ifndef EXTRACT_ONLY
19cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#include "RandGen.h"
20cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#endif
21cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
22cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckynamespace NCrypto {
23f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osakanamespace N7z {
24f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
25f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osakastatic const unsigned k_NumCyclesPower_Supported_MAX = 24;
26cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
27cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckybool CKeyInfo::IsEqualTo(const CKeyInfo &a) const
28cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
29cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (SaltSize != a.SaltSize || NumCyclesPower != a.NumCyclesPower)
30cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    return false;
31f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  for (unsigned i = 0; i < SaltSize; i++)
32cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (Salt[i] != a.Salt[i])
33cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      return false;
34cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  return (Password == a.Password);
35cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
36cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
37f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osakavoid CKeyInfo::CalcKey()
38cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
39cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (NumCyclesPower == 0x3F)
40cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
41f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    unsigned pos;
42cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    for (pos = 0; pos < SaltSize; pos++)
43cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      Key[pos] = Salt[pos];
44f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    for (unsigned i = 0; i < Password.Size() && pos < kKeySize; i++)
45cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      Key[pos++] = Password[i];
46cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    for (; pos < kKeySize; pos++)
47cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      Key[pos] = 0;
48cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
49cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  else
50cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
51f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    size_t bufSize = 8 + SaltSize + Password.Size();
52f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    CObjArray<Byte> buf(bufSize);
53f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    memcpy(buf, Salt, SaltSize);
54f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    memcpy(buf + SaltSize, Password, Password.Size());
55f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
56cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    CSha256 sha;
57cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Sha256_Init(&sha);
58f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
59f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    Byte *ctr = buf + SaltSize + Password.Size();
60f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
61f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    for (unsigned i = 0; i < 8; i++)
62f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka      ctr[i] = 0;
63f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
64f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    UInt64 numRounds = (UInt64)1 << NumCyclesPower;
65f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
66f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    do
67cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    {
68f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka      Sha256_Update(&sha, buf, bufSize);
69f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka      for (unsigned i = 0; i < 8; i++)
70f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka        if (++(ctr[i]) != 0)
71cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky          break;
72cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    }
73f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    while (--numRounds != 0);
74f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
75cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Sha256_Final(&sha, Key);
76cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
77cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
78cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
79f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osakabool CKeyInfoCache::GetKey(CKeyInfo &key)
80cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
81cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  FOR_VECTOR (i, Keys)
82cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
83cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    const CKeyInfo &cached = Keys[i];
84cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (key.IsEqualTo(cached))
85cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    {
86f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka      for (unsigned j = 0; j < kKeySize; j++)
87cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        key.Key[j] = cached.Key[j];
88cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      if (i != 0)
89cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        Keys.MoveToFront(i);
90cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      return true;
91cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    }
92cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
93cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  return false;
94cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
95cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
96f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osakavoid CKeyInfoCache::FindAndAdd(const CKeyInfo &key)
97f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka{
98f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  FOR_VECTOR (i, Keys)
99f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  {
100f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    const CKeyInfo &cached = Keys[i];
101f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    if (key.IsEqualTo(cached))
102f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    {
103f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka      if (i != 0)
104f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka        Keys.MoveToFront(i);
105f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka      return;
106f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    }
107f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  }
108f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  Add(key);
109f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka}
110f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
111f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osakavoid CKeyInfoCache::Add(const CKeyInfo &key)
112cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
113cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (Keys.Size() >= Size)
114cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    Keys.DeleteBack();
115cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  Keys.Insert(0, key);
116cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
117cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
118cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbeckystatic CKeyInfoCache g_GlobalKeyCache(32);
119f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
120f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka#ifndef _7ZIP_ST
121f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  static NWindows::NSynchronization::CCriticalSection g_GlobalKeyCacheCriticalSection;
122f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  #define MT_LOCK NWindows::NSynchronization::CCriticalSectionLock lock(g_GlobalKeyCacheCriticalSection);
123f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka#else
124f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  #define MT_LOCK
125f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka#endif
126cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
127cd66d540cead3f8200b0c73bad9c276d67896c3dDavid SrbeckyCBase::CBase():
128cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  _cachedKeys(16),
129cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  _ivSize(0)
130cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
131f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  for (unsigned i = 0; i < sizeof(_iv); i++)
132cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    _iv[i] = 0;
133cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
134cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
135f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osakavoid CBase::PrepareKey()
136cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
137f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  // BCJ2 threads use same password. So we use long lock.
138f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  MT_LOCK
139f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
140f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  bool finded = false;
141f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  if (!_cachedKeys.GetKey(_key))
142cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
143f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    finded = g_GlobalKeyCache.GetKey(_key);
144f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    if (!finded)
145f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka      _key.CalcKey();
146cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    _cachedKeys.Add(_key);
147cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
148f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  if (!finded)
149f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    g_GlobalKeyCache.FindAndAdd(_key);
150cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
151cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
152cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#ifndef EXTRACT_ONLY
153cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
154cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky/*
155cd66d540cead3f8200b0c73bad9c276d67896c3dDavid SrbeckySTDMETHODIMP CEncoder::ResetSalt()
156cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
157cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  _key.SaltSize = 4;
158cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  g_RandomGenerator.Generate(_key.Salt, _key.SaltSize);
159cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  return S_OK;
160cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
161cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky*/
162cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
163cd66d540cead3f8200b0c73bad9c276d67896c3dDavid SrbeckySTDMETHODIMP CEncoder::ResetInitVector()
164cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
165f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  for (unsigned i = 0; i < sizeof(_iv); i++)
166f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    _iv[i] = 0;
167cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  _ivSize = 8;
168f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  g_RandomGenerator.Generate(_iv, _ivSize);
169cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  return S_OK;
170cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
171cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
172cd66d540cead3f8200b0c73bad9c276d67896c3dDavid SrbeckySTDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
173cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
174f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  Byte props[2 + sizeof(_key.Salt) + sizeof(_iv)];
175f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  unsigned propsSize = 1;
176cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
177f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  props[0] = (Byte)(_key.NumCyclesPower
178f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka      | (_key.SaltSize == 0 ? 0 : (1 << 7))
179f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka      | (_ivSize       == 0 ? 0 : (1 << 6)));
180cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
181f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  if (_key.SaltSize != 0 || _ivSize != 0)
182cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
183f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    props[1] = (Byte)(
184f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka        ((_key.SaltSize == 0 ? 0 : _key.SaltSize - 1) << 4)
185f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka        | (_ivSize      == 0 ? 0 : _ivSize - 1));
186f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    memcpy(props + 2, _key.Salt, _key.SaltSize);
187f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    propsSize = 2 + _key.SaltSize;
188f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    memcpy(props + propsSize, _iv, _ivSize);
189f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    propsSize += _ivSize;
190cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
191f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
192f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  return WriteStream(outStream, props, propsSize);
193cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
194cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
195f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo OsakaCEncoder::CEncoder()
196cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
197f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  // _key.SaltSize = 4; g_RandomGenerator.Generate(_key.Salt, _key.SaltSize);
198f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  // _key.NumCyclesPower = 0x3F;
199f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  _key.NumCyclesPower = 19;
200cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  _aesFilter = new CAesCbcEncoder(kKeySize);
201cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
202cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
203cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#endif
204cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
205f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo OsakaCDecoder::CDecoder()
206f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka{
207f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  _aesFilter = new CAesCbcDecoder(kKeySize);
208f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka}
209f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
210cd66d540cead3f8200b0c73bad9c276d67896c3dDavid SrbeckySTDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
211cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
212f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  _key.ClearProps();
213f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
214f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  _ivSize = 0;
215f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  unsigned i;
216cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  for (i = 0; i < sizeof(_iv); i++)
217cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    _iv[i] = 0;
218f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
219cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (size == 0)
220cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    return S_OK;
221f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
222f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  Byte b0 = data[0];
223cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
224f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  _key.NumCyclesPower = b0 & 0x3F;
225f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  if ((b0 & 0xC0) == 0)
226f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    return size == 1 ? S_OK : E_INVALIDARG;
227cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
228f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  if (size <= 1)
229cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    return E_INVALIDARG;
230f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
231f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  Byte b1 = data[1];
232f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
233f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  unsigned saltSize = ((b0 >> 7) & 1) + (b1 >> 4);
234f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  unsigned ivSize   = ((b0 >> 6) & 1) + (b1 & 0x0F);
235cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
236f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  if (size != 2 + saltSize + ivSize)
237cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    return E_INVALIDARG;
238f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  _key.SaltSize = saltSize;
239f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  data += 2;
240f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  for (i = 0; i < saltSize; i++)
241f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    _key.Salt[i] = *data++;
242cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  for (i = 0; i < ivSize; i++)
243f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    _iv[i] = *data++;
244f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  return (_key.NumCyclesPower <= k_NumCyclesPower_Supported_MAX
245f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka      || _key.NumCyclesPower == 0x3F) ? S_OK : E_NOTIMPL;
246cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
247cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
248f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
249cd66d540cead3f8200b0c73bad9c276d67896c3dDavid SrbeckySTDMETHODIMP CBaseCoder::CryptoSetPassword(const Byte *data, UInt32 size)
250cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
251f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  COM_TRY_BEGIN
252f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
253cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  _key.Password.CopyFrom(data, (size_t)size);
254cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  return S_OK;
255f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
256f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  COM_TRY_END
257cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
258cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
259cd66d540cead3f8200b0c73bad9c276d67896c3dDavid SrbeckySTDMETHODIMP CBaseCoder::Init()
260cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
261f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  COM_TRY_BEGIN
262f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
263f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  PrepareKey();
264cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  CMyComPtr<ICryptoProperties> cp;
265cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  RINOK(_aesFilter.QueryInterface(IID_ICryptoProperties, &cp));
266f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  if (!cp)
267f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    return E_FAIL;
268f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  RINOK(cp->SetKey(_key.Key, kKeySize));
269cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  RINOK(cp->SetInitVector(_iv, sizeof(_iv)));
270cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  return _aesFilter->Init();
271f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
272f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  COM_TRY_END
273cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
274cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
275cd66d540cead3f8200b0c73bad9c276d67896c3dDavid SrbeckySTDMETHODIMP_(UInt32) CBaseCoder::Filter(Byte *data, UInt32 size)
276cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
277cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  return _aesFilter->Filter(data, size);
278cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
279cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
280cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}}
281