Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use the openssl EVP API for SHA256 and AES256 instead of the deprecated lo… #4840

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 68 additions & 21 deletions berkdb/crypto/aes_method.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,6 @@
* [email protected].
*/

/* AES_* and SHA1_* functions are made deprecated as of OpenSSL 3.0.
Disable compiler warning for the entire file as it's not very likely
that we'll ever modify this file. */
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"

#include "db_config.h"

#ifndef lint
Expand All @@ -28,6 +23,7 @@ static const char revid[] = "$Id: aes_method.c,v 1.18 2003/04/28 19:59:19 bostic
#include "db_int.h"
#include "dbinc/crypto.h"
#include "dbinc/hmac.h"
#include <openssl/evp.h>

static int __aes_derivekeys __P((DB_ENV *, DB_CIPHER *, u_int8_t *, size_t));

Expand Down Expand Up @@ -83,8 +79,15 @@ __aes_close(dbenv, data)
DB_ENV *dbenv;
void *data;
{
__os_free(dbenv, data);
return (0);
AES_CIPHER *aes = (AES_CIPHER *)data;

// free the EVP openssl contexts
if (aes) {
EVP_CIPHER_CTX_free(aes->encrypt_ctx);
EVP_CIPHER_CTX_free(aes->decrypt_ctx);
__os_free(dbenv, aes);
}
return (0);
}

/*
Expand All @@ -103,11 +106,23 @@ __aes_decrypt(dbenv, aes_data, iv, cipher, cipher_len)
size_t cipher_len;
{
AES_CIPHER *aes = (AES_CIPHER *)aes_data;
int outlen, tmplen ;

if (aes == NULL || iv == NULL || cipher == NULL)
return (EINVAL);

if ((cipher_len % DB_AES_CHUNK) != 0)
return (EINVAL);
AES_cbc_encrypt(cipher, cipher, cipher_len, &aes->decrypt_key, iv, AES_DECRYPT);

if (!EVP_DecryptInit_ex(aes->decrypt_ctx, NULL, NULL, NULL, iv))
return (EINVAL);

if (!EVP_DecryptUpdate(aes->decrypt_ctx, cipher, &outlen, cipher, cipher_len))
return (EINVAL);

if (!EVP_DecryptFinal_ex(aes->decrypt_ctx, cipher + outlen, &tmplen))
return (EINVAL);

return (0);
}

Expand All @@ -127,7 +142,7 @@ __aes_encrypt(dbenv, aes_data, iv, data, data_len)
size_t data_len;
{
AES_CIPHER *aes;
int ret;
int ret, outlen, tmplen;

aes = (AES_CIPHER *)aes_data;
if (aes == NULL || data == NULL)
Expand All @@ -144,7 +159,16 @@ __aes_encrypt(dbenv, aes_data, iv, data, data_len)
if ((ret = __db_generate_iv(dbenv, (uint32_t*)orig)) != 0)
return (ret);
memcpy(copy, orig, DB_IV_BYTES);
AES_cbc_encrypt(data, data, data_len, &aes->encrypt_key, copy, AES_ENCRYPT);

if (!EVP_EncryptInit_ex(aes->encrypt_ctx, NULL, NULL, NULL, copy))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you not need a key here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for taking so long to go back and look at this @riverszhang89 - the key is set into the EVP_CIPHER_CTX in the __aes_derivekeys method called during the init. So passing NULL along with the aes->encrypt_ctx in the __aes_encrypt is telling EVP_EncryptInit to use the already defined key in the context. This looks correct. I hope to do better testing of this once I setup another comdb2 test environment.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've now tested the code in creating an encrypted DB and it works. I ran it through valgrind as well to ensure no (new) memory leaks. @riverszhang89

return (EINVAL);

if (!EVP_EncryptUpdate(aes->encrypt_ctx, data, &outlen, data, data_len))
return (EINVAL);

if (!EVP_EncryptFinal_ex(aes->encrypt_ctx, data + outlen, &tmplen))
return (EINVAL);

memcpy(iv, orig, DB_IV_BYTES);
return (0);
}
Expand Down Expand Up @@ -174,17 +198,40 @@ __aes_derivekeys(dbenv, db_cipher, passwd, plen)
if (passwd == NULL) return (EINVAL);
AES_CIPHER *aes = (AES_CIPHER *)db_cipher->data;

SHA_CTX ctx;
SHA1_Init(&ctx);
SHA1_Update(&ctx, passwd, plen);
SHA1_Update(&ctx, (u_int8_t *)DB_ENC_MAGIC, strlen(DB_ENC_MAGIC));
SHA1_Update(&ctx, passwd, plen);
uint8_t temp[DB_MAC_KEY];
SHA1_Final(temp, &ctx);
// Create contexts
aes->encrypt_ctx = EVP_CIPHER_CTX_new();
aes->decrypt_ctx = EVP_CIPHER_CTX_new();

if (!aes->encrypt_ctx || !aes->decrypt_ctx)
return (EINVAL);

// Use Openssl EVP API for SHA1 operations
EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
uint8_t key[DB_MAC_KEY];
unsigned int key_len;

if (!md_ctx)
return (EINVAL);

// Initialize EVP digest context with SHA1
if (!EVP_DigestInit_ex(md_ctx, EVP_sha1(), NULL) ||
frumioj marked this conversation as resolved.
Show resolved Hide resolved
!EVP_DigestUpdate(md_ctx, passwd, plen) ||
!EVP_DigestUpdate(md_ctx, (u_int8_t *)DB_ENC_MAGIC, strlen(DB_ENC_MAGIC)) ||
!EVP_DigestUpdate(md_ctx, passwd, plen) ||
!EVP_DigestFinal_ex(md_ctx, key, &key_len))
{
EVP_MD_CTX_free(md_ctx);
return (EINVAL);
}

EVP_MD_CTX_free(md_ctx);

// Initialize EVP cipher contexts
if (!EVP_EncryptInit_ex(aes->encrypt_ctx, EVP_aes_256_cbc(), NULL, key, NULL))
return (EINVAL);

if (!EVP_DecryptInit_ex(aes->decrypt_ctx, EVP_aes_256_cbc(), NULL, key, NULL))
return (EINVAL);

if (AES_set_encrypt_key(temp, DB_AES_KEYLEN, &aes->encrypt_key) < 0)
return (EINVAL);
if (AES_set_decrypt_key(temp, DB_AES_KEYLEN, &aes->decrypt_key) < 0)
return (EINVAL);
return (0);
}
4 changes: 2 additions & 2 deletions berkdb/dbinc/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ typedef struct __cipher {
#define DB_AES_CHUNK 16 /* AES byte unit size */

typedef struct __aes_cipher {
AES_KEY decrypt_key; /* Decryption key instance */
AES_KEY encrypt_key; /* Encryption key instance */
EVP_CIPHER_CTX *encrypt_ctx;
EVP_CIPHER_CTX *decrypt_ctx;
} AES_CIPHER;

#include "dbinc_auto/crypto_ext.h"
Expand Down