From 1641a291e901f6bcee3e080d24c52063f402c47c Mon Sep 17 00:00:00 2001 From: dmiller Date: Thu, 6 Oct 2022 17:28:39 +0000 Subject: [PATCH] Fix a double-free due to uninitialized should_free in bignum_data_t --- nse_openssl.cc | 20 ++++++------- nse_openssl.h | 2 ++ nse_ssl_cert.cc | 74 +++++++++++++++++++------------------------------ 3 files changed, 41 insertions(+), 55 deletions(-) diff --git a/nse_openssl.cc b/nse_openssl.cc index 0f5b450e0..6add9bce3 100644 --- a/nse_openssl.cc +++ b/nse_openssl.cc @@ -48,14 +48,14 @@ typedef struct bignum_data { bool should_free; } bignum_data_t; -static int nse_pushbn( lua_State *L, BIGNUM *num) +int nse_pushbn( lua_State *L, BIGNUM *num, bool should_free) { bignum_data_t * data = (bignum_data_t *) lua_newuserdata( L, sizeof(bignum_data_t)); luaL_getmetatable( L, "BIGNUM" ); lua_setmetatable( L, -2 ); data->bn = num; /* Currently this is true for all uses in this file. */ - data->should_free = true; + data->should_free = should_free; return 1; } @@ -65,7 +65,7 @@ static int l_bignum_bin2bn( lua_State *L ) /** bignum_bin2bn( string s ) */ const unsigned char * s = (unsigned char *) luaL_checklstring( L, 1, &len ); BIGNUM * num = BN_new(); BN_bin2bn( s, len, num ); - return nse_pushbn(L, num); + return nse_pushbn(L, num, true); } static int l_bignum_dec2bn( lua_State *L ) /** bignum_dec2bn( string s ) */ @@ -73,7 +73,7 @@ static int l_bignum_dec2bn( lua_State *L ) /** bignum_dec2bn( string s ) */ const char * s = luaL_checkstring( L, 1 ); BIGNUM * num = BN_new(); BN_dec2bn( &num, s ); - return nse_pushbn(L, num); + return nse_pushbn(L, num, true); } static int l_bignum_hex2bn( lua_State *L ) /** bignum_hex2bn( string s ) */ @@ -81,7 +81,7 @@ static int l_bignum_hex2bn( lua_State *L ) /** bignum_hex2bn( string s ) */ const char * s = luaL_checkstring( L, 1 ); BIGNUM * num = BN_new(); BN_hex2bn( &num, s ); - return nse_pushbn(L, num); + return nse_pushbn(L, num, true); } static int l_bignum_rand( lua_State *L ) /** bignum_rand( number bits ) */ @@ -89,7 +89,7 @@ static int l_bignum_rand( lua_State *L ) /** bignum_rand( number bits ) */ size_t bits = luaL_checkinteger( L, 1 ); BIGNUM * num = BN_new(); BN_rand( num, bits, -1, 0 ); - return nse_pushbn(L, num); + return nse_pushbn(L, num, true); } static int l_bignum_mod_exp( lua_State *L ) /** bignum_mod_exp( BIGNUM a, BIGNUM p, BIGNUM m ) */ @@ -101,7 +101,7 @@ static int l_bignum_mod_exp( lua_State *L ) /** bignum_mod_exp( BIGNUM a, BIGNUM BN_CTX * ctx = BN_CTX_new(); BN_mod_exp( result, a->bn, p->bn, m->bn, ctx ); BN_CTX_free( ctx ); - return nse_pushbn(L, result); + return nse_pushbn(L, result, true); } static int l_bignum_div( lua_State *L ) /* bignum_div( BIGNUM a, BIGNUM d ) */ @@ -113,8 +113,8 @@ static int l_bignum_div( lua_State *L ) /* bignum_div( BIGNUM a, BIGNUM d ) */ BN_CTX * ctx = BN_CTX_new(); BN_div(dv, rem, a->bn, d->bn, ctx); BN_CTX_free( ctx ); - nse_pushbn(L, dv); - nse_pushbn(L, rem); + nse_pushbn(L, dv, true); + nse_pushbn(L, rem, true); return 2; } @@ -124,7 +124,7 @@ static int l_bignum_add( lua_State *L ) /** bignum_add( BIGNUM a, BIGNUM b ) */ bignum_data_t * b = (bignum_data_t *) luaL_checkudata(L, 2, "BIGNUM"); BIGNUM * result = BN_new(); BN_add( result, a->bn, b->bn ); - return nse_pushbn(L, result); + return nse_pushbn(L, result, true); } static int l_bignum_num_bits( lua_State *L ) /** bignum_num_bits( BIGNUM bn ) */ diff --git a/nse_openssl.h b/nse_openssl.h index f2db753da..09956622d 100644 --- a/nse_openssl.h +++ b/nse_openssl.h @@ -5,5 +5,7 @@ LUALIB_API int luaopen_openssl(lua_State *L); +#include +int nse_pushbn( lua_State *L, BIGNUM *num, bool should_free); #endif diff --git a/nse_ssl_cert.cc b/nse_ssl_cert.cc index bc35019a1..e0cd65e55 100644 --- a/nse_ssl_cert.cc +++ b/nse_ssl_cert.cc @@ -104,17 +104,13 @@ #include "nse_lua.h" #include "nse_nsock.h" +#include "nse_openssl.h" struct cert_userdata { X509 *cert; int attributes_table; }; -typedef struct bignum_data { - BIGNUM * bn; - bool should_free; -} bignum_data_t; - SSL *nse_nsock_get_ssl(lua_State *L); /* This is a reference to a table that will be used as the metatable for @@ -622,48 +618,36 @@ static int parse_ssl_cert(lua_State *L, X509 *cert) else #endif if (pkey_type == EVP_PKEY_RSA) { -#if OPENSSL_VERSION_NUMBER < 0x30000000L +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + BIGNUM *n = NULL, *e = NULL; + bool should_free = true; + EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_E, &e); + EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_N, &n); +#else + bool should_free = false; RSA *rsa = EVP_PKEY_get1_RSA(pubkey); - if (rsa) { -#endif - /* exponent */ - bignum_data_t * data = (bignum_data_t *) lua_newuserdata( L, sizeof(bignum_data_t)); - luaL_getmetatable( L, "BIGNUM" ); - lua_setmetatable( L, -2 ); -#if HAVE_OPAQUE_STRUCTS -#if OPENSSL_VERSION_NUMBER < 0x30000000L - const BIGNUM *n = NULL, *e = NULL; - data->should_free = false; - RSA_get0_key(rsa, &n, &e, NULL); -#else - BIGNUM *n = NULL, *e = NULL; - data->should_free = true; - EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_E, &e); - EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_N, &n); -#endif - data->bn = (BIGNUM*) e; -#else - data->bn = rsa->e; -#endif - lua_setfield(L, -2, "exponent"); - /* modulus */ - data = (bignum_data_t *) lua_newuserdata( L, sizeof(bignum_data_t)); - luaL_getmetatable( L, "BIGNUM" ); - lua_setmetatable( L, -2 ); -#if HAVE_OPAQUE_STRUCTS -#if OPENSSL_VERSION_NUMBER < 0x30000000L - data->should_free = false; -#else - data->should_free = true; -#endif - data->bn = (BIGNUM*) n; -#else - data->bn = rsa->n; -#endif - lua_setfield(L, -2, "modulus"); -#if OPENSSL_VERSION_NUMBER < 0x30000000L - RSA_free(rsa); + if (!rsa) { + // This should be impossible for this key type + return luaL_error(L, "EVP_PKEY_RSA missing RSA key!"); } +# if HAVE_OPAQUE_STRUCTS + const BIGNUM *n = NULL, *e = NULL; + RSA_get0_key(rsa, &n, &e, NULL); +# endif +#endif +#if HAVE_OPAQUE_STRUCTS +# define PASS_RSA_PARAM(_P) ((BIGNUM *)(_P)) +#else /* not HAVE_OPAQUE_STRUCTS */ +# define PASS_RSA_PARAM(_P) (rsa->_P) +#endif + /* exponent */ + nse_pushbn(L, PASS_RSA_PARAM(e), should_free); + lua_setfield(L, -2, "exponent"); + /* modulus */ + nse_pushbn(L, PASS_RSA_PARAM(n), should_free); + lua_setfield(L, -2, "modulus"); +#if OPENSSL_VERSION_NUMBER < 0x30000000L + RSA_free(rsa); #endif } lua_pushstring(L, pkey_type_to_string(pkey_type));