1 // Crypto/MyAes.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "../../../C/CpuArch.h"
6 
7 #include "MyAes.h"
8 
9 namespace NCrypto {
10 
CAesTabInitNCrypto::CAesTabInit11 static struct CAesTabInit { CAesTabInit() { AesGenTables();} } g_AesTabInit;
12 
CAesCbcCoder(bool encodeMode,unsigned keySize)13 CAesCbcCoder::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 
Init()23 STDMETHODIMP CAesCbcCoder::Init()
24 {
25   AesCbc_Init(_aes + _offset, _iv);
26   return _keyIsSet ? S_OK : E_FAIL;
27 }
28 
STDMETHODIMP_(UInt32)29 STDMETHODIMP_(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 
SetKey(const Byte * data,UInt32 size)42 STDMETHODIMP 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 
SetInitVector(const Byte * data,UInt32 size)54 STDMETHODIMP 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 
63 EXTERN_C_BEGIN
64 
65 void MY_FAST_CALL AesCbc_Encode(UInt32 *ivAes, Byte *data, size_t numBlocks);
66 void MY_FAST_CALL AesCbc_Decode(UInt32 *ivAes, Byte *data, size_t numBlocks);
67 void MY_FAST_CALL AesCtr_Code(UInt32 *ivAes, Byte *data, size_t numBlocks);
68 
69 void MY_FAST_CALL AesCbc_Encode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);
70 void MY_FAST_CALL AesCbc_Decode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);
71 void MY_FAST_CALL AesCtr_Code_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks);
72 
73 EXTERN_C_END
74 
SetFunctions(UInt32 algo)75 bool 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 
SetCoderProperties(const PROPID * propIDs,const PROPVARIANT * coderProps,UInt32 numProps)96 STDMETHODIMP 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