diff options
author | Egor Tensin <Egor.Tensin@gmail.com> | 2015-06-22 01:52:57 +0300 |
---|---|---|
committer | Egor Tensin <Egor.Tensin@gmail.com> | 2015-06-22 01:52:57 +0300 |
commit | 3b705c046c53ee01ba3daed0d0e7468b1a682cbc (patch) | |
tree | 65b5769aaac6b4f950a79cd2690fc30c80923571 /src | |
parent | bugfix & code style (diff) | |
download | aes-tools-3b705c046c53ee01ba3daed0d0e7468b1a682cbc.tar.gz aes-tools-3b705c046c53ee01ba3daed0d0e7468b1a682cbc.zip |
boxes: a number of improvements
* Algorithm interfaces are no longer required to load partial blocks,
the space for which is allocated dynamically.
* Padding schemes are now also separated, perhaps in the future to
become a "box" parameter.
Consequently, algorithm interfaces are no longer required to implement
padding either.
Diffstat (limited to 'src')
-rw-r--r-- | src/box.c | 237 | ||||
-rw-r--r-- | src/box_aes.c | 47 | ||||
-rw-r--r-- | src/error.c | 14 | ||||
-rw-r--r-- | src/padding.c | 87 |
4 files changed, 256 insertions, 129 deletions
@@ -9,6 +9,7 @@ #include <aesni/all.h> #include <stdlib.h> +#include <string.h> static const AesNI_BoxAlgorithmInterface* aesni_box_algorithms[] = { @@ -19,9 +20,9 @@ static const AesNI_BoxAlgorithmInterface* aesni_box_algorithms[] = AesNI_StatusCode aesni_box_init( AesNI_Box* box, - AesNI_BoxAlgorithm algorithm, + AesNI_Algorithm algorithm, const AesNI_BoxAlgorithmParams* algorithm_params, - AesNI_BoxMode mode, + AesNI_Mode mode, const AesNI_BoxBlock* iv, AesNI_ErrorDetails* err_details) { @@ -298,6 +299,92 @@ static AesNI_StatusCode aesni_box_encrypt_buffer_block( return status; } +static AesNI_StatusCode aesni_box_encrypt_buffer_partial_block_with_padding( + AesNI_Box* box, + const void* src, + size_t src_size, + void* dest, + size_t padding_size, + AesNI_ErrorDetails* err_details) +{ + AesNI_StatusCode status = AESNI_SUCCESS; + + size_t block_size; + + if (aesni_is_error(status = box->algorithm->get_block_size( + &block_size, err_details))) + return status; + + void* plaintext_buf = malloc(block_size); + if (plaintext_buf == NULL) + return status = aesni_error_memory_allocation(err_details); + + memcpy(plaintext_buf, src, src_size); + + if (aesni_is_error(status = aesni_fill_with_padding( + AESNI_PADDING_PKCS7, + (char*) plaintext_buf + src_size, + padding_size, + err_details))) + goto FREE_PLAINTEXT_BUF; + + if (aesni_is_error(status = aesni_box_encrypt_buffer_block( + box, plaintext_buf, dest, err_details))) + goto FREE_PLAINTEXT_BUF; + +FREE_PLAINTEXT_BUF: + free(plaintext_buf); + + return status; +} + +static AesNI_StatusCode aesni_box_encrypt_buffer_partial_block( + AesNI_Box* box, + const void* src, + size_t src_size, + void* dest, + AesNI_ErrorDetails* err_details) +{ + AesNI_StatusCode status = AESNI_SUCCESS; + + if (src_size == 0) + return status; + + size_t block_size; + + if (aesni_is_error(status = box->algorithm->get_block_size( + &block_size, err_details))) + return status; + + void* plaintext_buf = malloc(block_size); + if (plaintext_buf == NULL) + return status = aesni_error_memory_allocation(err_details); + + memset(plaintext_buf, 0x00, block_size); + memcpy(plaintext_buf, src, src_size); + + void* ciphertext_buf = malloc(block_size); + if (ciphertext_buf == NULL) + { + status = aesni_error_memory_allocation(err_details); + goto FREE_PLAINTEXT_BUF; + } + + if (aesni_is_error(status = aesni_box_encrypt_buffer_block( + box, plaintext_buf, ciphertext_buf, err_details))) + goto FREE_CIPHERTEXT_BUF; + + memcpy(dest, ciphertext_buf, src_size); + +FREE_CIPHERTEXT_BUF: + free(ciphertext_buf); + +FREE_PLAINTEXT_BUF: + free(plaintext_buf); + + return status; +} + AesNI_StatusCode aesni_box_encrypt_buffer( AesNI_Box* box, const void* src, @@ -320,7 +407,7 @@ AesNI_StatusCode aesni_box_encrypt_buffer( if (dest == NULL) return AESNI_SUCCESS; - if (src == NULL) + if (src == NULL && src_size != 0) return aesni_error_null_argument(err_details, "src"); size_t block_size; @@ -337,48 +424,11 @@ AesNI_StatusCode aesni_box_encrypt_buffer( return status; if (padding_size == 0) - { - const size_t partial_block_size = src_size % block_size; - - if (partial_block_size != 0) - { - AesNI_BoxBlock plaintext; - - if (aesni_is_error(status = box->algorithm->load_partial_block( - &plaintext, src, partial_block_size, err_details))) - return status; - - AesNI_BoxBlock ciphertext; - - if (aesni_is_error(status = aesni_box_encrypt_block( - box, &plaintext, &ciphertext, err_details))) - return status; - - if (aesni_is_error(status = box->algorithm->store_partial_block( - dest, &ciphertext, partial_block_size, err_details))) - return status; - } - } + return aesni_box_encrypt_buffer_partial_block( + box, src, src_size % block_size, dest, err_details); else - { - AesNI_BoxBlock plaintext; - - if (aesni_is_error(status = box->algorithm->load_block_with_padding( - &plaintext, src, src_size % block_size, err_details))) - return status; - - AesNI_BoxBlock ciphertext; - - if (aesni_is_error(status = aesni_box_encrypt_block( - box, &plaintext, &ciphertext, err_details))) - return status; - - if (aesni_is_error(status = box->algorithm->store_block( - dest, &ciphertext, err_details))) - return status; - } - - return status; + return aesni_box_encrypt_buffer_partial_block_with_padding( + box, src, src_size % block_size, dest, padding_size, err_details); } static AesNI_StatusCode aesni_box_get_decrypted_buffer_size( @@ -401,8 +451,8 @@ static AesNI_StatusCode aesni_box_get_decrypted_buffer_size( &block_size, err_details))) return status; - if (src_size % block_size != 0) - return aesni_error_invalid_plaintext_length(err_details); + if (src_size == 0 || src_size % block_size != 0) + return aesni_error_missing_padding(err_details); *dest_size = src_size; *max_padding_size = block_size; @@ -449,6 +499,53 @@ static AesNI_StatusCode aesni_box_decrypt_buffer_block( return status; } +static AesNI_StatusCode aesni_box_decrypt_buffer_partial_block( + AesNI_Box* box, + const void* src, + size_t src_size, + void* dest, + AesNI_ErrorDetails* err_details) +{ + AesNI_StatusCode status = AESNI_SUCCESS; + + if (src_size == 0) + return status; + + size_t block_size; + + if (aesni_is_error(status = box->algorithm->get_block_size( + &block_size, err_details))) + return status; + + void* ciphertext_buf = malloc(block_size); + if (ciphertext_buf == NULL) + return status = aesni_error_memory_allocation(err_details); + + memset(ciphertext_buf, 0x00, block_size); + memcpy(ciphertext_buf, src, src_size); + + void* plaintext_buf = malloc(block_size); + if (plaintext_buf == NULL) + { + status = aesni_error_memory_allocation(err_details); + goto FREE_CIPHERTEXT_BUF; + } + + if (aesni_is_error(status = aesni_box_decrypt_buffer_block( + box, ciphertext_buf, plaintext_buf, err_details))) + goto FREE_PLAINTEXT_BUF; + + memcpy(dest, plaintext_buf, src_size); + +FREE_PLAINTEXT_BUF: + free(plaintext_buf); + +FREE_CIPHERTEXT_BUF: + free(ciphertext_buf); + + return status; +} + AesNI_StatusCode aesni_box_decrypt_buffer( AesNI_Box* box, const void* src, @@ -463,10 +560,10 @@ AesNI_StatusCode aesni_box_decrypt_buffer( return aesni_error_null_argument(err_details, "dest_size"); AesNI_StatusCode status = AESNI_SUCCESS; - size_t padding_size = 0; + size_t max_padding_size = 0; if (aesni_is_error(status = aesni_box_get_decrypted_buffer_size( - box, src_size, dest_size, &padding_size, err_details))) + box, src_size, dest_size, &max_padding_size, err_details))) return status; if (dest == NULL) @@ -487,42 +584,24 @@ AesNI_StatusCode aesni_box_decrypt_buffer( box, src, dest, err_details))) return status; - if (padding_size == 0) + if (max_padding_size == 0) { - const size_t partial_block_size = src_size % block_size; - - if (partial_block_size != 0) - { - AesNI_BoxBlock ciphertext; - - if (aesni_is_error(status = box->algorithm->load_partial_block( - &ciphertext, src, partial_block_size, err_details))) - return status; - - AesNI_BoxBlock plaintext; - - if (aesni_is_error(status = aesni_box_decrypt_block( - box, &ciphertext, &plaintext, err_details))) - return status; - - if (aesni_is_error(status = box->algorithm->store_partial_block( - dest, &plaintext, partial_block_size, err_details))) - return status; - } + return aesni_box_decrypt_buffer_partial_block( + box, src, src_size % block_size, dest, err_details); } else { - padding_size = ((unsigned char*) dest)[-1]; - - if (padding_size > block_size) - return aesni_error_invalid_pkcs7_padding(err_details); - - for (size_t i = 1; i < padding_size; ++i) - if (((unsigned char*) dest)[-1 - i] != padding_size) - return aesni_error_invalid_pkcs7_padding(err_details); + size_t padding_size; + + if (aesni_is_error(status = aesni_extract_padding_size( + AESNI_PADDING_PKCS7, + (char*) dest - block_size, + block_size, + &padding_size, + err_details))) + return status; *dest_size -= padding_size; + return status; } - - return status; } diff --git a/src/box_aes.c b/src/box_aes.c index 49c5326..470e39b 100644 --- a/src/box_aes.c +++ b/src/box_aes.c @@ -92,18 +92,6 @@ static AesNI_StatusCode aesni_box_store_block_aes( return AESNI_SUCCESS; } -static AesNI_StatusCode aesni_box_store_partial_block_aes( - void* dest, - const AesNI_BoxBlock* src, - size_t src_size, - AesNI_ErrorDetails* err_details) -{ - __declspec(align(16)) unsigned char buf[16]; - aesni_store_block128(buf, src->aes_block); - memcpy(dest, buf, src_size); - return AESNI_SUCCESS; -} - static AesNI_StatusCode aesni_box_load_block_aes( AesNI_BoxBlock* dest, const void* src, @@ -113,32 +101,6 @@ static AesNI_StatusCode aesni_box_load_block_aes( return AESNI_SUCCESS; } -static AesNI_StatusCode aesni_box_load_partial_block_aes( - AesNI_BoxBlock* dest, - const void* src, - size_t src_size, - AesNI_ErrorDetails* err_details) -{ - __declspec(align(16)) unsigned char buf[16]; - memset(buf, 0x00, 16); - memcpy(buf, src, src_size); - dest->aes_block = aesni_load_block128_aligned(buf); - return AESNI_SUCCESS; -} - -static AesNI_StatusCode aesni_box_load_block_with_padding_aes( - AesNI_BoxBlock* dest, - const void* src, - size_t src_size, - AesNI_ErrorDetails* err_details) -{ - __declspec(align(16)) unsigned char padding[16]; - memset(padding + src_size, 16 - src_size, 16 - src_size); - memcpy(padding, src, src_size); - dest->aes_block = aesni_load_block128_aligned(padding); - return AESNI_SUCCESS; -} - static AesNI_StatusCode aesni_box_encrypt_block_aes128( const AesNI_BoxBlock* input, const AesNI_BoxEncryptionParams* params, @@ -220,10 +182,7 @@ AesNI_BoxAlgorithmInterface aesni_box_algorithm_aes128 = &aesni_box_next_counter_aes, &aesni_box_get_block_size_aes, &aesni_box_store_block_aes, - &aesni_box_store_partial_block_aes, &aesni_box_load_block_aes, - &aesni_box_load_partial_block_aes, - &aesni_box_load_block_with_padding_aes, }; AesNI_BoxAlgorithmInterface aesni_box_algorithm_aes192 = @@ -235,10 +194,7 @@ AesNI_BoxAlgorithmInterface aesni_box_algorithm_aes192 = &aesni_box_next_counter_aes, &aesni_box_get_block_size_aes, &aesni_box_store_block_aes, - &aesni_box_store_partial_block_aes, &aesni_box_load_block_aes, - &aesni_box_load_partial_block_aes, - &aesni_box_load_block_with_padding_aes, }; AesNI_BoxAlgorithmInterface aesni_box_algorithm_aes256 = @@ -250,8 +206,5 @@ AesNI_BoxAlgorithmInterface aesni_box_algorithm_aes256 = &aesni_box_next_counter_aes, &aesni_box_get_block_size_aes, &aesni_box_store_block_aes, - &aesni_box_store_partial_block_aes, &aesni_box_load_block_aes, - &aesni_box_load_partial_block_aes, - &aesni_box_load_block_with_padding_aes, }; diff --git a/src/error.c b/src/error.c index fd9136a..10550f3 100644 --- a/src/error.c +++ b/src/error.c @@ -26,7 +26,8 @@ static const char* aesni_strerror_messages[] = "Couldn't parse", "Invalid PKCS7 padding (wrong key?)", "Not implemented", - "Invalid plaintext length", + "Missing padding", + "Couldn't allocate memory", }; const char* aesni_strerror(AesNI_StatusCode ec) @@ -105,6 +106,7 @@ static AesNI_ErrorFormatter err_formatters[] = &aesni_format_error_strerror, &aesni_format_not_implemented_error, &aesni_format_error_strerror, + &aesni_format_error_strerror, }; size_t aesni_format_error( @@ -204,8 +206,14 @@ AesNI_StatusCode aesni_error_not_implemented( return status; } -AesNI_StatusCode aesni_error_invalid_plaintext_length( +AesNI_StatusCode aesni_error_missing_padding( + AesNI_ErrorDetails* err_details) +{ + return aesni_make_error(err_details, AESNI_MISSING_PADDING_ERROR); +} + +AesNI_StatusCode aesni_error_memory_allocation( AesNI_ErrorDetails* err_details) { - return aesni_make_error(err_details, AESNI_INVALID_PLAINTEXT_LENGTH_ERROR); + return aesni_make_error(err_details, AESNI_MEMORY_ALLOCATION_ERROR); } diff --git a/src/padding.c b/src/padding.c new file mode 100644 index 0000000..08cafb1 --- /dev/null +++ b/src/padding.c @@ -0,0 +1,87 @@ +/** + * \file + * \author Egor Tensin <Egor.Tensin@gmail.com> + * \date 2015 + * \copyright This file is licensed under the terms of the MIT License. + * See LICENSE.txt for details. + */ + +#include <aesni/all.h> + +#include <stdlib.h> +#include <string.h> + +static AesNI_StatusCode aesni_extract_padding_size_pkcs7( + const void* src, + size_t src_size, + size_t* padding_size, + AesNI_ErrorDetails* err_details) +{ + const unsigned char* cursor = (const unsigned char*) src + src_size - 1; + *padding_size = *cursor; + + for (size_t i = 1; i < *padding_size; ++i) + if (cursor[0 - i] != *padding_size) + return aesni_error_invalid_pkcs7_padding(err_details); + + return AESNI_SUCCESS; +} + +AesNI_StatusCode aesni_extract_padding_size( + AesNI_PaddingMethod method, + const void* src, + size_t src_size, + size_t* padding_size, + AesNI_ErrorDetails* err_details) +{ + assert(src); + assert(padding_size); + + if (src == NULL) + return aesni_error_null_argument(err_details, "src"); + if (padding_size == NULL) + return aesni_error_null_argument(err_details, "padding_size"); + + switch (method) + { + case AESNI_PADDING_PKCS7: + return aesni_extract_padding_size_pkcs7( + src, src_size, padding_size, err_details); + + default: + return aesni_error_not_implemented( + err_details, "unsupported padding method"); + } +} + +static AesNI_StatusCode aesni_fill_with_padding_pkcs7( + void* dest, + size_t padding_size, + AesNI_ErrorDetails* err_details) +{ + memset(dest, padding_size, padding_size); + return AESNI_SUCCESS; +} + +AesNI_StatusCode aesni_fill_with_padding( + AesNI_PaddingMethod method, + void* dest, + size_t padding_size, + AesNI_ErrorDetails* err_details) +{ + assert(dest); + + if (dest == NULL) + return aesni_error_null_argument(err_details, "dest"); + + switch (method) + { + case AESNI_PADDING_PKCS7: + return aesni_fill_with_padding_pkcs7( + dest, padding_size, err_details); + + default: + return aesni_error_not_implemented( + err_details, "unsupported padding method"); + } +} |