From e046b6bdfe61227ebf8e4e392d1c40697eb5663f Mon Sep 17 00:00:00 2001 From: Jichen Xu Date: Tue, 26 Jul 2022 15:47:09 +0900 Subject: [PATCH] refactor: move aes features to aes.h(c) Move aes features from security.h(c) to aes.h(c), fix correlated includes. This commit bring no new feature to the codebase. Refs: #56 --- src/admin.c | 1 + src/include/aes.h | 51 ++++++++ src/include/security.h | 22 ---- src/libpgmoneta/aes.c | 204 ++++++++++++++++++++++++++++++++ src/libpgmoneta/configuration.c | 1 + src/libpgmoneta/security.c | 170 -------------------------- 6 files changed, 257 insertions(+), 192 deletions(-) create mode 100644 src/include/aes.h create mode 100644 src/libpgmoneta/aes.c diff --git a/src/admin.c b/src/admin.c index dea8608c..91df1904 100644 --- a/src/admin.c +++ b/src/admin.c @@ -30,6 +30,7 @@ #include #include #include +#include #include /* system */ diff --git a/src/include/aes.h b/src/include/aes.h new file mode 100644 index 00000000..a72fea33 --- /dev/null +++ b/src/include/aes.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2022 Red Hat + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may + * be used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +/** + * Encrypt a string + * @param plaintext The string + * @param password The master password + * @param ciphertext The ciphertext output + * @param ciphertext_length The length of the ciphertext + * @return 0 upon success, otherwise 1 + */ +int +pgmoneta_encrypt(char* plaintext, char* password, char** ciphertext, int* ciphertext_length); + +/** + * Decrypt a string + * @param ciphertext The string + * @param ciphertext_length The length of the ciphertext + * @param password The master password + * @param plaintext The plaintext output + * @return 0 upon success, otherwise 1 + */ +int +pgmoneta_decrypt(char* ciphertext, int ciphertext_length, char* password, char** plaintext); \ No newline at end of file diff --git a/src/include/security.h b/src/include/security.h index 1ce1c122..c7183f82 100644 --- a/src/include/security.h +++ b/src/include/security.h @@ -80,28 +80,6 @@ pgmoneta_remote_management_scram_sha256(char* username, char* password, int serv int pgmoneta_get_master_key(char** masterkey); -/** - * Encrypt a string - * @param plaintext The string - * @param password The master password - * @param ciphertext The ciphertext output - * @param ciphertext_length The length of the ciphertext - * @return 0 upon success, otherwise 1 - */ -int -pgmoneta_encrypt(char* plaintext, char* password, char** ciphertext, int* ciphertext_length); - -/** - * Decrypt a string - * @param ciphertext The string - * @param ciphertext_length The length of the ciphertext - * @param password The master password - * @param plaintext The plaintext output - * @return 0 upon success, otherwise 1 - */ -int -pgmoneta_decrypt(char* ciphertext, int ciphertext_length, char* password, char** plaintext); - /** * Is the TLS configuration valid * @return 0 upon success, otherwise 1 diff --git a/src/libpgmoneta/aes.c b/src/libpgmoneta/aes.c new file mode 100644 index 00000000..8f77bcd2 --- /dev/null +++ b/src/libpgmoneta/aes.c @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2022 Red Hat + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may + * be used to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +static int derive_key_iv(char* password, unsigned char* key, unsigned char* iv); +static int aes_encrypt(char* plaintext, unsigned char* key, unsigned char* iv, char** ciphertext, int* ciphertext_length); +static int aes_decrypt(char* ciphertext, int ciphertext_length, unsigned char* key, unsigned char* iv, char** plaintext); + +// [public] +int +pgmoneta_encrypt(char* plaintext, char* password, char** ciphertext, int* ciphertext_length) +{ + unsigned char key[EVP_MAX_KEY_LENGTH]; + unsigned char iv[EVP_MAX_IV_LENGTH]; + + memset(&key, 0, sizeof(key)); + memset(&iv, 0, sizeof(iv)); + + if (derive_key_iv(password, key, iv) != 0) + { + return 1; + } + + return aes_encrypt(plaintext, key, iv, ciphertext, ciphertext_length); +} + +// [public] +int +pgmoneta_decrypt(char* ciphertext, int ciphertext_length, char* password, char** plaintext) +{ + unsigned char key[EVP_MAX_KEY_LENGTH]; + unsigned char iv[EVP_MAX_IV_LENGTH]; + + memset(&key, 0, sizeof(key)); + memset(&iv, 0, sizeof(iv)); + + if (derive_key_iv(password, key, iv) != 0) + { + return 1; + } + + return aes_decrypt(ciphertext, ciphertext_length, key, iv, plaintext); +} + +// [private] +static int +derive_key_iv(char* password, unsigned char* key, unsigned char* iv) +{ + +#if (OPENSSL_VERSION_NUMBER < 0x10100000L) + OpenSSL_add_all_algorithms(); +#endif + + if (!EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), NULL, + (unsigned char*) password, strlen(password), 1, + key, iv)) + { + return 1; + } + + return 0; +} + +// [private] +static int +aes_encrypt(char* plaintext, unsigned char* key, unsigned char* iv, char** ciphertext, int* ciphertext_length) +{ + EVP_CIPHER_CTX* ctx = NULL; + int length; + size_t size; + unsigned char* ct = NULL; + int ct_length; + + if (!(ctx = EVP_CIPHER_CTX_new())) + { + goto error; + } + + if (EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv) != 1) + { + goto error; + } + + size = strlen(plaintext) + EVP_CIPHER_block_size(EVP_aes_256_cbc()); + ct = malloc(size); + memset(ct, 0, size); + + if (EVP_EncryptUpdate(ctx, + ct, &length, + (unsigned char*)plaintext, strlen((char*)plaintext)) != 1) + { + goto error; + } + + ct_length = length; + + if (EVP_EncryptFinal_ex(ctx, ct + length, &length) != 1) + { + goto error; + } + + ct_length += length; + + EVP_CIPHER_CTX_free(ctx); + + *ciphertext = (char*)ct; + *ciphertext_length = ct_length; + + return 0; + +error: + if (ctx) + { + EVP_CIPHER_CTX_free(ctx); + } + + free(ct); + + return 1; +} + +// [private] +static int +aes_decrypt(char* ciphertext, int ciphertext_length, unsigned char* key, unsigned char* iv, char** plaintext) +{ + EVP_CIPHER_CTX* ctx = NULL; + int plaintext_length; + int length; + size_t size; + char* pt = NULL; + + if (!(ctx = EVP_CIPHER_CTX_new())) + { + goto error; + } + + if (EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv) != 1) + { + goto error; + } + + size = ciphertext_length + EVP_CIPHER_block_size(EVP_aes_256_cbc()); + pt = malloc(size); + memset(pt, 0, size); + + if (EVP_DecryptUpdate(ctx, + (unsigned char*)pt, &length, + (unsigned char*)ciphertext, ciphertext_length) != 1) + { + goto error; + } + + plaintext_length = length; + + if (EVP_DecryptFinal_ex(ctx, (unsigned char*)pt + length, &length) != 1) + { + goto error; + } + + plaintext_length += length; + + EVP_CIPHER_CTX_free(ctx); + + pt[plaintext_length] = 0; + *plaintext = pt; + + return 0; + +error: + if (ctx) + { + EVP_CIPHER_CTX_free(ctx); + } + + free(pt); + + return 1; +} diff --git a/src/libpgmoneta/configuration.c b/src/libpgmoneta/configuration.c index 2fe3caf6..a5ab4e9a 100644 --- a/src/libpgmoneta/configuration.c +++ b/src/libpgmoneta/configuration.c @@ -33,6 +33,7 @@ #include #include #include +#include /* system */ #include diff --git a/src/libpgmoneta/security.c b/src/libpgmoneta/security.c index da8abd06..aa7beeaf 100644 --- a/src/libpgmoneta/security.c +++ b/src/libpgmoneta/security.c @@ -84,10 +84,6 @@ static int server_scram256(char* username, char* password, int server_fd); static char* get_admin_password(char* username); -static int derive_key_iv(char* password, unsigned char* key, unsigned char* iv); -static int aes_encrypt(char* plaintext, unsigned char* key, unsigned char* iv, char** ciphertext, int* ciphertext_length); -static int aes_decrypt(char* ciphertext, int ciphertext_length, unsigned char* key, unsigned char* iv, char** plaintext); - static int sasl_prep(char* password, char** password_prep); static int generate_nounce(char** nounce); static int get_scram_attribute(char attribute, char* input, size_t size, char** value); @@ -1690,40 +1686,6 @@ pgmoneta_get_master_key(char** masterkey) return 1; } -int -pgmoneta_encrypt(char* plaintext, char* password, char** ciphertext, int* ciphertext_length) -{ - unsigned char key[EVP_MAX_KEY_LENGTH]; - unsigned char iv[EVP_MAX_IV_LENGTH]; - - memset(&key, 0, sizeof(key)); - memset(&iv, 0, sizeof(iv)); - - if (derive_key_iv(password, key, iv) != 0) - { - return 1; - } - - return aes_encrypt(plaintext, key, iv, ciphertext, ciphertext_length); -} - -int -pgmoneta_decrypt(char* ciphertext, int ciphertext_length, char* password, char** plaintext) -{ - unsigned char key[EVP_MAX_KEY_LENGTH]; - unsigned char iv[EVP_MAX_IV_LENGTH]; - - memset(&key, 0, sizeof(key)); - memset(&iv, 0, sizeof(iv)); - - if (derive_key_iv(password, key, iv) != 0) - { - return 1; - } - - return aes_decrypt(ciphertext, ciphertext_length, key, iv, plaintext); -} - int pgmoneta_tls_valid(void) { @@ -1836,138 +1798,6 @@ pgmoneta_tls_valid(void) return 1; } -static int -derive_key_iv(char* password, unsigned char* key, unsigned char* iv) -{ - -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) - OpenSSL_add_all_algorithms(); -#endif - - if (!EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), NULL, - (unsigned char*) password, strlen(password), 1, - key, iv)) - { - return 1; - } - - return 0; -} - -static int -aes_encrypt(char* plaintext, unsigned char* key, unsigned char* iv, char** ciphertext, int* ciphertext_length) -{ - EVP_CIPHER_CTX* ctx = NULL; - int length; - size_t size; - unsigned char* ct = NULL; - int ct_length; - - if (!(ctx = EVP_CIPHER_CTX_new())) - { - goto error; - } - - if (EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv) != 1) - { - goto error; - } - - size = strlen(plaintext) + EVP_CIPHER_block_size(EVP_aes_256_cbc()); - ct = malloc(size); - memset(ct, 0, size); - - if (EVP_EncryptUpdate(ctx, - ct, &length, - (unsigned char*)plaintext, strlen((char*)plaintext)) != 1) - { - goto error; - } - - ct_length = length; - - if (EVP_EncryptFinal_ex(ctx, ct + length, &length) != 1) - { - goto error; - } - - ct_length += length; - - EVP_CIPHER_CTX_free(ctx); - - *ciphertext = (char*)ct; - *ciphertext_length = ct_length; - - return 0; - -error: - if (ctx) - { - EVP_CIPHER_CTX_free(ctx); - } - - free(ct); - - return 1; -} - -static int -aes_decrypt(char* ciphertext, int ciphertext_length, unsigned char* key, unsigned char* iv, char** plaintext) -{ - EVP_CIPHER_CTX* ctx = NULL; - int plaintext_length; - int length; - size_t size; - char* pt = NULL; - - if (!(ctx = EVP_CIPHER_CTX_new())) - { - goto error; - } - - if (EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv) != 1) - { - goto error; - } - - size = ciphertext_length + EVP_CIPHER_block_size(EVP_aes_256_cbc()); - pt = malloc(size); - memset(pt, 0, size); - - if (EVP_DecryptUpdate(ctx, - (unsigned char*)pt, &length, - (unsigned char*)ciphertext, ciphertext_length) != 1) - { - goto error; - } - - plaintext_length = length; - - if (EVP_DecryptFinal_ex(ctx, (unsigned char*)pt + length, &length) != 1) - { - goto error; - } - - plaintext_length += length; - - EVP_CIPHER_CTX_free(ctx); - - pt[plaintext_length] = 0; - *plaintext = pt; - - return 0; - -error: - if (ctx) - { - EVP_CIPHER_CTX_free(ctx); - } - - free(pt); - - return 1; -} - static int sasl_prep(char* password, char** password_prep) {