// Crypto/MyAes.cpp #include "StdAfx.h" #include "../../../C/CpuArch.h" #include "MyAes.h" namespace NCrypto { static struct CAesTabInit { CAesTabInit() { AesGenTables();} } g_AesTabInit; CAesCbcCoder::CAesCbcCoder(bool encodeMode, unsigned keySize): _keySize(keySize), _keyIsSet(false), _encodeMode(encodeMode) { _offset = ((0 - (unsigned)(ptrdiff_t)_aes) & 0xF) / sizeof(UInt32); memset(_iv, 0, AES_BLOCK_SIZE); SetFunctions(0); } STDMETHODIMP CAesCbcCoder::Init() { AesCbc_Init(_aes + _offset, _iv); return _keyIsSet ? S_OK : E_FAIL; } STDMETHODIMP_(UInt32) CAesCbcCoder::Filter(Byte *data, UInt32 size) { if (!_keyIsSet) return 0; if (size == 0) return 0; if (size < AES_BLOCK_SIZE) return AES_BLOCK_SIZE; size >>= 4; _codeFunc(_aes + _offset, data, size); return size << 4; } STDMETHODIMP CAesCbcCoder::SetKey(const Byte *data, UInt32 size) { if ((size & 0x7) != 0 || size < 16 || size > 32) return E_INVALIDARG; if (_keySize != 0 && size != _keySize) return E_INVALIDARG; AES_SET_KEY_FUNC setKeyFunc = _encodeMode ? Aes_SetKey_Enc : Aes_SetKey_Dec; setKeyFunc(_aes + _offset + 4, data, size); _keyIsSet = true; return S_OK; } STDMETHODIMP CAesCbcCoder::SetInitVector(const Byte *data, UInt32 size) { if (size != AES_BLOCK_SIZE) return E_INVALIDARG; memcpy(_iv, data, size); CAesCbcCoder::Init(); // don't call virtual function here !!! return S_OK; } EXTERN_C_BEGIN void MY_FAST_CALL AesCbc_Encode(UInt32 *ivAes, Byte *data, size_t numBlocks); void MY_FAST_CALL AesCbc_Decode(UInt32 *ivAes, Byte *data, size_t numBlocks); void MY_FAST_CALL AesCtr_Code(UInt32 *ivAes, Byte *data, size_t numBlocks); void MY_FAST_CALL AesCbc_Encode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks); void MY_FAST_CALL AesCbc_Decode_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks); void MY_FAST_CALL AesCtr_Code_Intel(UInt32 *ivAes, Byte *data, size_t numBlocks); EXTERN_C_END bool CAesCbcCoder::SetFunctions(UInt32 algo) { _codeFunc = _encodeMode ? g_AesCbc_Encode : g_AesCbc_Decode; if (algo == 1) { _codeFunc = _encodeMode ? AesCbc_Encode: AesCbc_Decode; } if (algo == 2) { #ifdef MY_CPU_X86_OR_AMD64 if (g_AesCbc_Encode != AesCbc_Encode_Intel) #endif return false; } return true; } STDMETHODIMP CAesCbcCoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *coderProps, UInt32 numProps) { for (UInt32 i = 0; i < numProps; i++) { const PROPVARIANT &prop = coderProps[i]; if (propIDs[i] == NCoderPropID::kDefaultProp) { if (prop.vt != VT_UI4) return E_INVALIDARG; if (!SetFunctions(prop.ulVal)) return E_NOTIMPL; } } return S_OK; } }