diff options
Diffstat (limited to '')
-rw-r--r-- | CMakeLists.txt | 7 | ||||
-rw-r--r-- | include/aesni/all.h | 1 | ||||
-rw-r--r-- | include/aesni/data.h | 11 | ||||
-rw-r--r-- | include/aesni/file.h | 20 | ||||
-rw-r--r-- | src/file.c | 79 | ||||
-rw-r--r-- | utils/CMakeLists.txt | 8 | ||||
-rw-r--r-- | utils/aes128ecb_decrypt_file.cpp | 89 | ||||
-rw-r--r-- | utils/aes128ecb_encrypt_file.cpp | 90 |
8 files changed, 302 insertions, 3 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index dda23ba..c6be168 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,9 @@ -project(libaesni C ASM_MASM) +project(libaesni C CXX ASM_MASM) file(GLOB_RECURSE ${PROJECT_NAME}_headers "include/*.h") if(AESNI_USE_ASM) - file(GLOB ${PROJECT_NAME}_sources src/aes128.asm src/aes192.asm src/aes256.asm src/common.c) + file(GLOB ${PROJECT_NAME}_sources src/aes128.asm src/aes192.asm src/aes256.asm src/common.c src/file.c) else() - file(GLOB ${PROJECT_NAME}_sources src/aes128.c src/aes192.c src/aes256.c src/common.c) + file(GLOB ${PROJECT_NAME}_sources src/aes128.c src/aes192.c src/aes256.c src/common.c src/file.c) endif() add_library(${PROJECT_NAME} ${${PROJECT_NAME}_headers} ${${PROJECT_NAME}_sources}) @@ -12,3 +12,4 @@ target_compile_definitions(${PROJECT_NAME} PRIVATE _CRT_SECURE_NO_WARNINGS) add_subdirectory(examples) add_subdirectory(test) +add_subdirectory(utils) diff --git a/include/aesni/all.h b/include/aesni/all.h index 3935d2a..a383b87 100644 --- a/include/aesni/all.h +++ b/include/aesni/all.h @@ -10,4 +10,5 @@ #include "api.h" #include "data.h" +#include "file.h" #include "raw.h" diff --git a/include/aesni/data.h b/include/aesni/data.h index 0cee7c6..73b7f6e 100644 --- a/include/aesni/data.h +++ b/include/aesni/data.h @@ -13,6 +13,17 @@ typedef __m128i AesBlock128; +static __inline AesBlock128 load_aes_block128(const unsigned char* src) +{ + return _mm_loadu_si128((AesBlock128*) src); +} + +static __inline void __fastcall store_aes_block128(AesBlock128 block, + unsigned char* dest) +{ + _mm_storeu_si128((AesBlock128*) dest, block); +} + static __inline AesBlock128 __fastcall make_aes_block128(int hi3, int hi2, int lo1, int lo0) { return _mm_set_epi32(hi3, hi2, lo1, lo0); diff --git a/include/aesni/file.h b/include/aesni/file.h new file mode 100644 index 0000000..eb84d09 --- /dev/null +++ b/include/aesni/file.h @@ -0,0 +1,20 @@ +/** + * \file + * \author Egor Tensin <Egor.Tensin@gmail.com> + * \date 2015 + * \copyright This file is licensed under the terms of the MIT License. + * See LICENSE.txt for details. + */ + +#pragma once + +#include <stdio.h> + +size_t aes128ecb_encrypt_file(const unsigned char* src, + size_t src_size, + unsigned char* dest, + Aes128KeySchedule* key_schedule); +size_t aes128ecb_decrypt_file(const unsigned char* src, + size_t src_size, + unsigned char* dest, + Aes128KeySchedule* inverted_schedule); diff --git a/src/file.c b/src/file.c new file mode 100644 index 0000000..445d917 --- /dev/null +++ b/src/file.c @@ -0,0 +1,79 @@ +/** + * \file + * \author Egor Tensin <Egor.Tensin@gmail.com> + * \date 2015 + * \copyright This file is licensed under the terms of the MIT License. + * See LICENSE.txt for details. + */ + +#include <aesni/all.h> + +#include <stdlib.h> +#include <string.h> + +size_t aes128ecb_encrypt_file(const unsigned char* src, + size_t src_size, + unsigned char* dest, + Aes128KeySchedule* key_schedule) +{ + size_t rem_size = src_size % 16; + size_t padding_size = 16 - rem_size; + size_t dest_size = src_size + padding_size; + + if (dest == NULL) + return dest_size; + + size_t src_len = src_size / 16; + + for (size_t i = 0; i < src_len; ++i, src += 16, dest += 16) + { + AesBlock128 plaintext = load_aes_block128(src); + AesBlock128 ciphertext = aes128ecb_encrypt(plaintext, key_schedule); + store_aes_block128(ciphertext, dest); + } + + unsigned char padding[16] = { 0x10 }; + + if (rem_size != 0) + { + memcpy(padding, src, rem_size); + memset(padding + rem_size, padding_size, padding_size); + } + + AesBlock128 plaintext = load_aes_block128(padding); + AesBlock128 ciphertext = aes128ecb_encrypt(plaintext, key_schedule); + store_aes_block128(ciphertext, dest); + + return dest_size; +} + +size_t aes128ecb_decrypt_file(const unsigned char* src, + size_t src_size, + unsigned char* dest, + Aes128KeySchedule* inverted_schedule) +{ + size_t dest_size = src_size; + + if (dest == NULL) + return dest_size; + + size_t src_len = src_size / 16; + + for (size_t i = 0; i < src_len - 1; ++i, src += 16, dest += 16) + { + AesBlock128 ciphertext = load_aes_block128(src); + AesBlock128 plaintext = aes128ecb_decrypt(ciphertext, inverted_schedule); + store_aes_block128(plaintext, dest); + } + + AesBlock128 ciphertext = load_aes_block128(src); + AesBlock128 plaintext = aes128ecb_decrypt(ciphertext, inverted_schedule); + unsigned char padding[16]; + store_aes_block128(plaintext, padding); + + if (padding[0] == 0x10) + return dest_size - 16; + + memcpy(dest, padding, 16 - padding[15]); + return dest_size - padding[15]; +} diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt new file mode 100644 index 0000000..f6ca7d1 --- /dev/null +++ b/utils/CMakeLists.txt @@ -0,0 +1,8 @@ +macro(util prefix) + add_executable(util_${prefix} ${prefix}.cpp) + target_link_libraries(util_${prefix} libaesni) + set_target_properties(util_${prefix} PROPERTIES OUTPUT_NAME ${prefix}) +endmacro() + +util(aes128ecb_encrypt_file) +util(aes128ecb_decrypt_file) diff --git a/utils/aes128ecb_decrypt_file.cpp b/utils/aes128ecb_decrypt_file.cpp new file mode 100644 index 0000000..a6757d4 --- /dev/null +++ b/utils/aes128ecb_decrypt_file.cpp @@ -0,0 +1,89 @@ +/** + * \file + * \author Egor Tensin <Egor.Tensin@gmail.com> + * \date 2015 + * \copyright This file is licensed under the terms of the MIT License. + * See LICENSE.txt for details. + */ + +extern "C" +{ +#include <aesni/all.h> +} + +#include <cstdio> + +#include <iostream> +#include <fstream> +#include <string> +#include <vector> + +namespace +{ + void exit_with_usage() + { + std::cout << "Usage: aes128ecb_encrypt_file.exe KEY SRC DEST\n"; + std::exit(EXIT_FAILURE); + } + + std::ifstream::pos_type get_file_size(const std::string& path) + { + std::ifstream ifs(path, std::ifstream::binary | std::ifstream::ate); + return ifs.tellg(); + } +} + +int main(int argc, char** argv) +{ + AesBlock128 key; + Aes128KeySchedule key_schedule, inverted_schedule; + + if (argc != 4) + exit_with_usage(); + + if (parse_aes_block128(&key, argv[1]) != 0) + { + std::cerr << "Invalid 128-bit AES block '" << argv[1] << "'\n"; + exit_with_usage(); + } + + try + { + const std::string src_path(argv[2]); + const std::string dest_path(argv[3]); + + const auto src_size = get_file_size(src_path); + + std::ifstream src_ifs; + src_ifs.exceptions(std::ifstream::badbit | std::ifstream::failbit); + src_ifs.open(src_path, std::ifstream::binary); + + std::vector<unsigned char> src_buf; + src_buf.reserve(static_cast<std::vector<char>::size_type>(src_size)); + src_buf.assign(std::istreambuf_iterator<char>(src_ifs), + std::istreambuf_iterator<char>()); + + aes128_expand_key_schedule(key, &key_schedule); + aes128_invert_key_schedule(&key_schedule, &inverted_schedule); + + auto dest_size = aes128ecb_decrypt_file( + src_buf.data(), static_cast<std::size_t>(src_size), NULL, &inverted_schedule); + + std::vector<unsigned char> dest_buf(static_cast<std::vector<char>::size_type>(dest_size)); + + dest_size = aes128ecb_decrypt_file( + src_buf.data(), static_cast<std::size_t>(src_size), dest_buf.data(), &inverted_schedule); + + std::ofstream dest_ofs; + dest_ofs.exceptions(std::ofstream::badbit | std::ofstream::failbit); + dest_ofs.open(dest_path, std::ofstream::binary); + dest_ofs.write(reinterpret_cast<const char*>(dest_buf.data()), dest_size); + } + catch (const std::exception& e) + { + std::cerr << e.what() << "\n"; + return 1; + } + + return 0; +} diff --git a/utils/aes128ecb_encrypt_file.cpp b/utils/aes128ecb_encrypt_file.cpp new file mode 100644 index 0000000..aba8569 --- /dev/null +++ b/utils/aes128ecb_encrypt_file.cpp @@ -0,0 +1,90 @@ +/** + * \file + * \author Egor Tensin <Egor.Tensin@gmail.com> + * \date 2015 + * \copyright This file is licensed under the terms of the MIT License. + * See LICENSE.txt for details. + */ + +extern "C" +{ +#include <aesni/all.h> +} + +#include <cstdio> + +#include <iostream> +#include <fstream> +#include <string> +#include <vector> + +namespace +{ + void exit_with_usage() + { + std::cout << "Usage: aes128ecb_encrypt_file.exe KEY SRC DEST\n"; + std::exit(EXIT_FAILURE); + } + + std::ifstream::pos_type get_file_size(const std::string& path) + { + std::ifstream ifs(path, std::ifstream::binary | std::ifstream::ate); + return ifs.tellg(); + } +} + +int main(int argc, char** argv) +{ + AesBlock128 key; + Aes128KeySchedule key_schedule; + + if (argc != 4) + exit_with_usage(); + + if (parse_aes_block128(&key, argv[1]) != 0) + { + std::cerr << "Invalid 128-bit AES block '" << argv[1] << "'\n"; + exit_with_usage(); + } + + try + { + const std::string src_path(argv[2]); + const std::string dest_path(argv[3]); + + const auto src_size = get_file_size(src_path); + + std::ifstream src_ifs; + src_ifs.exceptions(std::ifstream::badbit | std::ifstream::failbit); + src_ifs.open(src_path, std::ifstream::binary); + + std::vector<unsigned char> src_buf; + src_buf.reserve(static_cast<std::vector<char>::size_type>(src_size)); + src_buf.assign(std::istreambuf_iterator<char>(src_ifs), + std::istreambuf_iterator<char>()); + + aes128_expand_key_schedule(key, &key_schedule); + + const auto dest_size = aes128ecb_encrypt_file( + src_buf.data(), static_cast<std::size_t>(src_size), NULL, &key_schedule); + + std::vector<unsigned char> dest_buf(static_cast<std::vector<char>::size_type>(dest_size)); + + aes128ecb_encrypt_file(src_buf.data(), + static_cast<std::size_t>(src_size), + dest_buf.data(), + &key_schedule); + + std::ofstream dest_ofs; + dest_ofs.exceptions(std::ofstream::badbit | std::ofstream::failbit); + dest_ofs.open(dest_path, std::ofstream::binary); + dest_ofs.write(reinterpret_cast<const char*>(dest_buf.data()), dest_buf.size()); + } + catch (const std::exception& e) + { + std::cerr << e.what() << "\n"; + return 1; + } + + return 0; +} |