From 4720b5ac21163936fb47f524037a6f12ce6e6ce2 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Wed, 22 Jul 2026 18:31:50 +0200 Subject: rewrite: the beginning This a giant fuck-you to myself while I have nothing (actually, tons of things) to do in a hospital. * The giant screens of preprocessor code are gone, they always sucked, fuck them. * Switched everything to the "boxes" interface as the only one remaining. * Restuctured things in aes/ so that the files they're in make at least a little bit of sense. * Removed a bunch of cruft and prematurely generic code. * This is half-baked at best: I just made sure that the tests pass. A lot of cleanup awaits. --- aes/include/aes/aes.h | 245 +++------------------- aes/include/aes/algorithm.h | 70 +++++++ aes/include/aes/all.h | 6 +- aes/include/aes/block.h | 66 ++++++ aes/include/aes/box.h | 42 ++-- aes/include/aes/box_aes.h | 20 -- aes/include/aes/box_data.h | 95 --------- aes/include/aes/data.h | 60 ------ aes/include/aes/error.h | 3 + aes/include/aes/key.h | 80 +++++++ aes/include/aes/mode.h | 146 +------------ aes/include/aes/round_keys.h | 111 ++++++++++ aes/src/aes.c | 347 ------------------------------- aes/src/algorithm.c | 264 +++++++++++++++++++++++ aes/src/asm/aes128.asm | 16 +- aes/src/asm/aes192.asm | 16 +- aes/src/asm/aes256.asm | 16 +- aes/src/block.c | 104 +++++++++ aes/src/box.c | 49 +---- aes/src/box_aes.c | 219 ------------------- aes/src/c/aes128.c | 8 +- aes/src/c/aes192.c | 8 +- aes/src/c/aes256.c | 8 +- aes/src/error.c | 4 + aes/src/key.c | 200 ++++++++++++++++++ aesxx/include/aesxx/aes.hpp | 230 -------------------- aesxx/include/aesxx/all.hpp | 2 - aesxx/include/aesxx/api.hpp | 136 ------------ aesxx/include/aesxx/box.hpp | 71 +++---- aesxx/include/aesxx/data.hpp | 58 ++++-- aesxx/include/aesxx/mode.hpp | 120 ----------- aesxx/utils/README.md | 2 - aesxx/utils/decrypt_block.cpp | 133 +----------- aesxx/utils/decrypt_bmp.cpp | 12 +- aesxx/utils/decrypt_file.cpp | 12 +- aesxx/utils/encrypt_block.cpp | 136 +----------- aesxx/utils/encrypt_bmp.cpp | 12 +- aesxx/utils/encrypt_file.cpp | 12 +- aesxx/utils/helpers/block_dumper.hpp | 85 -------- aesxx/utils/helpers/cmd_parser_block.hpp | 53 ++--- aesxx/utils/helpers/cmd_parser_file.hpp | 22 +- aesxx/utils/helpers/data_parsers.hpp | 10 + test/CMakeLists.txt | 22 -- test/cavp.py | 33 +-- test/nist.py | 25 +-- test/toolkit.py | 19 +- 46 files changed, 1143 insertions(+), 2265 deletions(-) create mode 100644 aes/include/aes/block.h delete mode 100644 aes/include/aes/box_aes.h delete mode 100644 aes/include/aes/box_data.h delete mode 100644 aes/include/aes/data.h create mode 100644 aes/include/aes/key.h create mode 100644 aes/include/aes/round_keys.h delete mode 100644 aes/src/aes.c create mode 100644 aes/src/algorithm.c create mode 100644 aes/src/block.c delete mode 100644 aes/src/box_aes.c create mode 100644 aes/src/key.c delete mode 100644 aesxx/include/aesxx/aes.hpp delete mode 100644 aesxx/include/aesxx/api.hpp delete mode 100644 aesxx/utils/helpers/block_dumper.hpp diff --git a/aes/include/aes/aes.h b/aes/include/aes/aes.h index 80f2b6f..01ab441 100644 --- a/aes/include/aes/aes.h +++ b/aes/include/aes/aes.h @@ -5,9 +5,8 @@ #pragma once -#include "data.h" -#include "error.h" -#include "mode.h" +#include "block.h" +#include "round_keys.h" #include @@ -15,234 +14,42 @@ extern "C" { #endif -typedef struct { - AES_Block key; -} AES128_Key; +AES_Block __fastcall aes128_encrypt_block_internal(AES_Block, const AES128_RoundKeys*); +AES_Block __fastcall aes192_encrypt_block_internal(AES_Block, const AES192_RoundKeys*); +AES_Block __fastcall aes256_encrypt_block_internal(AES_Block, const AES256_RoundKeys*); -typedef struct { - AES_Block hi; - AES_Block lo; -} AES192_Key; +AES_Block __fastcall aes128_decrypt_block_internal(AES_Block, const AES128_RoundKeys*); +AES_Block __fastcall aes192_decrypt_block_internal(AES_Block, const AES192_RoundKeys*); +AES_Block __fastcall aes256_decrypt_block_internal(AES_Block, const AES256_RoundKeys*); -typedef struct { - AES_Block hi; - AES_Block lo; -} AES256_Key; - -static inline AES128_Key aes128_make_key(int hi3, int hi2, int lo1, int lo0) { - AES128_Key key; - key.key = aes_make_block(hi3, hi2, lo1, lo0); - return key; -} - -static inline AES192_Key aes192_make_key(int hi5, int hi4, int lo3, int lo2, int lo1, int lo0) { - AES192_Key key; - key.hi = aes_make_block(0, 0, hi5, hi4); - key.lo = aes_make_block(lo3, lo2, lo1, lo0); - return key; -} - -static inline AES256_Key aes256_make_key( - int hi7, - int hi6, - int hi5, - int hi4, - int lo3, - int lo2, - int lo1, - int lo0 -) { - AES256_Key key; - key.hi = aes_make_block(hi7, hi6, hi5, hi4); - key.lo = aes_make_block(lo3, lo2, lo1, lo0); - return key; -} - -typedef struct { - char str[33]; -} AES_BlockString; - -typedef struct { - char str[49]; -} AES_BlockMatrixString; - -AES_StatusCode aes_format_block(AES_BlockString*, const AES_Block*, AES_ErrorDetails*); - -AES_StatusCode aes_format_block_as_matrix( - AES_BlockMatrixString*, - const AES_Block*, - AES_ErrorDetails* -); - -AES_StatusCode aes_print_block(const AES_Block*, AES_ErrorDetails*); - -AES_StatusCode aes_print_block_as_matrix(const AES_Block*, AES_ErrorDetails*); - -AES_StatusCode aes_parse_block(AES_Block* dest, const char* src, AES_ErrorDetails* err_details); - -typedef struct { - char str[33]; -} AES128_KeyString; - -typedef struct { - char str[49]; -} AES192_KeyString; - -typedef struct { - char str[65]; -} AES256_KeyString; - -AES_StatusCode aes128_format_key(AES128_KeyString*, const AES128_Key*, AES_ErrorDetails*); -AES_StatusCode aes192_format_key(AES192_KeyString*, const AES192_Key*, AES_ErrorDetails*); -AES_StatusCode aes256_format_key(AES256_KeyString*, const AES256_Key*, AES_ErrorDetails*); - -AES_StatusCode aes128_print_key(const AES128_Key*, AES_ErrorDetails*); -AES_StatusCode aes192_print_key(const AES192_Key*, AES_ErrorDetails*); -AES_StatusCode aes256_print_key(const AES256_Key*, AES_ErrorDetails*); - -AES_StatusCode aes128_parse_key(AES128_Key* dest, const char* src, AES_ErrorDetails* err_details); -AES_StatusCode aes192_parse_key(AES192_Key* dest, const char* src, AES_ErrorDetails* err_details); -AES_StatusCode aes256_parse_key(AES256_Key* dest, const char* src, AES_ErrorDetails* err_details); - -typedef struct { - AES_Block keys[11]; -} AES128_RoundKeys; - -typedef struct { - AES_Block keys[13]; -} AES192_RoundKeys; - -typedef struct { - AES_Block keys[15]; -} AES256_RoundKeys; - -void __fastcall aes128_expand_key_(AES_Block key, AES128_RoundKeys* encryption_keys); - -void __fastcall aes192_expand_key_( - AES_Block key_lo, - AES_Block key_hi, - AES192_RoundKeys* encryption_keys -); - -void __fastcall aes256_expand_key_( - AES_Block key_lo, - AES_Block key_hi, - AES256_RoundKeys* encryption_keys -); - -void __fastcall aes128_derive_decryption_keys_( - const AES128_RoundKeys* encryption_keys, - AES128_RoundKeys* decryption_keys -); - -void __fastcall aes192_derive_decryption_keys_( - const AES192_RoundKeys* encryption_keys, - AES192_RoundKeys* decryption_keys -); - -void __fastcall aes256_derive_decryption_keys_( - const AES256_RoundKeys* encryption_keys, - AES256_RoundKeys* decryption_keys -); - -AES_Block __fastcall aes128_encrypt_block_(AES_Block plaintext, const AES128_RoundKeys*); -AES_Block __fastcall aes192_encrypt_block_(AES_Block plaintext, const AES192_RoundKeys*); -AES_Block __fastcall aes256_encrypt_block_(AES_Block plaintext, const AES256_RoundKeys*); - -AES_Block __fastcall aes128_decrypt_block_(AES_Block ciphertext, const AES128_RoundKeys*); -AES_Block __fastcall aes192_decrypt_block_(AES_Block ciphertext, const AES192_RoundKeys*); -AES_Block __fastcall aes256_decrypt_block_(AES_Block ciphertext, const AES256_RoundKeys*); - -AES_ENCRYPT_BLOCK_ECB(128) -AES_DECRYPT_BLOCK_ECB(128) -AES_ENCRYPT_BLOCK_CBC(128) -AES_DECRYPT_BLOCK_CBC(128) -AES_ENCRYPT_BLOCK_CFB(128) -AES_DECRYPT_BLOCK_CFB(128) -AES_ENCRYPT_BLOCK_OFB(128) -AES_DECRYPT_BLOCK_OFB(128) -AES_ENCRYPT_BLOCK_CTR(128) -AES_DECRYPT_BLOCK_CTR(128) - -AES_ENCRYPT_BLOCK_ECB(192) -AES_DECRYPT_BLOCK_ECB(192) -AES_ENCRYPT_BLOCK_CBC(192) -AES_DECRYPT_BLOCK_CBC(192) -AES_ENCRYPT_BLOCK_CFB(192) -AES_DECRYPT_BLOCK_CFB(192) -AES_ENCRYPT_BLOCK_OFB(192) -AES_DECRYPT_BLOCK_OFB(192) -AES_ENCRYPT_BLOCK_CTR(192) -AES_DECRYPT_BLOCK_CTR(192) - -AES_ENCRYPT_BLOCK_ECB(256) -AES_DECRYPT_BLOCK_ECB(256) -AES_ENCRYPT_BLOCK_CBC(256) -AES_DECRYPT_BLOCK_CBC(256) -AES_ENCRYPT_BLOCK_CFB(256) -AES_DECRYPT_BLOCK_CFB(256) -AES_ENCRYPT_BLOCK_OFB(256) -AES_DECRYPT_BLOCK_OFB(256) -AES_ENCRYPT_BLOCK_CTR(256) -AES_DECRYPT_BLOCK_CTR(256) - -static inline void __fastcall aes128_expand_key( - const AES128_Key* key, - AES128_RoundKeys* encryption_keys -) { - assert(encryption_keys); - - aes128_expand_key_(key->key, encryption_keys); +static inline AES_Block aes128_encrypt_block(AES_Block plaintext, const AES128_RoundKeys* keys) { + assert(keys); + return aes128_encrypt_block_internal(plaintext, keys); } -static inline void __fastcall aes128_derive_decryption_keys( - const AES128_RoundKeys* encryption_keys, - AES128_RoundKeys* decryption_keys -) { - assert(encryption_keys); - assert(decryption_keys); - - aes128_derive_decryption_keys_(encryption_keys, decryption_keys); +static inline AES_Block aes192_encrypt_block(AES_Block plaintext, const AES192_RoundKeys* keys) { + assert(keys); + return aes192_encrypt_block_internal(plaintext, keys); } -static inline void __fastcall aes192_expand_key( - const AES192_Key* key, - AES192_RoundKeys* encryption_keys -) { - assert(key); - assert(encryption_keys); - - aes192_expand_key_(key->lo, key->hi, encryption_keys); +static inline AES_Block aes256_encrypt_block(AES_Block plaintext, const AES256_RoundKeys* keys) { + assert(keys); + return aes256_encrypt_block_internal(plaintext, keys); } -static inline void __fastcall aes192_derive_decryption_keys( - const AES192_RoundKeys* encryption_keys, - AES192_RoundKeys* decryption_keys -) { - assert(encryption_keys); - assert(decryption_keys); - - aes192_derive_decryption_keys_(encryption_keys, decryption_keys); +static inline AES_Block aes128_decrypt_block(AES_Block ciphertext, const AES128_RoundKeys* keys) { + assert(keys); + return aes128_decrypt_block_internal(ciphertext, keys); } -static inline void __fastcall aes256_expand_key( - const AES256_Key* key, - AES256_RoundKeys* encryption_keys -) { - assert(key); - assert(encryption_keys); - - aes256_expand_key_(key->lo, key->hi, encryption_keys); +static inline AES_Block aes192_decrypt_block(AES_Block ciphertext, const AES192_RoundKeys* keys) { + assert(keys); + return aes192_decrypt_block_internal(ciphertext, keys); } -static inline void __fastcall aes256_derive_decryption_keys( - const AES256_RoundKeys* encryption_keys, - AES256_RoundKeys* decryption_keys -) { - assert(encryption_keys); - assert(decryption_keys); - - aes256_derive_decryption_keys_(encryption_keys, decryption_keys); +static inline AES_Block aes256_decrypt_block(AES_Block ciphertext, const AES256_RoundKeys* keys) { + assert(keys); + return aes256_decrypt_block_internal(ciphertext, keys); } #ifdef __cplusplus diff --git a/aes/include/aes/algorithm.h b/aes/include/aes/algorithm.h index e17a75a..2e283fd 100644 --- a/aes/include/aes/algorithm.h +++ b/aes/include/aes/algorithm.h @@ -15,6 +15,76 @@ typedef enum { AES_AES256, } AES_Algorithm; +typedef union { + AES128_Key aes128_key; + AES192_Key aes192_key; + AES256_Key aes256_key; +} AES_Key; + +typedef union { + AES128_KeyString aes128; + AES192_KeyString aes192; + AES256_KeyString aes256; +} AES_KeyString; + +typedef union { + AES128_RoundKeys aes128_enc_keys; + AES192_RoundKeys aes192_enc_keys; + AES256_RoundKeys aes256_enc_keys; +} AES_EncryptionRoundKeys; + +typedef union { + AES128_RoundKeys aes128_dec_keys; + AES192_RoundKeys aes192_dec_keys; + AES256_RoundKeys aes256_dec_keys; +} AES_DecryptionRoundKeys; + +typedef AES_StatusCode (*AES_ParseKey)( + AES_Key* dest, + const char* src, + AES_ErrorDetails* err_details +); + +typedef AES_StatusCode (*AES_FormatKey)( + AES_KeyString* dest, + const AES_Key* src, + AES_ErrorDetails* err_details +); + +typedef AES_StatusCode (*AES_ExpandKey)( + const AES_Key* params, + AES_EncryptionRoundKeys*, + AES_DecryptionRoundKeys*, + AES_ErrorDetails* err_details +); + +typedef AES_StatusCode (*AES_EncryptBlock)( + const AES_Block* plaintext, + const AES_EncryptionRoundKeys* params, + AES_Block* ciphertext, + AES_ErrorDetails* err_details +); + +typedef AES_StatusCode (*AES_DecryptBlock)( + const AES_Block* ciphertext, + const AES_DecryptionRoundKeys* params, + AES_Block* plaintext, + AES_ErrorDetails* err_details +); + +typedef struct { + AES_ParseKey parse_key; + AES_FormatKey format_key; + AES_ExpandKey expand_key; + AES_EncryptBlock encrypt_block; + AES_DecryptBlock decrypt_block; +} AES_Ops; + +const AES_Ops* aes_get_ops(AES_Algorithm); + +AES_StatusCode aes_parse_key(AES_Algorithm, AES_Key*, const char*, AES_ErrorDetails*); +AES_StatusCode aes_format_key(AES_Algorithm, AES_KeyString*, const AES_Key*, AES_ErrorDetails*); + #ifdef __cplusplus } #endif diff --git a/aes/include/aes/all.h b/aes/include/aes/all.h index 8b60483..fb0a191 100644 --- a/aes/include/aes/all.h +++ b/aes/include/aes/all.h @@ -7,11 +7,11 @@ #include "aes.h" #include "algorithm.h" +#include "block.h" #include "box.h" -#include "box_aes.h" -#include "box_data.h" -#include "data.h" #include "error.h" +#include "key.h" #include "mode.h" #include "padding.h" +#include "round_keys.h" #include "workarounds.h" diff --git a/aes/include/aes/block.h b/aes/include/aes/block.h new file mode 100644 index 0000000..a41f79c --- /dev/null +++ b/aes/include/aes/block.h @@ -0,0 +1,66 @@ +// 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 +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef __m128i AES_Block; + +/* hi3 - the most significant 4-byte value, lo0 - the least. */ +static inline AES_Block aes_make_block(int hi3, int hi2, int lo1, int lo0) { + return _mm_set_epi32(hi3, hi2, lo1, lo0); +} + +static inline AES_Block aes_load_block(const void* src) { + return _mm_loadu_si128((AES_Block*)src); +} + +static inline AES_Block aes_load_block_aligned(const void* src) { + return _mm_load_si128((AES_Block*)src); +} + +static inline void aes_store_block(void* dest, AES_Block block) { + _mm_storeu_si128((AES_Block*)dest, block); +} + +static inline void aes_store_block_aligned(void* dest, AES_Block block) { + _mm_store_si128((AES_Block*)dest, block); +} + +static inline AES_Block aes_xor_blocks(AES_Block a, AES_Block b) { + return _mm_xor_si128(a, b); +} + +AES_Block aes_inc_block(AES_Block x); + +typedef struct { + char str[33]; +} AES_BlockString; + +typedef struct { + char str[49]; +} AES_BlockMatrixString; + +AES_StatusCode aes_format_block(AES_BlockString*, const AES_Block*, AES_ErrorDetails*); + +AES_StatusCode aes_format_block_as_matrix( + AES_BlockMatrixString*, + const AES_Block*, + AES_ErrorDetails* +); + +AES_StatusCode aes_parse_block(AES_Block* dest, const char* src, AES_ErrorDetails* err_details); + +#ifdef __cplusplus +} +#endif diff --git a/aes/include/aes/box.h b/aes/include/aes/box.h index 37292dd..3347edd 100644 --- a/aes/include/aes/box.h +++ b/aes/include/aes/box.h @@ -6,8 +6,9 @@ #pragma once #include "algorithm.h" -#include "box_data.h" +#include "block.h" #include "error.h" +#include "mode.h" #include @@ -15,43 +16,24 @@ extern "C" { #endif +typedef struct { + AES_Algorithm algorithm; + AES_Mode mode; + AES_Block iv; + AES_EncryptionRoundKeys encryption_keys; + AES_DecryptionRoundKeys decryption_keys; + const AES_Ops* ops; +} AES_Box; + AES_StatusCode aes_box_init( AES_Box* box, AES_Algorithm algorithm, - const AES_BoxKey* box_key, + const AES_Key* box_key, AES_Mode mode, const AES_Block* 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_Block* 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_BlockString* dest, - AES_Algorithm algorithm, - const AES_Block* src, - AES_ErrorDetails* err_details -); - AES_StatusCode aes_box_encrypt_block( AES_Box* box, const AES_Block* plaintext, diff --git a/aes/include/aes/box_aes.h b/aes/include/aes/box_aes.h deleted file mode 100644 index c9b9b67..0000000 --- a/aes/include/aes/box_aes.h +++ /dev/null @@ -1,20 +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_BoxOps aes128_box_ops; -extern AES_BoxOps aes192_box_ops; -extern AES_BoxOps aes256_box_ops; - -#ifdef __cplusplus -} -#endif diff --git a/aes/include/aes/box_data.h b/aes/include/aes/box_data.h deleted file mode 100644 index 3e49fa0..0000000 --- a/aes/include/aes/box_data.h +++ /dev/null @@ -1,95 +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 "algorithm.h" -#include "error.h" -#include "mode.h" - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef union { - AES128_Key aes128_key; - AES192_Key aes192_key; - AES256_Key aes256_key; -} AES_BoxKey; - -typedef union { - AES128_RoundKeys aes128_encryption_keys; - AES192_RoundKeys aes192_encryption_keys; - AES256_RoundKeys aes256_encryption_keys; -} AES_BoxEncryptionRoundKeys; - -typedef union { - AES128_RoundKeys aes128_decryption_keys; - AES192_RoundKeys aes192_decryption_keys; - AES256_RoundKeys aes256_decryption_keys; -} AES_BoxDecryptionRoundKeys; - -typedef union { - AES128_KeyString aes128; - AES192_KeyString aes192; - AES256_KeyString aes256; -} AES_BoxKeyString; - -typedef AES_StatusCode (*AES_BoxCalculateRoundKeys)( - const AES_BoxKey* params, - AES_BoxEncryptionRoundKeys*, - AES_BoxDecryptionRoundKeys*, - AES_ErrorDetails* err_details -); - -typedef AES_StatusCode (*AES_BoxParseKey)( - AES_BoxKey* dest, - const char* 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_Block* plaintext, - const AES_BoxEncryptionRoundKeys* params, - AES_Block* ciphertext, - AES_ErrorDetails* err_details -); - -typedef AES_StatusCode (*AES_BoxDecryptBlock)( - const AES_Block* ciphertext, - const AES_BoxDecryptionRoundKeys* params, - AES_Block* plaintext, - AES_ErrorDetails* err_details -); - -typedef struct { - AES_BoxCalculateRoundKeys calc_round_keys; - AES_BoxParseKey parse_key; - AES_BoxFormatKey format_key; - AES_BoxEncryptBlock encrypt_block; - AES_BoxDecryptBlock decrypt_block; -} AES_BoxOps; - -typedef struct { - AES_Algorithm algorithm; - AES_Mode mode; - AES_Block iv; - AES_BoxEncryptionRoundKeys encryption_keys; - AES_BoxDecryptionRoundKeys decryption_keys; - const AES_BoxOps* ops; -} AES_Box; - -#ifdef __cplusplus -} -#endif diff --git a/aes/include/aes/data.h b/aes/include/aes/data.h deleted file mode 100644 index e06ec33..0000000 --- a/aes/include/aes/data.h +++ /dev/null @@ -1,60 +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 - -typedef __m128i AES_Block; - -static inline AES_Block aes_load_block(const void* src) { - return _mm_loadu_si128((AES_Block*)src); -} - -static inline AES_Block aes_load_block_aligned(const void* src) { - return _mm_load_si128((AES_Block*)src); -} - -static inline void __fastcall aes_store_block(void* dest, AES_Block block) { - _mm_storeu_si128((AES_Block*)dest, block); -} - -static inline void __fastcall aes_store_block_aligned(void* dest, AES_Block block) { - _mm_store_si128((AES_Block*)dest, block); -} - -static inline AES_Block __fastcall aes_xor_blocks(AES_Block a, AES_Block b) { - return _mm_xor_si128(a, b); -} - -/** - * hi3 - The most significant 4-byte value. - * hi2 - The more significant 4-byte value. - * lo1 - The less significant 4-byte value. - * lo0 - The least significant 4-byte value. - */ -static inline AES_Block __fastcall aes_make_block(int hi3, int hi2, int lo1, int lo0) { - return _mm_set_epi32(hi3, hi2, lo1, lo0); -} - -static inline AES_Block __fastcall aes_reverse_byte_order_in_block(AES_Block block) { - return _mm_shuffle_epi8(block, aes_make_block(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f)); -} - -static inline AES_Block __fastcall aes_inc_block(AES_Block x) { - x = aes_reverse_byte_order_in_block(x); - x = _mm_add_epi32(x, aes_make_block(0, 0, 0, 1)); - x = aes_reverse_byte_order_in_block(x); - return x; -} - -#ifdef __cplusplus -} -#endif diff --git a/aes/include/aes/error.h b/aes/include/aes/error.h index d3822de..c32d1b7 100644 --- a/aes/include/aes/error.h +++ b/aes/include/aes/error.h @@ -19,6 +19,7 @@ typedef enum { AES_NOT_IMPLEMENTED_ERROR, AES_MISSING_PADDING_ERROR, AES_MEMORY_ALLOCATION_ERROR, + AES_MODE_REQUIRES_INIT_VECTOR_ERROR, } AES_StatusCode; static inline int aes_is_error(AES_StatusCode ec) { @@ -69,6 +70,8 @@ AES_StatusCode aes_error_missing_padding(AES_ErrorDetails* err_details); AES_StatusCode aes_error_memory_allocation(AES_ErrorDetails* err_details); +AES_StatusCode aes_error_mode_requires_init_vector(AES_ErrorDetails* err_details); + #ifdef __cplusplus } #endif diff --git a/aes/include/aes/key.h b/aes/include/aes/key.h new file mode 100644 index 0000000..95fe8e5 --- /dev/null +++ b/aes/include/aes/key.h @@ -0,0 +1,80 @@ +// Copyright (c) 2026 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 "block.h" +#include "error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + AES_Block key; +} AES128_Key; + +typedef struct { + AES_Block hi; + AES_Block lo; +} AES192_Key; + +typedef struct { + AES_Block hi; + AES_Block lo; +} AES256_Key; + +static inline AES128_Key aes128_make_key(int hi3, int hi2, int lo1, int lo0) { + AES128_Key key; + key.key = aes_make_block(hi3, hi2, lo1, lo0); + return key; +} + +static inline AES192_Key aes192_make_key(int hi5, int hi4, int lo3, int lo2, int lo1, int lo0) { + AES192_Key key; + key.hi = aes_make_block(0, 0, hi5, hi4); + key.lo = aes_make_block(lo3, lo2, lo1, lo0); + return key; +} + +static inline AES256_Key aes256_make_key( + int hi7, + int hi6, + int hi5, + int hi4, + int lo3, + int lo2, + int lo1, + int lo0 +) { + AES256_Key key; + key.hi = aes_make_block(hi7, hi6, hi5, hi4); + key.lo = aes_make_block(lo3, lo2, lo1, lo0); + return key; +} + +typedef struct { + char str[33]; +} AES128_KeyString; + +typedef struct { + char str[49]; +} AES192_KeyString; + +typedef struct { + char str[65]; +} AES256_KeyString; + +AES_StatusCode aes128_format_key(AES128_KeyString*, const AES128_Key*, AES_ErrorDetails*); +AES_StatusCode aes192_format_key(AES192_KeyString*, const AES192_Key*, AES_ErrorDetails*); +AES_StatusCode aes256_format_key(AES256_KeyString*, const AES256_Key*, AES_ErrorDetails*); + +AES_StatusCode aes128_parse_key(AES128_Key* dest, const char* src, AES_ErrorDetails* err_details); +AES_StatusCode aes192_parse_key(AES192_Key* dest, const char* src, AES_ErrorDetails* err_details); +AES_StatusCode aes256_parse_key(AES256_Key* dest, const char* src, AES_ErrorDetails* err_details); + +#ifdef __cplusplus +} +#endif diff --git a/aes/include/aes/mode.h b/aes/include/aes/mode.h index 656388f..57dfb50 100644 --- a/aes/include/aes/mode.h +++ b/aes/include/aes/mode.h @@ -19,149 +19,9 @@ typedef enum { AES_CTR, } AES_Mode; -#define AES_ENCRYPT_BLOCK_ECB(version) \ - static inline AES_Block __fastcall aes##version##_encrypt_block_ECB( \ - AES_Block plaintext, const AES##version##_RoundKeys* encryption_keys \ - ) { \ - assert(encryption_keys); \ - \ - return aes##version##_encrypt_block_(plaintext, encryption_keys); \ - } - -#define AES_DECRYPT_BLOCK_ECB(version) \ - static inline AES_Block __fastcall aes##version##_decrypt_block_ECB( \ - AES_Block ciphertext, const AES##version##_RoundKeys* decryption_keys \ - ) { \ - assert(decryption_keys); \ - \ - return aes##version##_decrypt_block_(ciphertext, decryption_keys); \ - } - -#define AES_ENCRYPT_BLOCK_CBC(version) \ - static inline AES_Block __fastcall aes##version##_encrypt_block_CBC( \ - AES_Block plaintext, \ - const AES##version##_RoundKeys* encryption_keys, \ - AES_Block init_vector, \ - AES_Block* next_init_vector \ - ) { \ - assert(encryption_keys); \ - assert(next_init_vector); \ - \ - return *next_init_vector = aes##version##_encrypt_block_( \ - aes_xor_blocks(plaintext, init_vector), encryption_keys \ - ); \ - } - -#define AES_DECRYPT_BLOCK_CBC(version) \ - static inline AES_Block __fastcall aes##version##_decrypt_block_CBC( \ - AES_Block ciphertext, \ - const AES##version##_RoundKeys* decryption_keys, \ - AES_Block init_vector, \ - AES_Block* next_init_vector \ - ) { \ - assert(decryption_keys); \ - assert(next_init_vector); \ - \ - AES_Block plaintext = aes_xor_blocks( \ - aes##version##_decrypt_block_(ciphertext, decryption_keys), init_vector \ - ); \ - *next_init_vector = ciphertext; \ - return plaintext; \ - } - -#define AES_ENCRYPT_BLOCK_CFB(version) \ - static inline AES_Block __fastcall aes##version##_encrypt_block_CFB( \ - AES_Block plaintext, \ - const AES##version##_RoundKeys* encryption_keys, \ - AES_Block init_vector, \ - AES_Block* next_init_vector \ - ) { \ - assert(encryption_keys); \ - assert(next_init_vector); \ - \ - return *next_init_vector = aes_xor_blocks( \ - aes##version##_encrypt_block_(init_vector, encryption_keys), plaintext \ - ); \ - } - -#define AES_DECRYPT_BLOCK_CFB(version) \ - static inline AES_Block __fastcall aes##version##_decrypt_block_CFB( \ - AES_Block ciphertext, \ - const AES##version##_RoundKeys* encryption_keys, \ - AES_Block init_vector, \ - AES_Block* next_init_vector \ - ) { \ - assert(encryption_keys); \ - assert(next_init_vector); \ - \ - AES_Block plaintext = aes_xor_blocks( \ - aes##version##_encrypt_block_(init_vector, encryption_keys), ciphertext \ - ); \ - *next_init_vector = ciphertext; \ - return plaintext; \ - } - -#define AES_ENCRYPT_BLOCK_OFB(version) \ - static inline AES_Block __fastcall aes##version##_encrypt_block_OFB( \ - AES_Block plaintext, \ - const AES##version##_RoundKeys* encryption_keys, \ - AES_Block init_vector, \ - AES_Block* next_init_vector \ - ) { \ - assert(encryption_keys); \ - assert(next_init_vector); \ - \ - AES_Block tmp = aes##version##_encrypt_block_(init_vector, encryption_keys); \ - *next_init_vector = tmp; \ - return aes_xor_blocks(tmp, plaintext); \ - } - -#define AES_DECRYPT_BLOCK_OFB(version) \ - static inline AES_Block __fastcall aes##version##_decrypt_block_OFB( \ - AES_Block ciphertext, \ - const AES##version##_RoundKeys* encryption_keys, \ - AES_Block init_vector, \ - AES_Block* next_init_vector \ - ) { \ - assert(encryption_keys); \ - assert(next_init_vector); \ - \ - return aes##version##_encrypt_block_OFB( \ - ciphertext, encryption_keys, init_vector, next_init_vector \ - ); \ - } - -#define AES_ENCRYPT_BLOCK_CTR(version) \ - static inline AES_Block __fastcall aes##version##_encrypt_block_CTR( \ - AES_Block plaintext, \ - const AES##version##_RoundKeys* encryption_keys, \ - AES_Block init_vector, \ - AES_Block* next_init_vector \ - ) { \ - assert(encryption_keys); \ - assert(next_init_vector); \ - \ - AES_Block ciphertext = aes_xor_blocks( \ - plaintext, aes##version##_encrypt_block_(init_vector, encryption_keys) \ - ); \ - *next_init_vector = aes_inc_block(init_vector); \ - return ciphertext; \ - } - -#define AES_DECRYPT_BLOCK_CTR(version) \ - static inline AES_Block __fastcall aes##version##_decrypt_block_CTR( \ - AES_Block ciphertext, \ - const AES##version##_RoundKeys* encryption_keys, \ - AES_Block init_vector, \ - AES_Block* next_init_vector \ - ) { \ - assert(encryption_keys); \ - assert(next_init_vector); \ - \ - return aes##version##_encrypt_block_CTR( \ - ciphertext, encryption_keys, init_vector, next_init_vector \ - ); \ - } +static inline int aes_mode_requires_init_vector(AES_Mode mode) { + return mode != AES_ECB; +} #ifdef __cplusplus } diff --git a/aes/include/aes/round_keys.h b/aes/include/aes/round_keys.h new file mode 100644 index 0000000..f5814b6 --- /dev/null +++ b/aes/include/aes/round_keys.h @@ -0,0 +1,111 @@ +// 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 "block.h" +#include "error.h" +#include "key.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + AES_Block keys[11]; +} AES128_RoundKeys; + +typedef struct { + AES_Block keys[13]; +} AES192_RoundKeys; + +typedef struct { + AES_Block keys[15]; +} AES256_RoundKeys; + +void __fastcall aes128_expand_key_internal(AES_Block key, AES128_RoundKeys* encryption_keys); + +void __fastcall aes192_expand_key_internal( + AES_Block key_lo, + AES_Block key_hi, + AES192_RoundKeys* encryption_keys +); + +void __fastcall aes256_expand_key_internal( + AES_Block key_lo, + AES_Block key_hi, + AES256_RoundKeys* encryption_keys +); + +void __fastcall aes128_derive_decryption_keys_internal( + const AES128_RoundKeys* encryption_keys, + AES128_RoundKeys* decryption_keys +); + +void __fastcall aes192_derive_decryption_keys_internal( + const AES192_RoundKeys* encryption_keys, + AES192_RoundKeys* decryption_keys +); + +void __fastcall aes256_derive_decryption_keys_internal( + const AES256_RoundKeys* encryption_keys, + AES256_RoundKeys* decryption_keys +); + +static inline void aes128_expand_key(const AES128_Key* key, AES128_RoundKeys* encryption_keys) { + assert(encryption_keys); + + aes128_expand_key_internal(key->key, encryption_keys); +} + +static inline void aes128_derive_decryption_keys( + const AES128_RoundKeys* encryption_keys, + AES128_RoundKeys* decryption_keys +) { + assert(encryption_keys); + assert(decryption_keys); + + aes128_derive_decryption_keys_internal(encryption_keys, decryption_keys); +} + +static inline void aes192_expand_key(const AES192_Key* key, AES192_RoundKeys* encryption_keys) { + assert(key); + assert(encryption_keys); + + aes192_expand_key_internal(key->lo, key->hi, encryption_keys); +} + +static inline void aes192_derive_decryption_keys( + const AES192_RoundKeys* encryption_keys, + AES192_RoundKeys* decryption_keys +) { + assert(encryption_keys); + assert(decryption_keys); + + aes192_derive_decryption_keys_internal(encryption_keys, decryption_keys); +} + +static inline void aes256_expand_key(const AES256_Key* key, AES256_RoundKeys* encryption_keys) { + assert(key); + assert(encryption_keys); + + aes256_expand_key_internal(key->lo, key->hi, encryption_keys); +} + +static inline void aes256_derive_decryption_keys( + const AES256_RoundKeys* encryption_keys, + AES256_RoundKeys* decryption_keys +) { + assert(encryption_keys); + assert(decryption_keys); + + aes256_derive_decryption_keys_internal(encryption_keys, decryption_keys); +} + +#ifdef __cplusplus +} +#endif diff --git a/aes/src/aes.c b/aes/src/aes.c deleted file mode 100644 index 999bdf1..0000000 --- a/aes/src/aes.c +++ /dev/null @@ -1,347 +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_format_block( - AES_BlockString* str, - const 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_block_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_format_block_as_matrix( - AES_BlockMatrixString* str, - const 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_block_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_print_block(const 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_BlockString str; - - if (aes_is_error(ec = aes_format_block(&str, block, err_details))) - return ec; - - printf("%s\n", str.str); - return ec; -} - -AES_StatusCode aes_print_block_as_matrix(const 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_BlockMatrixString str; - - if (aes_is_error(ec = aes_format_block_as_matrix(&str, block, err_details))) - return ec; - - printf("%s", str.str); - return ec; -} - -AES_StatusCode aes_parse_block(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_block_aligned(bytes); - return AES_SUCCESS; -} - -AES_StatusCode aes128_format_key( - AES128_KeyString* str, - const 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_block_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 aes192_format_key( - AES192_KeyString* str, - const 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_block_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_block_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 aes256_format_key( - AES256_KeyString* str, - const 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_block_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_block_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 aes128_print_key(const AES128_Key* key, AES_ErrorDetails* err_details) { - return aes_print_block(&key->key, err_details); -} - -AES_StatusCode aes192_print_key(const 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; - AES192_KeyString str; - - if (aes_is_error(ec = aes192_format_key(&str, key, err_details))) - return ec; - - printf("%s\n", str.str); - return ec; -} - -AES_StatusCode aes256_print_key(const 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; - AES256_KeyString str; - - if (aes_is_error(ec = aes256_format_key(&str, key, err_details))) - return ec; - - printf("%s\n", str.str); - return ec; -} - -AES_StatusCode aes128_parse_key(AES128_Key* dest, const char* src, AES_ErrorDetails* err_details) { - return aes_parse_block(&dest->key, src, err_details); -} - -AES_StatusCode aes192_parse_key(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_block_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_block_aligned(bytes); - } - - return AES_SUCCESS; -} - -AES_StatusCode aes256_parse_key(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_block_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_block_aligned(bytes); - } - - return AES_SUCCESS; -} diff --git a/aes/src/algorithm.c b/aes/src/algorithm.c new file mode 100644 index 0000000..2c3e056 --- /dev/null +++ b/aes/src/algorithm.c @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2026 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 + +#ifdef __cplusplus +extern "C" { +#endif + +static AES_StatusCode aes_parse_key_aes128( + AES_Key* dest, + const char* src, + AES_ErrorDetails* err_details +) { + if (dest == NULL) + return aes_error_null_argument(err_details, "dest"); + + return aes128_parse_key(&dest->aes128_key, src, err_details); +} + +static AES_StatusCode aes_parse_key_aes192( + AES_Key* dest, + const char* src, + AES_ErrorDetails* err_details +) { + if (dest == NULL) + return aes_error_null_argument(err_details, "dest"); + + return aes192_parse_key(&dest->aes192_key, src, err_details); +} + +static AES_StatusCode aes_parse_key_aes256( + AES_Key* dest, + const char* src, + AES_ErrorDetails* err_details +) { + if (dest == NULL) + return aes_error_null_argument(err_details, "dest"); + + return aes256_parse_key(&dest->aes256_key, src, err_details); +} + +static AES_StatusCode aes_format_key_aes128( + AES_KeyString* dest, + const AES_Key* 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 aes128_format_key(&dest->aes128, &src->aes128_key, err_details); +} + +static AES_StatusCode aes_format_key_aes192( + AES_KeyString* dest, + const AES_Key* 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 aes192_format_key(&dest->aes192, &src->aes192_key, err_details); +} + +static AES_StatusCode aes_format_key_aes256( + AES_KeyString* dest, + const AES_Key* 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 aes256_format_key(&dest->aes256, &src->aes256_key, err_details); +} + +static AES_StatusCode aes_expand_key_aes128( + const AES_Key* key, + AES_EncryptionRoundKeys* encryption_keys, + AES_DecryptionRoundKeys* decryption_keys, + AES_ErrorDetails* err_details +) { + AES_UNUSED_PARAMETER(err_details); + aes128_expand_key(&key->aes128_key, &encryption_keys->aes128_enc_keys); + aes128_derive_decryption_keys( + &encryption_keys->aes128_enc_keys, &decryption_keys->aes128_dec_keys + ); + return AES_SUCCESS; +} + +static AES_StatusCode aes_expand_key_aes192( + const AES_Key* key, + AES_EncryptionRoundKeys* encryption_keys, + AES_DecryptionRoundKeys* decryption_keys, + AES_ErrorDetails* err_details +) { + AES_UNUSED_PARAMETER(err_details); + aes192_expand_key(&key->aes192_key, &encryption_keys->aes192_enc_keys); + aes192_derive_decryption_keys( + &encryption_keys->aes192_enc_keys, &decryption_keys->aes192_dec_keys + ); + return AES_SUCCESS; +} + +static AES_StatusCode aes_expand_key_aes256( + const AES_Key* key, + AES_EncryptionRoundKeys* encryption_keys, + AES_DecryptionRoundKeys* decryption_keys, + AES_ErrorDetails* err_details +) { + AES_UNUSED_PARAMETER(err_details); + aes256_expand_key(&key->aes256_key, &encryption_keys->aes256_enc_keys); + aes256_derive_decryption_keys( + &encryption_keys->aes256_enc_keys, &decryption_keys->aes256_dec_keys + ); + return AES_SUCCESS; +} + +static AES_StatusCode aes_encrypt_block_aes128( + const AES_Block* input, + const AES_EncryptionRoundKeys* params, + AES_Block* output, + AES_ErrorDetails* err_details +) { + AES_UNUSED_PARAMETER(err_details); + *output = aes128_encrypt_block(*input, ¶ms->aes128_enc_keys); + return AES_SUCCESS; +} + +static AES_StatusCode aes_decrypt_block_aes128( + const AES_Block* input, + const AES_DecryptionRoundKeys* params, + AES_Block* output, + AES_ErrorDetails* err_details +) { + AES_UNUSED_PARAMETER(err_details); + *output = aes128_decrypt_block(*input, ¶ms->aes128_dec_keys); + return AES_SUCCESS; +} + +static AES_StatusCode aes_encrypt_block_aes192( + const AES_Block* input, + const AES_EncryptionRoundKeys* params, + AES_Block* output, + AES_ErrorDetails* err_details +) { + AES_UNUSED_PARAMETER(err_details); + *output = aes192_encrypt_block(*input, ¶ms->aes192_enc_keys); + return AES_SUCCESS; +} + +static AES_StatusCode aes_decrypt_block_aes192( + const AES_Block* input, + const AES_DecryptionRoundKeys* params, + AES_Block* output, + AES_ErrorDetails* err_details +) { + AES_UNUSED_PARAMETER(err_details); + *output = aes192_decrypt_block(*input, ¶ms->aes192_dec_keys); + return AES_SUCCESS; +} + +static AES_StatusCode aes_encrypt_block_aes256( + const AES_Block* input, + const AES_EncryptionRoundKeys* params, + AES_Block* output, + AES_ErrorDetails* err_details +) { + AES_UNUSED_PARAMETER(err_details); + *output = aes256_encrypt_block(*input, ¶ms->aes256_enc_keys); + return AES_SUCCESS; +} + +static AES_StatusCode aes_decrypt_block_aes256( + const AES_Block* input, + const AES_DecryptionRoundKeys* params, + AES_Block* output, + AES_ErrorDetails* err_details +) { + AES_UNUSED_PARAMETER(err_details); + *output = aes256_decrypt_block(*input, ¶ms->aes256_dec_keys); + return AES_SUCCESS; +} + +static AES_Ops aes128_ops = { + &aes_parse_key_aes128, + &aes_format_key_aes128, + &aes_expand_key_aes128, + &aes_encrypt_block_aes128, + &aes_decrypt_block_aes128, +}; + +static AES_Ops aes192_ops = { + &aes_parse_key_aes192, + &aes_format_key_aes192, + &aes_expand_key_aes192, + &aes_encrypt_block_aes192, + &aes_decrypt_block_aes192, +}; + +static AES_Ops aes256_ops = { + &aes_parse_key_aes256, + &aes_format_key_aes256, + &aes_expand_key_aes256, + &aes_encrypt_block_aes256, + &aes_decrypt_block_aes256, +}; + +static const AES_Ops* aes_ops_list[] = { + &aes128_ops, + &aes192_ops, + &aes256_ops, +}; + +const AES_Ops* aes_get_ops(AES_Algorithm algorithm) { + int l = 0; + size_t r = sizeof(aes_ops_list) / sizeof(aes_ops_list[0]) - 1; + + if ((int)algorithm < l || (size_t)algorithm > r) { + assert(0); + return NULL; + } + + return aes_ops_list[algorithm]; +} + +AES_StatusCode aes_parse_key( + AES_Algorithm algorithm, + AES_Key* dest, + 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_get_ops(algorithm)->parse_key(dest, src, err_details); +} + +AES_StatusCode aes_format_key( + AES_Algorithm algorithm, + AES_KeyString* dest, + const AES_Key* 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_get_ops(algorithm)->format_key(dest, src, err_details); +} diff --git a/aes/src/asm/aes128.asm b/aes/src/asm/aes128.asm index abf5063..67498fd 100644 --- a/aes/src/asm/aes128.asm +++ b/aes/src/asm/aes128.asm @@ -9,7 +9,7 @@ .code -@aes128_encrypt_block_@20 proc +@aes128_encrypt_block_internal@20 proc pxor xmm0, [ecx] aesenc xmm0, [ecx + 10h] aesenc xmm0, [ecx + 20h] @@ -22,9 +22,9 @@ aesenc xmm0, [ecx + 90h] aesenclast xmm0, [ecx + 0A0h] ret -@aes128_encrypt_block_@20 endp +@aes128_encrypt_block_internal@20 endp -@aes128_decrypt_block_@20 proc +@aes128_decrypt_block_internal@20 proc pxor xmm0, [ecx] aesdec xmm0, [ecx + 10h] aesdec xmm0, [ecx + 20h] @@ -37,9 +37,9 @@ aesdec xmm0, [ecx + 90h] aesdeclast xmm0, [ecx + 0A0h] ret -@aes128_decrypt_block_@20 endp +@aes128_decrypt_block_internal@20 endp -@aes128_expand_key_@20 proc +@aes128_expand_key_internal@20 proc ; A "word" (in terms of the FIPS 187 standard) is a 32-bit block. ; Words are denoted by `w[N]`. ; @@ -166,9 +166,9 @@ aes128_keygen_assist: add ecx, 10h ; ecx = &w[i+8] ret -@aes128_expand_key_@20 endp +@aes128_expand_key_internal@20 endp -@aes128_derive_decryption_keys_@8 proc +@aes128_derive_decryption_keys_internal@8 proc movdqa xmm5, [ecx] movdqa xmm4, [ecx + 0A0h] movdqa [edx], xmm4 @@ -198,6 +198,6 @@ aes128_keygen_assist: movdqa [edx + 50h], xmm5 ret -@aes128_derive_decryption_keys_@8 endp +@aes128_derive_decryption_keys_internal@8 endp end diff --git a/aes/src/asm/aes192.asm b/aes/src/asm/aes192.asm index 5411419..765152c 100644 --- a/aes/src/asm/aes192.asm +++ b/aes/src/asm/aes192.asm @@ -9,7 +9,7 @@ .code -@aes192_encrypt_block_@20 proc +@aes192_encrypt_block_internal@20 proc pxor xmm0, [ecx] aesenc xmm0, [ecx + 10h] aesenc xmm0, [ecx + 20h] @@ -24,9 +24,9 @@ aesenc xmm0, [ecx + 0B0h] aesenclast xmm0, [ecx + 0C0h] ret -@aes192_encrypt_block_@20 endp +@aes192_encrypt_block_internal@20 endp -@aes192_decrypt_block_@20 proc +@aes192_decrypt_block_internal@20 proc pxor xmm0, [ecx] aesdec xmm0, [ecx + 10h] aesdec xmm0, [ecx + 20h] @@ -41,9 +41,9 @@ aesdec xmm0, [ecx + 0B0h] aesdeclast xmm0, [ecx + 0C0h] ret -@aes192_decrypt_block_@20 endp +@aes192_decrypt_block_internal@20 endp -@aes192_expand_key_@36 proc +@aes192_expand_key_internal@36 proc ; A "word" (in terms of the FIPS 187 standard) is a 32-bit block. ; Words are denoted by `w[N]`. ; @@ -207,9 +207,9 @@ aes192_keygen_assist: ; 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 -@aes192_expand_key_@36 endp +@aes192_expand_key_internal@36 endp -@aes192_derive_decryption_keys_@8 proc +@aes192_derive_decryption_keys_internal@8 proc movdqa xmm5, [ecx] movdqa xmm4, [ecx + 0C0h] movdqa [edx], xmm4 @@ -244,6 +244,6 @@ aes192_keygen_assist: movdqa [edx + 60h], xmm5 ret -@aes192_derive_decryption_keys_@8 endp +@aes192_derive_decryption_keys_internal@8 endp end diff --git a/aes/src/asm/aes256.asm b/aes/src/asm/aes256.asm index 4c6c07c..58aad6b 100644 --- a/aes/src/asm/aes256.asm +++ b/aes/src/asm/aes256.asm @@ -9,7 +9,7 @@ .code -@aes256_encrypt_block_@20 proc +@aes256_encrypt_block_internal@20 proc pxor xmm0, [ecx] aesenc xmm0, [ecx + 10h] aesenc xmm0, [ecx + 20h] @@ -26,9 +26,9 @@ aesenc xmm0, [ecx + 0D0h] aesenclast xmm0, [ecx + 0E0h] ret -@aes256_encrypt_block_@20 endp +@aes256_encrypt_block_internal@20 endp -@aes256_decrypt_block_@20 proc +@aes256_decrypt_block_internal@20 proc pxor xmm0, [ecx] aesdec xmm0, [ecx + 10h] aesdec xmm0, [ecx + 20h] @@ -45,9 +45,9 @@ aesdec xmm0, [ecx + 0D0h] aesdeclast xmm0, [ecx + 0E0h] ret -@aes256_decrypt_block_@20 endp +@aes256_decrypt_block_internal@20 endp -@aes256_expand_key_@36 proc +@aes256_expand_key_internal@36 proc ; A "word" (in terms of the FIPS 187 standard) is a 32-bit block. ; Words are denoted by `w[N]`. ; @@ -240,9 +240,9 @@ aes256_keygen_assist: pxor xmm0, xmm1 ret -@aes256_expand_key_@36 endp +@aes256_expand_key_internal@36 endp -@aes256_derive_decryption_keys_@8 proc +@aes256_derive_decryption_keys_internal@8 proc movdqa xmm5, [ecx] movdqa xmm4, [ecx + 0E0h] movdqa [edx], xmm4 @@ -282,6 +282,6 @@ aes256_keygen_assist: movdqa [edx + 70h], xmm5 ret -@aes256_derive_decryption_keys_@8 endp +@aes256_derive_decryption_keys_internal@8 endp end diff --git a/aes/src/block.c b/aes/src/block.c new file mode 100644 index 0000000..552c445 --- /dev/null +++ b/aes/src/block.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2026 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 +#include + +static AES_Block reverse_byte_order(AES_Block block) { + return _mm_shuffle_epi8(block, aes_make_block(0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f)); +} + +AES_Block aes_inc_block(AES_Block x) { + x = reverse_byte_order(x); + x = _mm_add_epi32(x, aes_make_block(0, 0, 0, 1)); + x = reverse_byte_order(x); + return x; +} + +AES_StatusCode aes_format_block( + AES_BlockString* str, + const 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_block_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_format_block_as_matrix( + AES_BlockMatrixString* str, + const 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_block_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_parse_block(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_block_aligned(bytes); + return AES_SUCCESS; +} diff --git a/aes/src/box.c b/aes/src/box.c index dd50f25..e4750dc 100644 --- a/aes/src/box.c +++ b/aes/src/box.c @@ -10,16 +10,10 @@ #include #include -static const AES_BoxOps* aes_box_ops_list[] = { - &aes128_box_ops, - &aes192_box_ops, - &aes256_box_ops, -}; - AES_StatusCode aes_box_init( AES_Box* box, AES_Algorithm algorithm, - const AES_BoxKey* box_key, + const AES_Key* box_key, AES_Mode mode, const AES_Block* iv, AES_ErrorDetails* err_details @@ -28,13 +22,16 @@ AES_StatusCode aes_box_init( box->algorithm = algorithm; box->mode = mode; - if (iv != NULL) + + if (!iv && aes_mode_requires_init_vector(mode)) + return aes_error_mode_requires_init_vector(err_details); + if (iv) box->iv = *iv; - box->ops = aes_box_ops_list[algorithm]; - status = box->ops->calc_round_keys( - box_key, &box->encryption_keys, &box->decryption_keys, err_details - ); + box->ops = aes_get_ops(algorithm); + + status = + box->ops->expand_key(box_key, &box->encryption_keys, &box->decryption_keys, err_details); if (aes_is_error(status)) return status; @@ -533,31 +530,3 @@ AES_StatusCode aes_box_decrypt_buffer( return status; } } - -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_ops_list[algorithm]->parse_key(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_ops_list[algorithm]->format_key(dest, src, err_details); -} diff --git a/aes/src/box_aes.c b/aes/src/box_aes.c deleted file mode 100644 index d0c9a41..0000000 --- a/aes/src/box_aes.c +++ /dev/null @@ -1,219 +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); - aes128_expand_key_(box_key->aes128_key.key, &encryption_keys->aes128_encryption_keys); - 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); - aes192_expand_key_( - box_key->aes192_key.lo, box_key->aes192_key.hi, &encryption_keys->aes192_encryption_keys - ); - 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); - aes256_expand_key_( - box_key->aes256_key.lo, box_key->aes256_key.hi, &encryption_keys->aes256_encryption_keys - ); - aes256_derive_decryption_keys_( - &encryption_keys->aes256_encryption_keys, &decryption_keys->aes256_decryption_keys - ); - return AES_SUCCESS; -} - -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 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 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 aes256_parse_key(&dest->aes256_key, src, 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 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 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 aes256_format_key(&dest->aes256, &src->aes256_key, err_details); -} - -static AES_StatusCode aes_box_encrypt_block_aes128( - const AES_Block* input, - const AES_BoxEncryptionRoundKeys* params, - AES_Block* output, - AES_ErrorDetails* err_details -) { - AES_UNUSED_PARAMETER(err_details); - *output = aes128_encrypt_block_(*input, ¶ms->aes128_encryption_keys); - return AES_SUCCESS; -} - -static AES_StatusCode aes_box_decrypt_block_aes128( - const AES_Block* input, - const AES_BoxDecryptionRoundKeys* params, - AES_Block* output, - AES_ErrorDetails* err_details -) { - AES_UNUSED_PARAMETER(err_details); - *output = aes128_decrypt_block_(*input, ¶ms->aes128_decryption_keys); - return AES_SUCCESS; -} - -static AES_StatusCode aes_box_encrypt_block_aes192( - const AES_Block* input, - const AES_BoxEncryptionRoundKeys* params, - AES_Block* output, - AES_ErrorDetails* err_details -) { - AES_UNUSED_PARAMETER(err_details); - *output = aes192_encrypt_block_(*input, ¶ms->aes192_encryption_keys); - return AES_SUCCESS; -} - -static AES_StatusCode aes_box_decrypt_block_aes192( - const AES_Block* input, - const AES_BoxDecryptionRoundKeys* params, - AES_Block* output, - AES_ErrorDetails* err_details -) { - AES_UNUSED_PARAMETER(err_details); - *output = aes192_decrypt_block_(*input, ¶ms->aes192_decryption_keys); - return AES_SUCCESS; -} - -static AES_StatusCode aes_box_encrypt_block_aes256( - const AES_Block* input, - const AES_BoxEncryptionRoundKeys* params, - AES_Block* output, - AES_ErrorDetails* err_details -) { - AES_UNUSED_PARAMETER(err_details); - *output = aes256_encrypt_block_(*input, ¶ms->aes256_encryption_keys); - return AES_SUCCESS; -} - -static AES_StatusCode aes_box_decrypt_block_aes256( - const AES_Block* input, - const AES_BoxDecryptionRoundKeys* params, - AES_Block* output, - AES_ErrorDetails* err_details -) { - AES_UNUSED_PARAMETER(err_details); - *output = aes256_decrypt_block_(*input, ¶ms->aes256_decryption_keys); - return AES_SUCCESS; -} - -AES_BoxOps aes128_box_ops = { - &aes_box_derive_params_aes128, - &aes_box_parse_key_aes128, - &aes_box_format_key_aes128, - &aes_box_encrypt_block_aes128, - &aes_box_decrypt_block_aes128, -}; - -AES_BoxOps aes192_box_ops = { - &aes_box_derive_params_aes192, - &aes_box_parse_key_aes192, - &aes_box_format_key_aes192, - &aes_box_encrypt_block_aes192, - &aes_box_decrypt_block_aes192, -}; - -AES_BoxOps aes256_box_ops = { - &aes_box_derive_params_aes256, - &aes_box_parse_key_aes256, - &aes_box_format_key_aes256, - &aes_box_encrypt_block_aes256, - &aes_box_decrypt_block_aes256, -}; diff --git a/aes/src/c/aes128.c b/aes/src/c/aes128.c index 909b208..115c55e 100644 --- a/aes/src/c/aes128.c +++ b/aes/src/c/aes128.c @@ -10,7 +10,7 @@ #include #include -AES_Block __fastcall aes128_encrypt_block_( +AES_Block __fastcall aes128_encrypt_block_internal( AES_Block plaintext, const AES128_RoundKeys* encryption_keys ) { @@ -27,7 +27,7 @@ AES_Block __fastcall aes128_encrypt_block_( return _mm_aesenclast_si128(plaintext, encryption_keys->keys[10]); } -AES_Block __fastcall aes128_decrypt_block_( +AES_Block __fastcall aes128_decrypt_block_internal( AES_Block ciphertext, const AES128_RoundKeys* decryption_keys ) { @@ -60,7 +60,7 @@ static AES_Block __fastcall aes128_expand_key_assist(AES_Block prev, AES_Block h return prev; } -void __fastcall aes128_expand_key_(AES_Block key, AES128_RoundKeys* encryption_keys) { +void __fastcall aes128_expand_key_internal(AES_Block key, AES128_RoundKeys* encryption_keys) { AES_Block prev = encryption_keys->keys[0] = key; prev = encryption_keys->keys[1] = aes128_expand_key_assist(prev, _mm_aeskeygenassist_si128(prev, 0x01)); @@ -84,7 +84,7 @@ void __fastcall aes128_expand_key_(AES_Block key, AES128_RoundKeys* encryption_k aes128_expand_key_assist(prev, _mm_aeskeygenassist_si128(prev, 0x36)); } -void __fastcall aes128_derive_decryption_keys_( +void __fastcall aes128_derive_decryption_keys_internal( const AES128_RoundKeys* encryption_keys, AES128_RoundKeys* decryption_keys ) { diff --git a/aes/src/c/aes192.c b/aes/src/c/aes192.c index b5f1103..ba72107 100644 --- a/aes/src/c/aes192.c +++ b/aes/src/c/aes192.c @@ -10,7 +10,7 @@ #include #include -AES_Block __fastcall aes192_encrypt_block_( +AES_Block __fastcall aes192_encrypt_block_internal( AES_Block plaintext, const AES192_RoundKeys* encryption_keys ) { @@ -29,7 +29,7 @@ AES_Block __fastcall aes192_encrypt_block_( return _mm_aesenclast_si128(plaintext, encryption_keys->keys[12]); } -AES_Block __fastcall aes192_decrypt_block_( +AES_Block __fastcall aes192_decrypt_block_internal( AES_Block ciphertext, const AES192_RoundKeys* decryption_keys ) { @@ -73,7 +73,7 @@ static void __fastcall aes192_expand_key_assist( *prev_hi = _mm_xor_si128(*prev_hi, tmp); } -void __fastcall aes192_expand_key_( +void __fastcall aes192_expand_key_internal( AES_Block key_lo, AES_Block key_hi, AES192_RoundKeys* encryption_keys @@ -125,7 +125,7 @@ void __fastcall aes192_expand_key_( encryption_keys->keys[12] = key_lo; } -void __fastcall aes192_derive_decryption_keys_( +void __fastcall aes192_derive_decryption_keys_internal( const AES192_RoundKeys* encryption_keys, AES192_RoundKeys* decryption_keys ) { diff --git a/aes/src/c/aes256.c b/aes/src/c/aes256.c index cc5e13e..bc86965 100644 --- a/aes/src/c/aes256.c +++ b/aes/src/c/aes256.c @@ -10,7 +10,7 @@ #include #include -AES_Block __fastcall aes256_encrypt_block_( +AES_Block __fastcall aes256_encrypt_block_internal( AES_Block plaintext, const AES256_RoundKeys* encryption_keys ) { @@ -31,7 +31,7 @@ AES_Block __fastcall aes256_encrypt_block_( return _mm_aesenclast_si128(plaintext, encryption_keys->keys[14]); } -AES_Block __fastcall aes256_decrypt_block_( +AES_Block __fastcall aes256_decrypt_block_internal( AES_Block ciphertext, const AES256_RoundKeys* decryption_keys ) { @@ -75,7 +75,7 @@ static AES_Block __fastcall aes256_expand_key_assist( return *prev_hi; } -void __fastcall aes256_expand_key_( +void __fastcall aes256_expand_key_internal( AES_Block key_lo, AES_Block key_hi, AES256_RoundKeys* encryption_keys @@ -139,7 +139,7 @@ void __fastcall aes256_expand_key_( encryption_keys->keys[14] = aes256_expand_key_assist(&prev_lo, &prev_hi, hwgen); } -void __fastcall aes256_derive_decryption_keys_( +void __fastcall aes256_derive_decryption_keys_internal( const AES256_RoundKeys* encryption_keys, AES256_RoundKeys* decryption_keys ) { diff --git a/aes/src/error.c b/aes/src/error.c index 8de8a5d..004c869 100644 --- a/aes/src/error.c +++ b/aes/src/error.c @@ -220,3 +220,7 @@ AES_StatusCode aes_error_missing_padding(AES_ErrorDetails* err_details) { AES_StatusCode aes_error_memory_allocation(AES_ErrorDetails* err_details) { return aes_make_error(err_details, AES_MEMORY_ALLOCATION_ERROR); } + +AES_StatusCode aes_error_mode_requires_init_vector(AES_ErrorDetails* err_details) { + return aes_make_error(err_details, AES_MODE_REQUIRES_INIT_VECTOR_ERROR); +} diff --git a/aes/src/key.c b/aes/src/key.c new file mode 100644 index 0000000..35f858c --- /dev/null +++ b/aes/src/key.c @@ -0,0 +1,200 @@ +/* + * 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 aes128_format_key( + AES128_KeyString* str, + const 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_block_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 aes192_format_key( + AES192_KeyString* str, + const 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_block_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_block_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 aes256_format_key( + AES256_KeyString* str, + const 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_block_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_block_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 aes128_parse_key(AES128_Key* dest, const char* src, AES_ErrorDetails* err_details) { + return aes_parse_block(&dest->key, src, err_details); +} + +AES_StatusCode aes192_parse_key(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_block_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_block_aligned(bytes); + } + + return AES_SUCCESS; +} + +AES_StatusCode aes256_parse_key(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_block_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_block_aligned(bytes); + } + + return AES_SUCCESS; +} diff --git a/aesxx/include/aesxx/aes.hpp b/aesxx/include/aesxx/aes.hpp deleted file mode 100644 index 38d98fa..0000000 --- a/aesxx/include/aesxx/aes.hpp +++ /dev/null @@ -1,230 +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 -#include - -namespace aes { -namespace aes128 { - -typedef AES_Block Block; -typedef AES128_RoundKeys RoundKeys; -typedef AES128_Key Key; - -} // namespace aes128 - -template <> -struct Types { - typedef aes128::Block Block; - typedef aes128::RoundKeys RoundKeys; - typedef aes128::Key Key; -}; - -template <> -inline void from_string(aes128::Block& dest, std::string_view src) { - aes_parse_block(&dest, src.data(), ErrorDetailsThrowsInDestructor{}); -} - -template <> -inline std::string to_string(const aes128::Block& src) { - AES_BlockString str; - aes_format_block(&str, &src, ErrorDetailsThrowsInDestructor{}); - return {str.str}; -} - -template <> -inline std::string to_matrix_string(const aes128::Block& src) { - AES_BlockMatrixString str; - aes_format_block_as_matrix(&str, &src, ErrorDetailsThrowsInDestructor{}); - return {str.str}; -} - -template <> -inline void from_string(aes128::Key& dest, std::string_view src) { - aes128_parse_key(&dest, src.data(), ErrorDetailsThrowsInDestructor{}); -} - -template <> -inline std::string to_string(const aes128::Key& src) { - AES128_KeyString str; - aes128_format_key(&str, &src, ErrorDetailsThrowsInDestructor{}); - return {str.str}; -} - -template <> -inline void expand_key(const aes128::Key& key, aes128::RoundKeys& encryption_keys) { - aes128_expand_key(&key, &encryption_keys); -} - -template <> -inline void derive_decryption_keys( - const aes128::RoundKeys& encryption_keys, - aes128::RoundKeys& decryption_keys -) { - aes128_derive_decryption_keys(&encryption_keys, &decryption_keys); -} - -AESXX_ENCRYPT_BLOCK_ECB(128); -AESXX_DECRYPT_BLOCK_ECB(128); -AESXX_ENCRYPT_BLOCK_CBC(128); -AESXX_DECRYPT_BLOCK_CBC(128); -AESXX_ENCRYPT_BLOCK_CFB(128); -AESXX_DECRYPT_BLOCK_CFB(128); -AESXX_ENCRYPT_BLOCK_OFB(128); -AESXX_DECRYPT_BLOCK_OFB(128); -AESXX_ENCRYPT_BLOCK_CTR(128); -AESXX_DECRYPT_BLOCK_CTR(128); - -namespace aes192 { - -typedef AES_Block Block; -typedef AES192_RoundKeys RoundKeys; -typedef AES192_Key Key; - -} // namespace aes192 - -template <> -struct Types { - typedef aes192::Block Block; - typedef aes192::RoundKeys RoundKeys; - typedef aes192::Key Key; -}; - -template <> -inline void from_string(aes192::Block& dest, std::string_view src) { - aes_parse_block(&dest, src.data(), ErrorDetailsThrowsInDestructor{}); -} - -template <> -inline std::string to_string(const aes192::Block& src) { - AES_BlockString str; - aes_format_block(&str, &src, ErrorDetailsThrowsInDestructor{}); - return {str.str}; -} - -template <> -inline std::string to_matrix_string(const aes192::Block& src) { - AES_BlockMatrixString str; - aes_format_block_as_matrix(&str, &src, ErrorDetailsThrowsInDestructor{}); - return {str.str}; -} - -template <> -inline void from_string(aes192::Key& dest, std::string_view src) { - aes192_parse_key(&dest, src.data(), ErrorDetailsThrowsInDestructor{}); -} - -template <> -inline std::string to_string(const aes192::Key& src) { - AES192_KeyString str; - aes192_format_key(&str, &src, ErrorDetailsThrowsInDestructor{}); - return {str.str}; -} - -template <> -inline void expand_key(const aes192::Key& key, aes192::RoundKeys& encryption_keys) { - aes192_expand_key(&key, &encryption_keys); -} - -template <> -inline void derive_decryption_keys( - const aes192::RoundKeys& encryption_keys, - aes192::RoundKeys& decryption_keys -) { - aes192_derive_decryption_keys(&encryption_keys, &decryption_keys); -} - -AESXX_ENCRYPT_BLOCK_ECB(192); -AESXX_DECRYPT_BLOCK_ECB(192); -AESXX_ENCRYPT_BLOCK_CBC(192); -AESXX_DECRYPT_BLOCK_CBC(192); -AESXX_ENCRYPT_BLOCK_CFB(192); -AESXX_DECRYPT_BLOCK_CFB(192); -AESXX_ENCRYPT_BLOCK_OFB(192); -AESXX_DECRYPT_BLOCK_OFB(192); -AESXX_ENCRYPT_BLOCK_CTR(192); -AESXX_DECRYPT_BLOCK_CTR(192); - -namespace aes256 { - -typedef AES_Block Block; -typedef AES256_RoundKeys RoundKeys; -typedef AES256_Key Key; - -} // namespace aes256 - -template <> -struct Types { - typedef aes256::Block Block; - typedef aes256::RoundKeys RoundKeys; - typedef aes256::Key Key; -}; - -template <> -inline void from_string(aes256::Block& dest, std::string_view src) { - aes_parse_block(&dest, src.data(), ErrorDetailsThrowsInDestructor{}); -} - -template <> -inline std::string to_string(const aes256::Block& src) { - AES_BlockString str; - aes_format_block(&str, &src, ErrorDetailsThrowsInDestructor{}); - return {str.str}; -} - -template <> -inline std::string to_matrix_string(const aes256::Block& src) { - AES_BlockMatrixString str; - aes_format_block_as_matrix(&str, &src, ErrorDetailsThrowsInDestructor{}); - return {str.str}; -} - -template <> -inline void from_string(aes256::Key& dest, std::string_view src) { - aes256_parse_key(&dest, src.data(), ErrorDetailsThrowsInDestructor{}); -} - -template <> -inline std::string to_string(const aes256::Key& src) { - AES256_KeyString str; - aes256_format_key(&str, &src, ErrorDetailsThrowsInDestructor{}); - return {str.str}; -} - -template <> -inline void expand_key(const aes256::Key& key, aes256::RoundKeys& encryption_keys) { - aes256_expand_key(&key, &encryption_keys); -} - -template <> -inline void derive_decryption_keys( - const aes256::RoundKeys& encryption_keys, - aes256::RoundKeys& decryption_keys -) { - aes256_derive_decryption_keys(&encryption_keys, &decryption_keys); -} - -AESXX_ENCRYPT_BLOCK_ECB(256); -AESXX_DECRYPT_BLOCK_ECB(256); -AESXX_ENCRYPT_BLOCK_CBC(256); -AESXX_DECRYPT_BLOCK_CBC(256); -AESXX_ENCRYPT_BLOCK_CFB(256); -AESXX_DECRYPT_BLOCK_CFB(256); -AESXX_ENCRYPT_BLOCK_OFB(256); -AESXX_DECRYPT_BLOCK_OFB(256); -AESXX_ENCRYPT_BLOCK_CTR(256); -AESXX_DECRYPT_BLOCK_CTR(256); - -} // namespace aes diff --git a/aesxx/include/aesxx/all.hpp b/aesxx/include/aesxx/all.hpp index 99202a7..acea406 100644 --- a/aesxx/include/aesxx/all.hpp +++ b/aesxx/include/aesxx/all.hpp @@ -5,9 +5,7 @@ #pragma once -#include "aes.hpp" #include "algorithm.hpp" -#include "api.hpp" #include "box.hpp" #include "data.hpp" #include "debug.hpp" diff --git a/aesxx/include/aesxx/api.hpp b/aesxx/include/aesxx/api.hpp deleted file mode 100644 index 131e5e5..0000000 --- a/aesxx/include/aesxx/api.hpp +++ /dev/null @@ -1,136 +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 -#include - -namespace aes { - -template -struct Types; - -template -std::size_t get_number_of_rounds() { - if constexpr (algorithm == AES_AES128) - return 11; - if constexpr (algorithm == AES_AES192) - return 13; - if constexpr (algorithm == AES_AES256) - return 15; - static_assert("Unrecognized algorithm"); -} - -template -void from_string(typename Types::Block&, std::string_view); - -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&, std::string_view); - -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 -void encrypt_block( - const typename Types::Block& plaintext, - const typename Types::RoundKeys& round_keys, - typename Types::Block& iv, - typename Types::Block& ciphertext -) { - if constexpr (mode_requires_init_vector(mode)) { - encrypt_block(plaintext, round_keys, iv, ciphertext); - } else { - encrypt_block(plaintext, round_keys, ciphertext); - } -} - -template -void decrypt_block( - const typename Types::Block& ciphertext, - const typename Types::RoundKeys& round_keys, - typename Types::Block& iv, - typename Types::Block& plaintext -) { - if constexpr (mode_requires_init_vector(mode)) { - encrypt_block(plaintext, round_keys, iv, ciphertext); - } else { - encrypt_block(plaintext, round_keys, ciphertext); - } -} - -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 constexpr (mode_uses_encryption_keys_only(mode)) { - 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; -}; - -} // namespace aes diff --git a/aesxx/include/aesxx/box.hpp b/aesxx/include/aesxx/box.hpp index 870b3a7..c2ea6c9 100644 --- a/aesxx/include/aesxx/box.hpp +++ b/aesxx/include/aesxx/box.hpp @@ -6,12 +6,14 @@ #pragma once #include "algorithm.hpp" +#include "data.hpp" #include "error.hpp" #include "mode.hpp" #include #include +#include #include #include #include @@ -20,43 +22,48 @@ namespace aes { class Box { public: - typedef AES_Block Block; - typedef AES_BoxKey Key; + using Key = AES_Key; + /* static std::string format_key(const Key& src, Algorithm algorithm) { - AES_BoxKeyString str; - aes_box_format_key(&str, algorithm, &src, ErrorDetailsThrowsInDestructor{}); + AES_KeyString str; + aes_format_key(&str, algorithm, &src, ErrorDetailsThrowsInDestructor{}); return reinterpret_cast(&str); } + */ - static std::string format_block(const Block& src) { - AES_BlockString str; - aes_format_block(&str, &src, ErrorDetailsThrowsInDestructor{}); - return reinterpret_cast(&str); - } - - static void parse_block(Block& dest, std::string_view src) { - aes_parse_block(&dest, src.data(), ErrorDetailsThrowsInDestructor{}); + static void parse_key(Key& dest, Algorithm algorithm, std::string_view src) { + aes_parse_key(algorithm, &dest, src.data(), ErrorDetailsThrowsInDestructor{}); } - static void parse_key(Key& dest, Algorithm algorithm, std::string_view src) { - aes_box_parse_key(&dest, algorithm, src.data(), ErrorDetailsThrowsInDestructor{}); + Box(Algorithm algorithm, const Key& key, Mode mode, const std::optional& iv) { + aes_box_init( + &impl, algorithm, &key, mode, iv ? iv->ptr() : NULL, ErrorDetailsThrowsInDestructor{} + ); } - Box(Algorithm algorithm, const Key& key) { - aes_box_init(&impl, algorithm, &key, AES_ECB, nullptr, ErrorDetailsThrowsInDestructor{}); + Algorithm get_algorithm() const { + return impl.algorithm; } - Box(Algorithm algorithm, const Key& key, Mode mode, const Block& iv) { - aes_box_init(&impl, algorithm, &key, mode, &iv, ErrorDetailsThrowsInDestructor{}); + Mode get_mode() const { + return impl.mode; } void encrypt_block(const Block& plaintext, Block& ciphertext) { - aes_box_encrypt_block(&impl, &plaintext, &ciphertext, ErrorDetailsThrowsInDestructor{}); + dump_block("Plaintext", plaintext); + aes_box_encrypt_block( + &impl, plaintext.ptr(), ciphertext.ptr(), ErrorDetailsThrowsInDestructor{} + ); + dump_block("Ciphertext", ciphertext); } void decrypt_block(const Block& ciphertext, Block& plaintext) { - aes_box_decrypt_block(&impl, &ciphertext, &plaintext, ErrorDetailsThrowsInDestructor{}); + dump_block("Ciphertext", ciphertext); + aes_box_decrypt_block( + &impl, ciphertext.ptr(), plaintext.ptr(), ErrorDetailsThrowsInDestructor{} + ); + dump_block("Plaintext", plaintext); } std::vector encrypt_buffer(const void* src_buf, std::size_t src_size) { @@ -105,26 +112,16 @@ public: return dest_buf; } - std::string format_key(const Key& src) { - return format_key(src, get_algorithm()); - } - - void parse_key(Key& dest, std::string_view src) { - parse_key(dest, get_algorithm(), src); - } - - Algorithm get_algorithm() const { - return impl.algorithm; - } - - Mode get_mode() const { - return impl.mode; - } - private: - Key key; + void dump_block(std::string_view header, const Block& block) { + if (verbose > 0) + std::cout << std::format("{}: {}\n", header, block.to_string()); + if (verbose > 1) + std::cout << std::format("{}\n", block.to_matrix_string()); + } AES_Box impl; + int verbose = 0; }; } // namespace aes diff --git a/aesxx/include/aesxx/data.hpp b/aesxx/include/aesxx/data.hpp index 8e4691d..7500913 100644 --- a/aesxx/include/aesxx/data.hpp +++ b/aesxx/include/aesxx/data.hpp @@ -5,40 +5,54 @@ #pragma once +#include "algorithm.hpp" #include "error.hpp" #include +#include +#include + namespace aes { -typedef AES_Block Block128; +class Block { +public: + static Block parse(std::string_view src) { + return Block{src}; + } + + explicit Block(AES_Block impl) : impl{impl} {} + + Block(int hi3, int hi2, int lo1, int lo0) : impl{aes_make_block(hi3, hi2, lo1, lo0)} {} -inline void make_block(Block128& dest, int hi3, int hi2, int lo1, int lo0) { - dest = aes_make_block(hi3, hi2, lo1, lo0); -} + Block() : Block{0, 0, 0, 0} {} -inline void load_block(Block128& dest, const void* src) { - dest = aes_load_block(src); -} + explicit Block(std::string_view src) { + aes_parse_block(&impl, src.data(), ErrorDetailsThrowsInDestructor{}); + } -inline void load_block_aligned(Block128& dest, const void* src) { - dest = aes_load_block_aligned(src); -} + AES_Block* ptr() { + return &impl; + } -inline void store_block(void* dest, Block128& src) { - aes_store_block(dest, src); -} + const AES_Block* ptr() const { + return &impl; + } -inline void store_block_aligned(void* dest, Block128& src) { - aes_store_block_aligned(dest, src); -} + std::string to_string() const { + AES_BlockString str; + aes_format_block(&str, &impl, ErrorDetailsThrowsInDestructor{}); + return str.str; + } -inline Block128 xor_blocks(Block128& a, Block128& b) { - return aes_xor_blocks(a, b); -} + std::string to_matrix_string() const { + AES_BlockMatrixString str; + aes_format_block_as_matrix(&str, &impl, ErrorDetailsThrowsInDestructor{}); + return str.str; + } -inline Block128 inc_block(Block128& block) { - return aes_inc_block(block); -} +private: + AES_Block impl; +}; } // namespace aes diff --git a/aesxx/include/aesxx/mode.hpp b/aesxx/include/aesxx/mode.hpp index d6f282a..a0b279f 100644 --- a/aesxx/include/aesxx/mode.hpp +++ b/aesxx/include/aesxx/mode.hpp @@ -7,128 +7,8 @@ #include -#include - namespace aes { typedef AES_Mode Mode; -inline constexpr bool mode_requires_init_vector(Mode mode) { - return mode != AES_ECB; -} - -inline constexpr bool mode_uses_encryption_keys_only(Mode mode) { - return mode != AES_ECB && mode != AES_CBC; -} - -#define AESXX_ENCRYPT_BLOCK_ECB(version) \ - template <> \ - inline void encrypt_block( \ - const typename Types::Block& plaintext, \ - const typename Types::RoundKeys& encryption_keys, \ - typename Types::Block&, \ - typename Types::Block& ciphertext \ - ) { \ - ciphertext = aes##version##_encrypt_block_ECB(plaintext, &encryption_keys); \ - } - -#define AESXX_DECRYPT_BLOCK_ECB(version) \ - template <> \ - inline void decrypt_block( \ - const typename Types::Block& ciphertext, \ - const typename Types::RoundKeys& decryption_keys, \ - typename Types::Block&, \ - typename Types::Block& plaintext \ - ) { \ - plaintext = aes##version##_decrypt_block_ECB(ciphertext, &decryption_keys); \ - } - -#define AESXX_ENCRYPT_BLOCK_CBC(version) \ - 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##version##_encrypt_block_CBC(plaintext, &encryption_keys, iv, &iv); \ - } - -#define AESXX_DECRYPT_BLOCK_CBC(version) \ - 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##version##_decrypt_block_CBC(ciphertext, &decryption_keys, iv, &iv); \ - } - -#define AESXX_ENCRYPT_BLOCK_CFB(version) \ - 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##version##_encrypt_block_CFB(plaintext, &encryption_keys, iv, &iv); \ - } - -#define AESXX_DECRYPT_BLOCK_CFB(version) \ - 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##version##_decrypt_block_CFB(ciphertext, &encryption_keys, iv, &iv); \ - } - -#define AESXX_ENCRYPT_BLOCK_OFB(version) \ - 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##version##_encrypt_block_OFB(plaintext, &encryption_keys, iv, &iv); \ - } - -#define AESXX_DECRYPT_BLOCK_OFB(version) \ - 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##version##_decrypt_block_OFB(ciphertext, &encryption_keys, iv, &iv); \ - } - -#define AESXX_ENCRYPT_BLOCK_CTR(version) \ - 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##version##_encrypt_block_CTR(plaintext, &encryption_keys, iv, &iv); \ - } - -#define AESXX_DECRYPT_BLOCK_CTR(version) \ - 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##version##_decrypt_block_CTR(ciphertext, &encryption_keys, iv, &iv); \ - } - } // namespace aes diff --git a/aesxx/utils/README.md b/aesxx/utils/README.md index c133c92..a24bd15 100644 --- a/aesxx/utils/README.md +++ b/aesxx/utils/README.md @@ -12,8 +12,6 @@ Block encryption utilities can produce verbose human-readable output, including round keys, intermediate initialization vector values, etc. They are primarily intended for debugging purposes. Enable verbose output by passing the `--verbose` flag. -Please note that verbose output can only be produced when *not* using the -"boxes" interface (the `--use-boxes` flag). ### encrypt_block diff --git a/aesxx/utils/decrypt_block.cpp b/aesxx/utils/decrypt_block.cpp index c8edb34..7a296ff 100644 --- a/aesxx/utils/decrypt_block.cpp +++ b/aesxx/utils/decrypt_block.cpp @@ -3,7 +3,6 @@ // For details, see https://github.com/egor-tensin/aes-tools. // Distributed under the MIT License. -#include "helpers/block_dumper.hpp" #include "helpers/cmd_parser_block.hpp" #include @@ -18,128 +17,16 @@ namespace { -template -void decrypt_with_mode(const BlockSettings::Input& input, bool verbose = false) { - typename aes::Types::Block iv; - aes::make_block(iv, 0, 0, 0, 0); - - if (input.has_iv()) { - aes::from_string(iv, input.get_iv()); - if (verbose) - dump_iv(iv); - } - - typename aes::Types::Key key; - aes::from_string(key, input.get_key()); - if (verbose) - dump_key(key); - - aes::DecryptWrapper decrypt{key, iv}; - if (verbose) - dump_wrapper(decrypt); - - for (const auto& block : input.get_blocks()) { - typename aes::Types::Block ciphertext, plaintext; - aes::from_string(ciphertext, block); - - decrypt.decrypt_block(ciphertext, plaintext); - - if (verbose) { - dump_ciphertext(ciphertext); - dump_plaintext(plaintext); - dump_next_iv(decrypt); - } else { - std::cout << std::format("{}\n", aes::to_string(plaintext)); - } - } -} - -template -void decrypt_with_algorithm( - aes::Mode mode, - const BlockSettings::Input& input, - bool verbose = false -) { - switch (mode) { - case AES_ECB: - decrypt_with_mode(input, verbose); - break; - - case AES_CBC: - decrypt_with_mode(input, verbose); - break; - - case AES_CFB: - decrypt_with_mode(input, verbose); - break; - - case AES_OFB: - decrypt_with_mode(input, verbose); - break; - - case AES_CTR: - decrypt_with_mode(input, verbose); - break; - - default: - throw std::runtime_error("the selected mode of operation is not implemented"); - break; - } -} - -void decrypt_using_cxx_api( - aes::Algorithm algorithm, - aes::Mode mode, - const BlockSettings::Input& input, - bool verbose = false -) { - switch (algorithm) { - case AES_AES128: - decrypt_with_algorithm(mode, input, verbose); - break; - - case AES_AES192: - decrypt_with_algorithm(mode, input, verbose); - break; - - case AES_AES256: - decrypt_with_algorithm(mode, input, verbose); - break; - - default: - throw std::runtime_error("the selected algorithm is not implemented"); - break; - } -} - -void decrypt_using_particular_box(aes::Box& box, const std::vector& blocks) { - for (const auto& block : blocks) { - aes::Box::Block ciphertext; - box.parse_block(ciphertext, block); - - aes::Box::Block plaintext; - box.decrypt_block(ciphertext, plaintext); - std::cout << std::format("{}\n", box.format_block(plaintext)); - } -} - -void decrypt_using_boxes( - aes::Algorithm algorithm, - aes::Mode mode, - const BlockSettings::Input& input -) { +void decrypt_blocks(aes::Algorithm algorithm, aes::Mode mode, const BlockSettings::Input& input) { aes::Box::Key key; aes::Box::parse_key(key, algorithm, input.get_key()); - if (input.has_iv()) { - aes::Box::Block iv; - aes::Box::parse_block(iv, input.get_iv()); - aes::Box box{algorithm, key, mode, iv}; + aes::Box box{algorithm, key, mode, input.get_iv()}; - decrypt_using_particular_box(box, input.get_blocks()); - } else { - aes::Box box{algorithm, key}; - decrypt_using_particular_box(box, input.get_blocks()); + for (const auto& ciphertext : input.get_blocks()) { + aes::Block plaintext; + box.decrypt_block(ciphertext, plaintext); + std::cout << std::format("{}\n", plaintext.to_string()); } } @@ -162,13 +49,7 @@ int main(int argc, char** argv) { } for (const auto& input : settings.get_inputs()) { - if (settings.use_boxes()) { - decrypt_using_boxes(settings.get_algorithm(), settings.get_mode(), input); - } else { - decrypt_using_cxx_api( - settings.get_algorithm(), settings.get_mode(), input, settings.verbose() - ); - } + decrypt_blocks(settings.get_algorithm(), settings.get_mode(), input); } } catch (const aes::Error& e) { std::cerr << e; diff --git a/aesxx/utils/decrypt_bmp.cpp b/aesxx/utils/decrypt_bmp.cpp index 51a2572..cf5ac31 100644 --- a/aesxx/utils/decrypt_bmp.cpp +++ b/aesxx/utils/decrypt_bmp.cpp @@ -37,16 +37,8 @@ void decrypt_bmp(const FileSettings& settings) { aes::Box::Key key; aes::Box::parse_key(key, algorithm, settings.get_key()); - if (settings.has_iv()) { - aes::Box::Block iv; - aes::Box::parse_block(iv, settings.get_iv()); - - aes::Box box{algorithm, key, mode, iv}; - decrypt_bmp(box, settings.get_input_path(), settings.get_output_path()); - } else { - aes::Box box{algorithm, key}; - decrypt_bmp(box, settings.get_input_path(), settings.get_output_path()); - } + aes::Box box{algorithm, key, mode, settings.get_iv()}; + decrypt_bmp(box, settings.get_input_path(), settings.get_output_path()); } } // namespace diff --git a/aesxx/utils/decrypt_file.cpp b/aesxx/utils/decrypt_file.cpp index 6c915b5..9eb764f 100644 --- a/aesxx/utils/decrypt_file.cpp +++ b/aesxx/utils/decrypt_file.cpp @@ -35,16 +35,8 @@ void decrypt_file(const FileSettings& settings) { aes::Box::Key key; aes::Box::parse_key(key, algorithm, settings.get_key()); - if (settings.has_iv()) { - aes::Box::Block iv; - aes::Box::parse_block(iv, settings.get_iv()); - - aes::Box box{algorithm, key, mode, iv}; - decrypt_file(box, settings.get_input_path(), settings.get_output_path()); - } else { - aes::Box box{algorithm, key}; - decrypt_file(box, settings.get_input_path(), settings.get_output_path()); - } + aes::Box box{algorithm, key, mode, settings.get_iv()}; + decrypt_file(box, settings.get_input_path(), settings.get_output_path()); } } // namespace diff --git a/aesxx/utils/encrypt_block.cpp b/aesxx/utils/encrypt_block.cpp index a796483..40d9f1a 100644 --- a/aesxx/utils/encrypt_block.cpp +++ b/aesxx/utils/encrypt_block.cpp @@ -3,7 +3,6 @@ // For details, see https://github.com/egor-tensin/aes-tools. // Distributed under the MIT License. -#include "helpers/block_dumper.hpp" #include "helpers/cmd_parser_block.hpp" #include @@ -18,131 +17,16 @@ namespace { -template -void encrypt_with_mode(const BlockSettings::Input& input, bool verbose = false) { - typename aes::Types::Block iv; - aes::make_block(iv, 0, 0, 0, 0); - - if (input.has_iv()) { - aes::from_string(iv, input.get_iv()); - if (verbose) - dump_iv(iv); - } - - typename aes::Types::Key key; - aes::from_string(key, input.get_key()); - if (verbose) - dump_key(key); - - aes::EncryptWrapper encrypt{key, iv}; - if (verbose) - dump_wrapper(encrypt); - - for (const auto& input_block_string : input.get_blocks()) { - typename aes::Types::Block plaintext, ciphertext; - aes::from_string(plaintext, input_block_string); - - encrypt.encrypt_block(plaintext, ciphertext); - - if (verbose) { - dump_plaintext(plaintext); - dump_ciphertext(ciphertext); - dump_next_iv(encrypt); - } else { - std::cout << std::format("{}\n", aes::to_string(ciphertext)); - } - } -} - -template -void encrypt_with_algorithm( - aes::Mode mode, - const BlockSettings::Input& input, - bool verbose = false -) { - switch (mode) { - case AES_ECB: - encrypt_with_mode(input, verbose); - break; - - case AES_CBC: - encrypt_with_mode(input, verbose); - break; - - case AES_CFB: - encrypt_with_mode(input, verbose); - break; - - case AES_OFB: - encrypt_with_mode(input, verbose); - break; - - case AES_CTR: - encrypt_with_mode(input, verbose); - break; - - default: - throw std::runtime_error("the selected mode of operation is not implemented"); - break; - } -} - -void encrypt_using_cxx_api( - aes::Algorithm algorithm, - aes::Mode mode, - const BlockSettings::Input& input, - bool verbose = false -) { - switch (algorithm) { - case AES_AES128: - encrypt_with_algorithm(mode, input, verbose); - break; - - case AES_AES192: - encrypt_with_algorithm(mode, input, verbose); - break; - - case AES_AES256: - encrypt_with_algorithm(mode, input, verbose); - break; - - default: - throw std::runtime_error("the selected algorithm is not implemented"); - break; - } -} - -void encrypt_using_particular_box( - aes::Box& box, - const std::vector& input_block_strings -) { - for (const auto& input_block_string : input_block_strings) { - aes::Box::Block plaintext; - box.parse_block(plaintext, input_block_string); - - aes::Box::Block ciphertext; - box.encrypt_block(plaintext, ciphertext); - std::cout << std::format("{}\n", box.format_block(ciphertext)); - } -} - -void encrypt_using_boxes( - aes::Algorithm algorithm, - aes::Mode mode, - const BlockSettings::Input& input -) { +void encrypt_blocks(aes::Algorithm algorithm, aes::Mode mode, const BlockSettings::Input& input) { aes::Box::Key key; aes::Box::parse_key(key, algorithm, input.get_key()); - if (input.has_iv()) { - aes::Box::Block iv; - aes::Box::parse_block(iv, input.get_iv()); - aes::Box box{algorithm, key, mode, iv}; + aes::Box box{algorithm, key, mode, input.get_iv()}; - encrypt_using_particular_box(box, input.get_blocks()); - } else { - aes::Box box{algorithm, key}; - encrypt_using_particular_box(box, input.get_blocks()); + for (const auto& plaintext : input.get_blocks()) { + aes::Block ciphertext; + box.encrypt_block(plaintext, ciphertext); + std::cout << std::format("{}\n", ciphertext.to_string()); } } @@ -165,13 +49,7 @@ int main(int argc, char** argv) { } for (const auto& input : settings.get_inputs()) { - if (settings.use_boxes()) { - encrypt_using_boxes(settings.get_algorithm(), settings.get_mode(), input); - } else { - encrypt_using_cxx_api( - settings.get_algorithm(), settings.get_mode(), input, settings.verbose() - ); - } + encrypt_blocks(settings.get_algorithm(), settings.get_mode(), input); } } catch (const aes::Error& e) { std::cerr << e; diff --git a/aesxx/utils/encrypt_bmp.cpp b/aesxx/utils/encrypt_bmp.cpp index 19caee4..2fcde46 100644 --- a/aesxx/utils/encrypt_bmp.cpp +++ b/aesxx/utils/encrypt_bmp.cpp @@ -35,16 +35,8 @@ void encrypt_bmp(const FileSettings& settings) { aes::Box::Key key; aes::Box::parse_key(key, algorithm, settings.get_key()); - if (settings.has_iv()) { - aes::Box::Block iv; - aes::Box::parse_block(iv, settings.get_iv()); - - aes::Box box{algorithm, key, mode, iv}; - encrypt_bmp(box, settings.get_input_path(), settings.get_output_path()); - } else { - aes::Box box{algorithm, key}; - encrypt_bmp(box, settings.get_input_path(), settings.get_output_path()); - } + aes::Box box{algorithm, key, mode, settings.get_iv()}; + encrypt_bmp(box, settings.get_input_path(), settings.get_output_path()); } } // namespace diff --git a/aesxx/utils/encrypt_file.cpp b/aesxx/utils/encrypt_file.cpp index 1b7217c..4a2557f 100644 --- a/aesxx/utils/encrypt_file.cpp +++ b/aesxx/utils/encrypt_file.cpp @@ -35,16 +35,8 @@ void encrypt_file(const FileSettings& settings) { aes::Box::Key key; aes::Box::parse_key(key, algorithm, settings.get_key()); - if (settings.has_iv()) { - aes::Box::Block iv; - aes::Box::parse_block(iv, settings.get_iv()); - - aes::Box box{algorithm, key, mode, iv}; - encrypt_file(box, settings.get_input_path(), settings.get_output_path()); - } else { - aes::Box box{algorithm, key}; - encrypt_file(box, settings.get_input_path(), settings.get_output_path()); - } + aes::Box box{algorithm, key, mode, settings.get_iv()}; + encrypt_file(box, settings.get_input_path(), settings.get_output_path()); } } // namespace diff --git a/aesxx/utils/helpers/block_dumper.hpp b/aesxx/utils/helpers/block_dumper.hpp deleted file mode 100644 index 8284b67..0000000 --- a/aesxx/utils/helpers/block_dumper.hpp +++ /dev/null @@ -1,85 +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 -#include -#include -#include -#include - -template -void dump_block(std::string_view header, const typename aes::Types::Block& block) { - std::cout << std::format("{}: {}\n", header, aes::to_string(block)); - std::cout << std::format("{}\n", aes::to_matrix_string(block)); -} - -template -void dump_plaintext(const typename aes::Types::Block& block) { - dump_block("Plaintext", block); -} - -template -void dump_key(const typename aes::Types::Key& key) { - std::cout << std::format("Key: {}\n\n", aes::to_string(key)); -} - -template -void dump_ciphertext(const typename aes::Types::Block& ciphertext) { - dump_block("Ciphertext", ciphertext); -} - -template -void dump_iv(const typename aes::Types::Block& iv) { - dump_block("Initialization vector", iv); -} - -template -void dump_round_keys( - const char* header, - const typename aes::Types::RoundKeys& round_keys -) { - std::cout << std::format("{}:\n", header); - for (std::size_t i = 0; i < aes::get_number_of_rounds(); ++i) - std::cout << std::format("\t[{}]: {}\n", i, aes::to_string(round_keys.keys[i])); - std::cout << "\n"; -} - -template -void dump_encryption_keys(const typename aes::Types::RoundKeys& round_keys) { - dump_round_keys("Encryption round keys", round_keys); -} - -template -void dump_decryption_keys(const typename aes::Types::RoundKeys& round_keys) { - dump_round_keys("Decryption round keys", round_keys); -} - -template -void dump_wrapper(const aes::EncryptWrapper& wrapper) { - dump_encryption_keys(wrapper.encryption_keys); -} - -template -void dump_wrapper(const aes::DecryptWrapper& wrapper) { - dump_decryption_keys(wrapper.decryption_keys); -} - -template -void dump_next_iv(const aes::EncryptWrapper& wrapper) { - if constexpr (aes::mode_requires_init_vector(mode)) { - dump_block("Next initialization vector", wrapper.iv); - } -} - -template -void dump_next_iv(const aes::DecryptWrapper& wrapper) { - if constexpr (aes::mode_requires_init_vector(mode)) { - dump_block("Next initialization vector", wrapper.iv); - } -} diff --git a/aesxx/utils/helpers/cmd_parser_block.hpp b/aesxx/utils/helpers/cmd_parser_block.hpp index 4226fb5..7e24874 100644 --- a/aesxx/utils/helpers/cmd_parser_block.hpp +++ b/aesxx/utils/helpers/cmd_parser_block.hpp @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -23,32 +24,29 @@ class BlockSettings : public SettingsParser { public: class Input { public: - Input(std::string_view key, std::string_view iv, std::vector&& blocks) - : key{key}, iv{iv}, blocks{std::move(blocks)} {} - - Input(std::string key, std::vector&& blocks) - : key{key}, blocks{std::move(blocks)} {} + Input( + std::string_view key, + std::optional&& iv, + std::vector&& blocks + ) + : key{key}, iv{std::move(iv)}, blocks{std::move(blocks)} {} std::string get_key() const { return key; } - bool has_iv() const { - return !iv.empty(); - } - - std::string get_iv() const { + std::optional get_iv() const { return iv; } - std::vector get_blocks() const { + std::vector get_blocks() const { return blocks; } private: std::string key; - std::string iv; - std::vector blocks; + std::optional iv; + std::vector blocks; }; explicit BlockSettings(std::string_view argv0) : SettingsParser{argv0} { @@ -67,11 +65,6 @@ public: boost::program_options::value(&mode)->required()->value_name("MODE"), "set mode of operation" ); - visible.add_options()( - "use-boxes,b", - boost::program_options::bool_switch(&_use_boxes), - "use the \"boxes\" interface" - ); } const char* get_short_description() const override { @@ -111,10 +104,6 @@ public: return inputs; } - bool use_boxes() const { - return _use_boxes; - } - bool verbose() const { return _verbose; } @@ -129,35 +118,30 @@ private: std::string key{std::move(src.front())}; src.pop_front(); - std::string iv; + std::optional iv; - if (aes::mode_requires_init_vector(mode)) { + if (aes_mode_requires_init_vector(mode)) { if (src.empty()) { throw boost::program_options::error{ "an initialization vector is required for the selected mode of operation" }; } - iv = std::move(src.front()); + iv = aes::Block{std::move(src.front())}; src.pop_front(); } - auto blocks = parse_blocks(src); - - if (aes::mode_requires_init_vector(mode)) - return {key, iv, std::move(blocks)}; - else - return {key, std::move(blocks)}; + return {key, std::move(iv), parse_blocks(src)}; } - static std::vector parse_blocks(std::deque& src) { - std::vector blocks; + static std::vector parse_blocks(std::deque& src) { + std::vector blocks; while (!src.empty()) { std::string block{std::move(src.front())}; src.pop_front(); if (block == "--") break; - blocks.emplace_back(std::move(block)); + blocks.emplace_back(aes::Block{std::move(block)}); } return blocks; @@ -167,6 +151,5 @@ private: aes::Mode mode; std::vector inputs; - bool _use_boxes = false; bool _verbose = false; }; diff --git a/aesxx/utils/helpers/cmd_parser_file.hpp b/aesxx/utils/helpers/cmd_parser_file.hpp index 2e710b2..8adfb1d 100644 --- a/aesxx/utils/helpers/cmd_parser_file.hpp +++ b/aesxx/utils/helpers/cmd_parser_file.hpp @@ -10,8 +10,10 @@ #include +#include #include +#include #include #include #include @@ -39,7 +41,7 @@ public: ); visible.add_options()( "iv,v", - boost::program_options::value(&iv)->value_name("BLOCK"), + boost::program_options::value(&iv)->value_name("BLOCK"), "set initialization vector" ); visible.add_options()( @@ -66,12 +68,6 @@ public: SettingsParser::parse(argc, argv); if (exit_with_usage()) return; - - if (aes::mode_requires_init_vector(get_mode()) && iv.empty()) { - throw boost::program_options::error{ - "an initialization vector is required for the selected mode of operation" - }; - } } aes::Algorithm get_algorithm() const { @@ -94,12 +90,10 @@ public: return key; } - bool has_iv() const { - return !iv.empty(); - } - - std::string get_iv() const { - return iv; + std::optional get_iv() const { + if (iv) + return {*iv}; + return {}; } private: @@ -110,5 +104,5 @@ private: std::string output_path; std::string key; - std::string iv; + boost::optional iv; }; diff --git a/aesxx/utils/helpers/data_parsers.hpp b/aesxx/utils/helpers/data_parsers.hpp index a08f1bf..a66a433 100644 --- a/aesxx/utils/helpers/data_parsers.hpp +++ b/aesxx/utils/helpers/data_parsers.hpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -53,3 +54,12 @@ inline std::istream& operator>>(std::istream& is, aes::Algorithm& dest) { dest = it->second; return is; } + +namespace boost { + +inline void validate(any& dest, const std::vector& values, aes::Block*, int) { + const std::string& src = program_options::validators::get_single_string(values); + dest = aes::Block{src}; +} + +} // namespace boost diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 9a38d0a..2ee5728 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -10,17 +10,6 @@ add_test(NAME nist COMMAND Python3::Interpreter "${CMAKE_CURRENT_SOURCE_DIR}/nist.py" --path "$" ) -add_test(NAME nist_boxes COMMAND Python3::Interpreter - "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/tools/ctest-driver.py" - run - --pass-regex [=[Succeeded: *30$]=] - --fail-regex [=[Failed: *[1-9]]=] - -- - "$" - "${CMAKE_CURRENT_SOURCE_DIR}/nist.py" - --path "$" - --boxes -) add_test(NAME cavp COMMAND Python3::Interpreter "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/tools/ctest-driver.py" run @@ -31,17 +20,6 @@ add_test(NAME cavp COMMAND Python3::Interpreter "${CMAKE_CURRENT_SOURCE_DIR}/cavp.py" --path "$" ) -add_test(NAME cavp_boxes COMMAND Python3::Interpreter - "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/tools/ctest-driver.py" - run - --pass-regex [=[Succeeded: *96$]=] - --fail-regex [=[Failed: *[1-9]]=] - -- - "$" - "${CMAKE_CURRENT_SOURCE_DIR}/cavp.py" - --path "$" - --boxes -) add_test(NAME file COMMAND Python3::Interpreter "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/tools/ctest-driver.py" run diff --git a/test/cavp.py b/test/cavp.py index 047f254..928f6c9 100755 --- a/test/cavp.py +++ b/test/cavp.py @@ -101,42 +101,36 @@ class TestFile: for i in range(0, len(inputs), max_len): yield expected_output[i : i + max_len], inputs[i : i + max_len] - def _run_tests(self, tool, inputs, expected_output, use_boxes=False): + def _run_tests(self, tool, inputs, expected_output): for expected_output_chunk, input_chunk in self._split_into_chunks( expected_output, list(inputs) ): - actual_output = tool( - self.algorithm(), self.mode(), input_chunk, use_boxes=use_boxes - ) + actual_output = tool(self.algorithm(), self.mode(), input_chunk) if not verify_test_output(actual_output, expected_output_chunk): return TestExitCode.FAILURE return TestExitCode.SUCCESS - def run_encryption_tests(self, tools, use_boxes=False): + def run_encryption_tests(self, tools): logging.debug("Running encryption tests...") if not self.recognized(): return TestExitCode.SKIPPED try: keys, plaintexts, ciphertexts, init_vectors = self._encryption_data inputs = self._gen_inputs(keys, plaintexts, init_vectors) - return self._run_tests( - tools.run_encrypt_block, inputs, ciphertexts, use_boxes - ) + return self._run_tests(tools.run_encrypt_block, inputs, ciphertexts) except CalledProcessError as e: logging.error("Encountered an exception!") logging.exception(e) return TestExitCode.ERROR - def run_decryption_tests(self, tools, use_boxes=False): + def run_decryption_tests(self, tools): logging.debug("Running decryption tests...") if not self.recognized(): return TestExitCode.SKIPPED try: keys, plaintexts, ciphertexts, init_vectors = self._decryption_data inputs = self._gen_inputs(keys, ciphertexts, init_vectors) - return self._run_tests( - tools.run_decrypt_block, inputs, plaintexts, use_boxes - ) + return self._run_tests(tools.run_decrypt_block, inputs, plaintexts) except CalledProcessError as e: logging.error("Encountered an exception!") logging.exception(e) @@ -209,16 +203,14 @@ class TestArchive(zipfile.ZipFile): _script_dir = os.path.dirname(__file__) -def run_tests( - archive_path, tools_path=(), use_sde=False, use_boxes=False, verbose=False -): +def run_tests(archive_path, tools_path=(), use_sde=False, verbose=False): tools = Tools(tools_path, use_sde=use_sde) archive = TestArchive(archive_path) exit_codes = [] for test_file in archive.enum_test_files(): - exit_codes.append(test_file.run_encryption_tests(tools, use_boxes)) - exit_codes.append(test_file.run_decryption_tests(tools, use_boxes)) + exit_codes.append(test_file.run_encryption_tests(tools)) + exit_codes.append(test_file.run_decryption_tests(tools)) logging.info("Test exit codes:") logging.info("\tSkipped: %d", exit_codes.count(TestExitCode.SKIPPED)) @@ -254,13 +246,6 @@ def _parse_args(args=None): dest="use_sde", help="use Intel SDE to run the utilities", ) - parser.add_argument( - "--boxes", - "-b", - action="store_true", - dest="use_boxes", - help='use the "boxes" interface', - ) parser.add_argument( "--archive", "-a", diff --git a/test/nist.py b/test/nist.py index 447d34d..c51329c 100755 --- a/test/nist.py +++ b/test/nist.py @@ -184,7 +184,7 @@ class TestExitCode(Enum): SUCCESS, FAILURE, ERROR, SKIPPED = range(1, 5) -def run_encryption_test(tools, algorithm, mode, use_boxes=False): +def run_encryption_test(tools, algorithm, mode): logging.debug("Running encryption test...") logging.debug("Algorithm: %s", algorithm) logging.debug("Mode: %s", mode) @@ -195,7 +195,7 @@ def run_encryption_test(tools, algorithm, mode, use_boxes=False): iv = get_test_iv(algorithm, mode) expected_ciphertexts = get_test_ciphertexts(algorithm, mode) input_ = BlockInput(key, plaintexts, iv=iv) - actual_ciphertexts = tools.run_encrypt_block(algorithm, mode, input_, use_boxes) + actual_ciphertexts = tools.run_encrypt_block(algorithm, mode, input_) if verify_test_output(actual_ciphertexts, expected_ciphertexts): return TestExitCode.SUCCESS return TestExitCode.FAILURE @@ -205,7 +205,7 @@ def run_encryption_test(tools, algorithm, mode, use_boxes=False): return TestExitCode.ERROR -def run_decryption_test(tools, algorithm, mode, use_boxes=False): +def run_decryption_test(tools, algorithm, mode): logging.debug("Running decryption test...") logging.debug("Algorithm: %s", algorithm) logging.debug("Mode: %s", mode) @@ -216,7 +216,7 @@ def run_decryption_test(tools, algorithm, mode, use_boxes=False): iv = get_test_iv(algorithm, mode) expected_plaintexts = get_test_plaintexts(algorithm, mode) input_ = BlockInput(key, ciphertexts, iv=iv) - actual_plaintexts = tools.run_decrypt_block(algorithm, mode, input_, use_boxes) + actual_plaintexts = tools.run_decrypt_block(algorithm, mode, input_) if verify_test_output(actual_plaintexts, expected_plaintexts): return TestExitCode.SUCCESS return TestExitCode.FAILURE @@ -226,17 +226,13 @@ def run_decryption_test(tools, algorithm, mode, use_boxes=False): return TestExitCode.ERROR -def run_tests(tools_path=(), use_sde=False, use_boxes=False, verbose=False): +def run_tests(tools_path=(), use_sde=False, verbose=False): tools = Tools(tools_path, use_sde=use_sde) exit_codes = [] for algorithm, mode in get_tested_algorithms_and_modes(): - exit_codes.append( - run_encryption_test(tools, algorithm, mode, use_boxes=use_boxes) - ) - exit_codes.append( - run_decryption_test(tools, algorithm, mode, use_boxes=use_boxes) - ) + exit_codes.append(run_encryption_test(tools, algorithm, mode)) + exit_codes.append(run_decryption_test(tools, algorithm, mode)) logging.info("Test exit codes:") logging.info("\tSkipped: %d", exit_codes.count(TestExitCode.SKIPPED)) @@ -272,13 +268,6 @@ def _parse_args(args=None): dest="use_sde", help="use Intel SDE to run the utilities", ) - parser.add_argument( - "--boxes", - "-b", - action="store_true", - dest="use_boxes", - help='use the "boxes" interface', - ) parser.add_argument( "--verbose", "-v", action="store_true", help="verbose log output" ) diff --git a/test/toolkit.py b/test/toolkit.py index b6c3cd3..d14ce23 100644 --- a/test/toolkit.py +++ b/test/toolkit.py @@ -135,32 +135,29 @@ class Tools: return args @staticmethod - def _block_settings_to_args(algorithm, mode, use_boxes=False): - args = [ + def _block_settings_to_args(algorithm, mode): + return [ "--algorithm", str(algorithm), "--mode", str(mode), ] - if use_boxes: - args.append("--use-boxes") - return args @staticmethod - def _build_block_args(algorithm, mode, inputs, use_boxes=False): - args = Tools._block_settings_to_args(algorithm, mode, use_boxes) + def _build_block_args(algorithm, mode, inputs): + args = Tools._block_settings_to_args(algorithm, mode) if isinstance(inputs, Iterable): args.extend(Tools._block_inputs_to_args(iter(inputs))) else: args.extend(inputs.to_args()) return args - def run_encrypt_block(self, algorithm, mode, inputs, use_boxes=False): - args = self._build_block_args(algorithm, mode, inputs, use_boxes) + def run_encrypt_block(self, algorithm, mode, inputs): + args = self._build_block_args(algorithm, mode, inputs) return self.run(self._ENCRYPT_BLOCK, args) - def run_decrypt_block(self, algorithm, mode, inputs, use_boxes=False): - args = self._build_block_args(algorithm, mode, inputs, use_boxes) + def run_decrypt_block(self, algorithm, mode, inputs): + args = self._build_block_args(algorithm, mode, inputs) return self.run(self._DECRYPT_BLOCK, args) @staticmethod -- cgit v1.3