diff options
-rw-r--r-- | include/aesni/algorithm.h | 17 | ||||
-rw-r--r-- | include/aesni/all.h | 3 | ||||
-rw-r--r-- | include/aesni/box.h | 83 | ||||
-rw-r--r-- | include/aesni/mode.h | 19 | ||||
-rw-r--r-- | src/box.c | 442 |
5 files changed, 564 insertions, 0 deletions
diff --git a/include/aesni/algorithm.h b/include/aesni/algorithm.h new file mode 100644 index 0000000..8aacfdc --- /dev/null +++ b/include/aesni/algorithm.h @@ -0,0 +1,17 @@ +/** + * \file + * \author Egor Tensin <Egor.Tensin@gmail.com> + * \date 2015 + * \copyright This file is licensed under the terms of the MIT License. + * See LICENSE.txt for details. + */ + +#pragma once + +typedef enum +{ + AESNI_AES128, + AESNI_AES192, + AESNI_AES256, +} +AesNI_Algorithm; diff --git a/include/aesni/all.h b/include/aesni/all.h index 350e4dd..70f5e7e 100644 --- a/include/aesni/all.h +++ b/include/aesni/all.h @@ -15,8 +15,11 @@ * \defgroup aesni AesNI */ +#include "algorithm.h" #include "block.h" +#include "box.h" #include "buffer.h" #include "data.h" #include "error.h" +#include "mode.h" #include "raw.h" diff --git a/include/aesni/box.h b/include/aesni/box.h new file mode 100644 index 0000000..2ae6533 --- /dev/null +++ b/include/aesni/box.h @@ -0,0 +1,83 @@ +/** + * \file + * \author Egor Tensin <Egor.Tensin@gmail.com> + * \date 2015 + * \copyright This file is licensed under the terms of the MIT License. + * See LICENSE.txt for details. + */ + +#pragma once + +#include "algorithm.h" +#include "data.h" +#include "error.h" +#include "mode.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef union +{ + AesNI_KeySchedule128 aes128_key_schedule; + AesNI_KeySchedule192 aes192_key_schedule; + AesNI_KeySchedule256 aes256_key_schedule; +} +AesNI_EncryptionParams; + +typedef union +{ + AesNI_KeySchedule128 aes128_key_schedule; + AesNI_KeySchedule192 aes192_key_schedule; + AesNI_KeySchedule256 aes256_key_schedule; +} +AesNI_DecryptionParams; + +typedef union +{ + AesNI_Block128 aes_block; +} +AesNI_State; + +typedef union +{ + AesNI_Block128 aes128_key; + AesNI_Block192 aes192_key; + AesNI_Block256 aes256_key; +} +AesNI_AlgorithmParams; + +typedef struct +{ + AesNI_Algorithm algorithm; + AesNI_EncryptionParams encrypt_params; + AesNI_DecryptionParams decrypt_params; + AesNI_Mode mode; + AesNI_State iv; +} +AesNI_Box; + +AesNI_StatusCode aesni_box_init( + AesNI_Box*, + AesNI_Algorithm, + const AesNI_AlgorithmParams*, + AesNI_Mode, + const AesNI_State* iv, + AesNI_ErrorDetails*); + +AesNI_StatusCode aesni_box_encrypt( + AesNI_Box*, + const AesNI_State*, + AesNI_State*, + AesNI_ErrorDetails*); + +AesNI_StatusCode aesni_box_decrypt( + AesNI_Box*, + const AesNI_State*, + AesNI_State*, + AesNI_ErrorDetails*); + +#ifdef __cplusplus +} +#endif diff --git a/include/aesni/mode.h b/include/aesni/mode.h new file mode 100644 index 0000000..fc00e9c --- /dev/null +++ b/include/aesni/mode.h @@ -0,0 +1,19 @@ +/** + * \file + * \author Egor Tensin <Egor.Tensin@gmail.com> + * \date 2015 + * \copyright This file is licensed under the terms of the MIT License. + * See LICENSE.txt for details. + */ + +#pragma once + +typedef enum +{ + AESNI_ECB, + AESNI_CBC, + AESNI_CFB, + AESNI_OFB, + AESNI_CTR, +} +AesNI_Mode; diff --git a/src/box.c b/src/box.c new file mode 100644 index 0000000..01f3b20 --- /dev/null +++ b/src/box.c @@ -0,0 +1,442 @@ +/** + * \file + * \author Egor Tensin <Egor.Tensin@gmail.com> + * \date 2015 + * \copyright This file is licensed under the terms of the MIT License. + * See LICENSE.txt for details. + */ + +#include <aesni/all.h> + +static AesNI_StatusCode aesni_box_xor_state_aes( + AesNI_State* dest, + const AesNI_State* src, + AesNI_ErrorDetails* err_details) +{ + dest->aes_block = _mm_xor_si128(dest->aes_block, src->aes_block); + return AESNI_SUCCESS; +} + +static AesNI_StatusCode aesni_box_encrypt_aes128( + const AesNI_State* input, + const AesNI_EncryptionParams* params, + AesNI_State* output, + AesNI_ErrorDetails* err_details) +{ + output->aes_block = aesni_raw_encrypt_block128( + input->aes_block, + ¶ms->aes128_key_schedule); + return AESNI_SUCCESS; +} + +static AesNI_StatusCode aesni_box_decrypt_aes128( + const AesNI_State* input, + const AesNI_DecryptionParams* params, + AesNI_State* output, + AesNI_ErrorDetails* err_details) +{ + output->aes_block = aesni_raw_decrypt_block128( + input->aes_block, + ¶ms->aes128_key_schedule); + return AESNI_SUCCESS; +} + +static AesNI_StatusCode aesni_box_encrypt_aes192( + const AesNI_State* input, + const AesNI_EncryptionParams* params, + AesNI_State* output, + AesNI_ErrorDetails* err_details) +{ + output->aes_block = aesni_raw_encrypt_block192( + input->aes_block, + ¶ms->aes192_key_schedule); + return AESNI_SUCCESS; +} + +static AesNI_StatusCode aesni_box_decrypt_aes192( + const AesNI_State* input, + const AesNI_DecryptionParams* params, + AesNI_State* output, + AesNI_ErrorDetails* err_details) +{ + output->aes_block = aesni_raw_decrypt_block192( + input->aes_block, + ¶ms->aes192_key_schedule); + return AESNI_SUCCESS; +} + +static AesNI_StatusCode aesni_box_encrypt_aes256( + const AesNI_State* input, + const AesNI_EncryptionParams* params, + AesNI_State* output, + AesNI_ErrorDetails* err_details) +{ + output->aes_block = aesni_raw_encrypt_block256( + input->aes_block, + ¶ms->aes256_key_schedule); + return AESNI_SUCCESS; +} + +static AesNI_StatusCode aesni_box_decrypt_aes256( + const AesNI_State* input, + const AesNI_DecryptionParams* params, + AesNI_State* output, + AesNI_ErrorDetails* err_details) +{ + output->aes_block = aesni_raw_decrypt_block256( + input->aes_block, + ¶ms->aes256_key_schedule); + return AESNI_SUCCESS; +} + +typedef AesNI_StatusCode (*AesNI_BoxEncrypt)( + const AesNI_State*, + const AesNI_EncryptionParams* params, + AesNI_State* output, + AesNI_ErrorDetails* err_details); + +static AesNI_BoxEncrypt aesni_box_encrypt_algorithm[] = +{ + &aesni_box_encrypt_aes128, + &aesni_box_encrypt_aes192, + &aesni_box_encrypt_aes256, +}; + +typedef AesNI_StatusCode (*AesNI_BoxDecrypt)( + const AesNI_State*, + const AesNI_DecryptionParams* params, + AesNI_State* output, + AesNI_ErrorDetails* err_details); + +static AesNI_BoxDecrypt aesni_box_decrypt_algorithm[] = +{ + &aesni_box_decrypt_aes128, + &aesni_box_decrypt_aes192, + &aesni_box_decrypt_aes256, +}; + +typedef AesNI_StatusCode (*AesNI_BoxXorState)( + AesNI_State*, + const AesNI_State*, + AesNI_ErrorDetails*); + +static AesNI_BoxXorState aesni_box_xor_state[] = +{ + &aesni_box_xor_state_aes, + &aesni_box_xor_state_aes, + &aesni_box_xor_state_aes, +}; + +static AesNI_StatusCode aesni_box_init_aes128( + AesNI_Box* box, + const AesNI_AlgorithmParams* algorithm_params, + AesNI_ErrorDetails* err_details) +{ + aesni_raw_expand_key_schedule128( + algorithm_params->aes128_key, + &box->encrypt_params.aes128_key_schedule); + aesni_raw_invert_key_schedule128( + &box->encrypt_params.aes128_key_schedule, + &box->decrypt_params.aes128_key_schedule); + return AESNI_SUCCESS; +} + +static AesNI_StatusCode aesni_box_init_aes192( + AesNI_Box* box, + const AesNI_AlgorithmParams* algorithm_params, + AesNI_ErrorDetails* err_details) +{ + aesni_raw_expand_key_schedule192( + algorithm_params->aes192_key.lo, + algorithm_params->aes192_key.hi, + &box->encrypt_params.aes192_key_schedule); + aesni_raw_invert_key_schedule192( + &box->encrypt_params.aes192_key_schedule, + &box->decrypt_params.aes192_key_schedule); + return AESNI_SUCCESS; +} + +static AesNI_StatusCode aesni_box_init_aes256( + AesNI_Box* box, + const AesNI_AlgorithmParams* algorithm_params, + AesNI_ErrorDetails* err_details) +{ + aesni_raw_expand_key_schedule256( + algorithm_params->aes256_key.lo, + algorithm_params->aes256_key.hi, + &box->encrypt_params.aes256_key_schedule); + aesni_raw_invert_key_schedule256( + &box->encrypt_params.aes256_key_schedule, + &box->decrypt_params.aes256_key_schedule); + return AESNI_SUCCESS; +} + +typedef AesNI_StatusCode (*AesNI_BoxInitializeAlgorithm)( + AesNI_Box*, + const AesNI_AlgorithmParams*, + AesNI_ErrorDetails*); + +static AesNI_BoxInitializeAlgorithm aesni_box_init_algorithm[] = +{ + &aesni_box_init_aes128, + &aesni_box_init_aes192, + &aesni_box_init_aes256, +}; + +AesNI_StatusCode aesni_box_init( + AesNI_Box* box, + AesNI_Algorithm algorithm, + const AesNI_AlgorithmParams* algorithm_params, + AesNI_Mode mode, + const AesNI_State* iv, + AesNI_ErrorDetails* err_details) +{ + AesNI_StatusCode status = AESNI_SUCCESS; + + box->algorithm = algorithm; + if (aesni_is_error(status = aesni_box_init_algorithm[algorithm](box, algorithm_params, err_details))) + return status; + box->mode = mode; + if (iv != NULL) + box->iv = *iv; + + return status; +} + +static AesNI_StatusCode aesni_box_encrypt_ecb( + AesNI_Box* box, + const AesNI_State* input, + AesNI_State* output, + AesNI_ErrorDetails* err_details) +{ + return aesni_box_encrypt_algorithm[box->algorithm]( + input, + &box->encrypt_params, + output, + err_details); +} + +static AesNI_StatusCode aesni_box_encrypt_cbc( + AesNI_Box* box, + const AesNI_State* input, + AesNI_State* output, + AesNI_ErrorDetails* err_details) +{ + AesNI_StatusCode status = AESNI_SUCCESS; + + AesNI_State xored_input = *input; + status = aesni_box_xor_state[box->algorithm]( + &xored_input, + &box->iv, + err_details); + if (aesni_is_error(status)) + return status; + + status = aesni_box_encrypt_algorithm[box->algorithm]( + &xored_input, + &box->encrypt_params, + output, + err_details); + if (aesni_is_error(status)) + return status; + + box->iv = *output; + return status; +} + +static AesNI_StatusCode aesni_box_encrypt_cfb( + AesNI_Box* box, + const AesNI_State* input, + AesNI_State* output, + AesNI_ErrorDetails* err_details) +{ + AesNI_StatusCode status = aesni_box_encrypt_algorithm[box->algorithm]( + &box->iv, + &box->encrypt_params, + output, + err_details); + if (aesni_is_error(status)) + return status; + + status = aesni_box_xor_state[box->algorithm](output, input, err_details); + if (aesni_is_error(status)) + return status; + + box->iv = *output; + return status; +} + +static AesNI_StatusCode aesni_box_encrypt_ofb( + AesNI_Box* box, + const AesNI_State* input, + AesNI_State* output, + AesNI_ErrorDetails* err_details) +{ + AesNI_StatusCode status = aesni_box_encrypt_algorithm[box->algorithm]( + &box->iv, + &box->encrypt_params, + &box->iv, + err_details); + if (aesni_is_error(status)) + return status; + + *output = box->iv; + + status = aesni_box_xor_state[box->algorithm](output, input, err_details); + if (aesni_is_error(status)) + return status; + + return status; +} + +static AesNI_StatusCode aesni_box_encrypt_ctr( + AesNI_Box* box, + const AesNI_State* input, + AesNI_State* output, + AesNI_ErrorDetails* err_details) +{ + return aesni_error_not_implemented(err_details); +} + +typedef AesNI_StatusCode (*AesNI_BoxEncryptMode)( + AesNI_Box*, + const AesNI_State*, + AesNI_State*, + AesNI_ErrorDetails*); + +static AesNI_BoxEncryptMode aesni_box_encrypt_mode[] = +{ + &aesni_box_encrypt_ecb, + &aesni_box_encrypt_cbc, + &aesni_box_encrypt_cfb, + &aesni_box_encrypt_ofb, + &aesni_box_encrypt_ctr, +}; + +AesNI_StatusCode aesni_box_encrypt( + AesNI_Box* box, + const AesNI_State* input, + AesNI_State* output, + AesNI_ErrorDetails* err_details) +{ + return aesni_box_encrypt_mode[box->mode](box, input, output, err_details); +} + +static AesNI_StatusCode aesni_box_decrypt_ecb( + AesNI_Box* box, + const AesNI_State* input, + AesNI_State* output, + AesNI_ErrorDetails* err_details) +{ + return aesni_box_decrypt_algorithm[box->algorithm]( + input, + &box->decrypt_params, + output, + err_details); +} + +static AesNI_StatusCode aesni_box_decrypt_cbc( + AesNI_Box* box, + const AesNI_State* input, + AesNI_State* output, + AesNI_ErrorDetails* err_details) +{ + AesNI_StatusCode status = aesni_box_decrypt_algorithm[box->algorithm]( + input, + &box->decrypt_params, + output, + err_details); + if (aesni_is_error(status)) + return status; + + status = aesni_box_xor_state[box->algorithm]( + output, + &box->iv, + err_details); + if (aesni_is_error(status)) + return status; + + box->iv = *input; + return status; +} + +static AesNI_StatusCode aesni_box_decrypt_cfb( + AesNI_Box* box, + const AesNI_State* input, + AesNI_State* output, + AesNI_ErrorDetails* err_details) +{ + AesNI_StatusCode status = aesni_box_encrypt_algorithm[box->algorithm]( + &box->iv, + &box->encrypt_params, + output, + err_details); + if (aesni_is_error(status)) + return status; + + status = aesni_box_xor_state[box->algorithm]( + output, + input, + err_details); + if (aesni_is_error(status)) + return status; + + box->iv = *input; + + return status; +} + +static AesNI_StatusCode aesni_box_decrypt_ofb( + AesNI_Box* box, + const AesNI_State* input, + AesNI_State* output, + AesNI_ErrorDetails* err_details) +{ + AesNI_StatusCode status = aesni_box_encrypt_algorithm[box->algorithm]( + &box->iv, + &box->encrypt_params, + output, + err_details); + if (aesni_is_error(status)) + return status; + + box->iv = *output; + + status = aesni_box_xor_state[box->algorithm]( + output, + input, + err_details); + if (aesni_is_error(status)) + return status; + + return status; +} + +static AesNI_StatusCode aesni_box_decrypt_ctr( + AesNI_Box* box, + const AesNI_State* input, + AesNI_State* output, + AesNI_ErrorDetails* err_details) +{ + return aesni_error_not_implemented(err_details); +} + +typedef AesNI_BoxEncryptMode AesNI_BoxDecryptMode; + +static AesNI_BoxDecryptMode aesni_box_decrypt_mode[] = +{ + &aesni_box_decrypt_ecb, + &aesni_box_decrypt_cbc, + &aesni_box_decrypt_cfb, + &aesni_box_decrypt_ofb, + &aesni_box_decrypt_ctr, +}; + +AesNI_StatusCode aesni_box_decrypt( + AesNI_Box* box, + const AesNI_State* input, + AesNI_State* output, + AesNI_ErrorDetails* err_details) +{ + return aesni_box_decrypt_mode[box->mode](box, input, output, err_details); +} |