From 1cfd6f539a9b495aea3196f55f30e94fa11ab10b Mon Sep 17 00:00:00 2001 From: Romulus Ruja Date: Sun, 19 Dec 2021 21:27:06 +0200 Subject: [PATCH] code refactoring --- include/aes.hh | 67 +++------------ include/aes_auth.hh | 67 +++++++++++++++ include/aes_types.hh | 12 ++- include/cryptography.hh | 1 + src/aes.cc | 27 ++++++ src/aes_auth.cc | 178 ++++++++++++++++++++-------------------- 6 files changed, 203 insertions(+), 149 deletions(-) create mode 100644 include/aes_auth.hh diff --git a/include/aes.hh b/include/aes.hh index 1062bc3..8afd7b4 100644 --- a/include/aes.hh +++ b/include/aes.hh @@ -14,6 +14,7 @@ #include "types.hh" #include "aes_const.hh" + namespace CRYPTO { /** @@ -38,7 +39,7 @@ namespace CRYPTO * @param autoset IV autoset flag * @param ctx AES to enable IV autoset */ - [[deprecated("This function might be removed in further releases; AES_auth_encrypt will automatically generate a new IV on every encryption cycle.")]] void AES_iv_autoset(bool autoset, AES_CRYPTO ctx); + [[deprecated("This function might be removed in further releases;")]] void AES_iv_autoset(bool autoset, AES_CRYPTO ctx); /** * @brief Enable or disable IV append. If IV append enabled, then IV will be put at the beginning of every ciphertext. @@ -46,7 +47,7 @@ namespace CRYPTO * @param append IV append flag * @param ctx AES to enable IV append */ - [[deprecated("This function might be removed in further releases; AES_auth_encrypt will automatically append IV to ciphertext")]] void AES_iv_append(bool append, AES_CRYPTO ctx); + [[deprecated("This function might be removed in further releases;")]] void AES_iv_append(bool append, AES_CRYPTO ctx); /** * @brief Setup initialization vector to be used for encryption / decryption. @@ -55,7 +56,7 @@ namespace CRYPTO * @param ctx AES context to setup iv vector. * @return int 0 if success, -1 if failure. */ - int AES_setup_iv(const BYTE *iv, SIZE ivlen, AES_CRYPTO ctx); + [[deprecated("This function might be removed in further releases;")]] int AES_setup_iv(const BYTE *iv, SIZE ivlen, AES_CRYPTO ctx); /** * @brief Return current encryption key from AES context. @@ -93,7 +94,7 @@ namespace CRYPTO * @param ctx AES context to be initialized. * @return int 0 for success, -1 for failure. */ - [[deprecated("This function initializes AES context in CBC mode and it might be removed in further releases. Use AES_setup key & AES_init_ctx instead.")]] int AES_init(const BYTE *passphrase, SIZE passlen, const BYTE *salt, int rounds, CRYPTO_OP op, AES_CRYPTO ctx); + [[deprecated("This function might be removed in further releases. Use AES_init_ctx instead.")]] int AES_init(const BYTE *passphrase, SIZE passlen, const BYTE *salt, int rounds, CRYPTO_OP op, AES_CRYPTO ctx); /** * @brief Initialize AES context for both encryption and decryption. @@ -106,7 +107,7 @@ namespace CRYPTO * @param ctx AES context to be initialized. * @return int 0 for success, -1 for failure. */ - [[deprecated("This function initializes AES context in CBC mode and it might be removed in further releases. Use AES_setup key & AES_init_ctx instead.")]] int AES_init(const BYTE *passphrase, SIZE passlen, const BYTE *salt, int rounds, AES_CRYPTO ctx); + [[deprecated("This function might be removed in further releases. Use AES_init_ctx instead.")]] int AES_init(const BYTE *passphrase, SIZE passlen, const BYTE *salt, int rounds, AES_CRYPTO ctx); /** * @brief Check if AES context is ready for encryption; @@ -137,31 +138,7 @@ namespace CRYPTO int AES_ctx_dup(AES_CRYPTO dest, const _AES_CRYPTO *src); /** - * @brief Perform AES encryption. - * - * @param ctx Initialized AES context. - * @param in Data to be encrypted. - * @param inlen Data length in bytes. - * @param out Encrypted data (if null, then it is dynamically allocated). - * @param aad Additional Authenticated Data (AAD) - * @param aadlen Additional authenticated data size in bytes - * @return int Size of encrypted data if success, -1 if failure. - */ - int AES_auth_encrypt(AES_CRYPTO ctx, const BYTE *in, SIZE inlen, const BYTE *aad, SIZE aadlen, BYTES *out); - - /** - * @brief Perform AES encryption. - * - * @param ctx Initialized AES context. - * @param in Data to be encrypted. - * @param inlen Data length in bytes. - * @param out Encrypted data (if null, then it is dynamically allocated). - * @return int Size of encrypted data if success, -1 if failure. - */ - int AES_auth_encrypt(AES_CRYPTO ctx, const BYTE *in, SIZE inlen, BYTES *out); - - /** - * @brief Perform AES encryption. + * @brief Perform AES CBC encryption. * * @param ctx Initialized AES context. * @param in Data to be encrypted. @@ -169,34 +146,10 @@ namespace CRYPTO * @param out Encrypted data (if null, then it is dynamically allocated). * @return int Size of encrypted data if success, -1 if failure. */ - [[deprecated("This function uses CBC mode for encryption and might be removed in further releases; Use AES_auth_encrypt instead.")]] int AES_encrypt(AES_CRYPTO ctx, const BYTE *in, SIZE inlen, BYTES *out); - - /** - * @brief Perform AES encryption. - * - * @param ctx Initialized AES context. - * @param in Data to be encrypted. - * @param inlen Data length in bytes. - * @param out Encrypted data (if null, then it is dynamically allocated). - * @param aad Additional Authenticated Data (AAD) - * @param aadlen Additional authenticated data size in bytes - * @return int Size of encrypted data if success, -1 if failure. - */ - int AES_auth_decrypt(AES_CRYPTO ctx, const BYTE *in, SIZE inlen, const BYTE *aad, SIZE aadlen, BYTES *out); - - /** - * @brief Perform AES decryption. - * - * @param ctx Initialized AES context. - * @param in Data to be decrypted. - * @param inlen Data length in bytes. - * @param out Decrypted data (if null, then it is dynamically allocated). - * @return int Size of decrypted data if success, -1 if failure. - */ - int AES_auth_decrypt(AES_CRYPTO ctx, const BYTE *in, SIZE inlen, BYTES *out); + [[deprecated("This function might be removed in further releases;")]] int AES_encrypt(AES_CRYPTO ctx, const BYTE *in, SIZE inlen, BYTES *out); /** - * @brief Perform AES decryption. + * @brief Perform AES CBC decryption. * * @param ctx Initialized AES context. * @param in Data to be decrypted. @@ -204,7 +157,7 @@ namespace CRYPTO * @param out Decrypted data (if null, then it is dynamically allocated). * @return int Size of decrypted data if success, -1 if failure. */ - [[deprecated("This function uses CBC mode for decryption and might be removed in further releases; Use AES_auth_decrypt instead.")]] int AES_decrypt(AES_CRYPTO ctx, const BYTE *in, SIZE inlen, BYTES *out); + [[deprecated("This function might be removed in further releases;")]] int AES_decrypt(AES_CRYPTO ctx, const BYTE *in, SIZE inlen, BYTES *out); /** * @brief Frees memory allocated for AES context. diff --git a/include/aes_auth.hh b/include/aes_auth.hh new file mode 100644 index 0000000..a153add --- /dev/null +++ b/include/aes_auth.hh @@ -0,0 +1,67 @@ +/** + * @file aes_auth.hh + * @author Romulus-Emanuel Ruja + * @brief This file contains function definitions for AES GCM + * @date 2021-12-19 + * + * @copyright Copyright (c) 2021 MIT License + * + */ + + +#include "aes_const.hh" +#include "types.hh" + + +namespace CRYPTO +{ + /** + * @brief Perform AES GCM encryption. + * + * @param ctx Initialized AES context. + * @param in Data to be encrypted. + * @param inlen Data length in bytes. + * @param out Encrypted data (if null, then it is dynamically allocated). + * @param aad Additional Authenticated Data (AAD) + * @param aadlen Additional authenticated data size in bytes + * @return int Size of encrypted data if success, -1 if failure. + */ + int AES_auth_encrypt(AES_CRYPTO ctx, const BYTE *in, SIZE inlen, BYTES *out); + + /** + * @brief Perform AES GCM encryption. + * + * @param ctx Initialized AES context. + * @param in Data to be encrypted. + * @param inlen Data length in bytes. + * @param out Encrypted data (if null, then it is dynamically allocated). + * @param aad Additional Authenticated Data (AAD) + * @param aadlen Additional authenticated data size in bytes + * @return int Size of encrypted data if success, -1 if failure. + */ + int AES_auth_encrypt(AES_CRYPTO ctx, const BYTE *in, SIZE inlen, const BYTE *aad, SIZE aadlen, BYTES *out); + + /** + * @brief Perform AES GCM decryption. + * + * @param ctx Initialized AES context. + * @param in Data to be decrypted. + * @param inlen Data length in bytes. + * @param out Decrypted data (if null, then it is dynamically allocated). + * @param aad Additional Authenticated Data (AAD) + * @param aadlen Additional authenticated data size in bytes + * @return int Size of decrypted data if success, -1 if failure. + */ + int AES_auth_decrypt(AES_CRYPTO ctx, const BYTE *in, SIZE inlen, const BYTE *aad, SIZE aadlen, BYTES *out); + + /** + * @brief Perform AES GCM decryption. + * + * @param ctx Initialized AES context. + * @param in Data to be decrypted. + * @param inlen Data length in bytes. + * @param out Decrypted data (if null, then it is dynamically allocated). + * @return int Size of decrypted data if success, -1 if failure. + */ + int AES_auth_decrypt(AES_CRYPTO ctx, const BYTE *in, SIZE inlen, BYTES *out); +} diff --git a/include/aes_types.hh b/include/aes_types.hh index d16907b..c150a1e 100644 --- a/include/aes_types.hh +++ b/include/aes_types.hh @@ -8,13 +8,19 @@ struct _AES_CRYPTO { BYTES key; - BYTES iv; + // single IV used AES_encrypt & AES_decrypt functions; + [[deprecated("It might be removed in further releases;")]] BYTES iv; + + // distinct contexts are used for encryption & decryption EVP_CIPHER_CTX *encr; EVP_CIPHER_CTX *decr; + + // track context initialization for encryption & decryption bool encrinit; bool decrinit; - bool iv_autoset; - bool iv_append; + + [[deprecated("It might be removed in further releases;")]] bool iv_autoset; + [[deprecated("It might be removed in further releases;")]] bool iv_append; _AES_CRYPTO *ref; }; diff --git a/include/cryptography.hh b/include/cryptography.hh index 5d6f66f..7d1eef3 100644 --- a/include/cryptography.hh +++ b/include/cryptography.hh @@ -11,6 +11,7 @@ #include "aes_const.hh" #include "aes.hh" +#include "aes_auth.hh" #include "base64.hh" #include "rsa.hh" #include "random.hh" diff --git a/src/aes.cc b/src/aes.cc index 5a29b72..2cbfb8f 100644 --- a/src/aes.cc +++ b/src/aes.cc @@ -119,6 +119,33 @@ int CRYPTO::AES_read_iv(const _AES_CRYPTO *ctx, SIZE ivlen, BYTES *iv) return 0; } +int CRYPTO::AES_init_ctx(CRYPTO_OP op, AES_CRYPTO ctx) +{ + if ((op == ENCRYPT and not ctx->encrinit) or + (op == DECRYPT and not ctx->decrinit)) + { + EVP_CIPHER_CTX **aes = 0; + + op == ENCRYPT and (aes = &ctx->encr); + op == DECRYPT and (aes = &ctx->decr); + + if (not(*aes or (*aes = EVP_CIPHER_CTX_new()))) + { + return -1; + } + + if (EVP_CIPHER_CTX_init(*aes) <= 0) + { + return -1; + } + + op == ENCRYPT and (ctx->encrinit = 1); + op == DECRYPT and (ctx->decrinit = 1); + } + + return 0; +} + int CRYPTO::AES_init(const BYTE *passphrase, SIZE passlen, const BYTE *salt, int rounds, CRYPTO_OP op, AES_CRYPTO ctx) { if (not ctx) diff --git a/src/aes_auth.cc b/src/aes_auth.cc index 03573c5..e9301a6 100644 --- a/src/aes_auth.cc +++ b/src/aes_auth.cc @@ -1,5 +1,5 @@ #include "aes_types.hh" -#include "aes.hh" +#include "aes_auth.hh" #include "random.hh" #include @@ -7,38 +7,29 @@ #include -int CRYPTO::AES_init_ctx(CRYPTO_OP op, AES_CRYPTO ctx) +int CRYPTO::AES_auth_encrypt(AES_CRYPTO ctx, const BYTE *in, SIZE inlen, const BYTE *aad, SIZE aadlen, BYTES *out) { - if ((op == ENCRYPT and not ctx->encrinit) or - (op == DECRYPT and not ctx->decrinit)) - { - EVP_CIPHER_CTX **aes = 0; + BYTES iv = new BYTE[AES_GCM_IV_SIZE + 1]; + BYTES tag = new BYTE[AES_GCM_TAG_SIZE + 1]; - op == ENCRYPT and (aes = &ctx->encr); - op == DECRYPT and (aes = &ctx->decr); + int len; + int f_len; - if (not(*aes or (*aes = EVP_CIPHER_CTX_new()))) - { - return -1; - } + int output_size = AES_GCM_TAG_SIZE + AES_GCM_IV_SIZE + inlen; + BYTES outptr; - if (EVP_CIPHER_CTX_init(*aes) <= 0) - { - return -1; - } + int ret = 0; - op == ENCRYPT and (ctx->encrinit = 1); - op == DECRYPT and (ctx->decrinit = 1); + if (not tag or not iv) + { + ret = -1; + goto cleanup; } - return 0; -} - -int CRYPTO::AES_auth_encrypt(AES_CRYPTO ctx, const BYTE *in, SIZE inlen, const BYTE *aad, SIZE aadlen, BYTES *out) -{ if (1 != EVP_EncryptInit_ex(ctx->encr, EVP_aes_256_gcm(), NULL, NULL, NULL)) { - return -1; + ret = -1; + goto cleanup; } #if AES_GCM_IV_SIZE != AES_GCM_DEFAULT_IV_SIZE @@ -47,80 +38,72 @@ int CRYPTO::AES_auth_encrypt(AES_CRYPTO ctx, const BYTE *in, SIZE inlen, const B if (1 != EVP_CIPHER_CTX_ctrl(ctx->encr, EVP_CTRL_GCM_SET_IVLEN, AES_GCM_IV_SIZE, NULL)) { - return -1; + ret = -1; + goto cleanup; } #endif // new IV generated on every encryption cycle; + rand_bytes(AES_GCM_IV_SIZE, &iv); - if (not ctx->iv and not(ctx->iv = new BYTE[AES_GCM_IV_SIZE + 1])) - { - return -1; - } - - rand_bytes(AES_GCM_IV_SIZE, &ctx->iv); - - if (1 != EVP_EncryptInit_ex(ctx->encr, NULL, NULL, ctx->key, ctx->iv)) + if (1 != EVP_EncryptInit_ex(ctx->encr, NULL, NULL, ctx->key, iv)) { - return -1; + ret = -1; + goto cleanup; } - int len; - if (aad and aadlen) { if (1 != EVP_EncryptUpdate(ctx->encr, NULL, &len, aad, aadlen)) { - return -1; + ret = -1; + goto cleanup; } } // allocate memory for output data if required - // in GCM, plaintext size = ciphertext size - - int output_size = AES_GCM_TAG_SIZE + AES_GCM_IV_SIZE + inlen; + // plaintext size = ciphertext size if (not *out and not(*out = new BYTE[output_size + 1])) { - return -1; + ret = -1; + goto cleanup; } - BYTES outptr = *out; + outptr = *out; if (1 != EVP_EncryptUpdate(ctx->encr, outptr + AES_GCM_IV_SIZE, &len, in, inlen)) { - return -1; + ret = -1; + goto cleanup; } - int f_len; - if (1 != EVP_EncryptFinal_ex(ctx->encr, outptr + len + AES_GCM_IV_SIZE, &f_len)) { - return -1; - } - - BYTES tag = new BYTE[AES_GCM_TAG_SIZE + 1]; - - if (not tag) - { - return -1; + ret = -1; + goto cleanup; } if (1 != EVP_CIPHER_CTX_ctrl(ctx->encr, EVP_CTRL_GCM_GET_TAG, AES_GCM_TAG_SIZE, tag)) { - return -1; + ret = -1; + goto cleanup; } - memcpy(outptr, ctx->iv, AES_GCM_IV_SIZE); + memcpy(outptr, iv, AES_GCM_IV_SIZE); memcpy(outptr + AES_GCM_IV_SIZE + f_len + len, tag, AES_GCM_TAG_SIZE); +cleanup: delete[] tag; + delete[] iv; + tag = 0; + iv = 0; EVP_CIPHER_CTX_reset(ctx->encr); - return f_len + len + AES_GCM_IV_SIZE + AES_GCM_TAG_SIZE; + return ret < 0 ? -1 : f_len + len + AES_GCM_IV_SIZE + AES_GCM_TAG_SIZE; } int CRYPTO::AES_auth_encrypt(AES_CRYPTO ctx, const BYTE *in, SIZE inlen, BYTES *out) @@ -130,74 +113,91 @@ int CRYPTO::AES_auth_encrypt(AES_CRYPTO ctx, const BYTE *in, SIZE inlen, BYTES * int CRYPTO::AES_auth_decrypt(AES_CRYPTO ctx, const BYTE *in, SIZE inlen, const BYTE *aad, SIZE aadlen, BYTES *out) { + BYTES iv = new BYTE[AES_GCM_IV_SIZE + 1]; + BYTES tag = new BYTE[AES_GCM_TAG_SIZE + 1]; + + int len; + int f_len; + + // size of decrypted data = size of encrypted data + int decrlen = inlen - AES_GCM_IV_SIZE - AES_GCM_TAG_SIZE; + + int ret = 0; + + if (not tag or not iv) + { + ret = -1; + goto cleanup; + } + if (1 != EVP_DecryptInit_ex(ctx->decr, EVP_aes_256_gcm(), NULL, NULL, NULL)) { - return -1; + ret = -1; + goto cleanup; } #if AES_GCM_IV_SIZE != AES_GCM_DEFAULT_IV_SIZE if (1 != EVP_CIPHER_CTX_ctrl(ctx->decr, EVP_CTRL_GCM_SET_IVLEN, AES_GCM_IV_SIZE, NULL)) { - return -1; + ret = -1; + goto cleanup; } #endif - if (not ctx->iv and not(ctx->iv = new BYTE[AES_GCM_IV_SIZE + 1])) - { - return -1; - } - - memcpy(ctx->iv, in, AES_GCM_IV_SIZE); + memcpy(iv, in, AES_GCM_IV_SIZE); - if (1 != EVP_DecryptInit_ex(ctx->decr, NULL, NULL, ctx->key, ctx->iv)) + if (1 != EVP_DecryptInit_ex(ctx->decr, NULL, NULL, ctx->key, iv)) { - return -1; + ret = -1; + goto cleanup; } - int len; - - if (1 != EVP_DecryptUpdate(ctx->decr, NULL, &len, aad, aadlen)) + if (aad and aadlen) { - return -1; + if (1 != EVP_DecryptUpdate(ctx->decr, NULL, &len, aad, aadlen)) + { + ret = -1; + goto cleanup; + } } - // size of decrypted data = size of encrypted data - int decrlen = inlen - AES_GCM_IV_SIZE - AES_GCM_TAG_SIZE; - if (not *out and not(*out = new BYTE[decrlen + 1])) { - return -1; + ret = -1; + goto cleanup; } - if(1 != EVP_DecryptUpdate(ctx->decr, *out, &len, in + AES_GCM_IV_SIZE, decrlen)) + if (1 != EVP_DecryptUpdate(ctx->decr, *out, &len, in + AES_GCM_IV_SIZE, decrlen)) { - return -1; + ret = -1; + goto cleanup; } - BYTES tag = new BYTE[AES_GCM_TAG_SIZE + 1]; + memcpy(tag, in + inlen - AES_GCM_TAG_SIZE, AES_GCM_TAG_SIZE); - if(not tag) + if (1 != EVP_CIPHER_CTX_ctrl(ctx->decr, EVP_CTRL_GCM_SET_TAG, AES_GCM_TAG_SIZE, tag)) { - return -1; + ret = -1; + goto cleanup; } - memcpy(tag, in + inlen - AES_GCM_TAG_SIZE, AES_GCM_TAG_SIZE); - - if(1 != EVP_CIPHER_CTX_ctrl(ctx->decr, EVP_CTRL_GCM_SET_TAG, AES_GCM_TAG_SIZE, tag)) + if (1 != EVP_DecryptFinal_ex(ctx->decr, *out + len, &f_len)) { - return -1; + ret = -1; + goto cleanup; } - int f_len; +cleanup: - if(1 != EVP_DecryptFinal_ex(ctx->decr, *out + len, &f_len)) - { - return -1; - } + delete[] tag; + delete[] iv; + + tag = 0; + iv = 0; EVP_CIPHER_CTX_reset(ctx->decr); - return len + f_len; + return ret < 0 ? -1 : len + f_len; } int CRYPTO::AES_auth_decrypt(AES_CRYPTO ctx, const BYTE *in, SIZE inlen, BYTES *out)