diff options
-rw-r--r-- | include/aesni/all.h | 1 | ||||
-rw-r--r-- | include/aesni/buffer.h | 14 | ||||
-rw-r--r-- | include/aesni/error.h | 50 | ||||
-rw-r--r-- | src/buffer.c | 76 | ||||
-rw-r--r-- | src/error.c | 66 | ||||
-rw-r--r-- | utils/CMakeLists.txt | 2 | ||||
-rw-r--r-- | utils/aes128ecb_decrypt_file.cpp | 36 | ||||
-rw-r--r-- | utils/aes128ecb_encrypt_file.cpp | 30 | ||||
-rw-r--r-- | utils/common.hpp | 38 |
9 files changed, 271 insertions, 42 deletions
diff --git a/include/aesni/all.h b/include/aesni/all.h index 1360320..4653eca 100644 --- a/include/aesni/all.h +++ b/include/aesni/all.h @@ -11,4 +11,5 @@ #include "block.h" #include "buffer.h" #include "data.h" +#include "error.h" #include "raw.h" diff --git a/include/aesni/buffer.h b/include/aesni/buffer.h index daafc3e..13f19da 100644 --- a/include/aesni/buffer.h +++ b/include/aesni/buffer.h @@ -8,6 +8,8 @@ #pragma once +#include "error.h" + #include <stdlib.h> #ifdef __cplusplus @@ -15,16 +17,20 @@ extern "C" { #endif -size_t aesni_encrypt_buffer_ecb128( +int aesni_encrypt_buffer_ecb128( const void* src, size_t src_size, void* dest, - AesNI_KeySchedule128* key_schedule); -size_t aesni_decrypt_buffer_ecb128( + size_t* dest_size, + AesNI_KeySchedule128* key_schedule, + AesNI_ErrorDetails*); +int aesni_decrypt_buffer_ecb128( const void* src, size_t src_size, void* dest, - AesNI_KeySchedule128* inverted_schedule); + size_t* dest_size, + AesNI_KeySchedule128* inverted_schedule, + AesNI_ErrorDetails*); #ifdef __cplusplus } diff --git a/include/aesni/error.h b/include/aesni/error.h new file mode 100644 index 0000000..54d3d34 --- /dev/null +++ b/include/aesni/error.h @@ -0,0 +1,50 @@ +/** + * \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 + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef enum +{ + AESNI_ERROR_SUCCESS, + + AESNI_ERROR_NULL_ARGUMENT, + + AESNI_ERROR_INVALID_PKCS7_PADDING, +} +AesNI_ErrorCode; + +const char* aesni_strerror(AesNI_ErrorCode); + +typedef struct +{ + AesNI_ErrorCode ec; + + union + { + struct + { + char arg_name[32]; + } + null_arg; + } + params; +} +AesNI_ErrorDetails; + +void aesni_make_error_success(AesNI_ErrorDetails*); +void aesni_make_error_null_argument(AesNI_ErrorDetails*, const char* arg_name); +void aesni_make_error_invalid_pkcs7_padding(AesNI_ErrorDetails*); + +#ifdef __cplusplus +} +#endif diff --git a/src/buffer.c b/src/buffer.c index b4896f7..71ebad2 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -13,20 +13,40 @@ static unsigned char FULL_BLOCK_PADDING[16] = { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 }; -size_t aesni_encrypt_buffer_ecb128( +int aesni_encrypt_buffer_ecb128( const void* src, size_t src_size, void* dest, - AesNI_KeySchedule128* key_schedule) + size_t* dest_size, + AesNI_KeySchedule128* key_schedule, + AesNI_ErrorDetails* err_details) { - size_t rem_size = src_size % 16; - size_t padding_size = 16 - rem_size; - size_t dest_size = src_size + padding_size; + if (dest_size == NULL) + { + aesni_make_error_null_argument(err_details, "dest_size"); + return 1; + } + + const size_t rem_size = src_size % 16; + const size_t padding_size = 16 - rem_size; + *dest_size = src_size + padding_size; if (dest == NULL) - return dest_size; + return 0; - size_t src_len = src_size / 16; + if (src == NULL) + { + aesni_make_error_null_argument(err_details, "src"); + return 1; + } + + if (key_schedule == NULL) + { + aesni_make_error_null_argument(err_details, "key_schedule"); + return 1; + } + + const size_t src_len = src_size / 16; for (size_t i = 0; i < src_len; ++i, (char*) src += 16, (char*) dest += 16) { @@ -51,10 +71,10 @@ size_t aesni_encrypt_buffer_ecb128( AesNI_Block128 ciphertext = aesni_encrypt_block_ecb128(plaintext, key_schedule); aesni_store_block128(dest, ciphertext); - return dest_size; + return 0; } -static unsigned char get_padding_size(const unsigned char* padding) +static unsigned char get_pkcs7_padding_size(const unsigned char* padding) { if (padding[15] < 0x01 || padding[15] > 0x10) return 0; @@ -66,18 +86,38 @@ static unsigned char get_padding_size(const unsigned char* padding) return padding[15]; } -size_t aesni_decrypt_buffer_ecb128( +int aesni_decrypt_buffer_ecb128( const void* src, size_t src_size, void* dest, - AesNI_KeySchedule128* inverted_schedule) + size_t* dest_size, + AesNI_KeySchedule128* inverted_schedule, + AesNI_ErrorDetails* err_details) { - size_t dest_size = src_size; + if (dest_size == NULL) + { + aesni_make_error_null_argument(err_details, "dest_size"); + return 1; + } + + *dest_size = src_size; if (dest == NULL) - return dest_size; + return 0; + + if (src == NULL) + { + aesni_make_error_null_argument(err_details, "src"); + return 1; + } - size_t src_len = src_size / 16; + if (inverted_schedule == NULL) + { + aesni_make_error_null_argument(err_details, "inverted_schedule"); + return 1; + } + + const size_t src_len = src_size / 16; for (size_t i = 0; i < src_len - 1; ++i, (char*) src += 16, (char*) dest += 16) { @@ -91,15 +131,17 @@ size_t aesni_decrypt_buffer_ecb128( unsigned char padding[16]; aesni_store_block128(padding, plaintext); - unsigned char padding_size = get_padding_size(padding); + unsigned char padding_size = get_pkcs7_padding_size(padding); if (padding_size == 0) { - return dest_size - 16; + aesni_make_error_invalid_pkcs7_padding(err_details); + return 1; } else { memcpy(dest, padding, 16 - padding_size); - return dest_size - padding_size; + *dest_size -= padding_size; + return 0; } } diff --git a/src/error.c b/src/error.c new file mode 100644 index 0000000..c4af82c --- /dev/null +++ b/src/error.c @@ -0,0 +1,66 @@ +/** + * \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> + +static const char* err_msgs[] = +{ + "Success", + "Invalid argument value NULL", + "Invalid PKCS7 padding (wrong key?)", +}; + +const char* aesni_strerror(AesNI_ErrorCode ec) +{ + return err_msgs[ec]; +} + +static void aesni_make_error( + AesNI_ErrorDetails* err_details, + AesNI_ErrorCode ec) +{ + if (err_details == NULL) + return; + + err_details->ec = ec; +} + +void aesni_make_error_success( + AesNI_ErrorDetails* err_details) +{ + if (err_details == NULL) + return; + + aesni_make_error(err_details, AESNI_ERROR_SUCCESS); +} + +void aesni_make_error_null_argument( + AesNI_ErrorDetails* err_details, + const char* arg_name) +{ + if (err_details == NULL) + return; + + aesni_make_error(err_details, AESNI_ERROR_NULL_ARGUMENT); + + const size_t arg_name_size = sizeof(err_details->params.null_arg.arg_name); + strncpy(err_details->params.null_arg.arg_name, arg_name, arg_name_size); + err_details->params.null_arg.arg_name[arg_name_size - 1] = '\0'; +} + +void aesni_make_error_invalid_pkcs7_padding( + AesNI_ErrorDetails* err_details) +{ + if (err_details == NULL) + return; + + aesni_make_error(err_details, AESNI_ERROR_INVALID_PKCS7_PADDING); +} diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index f6ca7d1..a667663 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -1,5 +1,5 @@ macro(util prefix) - add_executable(util_${prefix} ${prefix}.cpp) + add_executable(util_${prefix} ${prefix}.cpp common.hpp) target_link_libraries(util_${prefix} libaesni) set_target_properties(util_${prefix} PROPERTIES OUTPUT_NAME ${prefix}) endmacro() diff --git a/utils/aes128ecb_decrypt_file.cpp b/utils/aes128ecb_decrypt_file.cpp index 33e0515..23545f9 100644 --- a/utils/aes128ecb_decrypt_file.cpp +++ b/utils/aes128ecb_decrypt_file.cpp @@ -6,10 +6,13 @@ * See LICENSE.txt for details. */ +#include "common.hpp" + #include <aesni/all.h> -#include <cstdio> +#include <cstdlib> +#include <exception> #include <iostream> #include <fstream> #include <string> @@ -51,27 +54,40 @@ int main(int argc, char** argv) const std::string src_path(argv[2]); const std::string dest_path(argv[3]); - const auto src_size = get_file_size(src_path); + const auto src_size = static_cast<std::size_t>(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<char> src_buf; - src_buf.reserve(static_cast<std::vector<char>::size_type>(src_size)); + src_buf.reserve(src_size); src_buf.assign(std::istreambuf_iterator<char>(src_ifs), std::istreambuf_iterator<char>()); aesni_expand_key_schedule128(key, &key_schedule); aesni_invert_key_schedule128(&key_schedule, &inverted_schedule); - auto dest_size = aesni_decrypt_buffer_ecb128( - src_buf.data(), static_cast<std::size_t>(src_size), NULL, &inverted_schedule); - - std::vector<char> dest_buf(static_cast<std::vector<char>::size_type>(dest_size)); - - dest_size = aesni_decrypt_buffer_ecb128( - src_buf.data(), static_cast<std::size_t>(src_size), dest_buf.data(), &inverted_schedule); + std::size_t dest_size; + + aesni_decrypt_buffer_ecb128( + src_buf.data(), + src_size, + NULL, + &dest_size, + &inverted_schedule, + aesni::ErrorDetailsThrowsInDestructor()); + + std::vector<char> dest_buf; + dest_buf.reserve(dest_size); + + aesni_decrypt_buffer_ecb128( + src_buf.data(), + src_size, + dest_buf.data(), + &dest_size, + &inverted_schedule, + aesni::ErrorDetailsThrowsInDestructor()); std::ofstream dest_ofs; dest_ofs.exceptions(std::ofstream::badbit | std::ofstream::failbit); diff --git a/utils/aes128ecb_encrypt_file.cpp b/utils/aes128ecb_encrypt_file.cpp index 07c3e91..42e297c 100644 --- a/utils/aes128ecb_encrypt_file.cpp +++ b/utils/aes128ecb_encrypt_file.cpp @@ -6,10 +6,13 @@ * See LICENSE.txt for details. */ +#include "common.hpp" + #include <aesni/all.h> -#include <cstdio> +#include <cstdlib> +#include <exception> #include <iostream> #include <fstream> #include <string> @@ -51,37 +54,44 @@ int main(int argc, char** argv) const std::string src_path(argv[2]); const std::string dest_path(argv[3]); - const auto src_size = get_file_size(src_path); + const auto src_size = static_cast<std::size_t>(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<char> src_buf; - src_buf.reserve(static_cast<std::vector<char>::size_type>(src_size)); + src_buf.reserve(src_size); src_buf.assign(std::istreambuf_iterator<char>(src_ifs), std::istreambuf_iterator<char>()); aesni_expand_key_schedule128(key, &key_schedule); - const auto dest_size = aesni_encrypt_buffer_ecb128( + std::size_t dest_size; + + aesni_encrypt_buffer_ecb128( src_buf.data(), - static_cast<std::size_t>(src_size), + src_size, NULL, - &key_schedule); + &dest_size, + &key_schedule, + aesni::ErrorDetailsThrowsInDestructor()); - std::vector<char> dest_buf(static_cast<std::vector<char>::size_type>(dest_size)); + std::vector<char> dest_buf; + dest_buf.reserve(dest_size); aesni_encrypt_buffer_ecb128( src_buf.data(), - static_cast<std::size_t>(src_size), + src_size, dest_buf.data(), - &key_schedule); + &dest_size, + &key_schedule, + aesni::ErrorDetailsThrowsInDestructor()); std::ofstream dest_ofs; dest_ofs.exceptions(std::ofstream::badbit | std::ofstream::failbit); dest_ofs.open(dest_path, std::ofstream::binary); - dest_ofs.write(dest_buf.data(), dest_buf.size()); + dest_ofs.write(dest_buf.data(), dest_size); } catch (const std::exception& e) { diff --git a/utils/common.hpp b/utils/common.hpp new file mode 100644 index 0000000..af61a32 --- /dev/null +++ b/utils/common.hpp @@ -0,0 +1,38 @@ +/** + * \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 <aesni/all.h> + +#include <stdexcept> + +namespace aesni +{ + class ErrorDetailsThrowsInDestructor + { + public: + ErrorDetailsThrowsInDestructor() + { + aesni_make_error_success(get()); + } + + ~ErrorDetailsThrowsInDestructor() + { + if (m_impl.ec != AESNI_ERROR_SUCCESS) + throw std::runtime_error(aesni_strerror(m_impl.ec)); + } + + AesNI_ErrorDetails* get() { return &m_impl; } + + operator AesNI_ErrorDetails*() { return get(); } + + private: + AesNI_ErrorDetails m_impl; + }; +} |