#ifndef ALCRYPTOLIB_STREAM_CIPHER_CIPHER_AES_CFB_2020_01_30_H #define ALCRYPTOLIB_STREAM_CIPHER_CIPHER_AES_CFB_2020_01_30_H // https://github.com/kokke/tiny-AES-c #include #include #if(__cplusplus >= 201703L) namespace al::crypto::stream::cipher { #else namespace al { namespace crypto { namespace stream { namespace cipher { #endif template> class cipher_aes_cfb : public al::crypto::stream::cipher::cipher_aes_mode_base { private: using base_class_type = al::crypto::stream::cipher::cipher_aes_mode_base; public: cipher_aes_cfb() = default; cipher_aes_cfb(const cipher_aes_cfb&) = default; cipher_aes_cfb(cipher_aes_cfb&&) noexcept = default; ~cipher_aes_cfb() override = default; auto operator=(const cipher_aes_cfb&) -> cipher_aes_cfb& = default; auto operator=(cipher_aes_cfb&&) noexcept -> cipher_aes_cfb& = default; auto encrypt(const std::uint8_t* input_data, const std::size_t input_data_size, const std::uint8_t* key_data, const std::size_t* key_size_hint_pointer, const std::uint8_t* iv_in_data, typename base_class_type::input_output_container_type& output_data) -> void override { static_cast(key_size_hint_pointer); const std::size_t output_length = base_class_type::GetPaddingLength(input_data_size); typename base_class_type::input_output_container_type input_data_aligned(output_length, 0U); std::copy(input_data, input_data + input_data_size, input_data_aligned.begin()); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) output_data.resize(output_length, 0U); typename base_class_type::input_output_container_type block (base_class_type::blockBytesLen); typename base_class_type::input_output_container_type block_encrypted(base_class_type::blockBytesLen); memcpy(block.data(), iv_in_data, base_class_type::blockBytesLen); for(std::size_t i = 0U; i < output_length; i += base_class_type::blockBytesLen) { base_class_type::EncryptBlock(block.data(), block_encrypted.data(), key_data); al::crypto::math::utils::XorBlocks(input_data_aligned.data() + i, // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) input_data_aligned.data() + (i + base_class_type::blockBytesLen), // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) block_encrypted.data(), output_data.data() + i); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) memcpy(block.data(), output_data.data() + i, base_class_type::blockBytesLen); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) } } auto decrypt(const std::uint8_t* input_data, const std::size_t input_data_size, const std::uint8_t* key_data, const std::size_t* key_size_hint_pointer, const std::uint8_t* iv_in_data, typename base_class_type::input_output_container_type& output_data) -> void override { static_cast(key_size_hint_pointer); output_data.resize(input_data_size); typename base_class_type::input_output_container_type block (base_class_type::blockBytesLen); typename base_class_type::input_output_container_type block_encrypted(base_class_type::blockBytesLen); memcpy(block.data(), iv_in_data, base_class_type::blockBytesLen); for(std::size_t i = 0U; i < input_data_size; i += base_class_type::blockBytesLen) { base_class_type::EncryptBlock(block.data(), block_encrypted.data(), key_data); al::crypto::math::utils::XorBlocks(input_data + i, // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) input_data + (i + base_class_type::blockBytesLen), // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) block_encrypted.data(), output_data.data() + i); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) memcpy(block.data(), input_data + i, base_class_type::blockBytesLen); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) } } }; #if(__cplusplus >= 201703L) } // namespace al::crypto::stream::cipher #else } // namespace cipher } // namespace stream } // namespace crypto } // namespace al #endif #endif // ALCRYPTOLIB_STREAM_CIPHER_CIPHER_AES_CFB_2020_01_30_H