From 351c5188013fff041c7217aed64478cfc7643480 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Sat, 21 Dec 2019 13:33:50 +0300 Subject: restructure the project --- CMakeLists.txt | 31 +- aes/CMakeLists.txt | 28 ++ aes/include/aes/aes.h | 541 ++++++++++++++++++++++++++++++ aes/include/aes/algorithm.h | 23 ++ aes/include/aes/all.h | 21 ++ aes/include/aes/box.h | 81 +++++ aes/include/aes/box_aes.h | 21 ++ aes/include/aes/box_data.h | 153 +++++++++ aes/include/aes/data.h | 122 +++++++ aes/include/aes/error.h | 96 ++++++ aes/include/aes/mode.h | 166 +++++++++ aes/include/aes/padding.h | 38 +++ aes/include/aes/workarounds.h | 16 + aes/src/aes.c | 384 +++++++++++++++++++++ aes/src/asm/aes128.asm | 203 +++++++++++ aes/src/asm/aes192.asm | 249 ++++++++++++++ aes/src/asm/aes256.asm | 287 ++++++++++++++++ aes/src/box.c | 683 ++++++++++++++++++++++++++++++++++++++ aes/src/box_aes.c | 331 ++++++++++++++++++ aes/src/c/aes128.c | 98 ++++++ aes/src/c/aes192.c | 133 ++++++++ aes/src/c/aes256.c | 161 +++++++++ aes/src/error.c | 251 ++++++++++++++ aes/src/padding.c | 88 +++++ aesxx/CMakeLists.txt | 13 + aesxx/include/aesxx/aes.hpp | 275 +++++++++++++++ aesxx/include/aesxx/algorithm.hpp | 13 + aesxx/include/aesxx/all.hpp | 15 + aesxx/include/aesxx/api.hpp | 174 ++++++++++ aesxx/include/aesxx/box.hpp | 207 ++++++++++++ aesxx/include/aesxx/data.hpp | 55 +++ aesxx/include/aesxx/debug.hpp | 174 ++++++++++ aesxx/include/aesxx/error.hpp | 104 ++++++ aesxx/include/aesxx/mode.hpp | 153 +++++++++ cxx/CMakeLists.txt | 13 - cxx/include/aesxx/aes.hpp | 275 --------------- cxx/include/aesxx/algorithm.hpp | 13 - cxx/include/aesxx/all.hpp | 15 - cxx/include/aesxx/api.hpp | 174 ---------- cxx/include/aesxx/box.hpp | 207 ------------ cxx/include/aesxx/data.hpp | 55 --- cxx/include/aesxx/debug.hpp | 174 ---------- cxx/include/aesxx/error.hpp | 104 ------ cxx/include/aesxx/mode.hpp | 153 --------- include/aes/aes.h | 541 ------------------------------ include/aes/algorithm.h | 23 -- include/aes/all.h | 21 -- include/aes/box.h | 81 ----- include/aes/box_aes.h | 21 -- include/aes/box_data.h | 153 --------- include/aes/data.h | 122 ------- include/aes/error.h | 96 ------ include/aes/mode.h | 166 --------- include/aes/padding.h | 38 --- include/aes/workarounds.h | 16 - src/aes.c | 384 --------------------- src/asm/aes128.asm | 203 ----------- src/asm/aes192.asm | 249 -------------- src/asm/aes256.asm | 287 ---------------- src/box.c | 683 -------------------------------------- src/box_aes.c | 331 ------------------ src/c/aes128.c | 98 ------ src/c/aes192.c | 133 -------- src/c/aes256.c | 161 --------- src/error.c | 251 -------------- src/padding.c | 88 ----- 66 files changed, 5359 insertions(+), 5358 deletions(-) create mode 100644 aes/CMakeLists.txt create mode 100644 aes/include/aes/aes.h create mode 100644 aes/include/aes/algorithm.h create mode 100644 aes/include/aes/all.h create mode 100644 aes/include/aes/box.h create mode 100644 aes/include/aes/box_aes.h create mode 100644 aes/include/aes/box_data.h create mode 100644 aes/include/aes/data.h create mode 100644 aes/include/aes/error.h create mode 100644 aes/include/aes/mode.h create mode 100644 aes/include/aes/padding.h create mode 100644 aes/include/aes/workarounds.h create mode 100644 aes/src/aes.c create mode 100644 aes/src/asm/aes128.asm create mode 100644 aes/src/asm/aes192.asm create mode 100644 aes/src/asm/aes256.asm create mode 100644 aes/src/box.c create mode 100644 aes/src/box_aes.c create mode 100644 aes/src/c/aes128.c create mode 100644 aes/src/c/aes192.c create mode 100644 aes/src/c/aes256.c create mode 100644 aes/src/error.c create mode 100644 aes/src/padding.c create mode 100644 aesxx/CMakeLists.txt create mode 100644 aesxx/include/aesxx/aes.hpp create mode 100644 aesxx/include/aesxx/algorithm.hpp create mode 100644 aesxx/include/aesxx/all.hpp create mode 100644 aesxx/include/aesxx/api.hpp create mode 100644 aesxx/include/aesxx/box.hpp create mode 100644 aesxx/include/aesxx/data.hpp create mode 100644 aesxx/include/aesxx/debug.hpp create mode 100644 aesxx/include/aesxx/error.hpp create mode 100644 aesxx/include/aesxx/mode.hpp delete mode 100644 cxx/CMakeLists.txt delete mode 100644 cxx/include/aesxx/aes.hpp delete mode 100644 cxx/include/aesxx/algorithm.hpp delete mode 100644 cxx/include/aesxx/all.hpp delete mode 100644 cxx/include/aesxx/api.hpp delete mode 100644 cxx/include/aesxx/box.hpp delete mode 100644 cxx/include/aesxx/data.hpp delete mode 100644 cxx/include/aesxx/debug.hpp delete mode 100644 cxx/include/aesxx/error.hpp delete mode 100644 cxx/include/aesxx/mode.hpp delete mode 100644 include/aes/aes.h delete mode 100644 include/aes/algorithm.h delete mode 100644 include/aes/all.h delete mode 100644 include/aes/box.h delete mode 100644 include/aes/box_aes.h delete mode 100644 include/aes/box_data.h delete mode 100644 include/aes/data.h delete mode 100644 include/aes/error.h delete mode 100644 include/aes/mode.h delete mode 100644 include/aes/padding.h delete mode 100644 include/aes/workarounds.h delete mode 100644 src/aes.c delete mode 100644 src/asm/aes128.asm delete mode 100644 src/asm/aes192.asm delete mode 100644 src/asm/aes256.asm delete mode 100644 src/box.c delete mode 100644 src/box_aes.c delete mode 100644 src/c/aes128.c delete mode 100644 src/c/aes192.c delete mode 100644 src/c/aes256.c delete mode 100644 src/error.c delete mode 100644 src/padding.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 6dc89d1..6ed976f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,35 +4,8 @@ project(aes_tools C CXX) include(cmake/common.cmake) -option(AES_TOOLS_ASM "Use the assembly language implementation instead of the one in C") - -file(GLOB_RECURSE aes_include "include/*.h") - -if(MSVC AND AES_TOOLS_ASM) - enable_language(ASM_MASM) - file(GLOB aes_src_c "src/*.c") - file(GLOB aes_src_asm "src/asm/*.asm") - set(aes_src ${aes_src_asm} ${aes_src_c}) - set_source_files_properties(${aes_src_asm} PROPERTIES COMPILE_FLAGS /safeseh) - # Setting CMAKE_ASM_MASM_FLAGS doesn't work: http://www.cmake.org/Bug/view.php?id=14711 -else() - file(GLOB_RECURSE aes_src "src/*.c") -endif() - -add_library(aes ${aes_src} ${aes_include}) -target_include_directories(aes PUBLIC include/) - -if(MSVC) - target_compile_definitions(aes PRIVATE _CRT_SECURE_NO_WARNINGS) -endif() - -if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) - target_compile_options(aes PUBLIC -mssse3 -maes) -endif() - -add_subdirectory(cxx) +add_subdirectory(aes) +add_subdirectory(aesxx) add_subdirectory(utils) -install(TARGETS aes ARCHIVE DESTINATION lib) -install(DIRECTORY include/aes DESTINATION include) install(FILES LICENSE.txt DESTINATION share) diff --git a/aes/CMakeLists.txt b/aes/CMakeLists.txt new file mode 100644 index 0000000..0ec262d --- /dev/null +++ b/aes/CMakeLists.txt @@ -0,0 +1,28 @@ +option(AES_TOOLS_ASM "Use the assembly language implementation instead of the one in C") + +file(GLOB_RECURSE aes_include "include/*.h") + +if(MSVC AND AES_TOOLS_ASM) + enable_language(ASM_MASM) + file(GLOB aes_src_c "src/*.c") + file(GLOB aes_src_asm "src/asm/*.asm") + set(aes_src ${aes_src_asm} ${aes_src_c}) + set_source_files_properties(${aes_src_asm} PROPERTIES COMPILE_FLAGS /safeseh) + # Setting CMAKE_ASM_MASM_FLAGS doesn't work: http://www.cmake.org/Bug/view.php?id=14711 +else() + file(GLOB_RECURSE aes_src "src/*.c") +endif() + +add_library(aes ${aes_src} ${aes_include}) +target_include_directories(aes PUBLIC include/) + +if(MSVC) + target_compile_definitions(aes PRIVATE _CRT_SECURE_NO_WARNINGS) +endif() + +if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) + target_compile_options(aes PUBLIC -mssse3 -maes) +endif() + +install(TARGETS aes ARCHIVE DESTINATION lib) +install(DIRECTORY include/aes DESTINATION include) diff --git a/aes/include/aes/aes.h b/aes/include/aes/aes.h new file mode 100644 index 0000000..1108235 --- /dev/null +++ b/aes/include/aes/aes.h @@ -0,0 +1,541 @@ +// Copyright (c) 2015 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#include "data.h" +#include "error.h" +#include "mode.h" + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef AES_Block128 AES_AES_Block; +typedef AES_AES_Block AES_AES128_Block; +typedef AES_AES_Block AES_AES192_Block; +typedef AES_AES_Block AES_AES256_Block; + +typedef struct +{ + AES_AES_Block key; +} +AES_AES128_Key; + +typedef struct +{ + AES_AES_Block hi; + AES_AES_Block lo; +} +AES_AES192_Key; + +typedef struct +{ + AES_AES_Block hi; + AES_AES_Block lo; +} +AES_AES256_Key; + +static __inline AES_AES_Block aes_AES_make_block( + int hi3, int hi2, int lo1, int lo0) +{ + return aes_make_block128(hi3, hi2, lo1, lo0); +} + +static __inline AES_AES128_Block aes_AES128_make_block( + int hi3, int hi2, int lo1, int lo0) +{ + return aes_AES_make_block(hi3, hi2, lo1, lo0); +} + +static __inline AES_AES192_Block aes_AES192_make_block( + int hi3, int hi2, int lo1, int lo0) +{ + return aes_AES_make_block(hi3, hi2, lo1, lo0); +} + +static __inline AES_AES256_Block aes_AES256_make_block( + int hi3, int hi2, int lo1, int lo0) +{ + return aes_AES_make_block(hi3, hi2, lo1, lo0); +} + +static __inline AES_AES128_Key aes_AES128_make_key( + int hi3, int hi2, int lo1, int lo0) +{ + AES_AES128_Key key; + key.key = aes_AES_make_block(hi3, hi2, lo1, lo0); + return key; +} + +static __inline AES_AES192_Key aes_AES192_make_key( + int hi5, int hi4, + int lo3, int lo2, int lo1, int lo0) +{ + AES_AES192_Key key; + key.hi = aes_AES_make_block( 0, 0, hi5, hi4); + key.lo = aes_AES_make_block(lo3, lo2, lo1, lo0); + return key; +} + +static __inline AES_AES256_Key aes_AES256_make_key( + int hi7, int hi6, int hi5, int hi4, + int lo3, int lo2, int lo1, int lo0) +{ + AES_AES256_Key key; + key.hi = aes_AES_make_block(hi7, hi6, hi5, hi4); + key.lo = aes_AES_make_block(lo3, lo2, lo1, lo0); + return key; +} + +typedef struct { char str[33]; } AES_AES_BlockString; +typedef AES_AES_BlockString AES_AES128_BlockString; +typedef AES_AES_BlockString AES_AES192_BlockString; +typedef AES_AES_BlockString AES_AES256_BlockString; + +typedef struct { char str[49]; } AES_AES_BlockMatrixString; +typedef AES_AES_BlockMatrixString AES_AES128_BlockMatrixString; +typedef AES_AES_BlockMatrixString AES_AES192_BlockMatrixString; +typedef AES_AES_BlockMatrixString AES_AES256_BlockMatrixString; + +AES_StatusCode aes_AES_format_block( + AES_AES_BlockString*, + const AES_AES_Block*, + AES_ErrorDetails*); + +static __inline AES_StatusCode aes_AES128_format_block( + AES_AES128_BlockString* dest, + const AES_AES128_Block* src, + AES_ErrorDetails* err_details) +{ + return aes_AES_format_block(dest, src, err_details); +} + +static __inline AES_StatusCode aes_AES192_format_block( + AES_AES192_BlockString* dest, + const AES_AES192_Block* src, + AES_ErrorDetails* err_details) +{ + return aes_AES_format_block(dest, src, err_details); +} + +static __inline AES_StatusCode aes_AES256_format_block( + AES_AES256_BlockString* dest, + const AES_AES256_Block* src, + AES_ErrorDetails* err_details) +{ + return aes_AES_format_block(dest, src, err_details); +} + +AES_StatusCode aes_AES_format_block_as_matrix( + AES_AES_BlockMatrixString*, + const AES_AES_Block*, + AES_ErrorDetails*); + +static __inline AES_StatusCode aes_AES128_format_block_as_matrix( + AES_AES128_BlockMatrixString* dest, + const AES_AES128_Block* src, + AES_ErrorDetails* err_details) +{ + return aes_AES_format_block_as_matrix(dest, src, err_details); +} + +static __inline AES_StatusCode aes_AES192_format_block_as_matrix( + AES_AES192_BlockMatrixString* dest, + const AES_AES192_Block* src, + AES_ErrorDetails* err_details) +{ + return aes_AES_format_block_as_matrix(dest, src, err_details); +} + +static __inline AES_StatusCode aes_AES256_format_block_as_matrix( + AES_AES256_BlockMatrixString* dest, + const AES_AES256_Block* src, + AES_ErrorDetails* err_details) +{ + return aes_AES_format_block_as_matrix(dest, src, err_details); +} + +AES_StatusCode aes_AES_print_block( + const AES_AES_Block*, + AES_ErrorDetails*); + +static __inline AES_StatusCode aes_AES128_print_block( + const AES_AES128_Block* block, + AES_ErrorDetails* err_details) +{ + return aes_AES_print_block(block, err_details); +} + +static __inline AES_StatusCode aes_AES192_print_block( + const AES_AES192_Block* block, + AES_ErrorDetails* err_details) +{ + return aes_AES_print_block(block, err_details); +} + +static __inline AES_StatusCode aes_AES256_print_block( + const AES_AES256_Block* block, + AES_ErrorDetails* err_details) +{ + return aes_AES_print_block(block, err_details); +} + +AES_StatusCode aes_AES_print_block_as_matrix( + const AES_AES_Block*, + AES_ErrorDetails*); + +static __inline AES_StatusCode aes_AES128_print_block_as_matrix( + const AES_AES128_Block* block, + AES_ErrorDetails* err_details) +{ + return aes_AES_print_block_as_matrix(block, err_details); +} + +static __inline AES_StatusCode aes_AES192_print_block_as_matrix( + const AES_AES192_Block* block, + AES_ErrorDetails* err_details) +{ + return aes_AES_print_block_as_matrix(block, err_details); +} + +static __inline AES_StatusCode aes_AES256_print_block_as_matrix( + const AES_AES256_Block* block, + AES_ErrorDetails* err_details) +{ + return aes_AES_print_block_as_matrix(block, err_details); +} + +AES_StatusCode aes_AES_parse_block( + AES_AES_Block* dest, + const char* src, + AES_ErrorDetails* err_details); + +static __inline AES_StatusCode aes_AES128_parse_block( + AES_AES128_Block* dest, + const char* src, + AES_ErrorDetails* err_details) +{ + return aes_AES_parse_block(dest, src, err_details); +} + +static __inline AES_StatusCode aes_AES192_parse_block( + AES_AES192_Block* dest, + const char* src, + AES_ErrorDetails* err_details) +{ + return aes_AES_parse_block(dest, src, err_details); +} + +static __inline AES_StatusCode aes_AES256_parse_block( + AES_AES256_Block* dest, + const char* src, + AES_ErrorDetails* err_details) +{ + return aes_AES_parse_block(dest, src, err_details); +} + +typedef struct { char str[33]; } AES_AES128_KeyString; +typedef struct { char str[49]; } AES_AES192_KeyString; +typedef struct { char str[65]; } AES_AES256_KeyString; + +AES_StatusCode aes_AES128_format_key( + AES_AES128_KeyString*, + const AES_AES128_Key*, + AES_ErrorDetails*); + +AES_StatusCode aes_AES192_format_key( + AES_AES192_KeyString*, + const AES_AES192_Key*, + AES_ErrorDetails*); + +AES_StatusCode aes_AES256_format_key( + AES_AES256_KeyString*, + const AES_AES256_Key*, + AES_ErrorDetails*); + +AES_StatusCode aes_AES128_print_key( + const AES_AES128_Key*, + AES_ErrorDetails*); + +AES_StatusCode aes_AES192_print_key( + const AES_AES192_Key*, + AES_ErrorDetails*); + +AES_StatusCode aes_AES256_print_key( + const AES_AES256_Key*, + AES_ErrorDetails*); + +AES_StatusCode aes_AES128_parse_key( + AES_AES128_Key* dest, + const char* src, + AES_ErrorDetails* err_details); + +AES_StatusCode aes_AES192_parse_key( + AES_AES192_Key* dest, + const char* src, + AES_ErrorDetails* err_details); + +AES_StatusCode aes_AES256_parse_key( + AES_AES256_Key* dest, + const char* src, + AES_ErrorDetails* err_details); + +typedef struct +{ + AES_AES_Block keys[11]; +} +AES_AES128_RoundKeys; + +typedef struct +{ + AES_AES_Block keys[13]; +} +AES_AES192_RoundKeys; + +typedef struct +{ + AES_AES_Block keys[15]; +} +AES_AES256_RoundKeys; + +void __fastcall aes_AES128_expand_key_( + AES_AES_Block key, + AES_AES128_RoundKeys* encryption_keys); + +void __fastcall aes_AES192_expand_key_( + AES_AES_Block key_lo, + AES_AES_Block key_hi, + AES_AES192_RoundKeys* encryption_keys); + +void __fastcall aes_AES256_expand_key_( + AES_AES_Block key_lo, + AES_AES_Block key_hi, + AES_AES256_RoundKeys* encryption_keys); + +void __fastcall aes_AES128_derive_decryption_keys_( + const AES_AES128_RoundKeys* encryption_keys, + AES_AES128_RoundKeys* decryption_keys); + +void __fastcall aes_AES192_derive_decryption_keys_( + const AES_AES192_RoundKeys* encryption_keys, + AES_AES192_RoundKeys* decryption_keys); + +void __fastcall aes_AES256_derive_decryption_keys_( + const AES_AES256_RoundKeys* encryption_keys, + AES_AES256_RoundKeys* decryption_keys); + +AES_AES_Block __fastcall aes_AES128_encrypt_block_( + AES_AES_Block plaintext, + const AES_AES128_RoundKeys*); + +AES_AES_Block __fastcall aes_AES192_encrypt_block_( + AES_AES_Block plaintext, + const AES_AES192_RoundKeys*); + +AES_AES_Block __fastcall aes_AES256_encrypt_block_( + AES_AES_Block plaintext, + const AES_AES256_RoundKeys*); + +AES_AES_Block __fastcall aes_AES128_decrypt_block_( + AES_AES_Block ciphertext, + const AES_AES128_RoundKeys*); + +AES_AES_Block __fastcall aes_AES192_decrypt_block_( + AES_AES_Block ciphertext, + const AES_AES192_RoundKeys*); + +AES_AES_Block __fastcall aes_AES256_decrypt_block_( + AES_AES_Block ciphertext, + const AES_AES256_RoundKeys*); + +static __inline AES_AES_Block __fastcall aes_AES_xor_blocks( + AES_AES_Block a, + AES_AES_Block b) +{ + return aes_xor_block128(a, b); +} + +static __inline AES_AES_Block __fastcall aes_AES128_xor_blocks( + AES_AES128_Block a, + AES_AES128_Block b) +{ + return aes_AES_xor_blocks(a, b); +} + +static __inline AES_AES_Block __fastcall aes_AES192_xor_blocks( + AES_AES192_Block a, + AES_AES192_Block b) +{ + return aes_AES_xor_blocks(a, b); +} + +static __inline AES_AES_Block __fastcall aes_AES256_xor_blocks( + AES_AES256_Block a, + AES_AES256_Block b) +{ + return aes_AES_xor_blocks(a, b); +} + +static __inline AES_AES_Block __fastcall aes_AES_inc_block( + AES_AES_Block block) +{ + block = aes_reverse_byte_order_block128(block); + block = aes_inc_block128(block); + return aes_reverse_byte_order_block128(block); +} + +static __inline AES_AES_Block __fastcall aes_AES128_inc_block( + AES_AES128_Block block) +{ + return aes_AES_inc_block(block); +} + +static __inline AES_AES_Block __fastcall aes_AES192_inc_block( + AES_AES192_Block block) +{ + return aes_AES_inc_block(block); +} + +static __inline AES_AES_Block __fastcall aes_AES256_inc_block( + AES_AES256_Block block) +{ + return aes_AES_inc_block(block); +} + +AES_ENCRYPT_BLOCK_ECB(AES128); +AES_DECRYPT_BLOCK_ECB(AES128); +AES_ENCRYPT_BLOCK_CBC(AES128); +AES_DECRYPT_BLOCK_CBC(AES128); +AES_ENCRYPT_BLOCK_CFB(AES128); +AES_DECRYPT_BLOCK_CFB(AES128); +AES_ENCRYPT_BLOCK_OFB(AES128); +AES_DECRYPT_BLOCK_OFB(AES128); +AES_ENCRYPT_BLOCK_CTR(AES128); +AES_DECRYPT_BLOCK_CTR(AES128); + +AES_ENCRYPT_BLOCK_ECB(AES192); +AES_DECRYPT_BLOCK_ECB(AES192); +AES_ENCRYPT_BLOCK_CBC(AES192); +AES_DECRYPT_BLOCK_CBC(AES192); +AES_ENCRYPT_BLOCK_CFB(AES192); +AES_DECRYPT_BLOCK_CFB(AES192); +AES_ENCRYPT_BLOCK_OFB(AES192); +AES_DECRYPT_BLOCK_OFB(AES192); +AES_ENCRYPT_BLOCK_CTR(AES192); +AES_DECRYPT_BLOCK_CTR(AES192); + +AES_ENCRYPT_BLOCK_ECB(AES256); +AES_DECRYPT_BLOCK_ECB(AES256); +AES_ENCRYPT_BLOCK_CBC(AES256); +AES_DECRYPT_BLOCK_CBC(AES256); +AES_ENCRYPT_BLOCK_CFB(AES256); +AES_DECRYPT_BLOCK_CFB(AES256); +AES_ENCRYPT_BLOCK_OFB(AES256); +AES_DECRYPT_BLOCK_OFB(AES256); +AES_ENCRYPT_BLOCK_CTR(AES256); +AES_DECRYPT_BLOCK_CTR(AES256); + +/** + * \brief Expands an AES-128 key into 10 encryption round keys. + * + * \param[in] key The AES-128 key. + * \param[out] encryption_keys The AES-128 encryption round keys. Must not be `NULL`. + */ +static __inline void __fastcall aes_AES128_expand_key( + const AES_AES128_Key* key, + AES_AES128_RoundKeys* encryption_keys) +{ + assert(encryption_keys); + + aes_AES128_expand_key_(key->key, encryption_keys); +} + +/** + * \brief Derives AES-128 decryption round keys from AES-128 encryption round keys. + * + * \param[in] encryption_keys The AES-128 encryption round keys. Must not be `NULL`. + * \param[out] decryption_keys The AES-128 decryption round keys. Must not be `NULL`. + */ +static __inline void __fastcall aes_AES128_derive_decryption_keys( + const AES_AES128_RoundKeys* encryption_keys, + AES_AES128_RoundKeys* decryption_keys) +{ + assert(encryption_keys); + assert(decryption_keys); + + aes_AES128_derive_decryption_keys_(encryption_keys, decryption_keys); +} + +/** + * \brief Expands an AES-192 key into 12 encryption round keys. + * + * \param[in] key The AES-192 key. + * \param[out] encryption_keys The AES-192 encryption round keys. Must not be `NULL`. + */ +static __inline void __fastcall aes_AES192_expand_key( + const AES_AES192_Key* key, + AES_AES192_RoundKeys* encryption_keys) +{ + assert(key); + assert(encryption_keys); + + aes_AES192_expand_key_(key->lo, key->hi, encryption_keys); +} + +/** + * \brief Derives AES-192 decryption round keys from AES-192 encryption round keys. + * + * \param[in] encryption_keys The AES-192 encryption round keys. Must not be `NULL`. + * \param[out] decryption_keys The AES-192 decryption round keys. Must not be `NULL`. + */ +static __inline void __fastcall aes_AES192_derive_decryption_keys( + const AES_AES192_RoundKeys* encryption_keys, + AES_AES192_RoundKeys* decryption_keys) +{ + assert(encryption_keys); + assert(decryption_keys); + + aes_AES192_derive_decryption_keys_(encryption_keys, decryption_keys); +} + +/** + * \brief Expands an AES-256 key into 14 encryption round keys. + * + * \param[in] key The AES-256 key. + * \param[out] encryption_keys The AES-256 encryption round keys. Must not be `NULL`. + */ +static __inline void __fastcall aes_AES256_expand_key( + const AES_AES256_Key* key, + AES_AES256_RoundKeys* encryption_keys) +{ + assert(key); + assert(encryption_keys); + + aes_AES256_expand_key_(key->lo, key->hi, encryption_keys); +} + +/** + * \brief Derives AES-256 decryption round keys from AES-256 encryption round keys. + * + * \param[in] encryption_keys The AES-256 encryption round keys. Must not be `NULL`. + * \param[out] decryption_keys The AES-256 decryption round keys. Must not be `NULL`. + */ +static __inline void __fastcall aes_AES256_derive_decryption_keys( + const AES_AES256_RoundKeys* encryption_keys, + AES_AES256_RoundKeys* decryption_keys) +{ + assert(encryption_keys); + assert(decryption_keys); + + aes_AES256_derive_decryption_keys_(encryption_keys, decryption_keys); +} + +#ifdef __cplusplus +} +#endif diff --git a/aes/include/aes/algorithm.h b/aes/include/aes/algorithm.h new file mode 100644 index 0000000..d88cf59 --- /dev/null +++ b/aes/include/aes/algorithm.h @@ -0,0 +1,23 @@ +// Copyright (c) 2015 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef enum +{ + AES_AES128, + AES_AES192, + AES_AES256, +} +AES_Algorithm; + +#ifdef __cplusplus +} +#endif diff --git a/aes/include/aes/all.h b/aes/include/aes/all.h new file mode 100644 index 0000000..ff27c18 --- /dev/null +++ b/aes/include/aes/all.h @@ -0,0 +1,21 @@ +// Copyright (c) 2015 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +/** + * \defgroup aes AES + */ + +#include "aes.h" +#include "algorithm.h" +#include "box.h" +#include "box_aes.h" +#include "box_data.h" +#include "data.h" +#include "error.h" +#include "mode.h" +#include "padding.h" +#include "workarounds.h" diff --git a/aes/include/aes/box.h b/aes/include/aes/box.h new file mode 100644 index 0000000..2051d3d --- /dev/null +++ b/aes/include/aes/box.h @@ -0,0 +1,81 @@ +// Copyright (c) 2015 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#include "algorithm.h" +#include "box_data.h" +#include "error.h" + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +AES_StatusCode aes_box_init( + AES_Box* box, + AES_Algorithm algorithm, + const AES_BoxKey* box_key, + AES_Mode mode, + const AES_BoxBlock* iv, + AES_ErrorDetails* err_details); + +AES_StatusCode aes_box_parse_key( + AES_BoxKey* dest, + AES_Algorithm algorithm, + const char* src, + AES_ErrorDetails* err_details); + +AES_StatusCode aes_box_parse_block( + AES_BoxBlock* dest, + AES_Algorithm algorithm, + const char* src, + AES_ErrorDetails* err_details); + +AES_StatusCode aes_box_format_key( + AES_BoxKeyString* dest, + AES_Algorithm algorithm, + const AES_BoxKey* src, + AES_ErrorDetails* err_details); + +AES_StatusCode aes_box_format_block( + AES_BoxBlockString* dest, + AES_Algorithm algorithm, + const AES_BoxBlock* src, + AES_ErrorDetails* err_details); + +AES_StatusCode aes_box_encrypt_block( + AES_Box* box, + const AES_BoxBlock* plaintext, + AES_BoxBlock* ciphertext, + AES_ErrorDetails* err_details); + +AES_StatusCode aes_box_decrypt_block( + AES_Box* box, + const AES_BoxBlock* ciphertext, + AES_BoxBlock* plaintext, + AES_ErrorDetails* err_details); + +AES_StatusCode aes_box_encrypt_buffer( + AES_Box* box, + const void* src, + size_t src_size, + void* dest, + size_t* dest_size, + AES_ErrorDetails* err_details); + +AES_StatusCode aes_box_decrypt_buffer( + AES_Box* box, + const void* src, + size_t src_size, + void* dest, + size_t* dest_size, + AES_ErrorDetails* err_details); + +#ifdef __cplusplus +} +#endif diff --git a/aes/include/aes/box_aes.h b/aes/include/aes/box_aes.h new file mode 100644 index 0000000..c92d883 --- /dev/null +++ b/aes/include/aes/box_aes.h @@ -0,0 +1,21 @@ +// Copyright (c) 2015 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#include "box_data.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern AES_BoxAlgorithmInterface aes_box_algorithm_aes128; +extern AES_BoxAlgorithmInterface aes_box_algorithm_aes192; +extern AES_BoxAlgorithmInterface aes_box_algorithm_aes256; + +#ifdef __cplusplus +} +#endif diff --git a/aes/include/aes/box_data.h b/aes/include/aes/box_data.h new file mode 100644 index 0000000..e2315eb --- /dev/null +++ b/aes/include/aes/box_data.h @@ -0,0 +1,153 @@ +// Copyright (c) 2015 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#include "aes.h" +#include "error.h" +#include "mode.h" + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef union +{ + AES_AES128_Key aes128_key; + AES_AES192_Key aes192_key; + AES_AES256_Key aes256_key; +} +AES_BoxKey; + +typedef union +{ + AES_AES128_RoundKeys aes128_encryption_keys; + AES_AES192_RoundKeys aes192_encryption_keys; + AES_AES256_RoundKeys aes256_encryption_keys; +} +AES_BoxEncryptionRoundKeys; + +typedef union +{ + AES_AES128_RoundKeys aes128_decryption_keys; + AES_AES192_RoundKeys aes192_decryption_keys; + AES_AES256_RoundKeys aes256_decryption_keys; +} +AES_BoxDecryptionRoundKeys; + +typedef union +{ + AES_AES128_KeyString aes128; + AES_AES192_KeyString aes192; + AES_AES256_KeyString aes256; +} +AES_BoxKeyString; + +typedef union +{ + AES_AES_Block aes_block; +} +AES_BoxBlock; + +typedef union +{ + AES_AES_BlockString aes; +} +AES_BoxBlockString; + +typedef AES_StatusCode (*AES_BoxCalculateRoundKeys)( + const AES_BoxKey* params, + AES_BoxEncryptionRoundKeys*, + AES_BoxDecryptionRoundKeys*, + AES_ErrorDetails* err_details); + +typedef AES_StatusCode (*AES_BoxParseBlock)( + AES_BoxBlock* dest, + const char* src, + AES_ErrorDetails* err_details); + +typedef AES_StatusCode (*AES_BoxParseKey)( + AES_BoxKey* dest, + const char* src, + AES_ErrorDetails* err_details); + +typedef AES_StatusCode (*AES_BoxFormatBlock)( + AES_BoxBlockString* dest, + const AES_BoxBlock* src, + AES_ErrorDetails* err_details); + +typedef AES_StatusCode (*AES_BoxFormatKey)( + AES_BoxKeyString* dest, + const AES_BoxKey* src, + AES_ErrorDetails* err_details); + +typedef AES_StatusCode (*AES_BoxEncryptBlock)( + const AES_BoxBlock* plaintext, + const AES_BoxEncryptionRoundKeys* params, + AES_BoxBlock* ciphertext, + AES_ErrorDetails* err_details); + +typedef AES_StatusCode (*AES_BoxDecryptBlock)( + const AES_BoxBlock* ciphertext, + const AES_BoxDecryptionRoundKeys* params, + AES_BoxBlock* plaintext, + AES_ErrorDetails* err_details); + +typedef AES_StatusCode (*AES_BoxXorBlock)( + AES_BoxBlock*, + const AES_BoxBlock*, + AES_ErrorDetails*); + +typedef AES_StatusCode (*AES_BoxIncBlock)( + AES_BoxBlock*, + AES_ErrorDetails*); + +typedef AES_StatusCode (*AES_BoxGetBlockSize)( + size_t*, + AES_ErrorDetails*); + +typedef AES_StatusCode (*AES_BoxStoreBlock)( + void*, + const AES_BoxBlock*, + AES_ErrorDetails*); + +typedef AES_StatusCode (*AES_BoxLoadBlock)( + AES_BoxBlock*, + const void*, + AES_ErrorDetails*); + +typedef struct +{ + AES_BoxCalculateRoundKeys calc_round_keys; + AES_BoxParseBlock parse_block; + AES_BoxParseKey parse_key; + AES_BoxFormatBlock format_block; + AES_BoxFormatKey format_key; + AES_BoxEncryptBlock encrypt_block; + AES_BoxDecryptBlock decrypt_block; + AES_BoxXorBlock xor_block; + AES_BoxIncBlock inc_block; + AES_BoxGetBlockSize get_block_size; + AES_BoxStoreBlock store_block; + AES_BoxLoadBlock load_block; +} +AES_BoxAlgorithmInterface; + +typedef struct +{ + const AES_BoxAlgorithmInterface* algorithm; + AES_BoxEncryptionRoundKeys encryption_keys; + AES_BoxDecryptionRoundKeys decryption_keys; + AES_Mode mode; + AES_BoxBlock iv; +} +AES_Box; + +#ifdef __cplusplus +} +#endif diff --git a/aes/include/aes/data.h b/aes/include/aes/data.h new file mode 100644 index 0000000..a441939 --- /dev/null +++ b/aes/include/aes/data.h @@ -0,0 +1,122 @@ +// Copyright (c) 2015 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * \brief Represents a 128-bit block. + */ +typedef __m128i AES_Block128; + +/** + * \brief Loads a 128-bit block from a memory location. + * + * \param[in] src The pointer to a memory location. Must not be `NULL`. + * + * \return The loaded 128-bit block. + */ +static __inline AES_Block128 aes_load_block128(const void* src) +{ + return _mm_loadu_si128((AES_Block128*) src); +} + +/** + * \brief Loads a 128-bit block from a 16-byte aligned memory location. + * + * \param[in] src The pointer to a 16-byte aligned memory location. Must not be `NULL`. + * + * \return The loaded 128-bit block. + */ +static __inline AES_Block128 aes_load_block128_aligned(const void* src) +{ + return _mm_load_si128((AES_Block128*) src); +} + +/** + * \brief Stores a 128-bit block in a memory location. + * + * \param[out] dest The pointer to a memory location. Must not be `NULL`. + * + * \param[in] block The block to be stored. + */ +static __inline void __fastcall aes_store_block128( + void* dest, + AES_Block128 block) +{ + _mm_storeu_si128((AES_Block128*) dest, block); +} + +/** + * \brief Stores a 128-bit block in a 16-byte aligned memory location. + * + * \param[out] dest The pointer to a 16-byte aligned memory location. Must not be `NULL`. + * + * \param[in] block The block to be stored. + */ +static __inline void __fastcall aes_store_block128_aligned( + void* dest, + AES_Block128 block) +{ + _mm_store_si128((AES_Block128*) dest, block); +} + +/** + * \brief XORs two 128-bit blocks. + * + * \param[in] a The first XOR operand. + * \param[in] b The second XOR operand. + * + * \return `a^b`. + */ +static __inline AES_Block128 __fastcall aes_xor_block128( + AES_Block128 a, + AES_Block128 b) +{ + return _mm_xor_si128(a, b); +} + +/** + * \brief Builds a 128-bit block from four 4-byte values. + * + * Builds a 128-bit block like this: + * + * * dest[127:96] = hi3 + * * dest[95:64] = hi2 + * * dest[63:32] = lo1 + * * dest[31:0] = lo0 + * + * \param[in] hi3 The most significant 4-byte value. + * \param[in] hi2 The more significant 4-byte value. + * \param[in] lo1 The less significant 4-byte value. + * \param[in] lo0 The least significant 4-byte value. + * + * \return The built 128-bit block. + */ +static __inline AES_Block128 __fastcall aes_make_block128(int hi3, int hi2, int lo1, int lo0) +{ + return _mm_set_epi32(hi3, hi2, lo1, lo0); +} + +static __inline AES_Block128 __fastcall aes_reverse_byte_order_block128(AES_Block128 block) +{ + return _mm_shuffle_epi8(block, aes_make_block128(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f)); +} + +static __inline AES_Block128 __fastcall aes_inc_block128(AES_Block128 x) +{ + return _mm_add_epi32(x, aes_make_block128(0, 0, 0, 1)); +} + +#ifdef __cplusplus +} +#endif diff --git a/aes/include/aes/error.h b/aes/include/aes/error.h new file mode 100644 index 0000000..e094f8a --- /dev/null +++ b/aes/include/aes/error.h @@ -0,0 +1,96 @@ +// Copyright (c) 2015 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef enum +{ + AES_SUCCESS, + AES_NULL_ARGUMENT_ERROR, + AES_PARSE_ERROR, + AES_INVALID_PKCS7_PADDING_ERROR, + AES_NOT_IMPLEMENTED_ERROR, + AES_MISSING_PADDING_ERROR, + AES_MEMORY_ALLOCATION_ERROR, +} +AES_StatusCode; + +static __inline int aes_is_error(AES_StatusCode ec) +{ + return ec != AES_SUCCESS; +} + +const char* aes_strerror(AES_StatusCode ec); + +#define AES_MAX_CALL_STACK_LENGTH 32 + +typedef struct +{ + AES_StatusCode ec; ///< Error code + + union + { + struct { char param_name[32]; } null_arg; + struct + { + char src[128]; + char what[32]; + } + parse_error; + struct { char what[128]; } not_implemented; + } + params; + + void* call_stack[AES_MAX_CALL_STACK_LENGTH]; + size_t call_stack_len; +} +AES_ErrorDetails; + +static __inline AES_StatusCode aes_get_error_code( + const AES_ErrorDetails* err_details) +{ + return err_details->ec; +} + +size_t aes_format_error( + const AES_ErrorDetails* err_details, + char* dest, + size_t dest_size); + +AES_StatusCode aes_success( + AES_ErrorDetails* err_details); + +AES_StatusCode aes_error_null_argument( + AES_ErrorDetails* err_details, + const char* param_name); + +AES_StatusCode aes_error_parse( + AES_ErrorDetails* err_details, + const char* src, + const char* what); + +AES_StatusCode aes_error_invalid_pkcs7_padding( + AES_ErrorDetails* err_details); + +AES_StatusCode aes_error_not_implemented( + AES_ErrorDetails* err_details, + const char* what); + +AES_StatusCode aes_error_missing_padding( + AES_ErrorDetails* err_details); + +AES_StatusCode aes_error_memory_allocation( + AES_ErrorDetails* err_details); + +#ifdef __cplusplus +} +#endif diff --git a/aes/include/aes/mode.h b/aes/include/aes/mode.h new file mode 100644 index 0000000..090628b --- /dev/null +++ b/aes/include/aes/mode.h @@ -0,0 +1,166 @@ +// Copyright (c) 2015 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef enum +{ + AES_ECB, + AES_CBC, + AES_CFB, + AES_OFB, + AES_CTR, +} +AES_Mode; + +#define AES_ENCRYPT_BLOCK_ECB(prefix) \ +static __inline AES_## prefix ##_Block __fastcall aes_## prefix ##_encrypt_block_ECB( \ + AES_## prefix ##_Block plaintext, \ + const AES_## prefix ##_RoundKeys* encryption_keys) \ +{ \ + assert(encryption_keys); \ +\ + return aes_## prefix ##_encrypt_block_(plaintext, encryption_keys); \ +} + +#define AES_DECRYPT_BLOCK_ECB(prefix) \ +static __inline AES_## prefix ##_Block __fastcall aes_## prefix ##_decrypt_block_ECB( \ + AES_## prefix ##_Block ciphertext, \ + const AES_## prefix ##_RoundKeys* decryption_keys) \ +{ \ + assert(decryption_keys); \ +\ + return aes_## prefix ##_decrypt_block_(ciphertext, decryption_keys); \ +} + +#define AES_ENCRYPT_BLOCK_CBC(prefix) \ +static __inline AES_## prefix ##_Block __fastcall aes_## prefix ##_encrypt_block_CBC( \ + AES_## prefix ##_Block plaintext, \ + const AES_## prefix ##_RoundKeys* encryption_keys, \ + AES_## prefix ##_Block init_vector, \ + AES_## prefix ##_Block* next_init_vector) \ +{ \ + assert(encryption_keys); \ + assert(next_init_vector); \ +\ + return *next_init_vector = aes_## prefix ##_encrypt_block_( \ + aes_## prefix ##_xor_blocks(plaintext, init_vector), encryption_keys); \ +} + +#define AES_DECRYPT_BLOCK_CBC(prefix) \ +static __inline AES_## prefix ##_Block __fastcall aes_## prefix ##_decrypt_block_CBC( \ + AES_## prefix ##_Block ciphertext, \ + const AES_## prefix ##_RoundKeys* decryption_keys, \ + AES_## prefix ##_Block init_vector, \ + AES_## prefix ##_Block* next_init_vector) \ +{ \ + assert(decryption_keys); \ + assert(next_init_vector); \ +\ + AES_## prefix ##_Block plaintext = aes_## prefix ##_xor_blocks( \ + aes_## prefix ##_decrypt_block_(ciphertext, decryption_keys), init_vector); \ + *next_init_vector = ciphertext; \ + return plaintext; \ +} + +#define AES_ENCRYPT_BLOCK_CFB(prefix) \ +static __inline AES_## prefix ##_Block __fastcall aes_## prefix ##_encrypt_block_CFB( \ + AES_## prefix ##_Block plaintext, \ + const AES_## prefix ##_RoundKeys* encryption_keys, \ + AES_## prefix ##_Block init_vector, \ + AES_## prefix ##_Block* next_init_vector) \ +{ \ + assert(encryption_keys); \ + assert(next_init_vector); \ +\ + return *next_init_vector = aes_## prefix ##_xor_blocks( \ + aes_## prefix ##_encrypt_block_(init_vector, encryption_keys), plaintext); \ +} + +#define AES_DECRYPT_BLOCK_CFB(prefix) \ +static __inline AES_## prefix ##_Block __fastcall aes_## prefix ##_decrypt_block_CFB( \ + AES_## prefix ##_Block ciphertext, \ + const AES_## prefix ##_RoundKeys* encryption_keys, \ + AES_## prefix ##_Block init_vector, \ + AES_## prefix ##_Block* next_init_vector) \ +{ \ + assert(encryption_keys); \ + assert(next_init_vector); \ +\ + AES_## prefix ##_Block plaintext = aes_## prefix ##_xor_blocks( \ + aes_## prefix ##_encrypt_block_(init_vector, encryption_keys), ciphertext); \ + *next_init_vector = ciphertext; \ + return plaintext; \ +} + +#define AES_ENCRYPT_BLOCK_OFB(prefix) \ +static __inline AES_## prefix ##_Block __fastcall aes_## prefix ##_encrypt_block_OFB( \ + AES_## prefix ##_Block plaintext, \ + const AES_## prefix ##_RoundKeys* encryption_keys, \ + AES_## prefix ##_Block init_vector, \ + AES_## prefix ##_Block* next_init_vector) \ +{ \ + assert(encryption_keys); \ + assert(next_init_vector); \ +\ + AES_## prefix ##_Block tmp = aes_## prefix ##_encrypt_block_(init_vector, encryption_keys); \ + *next_init_vector = tmp; \ + return aes_## prefix ##_xor_blocks(tmp, plaintext); \ +} + +#define AES_DECRYPT_BLOCK_OFB(prefix) \ +static __inline AES_## prefix ##_Block __fastcall aes_## prefix ##_decrypt_block_OFB( \ + AES_## prefix ##_Block ciphertext, \ + const AES_## prefix ##_RoundKeys* encryption_keys, \ + AES_## prefix ##_Block init_vector, \ + AES_## prefix ##_Block* next_init_vector) \ +{ \ + assert(encryption_keys); \ + assert(next_init_vector); \ +\ + return aes_## prefix ##_encrypt_block_OFB( \ + ciphertext, encryption_keys, init_vector, next_init_vector); \ +} + +#define AES_ENCRYPT_BLOCK_CTR(prefix) \ +static __inline AES_## prefix ##_Block __fastcall aes_## prefix ##_encrypt_block_CTR( \ + AES_## prefix ##_Block plaintext, \ + const AES_## prefix ##_RoundKeys* encryption_keys, \ + AES_## prefix ##_Block init_vector, \ + AES_## prefix ##_Block* next_init_vector) \ +{ \ + assert(encryption_keys); \ + assert(next_init_vector); \ +\ + AES_## prefix ##_Block ciphertext = aes_## prefix ##_xor_blocks( \ + plaintext, aes_## prefix ##_encrypt_block_(init_vector, encryption_keys)); \ + *next_init_vector = aes_## prefix ##_inc_block(init_vector); \ + return ciphertext; \ +} + +#define AES_DECRYPT_BLOCK_CTR(prefix) \ +static __inline AES_## prefix ##_Block __fastcall aes_## prefix ##_decrypt_block_CTR( \ + AES_## prefix ##_Block ciphertext, \ + const AES_## prefix ##_RoundKeys* encryption_keys, \ + AES_## prefix ##_Block init_vector, \ + AES_## prefix ##_Block* next_init_vector) \ +{ \ + assert(encryption_keys); \ + assert(next_init_vector); \ +\ + return aes_## prefix ##_encrypt_block_CTR( \ + ciphertext, encryption_keys, init_vector, next_init_vector); \ +} + +#ifdef __cplusplus +} +#endif diff --git a/aes/include/aes/padding.h b/aes/include/aes/padding.h new file mode 100644 index 0000000..ba316f5 --- /dev/null +++ b/aes/include/aes/padding.h @@ -0,0 +1,38 @@ +// Copyright (c) 2015 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#include "error.h" + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef enum +{ + AES_PADDING_PKCS7, +} +AES_PaddingMethod; + +AES_StatusCode aes_extract_padding_size( + AES_PaddingMethod, + const void* src, + size_t src_size, + size_t* padding_size, + AES_ErrorDetails*); + +AES_StatusCode aes_fill_with_padding( + AES_PaddingMethod, + void* dest, + size_t padding_size, + AES_ErrorDetails*); + +#ifdef __cplusplus +} +#endif diff --git a/aes/include/aes/workarounds.h b/aes/include/aes/workarounds.h new file mode 100644 index 0000000..914bd21 --- /dev/null +++ b/aes/include/aes/workarounds.h @@ -0,0 +1,16 @@ +// Copyright (c) 2016 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#if defined(_MSC_VER) +#define AES_ALIGN(t, x) __declspec(align(x)) t +#elif defined(__GNUC__) || defined(__MINGW32__) +#define AES_ALIGN(t, x) t __attribute__((aligned(x))) +#else +#warning "couldn't determine alignment attribute" +#endif + +#define AES_UNUSED_PARAMETER(...) (void) (__VA_ARGS__) diff --git a/aes/src/aes.c b/aes/src/aes.c new file mode 100644 index 0000000..1f7da13 --- /dev/null +++ b/aes/src/aes.c @@ -0,0 +1,384 @@ +/* + * Copyright (c) 2015 Egor Tensin + * This file is part of the "AES tools" project. + * For details, see https://github.com/egor-tensin/aes-tools. + * Distributed under the MIT License. + */ + +#include + +#include +#include +#include + +AES_StatusCode aes_AES_format_block( + AES_AES_BlockString* str, + const AES_AES_Block* block, + AES_ErrorDetails* err_details) +{ + assert(str); + assert(block); + + if (str == NULL) + return aes_error_null_argument(err_details, "str"); + if (block == NULL) + return aes_error_null_argument(err_details, "block"); + + char* cursor = str->str; + + AES_ALIGN(unsigned char, 16) bytes[16]; + aes_store_block128_aligned(bytes, *block); + + for (int i = 0; i < 16; ++i, cursor += 2) + sprintf(cursor, "%02x", bytes[i]); + + *cursor = '\0'; + return AES_SUCCESS; +} + +AES_StatusCode aes_AES_format_block_as_matrix( + AES_AES_BlockMatrixString* str, + const AES_AES_Block* block, + AES_ErrorDetails* err_details) +{ + assert(str); + assert(block); + + if (str == NULL) + return aes_error_null_argument(err_details, "str"); + if (block == NULL) + return aes_error_null_argument(err_details, "block"); + + char* cursor = str->str; + + AES_ALIGN(unsigned char, 16) bytes[4][4]; + aes_store_block128_aligned(bytes, *block); + + for (int i = 0; i < 4; ++i, cursor += 3) + { + for (int j = 0; j < 3; ++j, cursor += 3) + sprintf(cursor, "%02x ", bytes[j][i]); + sprintf(cursor, "%02x\n", bytes[3][i]); + } + + *cursor = '\0'; + return AES_SUCCESS; +} + +AES_StatusCode aes_AES_print_block( + const AES_AES_Block* block, + AES_ErrorDetails* err_details) +{ + assert(block); + + if (block == NULL) + return aes_error_null_argument(err_details, "block"); + + AES_StatusCode ec = AES_SUCCESS; + AES_AES_BlockString str; + + if (aes_is_error(ec = aes_AES_format_block(&str, block, err_details))) + return ec; + + printf("%s\n", str.str); + return ec; +} + +AES_StatusCode aes_AES_print_block_as_matrix( + const AES_AES_Block* block, + AES_ErrorDetails* err_details) +{ + assert(block); + + if (block == NULL) + return aes_error_null_argument(err_details, "block"); + + AES_StatusCode ec = AES_SUCCESS; + AES_AES_BlockMatrixString str; + + if (aes_is_error(ec = aes_AES_format_block_as_matrix(&str, block, err_details))) + return ec; + + printf("%s", str.str); + return ec; +} + +AES_StatusCode aes_AES_parse_block( + AES_AES_Block* dest, + const char* src, + AES_ErrorDetails* err_details) +{ + assert(dest); + assert(src); + + if (dest == NULL) + return aes_error_null_argument(err_details, "dest"); + if (src == NULL) + return aes_error_null_argument(err_details, "src"); + + const char* cursor = src; + + AES_ALIGN(unsigned char, 16) bytes[16]; + + for (int i = 0; i < 16; ++i) + { + int n; + unsigned int byte; + if (sscanf(cursor, "%2x%n", &byte, &n) != 1) + return aes_error_parse(err_details, src, "a 128-bit block"); + bytes[i] = (unsigned char) byte; + cursor += n; + } + + *dest = aes_load_block128_aligned(bytes); + return AES_SUCCESS; +} + +AES_StatusCode aes_AES128_format_key( + AES_AES128_KeyString* str, + const AES_AES128_Key* key, + AES_ErrorDetails* err_details) +{ + assert(str); + assert(key); + + if (str == NULL) + return aes_error_null_argument(err_details, "str"); + if (key == NULL) + return aes_error_null_argument(err_details, "key"); + + char* cursor = str->str; + + AES_ALIGN(unsigned char, 16) bytes[16]; + aes_store_block128_aligned(bytes, key->key); + + for (int i = 0; i < 16; ++i, cursor += 2) + sprintf(cursor, "%02x", bytes[i]); + + *cursor = '\0'; + return AES_SUCCESS; +} + +AES_StatusCode aes_AES192_format_key( + AES_AES192_KeyString* str, + const AES_AES192_Key* key, + AES_ErrorDetails* err_details) +{ + assert(str); + assert(key); + + if (str == NULL) + return aes_error_null_argument(err_details, "str"); + if (key == NULL) + return aes_error_null_argument(err_details, "key"); + + char* cursor = str->str; + + { + AES_ALIGN(unsigned char, 16) bytes[16]; + aes_store_block128_aligned(bytes, key->lo); + + for (int i = 0; i < 16; ++i, cursor += 2) + sprintf(cursor, "%02x", bytes[i]); + } + + { + AES_ALIGN(unsigned char, 16) bytes[16]; + aes_store_block128_aligned(bytes, key->hi); + + for (int i = 0; i < 8; ++i, cursor += 2) + sprintf(cursor, "%02x", bytes[i]); + } + + *cursor = '\0'; + return AES_SUCCESS; +} + +AES_StatusCode aes_AES256_format_key( + AES_AES256_KeyString* str, + const AES_AES256_Key* key, + AES_ErrorDetails* err_details) +{ + assert(str); + assert(key); + + if (str == NULL) + return aes_error_null_argument(err_details, "str"); + if (key == NULL) + return aes_error_null_argument(err_details, "key"); + + char* cursor = str->str; + + { + AES_ALIGN(unsigned char, 16) bytes[16]; + aes_store_block128_aligned(bytes, key->lo); + + for (int i = 0; i < 16; ++i, cursor += 2) + sprintf(cursor, "%02x", bytes[i]); + } + + { + AES_ALIGN(unsigned char, 16) bytes[16]; + aes_store_block128_aligned(bytes, key->hi); + + for (int i = 0; i < 16; ++i, cursor += 2) + sprintf(cursor, "%02x", bytes[i]); + } + + *cursor = '\0'; + return AES_SUCCESS; +} + +AES_StatusCode aes_AES128_print_key( + const AES_AES128_Key* key, + AES_ErrorDetails* err_details) +{ + return aes_AES_print_block(&key->key, err_details); +} + +AES_StatusCode aes_AES192_print_key( + const AES_AES192_Key* key, + AES_ErrorDetails* err_details) +{ + assert(key); + + if (key == NULL) + return aes_error_null_argument(err_details, "key"); + + AES_StatusCode ec = AES_SUCCESS; + AES_AES192_KeyString str; + + if (aes_is_error(ec = aes_AES192_format_key(&str, key, err_details))) + return ec; + + printf("%s\n", str.str); + return ec; +} + +AES_StatusCode aes_AES256_print_key( + const AES_AES256_Key* key, + AES_ErrorDetails* err_details) +{ + assert(key); + + if (key == NULL) + return aes_error_null_argument(err_details, "key"); + + AES_StatusCode ec = AES_SUCCESS; + AES_AES256_KeyString str; + + if (aes_is_error(ec = aes_AES256_format_key(&str, key, err_details))) + return ec; + + printf("%s\n", str.str); + return ec; +} + +AES_StatusCode aes_AES128_parse_key( + AES_AES128_Key* dest, + const char* src, + AES_ErrorDetails* err_details) +{ + return aes_AES_parse_block(&dest->key, src, err_details); +} + +AES_StatusCode aes_AES192_parse_key( + AES_AES192_Key* dest, + const char* src, + AES_ErrorDetails* err_details) +{ + assert(dest); + assert(src); + + if (dest == NULL) + return aes_error_null_argument(err_details, "dest"); + if (src == NULL) + return aes_error_null_argument(err_details, "src"); + + const char* cursor = src; + + { + AES_ALIGN(unsigned char, 16) bytes[16]; + + for (int i = 0; i < 16; ++i) + { + int n; + unsigned int byte; + if (sscanf(cursor, "%2x%n", &byte, &n) != 1) + return aes_error_parse(err_details, src, "a 192-bit block"); + bytes[i] = (unsigned char) byte; + cursor += n; + } + + dest->lo = aes_load_block128_aligned(bytes); + } + + { + AES_ALIGN(unsigned char, 16) bytes[16]; + + for (int i = 0; i < 8; ++i) + { + int n; + unsigned int byte; + if (sscanf(cursor, "%2x%n", &byte, &n) != 1) + return aes_error_parse(err_details, src, "a 192-bit block"); + bytes[i] = (unsigned char) byte; + cursor += n; + } + + memset(bytes + 8, 0x00, 8); + dest->hi = aes_load_block128_aligned(bytes); + } + + return AES_SUCCESS; +} + +AES_StatusCode aes_AES256_parse_key( + AES_AES256_Key* dest, + const char* src, + AES_ErrorDetails* err_details) +{ + assert(dest); + assert(src); + + if (dest == NULL) + return aes_error_null_argument(err_details, "dest"); + if (src == NULL) + return aes_error_null_argument(err_details, "src"); + + const char* cursor = src; + + { + AES_ALIGN(unsigned char, 16) bytes[16]; + + for (int i = 0; i < 16; ++i) + { + int n; + unsigned int byte; + if (sscanf(cursor, "%2x%n", &byte, &n) != 1) + return aes_error_parse(err_details, src, "a 256-bit block"); + bytes[i] = (unsigned char) byte; + cursor += n; + } + + dest->lo = aes_load_block128_aligned(bytes); + } + + { + AES_ALIGN(unsigned char, 16) bytes[16]; + + for (int i = 0; i < 16; ++i) + { + int n; + unsigned int byte; + if (sscanf(cursor, "%2x%n", &byte, &n) != 1) + return aes_error_parse(err_details, src, "a 256-bit block"); + bytes[i] = (unsigned char) byte; + cursor += n; + } + + dest->hi = aes_load_block128_aligned(bytes); + } + + return AES_SUCCESS; +} diff --git a/aes/src/asm/aes128.asm b/aes/src/asm/aes128.asm new file mode 100644 index 0000000..80be57c --- /dev/null +++ b/aes/src/asm/aes128.asm @@ -0,0 +1,203 @@ +; Copyright (c) 2015 Egor Tensin +; This file is part of the "AES tools" project. +; For details, see https://github.com/egor-tensin/aes-tools. +; Distributed under the MIT License. + +.586 +.xmm +.model flat + +.code + +@aes_AES128_encrypt_block_@20 proc + pxor xmm0, [ecx] + aesenc xmm0, [ecx + 10h] + aesenc xmm0, [ecx + 20h] + aesenc xmm0, [ecx + 30h] + aesenc xmm0, [ecx + 40h] + aesenc xmm0, [ecx + 50h] + aesenc xmm0, [ecx + 60h] + aesenc xmm0, [ecx + 70h] + aesenc xmm0, [ecx + 80h] + aesenc xmm0, [ecx + 90h] + aesenclast xmm0, [ecx + 0A0h] + ret +@aes_AES128_encrypt_block_@20 endp + +@aes_AES128_decrypt_block_@20 proc + pxor xmm0, [ecx] + aesdec xmm0, [ecx + 10h] + aesdec xmm0, [ecx + 20h] + aesdec xmm0, [ecx + 30h] + aesdec xmm0, [ecx + 40h] + aesdec xmm0, [ecx + 50h] + aesdec xmm0, [ecx + 60h] + aesdec xmm0, [ecx + 70h] + aesdec xmm0, [ecx + 80h] + aesdec xmm0, [ecx + 90h] + aesdeclast xmm0, [ecx + 0A0h] + ret +@aes_AES128_decrypt_block_@20 endp + +@aes_AES128_expand_key_@20 proc + ; A "word" (in terms of the FIPS 187 standard) is a 32-bit block. + ; Words are denoted by `w[N]`. + ; + ; A key schedule is composed of 10 "regular" keys and a dumb key for + ; the "whitening" step. + ; + ; A key schedule is thus composed of 44 "words". + ; The FIPS standard includes an algorithm to calculate these words via + ; a simple loop: + ; + ; i = 4 + ; while i < 44: + ; temp = w[i - 1] + ; if i % 4 == 0: + ; temp = SubWord(RotWord(temp))^Rcon + ; w[i] = w[i - 4]^temp + ; i = i + 1 + ; + ; The loop above may be unrolled like this: + ; + ; w[4] = SubWord(RotWord(w[3]))^Rcon^w[0] + ; w[5] = w[4]^w[1] + ; = SubWord(RotWord(w[3]))^Rcon^w[1]^w[0] + ; w[6] = w[5]^w[2] + ; = SubWord(RotWord(w[3]))^Rcon^w[2]^w[1]^w[0] + ; w[7] = w[6]^w[3] + ; = SubWord(RotWord(w[3]))^Rcon^w[3]^w[2]^w[1]^w[0] + ; w[8] = SubWord(RotWord(w[7]))^Rcon^w[4] + ; w[9] = w[8]^w[5] + ; = SubWord(RotWord(w[7]))^Rcon^w[5]^w[4] + ; w[10] = w[9]^w[6] + ; = SubWord(RotWord(w[7]))^Rcon^w[6]^w[5]^w[4] + ; w[11] = w[10]^w[7] + ; = SubWord(RotWord(w[7]))^Rcon^w[7]^w[6]^w[5]^w[4] + ; + ; ... and so on. + ; + ; The Intel AES-NI instruction set facilitates calculating SubWord + ; and RotWord using `aeskeygenassist`, which is used in this routine. + ; + ; Preconditions: + ; * xmm0[127:96] == w[3], + ; * xmm0[95:64] == w[2], + ; * xmm0[63:32] == w[1], + ; * xmm0[31:0] == w[0]. + + movdqa [ecx], xmm0 ; sets w[0], w[1], w[2], w[3] + add ecx, 10h ; ecx = &w[4] + + aeskeygenassist xmm5, xmm0, 01h ; xmm5[127:96] = RotWord(SubWord(w[3]))^Rcon + call aes128_keygen_assist ; sets w[4], w[5], w[6], w[7] + aeskeygenassist xmm5, xmm0, 02h ; xmm5[127:96] = RotWord(SubWord(w[7]))^Rcon + call aes128_keygen_assist ; sets w[8], w[9], w[10], w[11] + aeskeygenassist xmm5, xmm0, 04h ; xmm5[127:96] = RotWord(SubWord(w[11]))^Rcon + call aes128_keygen_assist ; sets w[12], w[13], w[14], w[15] + aeskeygenassist xmm5, xmm0, 08h ; xmm5[127:96] = RotWord(SubWord(w[15]))^Rcon + call aes128_keygen_assist ; sets w[16], w[17], w[18], w[19] + aeskeygenassist xmm5, xmm0, 10h ; xmm5[127:96] = RotWord(SubWord(w[19]))^Rcon + call aes128_keygen_assist ; sets w[20], w[21], w[22], w[23] + aeskeygenassist xmm5, xmm0, 20h ; xmm5[127:96] = RotWord(SubWord(w[23]))^Rcon + call aes128_keygen_assist ; sets w[24], w[25], w[26], w[27] + aeskeygenassist xmm5, xmm0, 40h ; xmm5[127:96] = RotWord(SubWord(w[27]))^Rcon + call aes128_keygen_assist ; sets w[28], w[29], w[30], w[31] + aeskeygenassist xmm5, xmm0, 80h ; xmm5[127:96] = RotWord(SubWord(w[31]))^Rcon + call aes128_keygen_assist ; sets w[32], w[33], w[34], w[35] + aeskeygenassist xmm5, xmm0, 1Bh ; xmm5[127:96] = RotWord(SubWord(w[35]))^Rcon + call aes128_keygen_assist ; sets w[36], w[37], w[38], w[39] + aeskeygenassist xmm5, xmm0, 36h ; xmm5[127:96] = RotWord(SubWord(w[39]))^Rcon + call aes128_keygen_assist ; sets w[40], w[41], w[42], w[43] + + ret + +aes128_keygen_assist: + ; Preconditions: + ; * xmm0[127:96] == w[i+3], + ; * xmm0[95:64] == w[i+2], + ; * xmm0[63:32] == w[i+1], + ; * xmm0[31:0] == w[i], + ; * xmm5[127:96] == RotWord(SubWord(w[i+3]))^Rcon, + ; * ecx == &w[i+4]. + ; + ; Postconditions: + ; * xmm0[127:96] == w[i+7] == RotWord(SubWord(w[i+3]))^Rcon^w[i+3]^w[i+2]^w[i+1]^w[i], + ; * xmm0[95:64] == w[i+6] == RotWord(SubWord(w[i+3]))^Rcon^w[i+2]^w[i+1]^w[i], + ; * xmm0[63:32] == w[i+5] == RotWord(SubWord(w[i+3]))^Rcon^w[i+1]^w[i], + ; * xmm0[31:0] == w[i+4] == RotWord(SubWord(w[i+3]))^Rcon^w[i], + ; * ecx == &w[i+8], + ; * the value in xmm4 is also modified. + + ; Calculate + ; w[i+3]^w[i+2]^w[i+1]^w[i], + ; w[i+2]^w[i+1]^w[i], + ; w[i+1]^w[i] and + ; w[i]. + movdqa xmm4, xmm0 ; xmm4 = xmm0 + pslldq xmm4, 4 ; xmm4 <<= 32 + pxor xmm0, xmm4 ; xmm0 ^= xmm4 + pslldq xmm4, 4 ; xmm4 <<= 32 + pxor xmm0, xmm4 ; xmm0 ^= xmm4 + pslldq xmm4, 4 ; xmm4 <<= 32 + pxor xmm0, xmm4 ; xmm0 ^= xmm4 + ; xmm0[127:96] == w[i+3]^w[i+2]^w[i+1]^w[i] + ; xmm0[95:64] == w[i+2]^w[i+1]^w[i] + ; xmm0[63:32] == w[i+1]^w[i] + ; xmm0[31:0] == w[i] + + ; Calculate + ; w[i+7] == RotWord(SubWord(w[i+3]))^Rcon^w[i+3]^w[i+2]^w[i+1]^w[i], + ; w[i+6] == RotWord(SubWord(w[i+3]))^Rcon^w[i+2]^w[i+1]^w[i], + ; w[i+5] == RotWord(SubWord(w[i+3]))^Rcon^w[i+1]^w[i] and + ; w[i+4] == RotWord(SubWord(w[i+3]))^Rcon^w[i]. + pshufd xmm4, xmm5, 0FFh ; xmm4[127:96] = xmm4[95:64] = xmm4[63:32] = xmm4[31:0] = xmm5[127:96] + pxor xmm0, xmm4 ; xmm0 ^= xmm4 + ; xmm0[127:96] == w[i+7] == RotWord(SubWord(w[i+3]))^Rcon^w[i+3]^w[i+2]^w[i+1]^w[i] + ; xmm0[95:64] == w[i+6] == RotWord(SubWord(w[i+3]))^Rcon^w[i+2]^w[i+1]^w[i] + ; xmm0[63:32] == w[i+5] == RotWord(SubWord(w[i+3]))^Rcon^w[i+1]^w[i] + ; xmm0[31:0] == w[i+4] == RotWord(SubWord(w[i+3]))^Rcon^w[i] + + ; Set w[i+4], w[i+5], w[i+6] and w[i+7]. + movdqa [ecx], xmm0 ; w[i+7] = RotWord(SubWord(w[i+3]))^Rcon^w[i+3]^w[i+2]^w[i+1]^w[i] + ; w[i+6] = RotWord(SubWord(w[i+3]))^Rcon^w[i+2]^w[i+1]^w[i] + ; w[i+5] = RotWord(SubWord(w[i+3]))^Rcon^w[i+1]^w[i] + ; w[i+4] = RotWord(SubWord(w[i+3]))^Rcon^w[i] + add ecx, 10h ; ecx = &w[i+8] + + ret +@aes_AES128_expand_key_@20 endp + +@aes_AES128_derive_decryption_keys_@8 proc + movdqa xmm5, [ecx] + movdqa xmm4, [ecx + 0A0h] + movdqa [edx], xmm4 + movdqa [edx + 0A0h], xmm5 + + aesimc xmm5, [ecx + 10h] + aesimc xmm4, [ecx + 90h] + movdqa [edx + 10h], xmm4 + movdqa [edx + 90h], xmm5 + + aesimc xmm5, [ecx + 20h] + aesimc xmm4, [ecx + 80h] + movdqa [edx + 20h], xmm4 + movdqa [edx + 80h], xmm5 + + aesimc xmm5, [ecx + 30h] + aesimc xmm4, [ecx + 70h] + movdqa [edx + 30h], xmm4 + movdqa [edx + 70h], xmm5 + + aesimc xmm5, [ecx + 40h] + aesimc xmm4, [ecx + 60h] + movdqa [edx + 40h], xmm4 + movdqa [edx + 60h], xmm5 + + aesimc xmm5, [ecx + 50h] + movdqa [edx + 50h], xmm5 + + ret +@aes_AES128_derive_decryption_keys_@8 endp + +end diff --git a/aes/src/asm/aes192.asm b/aes/src/asm/aes192.asm new file mode 100644 index 0000000..6a41243 --- /dev/null +++ b/aes/src/asm/aes192.asm @@ -0,0 +1,249 @@ +; Copyright (c) 2015 Egor Tensin +; This file is part of the "AES tools" project. +; For details, see https://github.com/egor-tensin/aes-tools. +; Distributed under the MIT License. + +.586 +.xmm +.model flat + +.code + +@aes_AES192_encrypt_block_@20 proc + pxor xmm0, [ecx] + aesenc xmm0, [ecx + 10h] + aesenc xmm0, [ecx + 20h] + aesenc xmm0, [ecx + 30h] + aesenc xmm0, [ecx + 40h] + aesenc xmm0, [ecx + 50h] + aesenc xmm0, [ecx + 60h] + aesenc xmm0, [ecx + 70h] + aesenc xmm0, [ecx + 80h] + aesenc xmm0, [ecx + 90h] + aesenc xmm0, [ecx + 0A0h] + aesenc xmm0, [ecx + 0B0h] + aesenclast xmm0, [ecx + 0C0h] + ret +@aes_AES192_encrypt_block_@20 endp + +@aes_AES192_decrypt_block_@20 proc + pxor xmm0, [ecx] + aesdec xmm0, [ecx + 10h] + aesdec xmm0, [ecx + 20h] + aesdec xmm0, [ecx + 30h] + aesdec xmm0, [ecx + 40h] + aesdec xmm0, [ecx + 50h] + aesdec xmm0, [ecx + 60h] + aesdec xmm0, [ecx + 70h] + aesdec xmm0, [ecx + 80h] + aesdec xmm0, [ecx + 90h] + aesdec xmm0, [ecx + 0A0h] + aesdec xmm0, [ecx + 0B0h] + aesdeclast xmm0, [ecx + 0C0h] + ret +@aes_AES192_decrypt_block_@20 endp + +@aes_AES192_expand_key_@36 proc + ; A "word" (in terms of the FIPS 187 standard) is a 32-bit block. + ; Words are denoted by `w[N]`. + ; + ; A key schedule is composed of 12 "regular" keys and a dumb key for + ; the "whitening" step. + ; + ; A key schedule is thus composed of 52 "words". + ; The FIPS standard includes an algorithm to calculate these words via + ; a simple loop: + ; + ; i = 6 + ; while i < 52: + ; temp = w[i - 1] + ; if i % 6 == 0: + ; temp = SubWord(RotWord(temp))^Rcon + ; w[i] = w[i - 6]^temp + ; i = i + 1 + ; + ; The loop above may be unrolled like this: + ; + ; w[6] = SubWord(RotWord(w[5]))^Rcon^w[0] + ; w[7] = w[6]^w[1] + ; = SubWord(RotWord(w[5]))^Rcon^w[0]^w[1] + ; w[8] = w[7]^w[2] + ; = SubWord(RotWord(w[5]))^Rcon^w[0]^w[1]^w[2] + ; w[9] = w[8]^w[3] + ; = SubWord(RotWord(w[5]))^Rcon^w[0]^w[1]^w[2]^w[3] + ; w[10] = w[9]^w[4] + ; = SubWord(RotWord(w[5]))^Rcon^w[0]^w[1]^w[2]^w[3]^w[4] + ; w[11] = w[10]^w[5] + ; = SubWord(RotWord(w[5]))^Rcon^w[0]^w[1]^w[2]^w[3]^w[4]^w[5] + ; w[12] = SubWord(RotWord(w[11]))^Rcon^w[6] + ; w[13] = w[12]^w[7] + ; = SubWord(RotWord(w[11]))^Rcon^w[6]^w[7] + ; w[14] = w[13]^w[8] + ; = SubWord(RotWord(w[11]))^Rcon^w[6]^w[7]^w[8] + ; w[15] = w[14]^w[9] + ; = SubWord(RotWord(w[11]))^Rcon^w[6]^w[7]^w[8]^w[9] + ; w[16] = w[15]^w[10] + ; = SubWord(RotWord(w[11]))^Rcon^w[6]^w[7]^w[8]^w[9]^w[10] + ; w[17] = w[16]^w[11] + ; = SubWort(RotWord(w[11]))^Rcon^w[6]^w[7]^w[8]^w[9]^w[10]^w[11] + ; + ; ... and so on. + ; + ; The Intel AES-NI instruction set facilitates calculating SubWord + ; and RotWord using `aeskeygenassist`, which is used in this routine. + ; + ; Preconditions: + ; * xmm1[63:32] == w[5], + ; * xmm1[31:0] == w[4], + ; * xmm0[127:96] == w[3], + ; * xmm0[95:64] == w[2], + ; * xmm0[63:32] == w[1], + ; * xmm0[31:0] == w[0]. + + movdqa [ecx], xmm0 ; sets w[0], w[1], w[2], w[3] + movq qword ptr [ecx + 10h], xmm1 ; sets w[4], w[5] + + aeskeygenassist xmm5, xmm1, 1 ; xmm5[63:32] = RotWord(SubWord(w[5]))^Rcon, + call aes192_keygen_assist + movdqu [ecx + 18h], xmm0 + movq qword ptr [ecx + 28h], xmm1 + aeskeygenassist xmm5, xmm1, 2 ; xmm5[63:32] = RotWord(SubWord(w[11]))^Rcon + call aes192_keygen_assist + movdqa [ecx + 30h], xmm0 + movq qword ptr [ecx + 40h], xmm1 + aeskeygenassist xmm5, xmm1, 4 ; xmm5[63:32] = RotWord(SubWord(w[17]))^Rcon + call aes192_keygen_assist + movdqu [ecx + 48h], xmm0 + movq qword ptr [ecx + 58h], xmm1 + aeskeygenassist xmm5, xmm1, 8 ; xmm5[63:32] = RotWord(SubWord(w[23]))^Rcon + call aes192_keygen_assist + movdqa [ecx + 60h], xmm0 + movq qword ptr [ecx + 70h], xmm1 + aeskeygenassist xmm5, xmm1, 10h ; xmm5[63:32] = RotWord(SubWord(w[29]))^Rcon + call aes192_keygen_assist + movdqu [ecx + 78h], xmm0 + movq qword ptr [ecx + 88h], xmm1 + aeskeygenassist xmm5, xmm1, 20h ; xmm5[63:32] = RotWord(SubWord(w[35]))^Rcon + call aes192_keygen_assist + movdqa [ecx + 90h], xmm0 + movq qword ptr [ecx + 0a0h], xmm1 + aeskeygenassist xmm5, xmm1, 40h ; xmm5[63:32] = RotWord(SubWord(w[41]))^Rcon + call aes192_keygen_assist + movdqu [ecx + 0a8h], xmm0 + movq qword ptr [ecx + 0b8h], xmm1 + aeskeygenassist xmm5, xmm1, 80h ; xmm5[63:32] = RotWord(SubWord(w[49]))^Rcon + call aes192_keygen_assist + movdqa [ecx + 0c0h], xmm0 + + ret + +aes192_keygen_assist: + ; Preconditions: + ; * xmm1[127:96] == 0, + ; * xmm1[95:64] == 0, + ; * xmm1[63:32] == w[i+5], + ; * xmm1[31:0] == w[i+4], + ; * xmm0[127:96] == w[i+3], + ; * xmm0[95:64] == w[i+2], + ; * xmm0[63:32] == w[i+1], + ; * xmm0[31:0] == w[i], + ; * xmm5[63:32] == RotWord(SubWord(w[i+5]))^Rcon. + ; + ; Postconditions: + ; * xmm1[127:96] == 0, + ; * xmm1[95:64] == 0, + ; * xmm1[63:32] == w[i+11] == RotWord(SubWord(w[i+5]))^Rcon^w[i+5]^w[i+4]^w[i+3]^w[i+2]^w[i+1]^w[i], + ; * xmm1[31:0] == w[i+10] == RotWord(SubWord(w[i+5]))^Rcon^w[i+4]^w[i+3]^w[i+2]^w[i+1]^w[i], + ; * xmm0[127:96] == w[i+9] == RotWord(SubWord(w[i+5]))^Rcon^w[i+3]^w[i+2]^w[i+1]^w[i], + ; * xmm0[95:64] == w[i+8] == RotWord(SubWord(w[i+5]))^Rcon^w[i+2]^w[i+1]^w[i], + ; * xmm0[63:32] == w[i+7] == RotWord(SubWord(w[i+5]))^Rcon^w[i+1]^w[i], + ; * xmm0[31:0] == w[i+6] == RotWord(SubWord(w[i+5]))^Rcon^w[i], + ; * the value in xmm4 is also modified. + + ; Calculate + ; w[i+3]^w[i+2]^w[i+1]^w[i], + ; w[i+2]^w[i+1]^w[i], + ; w[i+1]^w[i] and + ; w[i]. + movdqa xmm4, xmm0 ; xmm4 = xmm0 + pslldq xmm4, 4 ; xmm4 <<= 32 + pxor xmm0, xmm4 ; xmm0 ^= xmm4 + pslldq xmm4, 4 ; xmm4 <<= 32 + pxor xmm0, xmm4 ; xmm0 ^= xmm4 + pslldq xmm4, 4 ; xmm4 <<= 32 + pxor xmm0, xmm4 ; xmm0 ^= xmm4 + ; xmm0[127:96] == w[i+3]^w[i+2]^w[i+1]^w[i] + ; xmm0[95:64] == w[i+2]^w[i+1]^w[i] + ; xmm0[63:32] == w[i+1]^w[i] + ; xmm0[31:0] == w[i] + + ; Calculate + ; w[i+9] == RotWord(SubWord(w[i+5]))^Rcon^w[i+3]^w[i+2]^w[i+1]^w[i], + ; w[i+8] == RotWord(SubWord(w[i+5]))^Rcon^w[i+2]^w[i+1]^w[i], + ; w[i+7] == RotWord(SubWord(w[i+5]))^Rcon^w[i+1]^w[i] and + ; w[i+6] == RotWord(SubWord(w[i+5]))^Rcon^w[i]. + pshufd xmm4, xmm5, 55h ; xmm4[127:96] = xmm4[95:64] = xmm4[63:32] = xmm4[31:0] = xmm5[63:32] + pxor xmm0, xmm4 ; xmm0 ^= xmm4 + ; xmm0[127:96] == w[i+9] == RotWord(SubWord(w[i+5]))^Rcon^w[i+3]^w[i+2]^w[i+1]^w[i] + ; xmm0[95:64] == w[i+8] == RotWord(SubWord(w[i+5]))^Rcon^w[i+2]^w[i+1]^w[i] + ; xmm0[63:32] == w[i+7] == RotWord(SubWord(w[i+5]))^Rcon^w[i+1]^w[i] + ; xmm0[31:0] == w[i+6] == RotWord(SubWord(w[i+5]))^Rcon^w[i] + + ; Calculate + ; w[i+5]^w[i+4], + ; w[i+4]. + pshufd xmm4, xmm1, 0F3h ; xmm4 = xmm1[31:0] << 32 + pxor xmm1, xmm4 ; xmm1 ^= xmm5 + ; xmm1[63:32] == w[i+5]^w[i+4] + ; xmm1[31:0] == w[i+4] + + ; Calculate + ; w[i+10] == RotWord(SubWord(w[i+5]))^Rcon^w[i+5]^w[i+4]^w[i+3]^w[i+2]^w[i+1]^w[i], + ; w[i+11] == RotWord(SubWord(w[i+5]))^Rcon^w[i+4]^w[i+3]^w[i+2]^w[i+1]^w[i]. + pshufd xmm4, xmm0, 0FFh ; xmm4[127:96] = xmm4[95:64] = xmm4[63:32] = xmm4[31:0] = xmm0[127:96] + psrldq xmm4, 8 ; xmm4 >>= 64 + pxor xmm1, xmm4 ; xmm1 ^= xmm4 + ; xmm1[63:32] == w[i+11] == RotWord(SubWord(w[i+5]))^Rcon^w[i+5]^w[i+4]^w[i+3]^w[i+2]^w[i+1]^w[i] + ; xmm1[31:0] == w[i+10] == RotWord(SubWord(w[i+5]))^Rcon^w[i+4]^w[i+3]^w[i+2]^w[i+1]^w[i] + + ret +@aes_AES192_expand_key_@36 endp + +@aes_AES192_derive_decryption_keys_@8 proc + movdqa xmm5, [ecx] + movdqa xmm4, [ecx + 0C0h] + movdqa [edx], xmm4 + movdqa [edx + 0C0h], xmm5 + + aesimc xmm5, [ecx + 10h] + aesimc xmm4, [ecx + 0B0h] + movdqa [edx + 10h], xmm4 + movdqa [edx + 0B0h], xmm5 + + aesimc xmm5, [ecx + 20h] + aesimc xmm4, [ecx + 0A0h] + movdqa [edx + 20h], xmm4 + movdqa [edx + 0A0h], xmm5 + + aesimc xmm5, [ecx + 30h] + aesimc xmm4, [ecx + 90h] + movdqa [edx + 30h], xmm4 + movdqa [edx + 90h], xmm5 + + aesimc xmm5, [ecx + 40h] + aesimc xmm4, [ecx + 80h] + movdqa [edx + 40h], xmm4 + movdqa [edx + 80h], xmm5 + + aesimc xmm5, [ecx + 50h] + aesimc xmm4, [ecx + 70h] + movdqa [edx + 50h], xmm4 + movdqa [edx + 70h], xmm5 + + aesimc xmm5, [ecx + 60h] + movdqa [edx + 60h], xmm5 + + ret +@aes_AES192_derive_decryption_keys_@8 endp + +end diff --git a/aes/src/asm/aes256.asm b/aes/src/asm/aes256.asm new file mode 100644 index 0000000..82f5f6f --- /dev/null +++ b/aes/src/asm/aes256.asm @@ -0,0 +1,287 @@ +; Copyright (c) 2015 Egor Tensin +; This file is part of the "AES tools" project. +; For details, see https://github.com/egor-tensin/aes-tools. +; Distributed under the MIT License. + +.586 +.xmm +.model flat + +.code + +@aes_AES256_encrypt_block_@20 proc + pxor xmm0, [ecx] + aesenc xmm0, [ecx + 10h] + aesenc xmm0, [ecx + 20h] + aesenc xmm0, [ecx + 30h] + aesenc xmm0, [ecx + 40h] + aesenc xmm0, [ecx + 50h] + aesenc xmm0, [ecx + 60h] + aesenc xmm0, [ecx + 70h] + aesenc xmm0, [ecx + 80h] + aesenc xmm0, [ecx + 90h] + aesenc xmm0, [ecx + 0A0h] + aesenc xmm0, [ecx + 0B0h] + aesenc xmm0, [ecx + 0C0h] + aesenc xmm0, [ecx + 0D0h] + aesenclast xmm0, [ecx + 0E0h] + ret +@aes_AES256_encrypt_block_@20 endp + +@aes_AES256_decrypt_block_@20 proc + pxor xmm0, [ecx] + aesdec xmm0, [ecx + 10h] + aesdec xmm0, [ecx + 20h] + aesdec xmm0, [ecx + 30h] + aesdec xmm0, [ecx + 40h] + aesdec xmm0, [ecx + 50h] + aesdec xmm0, [ecx + 60h] + aesdec xmm0, [ecx + 70h] + aesdec xmm0, [ecx + 80h] + aesdec xmm0, [ecx + 90h] + aesdec xmm0, [ecx + 0A0h] + aesdec xmm0, [ecx + 0B0h] + aesdec xmm0, [ecx + 0C0h] + aesdec xmm0, [ecx + 0D0h] + aesdeclast xmm0, [ecx + 0E0h] + ret +@aes_AES256_decrypt_block_@20 endp + +@aes_AES256_expand_key_@36 proc + ; A "word" (in terms of the FIPS 187 standard) is a 32-bit block. + ; Words are denoted by `w[N]`. + ; + ; A key schedule is composed of 14 "regular" keys and a dumb key for + ; the "whitening" step. + ; + ; A key schedule is thus composed of 60 "words". + ; The FIPS standard includes an algorithm to calculate these words via + ; a simple loop: + ; + ; i = 8 + ; while i < 60: + ; temp = w[i - 1] + ; if i % 8 == 0: + ; temp = SubWord(RotWord(temp))^Rcon + ; elif i % 8 == 4: + ; temp = SubWord(temp) + ; w[i] = w[i - 8]^temp + ; i = i + 1 + ; + ; The loop above may be unrolled like this: + ; + ; w[8] = SubWord(RotWord(w[7]))^Rcon^w[0] + ; w[9] = w[8]^w[1] + ; = SubWord(RotWord(w[7]))^Rcon^w[1]^w[0] + ; w[10] = w[9]^w[2] + ; = SubWord(RotWord(w[7]))^Rcon^w[2]^w[1]^w[0] + ; w[11] = w[10]^w[3] + ; = SubWord(RotWord(w[7]))^Rcon^w[3]^w[2]^w[1]^w[0] + ; w[12] = SubWord(w[11])^w[4] + ; w[13] = w[12]^w[5] + ; = SubWord(w[11])^w[5]^w[4] + ; w[14] = w[13]^w[6] + ; = SubWord(w[11])^w[6]^w[5]^w[4] + ; w[15] = w[14]^w[7] + ; = SubWord(w[11])^w[7]^w[6]^w[5]^w[4] + ; w[16] = SubWord(RotWord(w[15]))^Rcon^w[8] + ; w[17] = w[16]^w[9] + ; = SubWord(RotWord(w[15]))^Rcon^w[9]^w[8] + ; w[18] = w[17]^w[10] + ; = SubWord(RotWord(w[15]))^Rcon^w[10]^w[9]^w[8] + ; w[19] = w[18]^w[11] + ; = SubWord(RotWord(w[15]))^Rcon^w[11]^w[10]^w[9]^w[8] + ; w[20] = SubWord(w[19])^w[12] + ; w[21] = w[20]^w[13] + ; = SubWord(w[19])^w[13]^w[12] + ; w[22] = w[21]^w[14] + ; = SubWord(w[19])^w[14]^w[13]^w[12] + ; w[23] = w[22]^w[15] + ; = SubWord(w[19])^w[15]^w[14]^w[13]^w[12] + ; + ; ... and so on. + ; + ; The Intel AES-NI instruction set facilitates calculating SubWord + ; and RotWord using `aeskeygenassist`, which is used in this routine. + ; + ; Preconditions: + ; * xmm1[127:96] == w[7], + ; * xmm1[95:64] == w[6], + ; * xmm1[63:32] == w[5], + ; * xmm1[31:0] == w[4], + ; * xmm0[127:96] == w[3], + ; * xmm0[95:64] == w[2], + ; * xmm0[63:32] == w[1], + ; * xmm0[31:0] == w[0]. + + movdqa [ecx], xmm0 ; sets w[0], w[1], w[2], w[3] + movdqa [ecx + 10h], xmm1 ; sets w[4], w[5], w[6], w[7] + lea ecx, [ecx + 20h] ; ecx = &w[8] + + aeskeygenassist xmm5, xmm1, 1h ; xmm5[127:96] = RotWord(SubWord(w[7]))^Rcon + pshufd xmm5, xmm5, 0FFh ; xmm5[95:64] = xmm5[63:32] = xmm5[31:0] = xmm5[127:96] + call aes256_keygen_assist ; sets w[8], w[9], w[10], w[11] + + aeskeygenassist xmm5, xmm1, 0 ; xmm5[95:64] = SubWord(w[11]) + pshufd xmm5, xmm5, 0AAh ; xmm5[127:96] = xmm5[63:32] = xmm5[31:0] = xmm5[95:64] + call aes256_keygen_assist ; sets w[12], w[13], w[14], w[15] + + aeskeygenassist xmm5, xmm1, 2h ; xmm5[127:96] = RotWord(SubWord(w[15]))^Rcon + pshufd xmm5, xmm5, 0FFh ; xmm5[95:64] = xmm5[63:32] = xmm5[31:0] = xmm5[127:96] + call aes256_keygen_assist ; sets w[16], w[17], w[18], w[19] + + aeskeygenassist xmm5, xmm1, 0 ; xmm5[95:64] = SubWord(w[19]) + pshufd xmm5, xmm5, 0AAh ; xmm5[127:96] = xmm5[63:32] = xmm5[31:0] = xmm5[95:64] + call aes256_keygen_assist ; sets w[20], w[21], w[22], w[23] + + aeskeygenassist xmm5, xmm1, 4h ; xmm5[127:96] = RotWord(SubWord(w[23]))^Rcon + pshufd xmm5, xmm5, 0FFh ; xmm5[95:64] = xmm5[63:32] = xmm5[31:0] = xmm5[127:96] + call aes256_keygen_assist ; sets w[24], w[25], w[26], w[27] + + aeskeygenassist xmm5, xmm1, 0 ; xmm5[95:64] = SubWord(w[27]) + pshufd xmm5, xmm5, 0AAh ; xmm5[127:96] = xmm5[63:32] = xmm5[31:0] = xmm5[95:64] + call aes256_keygen_assist ; sets w[28], w[29], w[30], w[31] + + aeskeygenassist xmm5, xmm1, 8h ; xmm5[127:96] = RotWord(SubWord(w[31]))^Rcon + pshufd xmm5, xmm5, 0FFh ; xmm5[95:64] = xmm5[63:32] = xmm5[31:0] = xmm5[127:96] + call aes256_keygen_assist ; sets w[32], w[33], w[34], w[35] + + aeskeygenassist xmm5, xmm1, 0 ; xmm5[95:64] = SubWord(w[35]) + pshufd xmm5, xmm5, 0AAh ; xmm5[127:96] = xmm5[63:32] = xmm5[31:0] = xmm5[95:64] + call aes256_keygen_assist ; sets w[36], w[37], w[38], w[39] + + aeskeygenassist xmm5, xmm1, 10h ; xmm5[127:96] = RotWord(SubWord(w[39]))^Rcon + pshufd xmm5, xmm5, 0FFh ; xmm5[95:64] = xmm5[63:32] = xmm5[31:0] = xmm5[127:96] + call aes256_keygen_assist ; sets w[40], w[41], w[42], w[43] + + aeskeygenassist xmm5, xmm1, 0 ; xmm5[95:64] = SubWord(w[43]) + pshufd xmm5, xmm5, 0AAh ; xmm5[127:96] = xmm5[63:32] = xmm5[31:0] = xmm5[95:64] + call aes256_keygen_assist ; sets w[44], w[45], w[46], w[47] + + aeskeygenassist xmm5, xmm1, 20h ; xmm5[127:96] = RotWord(SubWord(w[47]))^Rcon + pshufd xmm5, xmm5, 0FFh ; xmm5[95:64] = xmm5[63:32] = xmm5[31:0] = xmm5[127:96] + call aes256_keygen_assist ; sets w[48], w[49], w[50], w[51] + + aeskeygenassist xmm5, xmm1, 0 ; xmm5[95:64] = SubWord(w[51]) + pshufd xmm5, xmm5, 0AAh ; xmm5[127:96] = xmm5[63:32] = xmm5[31:0] = xmm5[95:64] + call aes256_keygen_assist ; sets w[52], w[53], w[54], w[55] + + aeskeygenassist xmm5, xmm1, 40h ; xmm5[127:96] = RotWord(SubWord(w[55]))^Rcon + pshufd xmm5, xmm5, 0FFh ; xmm5[95:64] = xmm5[63:32] = xmm5[31:0] = xmm5[127:96] + call aes256_keygen_assist ; sets w[56], w[57], w[58], w[59] + + ret + +aes256_keygen_assist: + ; Preconditions: + ; * xmm1[127:96] == w[i+7], + ; * xmm1[95:64] == w[i+6], + ; * xmm1[63:32] == w[i+5], + ; * xmm1[31:0] == w[i+4], + ; * xmm0[127:96] == w[i+3], + ; * xmm0[95:64] == w[i+2], + ; * xmm0[63:32] == w[i+1], + ; * xmm0[31:0] == w[i], + ; * xmm5[127:96] == xmm5[95:64] == xmm5[63:32] == xmm5[31:0] == HWGEN, + ; where HWGEN is either RotWord(SubWord(w[i+7]))^Rcon or SubWord(w[i+7]), + ; depending on the number of the round being processed, + ; * ecx == &w[i+8]. + ; + ; Postconditions: + ; * xmm1[127:96] == w[i+11] == HWGEN^w[i+3]^w[i+2]^w[i+1]^w[i], + ; * xmm1[95:64] == w[i+10] == HWGEN^w[i+2]^w[i+1]^w[i], + ; * xmm1[63:32] == w[i+9] == HWGEN^w[i+1]^w[i], + ; * xmm1[31:0] == w[i+8] == HWGEN^w[i], + ; * xmm0[127:96] == w[i+7], + ; * xmm0[95:64] == w[i+6], + ; * xmm0[63:32] == w[i+5], + ; * xmm0[31:0] == w[i+4], + ; * ecx == &w[i+12], + ; * the value in xmm4 is also modified. + + ; Calculate + ; w[i+3]^w[i+2]^w[i+1]^w[i], + ; w[i+2]^w[i+1]^w[i], + ; w[i+1]^w[i] and + ; w[i]. + movdqa xmm4, xmm0 ; xmm4 = xmm0 + pslldq xmm4, 4 ; xmm4 <<= 32 + pxor xmm0, xmm4 ; xmm0 ^= xmm4 + pslldq xmm4, 4 ; xmm4 <<= 32 + pxor xmm0, xmm4 ; xmm0 ^= xmm4 + pslldq xmm4, 4 ; xmm4 <<= 32 + pxor xmm0, xmm4 ; xmm0 ^= xmm4 + ; xmm0[127:96] == w[i+3]^w[i+2]^w[i+1]^w[i] + ; xmm0[95:64] == w[i+2]^w[i+1]^w[i] + ; xmm0[63:32] == w[i+1]^w[i] + ; xmm0[31:0] == w[i] + + ; Calculate + ; HWGEN^w[i+3]^w[i+2]^w[i+1]^w[i], + ; HWGEN^w[i+2]^w[i+1]^w[i], + ; HWGEN^w[i+1]^w[i] and + ; HWGEN^w[i]. + pxor xmm0, xmm5 ; xmm0 ^= xmm5 + ; xmm0[127:96] == w[i+11] == HWGEN^w[i+3]^w[i+2]^w[i+1]^w[i] + ; xmm0[95:64] == w[i+10] == HWGEN^w[i+2]^w[i+1]^w[i] + ; xmm0[63:32] == w[i+9] == HWGEN^w[i+1]^w[i] + ; xmm0[31:0] == w[i+8] == HWGEN^w[i] + + ; Set w[i+8], w[i+9], w[i+10] and w[i+11]. + movdqa [ecx], xmm0 ; w[i+8] = HWGEN^w[i] + ; w[i+9] = HWGEN^w[i+1]^w[i] + ; w[i+10] = HWGEN^w[i+2]^w[i+1]^w[i] + ; w[i+11] = HWGEN^w[i+3]^w[i+2]^w[i+1]^w[i] + add ecx, 10h ; ecx = &w[i+12] + + ; Swap the values in xmm0 and xmm1. + pxor xmm0, xmm1 + pxor xmm1, xmm0 + pxor xmm0, xmm1 + + ret +@aes_AES256_expand_key_@36 endp + +@aes_AES256_derive_decryption_keys_@8 proc + movdqa xmm5, [ecx] + movdqa xmm4, [ecx + 0E0h] + movdqa [edx], xmm4 + movdqa [edx + 0E0h], xmm5 + + aesimc xmm5, [ecx + 10h] + aesimc xmm4, [ecx + 0D0h] + movdqa [edx + 10h], xmm4 + movdqa [edx + 0D0h], xmm5 + + aesimc xmm5, [ecx + 20h] + aesimc xmm4, [ecx + 0C0h] + movdqa [edx + 20h], xmm4 + movdqa [edx + 0C0h], xmm5 + + aesimc xmm5, [ecx + 30h] + aesimc xmm4, [ecx + 0B0h] + movdqa [edx + 30h], xmm4 + movdqa [edx + 0B0h], xmm5 + + aesimc xmm5, [ecx + 40h] + aesimc xmm4, [ecx + 0A0h] + movdqa [edx + 40h], xmm4 + movdqa [edx + 0A0h], xmm5 + + aesimc xmm5, [ecx + 50h] + aesimc xmm4, [ecx + 90h] + movdqa [edx + 50h], xmm4 + movdqa [edx + 90h], xmm5 + + aesimc xmm5, [ecx + 60h] + aesimc xmm4, [ecx + 80h] + movdqa [edx + 60h], xmm4 + movdqa [edx + 80h], xmm5 + + aesimc xmm5, [ecx + 70h] + movdqa [edx + 70h], xmm5 + + ret +@aes_AES256_derive_decryption_keys_@8 endp + +end diff --git a/aes/src/box.c b/aes/src/box.c new file mode 100644 index 0000000..c7e1e90 --- /dev/null +++ b/aes/src/box.c @@ -0,0 +1,683 @@ +/* + * Copyright (c) 2015 Egor Tensin + * This file is part of the "AES tools" project. + * For details, see https://github.com/egor-tensin/aes-tools. + * Distributed under the MIT License. + */ + +#include + +#include +#include + +static const AES_BoxAlgorithmInterface* aes_box_algorithms[] = +{ + &aes_box_algorithm_aes128, + &aes_box_algorithm_aes192, + &aes_box_algorithm_aes256, +}; + +AES_StatusCode aes_box_init( + AES_Box* box, + AES_Algorithm algorithm, + const AES_BoxKey* box_key, + AES_Mode mode, + const AES_BoxBlock* iv, + AES_ErrorDetails* err_details) +{ + AES_StatusCode status = AES_SUCCESS; + + box->algorithm = aes_box_algorithms[algorithm]; + + if (aes_is_error(status = box->algorithm->calc_round_keys( + box_key, + &box->encryption_keys, + &box->decryption_keys, + err_details))) + return status; + + box->mode = mode; + if (iv != NULL) + box->iv = *iv; + + return status; +} + +static AES_StatusCode aes_box_encrypt_block_ecb( + AES_Box* box, + const AES_BoxBlock* input, + AES_BoxBlock* output, + AES_ErrorDetails* err_details) +{ + return box->algorithm->encrypt_block( + input, &box->encryption_keys, output, err_details); +} + +static AES_StatusCode aes_box_encrypt_block_cbc( + AES_Box* box, + const AES_BoxBlock* input, + AES_BoxBlock* output, + AES_ErrorDetails* err_details) +{ + AES_StatusCode status = AES_SUCCESS; + AES_BoxBlock xored_input = *input; + + if (aes_is_error(status = box->algorithm->xor_block( + &xored_input, &box->iv, err_details))) + return status; + + if (aes_is_error(status = box->algorithm->encrypt_block( + &xored_input, &box->encryption_keys, output, err_details))) + return status; + + box->iv = *output; + return status; +} + +static AES_StatusCode aes_box_encrypt_block_cfb( + AES_Box* box, + const AES_BoxBlock* input, + AES_BoxBlock* output, + AES_ErrorDetails* err_details) +{ + AES_StatusCode status = AES_SUCCESS; + + if (aes_is_error(status = box->algorithm->encrypt_block( + &box->iv, &box->encryption_keys, output, err_details))) + return status; + + if (aes_is_error(status = box->algorithm->xor_block( + output, input, err_details))) + return status; + + box->iv = *output; + return status; +} + +static AES_StatusCode aes_box_encrypt_block_ofb( + AES_Box* box, + const AES_BoxBlock* input, + AES_BoxBlock* output, + AES_ErrorDetails* err_details) +{ + AES_StatusCode status = AES_SUCCESS; + + if (aes_is_error(status = box->algorithm->encrypt_block( + &box->iv, &box->encryption_keys, &box->iv, err_details))) + return status; + + *output = box->iv; + + if (aes_is_error(status = box->algorithm->xor_block( + output, input, err_details))) + return status; + + return status; +} + +static AES_StatusCode aes_box_encrypt_block_ctr( + AES_Box* box, + const AES_BoxBlock* input, + AES_BoxBlock* output, + AES_ErrorDetails* err_details) +{ + AES_StatusCode status = AES_SUCCESS; + + if (aes_is_error(status = box->algorithm->encrypt_block( + &box->iv, &box->encryption_keys, output, err_details))) + return status; + + if (aes_is_error(status = box->algorithm->xor_block( + output, input, err_details))) + return status; + + if (aes_is_error(status = box->algorithm->inc_block( + &box->iv, err_details))) + return status; + + return status; +} + +typedef AES_StatusCode (*AES_BoxEncryptBlockInMode)( + AES_Box*, + const AES_BoxBlock*, + AES_BoxBlock*, + AES_ErrorDetails*); + +static AES_BoxEncryptBlockInMode aes_box_encrypt_block_in_mode[] = +{ + &aes_box_encrypt_block_ecb, + &aes_box_encrypt_block_cbc, + &aes_box_encrypt_block_cfb, + &aes_box_encrypt_block_ofb, + &aes_box_encrypt_block_ctr, +}; + +AES_StatusCode aes_box_encrypt_block( + AES_Box* box, + const AES_BoxBlock* input, + AES_BoxBlock* output, + AES_ErrorDetails* err_details) +{ + return aes_box_encrypt_block_in_mode[box->mode]( + box, input, output, err_details); +} + +static AES_StatusCode aes_box_decrypt_block_ecb( + AES_Box* box, + const AES_BoxBlock* input, + AES_BoxBlock* output, + AES_ErrorDetails* err_details) +{ + return box->algorithm->decrypt_block( + input, &box->decryption_keys, output, err_details); +} + +static AES_StatusCode aes_box_decrypt_block_cbc( + AES_Box* box, + const AES_BoxBlock* input, + AES_BoxBlock* output, + AES_ErrorDetails* err_details) +{ + AES_StatusCode status = AES_SUCCESS; + + if (aes_is_error(status = box->algorithm->decrypt_block( + input, &box->decryption_keys, output, err_details))) + return status; + + if (aes_is_error(status = box->algorithm->xor_block( + output, &box->iv, err_details))) + return status; + + box->iv = *input; + return status; +} + +static AES_StatusCode aes_box_decrypt_block_cfb( + AES_Box* box, + const AES_BoxBlock* input, + AES_BoxBlock* output, + AES_ErrorDetails* err_details) +{ + AES_StatusCode status = AES_SUCCESS; + + if (aes_is_error(status = box->algorithm->encrypt_block( + &box->iv, &box->encryption_keys, output, err_details))) + return status; + + if (aes_is_error(status = box->algorithm->xor_block( + output, input, err_details))) + return status; + + box->iv = *input; + return status; +} + +typedef AES_BoxEncryptBlockInMode AES_BoxDecryptBlockInMode; + +static AES_BoxDecryptBlockInMode aes_box_decrypt_block_in_mode[] = +{ + &aes_box_decrypt_block_ecb, + &aes_box_decrypt_block_cbc, + &aes_box_decrypt_block_cfb, + &aes_box_encrypt_block_ofb, + &aes_box_encrypt_block_ctr, +}; + +AES_StatusCode aes_box_decrypt_block( + AES_Box* box, + const AES_BoxBlock* input, + AES_BoxBlock* output, + AES_ErrorDetails* err_details) +{ + return aes_box_decrypt_block_in_mode[box->mode]( + box, input, output, err_details); +} + +static AES_StatusCode aes_box_get_encrypted_buffer_size( + AES_Box* box, + size_t src_size, + size_t* dest_size, + size_t* padding_size, + AES_ErrorDetails* err_details) +{ + AES_StatusCode status = AES_SUCCESS; + + switch (box->mode) + { + case AES_ECB: + case AES_CBC: + { + size_t block_size; + + if (aes_is_error(status = box->algorithm->get_block_size( + &block_size, err_details))) + return status; + + *padding_size = block_size - src_size % block_size; + *dest_size = src_size + *padding_size; + return status; + } + + case AES_CFB: + case AES_OFB: + case AES_CTR: + *dest_size = src_size; + *padding_size = 0; + return status; + + default: + return aes_error_not_implemented( + err_details, "unsupported mode of operation"); + } +} + +static AES_StatusCode aes_box_encrypt_buffer_block( + AES_Box* box, + const void* src, + void* dest, + AES_ErrorDetails* err_details) +{ + AES_StatusCode status = AES_SUCCESS; + + AES_BoxBlock plaintext; + + if (aes_is_error(status = box->algorithm->load_block( + &plaintext, src, err_details))) + return status; + + AES_BoxBlock ciphertext; + + if (aes_is_error(status = aes_box_encrypt_block( + box, &plaintext, &ciphertext, err_details))) + return status; + + if (aes_is_error(status = box->algorithm->store_block( + dest, &ciphertext, err_details))) + return status; + + return status; +} + +static AES_StatusCode aes_box_encrypt_buffer_partial_block_with_padding( + AES_Box* box, + const void* src, + size_t src_size, + void* dest, + size_t padding_size, + AES_ErrorDetails* err_details) +{ + AES_StatusCode status = AES_SUCCESS; + + size_t block_size; + + if (aes_is_error(status = box->algorithm->get_block_size( + &block_size, err_details))) + return status; + + void* plaintext_buf = malloc(block_size); + + if (plaintext_buf == NULL) + return status = aes_error_memory_allocation(err_details); + + memcpy(plaintext_buf, src, src_size); + + if (aes_is_error(status = aes_fill_with_padding( + AES_PADDING_PKCS7, + (char*) plaintext_buf + src_size, + padding_size, + err_details))) + goto FREE_PLAINTEXT_BUF; + + if (aes_is_error(status = aes_box_encrypt_buffer_block( + box, plaintext_buf, dest, err_details))) + goto FREE_PLAINTEXT_BUF; + +FREE_PLAINTEXT_BUF: + free(plaintext_buf); + + return status; +} + +static AES_StatusCode aes_box_encrypt_buffer_partial_block( + AES_Box* box, + const void* src, + size_t src_size, + void* dest, + AES_ErrorDetails* err_details) +{ + AES_StatusCode status = AES_SUCCESS; + + if (src_size == 0) + return status; + + size_t block_size; + + if (aes_is_error(status = box->algorithm->get_block_size( + &block_size, err_details))) + return status; + + void* plaintext_buf = malloc(block_size); + + if (plaintext_buf == NULL) + return status = aes_error_memory_allocation(err_details); + + memset(plaintext_buf, 0x00, block_size); + memcpy(plaintext_buf, src, src_size); + + void* ciphertext_buf = malloc(block_size); + + if (ciphertext_buf == NULL) + { + status = aes_error_memory_allocation(err_details); + goto FREE_PLAINTEXT_BUF; + } + + if (aes_is_error(status = aes_box_encrypt_buffer_block( + box, plaintext_buf, ciphertext_buf, err_details))) + goto FREE_CIPHERTEXT_BUF; + + memcpy(dest, ciphertext_buf, src_size); + +FREE_CIPHERTEXT_BUF: + free(ciphertext_buf); + +FREE_PLAINTEXT_BUF: + free(plaintext_buf); + + return status; +} + +AES_StatusCode aes_box_encrypt_buffer( + AES_Box* box, + const void* src, + size_t src_size, + void* dest, + size_t* dest_size, + AES_ErrorDetails* err_details) +{ + AES_StatusCode status = AES_SUCCESS; + + if (box == NULL) + return aes_error_null_argument(err_details, "box"); + if (dest_size == NULL) + return aes_error_null_argument(err_details, "dest_size"); + + size_t padding_size = 0; + + if (aes_is_error(status = aes_box_get_encrypted_buffer_size( + box, src_size, dest_size, &padding_size, err_details))) + return status; + + if (dest == NULL) + return AES_SUCCESS; + if (src == NULL && src_size != 0) + return aes_error_null_argument(err_details, "src"); + + size_t block_size; + + if (aes_is_error(status = box->algorithm->get_block_size( + &block_size, err_details))) + return status; + + const size_t src_len = src_size / block_size; + + for (size_t i = 0; i < src_len; ++i) + { + if (aes_is_error(status = aes_box_encrypt_buffer_block( + box, src, dest, err_details))) + return status; + + src = (char*) src + block_size; + dest = (char*) dest + block_size; + } + + if (padding_size == 0) + return aes_box_encrypt_buffer_partial_block( + box, src, src_size % block_size, dest, err_details); + else + return aes_box_encrypt_buffer_partial_block_with_padding( + box, src, src_size % block_size, dest, padding_size, err_details); +} + +static AES_StatusCode aes_box_get_decrypted_buffer_size( + AES_Box* box, + size_t src_size, + size_t* dest_size, + size_t* max_padding_size, + AES_ErrorDetails* err_details) +{ + AES_StatusCode status = AES_SUCCESS; + + switch (box->mode) + { + case AES_ECB: + case AES_CBC: + { + size_t block_size; + + if (aes_is_error(status = box->algorithm->get_block_size( + &block_size, err_details))) + return status; + + if (src_size == 0 || src_size % block_size != 0) + return aes_error_missing_padding(err_details); + + *dest_size = src_size; + *max_padding_size = block_size; + return status; + } + + case AES_CFB: + case AES_OFB: + case AES_CTR: + *dest_size = src_size; + *max_padding_size = 0; + return status; + + default: + return aes_error_not_implemented( + err_details, "unsupported mode of operation"); + } +} + +static AES_StatusCode aes_box_decrypt_buffer_block( + AES_Box* box, + const void* src, + void* dest, + AES_ErrorDetails* err_details) +{ + AES_StatusCode status = AES_SUCCESS; + + AES_BoxBlock ciphertext; + + if (aes_is_error(status = box->algorithm->load_block( + &ciphertext, src, err_details))) + return status; + + AES_BoxBlock plaintext; + + if (aes_is_error(status = aes_box_decrypt_block( + box, &ciphertext, &plaintext, err_details))) + return status; + + if (aes_is_error(status = box->algorithm->store_block( + dest, &plaintext, err_details))) + return status; + + return status; +} + +static AES_StatusCode aes_box_decrypt_buffer_partial_block( + AES_Box* box, + const void* src, + size_t src_size, + void* dest, + AES_ErrorDetails* err_details) +{ + AES_StatusCode status = AES_SUCCESS; + + if (src_size == 0) + return status; + + size_t block_size; + + if (aes_is_error(status = box->algorithm->get_block_size( + &block_size, err_details))) + return status; + + void* ciphertext_buf = malloc(block_size); + + if (ciphertext_buf == NULL) + return status = aes_error_memory_allocation(err_details); + + memset(ciphertext_buf, 0x00, block_size); + memcpy(ciphertext_buf, src, src_size); + + void* plaintext_buf = malloc(block_size); + + if (plaintext_buf == NULL) + { + status = aes_error_memory_allocation(err_details); + goto FREE_CIPHERTEXT_BUF; + } + + if (aes_is_error(status = aes_box_decrypt_buffer_block( + box, ciphertext_buf, plaintext_buf, err_details))) + goto FREE_PLAINTEXT_BUF; + + memcpy(dest, plaintext_buf, src_size); + +FREE_PLAINTEXT_BUF: + free(plaintext_buf); + +FREE_CIPHERTEXT_BUF: + free(ciphertext_buf); + + return status; +} + +AES_StatusCode aes_box_decrypt_buffer( + AES_Box* box, + const void* src, + size_t src_size, + void* dest, + size_t* dest_size, + AES_ErrorDetails* err_details) +{ + if (box == NULL) + return aes_error_null_argument(err_details, "box"); + if (dest_size == NULL) + return aes_error_null_argument(err_details, "dest_size"); + + AES_StatusCode status = AES_SUCCESS; + size_t max_padding_size = 0; + + if (aes_is_error(status = aes_box_get_decrypted_buffer_size( + box, src_size, dest_size, &max_padding_size, err_details))) + return status; + + if (dest == NULL) + return AES_SUCCESS; + if (src == NULL) + return aes_error_null_argument(err_details, "src"); + + size_t block_size; + + if (aes_is_error(status = box->algorithm->get_block_size( + &block_size, err_details))) + return status; + + const size_t src_len = src_size / block_size; + + for (size_t i = 0; i < src_len; ++i) + { + if (aes_is_error(status = aes_box_decrypt_buffer_block( + box, src, dest, err_details))) + return status; + + src = (char*) src + block_size; + dest = (char*) dest + block_size; + } + + if (max_padding_size == 0) + { + return aes_box_decrypt_buffer_partial_block( + box, src, src_size % block_size, dest, err_details); + } + else + { + size_t padding_size; + + if (aes_is_error(status = aes_extract_padding_size( + AES_PADDING_PKCS7, + (char*) dest - block_size, + block_size, + &padding_size, + err_details))) + return status; + + *dest_size -= padding_size; + return status; + } +} + +AES_StatusCode aes_box_parse_block( + AES_BoxBlock* dest, + AES_Algorithm algorithm, + const char* src, + AES_ErrorDetails* err_details) +{ + if (dest == NULL) + return aes_error_null_argument(err_details, "dest"); + if (src == NULL) + return aes_error_null_argument(err_details, "src"); + + return aes_box_algorithms[algorithm]->parse_block( + dest, src, err_details); +} + +AES_StatusCode aes_box_parse_key( + AES_BoxKey* dest, + AES_Algorithm algorithm, + const char* src, + AES_ErrorDetails* err_details) +{ + if (dest == NULL) + return aes_error_null_argument(err_details, "dest"); + if (src == NULL) + return aes_error_null_argument(err_details, "src"); + + return aes_box_algorithms[algorithm]->parse_key( + dest, src, err_details); +} + +AES_StatusCode aes_box_format_block( + AES_BoxBlockString* dest, + AES_Algorithm algorithm, + const AES_BoxBlock* src, + AES_ErrorDetails* err_details) +{ + if (dest == NULL) + return aes_error_null_argument(err_details, "dest"); + if (src == NULL) + return aes_error_null_argument(err_details, "src"); + + return aes_box_algorithms[algorithm]->format_block( + dest, src, err_details); +} + +AES_StatusCode aes_box_format_key( + AES_BoxKeyString* dest, + AES_Algorithm algorithm, + const AES_BoxKey* src, + AES_ErrorDetails* err_details) +{ + if (dest == NULL) + return aes_error_null_argument(err_details, "dest"); + if (src == NULL) + return aes_error_null_argument(err_details, "src"); + + return aes_box_algorithms[algorithm]->format_key( + dest, src, err_details); +} diff --git a/aes/src/box_aes.c b/aes/src/box_aes.c new file mode 100644 index 0000000..4d08d10 --- /dev/null +++ b/aes/src/box_aes.c @@ -0,0 +1,331 @@ +/* + * Copyright (c) 2015 Egor Tensin + * This file is part of the "AES tools" project. + * For details, see https://github.com/egor-tensin/aes-tools. + * Distributed under the MIT License. + */ + +#include + +#include +#include + +static AES_StatusCode aes_box_derive_params_aes128( + const AES_BoxKey* box_key, + AES_BoxEncryptionRoundKeys* encryption_keys, + AES_BoxDecryptionRoundKeys* decryption_keys, + AES_ErrorDetails* err_details) +{ + AES_UNUSED_PARAMETER(err_details); + aes_AES128_expand_key_( + box_key->aes128_key.key, + &encryption_keys->aes128_encryption_keys); + aes_AES128_derive_decryption_keys_( + &encryption_keys->aes128_encryption_keys, + &decryption_keys->aes128_decryption_keys); + return AES_SUCCESS; +} + +static AES_StatusCode aes_box_derive_params_aes192( + const AES_BoxKey* box_key, + AES_BoxEncryptionRoundKeys* encryption_keys, + AES_BoxDecryptionRoundKeys* decryption_keys, + AES_ErrorDetails* err_details) +{ + AES_UNUSED_PARAMETER(err_details); + aes_AES192_expand_key_( + box_key->aes192_key.lo, + box_key->aes192_key.hi, + &encryption_keys->aes192_encryption_keys); + aes_AES192_derive_decryption_keys_( + &encryption_keys->aes192_encryption_keys, + &decryption_keys->aes192_decryption_keys); + return AES_SUCCESS; +} + +static AES_StatusCode aes_box_derive_params_aes256( + const AES_BoxKey* box_key, + AES_BoxEncryptionRoundKeys* encryption_keys, + AES_BoxDecryptionRoundKeys* decryption_keys, + AES_ErrorDetails* err_details) +{ + AES_UNUSED_PARAMETER(err_details); + aes_AES256_expand_key_( + box_key->aes256_key.lo, + box_key->aes256_key.hi, + &encryption_keys->aes256_encryption_keys); + aes_AES256_derive_decryption_keys_( + &encryption_keys->aes256_encryption_keys, + &decryption_keys->aes256_decryption_keys); + return AES_SUCCESS; +} + +static AES_StatusCode aes_box_parse_block_aes( + AES_BoxBlock* dest, + const char* src, + AES_ErrorDetails* err_details) +{ + if (dest == NULL) + return aes_error_null_argument(err_details, "dest"); + + return aes_AES_parse_block(&dest->aes_block, src, err_details); +} + +static AES_StatusCode aes_box_parse_key_aes128( + AES_BoxKey* dest, + const char* src, + AES_ErrorDetails* err_details) +{ + if (dest == NULL) + return aes_error_null_argument(err_details, "dest"); + + return aes_AES128_parse_key(&dest->aes128_key, src, err_details); +} + +static AES_StatusCode aes_box_parse_key_aes192( + AES_BoxKey* dest, + const char* src, + AES_ErrorDetails* err_details) +{ + if (dest == NULL) + return aes_error_null_argument(err_details, "dest"); + + return aes_AES192_parse_key(&dest->aes192_key, src, err_details); +} + +static AES_StatusCode aes_box_parse_key_aes256( + AES_BoxKey* dest, + const char* src, + AES_ErrorDetails* err_details) +{ + if (dest == NULL) + return aes_error_null_argument(err_details, "dest"); + + return aes_AES256_parse_key(&dest->aes256_key, src, err_details); +} + +static AES_StatusCode aes_box_format_block_aes( + AES_BoxBlockString* dest, + const AES_BoxBlock* src, + AES_ErrorDetails* err_details) +{ + if (dest == NULL) + return aes_error_null_argument(err_details, "dest"); + if (src == NULL) + return aes_error_null_argument(err_details, "src"); + + return aes_AES128_format_block(&dest->aes, &src->aes_block, err_details); +} + +static AES_StatusCode aes_box_format_key_aes128( + AES_BoxKeyString* dest, + const AES_BoxKey* src, + AES_ErrorDetails* err_details) +{ + if (dest == NULL) + return aes_error_null_argument(err_details, "dest"); + if (src == NULL) + return aes_error_null_argument(err_details, "src"); + + return aes_AES128_format_key(&dest->aes128, &src->aes128_key, err_details); +} + +static AES_StatusCode aes_box_format_key_aes192( + AES_BoxKeyString* dest, + const AES_BoxKey* src, + AES_ErrorDetails* err_details) +{ + if (dest == NULL) + return aes_error_null_argument(err_details, "dest"); + if (src == NULL) + return aes_error_null_argument(err_details, "src"); + + return aes_AES192_format_key(&dest->aes192, &src->aes192_key, err_details); +} + +static AES_StatusCode aes_box_format_key_aes256( + AES_BoxKeyString* dest, + const AES_BoxKey* src, + AES_ErrorDetails* err_details) +{ + if (dest == NULL) + return aes_error_null_argument(err_details, "dest"); + if (src == NULL) + return aes_error_null_argument(err_details, "src"); + + return aes_AES256_format_key(&dest->aes256, &src->aes256_key, err_details); +} + +static AES_StatusCode aes_box_xor_block_aes( + AES_BoxBlock* dest, + const AES_BoxBlock* src, + AES_ErrorDetails* err_details) +{ + AES_UNUSED_PARAMETER(err_details); + dest->aes_block = aes_AES_xor_blocks(dest->aes_block, src->aes_block); + return AES_SUCCESS; +} + +static AES_StatusCode aes_box_inc_block_aes( + AES_BoxBlock* ctr, + AES_ErrorDetails* err_details) +{ + AES_UNUSED_PARAMETER(err_details); + ctr->aes_block = aes_AES_inc_block(ctr->aes_block); + return AES_SUCCESS; +} + +static AES_StatusCode aes_box_get_block_size_aes( + size_t* block_size, + AES_ErrorDetails* err_details) +{ + AES_UNUSED_PARAMETER(err_details); + *block_size = 16; + return AES_SUCCESS; +} + +static AES_StatusCode aes_box_store_block_aes( + void* dest, + const AES_BoxBlock* src, + AES_ErrorDetails* err_details) +{ + AES_UNUSED_PARAMETER(err_details); + aes_store_block128(dest, src->aes_block); + return AES_SUCCESS; +} + +static AES_StatusCode aes_box_load_block_aes( + AES_BoxBlock* dest, + const void* src, + AES_ErrorDetails* err_details) +{ + AES_UNUSED_PARAMETER(err_details); + dest->aes_block = aes_load_block128(src); + return AES_SUCCESS; +} + +static AES_StatusCode aes_box_encrypt_block_aes128( + const AES_BoxBlock* input, + const AES_BoxEncryptionRoundKeys* params, + AES_BoxBlock* output, + AES_ErrorDetails* err_details) +{ + AES_UNUSED_PARAMETER(err_details); + output->aes_block = aes_AES128_encrypt_block_( + input->aes_block, + ¶ms->aes128_encryption_keys); + return AES_SUCCESS; +} + +static AES_StatusCode aes_box_decrypt_block_aes128( + const AES_BoxBlock* input, + const AES_BoxDecryptionRoundKeys* params, + AES_BoxBlock* output, + AES_ErrorDetails* err_details) +{ + AES_UNUSED_PARAMETER(err_details); + output->aes_block = aes_AES128_decrypt_block_( + input->aes_block, + ¶ms->aes128_decryption_keys); + return AES_SUCCESS; +} + +static AES_StatusCode aes_box_encrypt_block_aes192( + const AES_BoxBlock* input, + const AES_BoxEncryptionRoundKeys* params, + AES_BoxBlock* output, + AES_ErrorDetails* err_details) +{ + AES_UNUSED_PARAMETER(err_details); + output->aes_block = aes_AES192_encrypt_block_( + input->aes_block, + ¶ms->aes192_encryption_keys); + return AES_SUCCESS; +} + +static AES_StatusCode aes_box_decrypt_block_aes192( + const AES_BoxBlock* input, + const AES_BoxDecryptionRoundKeys* params, + AES_BoxBlock* output, + AES_ErrorDetails* err_details) +{ + AES_UNUSED_PARAMETER(err_details); + output->aes_block = aes_AES192_decrypt_block_( + input->aes_block, + ¶ms->aes192_decryption_keys); + return AES_SUCCESS; +} + +static AES_StatusCode aes_box_encrypt_block_aes256( + const AES_BoxBlock* input, + const AES_BoxEncryptionRoundKeys* params, + AES_BoxBlock* output, + AES_ErrorDetails* err_details) +{ + AES_UNUSED_PARAMETER(err_details); + output->aes_block = aes_AES256_encrypt_block_( + input->aes_block, + ¶ms->aes256_encryption_keys); + return AES_SUCCESS; +} + +static AES_StatusCode aes_box_decrypt_block_aes256( + const AES_BoxBlock* input, + const AES_BoxDecryptionRoundKeys* params, + AES_BoxBlock* output, + AES_ErrorDetails* err_details) +{ + AES_UNUSED_PARAMETER(err_details); + output->aes_block = aes_AES256_decrypt_block_( + input->aes_block, + ¶ms->aes256_decryption_keys); + return AES_SUCCESS; +} + +AES_BoxAlgorithmInterface aes_box_algorithm_aes128 = +{ + &aes_box_derive_params_aes128, + &aes_box_parse_block_aes, + &aes_box_parse_key_aes128, + &aes_box_format_block_aes, + &aes_box_format_key_aes128, + &aes_box_encrypt_block_aes128, + &aes_box_decrypt_block_aes128, + &aes_box_xor_block_aes, + &aes_box_inc_block_aes, + &aes_box_get_block_size_aes, + &aes_box_store_block_aes, + &aes_box_load_block_aes, +}; + +AES_BoxAlgorithmInterface aes_box_algorithm_aes192 = +{ + &aes_box_derive_params_aes192, + &aes_box_parse_block_aes, + &aes_box_parse_key_aes192, + &aes_box_format_block_aes, + &aes_box_format_key_aes192, + &aes_box_encrypt_block_aes192, + &aes_box_decrypt_block_aes192, + &aes_box_xor_block_aes, + &aes_box_inc_block_aes, + &aes_box_get_block_size_aes, + &aes_box_store_block_aes, + &aes_box_load_block_aes, +}; + +AES_BoxAlgorithmInterface aes_box_algorithm_aes256 = +{ + &aes_box_derive_params_aes256, + &aes_box_parse_block_aes, + &aes_box_parse_key_aes256, + &aes_box_format_block_aes, + &aes_box_format_key_aes256, + &aes_box_encrypt_block_aes256, + &aes_box_decrypt_block_aes256, + &aes_box_xor_block_aes, + &aes_box_inc_block_aes, + &aes_box_get_block_size_aes, + &aes_box_store_block_aes, + &aes_box_load_block_aes, +}; diff --git a/aes/src/c/aes128.c b/aes/src/c/aes128.c new file mode 100644 index 0000000..a1bad40 --- /dev/null +++ b/aes/src/c/aes128.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2015 Egor Tensin + * This file is part of the "AES tools" project. + * For details, see https://github.com/egor-tensin/aes-tools. + * Distributed under the MIT License. + */ + +#include + +#include +#include + +AES_AES_Block __fastcall aes_AES128_encrypt_block_( + AES_AES_Block plaintext, + const AES_AES128_RoundKeys* encryption_keys) +{ + plaintext = _mm_xor_si128(plaintext, encryption_keys->keys[0]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[1]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[2]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[3]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[4]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[5]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[6]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[7]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[8]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[9]); + return _mm_aesenclast_si128(plaintext, encryption_keys->keys[10]); +} + +AES_AES_Block __fastcall aes_AES128_decrypt_block_( + AES_AES_Block ciphertext, + const AES_AES128_RoundKeys* decryption_keys) +{ + ciphertext = _mm_xor_si128(ciphertext, decryption_keys->keys[0]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[1]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[2]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[3]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[4]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[5]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[6]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[7]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[8]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[9]); + return _mm_aesdeclast_si128(ciphertext, decryption_keys->keys[10]); +} + +static AES_AES_Block __fastcall aes_aes128_expand_key_assist( + AES_AES_Block prev, + AES_AES_Block hwgen) +{ + AES_AES_Block tmp = prev; + + tmp = _mm_slli_si128(tmp, 4); + prev = _mm_xor_si128(prev, tmp); + tmp = _mm_slli_si128(tmp, 4); + prev = _mm_xor_si128(prev, tmp); + tmp = _mm_slli_si128(tmp, 4); + prev = _mm_xor_si128(prev, tmp); + + hwgen = _mm_shuffle_epi32(hwgen, 0xff); + prev = _mm_xor_si128(prev, hwgen); + + return prev; +} + +void __fastcall aes_AES128_expand_key_( + AES_AES_Block key, + AES_AES128_RoundKeys* encryption_keys) +{ + AES_Block128 prev = encryption_keys->keys[0] = key; + prev = encryption_keys->keys[1] = aes_aes128_expand_key_assist(prev, _mm_aeskeygenassist_si128(prev, 0x01)); + prev = encryption_keys->keys[2] = aes_aes128_expand_key_assist(prev, _mm_aeskeygenassist_si128(prev, 0x02)); + prev = encryption_keys->keys[3] = aes_aes128_expand_key_assist(prev, _mm_aeskeygenassist_si128(prev, 0x04)); + prev = encryption_keys->keys[4] = aes_aes128_expand_key_assist(prev, _mm_aeskeygenassist_si128(prev, 0x08)); + prev = encryption_keys->keys[5] = aes_aes128_expand_key_assist(prev, _mm_aeskeygenassist_si128(prev, 0x10)); + prev = encryption_keys->keys[6] = aes_aes128_expand_key_assist(prev, _mm_aeskeygenassist_si128(prev, 0x20)); + prev = encryption_keys->keys[7] = aes_aes128_expand_key_assist(prev, _mm_aeskeygenassist_si128(prev, 0x40)); + prev = encryption_keys->keys[8] = aes_aes128_expand_key_assist(prev, _mm_aeskeygenassist_si128(prev, 0x80)); + prev = encryption_keys->keys[9] = aes_aes128_expand_key_assist(prev, _mm_aeskeygenassist_si128(prev, 0x1b)); + prev = encryption_keys->keys[10] = aes_aes128_expand_key_assist(prev, _mm_aeskeygenassist_si128(prev, 0x36)); +} + +void __fastcall aes_AES128_derive_decryption_keys_( + const AES_AES128_RoundKeys* encryption_keys, + AES_AES128_RoundKeys* decryption_keys) +{ + decryption_keys->keys[0] = encryption_keys->keys[10]; + decryption_keys->keys[1] = _mm_aesimc_si128(encryption_keys->keys[9]); + decryption_keys->keys[2] = _mm_aesimc_si128(encryption_keys->keys[8]); + decryption_keys->keys[3] = _mm_aesimc_si128(encryption_keys->keys[7]); + decryption_keys->keys[4] = _mm_aesimc_si128(encryption_keys->keys[6]); + decryption_keys->keys[5] = _mm_aesimc_si128(encryption_keys->keys[5]); + decryption_keys->keys[6] = _mm_aesimc_si128(encryption_keys->keys[4]); + decryption_keys->keys[7] = _mm_aesimc_si128(encryption_keys->keys[3]); + decryption_keys->keys[8] = _mm_aesimc_si128(encryption_keys->keys[2]); + decryption_keys->keys[9] = _mm_aesimc_si128(encryption_keys->keys[1]); + decryption_keys->keys[10] = encryption_keys->keys[0]; +} diff --git a/aes/src/c/aes192.c b/aes/src/c/aes192.c new file mode 100644 index 0000000..d661b78 --- /dev/null +++ b/aes/src/c/aes192.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2015 Egor Tensin + * This file is part of the "AES tools" project. + * For details, see https://github.com/egor-tensin/aes-tools. + * Distributed under the MIT License. + */ + +#include + +#include +#include + +AES_AES_Block __fastcall aes_AES192_encrypt_block_( + AES_AES_Block plaintext, + const AES_AES192_RoundKeys* encryption_keys) +{ + plaintext = _mm_xor_si128(plaintext, encryption_keys->keys[0]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[1]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[2]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[3]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[4]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[5]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[6]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[7]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[8]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[9]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[10]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[11]); + return _mm_aesenclast_si128(plaintext, encryption_keys->keys[12]); +} + +AES_AES_Block __fastcall aes_AES192_decrypt_block_( + AES_AES_Block ciphertext, + const AES_AES192_RoundKeys* decryption_keys) +{ + ciphertext = _mm_xor_si128(ciphertext, decryption_keys->keys[0]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[1]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[2]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[3]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[4]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[5]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[6]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[7]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[8]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[9]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[10]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[11]); + return _mm_aesdeclast_si128(ciphertext, decryption_keys->keys[12]); +} + +static void __fastcall aes_aes192_expand_key_assist( + AES_AES_Block* prev_lo, + AES_AES_Block* prev_hi, + AES_AES_Block hwgen) +{ + AES_AES_Block tmp = *prev_lo; + + tmp = _mm_slli_si128(tmp, 4); + *prev_lo = _mm_xor_si128(*prev_lo, tmp); + tmp = _mm_slli_si128(tmp, 4); + *prev_lo = _mm_xor_si128(*prev_lo, tmp); + tmp = _mm_slli_si128(tmp, 4); + *prev_lo = _mm_xor_si128(*prev_lo, tmp); + + hwgen = _mm_shuffle_epi32(hwgen, 0x55); + *prev_lo = _mm_xor_si128(*prev_lo, hwgen); + + tmp = _mm_shuffle_epi32(*prev_hi, 0xf3); + *prev_hi = _mm_xor_si128(*prev_hi, tmp); + + tmp = _mm_shuffle_epi32(*prev_lo, 0xff); + tmp = _mm_srli_si128(tmp, 8); + *prev_hi = _mm_xor_si128(*prev_hi, tmp); +} + +void __fastcall aes_AES192_expand_key_( + AES_AES_Block key_lo, + AES_AES_Block key_hi, + AES_AES192_RoundKeys* encryption_keys) +{ + encryption_keys->keys[0] = key_lo; + encryption_keys->keys[1] = key_hi; + + aes_aes192_expand_key_assist(&key_lo, &key_hi, _mm_aeskeygenassist_si128(key_hi, 0x01)); + encryption_keys->keys[1] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(encryption_keys->keys[1]), _mm_castsi128_pd(key_lo), 0)); + encryption_keys->keys[2] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(key_lo), _mm_castsi128_pd(key_hi), 1)); + + aes_aes192_expand_key_assist(&key_lo, &key_hi, _mm_aeskeygenassist_si128(key_hi, 0x02)); + encryption_keys->keys[3] = key_lo; + encryption_keys->keys[4] = key_hi; + + aes_aes192_expand_key_assist(&key_lo, &key_hi, _mm_aeskeygenassist_si128(key_hi, 0x04)); + encryption_keys->keys[4] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(encryption_keys->keys[4]), _mm_castsi128_pd(key_lo), 0)); + encryption_keys->keys[5] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(key_lo), _mm_castsi128_pd(key_hi), 1)); + + aes_aes192_expand_key_assist(&key_lo, &key_hi, _mm_aeskeygenassist_si128(key_hi, 0x08)); + encryption_keys->keys[6] = key_lo; + encryption_keys->keys[7] = key_hi; + + aes_aes192_expand_key_assist(&key_lo, &key_hi, _mm_aeskeygenassist_si128(key_hi, 0x10)); + encryption_keys->keys[7] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(encryption_keys->keys[7]), _mm_castsi128_pd(key_lo), 0)); + encryption_keys->keys[8] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(key_lo), _mm_castsi128_pd(key_hi), 1)); + + aes_aes192_expand_key_assist(&key_lo, &key_hi, _mm_aeskeygenassist_si128(key_hi, 0x20)); + encryption_keys->keys[9] = key_lo; + encryption_keys->keys[10] = key_hi; + + aes_aes192_expand_key_assist(&key_lo, &key_hi, _mm_aeskeygenassist_si128(key_hi, 0x40)); + encryption_keys->keys[10] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(encryption_keys->keys[10]), _mm_castsi128_pd(key_lo), 0)); + encryption_keys->keys[11] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(key_lo), _mm_castsi128_pd(key_hi), 1)); + + aes_aes192_expand_key_assist(&key_lo, &key_hi, _mm_aeskeygenassist_si128(key_hi, 0x80)); + encryption_keys->keys[12] = key_lo; +} + +void __fastcall aes_AES192_derive_decryption_keys_( + const AES_AES192_RoundKeys* encryption_keys, + AES_AES192_RoundKeys* decryption_keys) +{ + decryption_keys->keys[0] = encryption_keys->keys[12]; + decryption_keys->keys[1] = _mm_aesimc_si128(encryption_keys->keys[11]); + decryption_keys->keys[2] = _mm_aesimc_si128(encryption_keys->keys[10]); + decryption_keys->keys[3] = _mm_aesimc_si128(encryption_keys->keys[9]); + decryption_keys->keys[4] = _mm_aesimc_si128(encryption_keys->keys[8]); + decryption_keys->keys[5] = _mm_aesimc_si128(encryption_keys->keys[7]); + decryption_keys->keys[6] = _mm_aesimc_si128(encryption_keys->keys[6]); + decryption_keys->keys[7] = _mm_aesimc_si128(encryption_keys->keys[5]); + decryption_keys->keys[8] = _mm_aesimc_si128(encryption_keys->keys[4]); + decryption_keys->keys[9] = _mm_aesimc_si128(encryption_keys->keys[3]); + decryption_keys->keys[10] = _mm_aesimc_si128(encryption_keys->keys[2]); + decryption_keys->keys[11] = _mm_aesimc_si128(encryption_keys->keys[1]); + decryption_keys->keys[12] = encryption_keys->keys[0]; +} diff --git a/aes/src/c/aes256.c b/aes/src/c/aes256.c new file mode 100644 index 0000000..2190322 --- /dev/null +++ b/aes/src/c/aes256.c @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2015 Egor Tensin + * This file is part of the "AES tools" project. + * For details, see https://github.com/egor-tensin/aes-tools. + * Distributed under the MIT License. + */ + +#include + +#include +#include + +AES_AES_Block __fastcall aes_AES256_encrypt_block_( + AES_AES_Block plaintext, + const AES_AES256_RoundKeys* encryption_keys) +{ + plaintext = _mm_xor_si128(plaintext, encryption_keys->keys[0]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[1]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[2]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[3]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[4]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[5]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[6]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[7]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[8]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[9]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[10]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[11]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[12]); + plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[13]); + return _mm_aesenclast_si128(plaintext, encryption_keys->keys[14]); +} + +AES_AES_Block __fastcall aes_AES256_decrypt_block_( + AES_AES_Block ciphertext, + const AES_AES256_RoundKeys* decryption_keys) +{ + ciphertext = _mm_xor_si128(ciphertext, decryption_keys->keys[0]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[1]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[2]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[3]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[4]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[5]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[6]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[7]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[8]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[9]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[10]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[11]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[12]); + ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[13]); + return _mm_aesdeclast_si128(ciphertext, decryption_keys->keys[14]); +} + +static AES_AES_Block __fastcall aes_aes256_expand_key_assist( + AES_AES_Block* prev_lo, + AES_AES_Block* prev_hi, + AES_AES_Block hwgen) +{ + AES_AES_Block tmp = *prev_lo; + + tmp = _mm_slli_si128(tmp, 4); + *prev_lo = _mm_xor_si128(*prev_lo, tmp); + tmp = _mm_slli_si128(tmp, 4); + *prev_lo = _mm_xor_si128(*prev_lo, tmp); + tmp = _mm_slli_si128(tmp, 4); + *prev_lo = _mm_xor_si128(*prev_lo, tmp); + + *prev_lo = _mm_xor_si128(*prev_lo, hwgen); + + *prev_hi = _mm_xor_si128(*prev_hi, *prev_lo); + *prev_lo = _mm_xor_si128(*prev_lo, *prev_hi); + *prev_hi = _mm_xor_si128(*prev_hi, *prev_lo); + + return *prev_hi; +} + +void __fastcall aes_AES256_expand_key_( + AES_AES_Block key_lo, + AES_AES_Block key_hi, + AES_AES256_RoundKeys* encryption_keys) +{ + AES_AES_Block prev_lo, prev_hi; + AES_AES_Block hwgen; + + prev_lo = encryption_keys->keys[0] = key_lo; + prev_hi = encryption_keys->keys[1] = key_hi; + + hwgen = _mm_aeskeygenassist_si128(prev_hi, 0x01); + hwgen = _mm_shuffle_epi32(hwgen, 0xff); + encryption_keys->keys[2] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); + + hwgen = _mm_aeskeygenassist_si128(prev_hi, 0); + hwgen = _mm_shuffle_epi32(hwgen, 0xaa); + encryption_keys->keys[3] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); + + hwgen = _mm_aeskeygenassist_si128(prev_hi, 0x02); + hwgen = _mm_shuffle_epi32(hwgen, 0xff); + encryption_keys->keys[4] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); + + hwgen = _mm_aeskeygenassist_si128(prev_hi, 0); + hwgen = _mm_shuffle_epi32(hwgen, 0xaa); + encryption_keys->keys[5] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); + + hwgen = _mm_aeskeygenassist_si128(prev_hi, 0x04); + hwgen = _mm_shuffle_epi32(hwgen, 0xff); + encryption_keys->keys[6] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); + + hwgen = _mm_aeskeygenassist_si128(prev_hi, 0); + hwgen = _mm_shuffle_epi32(hwgen, 0xaa); + encryption_keys->keys[7] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); + + hwgen = _mm_aeskeygenassist_si128(prev_hi, 0x08); + hwgen = _mm_shuffle_epi32(hwgen, 0xff); + encryption_keys->keys[8] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); + + hwgen = _mm_aeskeygenassist_si128(prev_hi, 0); + hwgen = _mm_shuffle_epi32(hwgen, 0xaa); + encryption_keys->keys[9] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); + + hwgen = _mm_aeskeygenassist_si128(prev_hi, 0x10); + hwgen = _mm_shuffle_epi32(hwgen, 0xff); + encryption_keys->keys[10] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); + + hwgen = _mm_aeskeygenassist_si128(prev_hi, 0); + hwgen = _mm_shuffle_epi32(hwgen, 0xaa); + encryption_keys->keys[11] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); + + hwgen = _mm_aeskeygenassist_si128(prev_hi, 0x20); + hwgen = _mm_shuffle_epi32(hwgen, 0xff); + encryption_keys->keys[12] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); + + hwgen = _mm_aeskeygenassist_si128(prev_hi, 0); + hwgen = _mm_shuffle_epi32(hwgen, 0xaa); + encryption_keys->keys[13] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); + + hwgen = _mm_aeskeygenassist_si128(prev_hi, 0x40); + hwgen = _mm_shuffle_epi32(hwgen, 0xff); + encryption_keys->keys[14] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); +} + +void __fastcall aes_AES256_derive_decryption_keys_( + const AES_AES256_RoundKeys* encryption_keys, + AES_AES256_RoundKeys* decryption_keys) +{ + decryption_keys->keys[0] = encryption_keys->keys[14]; + decryption_keys->keys[1] = _mm_aesimc_si128(encryption_keys->keys[13]); + decryption_keys->keys[2] = _mm_aesimc_si128(encryption_keys->keys[12]); + decryption_keys->keys[3] = _mm_aesimc_si128(encryption_keys->keys[11]); + decryption_keys->keys[4] = _mm_aesimc_si128(encryption_keys->keys[10]); + decryption_keys->keys[5] = _mm_aesimc_si128(encryption_keys->keys[9]); + decryption_keys->keys[6] = _mm_aesimc_si128(encryption_keys->keys[8]); + decryption_keys->keys[7] = _mm_aesimc_si128(encryption_keys->keys[7]); + decryption_keys->keys[8] = _mm_aesimc_si128(encryption_keys->keys[6]); + decryption_keys->keys[9] = _mm_aesimc_si128(encryption_keys->keys[5]); + decryption_keys->keys[10] = _mm_aesimc_si128(encryption_keys->keys[4]); + decryption_keys->keys[11] = _mm_aesimc_si128(encryption_keys->keys[3]); + decryption_keys->keys[12] = _mm_aesimc_si128(encryption_keys->keys[2]); + decryption_keys->keys[13] = _mm_aesimc_si128(encryption_keys->keys[1]); + decryption_keys->keys[14] = encryption_keys->keys[0]; +} diff --git a/aes/src/error.c b/aes/src/error.c new file mode 100644 index 0000000..d49c456 --- /dev/null +++ b/aes/src/error.c @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2015 Egor Tensin + * This file is part of the "AES tools" project. + * For details, see https://github.com/egor-tensin/aes-tools. + * Distributed under the MIT License. + */ + +#include + +#include +#include +#include +#include + +#if defined(_MSC_VER) && _MSC_VER < 1900 + +#include + +#define snprintf c99_snprintf +#define vsnprintf c99_vsnprintf + +static int c99_vsnprintf(char *dest, size_t dest_size, const char *fmt, va_list ap) +{ + int dest_len = -1; + + if (dest_size != 0) + dest_len = _vsnprintf_s(dest, dest_size, _TRUNCATE, fmt, ap); + if (dest_len == -1) + dest_len = _vscprintf(fmt, ap); + + return dest_len; +} + +static int c99_snprintf(char *dest, size_t dest_size, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + + int dest_len = c99_vsnprintf(dest, dest_size, fmt, ap); + + va_end(ap); + return dest_len; +} + +#endif + +static void aes_fill_string(char* dest, size_t dest_size, const char* src) +{ + strncpy(dest, src, dest_size); + dest[dest_size - 1] = '\0'; +} + +static const char* aes_strerror_messages[] = +{ + "Success", + "Invalid argument value NULL", + "Couldn't parse", + "Invalid PKCS7 padding (wrong key?)", + "Not implemented", + "Missing padding", + "Couldn't allocate memory", +}; + +const char* aes_strerror(AES_StatusCode ec) +{ + return aes_strerror_messages[ec]; +} + +static size_t aes_format_error_strerror( + const AES_ErrorDetails* err_details,\ + char* dest, + size_t dest_size) +{ + const AES_StatusCode ec = aes_get_error_code(err_details); + const char* const msg = aes_strerror(ec); + + if (dest == NULL) + return strlen(msg) + 1; + + aes_fill_string(dest, dest_size, msg); + return strlen(dest); +} + +static size_t aes_format_null_argument_error( + const AES_ErrorDetails* err_details, + char* dest, + size_t dest_size) +{ + static const char* const fmt = "Invalid argument value NULL for parameter '%s'"; + const char* const param_name = err_details->params.null_arg.param_name; + + if (dest == NULL && dest_size == 0) + return snprintf(NULL, 0, fmt, param_name) + 1; + + snprintf(dest, dest_size, fmt, param_name); + return strlen(dest); +} + +static size_t aes_format_parse_error( + const AES_ErrorDetails* err_details, + char* dest, + size_t dest_size) +{ + static const char* const fmt = "Couldn't parse '%s' (possibly not complete input) as %s"; + const char* const src = err_details->params.parse_error.src; + const char* const what = err_details->params.parse_error.what; + + if (dest == NULL) + return snprintf(NULL, 0, fmt, src, what) + 1; + + snprintf(dest, dest_size, fmt, src, what); + return strlen(dest); +} + +static size_t aes_format_not_implemented_error( + const AES_ErrorDetails* err_details, + char* dest, + size_t dest_size) +{ + static const char* const fmt = "Not implemented: %s"; + const char* const src = err_details->params.not_implemented.what; + + if (dest == NULL) + return snprintf(NULL, 0, fmt, src) + 1; + + snprintf(dest, dest_size, fmt, src); + return strlen(dest); +} + +typedef size_t (*AES_ErrorFormatter)(const AES_ErrorDetails*, char*, size_t); + +static AES_ErrorFormatter err_formatters[] = +{ + &aes_format_error_strerror, + &aes_format_null_argument_error, + &aes_format_parse_error, + &aes_format_error_strerror, + &aes_format_not_implemented_error, + &aes_format_error_strerror, + &aes_format_error_strerror, +}; + +size_t aes_format_error( + const AES_ErrorDetails* err_details, + char* dest, + size_t dest_size) +{ + assert(err_details); + + return err_formatters[err_details->ec](err_details, dest, dest_size); +} + +#ifdef WIN32 +#include + +static void aes_collect_call_stack(AES_ErrorDetails* err_details) +{ + err_details->call_stack_len = CaptureStackBackTrace( + 1, AES_MAX_CALL_STACK_LENGTH, err_details->call_stack, NULL); +} +#else +static void aes_collect_call_stack(AES_ErrorDetails* err_details) +{ + err_details->call_stack_len = 0; +} +#endif + +static AES_StatusCode aes_make_error( + AES_ErrorDetails* err_details, + AES_StatusCode ec) +{ + if (err_details == NULL) + return ec; + + if (aes_is_error(ec)) + aes_collect_call_stack(err_details); + + return err_details->ec = ec; +} + +AES_StatusCode aes_success( + AES_ErrorDetails* err_details) +{ + return aes_make_error(err_details, AES_SUCCESS); +} + +AES_StatusCode aes_error_null_argument( + AES_ErrorDetails* err_details, + const char* param_name) +{ + AES_StatusCode status = aes_make_error(err_details, AES_NULL_ARGUMENT_ERROR); + + if (err_details != NULL) + aes_fill_string( + err_details->params.null_arg.param_name, + sizeof(err_details->params.null_arg.param_name), param_name); + + return status; +} + +AES_StatusCode aes_error_parse( + AES_ErrorDetails* err_details, + const char* src, + const char* what) +{ + AES_StatusCode status = aes_make_error(err_details, AES_PARSE_ERROR); + + if (err_details != NULL) + { + aes_fill_string( + err_details->params.parse_error.src, + sizeof(err_details->params.parse_error.src), src); + aes_fill_string( + err_details->params.parse_error.what, + sizeof(err_details->params.parse_error.what), what); + } + + return status; +} + +AES_StatusCode aes_error_invalid_pkcs7_padding( + AES_ErrorDetails* err_details) +{ + return aes_make_error(err_details, AES_INVALID_PKCS7_PADDING_ERROR); +} + +AES_StatusCode aes_error_not_implemented( + AES_ErrorDetails* err_details, + const char* what) +{ + AES_StatusCode status = aes_make_error(err_details, AES_NOT_IMPLEMENTED_ERROR); + + if (err_details != NULL) + aes_fill_string( + err_details->params.not_implemented.what, + sizeof(err_details->params.not_implemented.what), what); + + return status; +} + +AES_StatusCode aes_error_missing_padding( + AES_ErrorDetails* err_details) +{ + return aes_make_error(err_details, AES_MISSING_PADDING_ERROR); +} + +AES_StatusCode aes_error_memory_allocation( + AES_ErrorDetails* err_details) +{ + return aes_make_error(err_details, AES_MEMORY_ALLOCATION_ERROR); +} diff --git a/aes/src/padding.c b/aes/src/padding.c new file mode 100644 index 0000000..a161ec7 --- /dev/null +++ b/aes/src/padding.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2015 Egor Tensin + * This file is part of the "AES tools" project. + * For details, see https://github.com/egor-tensin/aes-tools. + * Distributed under the MIT License. + */ + +#include + +#include +#include +#include + +static AES_StatusCode aes_extract_padding_size_pkcs7( + const void* src, + size_t src_size, + size_t* padding_size, + AES_ErrorDetails* err_details) +{ + const unsigned char* cursor = (const unsigned char*) src + src_size - 1; + *padding_size = *cursor; + + for (size_t i = 1; i < *padding_size; ++i) + if (cursor[0 - i] != *padding_size) + return aes_error_invalid_pkcs7_padding(err_details); + + return AES_SUCCESS; +} + +AES_StatusCode aes_extract_padding_size( + AES_PaddingMethod method, + const void* src, + size_t src_size, + size_t* padding_size, + AES_ErrorDetails* err_details) +{ + assert(src); + assert(padding_size); + + if (src == NULL) + return aes_error_null_argument(err_details, "src"); + if (padding_size == NULL) + return aes_error_null_argument(err_details, "padding_size"); + + switch (method) + { + case AES_PADDING_PKCS7: + return aes_extract_padding_size_pkcs7( + src, src_size, padding_size, err_details); + + default: + return aes_error_not_implemented( + err_details, "unsupported padding method"); + } +} + +static AES_StatusCode aes_fill_with_padding_pkcs7( + void* dest, + size_t padding_size, + AES_ErrorDetails* err_details) +{ + AES_UNUSED_PARAMETER(err_details); + memset(dest, (int) padding_size, padding_size); + return AES_SUCCESS; +} + +AES_StatusCode aes_fill_with_padding( + AES_PaddingMethod method, + void* dest, + size_t padding_size, + AES_ErrorDetails* err_details) +{ + assert(dest); + + if (dest == NULL) + return aes_error_null_argument(err_details, "dest"); + + switch (method) + { + case AES_PADDING_PKCS7: + return aes_fill_with_padding_pkcs7( + dest, padding_size, err_details); + + default: + return aes_error_not_implemented( + err_details, "unsupported padding method"); + } +} diff --git a/aesxx/CMakeLists.txt b/aesxx/CMakeLists.txt new file mode 100644 index 0000000..9bbf777 --- /dev/null +++ b/aesxx/CMakeLists.txt @@ -0,0 +1,13 @@ +find_package(Boost REQUIRED) + +add_library(aesxx INTERFACE) +target_include_directories(aesxx INTERFACE include/) +target_link_libraries(aesxx INTERFACE aes Boost::boost) + +if(MSVC_VERSION EQUAL 1900) + # These annoying DbgHelp.h warnings: + # https://connect.microsoft.com/VisualStudio/feedback/details/888527/warnings-on-dbghelp-h + target_compile_options(aesxx INTERFACE /wd4091) +endif() + +install(DIRECTORY include/aesxx DESTINATION include) diff --git a/aesxx/include/aesxx/aes.hpp b/aesxx/include/aesxx/aes.hpp new file mode 100644 index 0000000..efac790 --- /dev/null +++ b/aesxx/include/aesxx/aes.hpp @@ -0,0 +1,275 @@ +// Copyright (c) 2015 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#include "algorithm.hpp" +#include "api.hpp" +#include "error.hpp" +#include "mode.hpp" + +#include + +#include + +#include + +namespace aes +{ + namespace aes128 + { + typedef AES_AES128_Block Block; + typedef AES_AES128_RoundKeys RoundKeys; + typedef AES_AES128_Key Key; + } + + template <> + struct Types + { + typedef aes128::Block Block; + typedef aes128::RoundKeys RoundKeys; + typedef aes128::Key Key; + }; + + template <> + inline std::size_t get_number_of_rounds() + { + return 11; + } + + template <> + inline void from_string(aes128::Block& dest, const char* src) + { + aes_AES128_parse_block(&dest, src, ErrorDetailsThrowsInDestructor{}); + } + + template <> + inline std::string to_string(const aes128::Block& src) + { + AES_AES128_BlockString str; + aes_AES128_format_block(&str, &src, ErrorDetailsThrowsInDestructor{}); + return {str.str}; + } + + template <> + inline std::string to_matrix_string(const aes128::Block& src) + { + AES_AES128_BlockMatrixString str; + aes_AES128_format_block_as_matrix(&str, &src, ErrorDetailsThrowsInDestructor{}); + return {str.str}; + } + + template <> + inline void from_string(aes128::Key& dest, const char* src) + { + aes_AES128_parse_key(&dest, src, ErrorDetailsThrowsInDestructor{}); + } + + template <> + inline std::string to_string(const aes128::Key& src) + { + AES_AES128_KeyString str; + aes_AES128_format_key(&str, &src, ErrorDetailsThrowsInDestructor{}); + return {str.str}; + } + + template <> + inline void expand_key( + const aes128::Key& key, + aes128::RoundKeys& encryption_keys) + { + aes_AES128_expand_key(&key, &encryption_keys); + } + + template <> + inline void derive_decryption_keys( + const aes128::RoundKeys& encryption_keys, + aes128::RoundKeys& decryption_keys) + { + aes_AES128_derive_decryption_keys( + &encryption_keys, &decryption_keys); + } + + AESXX_ENCRYPT_BLOCK_ECB(AES128); + AESXX_DECRYPT_BLOCK_ECB(AES128); + AESXX_ENCRYPT_BLOCK_CBC(AES128); + AESXX_DECRYPT_BLOCK_CBC(AES128); + AESXX_ENCRYPT_BLOCK_CFB(AES128); + AESXX_DECRYPT_BLOCK_CFB(AES128); + AESXX_ENCRYPT_BLOCK_OFB(AES128); + AESXX_DECRYPT_BLOCK_OFB(AES128); + AESXX_ENCRYPT_BLOCK_CTR(AES128); + AESXX_DECRYPT_BLOCK_CTR(AES128); + + namespace aes192 + { + typedef AES_AES192_Block Block; + typedef AES_AES192_RoundKeys RoundKeys; + typedef AES_AES192_Key Key; + } + + template <> + struct Types + { + typedef aes192::Block Block; + typedef aes192::RoundKeys RoundKeys; + typedef aes192::Key Key; + }; + + template <> + inline std::size_t get_number_of_rounds() + { + return 13; + } + + template <> + inline void from_string(aes192::Block& dest, const char* src) + { + aes_AES192_parse_block(&dest, src, ErrorDetailsThrowsInDestructor{}); + } + + template <> + inline std::string to_string(const aes192::Block& src) + { + AES_AES192_BlockString str; + aes_AES192_format_block(&str, &src, ErrorDetailsThrowsInDestructor{}); + return {str.str}; + } + + template <> + inline std::string to_matrix_string(const aes192::Block& src) + { + AES_AES192_BlockMatrixString str; + aes_AES192_format_block_as_matrix(&str, &src, ErrorDetailsThrowsInDestructor{}); + return {str.str}; + } + + template <> + inline void from_string(aes192::Key& dest, const char* src) + { + aes_AES192_parse_key(&dest, src, ErrorDetailsThrowsInDestructor{}); + } + + template <> + inline std::string to_string(const aes192::Key& src) + { + AES_AES192_KeyString str; + aes_AES192_format_key(&str, &src, ErrorDetailsThrowsInDestructor{}); + return {str.str}; + } + + template <> + inline void expand_key( + const aes192::Key& key, + aes192::RoundKeys& encryption_keys) + { + aes_AES192_expand_key(&key, &encryption_keys); + } + + template <> + inline void derive_decryption_keys( + const aes192::RoundKeys& encryption_keys, + aes192::RoundKeys& decryption_keys) + { + aes_AES192_derive_decryption_keys( + &encryption_keys, &decryption_keys); + } + + AESXX_ENCRYPT_BLOCK_ECB(AES192); + AESXX_DECRYPT_BLOCK_ECB(AES192); + AESXX_ENCRYPT_BLOCK_CBC(AES192); + AESXX_DECRYPT_BLOCK_CBC(AES192); + AESXX_ENCRYPT_BLOCK_CFB(AES192); + AESXX_DECRYPT_BLOCK_CFB(AES192); + AESXX_ENCRYPT_BLOCK_OFB(AES192); + AESXX_DECRYPT_BLOCK_OFB(AES192); + AESXX_ENCRYPT_BLOCK_CTR(AES192); + AESXX_DECRYPT_BLOCK_CTR(AES192); + + namespace aes256 + { + typedef AES_AES256_Block Block; + typedef AES_AES256_RoundKeys RoundKeys; + typedef AES_AES256_Key Key; + } + + template <> + struct Types + { + typedef aes256::Block Block; + typedef aes256::RoundKeys RoundKeys; + typedef aes256::Key Key; + }; + + template <> + inline std::size_t get_number_of_rounds() + { + return 15; + } + + template <> + inline void from_string(aes256::Block& dest, const char* src) + { + aes_AES256_parse_block(&dest, src, ErrorDetailsThrowsInDestructor{}); + } + + template <> + inline std::string to_string(const aes256::Block& src) + { + AES_AES256_BlockString str; + aes_AES256_format_block(&str, &src, ErrorDetailsThrowsInDestructor{}); + return {str.str}; + } + + template <> + inline std::string to_matrix_string(const aes256::Block& src) + { + AES_AES256_BlockMatrixString str; + aes_AES256_format_block_as_matrix(&str, &src, ErrorDetailsThrowsInDestructor{}); + return {str.str}; + } + + template <> + inline void from_string(aes256::Key& dest, const char* src) + { + aes_AES256_parse_key(&dest, src, ErrorDetailsThrowsInDestructor{}); + } + + template <> + inline std::string to_string(const aes256::Key& src) + { + AES_AES256_KeyString str; + aes_AES256_format_key(&str, &src, ErrorDetailsThrowsInDestructor{}); + return {str.str}; + } + + template <> + inline void expand_key( + const aes256::Key& key, + aes256::RoundKeys& encryption_keys) + { + aes_AES256_expand_key(&key, &encryption_keys); + } + + template <> + inline void derive_decryption_keys( + const aes256::RoundKeys& encryption_keys, + aes256::RoundKeys& decryption_keys) + { + aes_AES256_derive_decryption_keys( + &encryption_keys, &decryption_keys); + } + + AESXX_ENCRYPT_BLOCK_ECB(AES256); + AESXX_DECRYPT_BLOCK_ECB(AES256); + AESXX_ENCRYPT_BLOCK_CBC(AES256); + AESXX_DECRYPT_BLOCK_CBC(AES256); + AESXX_ENCRYPT_BLOCK_CFB(AES256); + AESXX_DECRYPT_BLOCK_CFB(AES256); + AESXX_ENCRYPT_BLOCK_OFB(AES256); + AESXX_DECRYPT_BLOCK_OFB(AES256); + AESXX_ENCRYPT_BLOCK_CTR(AES256); + AESXX_DECRYPT_BLOCK_CTR(AES256); +} diff --git a/aesxx/include/aesxx/algorithm.hpp b/aesxx/include/aesxx/algorithm.hpp new file mode 100644 index 0000000..823e57f --- /dev/null +++ b/aesxx/include/aesxx/algorithm.hpp @@ -0,0 +1,13 @@ +// Copyright (c) 2015 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#include + +namespace aes +{ + typedef AES_Algorithm Algorithm; +} diff --git a/aesxx/include/aesxx/all.hpp b/aesxx/include/aesxx/all.hpp new file mode 100644 index 0000000..99202a7 --- /dev/null +++ b/aesxx/include/aesxx/all.hpp @@ -0,0 +1,15 @@ +// Copyright (c) 2015 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#include "aes.hpp" +#include "algorithm.hpp" +#include "api.hpp" +#include "box.hpp" +#include "data.hpp" +#include "debug.hpp" +#include "error.hpp" +#include "mode.hpp" diff --git a/aesxx/include/aesxx/api.hpp b/aesxx/include/aesxx/api.hpp new file mode 100644 index 0000000..68112bf --- /dev/null +++ b/aesxx/include/aesxx/api.hpp @@ -0,0 +1,174 @@ +// Copyright (c) 2015 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#include "algorithm.hpp" +#include "mode.hpp" + +#include + +#include +#include + +namespace aes +{ + template + struct Types; + + template + std::size_t get_number_of_rounds(); + + template + void from_string( + typename Types::Block&, + const char*); + + template + void from_string( + typename Types::Block& dest, + const std::string& src) + { + from_string(dest, src.c_str()); + } + + template + std::string to_string(const typename Types::Block&); + + template + std::string to_matrix_string(const typename Types::Block&); + + template + void from_string( + typename Types::Key&, + const char*); + + template + void from_string( + typename Types::Key& dest, + const std::string& src) + { + from_string(dest, src.c_str()); + } + + template + std::string to_string(const typename Types::Key&); + + template + void expand_key( + const typename Types::Key& key, + typename Types::RoundKeys& encryption_keys); + + template + void derive_decryption_keys( + const typename Types::RoundKeys& encryption_keys, + typename Types::RoundKeys& decryption_keys); + + template ::value>::type* = nullptr> + void encrypt_block( + const typename Types::Block& plaintext, + const typename Types::RoundKeys& round_keys, + typename Types::Block& iv, + typename Types::Block& ciphertext); + + template ::value>::type* = nullptr> + void encrypt_block( + const typename Types::Block& plaintext, + const typename Types::RoundKeys& round_keys, + typename Types::Block& ciphertext); + + template ::value>::type* = nullptr> + void encrypt_block( + const typename Types::Block& plaintext, + const typename Types::RoundKeys& round_keys, + typename Types::Block&, + typename Types::Block& ciphertext) + { + encrypt_block(plaintext, round_keys, ciphertext); + } + + template ::value>::type* = nullptr> + void decrypt_block( + const typename Types::Block& ciphertext, + const typename Types::RoundKeys& round_keys, + typename Types::Block& iv, + typename Types::Block& plaintext); + + template ::value>::type* = nullptr> + void decrypt_block( + const typename Types::Block& ciphertext, + const typename Types::RoundKeys& round_keys, + typename Types::Block& plaintext); + + template ::value>::type* = nullptr> + void decrypt_block( + const typename Types::Block& ciphertext, + const typename Types::RoundKeys& round_keys, + typename Types::Block&, + typename Types::Block& plaintext) + { + decrypt_block(ciphertext, round_keys, plaintext); + } + + template + struct EncryptWrapper + { + EncryptWrapper( + const typename Types::Key& key, + const typename Types::Block& iv) : iv{iv} + { + expand_key(key, encryption_keys); + } + + void encrypt_block( + const typename Types::Block& plaintext, + typename Types::Block& ciphertext) + { + aes::encrypt_block( + plaintext, encryption_keys, iv, ciphertext); + } + + typename Types::Block iv; + typename Types::RoundKeys encryption_keys; + }; + + template + struct DecryptWrapper + { + DecryptWrapper( + const typename Types::Key& key, + const typename Types::Block& iv) : iv{iv} + { + typename Types::RoundKeys encryption_keys; + expand_key(key, encryption_keys); + + if (ModeUsesEncryptionKeysOnly::value) + { + decryption_keys = encryption_keys; + } + else + { + derive_decryption_keys(encryption_keys, decryption_keys); + } + } + + void decrypt_block( + const typename Types::Block& ciphertext, + typename Types::Block& plaintext) + { + aes::decrypt_block( + ciphertext, decryption_keys, iv, plaintext); + } + + typename Types::Block iv; + typename Types::RoundKeys decryption_keys; + }; +} diff --git a/aesxx/include/aesxx/box.hpp b/aesxx/include/aesxx/box.hpp new file mode 100644 index 0000000..076407c --- /dev/null +++ b/aesxx/include/aesxx/box.hpp @@ -0,0 +1,207 @@ +// Copyright (c) 2015 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#include "algorithm.hpp" +#include "error.hpp" +#include "mode.hpp" + +#include + +#include + +#include +#include + +namespace aes +{ + class Box + { + public: + typedef AES_BoxBlock Block; + typedef AES_BoxKey Key; + + static std::string format_key(const Key& src, Algorithm algorithm) + { + AES_BoxKeyString str; + aes_box_format_key( + &str, algorithm, &src, ErrorDetailsThrowsInDestructor{}); + return reinterpret_cast(&str); + } + + static std::string format_block(const Block& src, Algorithm algorithm) + { + AES_BoxBlockString str; + aes_box_format_block( + &str, algorithm, &src, ErrorDetailsThrowsInDestructor{}); + return reinterpret_cast(&str); + } + + static void parse_block( + Block& dest, + Algorithm algorithm, + const char* src) + { + aes_box_parse_block(&dest, algorithm, src, + ErrorDetailsThrowsInDestructor{}); + } + + static void parse_block( + Block& dest, + Algorithm algorithm, + const std::string& src) + { + parse_block(dest, algorithm, src.c_str()); + } + + static void parse_key( + Key& dest, + Algorithm algorithm, + const char* src) + { + aes_box_parse_key(&dest, algorithm, src, + ErrorDetailsThrowsInDestructor{}); + } + + static void parse_key( + Key& dest, + Algorithm algorithm, + const std::string& src) + { + parse_key(dest, algorithm, src.c_str()); + } + + Box(Algorithm algorithm, const Key& key) + : algorithm{algorithm} + , mode{AES_ECB} + { + aes_box_init(&impl, algorithm, &key, mode, nullptr, + ErrorDetailsThrowsInDestructor{}); + } + + Box(Algorithm algorithm, const Key& key, Mode mode, const Block& iv) + : algorithm{algorithm} + , mode{mode} + { + aes_box_init(&impl, algorithm, &key, mode, &iv, + ErrorDetailsThrowsInDestructor{}); + } + + void encrypt_block(const Block& plaintext, Block& ciphertext) + { + aes_box_encrypt_block( + &impl, &plaintext, &ciphertext, + ErrorDetailsThrowsInDestructor{}); + } + + void decrypt_block(const Block& ciphertext, Block& plaintext) + { + aes_box_decrypt_block( + &impl, &ciphertext, &plaintext, + ErrorDetailsThrowsInDestructor{}); + } + + std::vector encrypt_buffer( + const void* src_buf, + std::size_t src_size) + { + std::size_t dest_size = 0; + + aes_box_encrypt_buffer( + &impl, + src_buf, + src_size, + nullptr, + &dest_size, + aes::ErrorDetailsThrowsInDestructor{}); + + std::vector dest_buf; + dest_buf.resize(dest_size); + + aes_box_encrypt_buffer( + &impl, + src_buf, + src_size, + dest_buf.data(), + &dest_size, + aes::ErrorDetailsThrowsInDestructor{}); + + dest_buf.resize(dest_size); + return dest_buf; + } + + std::vector decrypt_buffer( + const void* src_buf, + std::size_t src_size) + { + std::size_t dest_size = 0; + + aes_box_decrypt_buffer( + &impl, + src_buf, + src_size, + nullptr, + &dest_size, + aes::ErrorDetailsThrowsInDestructor{}); + + std::vector dest_buf; + dest_buf.resize(dest_size); + + aes_box_decrypt_buffer( + &impl, + src_buf, + src_size, + dest_buf.data(), + &dest_size, + aes::ErrorDetailsThrowsInDestructor{}); + + dest_buf.resize(dest_size); + return dest_buf; + } + + std::string format_block(const Block& src) + { + return format_block(src, get_algorithm()); + } + + std::string format_key(const Key& src) + { + return format_key(src, get_algorithm()); + } + + void parse_block(Block& dest, const char* src) + { + parse_block(dest, get_algorithm(), src); + } + + void parse_block(Block& dest, const std::string& src) + { + parse_block(dest, src.c_str()); + } + + void parse_key(Key& dest, const char* src) + { + parse_key(dest, get_algorithm(), src); + } + + void parse_key(Key& dest, const std::string& src) + { + parse_key(dest, src.c_str()); + } + + Algorithm get_algorithm() const { return algorithm; } + + Mode get_mode() const { return mode; } + + private: + Key key; + + Algorithm algorithm; + Mode mode; + + AES_Box impl; + }; +} diff --git a/aesxx/include/aesxx/data.hpp b/aesxx/include/aesxx/data.hpp new file mode 100644 index 0000000..f36df5e --- /dev/null +++ b/aesxx/include/aesxx/data.hpp @@ -0,0 +1,55 @@ +// Copyright (c) 2015 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#include "error.hpp" + +#include + +namespace aes +{ + typedef AES_Block128 Block128; + + inline void make_block(Block128& dest, int hi3, int hi2, int lo1, int lo0) + { + dest = aes_make_block128(hi3, hi2, lo1, lo0); + } + + inline void load_block(Block128& dest, const void* src) + { + dest = aes_load_block128(src); + } + + inline void load_block_aligned(Block128& dest, const void* src) + { + dest = aes_load_block128_aligned(src); + } + + inline void store_block(void* dest, Block128& src) + { + aes_store_block128(dest, src); + } + + inline void store_block_aligned(void* dest, Block128& src) + { + aes_store_block128_aligned(dest, src); + } + + inline Block128 xor_blocks(Block128& a, Block128& b) + { + return aes_xor_block128(a, b); + } + + inline Block128 reverse_byte_order(Block128& block) + { + return aes_reverse_byte_order_block128(block); + } + + inline Block128 inc_block(Block128& block) + { + return aes_inc_block128(block); + } +} diff --git a/aesxx/include/aesxx/debug.hpp b/aesxx/include/aesxx/debug.hpp new file mode 100644 index 0000000..96e81b5 --- /dev/null +++ b/aesxx/include/aesxx/debug.hpp @@ -0,0 +1,174 @@ +// Copyright (c) 2015 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#ifdef WIN32 +#include +#include +#pragma comment(lib, "DbgHelp.Lib") +#endif + +#include + +#include +#include + +namespace aes +{ + namespace aux + { + class CallStackFormatter + { + public: + CallStackFormatter() = default; + + std::string format_address(const void* addr) const + { + #ifdef WIN32 + return format_address_win32(addr); + #else + return format_address_fallback(addr); + #endif + } + + private: + template + static std::string put_between_brackets(const T& x) + { + std::ostringstream oss; + oss << "[" << x << "]"; + return oss.str(); + } + + template + static std::string stringify(const T& x) + { + std::ostringstream oss; + oss << x; + return oss.str(); + } + + static std::string format_address_fallback(const void* addr) + { + return put_between_brackets(addr); + } + + static std::string format_module( + const std::string& module_name, + const void* offset = nullptr) + { + if (offset == nullptr) + return put_between_brackets(module_name); + else + return put_between_brackets(module_name + "+" + stringify(offset)); + } + + static std::string format_symbol( + const std::string& symbol_name, + const void* offset = nullptr) + { + return format_module(symbol_name, offset); + } + + static std::string format_symbol( + const std::string& module_name, + const std::string& symbol_name, + const void* offset = nullptr) + { + return format_symbol(module_name + "!" + symbol_name, offset); + } + + #ifdef WIN32 + class DbgHelp + { + public: + DbgHelp() + { + initialized_flag = SymInitialize(GetCurrentProcess(), NULL, TRUE) != FALSE; + } + + bool initialized() const + { + return initialized_flag; + } + + ~DbgHelp() + { + if (initialized_flag) + SymCleanup(GetCurrentProcess()); + } + + private: + bool initialized_flag = false; + + DbgHelp(const DbgHelp&) = delete; + DbgHelp& operator=(const DbgHelp&) = delete; + }; + + DbgHelp dbghelp; + + std::string format_address_win32(const void* addr) const + { + if (!dbghelp.initialized()) + return format_address_fallback(addr); + + DWORD64 symbol_info_buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME]; + const auto symbol_info = reinterpret_cast(symbol_info_buf); + symbol_info->SizeOfStruct = sizeof(SYMBOL_INFO); + symbol_info->MaxNameLen = MAX_SYM_NAME; + + IMAGEHLP_MODULE64 module_info; + module_info.SizeOfStruct = sizeof(IMAGEHLP_MODULE64); + + DWORD64 symbol_offset; + + const auto symbol_resolved = SymFromAddr( + GetCurrentProcess(), + reinterpret_cast(addr), + &symbol_offset, + symbol_info); + + if (symbol_resolved) + { + const auto module_resolved = SymGetModuleInfo64( + GetCurrentProcess(), + symbol_info->ModBase, + &module_info); + + if (module_resolved) + { + return format_symbol( + module_info.ModuleName, + symbol_info->Name, + reinterpret_cast(symbol_offset)); + } + else + { + return format_symbol(symbol_info->Name, addr); + } + } + else + { + const auto module_resolved = SymGetModuleInfo64( + GetCurrentProcess(), + reinterpret_cast(addr), + &module_info); + + if (module_resolved) + { + const auto module_offset = reinterpret_cast(addr) - module_info.BaseOfImage; + return format_module(module_info.ModuleName, module_offset); + } + else + { + return format_address_fallback(addr); + } + } + } + #endif + }; + } +} diff --git a/aesxx/include/aesxx/error.hpp b/aesxx/include/aesxx/error.hpp new file mode 100644 index 0000000..4d2c783 --- /dev/null +++ b/aesxx/include/aesxx/error.hpp @@ -0,0 +1,104 @@ +// Copyright (c) 2015 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#include "debug.hpp" + +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace aes +{ + class Error : public std::runtime_error + { + public: + Error(const AES_ErrorDetails& err_details) + : std::runtime_error{format_error_message(err_details)} + { + fill_call_stack(err_details); + } + + void for_each_addr( + const std::function& callback) const + { + aux::CallStackFormatter formatter; + + std::for_each( + call_stack, + call_stack + call_stack_len, + [&formatter, &callback] (const void* addr) + { + callback(addr, formatter.format_address(addr)); + }); + } + + private: + static std::string format_error_message(const AES_ErrorDetails& err_details) + { + std::vector buf; + buf.resize(aes_format_error(&err_details, NULL, 0)); + aes_format_error(&err_details, buf.data(), buf.size()); + return {buf.begin(), buf.end()}; + } + + void fill_call_stack(const AES_ErrorDetails& err_details) + { + call_stack_len = err_details.call_stack_len; + + if (call_stack_len > AES_MAX_CALL_STACK_LENGTH) + call_stack_len = AES_MAX_CALL_STACK_LENGTH; + + std::memcpy(call_stack, err_details.call_stack, call_stack_len * sizeof(const void*)); + } + + std::size_t call_stack_len = 0; + const void* call_stack[AES_MAX_CALL_STACK_LENGTH] = {nullptr}; + }; + + inline std::ostream& operator<<(std::ostream& os, const Error& error) + { + os << "AES error: " << error.what() << '\n'; + os << "Call stack:\n"; + error.for_each_addr([&os] (const void* addr, const std::string& name) + { + os << '\t' << addr << ' ' << name << '\n'; + }); + return os; + } + + class ErrorDetailsThrowsInDestructor + { + public: + ErrorDetailsThrowsInDestructor() + { + aes_success(get()); + } + + ~ErrorDetailsThrowsInDestructor() BOOST_NOEXCEPT_IF(false) + { + if (aes_is_error(aes_get_error_code(get()))) + throw Error(impl); + } + + AES_ErrorDetails* get() { return &impl; } + + operator AES_ErrorDetails*() { return get(); } + + private: + AES_ErrorDetails impl; + }; +} diff --git a/aesxx/include/aesxx/mode.hpp b/aesxx/include/aesxx/mode.hpp new file mode 100644 index 0000000..1c6c4cf --- /dev/null +++ b/aesxx/include/aesxx/mode.hpp @@ -0,0 +1,153 @@ +// Copyright (c) 2015 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#include + +#include + +namespace aes +{ + typedef AES_Mode Mode; + + template + struct ModeRequiresInitVector : public std::true_type + { }; + + template <> + struct ModeRequiresInitVector : public std::false_type + { }; + + template + struct ModeUsesEncryptionKeysOnly : public std::true_type + { }; + + inline bool mode_requires_init_vector(Mode mode) + { + return mode != AES_ECB; + } + + template <> + struct ModeUsesEncryptionKeysOnly : public std::false_type + { }; + + template <> + struct ModeUsesEncryptionKeysOnly : public std::false_type + { }; + + inline bool mode_uses_encryption_keys_only(Mode mode) + { + return mode != AES_ECB && mode != AES_CBC; + } + +#define AESXX_ENCRYPT_BLOCK_ECB(prefix) \ + template <> \ + inline void encrypt_block( \ + const typename Types::Block& plaintext, \ + const typename Types::RoundKeys& encryption_keys, \ + typename Types::Block& ciphertext) \ + { \ + ciphertext = aes_## prefix ##_encrypt_block_ECB(plaintext, &encryption_keys); \ + } + +#define AESXX_DECRYPT_BLOCK_ECB(prefix) \ + template <> \ + inline void decrypt_block( \ + const typename Types::Block& ciphertext, \ + const typename Types::RoundKeys& decryption_keys, \ + typename Types::Block& plaintext) \ + { \ + plaintext = aes_## prefix ##_decrypt_block_ECB(ciphertext, &decryption_keys); \ + } + +#define AESXX_ENCRYPT_BLOCK_CBC(prefix) \ + template <> \ + inline void encrypt_block( \ + const typename Types::Block& plaintext, \ + const typename Types::RoundKeys& encryption_keys, \ + typename Types::Block& iv, \ + typename Types::Block& ciphertext) \ + { \ + ciphertext = aes_## prefix ##_encrypt_block_CBC(plaintext, &encryption_keys, iv, &iv); \ + } + +#define AESXX_DECRYPT_BLOCK_CBC(prefix) \ + template <> \ + inline void decrypt_block( \ + const typename Types::Block& ciphertext, \ + const typename Types::RoundKeys& decryption_keys, \ + typename Types::Block& iv, \ + typename Types::Block& plaintext) \ + { \ + plaintext = aes_## prefix ##_decrypt_block_CBC(ciphertext, &decryption_keys, iv, &iv); \ + } + +#define AESXX_ENCRYPT_BLOCK_CFB(prefix) \ + template <> \ + inline void encrypt_block( \ + const typename Types::Block& plaintext, \ + const typename Types::RoundKeys& encryption_keys, \ + typename Types::Block& iv, \ + typename Types::Block& ciphertext) \ + { \ + ciphertext = aes_## prefix ##_encrypt_block_CFB(plaintext, &encryption_keys, iv, &iv); \ + } + +#define AESXX_DECRYPT_BLOCK_CFB(prefix) \ + template <> \ + inline void decrypt_block( \ + const typename Types::Block& ciphertext, \ + const typename Types::RoundKeys& encryption_keys, \ + typename Types::Block& iv, \ + typename Types::Block& plaintext) \ + { \ + plaintext = aes_## prefix ##_decrypt_block_CFB(ciphertext, &encryption_keys, iv, &iv); \ + } + +#define AESXX_ENCRYPT_BLOCK_OFB(prefix) \ + template <> \ + inline void encrypt_block( \ + const typename Types::Block& plaintext, \ + const typename Types::RoundKeys& encryption_keys, \ + typename Types::Block& iv, \ + typename Types::Block& ciphertext) \ + { \ + ciphertext = aes_## prefix ##_encrypt_block_OFB(plaintext, &encryption_keys, iv, &iv); \ + } + +#define AESXX_DECRYPT_BLOCK_OFB(prefix) \ + template <> \ + inline void decrypt_block( \ + const typename Types::Block& ciphertext, \ + const typename Types::RoundKeys& encryption_keys, \ + typename Types::Block& iv, \ + typename Types::Block& plaintext) \ + { \ + plaintext = aes_## prefix ##_decrypt_block_OFB(ciphertext, &encryption_keys, iv, &iv); \ + } + +#define AESXX_ENCRYPT_BLOCK_CTR(prefix) \ + template <> \ + inline void encrypt_block( \ + const typename Types::Block& plaintext, \ + const typename Types::RoundKeys& encryption_keys, \ + typename Types::Block& iv, \ + typename Types::Block& ciphertext) \ + { \ + ciphertext = aes_## prefix ##_encrypt_block_CTR(plaintext, &encryption_keys, iv, &iv); \ + } + +#define AESXX_DECRYPT_BLOCK_CTR(prefix) \ + template <> \ + inline void decrypt_block( \ + const typename Types::Block& ciphertext, \ + const typename Types::RoundKeys& encryption_keys, \ + typename Types::Block& iv, \ + typename Types::Block& plaintext) \ + { \ + plaintext = aes_## prefix ##_decrypt_block_CTR(ciphertext, &encryption_keys, iv, &iv); \ + } +} diff --git a/cxx/CMakeLists.txt b/cxx/CMakeLists.txt deleted file mode 100644 index 9bbf777..0000000 --- a/cxx/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -find_package(Boost REQUIRED) - -add_library(aesxx INTERFACE) -target_include_directories(aesxx INTERFACE include/) -target_link_libraries(aesxx INTERFACE aes Boost::boost) - -if(MSVC_VERSION EQUAL 1900) - # These annoying DbgHelp.h warnings: - # https://connect.microsoft.com/VisualStudio/feedback/details/888527/warnings-on-dbghelp-h - target_compile_options(aesxx INTERFACE /wd4091) -endif() - -install(DIRECTORY include/aesxx DESTINATION include) diff --git a/cxx/include/aesxx/aes.hpp b/cxx/include/aesxx/aes.hpp deleted file mode 100644 index efac790..0000000 --- a/cxx/include/aesxx/aes.hpp +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright (c) 2015 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#include "algorithm.hpp" -#include "api.hpp" -#include "error.hpp" -#include "mode.hpp" - -#include - -#include - -#include - -namespace aes -{ - namespace aes128 - { - typedef AES_AES128_Block Block; - typedef AES_AES128_RoundKeys RoundKeys; - typedef AES_AES128_Key Key; - } - - template <> - struct Types - { - typedef aes128::Block Block; - typedef aes128::RoundKeys RoundKeys; - typedef aes128::Key Key; - }; - - template <> - inline std::size_t get_number_of_rounds() - { - return 11; - } - - template <> - inline void from_string(aes128::Block& dest, const char* src) - { - aes_AES128_parse_block(&dest, src, ErrorDetailsThrowsInDestructor{}); - } - - template <> - inline std::string to_string(const aes128::Block& src) - { - AES_AES128_BlockString str; - aes_AES128_format_block(&str, &src, ErrorDetailsThrowsInDestructor{}); - return {str.str}; - } - - template <> - inline std::string to_matrix_string(const aes128::Block& src) - { - AES_AES128_BlockMatrixString str; - aes_AES128_format_block_as_matrix(&str, &src, ErrorDetailsThrowsInDestructor{}); - return {str.str}; - } - - template <> - inline void from_string(aes128::Key& dest, const char* src) - { - aes_AES128_parse_key(&dest, src, ErrorDetailsThrowsInDestructor{}); - } - - template <> - inline std::string to_string(const aes128::Key& src) - { - AES_AES128_KeyString str; - aes_AES128_format_key(&str, &src, ErrorDetailsThrowsInDestructor{}); - return {str.str}; - } - - template <> - inline void expand_key( - const aes128::Key& key, - aes128::RoundKeys& encryption_keys) - { - aes_AES128_expand_key(&key, &encryption_keys); - } - - template <> - inline void derive_decryption_keys( - const aes128::RoundKeys& encryption_keys, - aes128::RoundKeys& decryption_keys) - { - aes_AES128_derive_decryption_keys( - &encryption_keys, &decryption_keys); - } - - AESXX_ENCRYPT_BLOCK_ECB(AES128); - AESXX_DECRYPT_BLOCK_ECB(AES128); - AESXX_ENCRYPT_BLOCK_CBC(AES128); - AESXX_DECRYPT_BLOCK_CBC(AES128); - AESXX_ENCRYPT_BLOCK_CFB(AES128); - AESXX_DECRYPT_BLOCK_CFB(AES128); - AESXX_ENCRYPT_BLOCK_OFB(AES128); - AESXX_DECRYPT_BLOCK_OFB(AES128); - AESXX_ENCRYPT_BLOCK_CTR(AES128); - AESXX_DECRYPT_BLOCK_CTR(AES128); - - namespace aes192 - { - typedef AES_AES192_Block Block; - typedef AES_AES192_RoundKeys RoundKeys; - typedef AES_AES192_Key Key; - } - - template <> - struct Types - { - typedef aes192::Block Block; - typedef aes192::RoundKeys RoundKeys; - typedef aes192::Key Key; - }; - - template <> - inline std::size_t get_number_of_rounds() - { - return 13; - } - - template <> - inline void from_string(aes192::Block& dest, const char* src) - { - aes_AES192_parse_block(&dest, src, ErrorDetailsThrowsInDestructor{}); - } - - template <> - inline std::string to_string(const aes192::Block& src) - { - AES_AES192_BlockString str; - aes_AES192_format_block(&str, &src, ErrorDetailsThrowsInDestructor{}); - return {str.str}; - } - - template <> - inline std::string to_matrix_string(const aes192::Block& src) - { - AES_AES192_BlockMatrixString str; - aes_AES192_format_block_as_matrix(&str, &src, ErrorDetailsThrowsInDestructor{}); - return {str.str}; - } - - template <> - inline void from_string(aes192::Key& dest, const char* src) - { - aes_AES192_parse_key(&dest, src, ErrorDetailsThrowsInDestructor{}); - } - - template <> - inline std::string to_string(const aes192::Key& src) - { - AES_AES192_KeyString str; - aes_AES192_format_key(&str, &src, ErrorDetailsThrowsInDestructor{}); - return {str.str}; - } - - template <> - inline void expand_key( - const aes192::Key& key, - aes192::RoundKeys& encryption_keys) - { - aes_AES192_expand_key(&key, &encryption_keys); - } - - template <> - inline void derive_decryption_keys( - const aes192::RoundKeys& encryption_keys, - aes192::RoundKeys& decryption_keys) - { - aes_AES192_derive_decryption_keys( - &encryption_keys, &decryption_keys); - } - - AESXX_ENCRYPT_BLOCK_ECB(AES192); - AESXX_DECRYPT_BLOCK_ECB(AES192); - AESXX_ENCRYPT_BLOCK_CBC(AES192); - AESXX_DECRYPT_BLOCK_CBC(AES192); - AESXX_ENCRYPT_BLOCK_CFB(AES192); - AESXX_DECRYPT_BLOCK_CFB(AES192); - AESXX_ENCRYPT_BLOCK_OFB(AES192); - AESXX_DECRYPT_BLOCK_OFB(AES192); - AESXX_ENCRYPT_BLOCK_CTR(AES192); - AESXX_DECRYPT_BLOCK_CTR(AES192); - - namespace aes256 - { - typedef AES_AES256_Block Block; - typedef AES_AES256_RoundKeys RoundKeys; - typedef AES_AES256_Key Key; - } - - template <> - struct Types - { - typedef aes256::Block Block; - typedef aes256::RoundKeys RoundKeys; - typedef aes256::Key Key; - }; - - template <> - inline std::size_t get_number_of_rounds() - { - return 15; - } - - template <> - inline void from_string(aes256::Block& dest, const char* src) - { - aes_AES256_parse_block(&dest, src, ErrorDetailsThrowsInDestructor{}); - } - - template <> - inline std::string to_string(const aes256::Block& src) - { - AES_AES256_BlockString str; - aes_AES256_format_block(&str, &src, ErrorDetailsThrowsInDestructor{}); - return {str.str}; - } - - template <> - inline std::string to_matrix_string(const aes256::Block& src) - { - AES_AES256_BlockMatrixString str; - aes_AES256_format_block_as_matrix(&str, &src, ErrorDetailsThrowsInDestructor{}); - return {str.str}; - } - - template <> - inline void from_string(aes256::Key& dest, const char* src) - { - aes_AES256_parse_key(&dest, src, ErrorDetailsThrowsInDestructor{}); - } - - template <> - inline std::string to_string(const aes256::Key& src) - { - AES_AES256_KeyString str; - aes_AES256_format_key(&str, &src, ErrorDetailsThrowsInDestructor{}); - return {str.str}; - } - - template <> - inline void expand_key( - const aes256::Key& key, - aes256::RoundKeys& encryption_keys) - { - aes_AES256_expand_key(&key, &encryption_keys); - } - - template <> - inline void derive_decryption_keys( - const aes256::RoundKeys& encryption_keys, - aes256::RoundKeys& decryption_keys) - { - aes_AES256_derive_decryption_keys( - &encryption_keys, &decryption_keys); - } - - AESXX_ENCRYPT_BLOCK_ECB(AES256); - AESXX_DECRYPT_BLOCK_ECB(AES256); - AESXX_ENCRYPT_BLOCK_CBC(AES256); - AESXX_DECRYPT_BLOCK_CBC(AES256); - AESXX_ENCRYPT_BLOCK_CFB(AES256); - AESXX_DECRYPT_BLOCK_CFB(AES256); - AESXX_ENCRYPT_BLOCK_OFB(AES256); - AESXX_DECRYPT_BLOCK_OFB(AES256); - AESXX_ENCRYPT_BLOCK_CTR(AES256); - AESXX_DECRYPT_BLOCK_CTR(AES256); -} diff --git a/cxx/include/aesxx/algorithm.hpp b/cxx/include/aesxx/algorithm.hpp deleted file mode 100644 index 823e57f..0000000 --- a/cxx/include/aesxx/algorithm.hpp +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) 2015 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#include - -namespace aes -{ - typedef AES_Algorithm Algorithm; -} diff --git a/cxx/include/aesxx/all.hpp b/cxx/include/aesxx/all.hpp deleted file mode 100644 index 99202a7..0000000 --- a/cxx/include/aesxx/all.hpp +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2015 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#include "aes.hpp" -#include "algorithm.hpp" -#include "api.hpp" -#include "box.hpp" -#include "data.hpp" -#include "debug.hpp" -#include "error.hpp" -#include "mode.hpp" diff --git a/cxx/include/aesxx/api.hpp b/cxx/include/aesxx/api.hpp deleted file mode 100644 index 68112bf..0000000 --- a/cxx/include/aesxx/api.hpp +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright (c) 2015 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#include "algorithm.hpp" -#include "mode.hpp" - -#include - -#include -#include - -namespace aes -{ - template - struct Types; - - template - std::size_t get_number_of_rounds(); - - template - void from_string( - typename Types::Block&, - const char*); - - template - void from_string( - typename Types::Block& dest, - const std::string& src) - { - from_string(dest, src.c_str()); - } - - template - std::string to_string(const typename Types::Block&); - - template - std::string to_matrix_string(const typename Types::Block&); - - template - void from_string( - typename Types::Key&, - const char*); - - template - void from_string( - typename Types::Key& dest, - const std::string& src) - { - from_string(dest, src.c_str()); - } - - template - std::string to_string(const typename Types::Key&); - - template - void expand_key( - const typename Types::Key& key, - typename Types::RoundKeys& encryption_keys); - - template - void derive_decryption_keys( - const typename Types::RoundKeys& encryption_keys, - typename Types::RoundKeys& decryption_keys); - - template ::value>::type* = nullptr> - void encrypt_block( - const typename Types::Block& plaintext, - const typename Types::RoundKeys& round_keys, - typename Types::Block& iv, - typename Types::Block& ciphertext); - - template ::value>::type* = nullptr> - void encrypt_block( - const typename Types::Block& plaintext, - const typename Types::RoundKeys& round_keys, - typename Types::Block& ciphertext); - - template ::value>::type* = nullptr> - void encrypt_block( - const typename Types::Block& plaintext, - const typename Types::RoundKeys& round_keys, - typename Types::Block&, - typename Types::Block& ciphertext) - { - encrypt_block(plaintext, round_keys, ciphertext); - } - - template ::value>::type* = nullptr> - void decrypt_block( - const typename Types::Block& ciphertext, - const typename Types::RoundKeys& round_keys, - typename Types::Block& iv, - typename Types::Block& plaintext); - - template ::value>::type* = nullptr> - void decrypt_block( - const typename Types::Block& ciphertext, - const typename Types::RoundKeys& round_keys, - typename Types::Block& plaintext); - - template ::value>::type* = nullptr> - void decrypt_block( - const typename Types::Block& ciphertext, - const typename Types::RoundKeys& round_keys, - typename Types::Block&, - typename Types::Block& plaintext) - { - decrypt_block(ciphertext, round_keys, plaintext); - } - - template - struct EncryptWrapper - { - EncryptWrapper( - const typename Types::Key& key, - const typename Types::Block& iv) : iv{iv} - { - expand_key(key, encryption_keys); - } - - void encrypt_block( - const typename Types::Block& plaintext, - typename Types::Block& ciphertext) - { - aes::encrypt_block( - plaintext, encryption_keys, iv, ciphertext); - } - - typename Types::Block iv; - typename Types::RoundKeys encryption_keys; - }; - - template - struct DecryptWrapper - { - DecryptWrapper( - const typename Types::Key& key, - const typename Types::Block& iv) : iv{iv} - { - typename Types::RoundKeys encryption_keys; - expand_key(key, encryption_keys); - - if (ModeUsesEncryptionKeysOnly::value) - { - decryption_keys = encryption_keys; - } - else - { - derive_decryption_keys(encryption_keys, decryption_keys); - } - } - - void decrypt_block( - const typename Types::Block& ciphertext, - typename Types::Block& plaintext) - { - aes::decrypt_block( - ciphertext, decryption_keys, iv, plaintext); - } - - typename Types::Block iv; - typename Types::RoundKeys decryption_keys; - }; -} diff --git a/cxx/include/aesxx/box.hpp b/cxx/include/aesxx/box.hpp deleted file mode 100644 index 076407c..0000000 --- a/cxx/include/aesxx/box.hpp +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright (c) 2015 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#include "algorithm.hpp" -#include "error.hpp" -#include "mode.hpp" - -#include - -#include - -#include -#include - -namespace aes -{ - class Box - { - public: - typedef AES_BoxBlock Block; - typedef AES_BoxKey Key; - - static std::string format_key(const Key& src, Algorithm algorithm) - { - AES_BoxKeyString str; - aes_box_format_key( - &str, algorithm, &src, ErrorDetailsThrowsInDestructor{}); - return reinterpret_cast(&str); - } - - static std::string format_block(const Block& src, Algorithm algorithm) - { - AES_BoxBlockString str; - aes_box_format_block( - &str, algorithm, &src, ErrorDetailsThrowsInDestructor{}); - return reinterpret_cast(&str); - } - - static void parse_block( - Block& dest, - Algorithm algorithm, - const char* src) - { - aes_box_parse_block(&dest, algorithm, src, - ErrorDetailsThrowsInDestructor{}); - } - - static void parse_block( - Block& dest, - Algorithm algorithm, - const std::string& src) - { - parse_block(dest, algorithm, src.c_str()); - } - - static void parse_key( - Key& dest, - Algorithm algorithm, - const char* src) - { - aes_box_parse_key(&dest, algorithm, src, - ErrorDetailsThrowsInDestructor{}); - } - - static void parse_key( - Key& dest, - Algorithm algorithm, - const std::string& src) - { - parse_key(dest, algorithm, src.c_str()); - } - - Box(Algorithm algorithm, const Key& key) - : algorithm{algorithm} - , mode{AES_ECB} - { - aes_box_init(&impl, algorithm, &key, mode, nullptr, - ErrorDetailsThrowsInDestructor{}); - } - - Box(Algorithm algorithm, const Key& key, Mode mode, const Block& iv) - : algorithm{algorithm} - , mode{mode} - { - aes_box_init(&impl, algorithm, &key, mode, &iv, - ErrorDetailsThrowsInDestructor{}); - } - - void encrypt_block(const Block& plaintext, Block& ciphertext) - { - aes_box_encrypt_block( - &impl, &plaintext, &ciphertext, - ErrorDetailsThrowsInDestructor{}); - } - - void decrypt_block(const Block& ciphertext, Block& plaintext) - { - aes_box_decrypt_block( - &impl, &ciphertext, &plaintext, - ErrorDetailsThrowsInDestructor{}); - } - - std::vector encrypt_buffer( - const void* src_buf, - std::size_t src_size) - { - std::size_t dest_size = 0; - - aes_box_encrypt_buffer( - &impl, - src_buf, - src_size, - nullptr, - &dest_size, - aes::ErrorDetailsThrowsInDestructor{}); - - std::vector dest_buf; - dest_buf.resize(dest_size); - - aes_box_encrypt_buffer( - &impl, - src_buf, - src_size, - dest_buf.data(), - &dest_size, - aes::ErrorDetailsThrowsInDestructor{}); - - dest_buf.resize(dest_size); - return dest_buf; - } - - std::vector decrypt_buffer( - const void* src_buf, - std::size_t src_size) - { - std::size_t dest_size = 0; - - aes_box_decrypt_buffer( - &impl, - src_buf, - src_size, - nullptr, - &dest_size, - aes::ErrorDetailsThrowsInDestructor{}); - - std::vector dest_buf; - dest_buf.resize(dest_size); - - aes_box_decrypt_buffer( - &impl, - src_buf, - src_size, - dest_buf.data(), - &dest_size, - aes::ErrorDetailsThrowsInDestructor{}); - - dest_buf.resize(dest_size); - return dest_buf; - } - - std::string format_block(const Block& src) - { - return format_block(src, get_algorithm()); - } - - std::string format_key(const Key& src) - { - return format_key(src, get_algorithm()); - } - - void parse_block(Block& dest, const char* src) - { - parse_block(dest, get_algorithm(), src); - } - - void parse_block(Block& dest, const std::string& src) - { - parse_block(dest, src.c_str()); - } - - void parse_key(Key& dest, const char* src) - { - parse_key(dest, get_algorithm(), src); - } - - void parse_key(Key& dest, const std::string& src) - { - parse_key(dest, src.c_str()); - } - - Algorithm get_algorithm() const { return algorithm; } - - Mode get_mode() const { return mode; } - - private: - Key key; - - Algorithm algorithm; - Mode mode; - - AES_Box impl; - }; -} diff --git a/cxx/include/aesxx/data.hpp b/cxx/include/aesxx/data.hpp deleted file mode 100644 index f36df5e..0000000 --- a/cxx/include/aesxx/data.hpp +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2015 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#include "error.hpp" - -#include - -namespace aes -{ - typedef AES_Block128 Block128; - - inline void make_block(Block128& dest, int hi3, int hi2, int lo1, int lo0) - { - dest = aes_make_block128(hi3, hi2, lo1, lo0); - } - - inline void load_block(Block128& dest, const void* src) - { - dest = aes_load_block128(src); - } - - inline void load_block_aligned(Block128& dest, const void* src) - { - dest = aes_load_block128_aligned(src); - } - - inline void store_block(void* dest, Block128& src) - { - aes_store_block128(dest, src); - } - - inline void store_block_aligned(void* dest, Block128& src) - { - aes_store_block128_aligned(dest, src); - } - - inline Block128 xor_blocks(Block128& a, Block128& b) - { - return aes_xor_block128(a, b); - } - - inline Block128 reverse_byte_order(Block128& block) - { - return aes_reverse_byte_order_block128(block); - } - - inline Block128 inc_block(Block128& block) - { - return aes_inc_block128(block); - } -} diff --git a/cxx/include/aesxx/debug.hpp b/cxx/include/aesxx/debug.hpp deleted file mode 100644 index 96e81b5..0000000 --- a/cxx/include/aesxx/debug.hpp +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright (c) 2015 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#ifdef WIN32 -#include -#include -#pragma comment(lib, "DbgHelp.Lib") -#endif - -#include - -#include -#include - -namespace aes -{ - namespace aux - { - class CallStackFormatter - { - public: - CallStackFormatter() = default; - - std::string format_address(const void* addr) const - { - #ifdef WIN32 - return format_address_win32(addr); - #else - return format_address_fallback(addr); - #endif - } - - private: - template - static std::string put_between_brackets(const T& x) - { - std::ostringstream oss; - oss << "[" << x << "]"; - return oss.str(); - } - - template - static std::string stringify(const T& x) - { - std::ostringstream oss; - oss << x; - return oss.str(); - } - - static std::string format_address_fallback(const void* addr) - { - return put_between_brackets(addr); - } - - static std::string format_module( - const std::string& module_name, - const void* offset = nullptr) - { - if (offset == nullptr) - return put_between_brackets(module_name); - else - return put_between_brackets(module_name + "+" + stringify(offset)); - } - - static std::string format_symbol( - const std::string& symbol_name, - const void* offset = nullptr) - { - return format_module(symbol_name, offset); - } - - static std::string format_symbol( - const std::string& module_name, - const std::string& symbol_name, - const void* offset = nullptr) - { - return format_symbol(module_name + "!" + symbol_name, offset); - } - - #ifdef WIN32 - class DbgHelp - { - public: - DbgHelp() - { - initialized_flag = SymInitialize(GetCurrentProcess(), NULL, TRUE) != FALSE; - } - - bool initialized() const - { - return initialized_flag; - } - - ~DbgHelp() - { - if (initialized_flag) - SymCleanup(GetCurrentProcess()); - } - - private: - bool initialized_flag = false; - - DbgHelp(const DbgHelp&) = delete; - DbgHelp& operator=(const DbgHelp&) = delete; - }; - - DbgHelp dbghelp; - - std::string format_address_win32(const void* addr) const - { - if (!dbghelp.initialized()) - return format_address_fallback(addr); - - DWORD64 symbol_info_buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME]; - const auto symbol_info = reinterpret_cast(symbol_info_buf); - symbol_info->SizeOfStruct = sizeof(SYMBOL_INFO); - symbol_info->MaxNameLen = MAX_SYM_NAME; - - IMAGEHLP_MODULE64 module_info; - module_info.SizeOfStruct = sizeof(IMAGEHLP_MODULE64); - - DWORD64 symbol_offset; - - const auto symbol_resolved = SymFromAddr( - GetCurrentProcess(), - reinterpret_cast(addr), - &symbol_offset, - symbol_info); - - if (symbol_resolved) - { - const auto module_resolved = SymGetModuleInfo64( - GetCurrentProcess(), - symbol_info->ModBase, - &module_info); - - if (module_resolved) - { - return format_symbol( - module_info.ModuleName, - symbol_info->Name, - reinterpret_cast(symbol_offset)); - } - else - { - return format_symbol(symbol_info->Name, addr); - } - } - else - { - const auto module_resolved = SymGetModuleInfo64( - GetCurrentProcess(), - reinterpret_cast(addr), - &module_info); - - if (module_resolved) - { - const auto module_offset = reinterpret_cast(addr) - module_info.BaseOfImage; - return format_module(module_info.ModuleName, module_offset); - } - else - { - return format_address_fallback(addr); - } - } - } - #endif - }; - } -} diff --git a/cxx/include/aesxx/error.hpp b/cxx/include/aesxx/error.hpp deleted file mode 100644 index 4d2c783..0000000 --- a/cxx/include/aesxx/error.hpp +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) 2015 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#include "debug.hpp" - -#include - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace aes -{ - class Error : public std::runtime_error - { - public: - Error(const AES_ErrorDetails& err_details) - : std::runtime_error{format_error_message(err_details)} - { - fill_call_stack(err_details); - } - - void for_each_addr( - const std::function& callback) const - { - aux::CallStackFormatter formatter; - - std::for_each( - call_stack, - call_stack + call_stack_len, - [&formatter, &callback] (const void* addr) - { - callback(addr, formatter.format_address(addr)); - }); - } - - private: - static std::string format_error_message(const AES_ErrorDetails& err_details) - { - std::vector buf; - buf.resize(aes_format_error(&err_details, NULL, 0)); - aes_format_error(&err_details, buf.data(), buf.size()); - return {buf.begin(), buf.end()}; - } - - void fill_call_stack(const AES_ErrorDetails& err_details) - { - call_stack_len = err_details.call_stack_len; - - if (call_stack_len > AES_MAX_CALL_STACK_LENGTH) - call_stack_len = AES_MAX_CALL_STACK_LENGTH; - - std::memcpy(call_stack, err_details.call_stack, call_stack_len * sizeof(const void*)); - } - - std::size_t call_stack_len = 0; - const void* call_stack[AES_MAX_CALL_STACK_LENGTH] = {nullptr}; - }; - - inline std::ostream& operator<<(std::ostream& os, const Error& error) - { - os << "AES error: " << error.what() << '\n'; - os << "Call stack:\n"; - error.for_each_addr([&os] (const void* addr, const std::string& name) - { - os << '\t' << addr << ' ' << name << '\n'; - }); - return os; - } - - class ErrorDetailsThrowsInDestructor - { - public: - ErrorDetailsThrowsInDestructor() - { - aes_success(get()); - } - - ~ErrorDetailsThrowsInDestructor() BOOST_NOEXCEPT_IF(false) - { - if (aes_is_error(aes_get_error_code(get()))) - throw Error(impl); - } - - AES_ErrorDetails* get() { return &impl; } - - operator AES_ErrorDetails*() { return get(); } - - private: - AES_ErrorDetails impl; - }; -} diff --git a/cxx/include/aesxx/mode.hpp b/cxx/include/aesxx/mode.hpp deleted file mode 100644 index 1c6c4cf..0000000 --- a/cxx/include/aesxx/mode.hpp +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright (c) 2015 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#include - -#include - -namespace aes -{ - typedef AES_Mode Mode; - - template - struct ModeRequiresInitVector : public std::true_type - { }; - - template <> - struct ModeRequiresInitVector : public std::false_type - { }; - - template - struct ModeUsesEncryptionKeysOnly : public std::true_type - { }; - - inline bool mode_requires_init_vector(Mode mode) - { - return mode != AES_ECB; - } - - template <> - struct ModeUsesEncryptionKeysOnly : public std::false_type - { }; - - template <> - struct ModeUsesEncryptionKeysOnly : public std::false_type - { }; - - inline bool mode_uses_encryption_keys_only(Mode mode) - { - return mode != AES_ECB && mode != AES_CBC; - } - -#define AESXX_ENCRYPT_BLOCK_ECB(prefix) \ - template <> \ - inline void encrypt_block( \ - const typename Types::Block& plaintext, \ - const typename Types::RoundKeys& encryption_keys, \ - typename Types::Block& ciphertext) \ - { \ - ciphertext = aes_## prefix ##_encrypt_block_ECB(plaintext, &encryption_keys); \ - } - -#define AESXX_DECRYPT_BLOCK_ECB(prefix) \ - template <> \ - inline void decrypt_block( \ - const typename Types::Block& ciphertext, \ - const typename Types::RoundKeys& decryption_keys, \ - typename Types::Block& plaintext) \ - { \ - plaintext = aes_## prefix ##_decrypt_block_ECB(ciphertext, &decryption_keys); \ - } - -#define AESXX_ENCRYPT_BLOCK_CBC(prefix) \ - template <> \ - inline void encrypt_block( \ - const typename Types::Block& plaintext, \ - const typename Types::RoundKeys& encryption_keys, \ - typename Types::Block& iv, \ - typename Types::Block& ciphertext) \ - { \ - ciphertext = aes_## prefix ##_encrypt_block_CBC(plaintext, &encryption_keys, iv, &iv); \ - } - -#define AESXX_DECRYPT_BLOCK_CBC(prefix) \ - template <> \ - inline void decrypt_block( \ - const typename Types::Block& ciphertext, \ - const typename Types::RoundKeys& decryption_keys, \ - typename Types::Block& iv, \ - typename Types::Block& plaintext) \ - { \ - plaintext = aes_## prefix ##_decrypt_block_CBC(ciphertext, &decryption_keys, iv, &iv); \ - } - -#define AESXX_ENCRYPT_BLOCK_CFB(prefix) \ - template <> \ - inline void encrypt_block( \ - const typename Types::Block& plaintext, \ - const typename Types::RoundKeys& encryption_keys, \ - typename Types::Block& iv, \ - typename Types::Block& ciphertext) \ - { \ - ciphertext = aes_## prefix ##_encrypt_block_CFB(plaintext, &encryption_keys, iv, &iv); \ - } - -#define AESXX_DECRYPT_BLOCK_CFB(prefix) \ - template <> \ - inline void decrypt_block( \ - const typename Types::Block& ciphertext, \ - const typename Types::RoundKeys& encryption_keys, \ - typename Types::Block& iv, \ - typename Types::Block& plaintext) \ - { \ - plaintext = aes_## prefix ##_decrypt_block_CFB(ciphertext, &encryption_keys, iv, &iv); \ - } - -#define AESXX_ENCRYPT_BLOCK_OFB(prefix) \ - template <> \ - inline void encrypt_block( \ - const typename Types::Block& plaintext, \ - const typename Types::RoundKeys& encryption_keys, \ - typename Types::Block& iv, \ - typename Types::Block& ciphertext) \ - { \ - ciphertext = aes_## prefix ##_encrypt_block_OFB(plaintext, &encryption_keys, iv, &iv); \ - } - -#define AESXX_DECRYPT_BLOCK_OFB(prefix) \ - template <> \ - inline void decrypt_block( \ - const typename Types::Block& ciphertext, \ - const typename Types::RoundKeys& encryption_keys, \ - typename Types::Block& iv, \ - typename Types::Block& plaintext) \ - { \ - plaintext = aes_## prefix ##_decrypt_block_OFB(ciphertext, &encryption_keys, iv, &iv); \ - } - -#define AESXX_ENCRYPT_BLOCK_CTR(prefix) \ - template <> \ - inline void encrypt_block( \ - const typename Types::Block& plaintext, \ - const typename Types::RoundKeys& encryption_keys, \ - typename Types::Block& iv, \ - typename Types::Block& ciphertext) \ - { \ - ciphertext = aes_## prefix ##_encrypt_block_CTR(plaintext, &encryption_keys, iv, &iv); \ - } - -#define AESXX_DECRYPT_BLOCK_CTR(prefix) \ - template <> \ - inline void decrypt_block( \ - const typename Types::Block& ciphertext, \ - const typename Types::RoundKeys& encryption_keys, \ - typename Types::Block& iv, \ - typename Types::Block& plaintext) \ - { \ - plaintext = aes_## prefix ##_decrypt_block_CTR(ciphertext, &encryption_keys, iv, &iv); \ - } -} diff --git a/include/aes/aes.h b/include/aes/aes.h deleted file mode 100644 index 1108235..0000000 --- a/include/aes/aes.h +++ /dev/null @@ -1,541 +0,0 @@ -// Copyright (c) 2015 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#include "data.h" -#include "error.h" -#include "mode.h" - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -typedef AES_Block128 AES_AES_Block; -typedef AES_AES_Block AES_AES128_Block; -typedef AES_AES_Block AES_AES192_Block; -typedef AES_AES_Block AES_AES256_Block; - -typedef struct -{ - AES_AES_Block key; -} -AES_AES128_Key; - -typedef struct -{ - AES_AES_Block hi; - AES_AES_Block lo; -} -AES_AES192_Key; - -typedef struct -{ - AES_AES_Block hi; - AES_AES_Block lo; -} -AES_AES256_Key; - -static __inline AES_AES_Block aes_AES_make_block( - int hi3, int hi2, int lo1, int lo0) -{ - return aes_make_block128(hi3, hi2, lo1, lo0); -} - -static __inline AES_AES128_Block aes_AES128_make_block( - int hi3, int hi2, int lo1, int lo0) -{ - return aes_AES_make_block(hi3, hi2, lo1, lo0); -} - -static __inline AES_AES192_Block aes_AES192_make_block( - int hi3, int hi2, int lo1, int lo0) -{ - return aes_AES_make_block(hi3, hi2, lo1, lo0); -} - -static __inline AES_AES256_Block aes_AES256_make_block( - int hi3, int hi2, int lo1, int lo0) -{ - return aes_AES_make_block(hi3, hi2, lo1, lo0); -} - -static __inline AES_AES128_Key aes_AES128_make_key( - int hi3, int hi2, int lo1, int lo0) -{ - AES_AES128_Key key; - key.key = aes_AES_make_block(hi3, hi2, lo1, lo0); - return key; -} - -static __inline AES_AES192_Key aes_AES192_make_key( - int hi5, int hi4, - int lo3, int lo2, int lo1, int lo0) -{ - AES_AES192_Key key; - key.hi = aes_AES_make_block( 0, 0, hi5, hi4); - key.lo = aes_AES_make_block(lo3, lo2, lo1, lo0); - return key; -} - -static __inline AES_AES256_Key aes_AES256_make_key( - int hi7, int hi6, int hi5, int hi4, - int lo3, int lo2, int lo1, int lo0) -{ - AES_AES256_Key key; - key.hi = aes_AES_make_block(hi7, hi6, hi5, hi4); - key.lo = aes_AES_make_block(lo3, lo2, lo1, lo0); - return key; -} - -typedef struct { char str[33]; } AES_AES_BlockString; -typedef AES_AES_BlockString AES_AES128_BlockString; -typedef AES_AES_BlockString AES_AES192_BlockString; -typedef AES_AES_BlockString AES_AES256_BlockString; - -typedef struct { char str[49]; } AES_AES_BlockMatrixString; -typedef AES_AES_BlockMatrixString AES_AES128_BlockMatrixString; -typedef AES_AES_BlockMatrixString AES_AES192_BlockMatrixString; -typedef AES_AES_BlockMatrixString AES_AES256_BlockMatrixString; - -AES_StatusCode aes_AES_format_block( - AES_AES_BlockString*, - const AES_AES_Block*, - AES_ErrorDetails*); - -static __inline AES_StatusCode aes_AES128_format_block( - AES_AES128_BlockString* dest, - const AES_AES128_Block* src, - AES_ErrorDetails* err_details) -{ - return aes_AES_format_block(dest, src, err_details); -} - -static __inline AES_StatusCode aes_AES192_format_block( - AES_AES192_BlockString* dest, - const AES_AES192_Block* src, - AES_ErrorDetails* err_details) -{ - return aes_AES_format_block(dest, src, err_details); -} - -static __inline AES_StatusCode aes_AES256_format_block( - AES_AES256_BlockString* dest, - const AES_AES256_Block* src, - AES_ErrorDetails* err_details) -{ - return aes_AES_format_block(dest, src, err_details); -} - -AES_StatusCode aes_AES_format_block_as_matrix( - AES_AES_BlockMatrixString*, - const AES_AES_Block*, - AES_ErrorDetails*); - -static __inline AES_StatusCode aes_AES128_format_block_as_matrix( - AES_AES128_BlockMatrixString* dest, - const AES_AES128_Block* src, - AES_ErrorDetails* err_details) -{ - return aes_AES_format_block_as_matrix(dest, src, err_details); -} - -static __inline AES_StatusCode aes_AES192_format_block_as_matrix( - AES_AES192_BlockMatrixString* dest, - const AES_AES192_Block* src, - AES_ErrorDetails* err_details) -{ - return aes_AES_format_block_as_matrix(dest, src, err_details); -} - -static __inline AES_StatusCode aes_AES256_format_block_as_matrix( - AES_AES256_BlockMatrixString* dest, - const AES_AES256_Block* src, - AES_ErrorDetails* err_details) -{ - return aes_AES_format_block_as_matrix(dest, src, err_details); -} - -AES_StatusCode aes_AES_print_block( - const AES_AES_Block*, - AES_ErrorDetails*); - -static __inline AES_StatusCode aes_AES128_print_block( - const AES_AES128_Block* block, - AES_ErrorDetails* err_details) -{ - return aes_AES_print_block(block, err_details); -} - -static __inline AES_StatusCode aes_AES192_print_block( - const AES_AES192_Block* block, - AES_ErrorDetails* err_details) -{ - return aes_AES_print_block(block, err_details); -} - -static __inline AES_StatusCode aes_AES256_print_block( - const AES_AES256_Block* block, - AES_ErrorDetails* err_details) -{ - return aes_AES_print_block(block, err_details); -} - -AES_StatusCode aes_AES_print_block_as_matrix( - const AES_AES_Block*, - AES_ErrorDetails*); - -static __inline AES_StatusCode aes_AES128_print_block_as_matrix( - const AES_AES128_Block* block, - AES_ErrorDetails* err_details) -{ - return aes_AES_print_block_as_matrix(block, err_details); -} - -static __inline AES_StatusCode aes_AES192_print_block_as_matrix( - const AES_AES192_Block* block, - AES_ErrorDetails* err_details) -{ - return aes_AES_print_block_as_matrix(block, err_details); -} - -static __inline AES_StatusCode aes_AES256_print_block_as_matrix( - const AES_AES256_Block* block, - AES_ErrorDetails* err_details) -{ - return aes_AES_print_block_as_matrix(block, err_details); -} - -AES_StatusCode aes_AES_parse_block( - AES_AES_Block* dest, - const char* src, - AES_ErrorDetails* err_details); - -static __inline AES_StatusCode aes_AES128_parse_block( - AES_AES128_Block* dest, - const char* src, - AES_ErrorDetails* err_details) -{ - return aes_AES_parse_block(dest, src, err_details); -} - -static __inline AES_StatusCode aes_AES192_parse_block( - AES_AES192_Block* dest, - const char* src, - AES_ErrorDetails* err_details) -{ - return aes_AES_parse_block(dest, src, err_details); -} - -static __inline AES_StatusCode aes_AES256_parse_block( - AES_AES256_Block* dest, - const char* src, - AES_ErrorDetails* err_details) -{ - return aes_AES_parse_block(dest, src, err_details); -} - -typedef struct { char str[33]; } AES_AES128_KeyString; -typedef struct { char str[49]; } AES_AES192_KeyString; -typedef struct { char str[65]; } AES_AES256_KeyString; - -AES_StatusCode aes_AES128_format_key( - AES_AES128_KeyString*, - const AES_AES128_Key*, - AES_ErrorDetails*); - -AES_StatusCode aes_AES192_format_key( - AES_AES192_KeyString*, - const AES_AES192_Key*, - AES_ErrorDetails*); - -AES_StatusCode aes_AES256_format_key( - AES_AES256_KeyString*, - const AES_AES256_Key*, - AES_ErrorDetails*); - -AES_StatusCode aes_AES128_print_key( - const AES_AES128_Key*, - AES_ErrorDetails*); - -AES_StatusCode aes_AES192_print_key( - const AES_AES192_Key*, - AES_ErrorDetails*); - -AES_StatusCode aes_AES256_print_key( - const AES_AES256_Key*, - AES_ErrorDetails*); - -AES_StatusCode aes_AES128_parse_key( - AES_AES128_Key* dest, - const char* src, - AES_ErrorDetails* err_details); - -AES_StatusCode aes_AES192_parse_key( - AES_AES192_Key* dest, - const char* src, - AES_ErrorDetails* err_details); - -AES_StatusCode aes_AES256_parse_key( - AES_AES256_Key* dest, - const char* src, - AES_ErrorDetails* err_details); - -typedef struct -{ - AES_AES_Block keys[11]; -} -AES_AES128_RoundKeys; - -typedef struct -{ - AES_AES_Block keys[13]; -} -AES_AES192_RoundKeys; - -typedef struct -{ - AES_AES_Block keys[15]; -} -AES_AES256_RoundKeys; - -void __fastcall aes_AES128_expand_key_( - AES_AES_Block key, - AES_AES128_RoundKeys* encryption_keys); - -void __fastcall aes_AES192_expand_key_( - AES_AES_Block key_lo, - AES_AES_Block key_hi, - AES_AES192_RoundKeys* encryption_keys); - -void __fastcall aes_AES256_expand_key_( - AES_AES_Block key_lo, - AES_AES_Block key_hi, - AES_AES256_RoundKeys* encryption_keys); - -void __fastcall aes_AES128_derive_decryption_keys_( - const AES_AES128_RoundKeys* encryption_keys, - AES_AES128_RoundKeys* decryption_keys); - -void __fastcall aes_AES192_derive_decryption_keys_( - const AES_AES192_RoundKeys* encryption_keys, - AES_AES192_RoundKeys* decryption_keys); - -void __fastcall aes_AES256_derive_decryption_keys_( - const AES_AES256_RoundKeys* encryption_keys, - AES_AES256_RoundKeys* decryption_keys); - -AES_AES_Block __fastcall aes_AES128_encrypt_block_( - AES_AES_Block plaintext, - const AES_AES128_RoundKeys*); - -AES_AES_Block __fastcall aes_AES192_encrypt_block_( - AES_AES_Block plaintext, - const AES_AES192_RoundKeys*); - -AES_AES_Block __fastcall aes_AES256_encrypt_block_( - AES_AES_Block plaintext, - const AES_AES256_RoundKeys*); - -AES_AES_Block __fastcall aes_AES128_decrypt_block_( - AES_AES_Block ciphertext, - const AES_AES128_RoundKeys*); - -AES_AES_Block __fastcall aes_AES192_decrypt_block_( - AES_AES_Block ciphertext, - const AES_AES192_RoundKeys*); - -AES_AES_Block __fastcall aes_AES256_decrypt_block_( - AES_AES_Block ciphertext, - const AES_AES256_RoundKeys*); - -static __inline AES_AES_Block __fastcall aes_AES_xor_blocks( - AES_AES_Block a, - AES_AES_Block b) -{ - return aes_xor_block128(a, b); -} - -static __inline AES_AES_Block __fastcall aes_AES128_xor_blocks( - AES_AES128_Block a, - AES_AES128_Block b) -{ - return aes_AES_xor_blocks(a, b); -} - -static __inline AES_AES_Block __fastcall aes_AES192_xor_blocks( - AES_AES192_Block a, - AES_AES192_Block b) -{ - return aes_AES_xor_blocks(a, b); -} - -static __inline AES_AES_Block __fastcall aes_AES256_xor_blocks( - AES_AES256_Block a, - AES_AES256_Block b) -{ - return aes_AES_xor_blocks(a, b); -} - -static __inline AES_AES_Block __fastcall aes_AES_inc_block( - AES_AES_Block block) -{ - block = aes_reverse_byte_order_block128(block); - block = aes_inc_block128(block); - return aes_reverse_byte_order_block128(block); -} - -static __inline AES_AES_Block __fastcall aes_AES128_inc_block( - AES_AES128_Block block) -{ - return aes_AES_inc_block(block); -} - -static __inline AES_AES_Block __fastcall aes_AES192_inc_block( - AES_AES192_Block block) -{ - return aes_AES_inc_block(block); -} - -static __inline AES_AES_Block __fastcall aes_AES256_inc_block( - AES_AES256_Block block) -{ - return aes_AES_inc_block(block); -} - -AES_ENCRYPT_BLOCK_ECB(AES128); -AES_DECRYPT_BLOCK_ECB(AES128); -AES_ENCRYPT_BLOCK_CBC(AES128); -AES_DECRYPT_BLOCK_CBC(AES128); -AES_ENCRYPT_BLOCK_CFB(AES128); -AES_DECRYPT_BLOCK_CFB(AES128); -AES_ENCRYPT_BLOCK_OFB(AES128); -AES_DECRYPT_BLOCK_OFB(AES128); -AES_ENCRYPT_BLOCK_CTR(AES128); -AES_DECRYPT_BLOCK_CTR(AES128); - -AES_ENCRYPT_BLOCK_ECB(AES192); -AES_DECRYPT_BLOCK_ECB(AES192); -AES_ENCRYPT_BLOCK_CBC(AES192); -AES_DECRYPT_BLOCK_CBC(AES192); -AES_ENCRYPT_BLOCK_CFB(AES192); -AES_DECRYPT_BLOCK_CFB(AES192); -AES_ENCRYPT_BLOCK_OFB(AES192); -AES_DECRYPT_BLOCK_OFB(AES192); -AES_ENCRYPT_BLOCK_CTR(AES192); -AES_DECRYPT_BLOCK_CTR(AES192); - -AES_ENCRYPT_BLOCK_ECB(AES256); -AES_DECRYPT_BLOCK_ECB(AES256); -AES_ENCRYPT_BLOCK_CBC(AES256); -AES_DECRYPT_BLOCK_CBC(AES256); -AES_ENCRYPT_BLOCK_CFB(AES256); -AES_DECRYPT_BLOCK_CFB(AES256); -AES_ENCRYPT_BLOCK_OFB(AES256); -AES_DECRYPT_BLOCK_OFB(AES256); -AES_ENCRYPT_BLOCK_CTR(AES256); -AES_DECRYPT_BLOCK_CTR(AES256); - -/** - * \brief Expands an AES-128 key into 10 encryption round keys. - * - * \param[in] key The AES-128 key. - * \param[out] encryption_keys The AES-128 encryption round keys. Must not be `NULL`. - */ -static __inline void __fastcall aes_AES128_expand_key( - const AES_AES128_Key* key, - AES_AES128_RoundKeys* encryption_keys) -{ - assert(encryption_keys); - - aes_AES128_expand_key_(key->key, encryption_keys); -} - -/** - * \brief Derives AES-128 decryption round keys from AES-128 encryption round keys. - * - * \param[in] encryption_keys The AES-128 encryption round keys. Must not be `NULL`. - * \param[out] decryption_keys The AES-128 decryption round keys. Must not be `NULL`. - */ -static __inline void __fastcall aes_AES128_derive_decryption_keys( - const AES_AES128_RoundKeys* encryption_keys, - AES_AES128_RoundKeys* decryption_keys) -{ - assert(encryption_keys); - assert(decryption_keys); - - aes_AES128_derive_decryption_keys_(encryption_keys, decryption_keys); -} - -/** - * \brief Expands an AES-192 key into 12 encryption round keys. - * - * \param[in] key The AES-192 key. - * \param[out] encryption_keys The AES-192 encryption round keys. Must not be `NULL`. - */ -static __inline void __fastcall aes_AES192_expand_key( - const AES_AES192_Key* key, - AES_AES192_RoundKeys* encryption_keys) -{ - assert(key); - assert(encryption_keys); - - aes_AES192_expand_key_(key->lo, key->hi, encryption_keys); -} - -/** - * \brief Derives AES-192 decryption round keys from AES-192 encryption round keys. - * - * \param[in] encryption_keys The AES-192 encryption round keys. Must not be `NULL`. - * \param[out] decryption_keys The AES-192 decryption round keys. Must not be `NULL`. - */ -static __inline void __fastcall aes_AES192_derive_decryption_keys( - const AES_AES192_RoundKeys* encryption_keys, - AES_AES192_RoundKeys* decryption_keys) -{ - assert(encryption_keys); - assert(decryption_keys); - - aes_AES192_derive_decryption_keys_(encryption_keys, decryption_keys); -} - -/** - * \brief Expands an AES-256 key into 14 encryption round keys. - * - * \param[in] key The AES-256 key. - * \param[out] encryption_keys The AES-256 encryption round keys. Must not be `NULL`. - */ -static __inline void __fastcall aes_AES256_expand_key( - const AES_AES256_Key* key, - AES_AES256_RoundKeys* encryption_keys) -{ - assert(key); - assert(encryption_keys); - - aes_AES256_expand_key_(key->lo, key->hi, encryption_keys); -} - -/** - * \brief Derives AES-256 decryption round keys from AES-256 encryption round keys. - * - * \param[in] encryption_keys The AES-256 encryption round keys. Must not be `NULL`. - * \param[out] decryption_keys The AES-256 decryption round keys. Must not be `NULL`. - */ -static __inline void __fastcall aes_AES256_derive_decryption_keys( - const AES_AES256_RoundKeys* encryption_keys, - AES_AES256_RoundKeys* decryption_keys) -{ - assert(encryption_keys); - assert(decryption_keys); - - aes_AES256_derive_decryption_keys_(encryption_keys, decryption_keys); -} - -#ifdef __cplusplus -} -#endif diff --git a/include/aes/algorithm.h b/include/aes/algorithm.h deleted file mode 100644 index d88cf59..0000000 --- a/include/aes/algorithm.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2015 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#ifdef __cplusplus -extern "C" -{ -#endif - -typedef enum -{ - AES_AES128, - AES_AES192, - AES_AES256, -} -AES_Algorithm; - -#ifdef __cplusplus -} -#endif diff --git a/include/aes/all.h b/include/aes/all.h deleted file mode 100644 index ff27c18..0000000 --- a/include/aes/all.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2015 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -/** - * \defgroup aes AES - */ - -#include "aes.h" -#include "algorithm.h" -#include "box.h" -#include "box_aes.h" -#include "box_data.h" -#include "data.h" -#include "error.h" -#include "mode.h" -#include "padding.h" -#include "workarounds.h" diff --git a/include/aes/box.h b/include/aes/box.h deleted file mode 100644 index 2051d3d..0000000 --- a/include/aes/box.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 2015 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#include "algorithm.h" -#include "box_data.h" -#include "error.h" - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -AES_StatusCode aes_box_init( - AES_Box* box, - AES_Algorithm algorithm, - const AES_BoxKey* box_key, - AES_Mode mode, - const AES_BoxBlock* iv, - AES_ErrorDetails* err_details); - -AES_StatusCode aes_box_parse_key( - AES_BoxKey* dest, - AES_Algorithm algorithm, - const char* src, - AES_ErrorDetails* err_details); - -AES_StatusCode aes_box_parse_block( - AES_BoxBlock* dest, - AES_Algorithm algorithm, - const char* src, - AES_ErrorDetails* err_details); - -AES_StatusCode aes_box_format_key( - AES_BoxKeyString* dest, - AES_Algorithm algorithm, - const AES_BoxKey* src, - AES_ErrorDetails* err_details); - -AES_StatusCode aes_box_format_block( - AES_BoxBlockString* dest, - AES_Algorithm algorithm, - const AES_BoxBlock* src, - AES_ErrorDetails* err_details); - -AES_StatusCode aes_box_encrypt_block( - AES_Box* box, - const AES_BoxBlock* plaintext, - AES_BoxBlock* ciphertext, - AES_ErrorDetails* err_details); - -AES_StatusCode aes_box_decrypt_block( - AES_Box* box, - const AES_BoxBlock* ciphertext, - AES_BoxBlock* plaintext, - AES_ErrorDetails* err_details); - -AES_StatusCode aes_box_encrypt_buffer( - AES_Box* box, - const void* src, - size_t src_size, - void* dest, - size_t* dest_size, - AES_ErrorDetails* err_details); - -AES_StatusCode aes_box_decrypt_buffer( - AES_Box* box, - const void* src, - size_t src_size, - void* dest, - size_t* dest_size, - AES_ErrorDetails* err_details); - -#ifdef __cplusplus -} -#endif diff --git a/include/aes/box_aes.h b/include/aes/box_aes.h deleted file mode 100644 index c92d883..0000000 --- a/include/aes/box_aes.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2015 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#include "box_data.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -extern AES_BoxAlgorithmInterface aes_box_algorithm_aes128; -extern AES_BoxAlgorithmInterface aes_box_algorithm_aes192; -extern AES_BoxAlgorithmInterface aes_box_algorithm_aes256; - -#ifdef __cplusplus -} -#endif diff --git a/include/aes/box_data.h b/include/aes/box_data.h deleted file mode 100644 index e2315eb..0000000 --- a/include/aes/box_data.h +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright (c) 2015 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#include "aes.h" -#include "error.h" -#include "mode.h" - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -typedef union -{ - AES_AES128_Key aes128_key; - AES_AES192_Key aes192_key; - AES_AES256_Key aes256_key; -} -AES_BoxKey; - -typedef union -{ - AES_AES128_RoundKeys aes128_encryption_keys; - AES_AES192_RoundKeys aes192_encryption_keys; - AES_AES256_RoundKeys aes256_encryption_keys; -} -AES_BoxEncryptionRoundKeys; - -typedef union -{ - AES_AES128_RoundKeys aes128_decryption_keys; - AES_AES192_RoundKeys aes192_decryption_keys; - AES_AES256_RoundKeys aes256_decryption_keys; -} -AES_BoxDecryptionRoundKeys; - -typedef union -{ - AES_AES128_KeyString aes128; - AES_AES192_KeyString aes192; - AES_AES256_KeyString aes256; -} -AES_BoxKeyString; - -typedef union -{ - AES_AES_Block aes_block; -} -AES_BoxBlock; - -typedef union -{ - AES_AES_BlockString aes; -} -AES_BoxBlockString; - -typedef AES_StatusCode (*AES_BoxCalculateRoundKeys)( - const AES_BoxKey* params, - AES_BoxEncryptionRoundKeys*, - AES_BoxDecryptionRoundKeys*, - AES_ErrorDetails* err_details); - -typedef AES_StatusCode (*AES_BoxParseBlock)( - AES_BoxBlock* dest, - const char* src, - AES_ErrorDetails* err_details); - -typedef AES_StatusCode (*AES_BoxParseKey)( - AES_BoxKey* dest, - const char* src, - AES_ErrorDetails* err_details); - -typedef AES_StatusCode (*AES_BoxFormatBlock)( - AES_BoxBlockString* dest, - const AES_BoxBlock* src, - AES_ErrorDetails* err_details); - -typedef AES_StatusCode (*AES_BoxFormatKey)( - AES_BoxKeyString* dest, - const AES_BoxKey* src, - AES_ErrorDetails* err_details); - -typedef AES_StatusCode (*AES_BoxEncryptBlock)( - const AES_BoxBlock* plaintext, - const AES_BoxEncryptionRoundKeys* params, - AES_BoxBlock* ciphertext, - AES_ErrorDetails* err_details); - -typedef AES_StatusCode (*AES_BoxDecryptBlock)( - const AES_BoxBlock* ciphertext, - const AES_BoxDecryptionRoundKeys* params, - AES_BoxBlock* plaintext, - AES_ErrorDetails* err_details); - -typedef AES_StatusCode (*AES_BoxXorBlock)( - AES_BoxBlock*, - const AES_BoxBlock*, - AES_ErrorDetails*); - -typedef AES_StatusCode (*AES_BoxIncBlock)( - AES_BoxBlock*, - AES_ErrorDetails*); - -typedef AES_StatusCode (*AES_BoxGetBlockSize)( - size_t*, - AES_ErrorDetails*); - -typedef AES_StatusCode (*AES_BoxStoreBlock)( - void*, - const AES_BoxBlock*, - AES_ErrorDetails*); - -typedef AES_StatusCode (*AES_BoxLoadBlock)( - AES_BoxBlock*, - const void*, - AES_ErrorDetails*); - -typedef struct -{ - AES_BoxCalculateRoundKeys calc_round_keys; - AES_BoxParseBlock parse_block; - AES_BoxParseKey parse_key; - AES_BoxFormatBlock format_block; - AES_BoxFormatKey format_key; - AES_BoxEncryptBlock encrypt_block; - AES_BoxDecryptBlock decrypt_block; - AES_BoxXorBlock xor_block; - AES_BoxIncBlock inc_block; - AES_BoxGetBlockSize get_block_size; - AES_BoxStoreBlock store_block; - AES_BoxLoadBlock load_block; -} -AES_BoxAlgorithmInterface; - -typedef struct -{ - const AES_BoxAlgorithmInterface* algorithm; - AES_BoxEncryptionRoundKeys encryption_keys; - AES_BoxDecryptionRoundKeys decryption_keys; - AES_Mode mode; - AES_BoxBlock iv; -} -AES_Box; - -#ifdef __cplusplus -} -#endif diff --git a/include/aes/data.h b/include/aes/data.h deleted file mode 100644 index a441939..0000000 --- a/include/aes/data.h +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (c) 2015 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#include -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -/** - * \brief Represents a 128-bit block. - */ -typedef __m128i AES_Block128; - -/** - * \brief Loads a 128-bit block from a memory location. - * - * \param[in] src The pointer to a memory location. Must not be `NULL`. - * - * \return The loaded 128-bit block. - */ -static __inline AES_Block128 aes_load_block128(const void* src) -{ - return _mm_loadu_si128((AES_Block128*) src); -} - -/** - * \brief Loads a 128-bit block from a 16-byte aligned memory location. - * - * \param[in] src The pointer to a 16-byte aligned memory location. Must not be `NULL`. - * - * \return The loaded 128-bit block. - */ -static __inline AES_Block128 aes_load_block128_aligned(const void* src) -{ - return _mm_load_si128((AES_Block128*) src); -} - -/** - * \brief Stores a 128-bit block in a memory location. - * - * \param[out] dest The pointer to a memory location. Must not be `NULL`. - * - * \param[in] block The block to be stored. - */ -static __inline void __fastcall aes_store_block128( - void* dest, - AES_Block128 block) -{ - _mm_storeu_si128((AES_Block128*) dest, block); -} - -/** - * \brief Stores a 128-bit block in a 16-byte aligned memory location. - * - * \param[out] dest The pointer to a 16-byte aligned memory location. Must not be `NULL`. - * - * \param[in] block The block to be stored. - */ -static __inline void __fastcall aes_store_block128_aligned( - void* dest, - AES_Block128 block) -{ - _mm_store_si128((AES_Block128*) dest, block); -} - -/** - * \brief XORs two 128-bit blocks. - * - * \param[in] a The first XOR operand. - * \param[in] b The second XOR operand. - * - * \return `a^b`. - */ -static __inline AES_Block128 __fastcall aes_xor_block128( - AES_Block128 a, - AES_Block128 b) -{ - return _mm_xor_si128(a, b); -} - -/** - * \brief Builds a 128-bit block from four 4-byte values. - * - * Builds a 128-bit block like this: - * - * * dest[127:96] = hi3 - * * dest[95:64] = hi2 - * * dest[63:32] = lo1 - * * dest[31:0] = lo0 - * - * \param[in] hi3 The most significant 4-byte value. - * \param[in] hi2 The more significant 4-byte value. - * \param[in] lo1 The less significant 4-byte value. - * \param[in] lo0 The least significant 4-byte value. - * - * \return The built 128-bit block. - */ -static __inline AES_Block128 __fastcall aes_make_block128(int hi3, int hi2, int lo1, int lo0) -{ - return _mm_set_epi32(hi3, hi2, lo1, lo0); -} - -static __inline AES_Block128 __fastcall aes_reverse_byte_order_block128(AES_Block128 block) -{ - return _mm_shuffle_epi8(block, aes_make_block128(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f)); -} - -static __inline AES_Block128 __fastcall aes_inc_block128(AES_Block128 x) -{ - return _mm_add_epi32(x, aes_make_block128(0, 0, 0, 1)); -} - -#ifdef __cplusplus -} -#endif diff --git a/include/aes/error.h b/include/aes/error.h deleted file mode 100644 index e094f8a..0000000 --- a/include/aes/error.h +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) 2015 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -typedef enum -{ - AES_SUCCESS, - AES_NULL_ARGUMENT_ERROR, - AES_PARSE_ERROR, - AES_INVALID_PKCS7_PADDING_ERROR, - AES_NOT_IMPLEMENTED_ERROR, - AES_MISSING_PADDING_ERROR, - AES_MEMORY_ALLOCATION_ERROR, -} -AES_StatusCode; - -static __inline int aes_is_error(AES_StatusCode ec) -{ - return ec != AES_SUCCESS; -} - -const char* aes_strerror(AES_StatusCode ec); - -#define AES_MAX_CALL_STACK_LENGTH 32 - -typedef struct -{ - AES_StatusCode ec; ///< Error code - - union - { - struct { char param_name[32]; } null_arg; - struct - { - char src[128]; - char what[32]; - } - parse_error; - struct { char what[128]; } not_implemented; - } - params; - - void* call_stack[AES_MAX_CALL_STACK_LENGTH]; - size_t call_stack_len; -} -AES_ErrorDetails; - -static __inline AES_StatusCode aes_get_error_code( - const AES_ErrorDetails* err_details) -{ - return err_details->ec; -} - -size_t aes_format_error( - const AES_ErrorDetails* err_details, - char* dest, - size_t dest_size); - -AES_StatusCode aes_success( - AES_ErrorDetails* err_details); - -AES_StatusCode aes_error_null_argument( - AES_ErrorDetails* err_details, - const char* param_name); - -AES_StatusCode aes_error_parse( - AES_ErrorDetails* err_details, - const char* src, - const char* what); - -AES_StatusCode aes_error_invalid_pkcs7_padding( - AES_ErrorDetails* err_details); - -AES_StatusCode aes_error_not_implemented( - AES_ErrorDetails* err_details, - const char* what); - -AES_StatusCode aes_error_missing_padding( - AES_ErrorDetails* err_details); - -AES_StatusCode aes_error_memory_allocation( - AES_ErrorDetails* err_details); - -#ifdef __cplusplus -} -#endif diff --git a/include/aes/mode.h b/include/aes/mode.h deleted file mode 100644 index 090628b..0000000 --- a/include/aes/mode.h +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright (c) 2015 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -typedef enum -{ - AES_ECB, - AES_CBC, - AES_CFB, - AES_OFB, - AES_CTR, -} -AES_Mode; - -#define AES_ENCRYPT_BLOCK_ECB(prefix) \ -static __inline AES_## prefix ##_Block __fastcall aes_## prefix ##_encrypt_block_ECB( \ - AES_## prefix ##_Block plaintext, \ - const AES_## prefix ##_RoundKeys* encryption_keys) \ -{ \ - assert(encryption_keys); \ -\ - return aes_## prefix ##_encrypt_block_(plaintext, encryption_keys); \ -} - -#define AES_DECRYPT_BLOCK_ECB(prefix) \ -static __inline AES_## prefix ##_Block __fastcall aes_## prefix ##_decrypt_block_ECB( \ - AES_## prefix ##_Block ciphertext, \ - const AES_## prefix ##_RoundKeys* decryption_keys) \ -{ \ - assert(decryption_keys); \ -\ - return aes_## prefix ##_decrypt_block_(ciphertext, decryption_keys); \ -} - -#define AES_ENCRYPT_BLOCK_CBC(prefix) \ -static __inline AES_## prefix ##_Block __fastcall aes_## prefix ##_encrypt_block_CBC( \ - AES_## prefix ##_Block plaintext, \ - const AES_## prefix ##_RoundKeys* encryption_keys, \ - AES_## prefix ##_Block init_vector, \ - AES_## prefix ##_Block* next_init_vector) \ -{ \ - assert(encryption_keys); \ - assert(next_init_vector); \ -\ - return *next_init_vector = aes_## prefix ##_encrypt_block_( \ - aes_## prefix ##_xor_blocks(plaintext, init_vector), encryption_keys); \ -} - -#define AES_DECRYPT_BLOCK_CBC(prefix) \ -static __inline AES_## prefix ##_Block __fastcall aes_## prefix ##_decrypt_block_CBC( \ - AES_## prefix ##_Block ciphertext, \ - const AES_## prefix ##_RoundKeys* decryption_keys, \ - AES_## prefix ##_Block init_vector, \ - AES_## prefix ##_Block* next_init_vector) \ -{ \ - assert(decryption_keys); \ - assert(next_init_vector); \ -\ - AES_## prefix ##_Block plaintext = aes_## prefix ##_xor_blocks( \ - aes_## prefix ##_decrypt_block_(ciphertext, decryption_keys), init_vector); \ - *next_init_vector = ciphertext; \ - return plaintext; \ -} - -#define AES_ENCRYPT_BLOCK_CFB(prefix) \ -static __inline AES_## prefix ##_Block __fastcall aes_## prefix ##_encrypt_block_CFB( \ - AES_## prefix ##_Block plaintext, \ - const AES_## prefix ##_RoundKeys* encryption_keys, \ - AES_## prefix ##_Block init_vector, \ - AES_## prefix ##_Block* next_init_vector) \ -{ \ - assert(encryption_keys); \ - assert(next_init_vector); \ -\ - return *next_init_vector = aes_## prefix ##_xor_blocks( \ - aes_## prefix ##_encrypt_block_(init_vector, encryption_keys), plaintext); \ -} - -#define AES_DECRYPT_BLOCK_CFB(prefix) \ -static __inline AES_## prefix ##_Block __fastcall aes_## prefix ##_decrypt_block_CFB( \ - AES_## prefix ##_Block ciphertext, \ - const AES_## prefix ##_RoundKeys* encryption_keys, \ - AES_## prefix ##_Block init_vector, \ - AES_## prefix ##_Block* next_init_vector) \ -{ \ - assert(encryption_keys); \ - assert(next_init_vector); \ -\ - AES_## prefix ##_Block plaintext = aes_## prefix ##_xor_blocks( \ - aes_## prefix ##_encrypt_block_(init_vector, encryption_keys), ciphertext); \ - *next_init_vector = ciphertext; \ - return plaintext; \ -} - -#define AES_ENCRYPT_BLOCK_OFB(prefix) \ -static __inline AES_## prefix ##_Block __fastcall aes_## prefix ##_encrypt_block_OFB( \ - AES_## prefix ##_Block plaintext, \ - const AES_## prefix ##_RoundKeys* encryption_keys, \ - AES_## prefix ##_Block init_vector, \ - AES_## prefix ##_Block* next_init_vector) \ -{ \ - assert(encryption_keys); \ - assert(next_init_vector); \ -\ - AES_## prefix ##_Block tmp = aes_## prefix ##_encrypt_block_(init_vector, encryption_keys); \ - *next_init_vector = tmp; \ - return aes_## prefix ##_xor_blocks(tmp, plaintext); \ -} - -#define AES_DECRYPT_BLOCK_OFB(prefix) \ -static __inline AES_## prefix ##_Block __fastcall aes_## prefix ##_decrypt_block_OFB( \ - AES_## prefix ##_Block ciphertext, \ - const AES_## prefix ##_RoundKeys* encryption_keys, \ - AES_## prefix ##_Block init_vector, \ - AES_## prefix ##_Block* next_init_vector) \ -{ \ - assert(encryption_keys); \ - assert(next_init_vector); \ -\ - return aes_## prefix ##_encrypt_block_OFB( \ - ciphertext, encryption_keys, init_vector, next_init_vector); \ -} - -#define AES_ENCRYPT_BLOCK_CTR(prefix) \ -static __inline AES_## prefix ##_Block __fastcall aes_## prefix ##_encrypt_block_CTR( \ - AES_## prefix ##_Block plaintext, \ - const AES_## prefix ##_RoundKeys* encryption_keys, \ - AES_## prefix ##_Block init_vector, \ - AES_## prefix ##_Block* next_init_vector) \ -{ \ - assert(encryption_keys); \ - assert(next_init_vector); \ -\ - AES_## prefix ##_Block ciphertext = aes_## prefix ##_xor_blocks( \ - plaintext, aes_## prefix ##_encrypt_block_(init_vector, encryption_keys)); \ - *next_init_vector = aes_## prefix ##_inc_block(init_vector); \ - return ciphertext; \ -} - -#define AES_DECRYPT_BLOCK_CTR(prefix) \ -static __inline AES_## prefix ##_Block __fastcall aes_## prefix ##_decrypt_block_CTR( \ - AES_## prefix ##_Block ciphertext, \ - const AES_## prefix ##_RoundKeys* encryption_keys, \ - AES_## prefix ##_Block init_vector, \ - AES_## prefix ##_Block* next_init_vector) \ -{ \ - assert(encryption_keys); \ - assert(next_init_vector); \ -\ - return aes_## prefix ##_encrypt_block_CTR( \ - ciphertext, encryption_keys, init_vector, next_init_vector); \ -} - -#ifdef __cplusplus -} -#endif diff --git a/include/aes/padding.h b/include/aes/padding.h deleted file mode 100644 index ba316f5..0000000 --- a/include/aes/padding.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2015 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#include "error.h" - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -typedef enum -{ - AES_PADDING_PKCS7, -} -AES_PaddingMethod; - -AES_StatusCode aes_extract_padding_size( - AES_PaddingMethod, - const void* src, - size_t src_size, - size_t* padding_size, - AES_ErrorDetails*); - -AES_StatusCode aes_fill_with_padding( - AES_PaddingMethod, - void* dest, - size_t padding_size, - AES_ErrorDetails*); - -#ifdef __cplusplus -} -#endif diff --git a/include/aes/workarounds.h b/include/aes/workarounds.h deleted file mode 100644 index 914bd21..0000000 --- a/include/aes/workarounds.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) 2016 Egor Tensin -// This file is part of the "AES tools" project. -// For details, see https://github.com/egor-tensin/aes-tools. -// Distributed under the MIT License. - -#pragma once - -#if defined(_MSC_VER) -#define AES_ALIGN(t, x) __declspec(align(x)) t -#elif defined(__GNUC__) || defined(__MINGW32__) -#define AES_ALIGN(t, x) t __attribute__((aligned(x))) -#else -#warning "couldn't determine alignment attribute" -#endif - -#define AES_UNUSED_PARAMETER(...) (void) (__VA_ARGS__) diff --git a/src/aes.c b/src/aes.c deleted file mode 100644 index 1f7da13..0000000 --- a/src/aes.c +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Copyright (c) 2015 Egor Tensin - * This file is part of the "AES tools" project. - * For details, see https://github.com/egor-tensin/aes-tools. - * Distributed under the MIT License. - */ - -#include - -#include -#include -#include - -AES_StatusCode aes_AES_format_block( - AES_AES_BlockString* str, - const AES_AES_Block* block, - AES_ErrorDetails* err_details) -{ - assert(str); - assert(block); - - if (str == NULL) - return aes_error_null_argument(err_details, "str"); - if (block == NULL) - return aes_error_null_argument(err_details, "block"); - - char* cursor = str->str; - - AES_ALIGN(unsigned char, 16) bytes[16]; - aes_store_block128_aligned(bytes, *block); - - for (int i = 0; i < 16; ++i, cursor += 2) - sprintf(cursor, "%02x", bytes[i]); - - *cursor = '\0'; - return AES_SUCCESS; -} - -AES_StatusCode aes_AES_format_block_as_matrix( - AES_AES_BlockMatrixString* str, - const AES_AES_Block* block, - AES_ErrorDetails* err_details) -{ - assert(str); - assert(block); - - if (str == NULL) - return aes_error_null_argument(err_details, "str"); - if (block == NULL) - return aes_error_null_argument(err_details, "block"); - - char* cursor = str->str; - - AES_ALIGN(unsigned char, 16) bytes[4][4]; - aes_store_block128_aligned(bytes, *block); - - for (int i = 0; i < 4; ++i, cursor += 3) - { - for (int j = 0; j < 3; ++j, cursor += 3) - sprintf(cursor, "%02x ", bytes[j][i]); - sprintf(cursor, "%02x\n", bytes[3][i]); - } - - *cursor = '\0'; - return AES_SUCCESS; -} - -AES_StatusCode aes_AES_print_block( - const AES_AES_Block* block, - AES_ErrorDetails* err_details) -{ - assert(block); - - if (block == NULL) - return aes_error_null_argument(err_details, "block"); - - AES_StatusCode ec = AES_SUCCESS; - AES_AES_BlockString str; - - if (aes_is_error(ec = aes_AES_format_block(&str, block, err_details))) - return ec; - - printf("%s\n", str.str); - return ec; -} - -AES_StatusCode aes_AES_print_block_as_matrix( - const AES_AES_Block* block, - AES_ErrorDetails* err_details) -{ - assert(block); - - if (block == NULL) - return aes_error_null_argument(err_details, "block"); - - AES_StatusCode ec = AES_SUCCESS; - AES_AES_BlockMatrixString str; - - if (aes_is_error(ec = aes_AES_format_block_as_matrix(&str, block, err_details))) - return ec; - - printf("%s", str.str); - return ec; -} - -AES_StatusCode aes_AES_parse_block( - AES_AES_Block* dest, - const char* src, - AES_ErrorDetails* err_details) -{ - assert(dest); - assert(src); - - if (dest == NULL) - return aes_error_null_argument(err_details, "dest"); - if (src == NULL) - return aes_error_null_argument(err_details, "src"); - - const char* cursor = src; - - AES_ALIGN(unsigned char, 16) bytes[16]; - - for (int i = 0; i < 16; ++i) - { - int n; - unsigned int byte; - if (sscanf(cursor, "%2x%n", &byte, &n) != 1) - return aes_error_parse(err_details, src, "a 128-bit block"); - bytes[i] = (unsigned char) byte; - cursor += n; - } - - *dest = aes_load_block128_aligned(bytes); - return AES_SUCCESS; -} - -AES_StatusCode aes_AES128_format_key( - AES_AES128_KeyString* str, - const AES_AES128_Key* key, - AES_ErrorDetails* err_details) -{ - assert(str); - assert(key); - - if (str == NULL) - return aes_error_null_argument(err_details, "str"); - if (key == NULL) - return aes_error_null_argument(err_details, "key"); - - char* cursor = str->str; - - AES_ALIGN(unsigned char, 16) bytes[16]; - aes_store_block128_aligned(bytes, key->key); - - for (int i = 0; i < 16; ++i, cursor += 2) - sprintf(cursor, "%02x", bytes[i]); - - *cursor = '\0'; - return AES_SUCCESS; -} - -AES_StatusCode aes_AES192_format_key( - AES_AES192_KeyString* str, - const AES_AES192_Key* key, - AES_ErrorDetails* err_details) -{ - assert(str); - assert(key); - - if (str == NULL) - return aes_error_null_argument(err_details, "str"); - if (key == NULL) - return aes_error_null_argument(err_details, "key"); - - char* cursor = str->str; - - { - AES_ALIGN(unsigned char, 16) bytes[16]; - aes_store_block128_aligned(bytes, key->lo); - - for (int i = 0; i < 16; ++i, cursor += 2) - sprintf(cursor, "%02x", bytes[i]); - } - - { - AES_ALIGN(unsigned char, 16) bytes[16]; - aes_store_block128_aligned(bytes, key->hi); - - for (int i = 0; i < 8; ++i, cursor += 2) - sprintf(cursor, "%02x", bytes[i]); - } - - *cursor = '\0'; - return AES_SUCCESS; -} - -AES_StatusCode aes_AES256_format_key( - AES_AES256_KeyString* str, - const AES_AES256_Key* key, - AES_ErrorDetails* err_details) -{ - assert(str); - assert(key); - - if (str == NULL) - return aes_error_null_argument(err_details, "str"); - if (key == NULL) - return aes_error_null_argument(err_details, "key"); - - char* cursor = str->str; - - { - AES_ALIGN(unsigned char, 16) bytes[16]; - aes_store_block128_aligned(bytes, key->lo); - - for (int i = 0; i < 16; ++i, cursor += 2) - sprintf(cursor, "%02x", bytes[i]); - } - - { - AES_ALIGN(unsigned char, 16) bytes[16]; - aes_store_block128_aligned(bytes, key->hi); - - for (int i = 0; i < 16; ++i, cursor += 2) - sprintf(cursor, "%02x", bytes[i]); - } - - *cursor = '\0'; - return AES_SUCCESS; -} - -AES_StatusCode aes_AES128_print_key( - const AES_AES128_Key* key, - AES_ErrorDetails* err_details) -{ - return aes_AES_print_block(&key->key, err_details); -} - -AES_StatusCode aes_AES192_print_key( - const AES_AES192_Key* key, - AES_ErrorDetails* err_details) -{ - assert(key); - - if (key == NULL) - return aes_error_null_argument(err_details, "key"); - - AES_StatusCode ec = AES_SUCCESS; - AES_AES192_KeyString str; - - if (aes_is_error(ec = aes_AES192_format_key(&str, key, err_details))) - return ec; - - printf("%s\n", str.str); - return ec; -} - -AES_StatusCode aes_AES256_print_key( - const AES_AES256_Key* key, - AES_ErrorDetails* err_details) -{ - assert(key); - - if (key == NULL) - return aes_error_null_argument(err_details, "key"); - - AES_StatusCode ec = AES_SUCCESS; - AES_AES256_KeyString str; - - if (aes_is_error(ec = aes_AES256_format_key(&str, key, err_details))) - return ec; - - printf("%s\n", str.str); - return ec; -} - -AES_StatusCode aes_AES128_parse_key( - AES_AES128_Key* dest, - const char* src, - AES_ErrorDetails* err_details) -{ - return aes_AES_parse_block(&dest->key, src, err_details); -} - -AES_StatusCode aes_AES192_parse_key( - AES_AES192_Key* dest, - const char* src, - AES_ErrorDetails* err_details) -{ - assert(dest); - assert(src); - - if (dest == NULL) - return aes_error_null_argument(err_details, "dest"); - if (src == NULL) - return aes_error_null_argument(err_details, "src"); - - const char* cursor = src; - - { - AES_ALIGN(unsigned char, 16) bytes[16]; - - for (int i = 0; i < 16; ++i) - { - int n; - unsigned int byte; - if (sscanf(cursor, "%2x%n", &byte, &n) != 1) - return aes_error_parse(err_details, src, "a 192-bit block"); - bytes[i] = (unsigned char) byte; - cursor += n; - } - - dest->lo = aes_load_block128_aligned(bytes); - } - - { - AES_ALIGN(unsigned char, 16) bytes[16]; - - for (int i = 0; i < 8; ++i) - { - int n; - unsigned int byte; - if (sscanf(cursor, "%2x%n", &byte, &n) != 1) - return aes_error_parse(err_details, src, "a 192-bit block"); - bytes[i] = (unsigned char) byte; - cursor += n; - } - - memset(bytes + 8, 0x00, 8); - dest->hi = aes_load_block128_aligned(bytes); - } - - return AES_SUCCESS; -} - -AES_StatusCode aes_AES256_parse_key( - AES_AES256_Key* dest, - const char* src, - AES_ErrorDetails* err_details) -{ - assert(dest); - assert(src); - - if (dest == NULL) - return aes_error_null_argument(err_details, "dest"); - if (src == NULL) - return aes_error_null_argument(err_details, "src"); - - const char* cursor = src; - - { - AES_ALIGN(unsigned char, 16) bytes[16]; - - for (int i = 0; i < 16; ++i) - { - int n; - unsigned int byte; - if (sscanf(cursor, "%2x%n", &byte, &n) != 1) - return aes_error_parse(err_details, src, "a 256-bit block"); - bytes[i] = (unsigned char) byte; - cursor += n; - } - - dest->lo = aes_load_block128_aligned(bytes); - } - - { - AES_ALIGN(unsigned char, 16) bytes[16]; - - for (int i = 0; i < 16; ++i) - { - int n; - unsigned int byte; - if (sscanf(cursor, "%2x%n", &byte, &n) != 1) - return aes_error_parse(err_details, src, "a 256-bit block"); - bytes[i] = (unsigned char) byte; - cursor += n; - } - - dest->hi = aes_load_block128_aligned(bytes); - } - - return AES_SUCCESS; -} diff --git a/src/asm/aes128.asm b/src/asm/aes128.asm deleted file mode 100644 index 80be57c..0000000 --- a/src/asm/aes128.asm +++ /dev/null @@ -1,203 +0,0 @@ -; Copyright (c) 2015 Egor Tensin -; This file is part of the "AES tools" project. -; For details, see https://github.com/egor-tensin/aes-tools. -; Distributed under the MIT License. - -.586 -.xmm -.model flat - -.code - -@aes_AES128_encrypt_block_@20 proc - pxor xmm0, [ecx] - aesenc xmm0, [ecx + 10h] - aesenc xmm0, [ecx + 20h] - aesenc xmm0, [ecx + 30h] - aesenc xmm0, [ecx + 40h] - aesenc xmm0, [ecx + 50h] - aesenc xmm0, [ecx + 60h] - aesenc xmm0, [ecx + 70h] - aesenc xmm0, [ecx + 80h] - aesenc xmm0, [ecx + 90h] - aesenclast xmm0, [ecx + 0A0h] - ret -@aes_AES128_encrypt_block_@20 endp - -@aes_AES128_decrypt_block_@20 proc - pxor xmm0, [ecx] - aesdec xmm0, [ecx + 10h] - aesdec xmm0, [ecx + 20h] - aesdec xmm0, [ecx + 30h] - aesdec xmm0, [ecx + 40h] - aesdec xmm0, [ecx + 50h] - aesdec xmm0, [ecx + 60h] - aesdec xmm0, [ecx + 70h] - aesdec xmm0, [ecx + 80h] - aesdec xmm0, [ecx + 90h] - aesdeclast xmm0, [ecx + 0A0h] - ret -@aes_AES128_decrypt_block_@20 endp - -@aes_AES128_expand_key_@20 proc - ; A "word" (in terms of the FIPS 187 standard) is a 32-bit block. - ; Words are denoted by `w[N]`. - ; - ; A key schedule is composed of 10 "regular" keys and a dumb key for - ; the "whitening" step. - ; - ; A key schedule is thus composed of 44 "words". - ; The FIPS standard includes an algorithm to calculate these words via - ; a simple loop: - ; - ; i = 4 - ; while i < 44: - ; temp = w[i - 1] - ; if i % 4 == 0: - ; temp = SubWord(RotWord(temp))^Rcon - ; w[i] = w[i - 4]^temp - ; i = i + 1 - ; - ; The loop above may be unrolled like this: - ; - ; w[4] = SubWord(RotWord(w[3]))^Rcon^w[0] - ; w[5] = w[4]^w[1] - ; = SubWord(RotWord(w[3]))^Rcon^w[1]^w[0] - ; w[6] = w[5]^w[2] - ; = SubWord(RotWord(w[3]))^Rcon^w[2]^w[1]^w[0] - ; w[7] = w[6]^w[3] - ; = SubWord(RotWord(w[3]))^Rcon^w[3]^w[2]^w[1]^w[0] - ; w[8] = SubWord(RotWord(w[7]))^Rcon^w[4] - ; w[9] = w[8]^w[5] - ; = SubWord(RotWord(w[7]))^Rcon^w[5]^w[4] - ; w[10] = w[9]^w[6] - ; = SubWord(RotWord(w[7]))^Rcon^w[6]^w[5]^w[4] - ; w[11] = w[10]^w[7] - ; = SubWord(RotWord(w[7]))^Rcon^w[7]^w[6]^w[5]^w[4] - ; - ; ... and so on. - ; - ; The Intel AES-NI instruction set facilitates calculating SubWord - ; and RotWord using `aeskeygenassist`, which is used in this routine. - ; - ; Preconditions: - ; * xmm0[127:96] == w[3], - ; * xmm0[95:64] == w[2], - ; * xmm0[63:32] == w[1], - ; * xmm0[31:0] == w[0]. - - movdqa [ecx], xmm0 ; sets w[0], w[1], w[2], w[3] - add ecx, 10h ; ecx = &w[4] - - aeskeygenassist xmm5, xmm0, 01h ; xmm5[127:96] = RotWord(SubWord(w[3]))^Rcon - call aes128_keygen_assist ; sets w[4], w[5], w[6], w[7] - aeskeygenassist xmm5, xmm0, 02h ; xmm5[127:96] = RotWord(SubWord(w[7]))^Rcon - call aes128_keygen_assist ; sets w[8], w[9], w[10], w[11] - aeskeygenassist xmm5, xmm0, 04h ; xmm5[127:96] = RotWord(SubWord(w[11]))^Rcon - call aes128_keygen_assist ; sets w[12], w[13], w[14], w[15] - aeskeygenassist xmm5, xmm0, 08h ; xmm5[127:96] = RotWord(SubWord(w[15]))^Rcon - call aes128_keygen_assist ; sets w[16], w[17], w[18], w[19] - aeskeygenassist xmm5, xmm0, 10h ; xmm5[127:96] = RotWord(SubWord(w[19]))^Rcon - call aes128_keygen_assist ; sets w[20], w[21], w[22], w[23] - aeskeygenassist xmm5, xmm0, 20h ; xmm5[127:96] = RotWord(SubWord(w[23]))^Rcon - call aes128_keygen_assist ; sets w[24], w[25], w[26], w[27] - aeskeygenassist xmm5, xmm0, 40h ; xmm5[127:96] = RotWord(SubWord(w[27]))^Rcon - call aes128_keygen_assist ; sets w[28], w[29], w[30], w[31] - aeskeygenassist xmm5, xmm0, 80h ; xmm5[127:96] = RotWord(SubWord(w[31]))^Rcon - call aes128_keygen_assist ; sets w[32], w[33], w[34], w[35] - aeskeygenassist xmm5, xmm0, 1Bh ; xmm5[127:96] = RotWord(SubWord(w[35]))^Rcon - call aes128_keygen_assist ; sets w[36], w[37], w[38], w[39] - aeskeygenassist xmm5, xmm0, 36h ; xmm5[127:96] = RotWord(SubWord(w[39]))^Rcon - call aes128_keygen_assist ; sets w[40], w[41], w[42], w[43] - - ret - -aes128_keygen_assist: - ; Preconditions: - ; * xmm0[127:96] == w[i+3], - ; * xmm0[95:64] == w[i+2], - ; * xmm0[63:32] == w[i+1], - ; * xmm0[31:0] == w[i], - ; * xmm5[127:96] == RotWord(SubWord(w[i+3]))^Rcon, - ; * ecx == &w[i+4]. - ; - ; Postconditions: - ; * xmm0[127:96] == w[i+7] == RotWord(SubWord(w[i+3]))^Rcon^w[i+3]^w[i+2]^w[i+1]^w[i], - ; * xmm0[95:64] == w[i+6] == RotWord(SubWord(w[i+3]))^Rcon^w[i+2]^w[i+1]^w[i], - ; * xmm0[63:32] == w[i+5] == RotWord(SubWord(w[i+3]))^Rcon^w[i+1]^w[i], - ; * xmm0[31:0] == w[i+4] == RotWord(SubWord(w[i+3]))^Rcon^w[i], - ; * ecx == &w[i+8], - ; * the value in xmm4 is also modified. - - ; Calculate - ; w[i+3]^w[i+2]^w[i+1]^w[i], - ; w[i+2]^w[i+1]^w[i], - ; w[i+1]^w[i] and - ; w[i]. - movdqa xmm4, xmm0 ; xmm4 = xmm0 - pslldq xmm4, 4 ; xmm4 <<= 32 - pxor xmm0, xmm4 ; xmm0 ^= xmm4 - pslldq xmm4, 4 ; xmm4 <<= 32 - pxor xmm0, xmm4 ; xmm0 ^= xmm4 - pslldq xmm4, 4 ; xmm4 <<= 32 - pxor xmm0, xmm4 ; xmm0 ^= xmm4 - ; xmm0[127:96] == w[i+3]^w[i+2]^w[i+1]^w[i] - ; xmm0[95:64] == w[i+2]^w[i+1]^w[i] - ; xmm0[63:32] == w[i+1]^w[i] - ; xmm0[31:0] == w[i] - - ; Calculate - ; w[i+7] == RotWord(SubWord(w[i+3]))^Rcon^w[i+3]^w[i+2]^w[i+1]^w[i], - ; w[i+6] == RotWord(SubWord(w[i+3]))^Rcon^w[i+2]^w[i+1]^w[i], - ; w[i+5] == RotWord(SubWord(w[i+3]))^Rcon^w[i+1]^w[i] and - ; w[i+4] == RotWord(SubWord(w[i+3]))^Rcon^w[i]. - pshufd xmm4, xmm5, 0FFh ; xmm4[127:96] = xmm4[95:64] = xmm4[63:32] = xmm4[31:0] = xmm5[127:96] - pxor xmm0, xmm4 ; xmm0 ^= xmm4 - ; xmm0[127:96] == w[i+7] == RotWord(SubWord(w[i+3]))^Rcon^w[i+3]^w[i+2]^w[i+1]^w[i] - ; xmm0[95:64] == w[i+6] == RotWord(SubWord(w[i+3]))^Rcon^w[i+2]^w[i+1]^w[i] - ; xmm0[63:32] == w[i+5] == RotWord(SubWord(w[i+3]))^Rcon^w[i+1]^w[i] - ; xmm0[31:0] == w[i+4] == RotWord(SubWord(w[i+3]))^Rcon^w[i] - - ; Set w[i+4], w[i+5], w[i+6] and w[i+7]. - movdqa [ecx], xmm0 ; w[i+7] = RotWord(SubWord(w[i+3]))^Rcon^w[i+3]^w[i+2]^w[i+1]^w[i] - ; w[i+6] = RotWord(SubWord(w[i+3]))^Rcon^w[i+2]^w[i+1]^w[i] - ; w[i+5] = RotWord(SubWord(w[i+3]))^Rcon^w[i+1]^w[i] - ; w[i+4] = RotWord(SubWord(w[i+3]))^Rcon^w[i] - add ecx, 10h ; ecx = &w[i+8] - - ret -@aes_AES128_expand_key_@20 endp - -@aes_AES128_derive_decryption_keys_@8 proc - movdqa xmm5, [ecx] - movdqa xmm4, [ecx + 0A0h] - movdqa [edx], xmm4 - movdqa [edx + 0A0h], xmm5 - - aesimc xmm5, [ecx + 10h] - aesimc xmm4, [ecx + 90h] - movdqa [edx + 10h], xmm4 - movdqa [edx + 90h], xmm5 - - aesimc xmm5, [ecx + 20h] - aesimc xmm4, [ecx + 80h] - movdqa [edx + 20h], xmm4 - movdqa [edx + 80h], xmm5 - - aesimc xmm5, [ecx + 30h] - aesimc xmm4, [ecx + 70h] - movdqa [edx + 30h], xmm4 - movdqa [edx + 70h], xmm5 - - aesimc xmm5, [ecx + 40h] - aesimc xmm4, [ecx + 60h] - movdqa [edx + 40h], xmm4 - movdqa [edx + 60h], xmm5 - - aesimc xmm5, [ecx + 50h] - movdqa [edx + 50h], xmm5 - - ret -@aes_AES128_derive_decryption_keys_@8 endp - -end diff --git a/src/asm/aes192.asm b/src/asm/aes192.asm deleted file mode 100644 index 6a41243..0000000 --- a/src/asm/aes192.asm +++ /dev/null @@ -1,249 +0,0 @@ -; Copyright (c) 2015 Egor Tensin -; This file is part of the "AES tools" project. -; For details, see https://github.com/egor-tensin/aes-tools. -; Distributed under the MIT License. - -.586 -.xmm -.model flat - -.code - -@aes_AES192_encrypt_block_@20 proc - pxor xmm0, [ecx] - aesenc xmm0, [ecx + 10h] - aesenc xmm0, [ecx + 20h] - aesenc xmm0, [ecx + 30h] - aesenc xmm0, [ecx + 40h] - aesenc xmm0, [ecx + 50h] - aesenc xmm0, [ecx + 60h] - aesenc xmm0, [ecx + 70h] - aesenc xmm0, [ecx + 80h] - aesenc xmm0, [ecx + 90h] - aesenc xmm0, [ecx + 0A0h] - aesenc xmm0, [ecx + 0B0h] - aesenclast xmm0, [ecx + 0C0h] - ret -@aes_AES192_encrypt_block_@20 endp - -@aes_AES192_decrypt_block_@20 proc - pxor xmm0, [ecx] - aesdec xmm0, [ecx + 10h] - aesdec xmm0, [ecx + 20h] - aesdec xmm0, [ecx + 30h] - aesdec xmm0, [ecx + 40h] - aesdec xmm0, [ecx + 50h] - aesdec xmm0, [ecx + 60h] - aesdec xmm0, [ecx + 70h] - aesdec xmm0, [ecx + 80h] - aesdec xmm0, [ecx + 90h] - aesdec xmm0, [ecx + 0A0h] - aesdec xmm0, [ecx + 0B0h] - aesdeclast xmm0, [ecx + 0C0h] - ret -@aes_AES192_decrypt_block_@20 endp - -@aes_AES192_expand_key_@36 proc - ; A "word" (in terms of the FIPS 187 standard) is a 32-bit block. - ; Words are denoted by `w[N]`. - ; - ; A key schedule is composed of 12 "regular" keys and a dumb key for - ; the "whitening" step. - ; - ; A key schedule is thus composed of 52 "words". - ; The FIPS standard includes an algorithm to calculate these words via - ; a simple loop: - ; - ; i = 6 - ; while i < 52: - ; temp = w[i - 1] - ; if i % 6 == 0: - ; temp = SubWord(RotWord(temp))^Rcon - ; w[i] = w[i - 6]^temp - ; i = i + 1 - ; - ; The loop above may be unrolled like this: - ; - ; w[6] = SubWord(RotWord(w[5]))^Rcon^w[0] - ; w[7] = w[6]^w[1] - ; = SubWord(RotWord(w[5]))^Rcon^w[0]^w[1] - ; w[8] = w[7]^w[2] - ; = SubWord(RotWord(w[5]))^Rcon^w[0]^w[1]^w[2] - ; w[9] = w[8]^w[3] - ; = SubWord(RotWord(w[5]))^Rcon^w[0]^w[1]^w[2]^w[3] - ; w[10] = w[9]^w[4] - ; = SubWord(RotWord(w[5]))^Rcon^w[0]^w[1]^w[2]^w[3]^w[4] - ; w[11] = w[10]^w[5] - ; = SubWord(RotWord(w[5]))^Rcon^w[0]^w[1]^w[2]^w[3]^w[4]^w[5] - ; w[12] = SubWord(RotWord(w[11]))^Rcon^w[6] - ; w[13] = w[12]^w[7] - ; = SubWord(RotWord(w[11]))^Rcon^w[6]^w[7] - ; w[14] = w[13]^w[8] - ; = SubWord(RotWord(w[11]))^Rcon^w[6]^w[7]^w[8] - ; w[15] = w[14]^w[9] - ; = SubWord(RotWord(w[11]))^Rcon^w[6]^w[7]^w[8]^w[9] - ; w[16] = w[15]^w[10] - ; = SubWord(RotWord(w[11]))^Rcon^w[6]^w[7]^w[8]^w[9]^w[10] - ; w[17] = w[16]^w[11] - ; = SubWort(RotWord(w[11]))^Rcon^w[6]^w[7]^w[8]^w[9]^w[10]^w[11] - ; - ; ... and so on. - ; - ; The Intel AES-NI instruction set facilitates calculating SubWord - ; and RotWord using `aeskeygenassist`, which is used in this routine. - ; - ; Preconditions: - ; * xmm1[63:32] == w[5], - ; * xmm1[31:0] == w[4], - ; * xmm0[127:96] == w[3], - ; * xmm0[95:64] == w[2], - ; * xmm0[63:32] == w[1], - ; * xmm0[31:0] == w[0]. - - movdqa [ecx], xmm0 ; sets w[0], w[1], w[2], w[3] - movq qword ptr [ecx + 10h], xmm1 ; sets w[4], w[5] - - aeskeygenassist xmm5, xmm1, 1 ; xmm5[63:32] = RotWord(SubWord(w[5]))^Rcon, - call aes192_keygen_assist - movdqu [ecx + 18h], xmm0 - movq qword ptr [ecx + 28h], xmm1 - aeskeygenassist xmm5, xmm1, 2 ; xmm5[63:32] = RotWord(SubWord(w[11]))^Rcon - call aes192_keygen_assist - movdqa [ecx + 30h], xmm0 - movq qword ptr [ecx + 40h], xmm1 - aeskeygenassist xmm5, xmm1, 4 ; xmm5[63:32] = RotWord(SubWord(w[17]))^Rcon - call aes192_keygen_assist - movdqu [ecx + 48h], xmm0 - movq qword ptr [ecx + 58h], xmm1 - aeskeygenassist xmm5, xmm1, 8 ; xmm5[63:32] = RotWord(SubWord(w[23]))^Rcon - call aes192_keygen_assist - movdqa [ecx + 60h], xmm0 - movq qword ptr [ecx + 70h], xmm1 - aeskeygenassist xmm5, xmm1, 10h ; xmm5[63:32] = RotWord(SubWord(w[29]))^Rcon - call aes192_keygen_assist - movdqu [ecx + 78h], xmm0 - movq qword ptr [ecx + 88h], xmm1 - aeskeygenassist xmm5, xmm1, 20h ; xmm5[63:32] = RotWord(SubWord(w[35]))^Rcon - call aes192_keygen_assist - movdqa [ecx + 90h], xmm0 - movq qword ptr [ecx + 0a0h], xmm1 - aeskeygenassist xmm5, xmm1, 40h ; xmm5[63:32] = RotWord(SubWord(w[41]))^Rcon - call aes192_keygen_assist - movdqu [ecx + 0a8h], xmm0 - movq qword ptr [ecx + 0b8h], xmm1 - aeskeygenassist xmm5, xmm1, 80h ; xmm5[63:32] = RotWord(SubWord(w[49]))^Rcon - call aes192_keygen_assist - movdqa [ecx + 0c0h], xmm0 - - ret - -aes192_keygen_assist: - ; Preconditions: - ; * xmm1[127:96] == 0, - ; * xmm1[95:64] == 0, - ; * xmm1[63:32] == w[i+5], - ; * xmm1[31:0] == w[i+4], - ; * xmm0[127:96] == w[i+3], - ; * xmm0[95:64] == w[i+2], - ; * xmm0[63:32] == w[i+1], - ; * xmm0[31:0] == w[i], - ; * xmm5[63:32] == RotWord(SubWord(w[i+5]))^Rcon. - ; - ; Postconditions: - ; * xmm1[127:96] == 0, - ; * xmm1[95:64] == 0, - ; * xmm1[63:32] == w[i+11] == RotWord(SubWord(w[i+5]))^Rcon^w[i+5]^w[i+4]^w[i+3]^w[i+2]^w[i+1]^w[i], - ; * xmm1[31:0] == w[i+10] == RotWord(SubWord(w[i+5]))^Rcon^w[i+4]^w[i+3]^w[i+2]^w[i+1]^w[i], - ; * xmm0[127:96] == w[i+9] == RotWord(SubWord(w[i+5]))^Rcon^w[i+3]^w[i+2]^w[i+1]^w[i], - ; * xmm0[95:64] == w[i+8] == RotWord(SubWord(w[i+5]))^Rcon^w[i+2]^w[i+1]^w[i], - ; * xmm0[63:32] == w[i+7] == RotWord(SubWord(w[i+5]))^Rcon^w[i+1]^w[i], - ; * xmm0[31:0] == w[i+6] == RotWord(SubWord(w[i+5]))^Rcon^w[i], - ; * the value in xmm4 is also modified. - - ; Calculate - ; w[i+3]^w[i+2]^w[i+1]^w[i], - ; w[i+2]^w[i+1]^w[i], - ; w[i+1]^w[i] and - ; w[i]. - movdqa xmm4, xmm0 ; xmm4 = xmm0 - pslldq xmm4, 4 ; xmm4 <<= 32 - pxor xmm0, xmm4 ; xmm0 ^= xmm4 - pslldq xmm4, 4 ; xmm4 <<= 32 - pxor xmm0, xmm4 ; xmm0 ^= xmm4 - pslldq xmm4, 4 ; xmm4 <<= 32 - pxor xmm0, xmm4 ; xmm0 ^= xmm4 - ; xmm0[127:96] == w[i+3]^w[i+2]^w[i+1]^w[i] - ; xmm0[95:64] == w[i+2]^w[i+1]^w[i] - ; xmm0[63:32] == w[i+1]^w[i] - ; xmm0[31:0] == w[i] - - ; Calculate - ; w[i+9] == RotWord(SubWord(w[i+5]))^Rcon^w[i+3]^w[i+2]^w[i+1]^w[i], - ; w[i+8] == RotWord(SubWord(w[i+5]))^Rcon^w[i+2]^w[i+1]^w[i], - ; w[i+7] == RotWord(SubWord(w[i+5]))^Rcon^w[i+1]^w[i] and - ; w[i+6] == RotWord(SubWord(w[i+5]))^Rcon^w[i]. - pshufd xmm4, xmm5, 55h ; xmm4[127:96] = xmm4[95:64] = xmm4[63:32] = xmm4[31:0] = xmm5[63:32] - pxor xmm0, xmm4 ; xmm0 ^= xmm4 - ; xmm0[127:96] == w[i+9] == RotWord(SubWord(w[i+5]))^Rcon^w[i+3]^w[i+2]^w[i+1]^w[i] - ; xmm0[95:64] == w[i+8] == RotWord(SubWord(w[i+5]))^Rcon^w[i+2]^w[i+1]^w[i] - ; xmm0[63:32] == w[i+7] == RotWord(SubWord(w[i+5]))^Rcon^w[i+1]^w[i] - ; xmm0[31:0] == w[i+6] == RotWord(SubWord(w[i+5]))^Rcon^w[i] - - ; Calculate - ; w[i+5]^w[i+4], - ; w[i+4]. - pshufd xmm4, xmm1, 0F3h ; xmm4 = xmm1[31:0] << 32 - pxor xmm1, xmm4 ; xmm1 ^= xmm5 - ; xmm1[63:32] == w[i+5]^w[i+4] - ; xmm1[31:0] == w[i+4] - - ; Calculate - ; w[i+10] == RotWord(SubWord(w[i+5]))^Rcon^w[i+5]^w[i+4]^w[i+3]^w[i+2]^w[i+1]^w[i], - ; w[i+11] == RotWord(SubWord(w[i+5]))^Rcon^w[i+4]^w[i+3]^w[i+2]^w[i+1]^w[i]. - pshufd xmm4, xmm0, 0FFh ; xmm4[127:96] = xmm4[95:64] = xmm4[63:32] = xmm4[31:0] = xmm0[127:96] - psrldq xmm4, 8 ; xmm4 >>= 64 - pxor xmm1, xmm4 ; xmm1 ^= xmm4 - ; xmm1[63:32] == w[i+11] == RotWord(SubWord(w[i+5]))^Rcon^w[i+5]^w[i+4]^w[i+3]^w[i+2]^w[i+1]^w[i] - ; xmm1[31:0] == w[i+10] == RotWord(SubWord(w[i+5]))^Rcon^w[i+4]^w[i+3]^w[i+2]^w[i+1]^w[i] - - ret -@aes_AES192_expand_key_@36 endp - -@aes_AES192_derive_decryption_keys_@8 proc - movdqa xmm5, [ecx] - movdqa xmm4, [ecx + 0C0h] - movdqa [edx], xmm4 - movdqa [edx + 0C0h], xmm5 - - aesimc xmm5, [ecx + 10h] - aesimc xmm4, [ecx + 0B0h] - movdqa [edx + 10h], xmm4 - movdqa [edx + 0B0h], xmm5 - - aesimc xmm5, [ecx + 20h] - aesimc xmm4, [ecx + 0A0h] - movdqa [edx + 20h], xmm4 - movdqa [edx + 0A0h], xmm5 - - aesimc xmm5, [ecx + 30h] - aesimc xmm4, [ecx + 90h] - movdqa [edx + 30h], xmm4 - movdqa [edx + 90h], xmm5 - - aesimc xmm5, [ecx + 40h] - aesimc xmm4, [ecx + 80h] - movdqa [edx + 40h], xmm4 - movdqa [edx + 80h], xmm5 - - aesimc xmm5, [ecx + 50h] - aesimc xmm4, [ecx + 70h] - movdqa [edx + 50h], xmm4 - movdqa [edx + 70h], xmm5 - - aesimc xmm5, [ecx + 60h] - movdqa [edx + 60h], xmm5 - - ret -@aes_AES192_derive_decryption_keys_@8 endp - -end diff --git a/src/asm/aes256.asm b/src/asm/aes256.asm deleted file mode 100644 index 82f5f6f..0000000 --- a/src/asm/aes256.asm +++ /dev/null @@ -1,287 +0,0 @@ -; Copyright (c) 2015 Egor Tensin -; This file is part of the "AES tools" project. -; For details, see https://github.com/egor-tensin/aes-tools. -; Distributed under the MIT License. - -.586 -.xmm -.model flat - -.code - -@aes_AES256_encrypt_block_@20 proc - pxor xmm0, [ecx] - aesenc xmm0, [ecx + 10h] - aesenc xmm0, [ecx + 20h] - aesenc xmm0, [ecx + 30h] - aesenc xmm0, [ecx + 40h] - aesenc xmm0, [ecx + 50h] - aesenc xmm0, [ecx + 60h] - aesenc xmm0, [ecx + 70h] - aesenc xmm0, [ecx + 80h] - aesenc xmm0, [ecx + 90h] - aesenc xmm0, [ecx + 0A0h] - aesenc xmm0, [ecx + 0B0h] - aesenc xmm0, [ecx + 0C0h] - aesenc xmm0, [ecx + 0D0h] - aesenclast xmm0, [ecx + 0E0h] - ret -@aes_AES256_encrypt_block_@20 endp - -@aes_AES256_decrypt_block_@20 proc - pxor xmm0, [ecx] - aesdec xmm0, [ecx + 10h] - aesdec xmm0, [ecx + 20h] - aesdec xmm0, [ecx + 30h] - aesdec xmm0, [ecx + 40h] - aesdec xmm0, [ecx + 50h] - aesdec xmm0, [ecx + 60h] - aesdec xmm0, [ecx + 70h] - aesdec xmm0, [ecx + 80h] - aesdec xmm0, [ecx + 90h] - aesdec xmm0, [ecx + 0A0h] - aesdec xmm0, [ecx + 0B0h] - aesdec xmm0, [ecx + 0C0h] - aesdec xmm0, [ecx + 0D0h] - aesdeclast xmm0, [ecx + 0E0h] - ret -@aes_AES256_decrypt_block_@20 endp - -@aes_AES256_expand_key_@36 proc - ; A "word" (in terms of the FIPS 187 standard) is a 32-bit block. - ; Words are denoted by `w[N]`. - ; - ; A key schedule is composed of 14 "regular" keys and a dumb key for - ; the "whitening" step. - ; - ; A key schedule is thus composed of 60 "words". - ; The FIPS standard includes an algorithm to calculate these words via - ; a simple loop: - ; - ; i = 8 - ; while i < 60: - ; temp = w[i - 1] - ; if i % 8 == 0: - ; temp = SubWord(RotWord(temp))^Rcon - ; elif i % 8 == 4: - ; temp = SubWord(temp) - ; w[i] = w[i - 8]^temp - ; i = i + 1 - ; - ; The loop above may be unrolled like this: - ; - ; w[8] = SubWord(RotWord(w[7]))^Rcon^w[0] - ; w[9] = w[8]^w[1] - ; = SubWord(RotWord(w[7]))^Rcon^w[1]^w[0] - ; w[10] = w[9]^w[2] - ; = SubWord(RotWord(w[7]))^Rcon^w[2]^w[1]^w[0] - ; w[11] = w[10]^w[3] - ; = SubWord(RotWord(w[7]))^Rcon^w[3]^w[2]^w[1]^w[0] - ; w[12] = SubWord(w[11])^w[4] - ; w[13] = w[12]^w[5] - ; = SubWord(w[11])^w[5]^w[4] - ; w[14] = w[13]^w[6] - ; = SubWord(w[11])^w[6]^w[5]^w[4] - ; w[15] = w[14]^w[7] - ; = SubWord(w[11])^w[7]^w[6]^w[5]^w[4] - ; w[16] = SubWord(RotWord(w[15]))^Rcon^w[8] - ; w[17] = w[16]^w[9] - ; = SubWord(RotWord(w[15]))^Rcon^w[9]^w[8] - ; w[18] = w[17]^w[10] - ; = SubWord(RotWord(w[15]))^Rcon^w[10]^w[9]^w[8] - ; w[19] = w[18]^w[11] - ; = SubWord(RotWord(w[15]))^Rcon^w[11]^w[10]^w[9]^w[8] - ; w[20] = SubWord(w[19])^w[12] - ; w[21] = w[20]^w[13] - ; = SubWord(w[19])^w[13]^w[12] - ; w[22] = w[21]^w[14] - ; = SubWord(w[19])^w[14]^w[13]^w[12] - ; w[23] = w[22]^w[15] - ; = SubWord(w[19])^w[15]^w[14]^w[13]^w[12] - ; - ; ... and so on. - ; - ; The Intel AES-NI instruction set facilitates calculating SubWord - ; and RotWord using `aeskeygenassist`, which is used in this routine. - ; - ; Preconditions: - ; * xmm1[127:96] == w[7], - ; * xmm1[95:64] == w[6], - ; * xmm1[63:32] == w[5], - ; * xmm1[31:0] == w[4], - ; * xmm0[127:96] == w[3], - ; * xmm0[95:64] == w[2], - ; * xmm0[63:32] == w[1], - ; * xmm0[31:0] == w[0]. - - movdqa [ecx], xmm0 ; sets w[0], w[1], w[2], w[3] - movdqa [ecx + 10h], xmm1 ; sets w[4], w[5], w[6], w[7] - lea ecx, [ecx + 20h] ; ecx = &w[8] - - aeskeygenassist xmm5, xmm1, 1h ; xmm5[127:96] = RotWord(SubWord(w[7]))^Rcon - pshufd xmm5, xmm5, 0FFh ; xmm5[95:64] = xmm5[63:32] = xmm5[31:0] = xmm5[127:96] - call aes256_keygen_assist ; sets w[8], w[9], w[10], w[11] - - aeskeygenassist xmm5, xmm1, 0 ; xmm5[95:64] = SubWord(w[11]) - pshufd xmm5, xmm5, 0AAh ; xmm5[127:96] = xmm5[63:32] = xmm5[31:0] = xmm5[95:64] - call aes256_keygen_assist ; sets w[12], w[13], w[14], w[15] - - aeskeygenassist xmm5, xmm1, 2h ; xmm5[127:96] = RotWord(SubWord(w[15]))^Rcon - pshufd xmm5, xmm5, 0FFh ; xmm5[95:64] = xmm5[63:32] = xmm5[31:0] = xmm5[127:96] - call aes256_keygen_assist ; sets w[16], w[17], w[18], w[19] - - aeskeygenassist xmm5, xmm1, 0 ; xmm5[95:64] = SubWord(w[19]) - pshufd xmm5, xmm5, 0AAh ; xmm5[127:96] = xmm5[63:32] = xmm5[31:0] = xmm5[95:64] - call aes256_keygen_assist ; sets w[20], w[21], w[22], w[23] - - aeskeygenassist xmm5, xmm1, 4h ; xmm5[127:96] = RotWord(SubWord(w[23]))^Rcon - pshufd xmm5, xmm5, 0FFh ; xmm5[95:64] = xmm5[63:32] = xmm5[31:0] = xmm5[127:96] - call aes256_keygen_assist ; sets w[24], w[25], w[26], w[27] - - aeskeygenassist xmm5, xmm1, 0 ; xmm5[95:64] = SubWord(w[27]) - pshufd xmm5, xmm5, 0AAh ; xmm5[127:96] = xmm5[63:32] = xmm5[31:0] = xmm5[95:64] - call aes256_keygen_assist ; sets w[28], w[29], w[30], w[31] - - aeskeygenassist xmm5, xmm1, 8h ; xmm5[127:96] = RotWord(SubWord(w[31]))^Rcon - pshufd xmm5, xmm5, 0FFh ; xmm5[95:64] = xmm5[63:32] = xmm5[31:0] = xmm5[127:96] - call aes256_keygen_assist ; sets w[32], w[33], w[34], w[35] - - aeskeygenassist xmm5, xmm1, 0 ; xmm5[95:64] = SubWord(w[35]) - pshufd xmm5, xmm5, 0AAh ; xmm5[127:96] = xmm5[63:32] = xmm5[31:0] = xmm5[95:64] - call aes256_keygen_assist ; sets w[36], w[37], w[38], w[39] - - aeskeygenassist xmm5, xmm1, 10h ; xmm5[127:96] = RotWord(SubWord(w[39]))^Rcon - pshufd xmm5, xmm5, 0FFh ; xmm5[95:64] = xmm5[63:32] = xmm5[31:0] = xmm5[127:96] - call aes256_keygen_assist ; sets w[40], w[41], w[42], w[43] - - aeskeygenassist xmm5, xmm1, 0 ; xmm5[95:64] = SubWord(w[43]) - pshufd xmm5, xmm5, 0AAh ; xmm5[127:96] = xmm5[63:32] = xmm5[31:0] = xmm5[95:64] - call aes256_keygen_assist ; sets w[44], w[45], w[46], w[47] - - aeskeygenassist xmm5, xmm1, 20h ; xmm5[127:96] = RotWord(SubWord(w[47]))^Rcon - pshufd xmm5, xmm5, 0FFh ; xmm5[95:64] = xmm5[63:32] = xmm5[31:0] = xmm5[127:96] - call aes256_keygen_assist ; sets w[48], w[49], w[50], w[51] - - aeskeygenassist xmm5, xmm1, 0 ; xmm5[95:64] = SubWord(w[51]) - pshufd xmm5, xmm5, 0AAh ; xmm5[127:96] = xmm5[63:32] = xmm5[31:0] = xmm5[95:64] - call aes256_keygen_assist ; sets w[52], w[53], w[54], w[55] - - aeskeygenassist xmm5, xmm1, 40h ; xmm5[127:96] = RotWord(SubWord(w[55]))^Rcon - pshufd xmm5, xmm5, 0FFh ; xmm5[95:64] = xmm5[63:32] = xmm5[31:0] = xmm5[127:96] - call aes256_keygen_assist ; sets w[56], w[57], w[58], w[59] - - ret - -aes256_keygen_assist: - ; Preconditions: - ; * xmm1[127:96] == w[i+7], - ; * xmm1[95:64] == w[i+6], - ; * xmm1[63:32] == w[i+5], - ; * xmm1[31:0] == w[i+4], - ; * xmm0[127:96] == w[i+3], - ; * xmm0[95:64] == w[i+2], - ; * xmm0[63:32] == w[i+1], - ; * xmm0[31:0] == w[i], - ; * xmm5[127:96] == xmm5[95:64] == xmm5[63:32] == xmm5[31:0] == HWGEN, - ; where HWGEN is either RotWord(SubWord(w[i+7]))^Rcon or SubWord(w[i+7]), - ; depending on the number of the round being processed, - ; * ecx == &w[i+8]. - ; - ; Postconditions: - ; * xmm1[127:96] == w[i+11] == HWGEN^w[i+3]^w[i+2]^w[i+1]^w[i], - ; * xmm1[95:64] == w[i+10] == HWGEN^w[i+2]^w[i+1]^w[i], - ; * xmm1[63:32] == w[i+9] == HWGEN^w[i+1]^w[i], - ; * xmm1[31:0] == w[i+8] == HWGEN^w[i], - ; * xmm0[127:96] == w[i+7], - ; * xmm0[95:64] == w[i+6], - ; * xmm0[63:32] == w[i+5], - ; * xmm0[31:0] == w[i+4], - ; * ecx == &w[i+12], - ; * the value in xmm4 is also modified. - - ; Calculate - ; w[i+3]^w[i+2]^w[i+1]^w[i], - ; w[i+2]^w[i+1]^w[i], - ; w[i+1]^w[i] and - ; w[i]. - movdqa xmm4, xmm0 ; xmm4 = xmm0 - pslldq xmm4, 4 ; xmm4 <<= 32 - pxor xmm0, xmm4 ; xmm0 ^= xmm4 - pslldq xmm4, 4 ; xmm4 <<= 32 - pxor xmm0, xmm4 ; xmm0 ^= xmm4 - pslldq xmm4, 4 ; xmm4 <<= 32 - pxor xmm0, xmm4 ; xmm0 ^= xmm4 - ; xmm0[127:96] == w[i+3]^w[i+2]^w[i+1]^w[i] - ; xmm0[95:64] == w[i+2]^w[i+1]^w[i] - ; xmm0[63:32] == w[i+1]^w[i] - ; xmm0[31:0] == w[i] - - ; Calculate - ; HWGEN^w[i+3]^w[i+2]^w[i+1]^w[i], - ; HWGEN^w[i+2]^w[i+1]^w[i], - ; HWGEN^w[i+1]^w[i] and - ; HWGEN^w[i]. - pxor xmm0, xmm5 ; xmm0 ^= xmm5 - ; xmm0[127:96] == w[i+11] == HWGEN^w[i+3]^w[i+2]^w[i+1]^w[i] - ; xmm0[95:64] == w[i+10] == HWGEN^w[i+2]^w[i+1]^w[i] - ; xmm0[63:32] == w[i+9] == HWGEN^w[i+1]^w[i] - ; xmm0[31:0] == w[i+8] == HWGEN^w[i] - - ; Set w[i+8], w[i+9], w[i+10] and w[i+11]. - movdqa [ecx], xmm0 ; w[i+8] = HWGEN^w[i] - ; w[i+9] = HWGEN^w[i+1]^w[i] - ; w[i+10] = HWGEN^w[i+2]^w[i+1]^w[i] - ; w[i+11] = HWGEN^w[i+3]^w[i+2]^w[i+1]^w[i] - add ecx, 10h ; ecx = &w[i+12] - - ; Swap the values in xmm0 and xmm1. - pxor xmm0, xmm1 - pxor xmm1, xmm0 - pxor xmm0, xmm1 - - ret -@aes_AES256_expand_key_@36 endp - -@aes_AES256_derive_decryption_keys_@8 proc - movdqa xmm5, [ecx] - movdqa xmm4, [ecx + 0E0h] - movdqa [edx], xmm4 - movdqa [edx + 0E0h], xmm5 - - aesimc xmm5, [ecx + 10h] - aesimc xmm4, [ecx + 0D0h] - movdqa [edx + 10h], xmm4 - movdqa [edx + 0D0h], xmm5 - - aesimc xmm5, [ecx + 20h] - aesimc xmm4, [ecx + 0C0h] - movdqa [edx + 20h], xmm4 - movdqa [edx + 0C0h], xmm5 - - aesimc xmm5, [ecx + 30h] - aesimc xmm4, [ecx + 0B0h] - movdqa [edx + 30h], xmm4 - movdqa [edx + 0B0h], xmm5 - - aesimc xmm5, [ecx + 40h] - aesimc xmm4, [ecx + 0A0h] - movdqa [edx + 40h], xmm4 - movdqa [edx + 0A0h], xmm5 - - aesimc xmm5, [ecx + 50h] - aesimc xmm4, [ecx + 90h] - movdqa [edx + 50h], xmm4 - movdqa [edx + 90h], xmm5 - - aesimc xmm5, [ecx + 60h] - aesimc xmm4, [ecx + 80h] - movdqa [edx + 60h], xmm4 - movdqa [edx + 80h], xmm5 - - aesimc xmm5, [ecx + 70h] - movdqa [edx + 70h], xmm5 - - ret -@aes_AES256_derive_decryption_keys_@8 endp - -end diff --git a/src/box.c b/src/box.c deleted file mode 100644 index c7e1e90..0000000 --- a/src/box.c +++ /dev/null @@ -1,683 +0,0 @@ -/* - * Copyright (c) 2015 Egor Tensin - * This file is part of the "AES tools" project. - * For details, see https://github.com/egor-tensin/aes-tools. - * Distributed under the MIT License. - */ - -#include - -#include -#include - -static const AES_BoxAlgorithmInterface* aes_box_algorithms[] = -{ - &aes_box_algorithm_aes128, - &aes_box_algorithm_aes192, - &aes_box_algorithm_aes256, -}; - -AES_StatusCode aes_box_init( - AES_Box* box, - AES_Algorithm algorithm, - const AES_BoxKey* box_key, - AES_Mode mode, - const AES_BoxBlock* iv, - AES_ErrorDetails* err_details) -{ - AES_StatusCode status = AES_SUCCESS; - - box->algorithm = aes_box_algorithms[algorithm]; - - if (aes_is_error(status = box->algorithm->calc_round_keys( - box_key, - &box->encryption_keys, - &box->decryption_keys, - err_details))) - return status; - - box->mode = mode; - if (iv != NULL) - box->iv = *iv; - - return status; -} - -static AES_StatusCode aes_box_encrypt_block_ecb( - AES_Box* box, - const AES_BoxBlock* input, - AES_BoxBlock* output, - AES_ErrorDetails* err_details) -{ - return box->algorithm->encrypt_block( - input, &box->encryption_keys, output, err_details); -} - -static AES_StatusCode aes_box_encrypt_block_cbc( - AES_Box* box, - const AES_BoxBlock* input, - AES_BoxBlock* output, - AES_ErrorDetails* err_details) -{ - AES_StatusCode status = AES_SUCCESS; - AES_BoxBlock xored_input = *input; - - if (aes_is_error(status = box->algorithm->xor_block( - &xored_input, &box->iv, err_details))) - return status; - - if (aes_is_error(status = box->algorithm->encrypt_block( - &xored_input, &box->encryption_keys, output, err_details))) - return status; - - box->iv = *output; - return status; -} - -static AES_StatusCode aes_box_encrypt_block_cfb( - AES_Box* box, - const AES_BoxBlock* input, - AES_BoxBlock* output, - AES_ErrorDetails* err_details) -{ - AES_StatusCode status = AES_SUCCESS; - - if (aes_is_error(status = box->algorithm->encrypt_block( - &box->iv, &box->encryption_keys, output, err_details))) - return status; - - if (aes_is_error(status = box->algorithm->xor_block( - output, input, err_details))) - return status; - - box->iv = *output; - return status; -} - -static AES_StatusCode aes_box_encrypt_block_ofb( - AES_Box* box, - const AES_BoxBlock* input, - AES_BoxBlock* output, - AES_ErrorDetails* err_details) -{ - AES_StatusCode status = AES_SUCCESS; - - if (aes_is_error(status = box->algorithm->encrypt_block( - &box->iv, &box->encryption_keys, &box->iv, err_details))) - return status; - - *output = box->iv; - - if (aes_is_error(status = box->algorithm->xor_block( - output, input, err_details))) - return status; - - return status; -} - -static AES_StatusCode aes_box_encrypt_block_ctr( - AES_Box* box, - const AES_BoxBlock* input, - AES_BoxBlock* output, - AES_ErrorDetails* err_details) -{ - AES_StatusCode status = AES_SUCCESS; - - if (aes_is_error(status = box->algorithm->encrypt_block( - &box->iv, &box->encryption_keys, output, err_details))) - return status; - - if (aes_is_error(status = box->algorithm->xor_block( - output, input, err_details))) - return status; - - if (aes_is_error(status = box->algorithm->inc_block( - &box->iv, err_details))) - return status; - - return status; -} - -typedef AES_StatusCode (*AES_BoxEncryptBlockInMode)( - AES_Box*, - const AES_BoxBlock*, - AES_BoxBlock*, - AES_ErrorDetails*); - -static AES_BoxEncryptBlockInMode aes_box_encrypt_block_in_mode[] = -{ - &aes_box_encrypt_block_ecb, - &aes_box_encrypt_block_cbc, - &aes_box_encrypt_block_cfb, - &aes_box_encrypt_block_ofb, - &aes_box_encrypt_block_ctr, -}; - -AES_StatusCode aes_box_encrypt_block( - AES_Box* box, - const AES_BoxBlock* input, - AES_BoxBlock* output, - AES_ErrorDetails* err_details) -{ - return aes_box_encrypt_block_in_mode[box->mode]( - box, input, output, err_details); -} - -static AES_StatusCode aes_box_decrypt_block_ecb( - AES_Box* box, - const AES_BoxBlock* input, - AES_BoxBlock* output, - AES_ErrorDetails* err_details) -{ - return box->algorithm->decrypt_block( - input, &box->decryption_keys, output, err_details); -} - -static AES_StatusCode aes_box_decrypt_block_cbc( - AES_Box* box, - const AES_BoxBlock* input, - AES_BoxBlock* output, - AES_ErrorDetails* err_details) -{ - AES_StatusCode status = AES_SUCCESS; - - if (aes_is_error(status = box->algorithm->decrypt_block( - input, &box->decryption_keys, output, err_details))) - return status; - - if (aes_is_error(status = box->algorithm->xor_block( - output, &box->iv, err_details))) - return status; - - box->iv = *input; - return status; -} - -static AES_StatusCode aes_box_decrypt_block_cfb( - AES_Box* box, - const AES_BoxBlock* input, - AES_BoxBlock* output, - AES_ErrorDetails* err_details) -{ - AES_StatusCode status = AES_SUCCESS; - - if (aes_is_error(status = box->algorithm->encrypt_block( - &box->iv, &box->encryption_keys, output, err_details))) - return status; - - if (aes_is_error(status = box->algorithm->xor_block( - output, input, err_details))) - return status; - - box->iv = *input; - return status; -} - -typedef AES_BoxEncryptBlockInMode AES_BoxDecryptBlockInMode; - -static AES_BoxDecryptBlockInMode aes_box_decrypt_block_in_mode[] = -{ - &aes_box_decrypt_block_ecb, - &aes_box_decrypt_block_cbc, - &aes_box_decrypt_block_cfb, - &aes_box_encrypt_block_ofb, - &aes_box_encrypt_block_ctr, -}; - -AES_StatusCode aes_box_decrypt_block( - AES_Box* box, - const AES_BoxBlock* input, - AES_BoxBlock* output, - AES_ErrorDetails* err_details) -{ - return aes_box_decrypt_block_in_mode[box->mode]( - box, input, output, err_details); -} - -static AES_StatusCode aes_box_get_encrypted_buffer_size( - AES_Box* box, - size_t src_size, - size_t* dest_size, - size_t* padding_size, - AES_ErrorDetails* err_details) -{ - AES_StatusCode status = AES_SUCCESS; - - switch (box->mode) - { - case AES_ECB: - case AES_CBC: - { - size_t block_size; - - if (aes_is_error(status = box->algorithm->get_block_size( - &block_size, err_details))) - return status; - - *padding_size = block_size - src_size % block_size; - *dest_size = src_size + *padding_size; - return status; - } - - case AES_CFB: - case AES_OFB: - case AES_CTR: - *dest_size = src_size; - *padding_size = 0; - return status; - - default: - return aes_error_not_implemented( - err_details, "unsupported mode of operation"); - } -} - -static AES_StatusCode aes_box_encrypt_buffer_block( - AES_Box* box, - const void* src, - void* dest, - AES_ErrorDetails* err_details) -{ - AES_StatusCode status = AES_SUCCESS; - - AES_BoxBlock plaintext; - - if (aes_is_error(status = box->algorithm->load_block( - &plaintext, src, err_details))) - return status; - - AES_BoxBlock ciphertext; - - if (aes_is_error(status = aes_box_encrypt_block( - box, &plaintext, &ciphertext, err_details))) - return status; - - if (aes_is_error(status = box->algorithm->store_block( - dest, &ciphertext, err_details))) - return status; - - return status; -} - -static AES_StatusCode aes_box_encrypt_buffer_partial_block_with_padding( - AES_Box* box, - const void* src, - size_t src_size, - void* dest, - size_t padding_size, - AES_ErrorDetails* err_details) -{ - AES_StatusCode status = AES_SUCCESS; - - size_t block_size; - - if (aes_is_error(status = box->algorithm->get_block_size( - &block_size, err_details))) - return status; - - void* plaintext_buf = malloc(block_size); - - if (plaintext_buf == NULL) - return status = aes_error_memory_allocation(err_details); - - memcpy(plaintext_buf, src, src_size); - - if (aes_is_error(status = aes_fill_with_padding( - AES_PADDING_PKCS7, - (char*) plaintext_buf + src_size, - padding_size, - err_details))) - goto FREE_PLAINTEXT_BUF; - - if (aes_is_error(status = aes_box_encrypt_buffer_block( - box, plaintext_buf, dest, err_details))) - goto FREE_PLAINTEXT_BUF; - -FREE_PLAINTEXT_BUF: - free(plaintext_buf); - - return status; -} - -static AES_StatusCode aes_box_encrypt_buffer_partial_block( - AES_Box* box, - const void* src, - size_t src_size, - void* dest, - AES_ErrorDetails* err_details) -{ - AES_StatusCode status = AES_SUCCESS; - - if (src_size == 0) - return status; - - size_t block_size; - - if (aes_is_error(status = box->algorithm->get_block_size( - &block_size, err_details))) - return status; - - void* plaintext_buf = malloc(block_size); - - if (plaintext_buf == NULL) - return status = aes_error_memory_allocation(err_details); - - memset(plaintext_buf, 0x00, block_size); - memcpy(plaintext_buf, src, src_size); - - void* ciphertext_buf = malloc(block_size); - - if (ciphertext_buf == NULL) - { - status = aes_error_memory_allocation(err_details); - goto FREE_PLAINTEXT_BUF; - } - - if (aes_is_error(status = aes_box_encrypt_buffer_block( - box, plaintext_buf, ciphertext_buf, err_details))) - goto FREE_CIPHERTEXT_BUF; - - memcpy(dest, ciphertext_buf, src_size); - -FREE_CIPHERTEXT_BUF: - free(ciphertext_buf); - -FREE_PLAINTEXT_BUF: - free(plaintext_buf); - - return status; -} - -AES_StatusCode aes_box_encrypt_buffer( - AES_Box* box, - const void* src, - size_t src_size, - void* dest, - size_t* dest_size, - AES_ErrorDetails* err_details) -{ - AES_StatusCode status = AES_SUCCESS; - - if (box == NULL) - return aes_error_null_argument(err_details, "box"); - if (dest_size == NULL) - return aes_error_null_argument(err_details, "dest_size"); - - size_t padding_size = 0; - - if (aes_is_error(status = aes_box_get_encrypted_buffer_size( - box, src_size, dest_size, &padding_size, err_details))) - return status; - - if (dest == NULL) - return AES_SUCCESS; - if (src == NULL && src_size != 0) - return aes_error_null_argument(err_details, "src"); - - size_t block_size; - - if (aes_is_error(status = box->algorithm->get_block_size( - &block_size, err_details))) - return status; - - const size_t src_len = src_size / block_size; - - for (size_t i = 0; i < src_len; ++i) - { - if (aes_is_error(status = aes_box_encrypt_buffer_block( - box, src, dest, err_details))) - return status; - - src = (char*) src + block_size; - dest = (char*) dest + block_size; - } - - if (padding_size == 0) - return aes_box_encrypt_buffer_partial_block( - box, src, src_size % block_size, dest, err_details); - else - return aes_box_encrypt_buffer_partial_block_with_padding( - box, src, src_size % block_size, dest, padding_size, err_details); -} - -static AES_StatusCode aes_box_get_decrypted_buffer_size( - AES_Box* box, - size_t src_size, - size_t* dest_size, - size_t* max_padding_size, - AES_ErrorDetails* err_details) -{ - AES_StatusCode status = AES_SUCCESS; - - switch (box->mode) - { - case AES_ECB: - case AES_CBC: - { - size_t block_size; - - if (aes_is_error(status = box->algorithm->get_block_size( - &block_size, err_details))) - return status; - - if (src_size == 0 || src_size % block_size != 0) - return aes_error_missing_padding(err_details); - - *dest_size = src_size; - *max_padding_size = block_size; - return status; - } - - case AES_CFB: - case AES_OFB: - case AES_CTR: - *dest_size = src_size; - *max_padding_size = 0; - return status; - - default: - return aes_error_not_implemented( - err_details, "unsupported mode of operation"); - } -} - -static AES_StatusCode aes_box_decrypt_buffer_block( - AES_Box* box, - const void* src, - void* dest, - AES_ErrorDetails* err_details) -{ - AES_StatusCode status = AES_SUCCESS; - - AES_BoxBlock ciphertext; - - if (aes_is_error(status = box->algorithm->load_block( - &ciphertext, src, err_details))) - return status; - - AES_BoxBlock plaintext; - - if (aes_is_error(status = aes_box_decrypt_block( - box, &ciphertext, &plaintext, err_details))) - return status; - - if (aes_is_error(status = box->algorithm->store_block( - dest, &plaintext, err_details))) - return status; - - return status; -} - -static AES_StatusCode aes_box_decrypt_buffer_partial_block( - AES_Box* box, - const void* src, - size_t src_size, - void* dest, - AES_ErrorDetails* err_details) -{ - AES_StatusCode status = AES_SUCCESS; - - if (src_size == 0) - return status; - - size_t block_size; - - if (aes_is_error(status = box->algorithm->get_block_size( - &block_size, err_details))) - return status; - - void* ciphertext_buf = malloc(block_size); - - if (ciphertext_buf == NULL) - return status = aes_error_memory_allocation(err_details); - - memset(ciphertext_buf, 0x00, block_size); - memcpy(ciphertext_buf, src, src_size); - - void* plaintext_buf = malloc(block_size); - - if (plaintext_buf == NULL) - { - status = aes_error_memory_allocation(err_details); - goto FREE_CIPHERTEXT_BUF; - } - - if (aes_is_error(status = aes_box_decrypt_buffer_block( - box, ciphertext_buf, plaintext_buf, err_details))) - goto FREE_PLAINTEXT_BUF; - - memcpy(dest, plaintext_buf, src_size); - -FREE_PLAINTEXT_BUF: - free(plaintext_buf); - -FREE_CIPHERTEXT_BUF: - free(ciphertext_buf); - - return status; -} - -AES_StatusCode aes_box_decrypt_buffer( - AES_Box* box, - const void* src, - size_t src_size, - void* dest, - size_t* dest_size, - AES_ErrorDetails* err_details) -{ - if (box == NULL) - return aes_error_null_argument(err_details, "box"); - if (dest_size == NULL) - return aes_error_null_argument(err_details, "dest_size"); - - AES_StatusCode status = AES_SUCCESS; - size_t max_padding_size = 0; - - if (aes_is_error(status = aes_box_get_decrypted_buffer_size( - box, src_size, dest_size, &max_padding_size, err_details))) - return status; - - if (dest == NULL) - return AES_SUCCESS; - if (src == NULL) - return aes_error_null_argument(err_details, "src"); - - size_t block_size; - - if (aes_is_error(status = box->algorithm->get_block_size( - &block_size, err_details))) - return status; - - const size_t src_len = src_size / block_size; - - for (size_t i = 0; i < src_len; ++i) - { - if (aes_is_error(status = aes_box_decrypt_buffer_block( - box, src, dest, err_details))) - return status; - - src = (char*) src + block_size; - dest = (char*) dest + block_size; - } - - if (max_padding_size == 0) - { - return aes_box_decrypt_buffer_partial_block( - box, src, src_size % block_size, dest, err_details); - } - else - { - size_t padding_size; - - if (aes_is_error(status = aes_extract_padding_size( - AES_PADDING_PKCS7, - (char*) dest - block_size, - block_size, - &padding_size, - err_details))) - return status; - - *dest_size -= padding_size; - return status; - } -} - -AES_StatusCode aes_box_parse_block( - AES_BoxBlock* dest, - AES_Algorithm algorithm, - const char* src, - AES_ErrorDetails* err_details) -{ - if (dest == NULL) - return aes_error_null_argument(err_details, "dest"); - if (src == NULL) - return aes_error_null_argument(err_details, "src"); - - return aes_box_algorithms[algorithm]->parse_block( - dest, src, err_details); -} - -AES_StatusCode aes_box_parse_key( - AES_BoxKey* dest, - AES_Algorithm algorithm, - const char* src, - AES_ErrorDetails* err_details) -{ - if (dest == NULL) - return aes_error_null_argument(err_details, "dest"); - if (src == NULL) - return aes_error_null_argument(err_details, "src"); - - return aes_box_algorithms[algorithm]->parse_key( - dest, src, err_details); -} - -AES_StatusCode aes_box_format_block( - AES_BoxBlockString* dest, - AES_Algorithm algorithm, - const AES_BoxBlock* src, - AES_ErrorDetails* err_details) -{ - if (dest == NULL) - return aes_error_null_argument(err_details, "dest"); - if (src == NULL) - return aes_error_null_argument(err_details, "src"); - - return aes_box_algorithms[algorithm]->format_block( - dest, src, err_details); -} - -AES_StatusCode aes_box_format_key( - AES_BoxKeyString* dest, - AES_Algorithm algorithm, - const AES_BoxKey* src, - AES_ErrorDetails* err_details) -{ - if (dest == NULL) - return aes_error_null_argument(err_details, "dest"); - if (src == NULL) - return aes_error_null_argument(err_details, "src"); - - return aes_box_algorithms[algorithm]->format_key( - dest, src, err_details); -} diff --git a/src/box_aes.c b/src/box_aes.c deleted file mode 100644 index 4d08d10..0000000 --- a/src/box_aes.c +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright (c) 2015 Egor Tensin - * This file is part of the "AES tools" project. - * For details, see https://github.com/egor-tensin/aes-tools. - * Distributed under the MIT License. - */ - -#include - -#include -#include - -static AES_StatusCode aes_box_derive_params_aes128( - const AES_BoxKey* box_key, - AES_BoxEncryptionRoundKeys* encryption_keys, - AES_BoxDecryptionRoundKeys* decryption_keys, - AES_ErrorDetails* err_details) -{ - AES_UNUSED_PARAMETER(err_details); - aes_AES128_expand_key_( - box_key->aes128_key.key, - &encryption_keys->aes128_encryption_keys); - aes_AES128_derive_decryption_keys_( - &encryption_keys->aes128_encryption_keys, - &decryption_keys->aes128_decryption_keys); - return AES_SUCCESS; -} - -static AES_StatusCode aes_box_derive_params_aes192( - const AES_BoxKey* box_key, - AES_BoxEncryptionRoundKeys* encryption_keys, - AES_BoxDecryptionRoundKeys* decryption_keys, - AES_ErrorDetails* err_details) -{ - AES_UNUSED_PARAMETER(err_details); - aes_AES192_expand_key_( - box_key->aes192_key.lo, - box_key->aes192_key.hi, - &encryption_keys->aes192_encryption_keys); - aes_AES192_derive_decryption_keys_( - &encryption_keys->aes192_encryption_keys, - &decryption_keys->aes192_decryption_keys); - return AES_SUCCESS; -} - -static AES_StatusCode aes_box_derive_params_aes256( - const AES_BoxKey* box_key, - AES_BoxEncryptionRoundKeys* encryption_keys, - AES_BoxDecryptionRoundKeys* decryption_keys, - AES_ErrorDetails* err_details) -{ - AES_UNUSED_PARAMETER(err_details); - aes_AES256_expand_key_( - box_key->aes256_key.lo, - box_key->aes256_key.hi, - &encryption_keys->aes256_encryption_keys); - aes_AES256_derive_decryption_keys_( - &encryption_keys->aes256_encryption_keys, - &decryption_keys->aes256_decryption_keys); - return AES_SUCCESS; -} - -static AES_StatusCode aes_box_parse_block_aes( - AES_BoxBlock* dest, - const char* src, - AES_ErrorDetails* err_details) -{ - if (dest == NULL) - return aes_error_null_argument(err_details, "dest"); - - return aes_AES_parse_block(&dest->aes_block, src, err_details); -} - -static AES_StatusCode aes_box_parse_key_aes128( - AES_BoxKey* dest, - const char* src, - AES_ErrorDetails* err_details) -{ - if (dest == NULL) - return aes_error_null_argument(err_details, "dest"); - - return aes_AES128_parse_key(&dest->aes128_key, src, err_details); -} - -static AES_StatusCode aes_box_parse_key_aes192( - AES_BoxKey* dest, - const char* src, - AES_ErrorDetails* err_details) -{ - if (dest == NULL) - return aes_error_null_argument(err_details, "dest"); - - return aes_AES192_parse_key(&dest->aes192_key, src, err_details); -} - -static AES_StatusCode aes_box_parse_key_aes256( - AES_BoxKey* dest, - const char* src, - AES_ErrorDetails* err_details) -{ - if (dest == NULL) - return aes_error_null_argument(err_details, "dest"); - - return aes_AES256_parse_key(&dest->aes256_key, src, err_details); -} - -static AES_StatusCode aes_box_format_block_aes( - AES_BoxBlockString* dest, - const AES_BoxBlock* src, - AES_ErrorDetails* err_details) -{ - if (dest == NULL) - return aes_error_null_argument(err_details, "dest"); - if (src == NULL) - return aes_error_null_argument(err_details, "src"); - - return aes_AES128_format_block(&dest->aes, &src->aes_block, err_details); -} - -static AES_StatusCode aes_box_format_key_aes128( - AES_BoxKeyString* dest, - const AES_BoxKey* src, - AES_ErrorDetails* err_details) -{ - if (dest == NULL) - return aes_error_null_argument(err_details, "dest"); - if (src == NULL) - return aes_error_null_argument(err_details, "src"); - - return aes_AES128_format_key(&dest->aes128, &src->aes128_key, err_details); -} - -static AES_StatusCode aes_box_format_key_aes192( - AES_BoxKeyString* dest, - const AES_BoxKey* src, - AES_ErrorDetails* err_details) -{ - if (dest == NULL) - return aes_error_null_argument(err_details, "dest"); - if (src == NULL) - return aes_error_null_argument(err_details, "src"); - - return aes_AES192_format_key(&dest->aes192, &src->aes192_key, err_details); -} - -static AES_StatusCode aes_box_format_key_aes256( - AES_BoxKeyString* dest, - const AES_BoxKey* src, - AES_ErrorDetails* err_details) -{ - if (dest == NULL) - return aes_error_null_argument(err_details, "dest"); - if (src == NULL) - return aes_error_null_argument(err_details, "src"); - - return aes_AES256_format_key(&dest->aes256, &src->aes256_key, err_details); -} - -static AES_StatusCode aes_box_xor_block_aes( - AES_BoxBlock* dest, - const AES_BoxBlock* src, - AES_ErrorDetails* err_details) -{ - AES_UNUSED_PARAMETER(err_details); - dest->aes_block = aes_AES_xor_blocks(dest->aes_block, src->aes_block); - return AES_SUCCESS; -} - -static AES_StatusCode aes_box_inc_block_aes( - AES_BoxBlock* ctr, - AES_ErrorDetails* err_details) -{ - AES_UNUSED_PARAMETER(err_details); - ctr->aes_block = aes_AES_inc_block(ctr->aes_block); - return AES_SUCCESS; -} - -static AES_StatusCode aes_box_get_block_size_aes( - size_t* block_size, - AES_ErrorDetails* err_details) -{ - AES_UNUSED_PARAMETER(err_details); - *block_size = 16; - return AES_SUCCESS; -} - -static AES_StatusCode aes_box_store_block_aes( - void* dest, - const AES_BoxBlock* src, - AES_ErrorDetails* err_details) -{ - AES_UNUSED_PARAMETER(err_details); - aes_store_block128(dest, src->aes_block); - return AES_SUCCESS; -} - -static AES_StatusCode aes_box_load_block_aes( - AES_BoxBlock* dest, - const void* src, - AES_ErrorDetails* err_details) -{ - AES_UNUSED_PARAMETER(err_details); - dest->aes_block = aes_load_block128(src); - return AES_SUCCESS; -} - -static AES_StatusCode aes_box_encrypt_block_aes128( - const AES_BoxBlock* input, - const AES_BoxEncryptionRoundKeys* params, - AES_BoxBlock* output, - AES_ErrorDetails* err_details) -{ - AES_UNUSED_PARAMETER(err_details); - output->aes_block = aes_AES128_encrypt_block_( - input->aes_block, - ¶ms->aes128_encryption_keys); - return AES_SUCCESS; -} - -static AES_StatusCode aes_box_decrypt_block_aes128( - const AES_BoxBlock* input, - const AES_BoxDecryptionRoundKeys* params, - AES_BoxBlock* output, - AES_ErrorDetails* err_details) -{ - AES_UNUSED_PARAMETER(err_details); - output->aes_block = aes_AES128_decrypt_block_( - input->aes_block, - ¶ms->aes128_decryption_keys); - return AES_SUCCESS; -} - -static AES_StatusCode aes_box_encrypt_block_aes192( - const AES_BoxBlock* input, - const AES_BoxEncryptionRoundKeys* params, - AES_BoxBlock* output, - AES_ErrorDetails* err_details) -{ - AES_UNUSED_PARAMETER(err_details); - output->aes_block = aes_AES192_encrypt_block_( - input->aes_block, - ¶ms->aes192_encryption_keys); - return AES_SUCCESS; -} - -static AES_StatusCode aes_box_decrypt_block_aes192( - const AES_BoxBlock* input, - const AES_BoxDecryptionRoundKeys* params, - AES_BoxBlock* output, - AES_ErrorDetails* err_details) -{ - AES_UNUSED_PARAMETER(err_details); - output->aes_block = aes_AES192_decrypt_block_( - input->aes_block, - ¶ms->aes192_decryption_keys); - return AES_SUCCESS; -} - -static AES_StatusCode aes_box_encrypt_block_aes256( - const AES_BoxBlock* input, - const AES_BoxEncryptionRoundKeys* params, - AES_BoxBlock* output, - AES_ErrorDetails* err_details) -{ - AES_UNUSED_PARAMETER(err_details); - output->aes_block = aes_AES256_encrypt_block_( - input->aes_block, - ¶ms->aes256_encryption_keys); - return AES_SUCCESS; -} - -static AES_StatusCode aes_box_decrypt_block_aes256( - const AES_BoxBlock* input, - const AES_BoxDecryptionRoundKeys* params, - AES_BoxBlock* output, - AES_ErrorDetails* err_details) -{ - AES_UNUSED_PARAMETER(err_details); - output->aes_block = aes_AES256_decrypt_block_( - input->aes_block, - ¶ms->aes256_decryption_keys); - return AES_SUCCESS; -} - -AES_BoxAlgorithmInterface aes_box_algorithm_aes128 = -{ - &aes_box_derive_params_aes128, - &aes_box_parse_block_aes, - &aes_box_parse_key_aes128, - &aes_box_format_block_aes, - &aes_box_format_key_aes128, - &aes_box_encrypt_block_aes128, - &aes_box_decrypt_block_aes128, - &aes_box_xor_block_aes, - &aes_box_inc_block_aes, - &aes_box_get_block_size_aes, - &aes_box_store_block_aes, - &aes_box_load_block_aes, -}; - -AES_BoxAlgorithmInterface aes_box_algorithm_aes192 = -{ - &aes_box_derive_params_aes192, - &aes_box_parse_block_aes, - &aes_box_parse_key_aes192, - &aes_box_format_block_aes, - &aes_box_format_key_aes192, - &aes_box_encrypt_block_aes192, - &aes_box_decrypt_block_aes192, - &aes_box_xor_block_aes, - &aes_box_inc_block_aes, - &aes_box_get_block_size_aes, - &aes_box_store_block_aes, - &aes_box_load_block_aes, -}; - -AES_BoxAlgorithmInterface aes_box_algorithm_aes256 = -{ - &aes_box_derive_params_aes256, - &aes_box_parse_block_aes, - &aes_box_parse_key_aes256, - &aes_box_format_block_aes, - &aes_box_format_key_aes256, - &aes_box_encrypt_block_aes256, - &aes_box_decrypt_block_aes256, - &aes_box_xor_block_aes, - &aes_box_inc_block_aes, - &aes_box_get_block_size_aes, - &aes_box_store_block_aes, - &aes_box_load_block_aes, -}; diff --git a/src/c/aes128.c b/src/c/aes128.c deleted file mode 100644 index a1bad40..0000000 --- a/src/c/aes128.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2015 Egor Tensin - * This file is part of the "AES tools" project. - * For details, see https://github.com/egor-tensin/aes-tools. - * Distributed under the MIT License. - */ - -#include - -#include -#include - -AES_AES_Block __fastcall aes_AES128_encrypt_block_( - AES_AES_Block plaintext, - const AES_AES128_RoundKeys* encryption_keys) -{ - plaintext = _mm_xor_si128(plaintext, encryption_keys->keys[0]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[1]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[2]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[3]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[4]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[5]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[6]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[7]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[8]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[9]); - return _mm_aesenclast_si128(plaintext, encryption_keys->keys[10]); -} - -AES_AES_Block __fastcall aes_AES128_decrypt_block_( - AES_AES_Block ciphertext, - const AES_AES128_RoundKeys* decryption_keys) -{ - ciphertext = _mm_xor_si128(ciphertext, decryption_keys->keys[0]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[1]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[2]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[3]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[4]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[5]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[6]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[7]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[8]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[9]); - return _mm_aesdeclast_si128(ciphertext, decryption_keys->keys[10]); -} - -static AES_AES_Block __fastcall aes_aes128_expand_key_assist( - AES_AES_Block prev, - AES_AES_Block hwgen) -{ - AES_AES_Block tmp = prev; - - tmp = _mm_slli_si128(tmp, 4); - prev = _mm_xor_si128(prev, tmp); - tmp = _mm_slli_si128(tmp, 4); - prev = _mm_xor_si128(prev, tmp); - tmp = _mm_slli_si128(tmp, 4); - prev = _mm_xor_si128(prev, tmp); - - hwgen = _mm_shuffle_epi32(hwgen, 0xff); - prev = _mm_xor_si128(prev, hwgen); - - return prev; -} - -void __fastcall aes_AES128_expand_key_( - AES_AES_Block key, - AES_AES128_RoundKeys* encryption_keys) -{ - AES_Block128 prev = encryption_keys->keys[0] = key; - prev = encryption_keys->keys[1] = aes_aes128_expand_key_assist(prev, _mm_aeskeygenassist_si128(prev, 0x01)); - prev = encryption_keys->keys[2] = aes_aes128_expand_key_assist(prev, _mm_aeskeygenassist_si128(prev, 0x02)); - prev = encryption_keys->keys[3] = aes_aes128_expand_key_assist(prev, _mm_aeskeygenassist_si128(prev, 0x04)); - prev = encryption_keys->keys[4] = aes_aes128_expand_key_assist(prev, _mm_aeskeygenassist_si128(prev, 0x08)); - prev = encryption_keys->keys[5] = aes_aes128_expand_key_assist(prev, _mm_aeskeygenassist_si128(prev, 0x10)); - prev = encryption_keys->keys[6] = aes_aes128_expand_key_assist(prev, _mm_aeskeygenassist_si128(prev, 0x20)); - prev = encryption_keys->keys[7] = aes_aes128_expand_key_assist(prev, _mm_aeskeygenassist_si128(prev, 0x40)); - prev = encryption_keys->keys[8] = aes_aes128_expand_key_assist(prev, _mm_aeskeygenassist_si128(prev, 0x80)); - prev = encryption_keys->keys[9] = aes_aes128_expand_key_assist(prev, _mm_aeskeygenassist_si128(prev, 0x1b)); - prev = encryption_keys->keys[10] = aes_aes128_expand_key_assist(prev, _mm_aeskeygenassist_si128(prev, 0x36)); -} - -void __fastcall aes_AES128_derive_decryption_keys_( - const AES_AES128_RoundKeys* encryption_keys, - AES_AES128_RoundKeys* decryption_keys) -{ - decryption_keys->keys[0] = encryption_keys->keys[10]; - decryption_keys->keys[1] = _mm_aesimc_si128(encryption_keys->keys[9]); - decryption_keys->keys[2] = _mm_aesimc_si128(encryption_keys->keys[8]); - decryption_keys->keys[3] = _mm_aesimc_si128(encryption_keys->keys[7]); - decryption_keys->keys[4] = _mm_aesimc_si128(encryption_keys->keys[6]); - decryption_keys->keys[5] = _mm_aesimc_si128(encryption_keys->keys[5]); - decryption_keys->keys[6] = _mm_aesimc_si128(encryption_keys->keys[4]); - decryption_keys->keys[7] = _mm_aesimc_si128(encryption_keys->keys[3]); - decryption_keys->keys[8] = _mm_aesimc_si128(encryption_keys->keys[2]); - decryption_keys->keys[9] = _mm_aesimc_si128(encryption_keys->keys[1]); - decryption_keys->keys[10] = encryption_keys->keys[0]; -} diff --git a/src/c/aes192.c b/src/c/aes192.c deleted file mode 100644 index d661b78..0000000 --- a/src/c/aes192.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2015 Egor Tensin - * This file is part of the "AES tools" project. - * For details, see https://github.com/egor-tensin/aes-tools. - * Distributed under the MIT License. - */ - -#include - -#include -#include - -AES_AES_Block __fastcall aes_AES192_encrypt_block_( - AES_AES_Block plaintext, - const AES_AES192_RoundKeys* encryption_keys) -{ - plaintext = _mm_xor_si128(plaintext, encryption_keys->keys[0]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[1]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[2]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[3]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[4]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[5]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[6]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[7]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[8]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[9]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[10]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[11]); - return _mm_aesenclast_si128(plaintext, encryption_keys->keys[12]); -} - -AES_AES_Block __fastcall aes_AES192_decrypt_block_( - AES_AES_Block ciphertext, - const AES_AES192_RoundKeys* decryption_keys) -{ - ciphertext = _mm_xor_si128(ciphertext, decryption_keys->keys[0]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[1]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[2]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[3]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[4]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[5]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[6]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[7]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[8]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[9]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[10]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[11]); - return _mm_aesdeclast_si128(ciphertext, decryption_keys->keys[12]); -} - -static void __fastcall aes_aes192_expand_key_assist( - AES_AES_Block* prev_lo, - AES_AES_Block* prev_hi, - AES_AES_Block hwgen) -{ - AES_AES_Block tmp = *prev_lo; - - tmp = _mm_slli_si128(tmp, 4); - *prev_lo = _mm_xor_si128(*prev_lo, tmp); - tmp = _mm_slli_si128(tmp, 4); - *prev_lo = _mm_xor_si128(*prev_lo, tmp); - tmp = _mm_slli_si128(tmp, 4); - *prev_lo = _mm_xor_si128(*prev_lo, tmp); - - hwgen = _mm_shuffle_epi32(hwgen, 0x55); - *prev_lo = _mm_xor_si128(*prev_lo, hwgen); - - tmp = _mm_shuffle_epi32(*prev_hi, 0xf3); - *prev_hi = _mm_xor_si128(*prev_hi, tmp); - - tmp = _mm_shuffle_epi32(*prev_lo, 0xff); - tmp = _mm_srli_si128(tmp, 8); - *prev_hi = _mm_xor_si128(*prev_hi, tmp); -} - -void __fastcall aes_AES192_expand_key_( - AES_AES_Block key_lo, - AES_AES_Block key_hi, - AES_AES192_RoundKeys* encryption_keys) -{ - encryption_keys->keys[0] = key_lo; - encryption_keys->keys[1] = key_hi; - - aes_aes192_expand_key_assist(&key_lo, &key_hi, _mm_aeskeygenassist_si128(key_hi, 0x01)); - encryption_keys->keys[1] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(encryption_keys->keys[1]), _mm_castsi128_pd(key_lo), 0)); - encryption_keys->keys[2] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(key_lo), _mm_castsi128_pd(key_hi), 1)); - - aes_aes192_expand_key_assist(&key_lo, &key_hi, _mm_aeskeygenassist_si128(key_hi, 0x02)); - encryption_keys->keys[3] = key_lo; - encryption_keys->keys[4] = key_hi; - - aes_aes192_expand_key_assist(&key_lo, &key_hi, _mm_aeskeygenassist_si128(key_hi, 0x04)); - encryption_keys->keys[4] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(encryption_keys->keys[4]), _mm_castsi128_pd(key_lo), 0)); - encryption_keys->keys[5] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(key_lo), _mm_castsi128_pd(key_hi), 1)); - - aes_aes192_expand_key_assist(&key_lo, &key_hi, _mm_aeskeygenassist_si128(key_hi, 0x08)); - encryption_keys->keys[6] = key_lo; - encryption_keys->keys[7] = key_hi; - - aes_aes192_expand_key_assist(&key_lo, &key_hi, _mm_aeskeygenassist_si128(key_hi, 0x10)); - encryption_keys->keys[7] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(encryption_keys->keys[7]), _mm_castsi128_pd(key_lo), 0)); - encryption_keys->keys[8] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(key_lo), _mm_castsi128_pd(key_hi), 1)); - - aes_aes192_expand_key_assist(&key_lo, &key_hi, _mm_aeskeygenassist_si128(key_hi, 0x20)); - encryption_keys->keys[9] = key_lo; - encryption_keys->keys[10] = key_hi; - - aes_aes192_expand_key_assist(&key_lo, &key_hi, _mm_aeskeygenassist_si128(key_hi, 0x40)); - encryption_keys->keys[10] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(encryption_keys->keys[10]), _mm_castsi128_pd(key_lo), 0)); - encryption_keys->keys[11] = _mm_castpd_si128(_mm_shuffle_pd(_mm_castsi128_pd(key_lo), _mm_castsi128_pd(key_hi), 1)); - - aes_aes192_expand_key_assist(&key_lo, &key_hi, _mm_aeskeygenassist_si128(key_hi, 0x80)); - encryption_keys->keys[12] = key_lo; -} - -void __fastcall aes_AES192_derive_decryption_keys_( - const AES_AES192_RoundKeys* encryption_keys, - AES_AES192_RoundKeys* decryption_keys) -{ - decryption_keys->keys[0] = encryption_keys->keys[12]; - decryption_keys->keys[1] = _mm_aesimc_si128(encryption_keys->keys[11]); - decryption_keys->keys[2] = _mm_aesimc_si128(encryption_keys->keys[10]); - decryption_keys->keys[3] = _mm_aesimc_si128(encryption_keys->keys[9]); - decryption_keys->keys[4] = _mm_aesimc_si128(encryption_keys->keys[8]); - decryption_keys->keys[5] = _mm_aesimc_si128(encryption_keys->keys[7]); - decryption_keys->keys[6] = _mm_aesimc_si128(encryption_keys->keys[6]); - decryption_keys->keys[7] = _mm_aesimc_si128(encryption_keys->keys[5]); - decryption_keys->keys[8] = _mm_aesimc_si128(encryption_keys->keys[4]); - decryption_keys->keys[9] = _mm_aesimc_si128(encryption_keys->keys[3]); - decryption_keys->keys[10] = _mm_aesimc_si128(encryption_keys->keys[2]); - decryption_keys->keys[11] = _mm_aesimc_si128(encryption_keys->keys[1]); - decryption_keys->keys[12] = encryption_keys->keys[0]; -} diff --git a/src/c/aes256.c b/src/c/aes256.c deleted file mode 100644 index 2190322..0000000 --- a/src/c/aes256.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2015 Egor Tensin - * This file is part of the "AES tools" project. - * For details, see https://github.com/egor-tensin/aes-tools. - * Distributed under the MIT License. - */ - -#include - -#include -#include - -AES_AES_Block __fastcall aes_AES256_encrypt_block_( - AES_AES_Block plaintext, - const AES_AES256_RoundKeys* encryption_keys) -{ - plaintext = _mm_xor_si128(plaintext, encryption_keys->keys[0]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[1]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[2]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[3]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[4]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[5]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[6]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[7]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[8]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[9]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[10]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[11]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[12]); - plaintext = _mm_aesenc_si128(plaintext, encryption_keys->keys[13]); - return _mm_aesenclast_si128(plaintext, encryption_keys->keys[14]); -} - -AES_AES_Block __fastcall aes_AES256_decrypt_block_( - AES_AES_Block ciphertext, - const AES_AES256_RoundKeys* decryption_keys) -{ - ciphertext = _mm_xor_si128(ciphertext, decryption_keys->keys[0]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[1]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[2]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[3]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[4]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[5]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[6]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[7]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[8]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[9]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[10]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[11]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[12]); - ciphertext = _mm_aesdec_si128(ciphertext, decryption_keys->keys[13]); - return _mm_aesdeclast_si128(ciphertext, decryption_keys->keys[14]); -} - -static AES_AES_Block __fastcall aes_aes256_expand_key_assist( - AES_AES_Block* prev_lo, - AES_AES_Block* prev_hi, - AES_AES_Block hwgen) -{ - AES_AES_Block tmp = *prev_lo; - - tmp = _mm_slli_si128(tmp, 4); - *prev_lo = _mm_xor_si128(*prev_lo, tmp); - tmp = _mm_slli_si128(tmp, 4); - *prev_lo = _mm_xor_si128(*prev_lo, tmp); - tmp = _mm_slli_si128(tmp, 4); - *prev_lo = _mm_xor_si128(*prev_lo, tmp); - - *prev_lo = _mm_xor_si128(*prev_lo, hwgen); - - *prev_hi = _mm_xor_si128(*prev_hi, *prev_lo); - *prev_lo = _mm_xor_si128(*prev_lo, *prev_hi); - *prev_hi = _mm_xor_si128(*prev_hi, *prev_lo); - - return *prev_hi; -} - -void __fastcall aes_AES256_expand_key_( - AES_AES_Block key_lo, - AES_AES_Block key_hi, - AES_AES256_RoundKeys* encryption_keys) -{ - AES_AES_Block prev_lo, prev_hi; - AES_AES_Block hwgen; - - prev_lo = encryption_keys->keys[0] = key_lo; - prev_hi = encryption_keys->keys[1] = key_hi; - - hwgen = _mm_aeskeygenassist_si128(prev_hi, 0x01); - hwgen = _mm_shuffle_epi32(hwgen, 0xff); - encryption_keys->keys[2] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); - - hwgen = _mm_aeskeygenassist_si128(prev_hi, 0); - hwgen = _mm_shuffle_epi32(hwgen, 0xaa); - encryption_keys->keys[3] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); - - hwgen = _mm_aeskeygenassist_si128(prev_hi, 0x02); - hwgen = _mm_shuffle_epi32(hwgen, 0xff); - encryption_keys->keys[4] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); - - hwgen = _mm_aeskeygenassist_si128(prev_hi, 0); - hwgen = _mm_shuffle_epi32(hwgen, 0xaa); - encryption_keys->keys[5] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); - - hwgen = _mm_aeskeygenassist_si128(prev_hi, 0x04); - hwgen = _mm_shuffle_epi32(hwgen, 0xff); - encryption_keys->keys[6] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); - - hwgen = _mm_aeskeygenassist_si128(prev_hi, 0); - hwgen = _mm_shuffle_epi32(hwgen, 0xaa); - encryption_keys->keys[7] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); - - hwgen = _mm_aeskeygenassist_si128(prev_hi, 0x08); - hwgen = _mm_shuffle_epi32(hwgen, 0xff); - encryption_keys->keys[8] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); - - hwgen = _mm_aeskeygenassist_si128(prev_hi, 0); - hwgen = _mm_shuffle_epi32(hwgen, 0xaa); - encryption_keys->keys[9] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); - - hwgen = _mm_aeskeygenassist_si128(prev_hi, 0x10); - hwgen = _mm_shuffle_epi32(hwgen, 0xff); - encryption_keys->keys[10] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); - - hwgen = _mm_aeskeygenassist_si128(prev_hi, 0); - hwgen = _mm_shuffle_epi32(hwgen, 0xaa); - encryption_keys->keys[11] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); - - hwgen = _mm_aeskeygenassist_si128(prev_hi, 0x20); - hwgen = _mm_shuffle_epi32(hwgen, 0xff); - encryption_keys->keys[12] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); - - hwgen = _mm_aeskeygenassist_si128(prev_hi, 0); - hwgen = _mm_shuffle_epi32(hwgen, 0xaa); - encryption_keys->keys[13] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); - - hwgen = _mm_aeskeygenassist_si128(prev_hi, 0x40); - hwgen = _mm_shuffle_epi32(hwgen, 0xff); - encryption_keys->keys[14] = aes_aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); -} - -void __fastcall aes_AES256_derive_decryption_keys_( - const AES_AES256_RoundKeys* encryption_keys, - AES_AES256_RoundKeys* decryption_keys) -{ - decryption_keys->keys[0] = encryption_keys->keys[14]; - decryption_keys->keys[1] = _mm_aesimc_si128(encryption_keys->keys[13]); - decryption_keys->keys[2] = _mm_aesimc_si128(encryption_keys->keys[12]); - decryption_keys->keys[3] = _mm_aesimc_si128(encryption_keys->keys[11]); - decryption_keys->keys[4] = _mm_aesimc_si128(encryption_keys->keys[10]); - decryption_keys->keys[5] = _mm_aesimc_si128(encryption_keys->keys[9]); - decryption_keys->keys[6] = _mm_aesimc_si128(encryption_keys->keys[8]); - decryption_keys->keys[7] = _mm_aesimc_si128(encryption_keys->keys[7]); - decryption_keys->keys[8] = _mm_aesimc_si128(encryption_keys->keys[6]); - decryption_keys->keys[9] = _mm_aesimc_si128(encryption_keys->keys[5]); - decryption_keys->keys[10] = _mm_aesimc_si128(encryption_keys->keys[4]); - decryption_keys->keys[11] = _mm_aesimc_si128(encryption_keys->keys[3]); - decryption_keys->keys[12] = _mm_aesimc_si128(encryption_keys->keys[2]); - decryption_keys->keys[13] = _mm_aesimc_si128(encryption_keys->keys[1]); - decryption_keys->keys[14] = encryption_keys->keys[0]; -} diff --git a/src/error.c b/src/error.c deleted file mode 100644 index d49c456..0000000 --- a/src/error.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright (c) 2015 Egor Tensin - * This file is part of the "AES tools" project. - * For details, see https://github.com/egor-tensin/aes-tools. - * Distributed under the MIT License. - */ - -#include - -#include -#include -#include -#include - -#if defined(_MSC_VER) && _MSC_VER < 1900 - -#include - -#define snprintf c99_snprintf -#define vsnprintf c99_vsnprintf - -static int c99_vsnprintf(char *dest, size_t dest_size, const char *fmt, va_list ap) -{ - int dest_len = -1; - - if (dest_size != 0) - dest_len = _vsnprintf_s(dest, dest_size, _TRUNCATE, fmt, ap); - if (dest_len == -1) - dest_len = _vscprintf(fmt, ap); - - return dest_len; -} - -static int c99_snprintf(char *dest, size_t dest_size, const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - - int dest_len = c99_vsnprintf(dest, dest_size, fmt, ap); - - va_end(ap); - return dest_len; -} - -#endif - -static void aes_fill_string(char* dest, size_t dest_size, const char* src) -{ - strncpy(dest, src, dest_size); - dest[dest_size - 1] = '\0'; -} - -static const char* aes_strerror_messages[] = -{ - "Success", - "Invalid argument value NULL", - "Couldn't parse", - "Invalid PKCS7 padding (wrong key?)", - "Not implemented", - "Missing padding", - "Couldn't allocate memory", -}; - -const char* aes_strerror(AES_StatusCode ec) -{ - return aes_strerror_messages[ec]; -} - -static size_t aes_format_error_strerror( - const AES_ErrorDetails* err_details,\ - char* dest, - size_t dest_size) -{ - const AES_StatusCode ec = aes_get_error_code(err_details); - const char* const msg = aes_strerror(ec); - - if (dest == NULL) - return strlen(msg) + 1; - - aes_fill_string(dest, dest_size, msg); - return strlen(dest); -} - -static size_t aes_format_null_argument_error( - const AES_ErrorDetails* err_details, - char* dest, - size_t dest_size) -{ - static const char* const fmt = "Invalid argument value NULL for parameter '%s'"; - const char* const param_name = err_details->params.null_arg.param_name; - - if (dest == NULL && dest_size == 0) - return snprintf(NULL, 0, fmt, param_name) + 1; - - snprintf(dest, dest_size, fmt, param_name); - return strlen(dest); -} - -static size_t aes_format_parse_error( - const AES_ErrorDetails* err_details, - char* dest, - size_t dest_size) -{ - static const char* const fmt = "Couldn't parse '%s' (possibly not complete input) as %s"; - const char* const src = err_details->params.parse_error.src; - const char* const what = err_details->params.parse_error.what; - - if (dest == NULL) - return snprintf(NULL, 0, fmt, src, what) + 1; - - snprintf(dest, dest_size, fmt, src, what); - return strlen(dest); -} - -static size_t aes_format_not_implemented_error( - const AES_ErrorDetails* err_details, - char* dest, - size_t dest_size) -{ - static const char* const fmt = "Not implemented: %s"; - const char* const src = err_details->params.not_implemented.what; - - if (dest == NULL) - return snprintf(NULL, 0, fmt, src) + 1; - - snprintf(dest, dest_size, fmt, src); - return strlen(dest); -} - -typedef size_t (*AES_ErrorFormatter)(const AES_ErrorDetails*, char*, size_t); - -static AES_ErrorFormatter err_formatters[] = -{ - &aes_format_error_strerror, - &aes_format_null_argument_error, - &aes_format_parse_error, - &aes_format_error_strerror, - &aes_format_not_implemented_error, - &aes_format_error_strerror, - &aes_format_error_strerror, -}; - -size_t aes_format_error( - const AES_ErrorDetails* err_details, - char* dest, - size_t dest_size) -{ - assert(err_details); - - return err_formatters[err_details->ec](err_details, dest, dest_size); -} - -#ifdef WIN32 -#include - -static void aes_collect_call_stack(AES_ErrorDetails* err_details) -{ - err_details->call_stack_len = CaptureStackBackTrace( - 1, AES_MAX_CALL_STACK_LENGTH, err_details->call_stack, NULL); -} -#else -static void aes_collect_call_stack(AES_ErrorDetails* err_details) -{ - err_details->call_stack_len = 0; -} -#endif - -static AES_StatusCode aes_make_error( - AES_ErrorDetails* err_details, - AES_StatusCode ec) -{ - if (err_details == NULL) - return ec; - - if (aes_is_error(ec)) - aes_collect_call_stack(err_details); - - return err_details->ec = ec; -} - -AES_StatusCode aes_success( - AES_ErrorDetails* err_details) -{ - return aes_make_error(err_details, AES_SUCCESS); -} - -AES_StatusCode aes_error_null_argument( - AES_ErrorDetails* err_details, - const char* param_name) -{ - AES_StatusCode status = aes_make_error(err_details, AES_NULL_ARGUMENT_ERROR); - - if (err_details != NULL) - aes_fill_string( - err_details->params.null_arg.param_name, - sizeof(err_details->params.null_arg.param_name), param_name); - - return status; -} - -AES_StatusCode aes_error_parse( - AES_ErrorDetails* err_details, - const char* src, - const char* what) -{ - AES_StatusCode status = aes_make_error(err_details, AES_PARSE_ERROR); - - if (err_details != NULL) - { - aes_fill_string( - err_details->params.parse_error.src, - sizeof(err_details->params.parse_error.src), src); - aes_fill_string( - err_details->params.parse_error.what, - sizeof(err_details->params.parse_error.what), what); - } - - return status; -} - -AES_StatusCode aes_error_invalid_pkcs7_padding( - AES_ErrorDetails* err_details) -{ - return aes_make_error(err_details, AES_INVALID_PKCS7_PADDING_ERROR); -} - -AES_StatusCode aes_error_not_implemented( - AES_ErrorDetails* err_details, - const char* what) -{ - AES_StatusCode status = aes_make_error(err_details, AES_NOT_IMPLEMENTED_ERROR); - - if (err_details != NULL) - aes_fill_string( - err_details->params.not_implemented.what, - sizeof(err_details->params.not_implemented.what), what); - - return status; -} - -AES_StatusCode aes_error_missing_padding( - AES_ErrorDetails* err_details) -{ - return aes_make_error(err_details, AES_MISSING_PADDING_ERROR); -} - -AES_StatusCode aes_error_memory_allocation( - AES_ErrorDetails* err_details) -{ - return aes_make_error(err_details, AES_MEMORY_ALLOCATION_ERROR); -} diff --git a/src/padding.c b/src/padding.c deleted file mode 100644 index a161ec7..0000000 --- a/src/padding.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2015 Egor Tensin - * This file is part of the "AES tools" project. - * For details, see https://github.com/egor-tensin/aes-tools. - * Distributed under the MIT License. - */ - -#include - -#include -#include -#include - -static AES_StatusCode aes_extract_padding_size_pkcs7( - const void* src, - size_t src_size, - size_t* padding_size, - AES_ErrorDetails* err_details) -{ - const unsigned char* cursor = (const unsigned char*) src + src_size - 1; - *padding_size = *cursor; - - for (size_t i = 1; i < *padding_size; ++i) - if (cursor[0 - i] != *padding_size) - return aes_error_invalid_pkcs7_padding(err_details); - - return AES_SUCCESS; -} - -AES_StatusCode aes_extract_padding_size( - AES_PaddingMethod method, - const void* src, - size_t src_size, - size_t* padding_size, - AES_ErrorDetails* err_details) -{ - assert(src); - assert(padding_size); - - if (src == NULL) - return aes_error_null_argument(err_details, "src"); - if (padding_size == NULL) - return aes_error_null_argument(err_details, "padding_size"); - - switch (method) - { - case AES_PADDING_PKCS7: - return aes_extract_padding_size_pkcs7( - src, src_size, padding_size, err_details); - - default: - return aes_error_not_implemented( - err_details, "unsupported padding method"); - } -} - -static AES_StatusCode aes_fill_with_padding_pkcs7( - void* dest, - size_t padding_size, - AES_ErrorDetails* err_details) -{ - AES_UNUSED_PARAMETER(err_details); - memset(dest, (int) padding_size, padding_size); - return AES_SUCCESS; -} - -AES_StatusCode aes_fill_with_padding( - AES_PaddingMethod method, - void* dest, - size_t padding_size, - AES_ErrorDetails* err_details) -{ - assert(dest); - - if (dest == NULL) - return aes_error_null_argument(err_details, "dest"); - - switch (method) - { - case AES_PADDING_PKCS7: - return aes_fill_with_padding_pkcs7( - dest, padding_size, err_details); - - default: - return aes_error_not_implemented( - err_details, "unsupported padding method"); - } -} -- cgit v1.2.3