Ensure crypto CTX objects are freed. Fixes #2550

This commit is contained in:
dmiller 2022-10-25 17:00:01 +00:00
parent e4fd4bd2fe
commit 7332939768
3 changed files with 79 additions and 86 deletions

View file

@ -162,6 +162,7 @@ static char *make_nonce(const struct timeval *tv)
enhex(hash_hex, hashbuf, hash_size);
strbuf_sprintf(&buf, &size, &offset, "%s-%s", time_buf, hash_hex);
EVP_MD_CTX_free(md5);
return buf;
}
@ -216,6 +217,7 @@ static void make_response(char buf[EVP_MAX_MD_SIZE * 2 + 1],
EVP_DigestFinal_ex(md5, hashbuf, &hash_size);
enhex(buf, hashbuf, hash_size);
EVP_MD_CTX_free(md5);
}
/* Extract the issuance time from a nonce (without checking other aspects of

View file

@ -72,17 +72,10 @@
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined LIBRESSL_VERSION_NUMBER
#define HAVE_OPAQUE_EVP_PKEY 1
#define FUNC_EVP_MD_CTX_init EVP_MD_CTX_reset
#define FUNC_EVP_MD_CTX_cleanup EVP_MD_CTX_reset
#define FUNC_EVP_CIPHER_CTX_init EVP_CIPHER_CTX_reset
#define FUNC_EVP_CIPHER_CTX_cleanup EVP_CIPHER_CTX_reset
#define PASS_EVP_CTX(ctx) (ctx)
#else
#define FUNC_EVP_MD_CTX_init EVP_MD_CTX_init
#define FUNC_EVP_MD_CTX_cleanup EVP_MD_CTX_cleanup
#define FUNC_EVP_CIPHER_CTX_init EVP_CIPHER_CTX_init
#define FUNC_EVP_CIPHER_CTX_cleanup EVP_CIPHER_CTX_cleanup
#define PASS_EVP_CTX(ctx) (&(ctx))
#define EVP_MD_CTX_new EVP_MD_CTX_create
#define EVP_MD_CTX_free EVP_MD_CTX_destroy
#define EVP_CIPHER_CTX_free EVP_CIPHER_CTX_cleanup
#endif
#endif /* HAVE_OPENSSL */
@ -136,22 +129,23 @@ int Crypto::aes128_cbc_encrypt(u8 *inbuff, size_t inlen, u8 *dst_buff, u8 *key,
#if HAVE_OPAQUE_EVP_PKEY
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
#else
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX stack_ctx;
EVP_CIPHER_CTX *ctx = &stack_ctx;
EVP_CIPHER_CTX_init(ctx);
#endif
FUNC_EVP_CIPHER_CTX_init(PASS_EVP_CTX(ctx));
EVP_CIPHER_CTX_set_padding(PASS_EVP_CTX(ctx), 0);
EVP_CIPHER_CTX_set_padding(ctx, 0);
int result=OP_SUCCESS;
if( EVP_EncryptInit(PASS_EVP_CTX(ctx), EVP_aes_128_cbc(), key, iv)==0 ){
if( EVP_EncryptInit(ctx, EVP_aes_128_cbc(), key, iv)==0 ){
nping_print(DBG_4, "EVP_EncryptInit() failed");
result=OP_FAILURE;
}else if( EVP_EncryptUpdate(PASS_EVP_CTX(ctx), dst_buff, &flen, inbuff, (int)inlen)==0 ){
}else if( EVP_EncryptUpdate(ctx, dst_buff, &flen, inbuff, (int)inlen)==0 ){
nping_print(DBG_4, "EVP_EncryptUpdate() failed");
result=OP_FAILURE;
}else if( EVP_EncryptFinal(PASS_EVP_CTX(ctx), dst_buff+flen, &flen2)==0 ){
}else if( EVP_EncryptFinal(ctx, dst_buff+flen, &flen2)==0 ){
nping_print(DBG_4, "EVP_EncryptFinal() failed");
result=OP_FAILURE;
}
FUNC_EVP_CIPHER_CTX_cleanup(PASS_EVP_CTX(ctx));
EVP_CIPHER_CTX_free(ctx);
return result;
}
#endif
@ -175,18 +169,19 @@ int Crypto::aes128_cbc_decrypt(u8 *inbuff, size_t inlen, u8 *dst_buff, u8 *key,
#if HAVE_OPAQUE_EVP_PKEY
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
#else
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX stack_ctx;
EVP_CIPHER_CTX *ctx = &stack_ctx;
EVP_CIPHER_CTX_init(ctx);
#endif
FUNC_EVP_CIPHER_CTX_init(PASS_EVP_CTX(ctx));
EVP_CIPHER_CTX_set_padding(PASS_EVP_CTX(ctx), 0);
EVP_CIPHER_CTX_set_padding(ctx, 0);
int result=OP_SUCCESS;
if( EVP_DecryptInit(PASS_EVP_CTX(ctx), EVP_aes_128_cbc(), key, iv)==0 ){
if( EVP_DecryptInit(ctx, EVP_aes_128_cbc(), key, iv)==0 ){
nping_print(DBG_4, "EVP_DecryptInit() failed");
result=OP_FAILURE;
}else if( EVP_DecryptUpdate(PASS_EVP_CTX(ctx), dst_buff, &flen1, inbuff, (int)inlen)==0 ){
}else if( EVP_DecryptUpdate(ctx, dst_buff, &flen1, inbuff, (int)inlen)==0 ){
nping_print(DBG_4, "EVP_DecryptUpdate() failed");
result=OP_FAILURE;
}else if( EVP_DecryptFinal(PASS_EVP_CTX(ctx), dst_buff+flen1, &flen2)==0 ){
}else if( EVP_DecryptFinal(ctx, dst_buff+flen1, &flen2)==0 ){
nping_print(DBG_4, "OpenSSL bug: it says EVP_DecryptFinal() failed when it didn't (%s).",
ERR_error_string(ERR_peek_last_error(), NULL));
/* We do not return OP_FAILURE in this case because the
@ -215,7 +210,7 @@ int Crypto::aes128_cbc_decrypt(u8 *inbuff, size_t inlen, u8 *dst_buff, u8 *key,
//ERR_free_strings();
//ERR_pop_to_mark();
}
FUNC_EVP_CIPHER_CTX_cleanup(PASS_EVP_CTX(ctx));
EVP_CIPHER_CTX_free(ctx);
return result;
}
#endif
@ -252,33 +247,28 @@ u8 *Crypto::deriveKey(const u8 *from, size_t fromlen, size_t *final_len){
static u8 hash[MAX(SHA256_HASH_LEN, EVP_MAX_MD_SIZE)];
static u8 next[MAX(SHA256_HASH_LEN, EVP_MAX_MD_SIZE)];
unsigned int lastlen;
#if HAVE_OPAQUE_EVP_PKEY
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
#else
EVP_MD_CTX ctx;
#endif
FUNC_EVP_MD_CTX_init(PASS_EVP_CTX(ctx));
if( EVP_MD_size(EVP_sha256()) != SHA256_HASH_LEN )
nping_fatal(QT_2, "OpenSSL is broken. SHA256 len is %d\n", EVP_MD_size(EVP_sha256()) );
/* Compute the SHA256 hash of the supplied buffer */
EVP_DigestInit(PASS_EVP_CTX(ctx), EVP_sha256());
EVP_DigestUpdate(PASS_EVP_CTX(ctx), from, fromlen);
EVP_DigestFinal(PASS_EVP_CTX(ctx), hash, &lastlen);
EVP_DigestInit(ctx, EVP_sha256());
EVP_DigestUpdate(ctx, from, fromlen);
EVP_DigestFinal(ctx, hash, &lastlen);
/* Now compute the 1000th hash of that hash */
for(int i=0; i<TIMES_KEY_DERIVATION; i++){
EVP_MD_CTX_init(PASS_EVP_CTX(ctx));
EVP_DigestInit(PASS_EVP_CTX(ctx), EVP_sha256());
EVP_DigestUpdate(PASS_EVP_CTX(ctx), hash, SHA256_HASH_LEN);
EVP_DigestFinal(PASS_EVP_CTX(ctx), next, &lastlen);
EVP_MD_CTX_init(ctx);
EVP_DigestInit(ctx, EVP_sha256());
EVP_DigestUpdate(ctx, hash, SHA256_HASH_LEN);
EVP_DigestFinal(ctx, next, &lastlen);
memcpy(hash, next, SHA256_HASH_LEN);
}
if(final_len!=NULL)
*final_len=SHA256_HASH_LEN;
FUNC_EVP_MD_CTX_cleanup(PASS_EVP_CTX(ctx));
EVP_MD_CTX_free(ctx);
return hash;
}
#endif

View file

@ -15,20 +15,13 @@
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined LIBRESSL_VERSION_NUMBER
#define HAVE_OPAQUE_STRUCTS 1
#define FUNC_EVP_MD_CTX_init EVP_MD_CTX_reset
#define FUNC_EVP_MD_CTX_cleanup EVP_MD_CTX_reset
#define FUNC_EVP_CIPHER_CTX_init EVP_CIPHER_CTX_reset
#define FUNC_EVP_CIPHER_CTX_cleanup EVP_CIPHER_CTX_reset
#define PASS_EVP_CTX(ctx) (ctx)
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
# include <openssl/provider.h>
#endif
#else
#define FUNC_EVP_MD_CTX_init EVP_MD_CTX_init
#define FUNC_EVP_MD_CTX_cleanup EVP_MD_CTX_cleanup
#define FUNC_EVP_CIPHER_CTX_init EVP_CIPHER_CTX_init
#define FUNC_EVP_CIPHER_CTX_cleanup EVP_CIPHER_CTX_cleanup
#define PASS_EVP_CTX(ctx) (&(ctx))
#define EVP_MD_CTX_new EVP_MD_CTX_create
#define EVP_MD_CTX_free EVP_MD_CTX_destroy
#define EVP_CIPHER_CTX_free EVP_CIPHER_CTX_cleanup
#endif
#include "nse_lua.h"
@ -282,25 +275,23 @@ static int l_digest(lua_State *L) /** digest(string algorithm, string messag
const unsigned char *msg = (unsigned char *) luaL_checklstring( L, 2, &msg_len );
unsigned char digest[EVP_MAX_MD_SIZE];
const EVP_MD * evp_md;
#if HAVE_OPAQUE_STRUCTS
EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
#else
EVP_MD_CTX mdctx;
#endif
EVP_MD_CTX *mdctx = NULL;
evp_md = EVP_get_digestbyname( algorithm );
if (!evp_md) return luaL_error( L, "Unknown digest algorithm: %s", algorithm );
FUNC_EVP_MD_CTX_init(PASS_EVP_CTX(mdctx));
mdctx = EVP_MD_CTX_new();
if (!mdctx) return NSE_SSL_LUA_ERR(L);
if (!(
EVP_DigestInit_ex( PASS_EVP_CTX(mdctx), evp_md, NULL ) &&
EVP_DigestUpdate( PASS_EVP_CTX(mdctx), msg, msg_len ) &&
EVP_DigestFinal_ex( PASS_EVP_CTX(mdctx), digest, &digest_len ))) {
FUNC_EVP_MD_CTX_cleanup( PASS_EVP_CTX(mdctx) );
EVP_DigestInit_ex( mdctx, evp_md, NULL ) &&
EVP_DigestUpdate( mdctx, msg, msg_len ) &&
EVP_DigestFinal_ex( mdctx, digest, &digest_len ))) {
EVP_MD_CTX_free( mdctx );
return NSE_SSL_LUA_ERR(L);
}
FUNC_EVP_MD_CTX_cleanup( PASS_EVP_CTX(mdctx) );
EVP_MD_CTX_free( mdctx );
lua_pushlstring( L, (char *) digest, digest_len );
return 1;
@ -393,41 +384,46 @@ static int l_encrypt(lua_State *L) /** encrypt( string algorithm, string key, st
#if HAVE_OPAQUE_STRUCTS
EVP_CIPHER_CTX *cipher_ctx = EVP_CIPHER_CTX_new();
#else
EVP_CIPHER_CTX cipher_ctx;
EVP_CIPHER_CTX stack_ctx;
EVP_CIPHER_CTX *cipher_ctx = &stack_ctx;
EVP_CIPHER_CTX_init( cipher_ctx );
#endif
FUNC_EVP_CIPHER_CTX_init( PASS_EVP_CTX(cipher_ctx) );
/* First create the cipher context, then set the key length and padding, and
check the iv length. Below we set the key and iv. */
if (!(
EVP_EncryptInit_ex( PASS_EVP_CTX(cipher_ctx), evp_cipher, NULL, NULL, NULL ) &&
EVP_CIPHER_CTX_set_key_length( PASS_EVP_CTX(cipher_ctx), key_len ) &&
EVP_CIPHER_CTX_set_padding( PASS_EVP_CTX(cipher_ctx), padding ))) {
EVP_EncryptInit_ex( cipher_ctx, evp_cipher, NULL, NULL, NULL ) &&
EVP_CIPHER_CTX_set_key_length( cipher_ctx, key_len ) &&
EVP_CIPHER_CTX_set_padding( cipher_ctx, padding ))) {
EVP_CIPHER_CTX_free(cipher_ctx);
return NSE_SSL_LUA_ERR(L);
}
if (iv != NULL && (int) iv_len != EVP_CIPHER_CTX_iv_length( PASS_EVP_CTX(cipher_ctx) )) {
if (iv != NULL && (int) iv_len != EVP_CIPHER_CTX_iv_length( cipher_ctx )) {
EVP_CIPHER_CTX_free(cipher_ctx);
return luaL_error( L, "Length of iv is %d; should be %d",
(int) iv_len, EVP_CIPHER_CTX_iv_length( PASS_EVP_CTX(cipher_ctx) ));
(int) iv_len, EVP_CIPHER_CTX_iv_length( cipher_ctx ));
}
int out_len, final_len;
unsigned char * out = (unsigned char *) malloc( data_len + EVP_MAX_BLOCK_LENGTH );
if (!out) return luaL_error( L, "Couldn't allocate memory.");
if (!out) {
EVP_CIPHER_CTX_free(cipher_ctx);
return luaL_error( L, "Couldn't allocate memory.");
}
if (!(
EVP_EncryptInit_ex( PASS_EVP_CTX(cipher_ctx), NULL, NULL, key, iv ) &&
EVP_EncryptUpdate( PASS_EVP_CTX(cipher_ctx), out, &out_len, data, data_len ) &&
EVP_EncryptFinal_ex( PASS_EVP_CTX(cipher_ctx), out + out_len, &final_len ) )) {
FUNC_EVP_CIPHER_CTX_cleanup( PASS_EVP_CTX(cipher_ctx) );
EVP_EncryptInit_ex( cipher_ctx, NULL, NULL, key, iv ) &&
EVP_EncryptUpdate( cipher_ctx, out, &out_len, data, data_len ) &&
EVP_EncryptFinal_ex( cipher_ctx, out + out_len, &final_len ) )) {
EVP_CIPHER_CTX_free(cipher_ctx);
free( out );
return NSE_SSL_LUA_ERR(L);
}
lua_pushlstring( L, (char *) out, out_len + final_len );
FUNC_EVP_CIPHER_CTX_cleanup( PASS_EVP_CTX(cipher_ctx) );
EVP_CIPHER_CTX_free( cipher_ctx );
free( out );
return 1;
@ -450,39 +446,44 @@ static int l_decrypt(lua_State *L) /** decrypt( string algorithm, string key, st
#if HAVE_OPAQUE_STRUCTS
EVP_CIPHER_CTX *cipher_ctx = EVP_CIPHER_CTX_new();
#else
EVP_CIPHER_CTX cipher_ctx;
EVP_CIPHER_CTX stack_ctx;
EVP_CIPHER_CTX *cipher_ctx = &stack_ctx;
EVP_CIPHER_CTX_init( cipher_ctx );
#endif
FUNC_EVP_CIPHER_CTX_init( PASS_EVP_CTX(cipher_ctx) );
if (!(
EVP_DecryptInit_ex( PASS_EVP_CTX(cipher_ctx), evp_cipher, NULL, NULL, NULL ) &&
EVP_CIPHER_CTX_set_key_length( PASS_EVP_CTX(cipher_ctx), key_len ) &&
EVP_CIPHER_CTX_set_padding( PASS_EVP_CTX(cipher_ctx), padding ))) {
EVP_DecryptInit_ex( cipher_ctx, evp_cipher, NULL, NULL, NULL ) &&
EVP_CIPHER_CTX_set_key_length( cipher_ctx, key_len ) &&
EVP_CIPHER_CTX_set_padding( cipher_ctx, padding ))) {
EVP_CIPHER_CTX_free(cipher_ctx);
return NSE_SSL_LUA_ERR(L);
}
if (iv != NULL && (int) iv_len != EVP_CIPHER_CTX_iv_length( PASS_EVP_CTX(cipher_ctx) )) {
if (iv != NULL && (int) iv_len != EVP_CIPHER_CTX_iv_length( cipher_ctx )) {
EVP_CIPHER_CTX_free(cipher_ctx);
return luaL_error( L, "Length of iv is %d; should be %d",
(int) iv_len, EVP_CIPHER_CTX_iv_length( PASS_EVP_CTX(cipher_ctx) ));
(int) iv_len, EVP_CIPHER_CTX_iv_length( cipher_ctx ));
}
int out_len, final_len;
unsigned char * out = (unsigned char *) malloc( data_len );
if (!out) return luaL_error( L, "Couldn't allocate memory.");
if (!out) {
EVP_CIPHER_CTX_free(cipher_ctx);
return luaL_error( L, "Couldn't allocate memory.");
}
if (!(
EVP_DecryptInit_ex( PASS_EVP_CTX(cipher_ctx), NULL, NULL, key, iv ) &&
EVP_DecryptUpdate( PASS_EVP_CTX(cipher_ctx), out, &out_len, data, data_len ) &&
EVP_DecryptFinal_ex( PASS_EVP_CTX(cipher_ctx), out + out_len, &final_len ) )) {
FUNC_EVP_CIPHER_CTX_cleanup( PASS_EVP_CTX(cipher_ctx) );
EVP_DecryptInit_ex( cipher_ctx, NULL, NULL, key, iv ) &&
EVP_DecryptUpdate( cipher_ctx, out, &out_len, data, data_len ) &&
EVP_DecryptFinal_ex( cipher_ctx, out + out_len, &final_len ) )) {
EVP_CIPHER_CTX_free( cipher_ctx );
free( out );
return NSE_SSL_LUA_ERR(L);
}
lua_pushlstring( L, (char *) out, out_len + final_len );
FUNC_EVP_CIPHER_CTX_cleanup( PASS_EVP_CTX(cipher_ctx) );
EVP_CIPHER_CTX_free( cipher_ctx );
free( out );
return 1;