diff --git a/nse_openssl.cc b/nse_openssl.cc index 808c11806..cc94472a4 100644 --- a/nse_openssl.cc +++ b/nse_openssl.cc @@ -214,6 +214,18 @@ static int l_bignum_bn2bin( lua_State *L ) /** bignum_bn2bin( BIGNUM bn ) */ return 1; } +static int l_bignum_bn2mpi( lua_State *L ) /** bignum_bn2mpi( BIGNUM bn ) */ +{ + bignum_data_t * userdata = (bignum_data_t *) luaL_checkudata(L, 1, "BIGNUM"); + unsigned char * result = (unsigned char *) malloc( BN_bn2mpi( userdata->bn, NULL ) ); + if (!result) return luaL_error( L, "Couldn't allocate memory."); + + int len = BN_bn2mpi( userdata->bn, result ); + lua_pushlstring( L, (char *) result, len ); + free( result ); + return 1; +} + static int l_bignum_bn2dec( lua_State *L ) /** bignum_bn2dec( BIGNUM bn ) */ { bignum_data_t * userdata = (bignum_data_t *) luaL_checkudata(L, 1, "BIGNUM"); @@ -515,6 +527,7 @@ static const struct luaL_Reg bignum_methods[] = { { "num_bits", l_bignum_num_bits }, { "num_bytes", l_bignum_num_bytes }, { "tobin", l_bignum_bn2bin }, + { "tompi", l_bignum_bn2mpi }, { "todec", l_bignum_bn2dec }, { "tohex", l_bignum_bn2hex }, { "is_bit_set", l_bignum_is_bit_set }, @@ -541,6 +554,7 @@ static const struct luaL_Reg openssllib[] = { { "bignum_rand", l_bignum_rand }, { "bignum_pseudo_rand", l_bignum_rand }, { "bignum_bn2bin", l_bignum_bn2bin }, + { "bignum_bn2mpi", l_bignum_bn2mpi }, { "bignum_bn2dec", l_bignum_bn2dec }, { "bignum_bn2hex", l_bignum_bn2hex }, { "bignum_add", l_bignum_add }, diff --git a/nselib/ssh2.lua b/nselib/ssh2.lua index da2ab3eae..e8707c880 100644 --- a/nselib/ssh2.lua +++ b/nselib/ssh2.lua @@ -53,11 +53,11 @@ end --- Pack a multiprecision integer for sending. -- @param bn openssl bignum. -- @return Packed multiprecision integer. -transport.pack_mpint = function( bn ) +transport.pack_mpint = openssl.bignum_bn2mpi or function( bn ) local bytes, packed bytes = bn:num_bytes() packed = bn:tobin() - if bn:num_bits() % 8 == 0 then + if bytes > 0 and bn:num_bits() % 8 == 0 then bytes = bytes + 1 packed = '\0' .. packed end @@ -378,4 +378,26 @@ SSH2 = { } +local unittest = require "unittest" +if not unittest.testing() then + return _ENV +end + +test_suite = unittest.TestSuite:new() + +local mpints = { + {"0", "\x00\x00\x00\x00"}, + {"9a378f9b2e332a7", "\x00\x00\x00\x08\x09\xa3\x78\xf9\xb2\xe3\x32\xa7"}, + {"80", "\x00\x00\x00\x02\x00\x80"}, + --[[ RFC 4251 says negative numbers are 2's complement, but OpenSSL doesn't do that + {"-1234", "\x00\x00\x00\x02\xed\xcc"}, + {"-deadbeef", "\x00\x00\x00\x05\xff\x21\x52\x41\x11"}, + ]]-- +} + +for _, t in ipairs(mpints) do + local bn = openssl.bignum_hex2bn(t[1]) + test_suite:add_test(unittest.equal(transport.pack_mpint(bn), t[2]), ("pack mpint 0x%s"):format(t[1])) +end + return _ENV;