From c11a0bd2abef4c9536432664600ce6b6ed6ccbe4 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Mon, 15 Jun 2015 01:04:48 +0300 Subject: error handling refactoring + more docs --- include/aesni/buffer.h | 8 +-- include/aesni/error.h | 120 ++++++++++++++++++++++++++++++++---- src/buffer.c | 57 +++++------------ src/error.c | 41 +++++------- utils/cxx/include/aesnixx/error.hpp | 2 +- 5 files changed, 144 insertions(+), 84 deletions(-) diff --git a/include/aesni/buffer.h b/include/aesni/buffer.h index 6222f4f..fff616f 100644 --- a/include/aesni/buffer.h +++ b/include/aesni/buffer.h @@ -18,20 +18,20 @@ extern "C" { #endif -int aesni_encrypt_buffer_ecb128( +AesNI_StatusCode aesni_encrypt_buffer_ecb128( const void* src, size_t src_size, void* dest, size_t* dest_size, AesNI_KeySchedule128* key_schedule, - AesNI_ErrorDetails*); -int aesni_decrypt_buffer_ecb128( + AesNI_ErrorDetails* err_details); +AesNI_StatusCode aesni_decrypt_buffer_ecb128( const void* src, size_t src_size, void* dest, size_t* dest_size, AesNI_KeySchedule128* inverted_schedule, - AesNI_ErrorDetails*); + AesNI_ErrorDetails* err_details); #ifdef __cplusplus } diff --git a/include/aesni/error.h b/include/aesni/error.h index 91bf168..56a1da1 100644 --- a/include/aesni/error.h +++ b/include/aesni/error.h @@ -9,6 +9,28 @@ #pragma once +/** + * \defgroup aesni_error_handling Error handling + * \ingroup aesni + * \brief Error data structures and formatting functions. + * + * Some library functions cannot fail, which is simple. + * Other functions return an error code. + * You can check if a function exited with an error by passing the returned + * error code to aesni_is_error(). + * + * Some possibly-may-fail functions accept a pointer to an "error details" + * structure. + * This pointer can always be `NULL`. + * In this case, simply an error code is returned. + * Otherwise, the error details structure is filled with appropriate info about + * the error, possibly including a few details like invalid arguments names, + * etc. + * + * You can format an error details structure using the formatting functions. + * \{ + */ + #include #ifdef __cplusplus @@ -16,45 +38,117 @@ extern "C" { #endif +/** + * \brief API status codes. + */ typedef enum { - AESNI_ERROR_SUCCESS, + AESNI_SUCCESS, ///< Indicates an operation + + AESNI_ERROR_NULL_ARGUMENT, ///< Invalid argument value NULL - AESNI_ERROR_NULL_ARGUMENT, + AESNI_ERROR_INVALID_PKCS7_PADDING, ///< Invalid PKCS7 padding +} +AesNI_StatusCode; - AESNI_ERROR_INVALID_PKCS7_PADDING, +static __inline int aesni_is_error(AesNI_StatusCode ec) +{ + return ec != AESNI_SUCCESS; } -AesNI_ErrorCode; -const char* aesni_strerror(AesNI_ErrorCode); +/** + * \brief Retrieves a simple error message for an error code. + * + * For example, + * \code{.c} + * printf("%s\n", aesni_strerror(AESNI_ERROR_NULL_ARGUMENT)); + * \endcode + * would print + * \code + * Invalid argument value NULL + * \endcode + * + * \param[in] ec The error code. + * \return A pointer to a statically-allocated C string. + */ +const char* aesni_strerror(AesNI_StatusCode ec); +/** + * \brief Stores error details: error code & possibly a few parameters. + */ typedef struct { - AesNI_ErrorCode ec; + AesNI_StatusCode ec; ///< Error code union { struct { - char arg_name[32]; + char arg_name[32]; ///< Name of the NULL argument } - null_arg; + null_arg; ///< `NULL` argument error parameters } params; } AesNI_ErrorDetails; -static __inline AesNI_ErrorCode aesni_get_error_code(const AesNI_ErrorDetails* err_details) +/** + * \brief Extracts an error code from error details. + * + * \param[in] err_details The error details structure. Must not be `NULL`. + * \return The error code stored in the error details. + */ +static __inline AesNI_StatusCode aesni_get_error_code( + const AesNI_ErrorDetails* err_details) { return err_details->ec; } -size_t aesni_format_error(const AesNI_ErrorDetails*, char*, size_t); +/** + * \brief Formats a pretty error message, including error parameters. + * + * \param[in] err_details The pointer to error details. Must not be `NULL`. + * \param[out] dest The pointer to the destination string buffer. + * \param[in] dest_size The size of the destination buffer, in bytes. + * \return If `dest` is NULL, the number of bytes required to store the full + * error message, and the number of characters written (excluding the + * terminating '\0' character) otherwise. + */ +size_t aesni_format_error( + const AesNI_ErrorDetails* err_details, + char* dest, + size_t dest_size); -void aesni_make_error_success(AesNI_ErrorDetails*); -void aesni_make_error_null_argument(AesNI_ErrorDetails*, const char* arg_name); -void aesni_make_error_invalid_pkcs7_padding(AesNI_ErrorDetails*); +/** + * \brief Initializes error details structure. + * + * \param[out] err_details The error details structure to fill. + */ +AesNI_StatusCode aesni_make_error_success( + AesNI_ErrorDetails* err_details); + +/** + * \brief Builds error details from a `NULL` argument error. + * + * \param[out] err_details The error details structure to fill. + * \param[in] arg_name The `NULL` argument name. Must not be `NULL`. + */ +AesNI_StatusCode aesni_make_error_null_argument( + AesNI_ErrorDetails* err_details, + const char* arg_name); + +/** + * \brief Builds error details from an invalid PKCS7 padding error. + * + * \param[out] err_details The error details structure to fill. + */ +AesNI_StatusCode aesni_make_error_invalid_pkcs7_padding( + AesNI_ErrorDetails* err_details); #ifdef __cplusplus } #endif + +/** + * \} + */ diff --git a/src/buffer.c b/src/buffer.c index 71ebad2..74ff519 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -13,7 +13,7 @@ static unsigned char FULL_BLOCK_PADDING[16] = { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 }; -int aesni_encrypt_buffer_ecb128( +AesNI_StatusCode aesni_encrypt_buffer_ecb128( const void* src, size_t src_size, void* dest, @@ -22,29 +22,18 @@ int aesni_encrypt_buffer_ecb128( AesNI_ErrorDetails* err_details) { if (dest_size == NULL) - { - aesni_make_error_null_argument(err_details, "dest_size"); - return 1; - } + return aesni_make_error_null_argument(err_details, "dest_size"); const size_t rem_size = src_size % 16; const size_t padding_size = 16 - rem_size; *dest_size = src_size + padding_size; if (dest == NULL) - return 0; - + return AESNI_SUCCESS; if (src == NULL) - { - aesni_make_error_null_argument(err_details, "src"); - return 1; - } - + return aesni_make_error_null_argument(err_details, "src"); if (key_schedule == NULL) - { - aesni_make_error_null_argument(err_details, "key_schedule"); - return 1; - } + return aesni_make_error_null_argument(err_details, "key_schedule"); const size_t src_len = src_size / 16; @@ -71,7 +60,7 @@ int aesni_encrypt_buffer_ecb128( AesNI_Block128 ciphertext = aesni_encrypt_block_ecb128(plaintext, key_schedule); aesni_store_block128(dest, ciphertext); - return 0; + return AESNI_SUCCESS; } static unsigned char get_pkcs7_padding_size(const unsigned char* padding) @@ -86,7 +75,7 @@ static unsigned char get_pkcs7_padding_size(const unsigned char* padding) return padding[15]; } -int aesni_decrypt_buffer_ecb128( +AesNI_StatusCode aesni_decrypt_buffer_ecb128( const void* src, size_t src_size, void* dest, @@ -95,27 +84,16 @@ int aesni_decrypt_buffer_ecb128( AesNI_ErrorDetails* err_details) { if (dest_size == NULL) - { - aesni_make_error_null_argument(err_details, "dest_size"); - return 1; - } + return aesni_make_error_null_argument(err_details, "dest_size"); *dest_size = src_size; if (dest == NULL) return 0; - if (src == NULL) - { - aesni_make_error_null_argument(err_details, "src"); - return 1; - } - + return aesni_make_error_null_argument(err_details, "src"); if (inverted_schedule == NULL) - { - aesni_make_error_null_argument(err_details, "inverted_schedule"); - return 1; - } + return aesni_make_error_null_argument(err_details, "inverted_schedule"); const size_t src_len = src_size / 16; @@ -134,14 +112,9 @@ int aesni_decrypt_buffer_ecb128( unsigned char padding_size = get_pkcs7_padding_size(padding); if (padding_size == 0) - { - aesni_make_error_invalid_pkcs7_padding(err_details); - return 1; - } - else - { - memcpy(dest, padding, 16 - padding_size); - *dest_size -= padding_size; - return 0; - } + return aesni_make_error_invalid_pkcs7_padding(err_details); + + memcpy(dest, padding, 16 - padding_size); + *dest_size -= padding_size; + return AESNI_SUCCESS; } diff --git a/src/error.c b/src/error.c index e52cd4d..034aa72 100644 --- a/src/error.c +++ b/src/error.c @@ -20,17 +20,17 @@ static const char* err_msgs[] = "Invalid PKCS7 padding (wrong key?)", }; -const char* aesni_strerror(AesNI_ErrorCode ec) +const char* aesni_strerror(AesNI_StatusCode ec) { return err_msgs[ec]; } -static size_t aesni_format_error_simple( +static size_t aesni_format_error_strerror( const AesNI_ErrorDetails* err_details,\ char* dest, size_t dest_size) { - const AesNI_ErrorCode ec = aesni_get_error_code(err_details); + const AesNI_StatusCode ec = aesni_get_error_code(err_details); const char* const msg = aesni_strerror(ec); if (dest == NULL && dest_size == 0) @@ -60,9 +60,9 @@ typedef size_t (*AesNI_ErrorFormatter)(const AesNI_ErrorDetails*, char*, size_t) static AesNI_ErrorFormatter err_formatters[] = { - &aesni_format_error_simple, + &aesni_format_error_strerror, &aesni_format_error_null_argument, - &aesni_format_error_simple, + &aesni_format_error_strerror, }; size_t aesni_format_error( @@ -75,44 +75,37 @@ size_t aesni_format_error( return err_formatters[err_details->ec](err_details, dest, dest_size); } -static void aesni_make_error( +static AesNI_StatusCode aesni_make_error( AesNI_ErrorDetails* err_details, - AesNI_ErrorCode ec) + AesNI_StatusCode ec) { if (err_details == NULL) - return; + return ec; - err_details->ec = ec; + return err_details->ec = ec; } -void aesni_make_error_success( +AesNI_StatusCode aesni_make_error_success( AesNI_ErrorDetails* err_details) { - if (err_details == NULL) - return; - - aesni_make_error(err_details, AESNI_ERROR_SUCCESS); + return aesni_make_error(err_details, AESNI_SUCCESS); } -void aesni_make_error_null_argument( +AesNI_StatusCode aesni_make_error_null_argument( AesNI_ErrorDetails* err_details, const char* arg_name) { - if (err_details == NULL) - return; - - aesni_make_error(err_details, AESNI_ERROR_NULL_ARGUMENT); + AesNI_StatusCode status = aesni_make_error(err_details, AESNI_ERROR_NULL_ARGUMENT); const size_t arg_name_size = sizeof(err_details->params.null_arg.arg_name); strncpy(err_details->params.null_arg.arg_name, arg_name, arg_name_size); err_details->params.null_arg.arg_name[arg_name_size - 1] = '\0'; + + return status; } -void aesni_make_error_invalid_pkcs7_padding( +AesNI_StatusCode aesni_make_error_invalid_pkcs7_padding( AesNI_ErrorDetails* err_details) { - if (err_details == NULL) - return; - - aesni_make_error(err_details, AESNI_ERROR_INVALID_PKCS7_PADDING); + return aesni_make_error(err_details, AESNI_ERROR_INVALID_PKCS7_PADDING); } diff --git a/utils/cxx/include/aesnixx/error.hpp b/utils/cxx/include/aesnixx/error.hpp index db390ea..81e63c6 100644 --- a/utils/cxx/include/aesnixx/error.hpp +++ b/utils/cxx/include/aesnixx/error.hpp @@ -28,7 +28,7 @@ namespace aesni ~ErrorDetailsThrowsInDestructor() { - if (aesni_get_error_code(get()) != AESNI_ERROR_SUCCESS) + if (aesni_is_error(aesni_get_error_code(get()))) { std::vector msg; msg.resize(aesni_format_error(get(), NULL, 0)); -- cgit v1.2.3