1// Crypto/MyAes.cpp
2
3#include "StdAfx.h"
4
5#include "../../../C/CpuArch.h"
6
7#include "MyAes.h"
8
9namespace NCrypto {
10
11static struct CAesTabInit { CAesTabInit() { AesGenTables();} } g_AesTabInit;
12
13CAesCbcCoder::CAesCbcCoder(bool encodeMode, unsigned keySize):
14  _keySize(keySize),
15  _keyIsSet(false),
16  _encodeMode(encodeMode)
17{
18  _offset = ((0 - (unsigned)(ptrdiff_t)_aes) & 0xF) / sizeof(UInt32);
19  memset(_iv, 0, AES_BLOCK_SIZE);
20  SetFunctions(0);
21}
22
23STDMETHODIMP CAesCbcCoder::Init()
24{
25  AesCbc_Init(_aes + _offset, _iv);
26  return _keyIsSet ? S_OK : E_FAIL;
27}
28
29STDMETHODIMP_(UInt32) CAesCbcCoder::Filter(Byte *data, UInt32 size)
30{
31  if (!_keyIsSet)
32    return 0;
33  if (size == 0)
34    return 0;
35  if (size < AES_BLOCK_SIZE)
36    return AES_BLOCK_SIZE;
37  size >>= 4;
38  _codeFunc(_aes + _offset, data, size);
39  return size << 4;
40}
41
42STDMETHODIMP CAesCbcCoder::SetKey(const Byte *data, UInt32 size)
43{
44  if ((size & 0x7) != 0 || size < 16 || size > 32)
45    return E_INVALIDARG;
46  if (_keySize != 0 && size != _keySize)
47    return E_INVALIDARG;
48  AES_SET_KEY_FUNC setKeyFunc = _encodeMode ? Aes_SetKey_Enc : Aes_SetKey_Dec;
49  setKeyFunc(_aes + _offset + 4, data, size);
50  _keyIsSet = true;
51  return S_OK;
52}
53
54STDMETHODIMP CAesCbcCoder::SetInitVector(const Byte *data, UInt32 size)
55{
56  if (size != AES_BLOCK_SIZE)
57    return E_INVALIDARG;
58  memcpy(_iv, data, size);
59  CAesCbcCoder::Init(); // don't call virtual function here !!!
60  return S_OK;
61}
62
63EXTERN_C_BEGIN
64
65void MY_FAST_CALL AesCbc_Encode(UInt32 *ivAes, Byte *data, size_t numBlocks);
66void MY_FAST_CALL AesCbc_Decode(UInt32 *ivAes, Byte *data, size_t numBlocks);
67void MY_FAST_CALL AesCtr_Code(UInt32 *ivAes, Byte *data, size_t numBlocks);
68
69void MY_FAST_CALL AesCbc_Encode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);
70void MY_FAST_CALL AesCbc_Decode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);
71void MY_FAST_CALL AesCtr_Code_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);
72
73EXTERN_C_END
74
75bool CAesCbcCoder::SetFunctions(UInt32 algo)
76{
77  _codeFunc = _encodeMode ?
78      g_AesCbc_Encode :
79      g_AesCbc_Decode;
80  if (algo == 1)
81  {
82    _codeFunc = _encodeMode ?
83        AesCbc_Encode:
84        AesCbc_Decode;
85  }
86  if (algo == 2)
87  {
88    #ifdef MY_CPU_X86_OR_AMD64
89    if (g_AesCbc_Encode != AesCbc_Encode_Intel)
90    #endif
91      return false;
92  }
93  return true;
94}
95
96STDMETHODIMP CAesCbcCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps)
97{
98  for (UInt32 i = 0; i < numProps; i++)
99  {
100    const PROPVARIANT &prop = coderProps[i];
101    if (propIDs[i] == NCoderPropID::kDefaultProp)
102    {
103      if (prop.vt != VT_UI4)
104        return E_INVALIDARG;
105      if (!SetFunctions(prop.ulVal))
106        return E_NOTIMPL;
107    }
108  }
109  return S_OK;
110}
111
112}
113