diff --git a/ncat/http_digest.c b/ncat/http_digest.c index 056dbfc1e..b5f80a920 100644 --- a/ncat/http_digest.c +++ b/ncat/http_digest.c @@ -77,7 +77,7 @@ #include "ncat.h" #include "http.h" -#include +#include #include /* What's a good length for this? I think it exists only to prevent us from @@ -133,14 +133,19 @@ int http_digest_init_secret(void) return 0; } +#if OPENSSL_API_LEVEL < 10100 +#define EVP_MD_CTX_new EVP_MD_CTX_create +#define EVP_MD_CTX_free EVP_MD_CTX_destroy +#endif static char *make_nonce(const struct timeval *tv) { char *buf = NULL; size_t size = 0, offset = 0; - MD5_CTX md5; - unsigned char hashbuf[MD5_DIGEST_LENGTH]; - char hash_hex[MD5_DIGEST_LENGTH * 2 + 1]; + EVP_MD_CTX *md5; + unsigned char hashbuf[EVP_MAX_MD_SIZE]; + char hash_hex[EVP_MAX_MD_SIZE * 2 + 1]; char time_buf[32]; + unsigned int hash_size = 0; /* Crash if someone forgot to call http_digest_init_secret. */ if (!secret_initialized) @@ -148,13 +153,13 @@ static char *make_nonce(const struct timeval *tv) Snprintf(time_buf, sizeof(time_buf), "%lu.%06lu", (long unsigned) tv->tv_sec, (long unsigned) tv->tv_usec); - - MD5_Init(&md5); - MD5_Update(&md5, secret, sizeof(secret)); - MD5_Update(&md5, ":", 1); - MD5_Update(&md5, time_buf, strlen(time_buf)); - MD5_Final(hashbuf, &md5); - enhex(hash_hex, hashbuf, sizeof(hashbuf)); + md5 = EVP_MD_CTX_new(); + EVP_DigestInit_ex(md5, EVP_md5(), NULL); + EVP_DigestUpdate(md5, secret, sizeof(secret)); + EVP_DigestUpdate(md5, ":", 1); + EVP_DigestUpdate(md5, time_buf, strlen(time_buf)); + EVP_DigestFinal_ex(md5, hashbuf, &hash_size); + enhex(hash_hex, hashbuf, hash_size); strbuf_sprintf(&buf, &size, &offset, "%s-%s", time_buf, hash_hex); @@ -163,51 +168,54 @@ static char *make_nonce(const struct timeval *tv) /* Arguments are assumed to be non-NULL, with the exception of nc and cnonce, which may be garbage only if qop == QOP_NONE. */ -static void make_response(char buf[MD5_DIGEST_LENGTH * 2 + 1], +static void make_response(char buf[EVP_MAX_MD_SIZE * 2 + 1], const char *username, const char *realm, const char *password, const char *method, const char *uri, const char *nonce, enum http_digest_qop qop, const char *nc, const char *cnonce) { - char HA1_hex[MD5_DIGEST_LENGTH * 2 + 1], HA2_hex[MD5_DIGEST_LENGTH * 2 + 1]; - unsigned char hashbuf[MD5_DIGEST_LENGTH]; - MD5_CTX md5; + char HA1_hex[EVP_MAX_MD_SIZE * 2 + 1], HA2_hex[EVP_MAX_MD_SIZE * 2 + 1]; + unsigned char hashbuf[EVP_MAX_MD_SIZE]; + EVP_MD_CTX *md5; + unsigned int hash_size = 0; + const EVP_MD *md = EVP_md5(); /* Calculate H(A1). */ - MD5_Init(&md5); - MD5_Update(&md5, username, strlen(username)); - MD5_Update(&md5, ":", 1); - MD5_Update(&md5, realm, strlen(realm)); - MD5_Update(&md5, ":", 1); - MD5_Update(&md5, password, strlen(password)); - MD5_Final(hashbuf, &md5); - enhex(HA1_hex, hashbuf, sizeof(hashbuf)); + md5 = EVP_MD_CTX_new(); + EVP_DigestInit_ex(md5, md, NULL); + EVP_DigestUpdate(md5, username, strlen(username)); + EVP_DigestUpdate(md5, ":", 1); + EVP_DigestUpdate(md5, realm, strlen(realm)); + EVP_DigestUpdate(md5, ":", 1); + EVP_DigestUpdate(md5, password, strlen(password)); + EVP_DigestFinal_ex(md5, hashbuf, &hash_size); + enhex(HA1_hex, hashbuf, hash_size); /* Calculate H(A2). */ - MD5_Init(&md5); - MD5_Update(&md5, method, strlen(method)); - MD5_Update(&md5, ":", 1); - MD5_Update(&md5, uri, strlen(uri)); - MD5_Final(hashbuf, &md5); - enhex(HA2_hex, hashbuf, sizeof(hashbuf)); + EVP_DigestInit_ex(md5, md, NULL); + EVP_DigestUpdate(md5, method, strlen(method)); + EVP_DigestUpdate(md5, ":", 1); + EVP_DigestUpdate(md5, uri, strlen(uri)); + EVP_DigestFinal_ex(md5, hashbuf, &hash_size); + enhex(HA2_hex, hashbuf, hash_size); /* Calculate response. */ - MD5_Init(&md5); - MD5_Update(&md5, HA1_hex, strlen(HA1_hex)); - MD5_Update(&md5, ":", 1); - MD5_Update(&md5, nonce, strlen(nonce)); + EVP_DigestInit_ex(md5, md, NULL); + EVP_DigestUpdate(md5, HA1_hex, strlen(HA1_hex)); + EVP_DigestUpdate(md5, ":", 1); + EVP_DigestUpdate(md5, nonce, strlen(nonce)); if (qop == QOP_AUTH) { - MD5_Update(&md5, ":", 1); - MD5_Update(&md5, nc, strlen(nc)); - MD5_Update(&md5, ":", 1); - MD5_Update(&md5, cnonce, strlen(cnonce)); - MD5_Update(&md5, ":", 1); - MD5_Update(&md5, "auth", strlen("auth")); + EVP_DigestUpdate(md5, ":", 1); + EVP_DigestUpdate(md5, nc, strlen(nc)); + EVP_DigestUpdate(md5, ":", 1); + EVP_DigestUpdate(md5, cnonce, strlen(cnonce)); + EVP_DigestUpdate(md5, ":", 1); + EVP_DigestUpdate(md5, "auth", strlen("auth")); } - MD5_Update(&md5, ":", 1); - MD5_Update(&md5, HA2_hex, strlen(HA2_hex)); - MD5_Final(hashbuf, &md5); + EVP_DigestUpdate(md5, ":", 1); + EVP_DigestUpdate(md5, HA2_hex, strlen(HA2_hex)); + EVP_DigestFinal_ex(md5, hashbuf, &hash_size); - enhex(buf, hashbuf, sizeof(hashbuf)); + enhex(buf, hashbuf, hash_size); } /* Extract the issuance time from a nonce (without checking other aspects of @@ -258,7 +266,7 @@ char *http_digest_proxy_authorization(const struct http_challenge *challenge, varying client nonce count. */ static const u32 nc = 0x00000001; - char response_hex[MD5_DIGEST_LENGTH * 2 + 1]; + char response_hex[EVP_MAX_MD_SIZE * 2 + 1]; unsigned char cnonce[CNONCE_LENGTH]; char cnonce_buf[CNONCE_LENGTH * 2 + 1]; char nc_buf[8 + 1]; @@ -322,7 +330,7 @@ int http_digest_check_credentials(const char *username, const char *realm, const char *password, const char *method, const struct http_credentials *credentials) { - char response_hex[MD5_DIGEST_LENGTH * 2 + 1]; + char response_hex[EVP_MAX_MD_SIZE * 2 + 1]; struct timeval tv; char *nonce; diff --git a/ncat/ncat.h b/ncat/ncat.h index 01c8e27ed..238a5c048 100644 --- a/ncat/ncat.h +++ b/ncat/ncat.h @@ -66,10 +66,6 @@ #include -#ifdef HAVE_OPENSSL -#include -#endif - #include "nsock.h" #include "util.h" #include "sys_wrap.h" diff --git a/ncat/ncat_connect.c b/ncat/ncat_connect.c index 2f216e52a..0e4b50761 100644 --- a/ncat/ncat_connect.c +++ b/ncat/ncat_connect.c @@ -80,6 +80,11 @@ #ifdef HAVE_OPENSSL #include #include + +/* Deprecated in OpenSSL 3.0 */ +#if OPENSSL_API_LEVEL >= 30000 +#define SSL_get_peer_certificate SSL_get1_peer_certificate +#endif #endif #ifdef WIN32 diff --git a/ncat/ncat_ssl.c b/ncat/ncat_ssl.c index 7749b2964..bc9bdc11f 100644 --- a/ncat/ncat_ssl.c +++ b/ncat/ncat_ssl.c @@ -67,7 +67,6 @@ #include #include -#include #include #include #include @@ -81,6 +80,14 @@ #define FUNC_ASN1_STRING_data ASN1_STRING_data #endif +#if OPENSSL_API_LEVEL >= 30000 +#include +/* Deprecated in OpenSSL 3.0 */ +#define SSL_get_peer_certificate SSL_get1_peer_certificate +#else +#include +#endif + /* Required for windows compilation to Eliminate APPLINK errors. See http://www.openssl.org/support/faq.html#PROG2 */ #ifdef WIN32 @@ -110,6 +117,15 @@ SSL_CTX *setup_ssl_listen(void) OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); SSL_load_error_strings(); +#elif OPENSSL_API_LEVEL >= 30000 + if (NULL == OSSL_PROVIDER_load(NULL, "legacy")) + { + loguser("OpenSSL legacy provider failed to load.\n"); + } + if (NULL == OSSL_PROVIDER_load(NULL, "default")) + { + loguser("OpenSSL default provider failed to load.\n"); + } #endif /* RAND_status initializes the random number generator through a variety of @@ -455,14 +471,16 @@ int ssl_post_connect_check(SSL *ssl, const char *hostname) "Making Certificates"; and apps/req.c in the OpenSSL source. */ static int ssl_gen_cert(X509 **cert, EVP_PKEY **key) { - RSA *rsa = NULL; X509_NAME *subj; X509_EXTENSION *ext; X509V3_CTX ctx; - BIGNUM *bne = NULL; const char *commonName = "localhost"; char dNSName[128]; - int rc, ret=0; + int rc; +#if OPENSSL_API_LEVEL < 30000 + int ret = 0; + RSA *rsa = NULL; + BIGNUM *bne = NULL; *cert = NULL; *key = NULL; @@ -491,6 +509,12 @@ static int ssl_gen_cert(X509 **cert, EVP_PKEY **key) RSA_free(rsa); goto err; } +#else + *cert = NULL; + *key = EVP_RSA_gen(DEFAULT_KEY_BITS); + if (*key == NULL) + goto err; +#endif /* Generate a certificate. */ *cert = X509_new(); diff --git a/ncat/ncat_ssl.h b/ncat/ncat_ssl.h index 458736e27..fca0b1771 100644 --- a/ncat/ncat_ssl.h +++ b/ncat/ncat_ssl.h @@ -67,6 +67,18 @@ #include #include +/* OPENSSL_API_LEVEL per OpenSSL 3.0: decimal MMmmpp */ +#ifndef OPENSSL_API_LEVEL +# if OPENSSL_API_COMPAT < 0x900000L +# define OPENSSL_API_LEVEL (OPENSSL_API_COMPAT) +# else +# define OPENSSL_API_LEVEL \ + (((OPENSSL_API_COMPAT >> 28) & 0xF) * 10000 \ + + ((OPENSSL_API_COMPAT >> 20) & 0xFF) * 100 \ + + ((OPENSSL_API_COMPAT >> 12) & 0xFF)) +# endif +#endif + #define NCAT_CA_CERTS_FILE "ca-bundle.crt" enum { diff --git a/ncat/test/test-wildcard.c b/ncat/test/test-wildcard.c index 8eda9e943..428ece71c 100644 --- a/ncat/test/test-wildcard.c +++ b/ncat/test/test-wildcard.c @@ -12,7 +12,6 @@ are rejected. The SSL transactions happen over OpenSSL BIO pairs. #include #include -#include #include #include #include @@ -20,6 +19,10 @@ are rejected. The SSL transactions happen over OpenSSL BIO pairs. #include #include "ncat_core.h" +#include "ncat_ssl.h" +#if OPENSSL_API_LEVEL < 30000 +#include +#endif #define KEY_BITS 2048 @@ -291,9 +294,10 @@ stack_err: static int gen_cert(X509 **cert, EVP_PKEY **key, const struct lstr commonNames[], const struct lstr dNSNames[]) { +#if OPENSSL_API_LEVEL < 30000 + int rc, ret=0; RSA *rsa = NULL; BIGNUM *bne = NULL; - int rc, ret=0; *cert = NULL; *key = NULL; @@ -322,6 +326,12 @@ static int gen_cert(X509 **cert, EVP_PKEY **key, RSA_free(rsa); goto err; } +#else + *cert = NULL; + *key = EVP_RSA_gen(KEY_BITS); + if (*key == NULL) + goto err; +#endif /* Generate a certificate. */ *cert = X509_new(); diff --git a/nse_openssl.cc b/nse_openssl.cc index 92dea3ac8..f75ad27fa 100644 --- a/nse_openssl.cc +++ b/nse_openssl.cc @@ -8,18 +8,10 @@ #include #include -#include #include #include #include -#include -#include #include -#ifndef OPENSSL_NO_RC4 -#include -#endif -#include -#include #if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined LIBRESSL_VERSION_NUMBER #define HAVE_OPAQUE_STRUCTS 1 @@ -37,13 +29,34 @@ #endif #include "nse_lua.h" -#if OPENSSL_API_COMPAT >= 0x10100000L - /* Needed for get_random_bytes, since RAND_pseudo_bytes is gone */ - #include -#endif +/* Needed for get_random_bytes */ +#include +#include "NmapOps.h" +#include "output.h" +extern NmapOps o; #include "nse_openssl.h" +/* OPENSSL_API_LEVEL per OpenSSL 3.0: decimal MMmmpp */ +#ifndef OPENSSL_API_LEVEL +# if OPENSSL_API_COMPAT < 0x900000L +# define OPENSSL_API_LEVEL (OPENSSL_API_COMPAT) +# else +# define OPENSSL_API_LEVEL \ + (((OPENSSL_API_COMPAT >> 28) & 0xF) * 10000 \ + + ((OPENSSL_API_COMPAT >> 20) & 0xFF) * 100 \ + + ((OPENSSL_API_COMPAT >> 12) & 0xFF)) +# endif +#endif + + +#if OPENSSL_API_LEVEL >= 30000 +#include +#endif + +#define NSE_SSL_LUA_ERR(_L) \ + luaL_error(_L, "OpenSSL error: %s", ERR_error_string(ERR_get_error(), NULL)) + typedef struct bignum_data { BIGNUM * bn; bool should_free; @@ -93,14 +106,6 @@ static int l_bignum_rand( lua_State *L ) /** bignum_rand( number bits ) */ return nse_pushbn(L, num); } -static int l_bignum_pseudo_rand( lua_State *L ) /** bignum_pseudo_rand( number bits ) */ -{ - size_t bits = luaL_checkinteger( L, 1 ); - BIGNUM * num = BN_new(); - BN_pseudo_rand( num, bits, -1, 0 ); - return nse_pushbn(L, num); -} - static int l_bignum_mod_exp( lua_State *L ) /** bignum_mod_exp( BIGNUM a, BIGNUM p, BIGNUM m ) */ { bignum_data_t * a = (bignum_data_t *) luaL_checkudata(L, 1, "BIGNUM"); @@ -174,29 +179,42 @@ static int l_bignum_is_bit_set( lua_State *L ) /** bignum_set_bit( BIGNUM bn, nu return 1; } -static int l_bignum_is_prime( lua_State *L ) /** bignum_is_prime( BIGNUM p, number nchecks ) */ +static int l_bignum_is_prime( lua_State *L ) /** bignum_is_prime( BIGNUM p ) */ { bignum_data_t * p = (bignum_data_t *) luaL_checkudata( L, 1, "BIGNUM" ); - int nchecks = luaL_optinteger( L, 2, BN_prime_checks ); BN_CTX * ctx = BN_CTX_new(); - int is_prime = BN_is_prime_ex( p->bn, nchecks, ctx, NULL ); + int is_prime = +#if OPENSSL_API_LEVEL < 30000 + BN_is_prime_ex( p->bn, BN_prime_checks, ctx, NULL ); +#else + BN_check_prime( p->bn, ctx, NULL ); +#endif BN_CTX_free( ctx ); lua_pushboolean( L, is_prime ); return 1; } -static int l_bignum_is_safe_prime( lua_State *L ) /** bignum_is_safe_prime( BIGNUM p, number nchecks ) */ +static int l_bignum_is_safe_prime( lua_State *L ) /** bignum_is_safe_prime( BIGNUM p ) */ { bignum_data_t * p = (bignum_data_t *) luaL_checkudata( L, 1, "BIGNUM" ); - int nchecks = luaL_optinteger( L, 2, BN_prime_checks ); BN_CTX * ctx = BN_CTX_new(); - int is_prime = BN_is_prime_ex( p->bn, nchecks, ctx, NULL ); + int is_prime = +#if OPENSSL_API_LEVEL < 30000 + BN_is_prime_ex( p->bn, BN_prime_checks, ctx, NULL ); +#else + BN_check_prime( p->bn, ctx, NULL ); +#endif int is_safe = 0; if (is_prime) { BIGNUM * n = BN_dup( p->bn ); BN_sub_word( n, (BN_ULONG)1 ); BN_div_word( n, (BN_ULONG)2 ); - is_safe = BN_is_prime_ex( n, nchecks, ctx, NULL ); + is_safe = +#if OPENSSL_API_LEVEL < 30000 + BN_is_prime_ex( n, BN_prime_checks, ctx, NULL ); +#else + BN_check_prime( n, ctx, NULL ); +#endif BN_clear_free( n ); } BN_CTX_free( ctx ); @@ -264,56 +282,12 @@ static int l_rand_pseudo_bytes( lua_State *L ) /** rand_pseudo_bytes( number byt unsigned char * result = (unsigned char *) malloc( len ); if (!result) return luaL_error( L, "Couldn't allocate memory."); -#if OPENSSL_API_COMPAT < 0x10100000L - RAND_pseudo_bytes( result, len ); -#else get_random_bytes( result, len ); -#endif lua_pushlstring( L, (char *) result, len ); free( result ); return 1; } -static int l_md4(lua_State *L) /** md4(string s) */ -{ - size_t len; - const unsigned char *s = (unsigned char *) luaL_checklstring( L, 1, &len ); - unsigned char digest[16]; - - lua_pushlstring( L, (char *) MD4( s, len, digest ), 16 ); - return 1; -} - -static int l_md5(lua_State *L) /** md5(string s) */ -{ - size_t len; - const unsigned char *s = (unsigned char *) luaL_checklstring( L, 1, &len ); - unsigned char digest[16]; - - lua_pushlstring( L, (char *) MD5( s, len, digest ), 16 ); - return 1; -} - -static int l_sha1(lua_State *L) /** sha1(string s) */ -{ - size_t len; - const unsigned char *s = (unsigned char *) luaL_checklstring( L, 1, &len ); - unsigned char digest[20]; - - lua_pushlstring( L, (char *) SHA1( s, len, digest ), 20 ); - return 1; -} - -static int l_ripemd160(lua_State *L) /** ripemd160(string s) */ -{ - size_t len; - const unsigned char *s = (unsigned char *) luaL_checklstring( L, 1, &len ); - unsigned char digest[20]; - - lua_pushlstring( L, (char *) RIPEMD160( s, len, digest ), 20 ); - return 1; -} - static int l_digest(lua_State *L) /** digest(string algorithm, string message) */ { size_t msg_len; @@ -338,9 +312,7 @@ static int l_digest(lua_State *L) /** digest(string algorithm, string messag 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) ); - unsigned long e = ERR_get_error(); - return luaL_error( L, "OpenSSL error %d in %s: function %s: %s", e, ERR_lib_error_string(e), - ERR_func_error_string(e), ERR_reason_error_string(e)); + return NSE_SSL_LUA_ERR(L); } FUNC_EVP_MD_CTX_cleanup( PASS_EVP_CTX(mdctx) ); @@ -348,6 +320,20 @@ static int l_digest(lua_State *L) /** digest(string algorithm, string messag return 1; } +/** md4(string s) */ +#define NSE_DECLARE_DIGEST(_mdname) \ +static int l_##_mdname(lua_State *L) \ +{ \ + lua_pushliteral(L, #_mdname); \ + lua_insert(L, 1); \ + return l_digest(L); \ +} + +NSE_DECLARE_DIGEST(md4) +NSE_DECLARE_DIGEST(md5) +NSE_DECLARE_DIGEST(sha1) +NSE_DECLARE_DIGEST(ripemd160) + static int l_hmac(lua_State *L) /** hmac(string algorithm, string key, string message) */ { size_t key_len, msg_len; @@ -432,9 +418,7 @@ static int l_encrypt(lua_State *L) /** encrypt( string algorithm, string key, st 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 ))) { - unsigned long e = ERR_get_error(); - return luaL_error( L, "OpenSSL error %d in %s: function %s: %s", e, ERR_lib_error_string(e), - ERR_func_error_string(e), ERR_reason_error_string(e)); + return NSE_SSL_LUA_ERR(L); } if (iv != NULL && (int) iv_len != EVP_CIPHER_CTX_iv_length( PASS_EVP_CTX(cipher_ctx) )) { @@ -452,9 +436,7 @@ static int l_encrypt(lua_State *L) /** encrypt( string algorithm, string key, st EVP_EncryptFinal_ex( PASS_EVP_CTX(cipher_ctx), out + out_len, &final_len ) )) { FUNC_EVP_CIPHER_CTX_cleanup( PASS_EVP_CTX(cipher_ctx) ); free( out ); - unsigned long e = ERR_get_error(); - return luaL_error( L, "OpenSSL error %d in %s: function %s: %s", e, ERR_lib_error_string(e), - ERR_func_error_string(e), ERR_reason_error_string(e)); + return NSE_SSL_LUA_ERR(L); } lua_pushlstring( L, (char *) out, out_len + final_len ); @@ -491,9 +473,7 @@ static int l_decrypt(lua_State *L) /** decrypt( string algorithm, string key, st 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 ))) { - unsigned long e = ERR_get_error(); - return luaL_error( L, "OpenSSL error %d in %s: function %s: %s", e, ERR_lib_error_string(e), - ERR_func_error_string(e), ERR_reason_error_string(e)); + return NSE_SSL_LUA_ERR(L); } if (iv != NULL && (int) iv_len != EVP_CIPHER_CTX_iv_length( PASS_EVP_CTX(cipher_ctx) )) { @@ -511,9 +491,7 @@ static int l_decrypt(lua_State *L) /** decrypt( string algorithm, string key, st EVP_DecryptFinal_ex( PASS_EVP_CTX(cipher_ctx), out + out_len, &final_len ) )) { FUNC_EVP_CIPHER_CTX_cleanup( PASS_EVP_CTX(cipher_ctx) ); free( out ); - unsigned long e = ERR_get_error(); - return luaL_error( L, "OpenSSL error %d in %s: function %s: %s", e, ERR_lib_error_string(e), - ERR_func_error_string(e), ERR_reason_error_string(e)); + return NSE_SSL_LUA_ERR(L); } lua_pushlstring( L, (char *) out, out_len + final_len ); @@ -531,51 +509,21 @@ static int l_DES_string_to_key(lua_State *L) /** DES_string_to_key( string data if (len != 7 ) return luaL_error( L, "String must have length of 7 bytes." ); - DES_cblock key; - key[0] = data[0]; + unsigned char key[8] = {0}; + // key is each 7 bits of data separated by 0 bit + // Clear the lsb of the first byte: + key[0] = data[0] & ~1; + // Least significant i bits of i-1 byte plus most significant 8-i bits of i-th byte + // clearing the lsb of result to keep only the 7-i bits of i-th byte for( int i = 1; i < 8; i++ ) - key[i] = data[i-1] << (8-i) | data[i] >> i; + key[i] = (data[i-1] << (8-i) | data[i] >> i) & ~1; - DES_set_odd_parity( &key ); // lgtm [cpp/weak-cryptographic-algorithm] + // DES_set_odd_parity( &key ); // lgtm [cpp/weak-cryptographic-algorithm] lua_pushlstring( L, (char *) key, 8 ); return 1; } -#ifndef OPENSSL_NO_RC4 -static int l_rc4_options (lua_State *L) -{ - lua_pushstring(L, RC4_options()); - return 1; -} - -static int l_rc4_encrypt (lua_State *L) -{ - RC4_KEY *key = (RC4_KEY *) lua_touserdata(L, lua_upvalueindex(1)); - size_t len; - const char *indata = luaL_checklstring(L, 1, &len); - unsigned char *outdata = (unsigned char *) lua_newuserdata(L, sizeof(unsigned char)*len); - - RC4(key, len, (const unsigned char *)indata, outdata); // lgtm [cpp/weak-cryptographic-algorithm] - lua_pushlstring(L, (const char *)outdata, len); - - return 1; -} - -static int l_rc4 (lua_State *L) -{ - size_t len; - const char *data = luaL_checklstring(L, 1, &len); - - lua_newuserdata(L, sizeof(RC4_KEY)); - RC4_set_key((RC4_KEY *)lua_touserdata(L, -1), (int)len, (const unsigned char *)data); // lgtm [cpp/weak-cryptographic-algorithm] - - lua_pushcclosure(L, l_rc4_encrypt, 1); - - return 1; -} -#endif - static const struct luaL_Reg bignum_methods[] = { { "num_bits", l_bignum_num_bits }, { "num_bytes", l_bignum_num_bytes }, @@ -604,7 +552,7 @@ static const struct luaL_Reg openssllib[] = { { "bignum_dec2bn", l_bignum_dec2bn }, { "bignum_hex2bn", l_bignum_hex2bn }, { "bignum_rand", l_bignum_rand }, - { "bignum_pseudo_rand", l_bignum_pseudo_rand }, + { "bignum_pseudo_rand", l_bignum_rand }, { "bignum_bn2bin", l_bignum_bn2bin }, { "bignum_bn2dec", l_bignum_bn2dec }, { "bignum_bn2hex", l_bignum_bn2hex }, @@ -613,10 +561,12 @@ static const struct luaL_Reg openssllib[] = { { "bignum_div", l_bignum_div }, { "rand_bytes", l_rand_bytes }, { "rand_pseudo_bytes", l_rand_pseudo_bytes }, + // These functions declared above with NSE_DECLARE_DIGEST { "md4", l_md4 }, { "md5", l_md5 }, { "sha1", l_sha1 }, { "ripemd160", l_ripemd160 }, + { "digest", l_digest }, { "hmac", l_hmac }, { "encrypt", l_encrypt }, @@ -624,10 +574,6 @@ static const struct luaL_Reg openssllib[] = { { "DES_string_to_key", l_DES_string_to_key }, { "supported_digests", l_supported_digests }, { "supported_ciphers", l_supported_ciphers }, -#ifndef OPENSSL_NO_RC4 - { "rc4_options", l_rc4_options }, - { "rc4", l_rc4 }, -#endif { NULL, NULL } }; @@ -636,11 +582,15 @@ LUALIB_API int luaopen_openssl(lua_State *L) { #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined LIBRESSL_VERSION_NUMBER OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); -#else - /* This is now deprecated in OpenSSL 1.1.0 _ No explicit initialisation - or de-initialisation is necessary */ - // OpenSSL_add_all_algorithms(); - // ERR_load_crypto_strings(); +#elif OPENSSL_API_LEVEL >= 30000 + if (NULL == OSSL_PROVIDER_load(NULL, "legacy") && o.verbose) + { + log_write(LOG_STDOUT, "%s: OpenSSL legacy provider failed to load.\n", SCRIPT_ENGINE); + } + if (NULL == OSSL_PROVIDER_load(NULL, "default") && o.verbose) + { + log_write(LOG_STDOUT, "%s: OpenSSL default provider failed to load.\n", SCRIPT_ENGINE); + } #endif luaL_newlib(L, openssllib); diff --git a/nse_ssl_cert.cc b/nse_ssl_cert.cc index 469d9cc4d..d2a30be90 100644 --- a/nse_ssl_cert.cc +++ b/nse_ssl_cert.cc @@ -74,7 +74,6 @@ #include #include #include -#include #include #include #include @@ -90,6 +89,27 @@ #define X509_get0_notAfter X509_get_notAfter #endif +/* OPENSSL_API_LEVEL per OpenSSL 3.0: decimal MMmmpp */ +#ifndef OPENSSL_API_LEVEL +# if OPENSSL_API_COMPAT < 0x900000L +# define OPENSSL_API_LEVEL (OPENSSL_API_COMPAT) +# else +# define OPENSSL_API_LEVEL \ + (((OPENSSL_API_COMPAT >> 28) & 0xF) * 10000 \ + + ((OPENSSL_API_COMPAT >> 20) & 0xFF) * 100 \ + + ((OPENSSL_API_COMPAT >> 12) & 0xFF)) +# endif +#endif + +#if OPENSSL_API_LEVEL >= 30000 +#include +/* Deprecated in OpenSSL 3.0 */ +#define SSL_get_peer_certificate SSL_get1_peer_certificate +#else +#include +#endif + + /* struct tm */ #include @@ -439,7 +459,39 @@ static const char *pkey_type_to_string(int type) } int lua_push_ecdhparams(lua_State *L, EVP_PKEY *pubkey) { -#ifdef HAVE_OPENSSL_EC +#if OPENSSL_API_LEVEL >= 30000 + char tmp[64] = {0}; + size_t len = 0; + /* This structure (ecdhparams.curve_params) comes from tls.lua */ + lua_createtable(L, 0, 1); /* ecdhparams */ + lua_createtable(L, 0, 2); /* curve_params */ + if (EVP_PKEY_get_utf8_string_param(pubkey, OSSL_PKEY_PARAM_GROUP_NAME, + tmp, sizeof(tmp), &len)) { + lua_pushlstring(L, tmp, len); + lua_setfield(L, -2, "curve"); + lua_pushliteral(L, "namedcurve"); + lua_setfield(L, -2, "ec_curve_type"); + } + else if (EVP_PKEY_get_utf8_string_param(pubkey, OSSL_PKEY_PARAM_EC_FIELD_TYPE, + tmp, sizeof(tmp), &len)) { + /* According to RFC 5480 section 2.1.1, explicit curves must not be used with + X.509. This may change in the future, but for now it doesn't seem worth it + to add in code to extract the extra parameters. */ + if (0 == strncmp(tmp, "prime-field", len)) { + lua_pushliteral(L, "explicit_prime"); + } + else if (0 == strncmp(tmp, "characteristic-two-field", len)) { + lua_pushliteral(L, "explicit_char2"); + } + else { + /* Something weird happened. */ + lua_pushlstring(L, tmp, len); + } + lua_setfield(L, -2, "ec_curve_type"); + } + lua_setfield(L, -2, "curve_params"); + return 1; +#elif defined(HAVE_OPENSSL_EC) EC_KEY *ec_key = EVP_PKEY_get1_EC_KEY(pubkey); const EC_GROUP *group = EC_KEY_get0_group(ec_key); int nid; @@ -582,16 +634,24 @@ static int parse_ssl_cert(lua_State *L, X509 *cert) else #endif if (pkey_type == EVP_PKEY_RSA) { +#if OPENSSL_API_LEVEL < 30000 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 ); - data->should_free = false; #if HAVE_OPAQUE_STRUCTS - const BIGNUM *n, *e; + BIGNUM *n = NULL, *e = NULL; +#if OPENSSL_API_LEVEL < 30000 + data->should_free = false; RSA_get0_key(rsa, &n, &e, NULL); +#else + 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; @@ -601,15 +661,21 @@ static int parse_ssl_cert(lua_State *L, X509 *cert) data = (bignum_data_t *) lua_newuserdata( L, sizeof(bignum_data_t)); luaL_getmetatable( L, "BIGNUM" ); lua_setmetatable( L, -2 ); - data->should_free = false; #if HAVE_OPAQUE_STRUCTS +#if OPENSSL_API_LEVEL < 30000 + 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_API_LEVEL < 30000 RSA_free(rsa); } +#endif } lua_pushstring(L, pkey_type_to_string(pkey_type)); lua_setfield(L, -2, "type"); diff --git a/nselib/openssl.luadoc b/nselib/openssl.luadoc index d8ba53aed..b794aa65b 100644 --- a/nselib/openssl.luadoc +++ b/nselib/openssl.luadoc @@ -52,20 +52,20 @@ function bignum_is_bit_set(bignum, position) -- -- Performs Miller-Rabin probabilistic primality tests. -- @param bignum bignum to check for primality --- @param nchecks Number of checks to perform. Default: number of checks dependent on bitsize of bignum, with a false positive rate of at most 2^-80 --- @return True if the number is probably prime, false if it is composite. -function bignum_is_prime(bignum, nchecks) +-- @return True if the number is probably prime with a false positive rate of at most 2^-80, false if it is composite. + +function bignum_is_prime(bignum) --- Checks whether bignum is a safe prime. -- -- A safe prime is defined as a prime p so that (p-1)/2 is also prime. Using -- non-safe primes in discrete logarithm cryptography like Diffie-Hellman can --- result in weak, easily broken key exchanges. +-- result in weak, easily broken key exchanges. The number of checks is +-- dependent on bitsize of bignum, with a false positive rate of at most 2^-80 -- @param bignum bignum to check for primality --- @param nchecks Number of checks to perform. Default: number of checks dependent on bitsize of bignum, with a false positive rate of at most 2^-80 -- @return True if the number is a safe prime, false if it is not. -- @return True if the number is probably prime, false if it is composite. -function bignum_is_safe_prime(bignum, nchecks) +function bignum_is_safe_prime(bignum) --- Converts a binary-encoded string into a bignum. -- @param string Binary string. @@ -103,8 +103,10 @@ function bignum_bn2hex(bignum) function bignum_rand(bits) --- Returns a pseudorandom bignum. +-- +-- Alias for bignum_rand(). -- @param bits Size of the returned bignum in bits. --- @return Pseudorandom bignum. +-- @return Random bignum. function bignum_pseudo_rand(bits) --- Returns the bignum which is the result of a^p mod @@ -208,12 +210,3 @@ function supported_digests() -- @param data A 7-byte string. -- @return An 8-byte string. function DES_string_to_key(data) - ---- Returns options for RC4. --- @return Option string. -function rc4_options() - ---- Function which generates an RC4 cipher function with the given key. --- @param key_data The key for the cipher. --- @return A function which performs the RC4 stream cipher on an input string and returns the result. -function rc4(key_data) diff --git a/nsock/src/nsock_ssl.c b/nsock/src/nsock_ssl.c index e723f4ad5..95f80a9b0 100644 --- a/nsock/src/nsock_ssl.c +++ b/nsock/src/nsock_ssl.c @@ -59,10 +59,14 @@ #include "nsock.h" #include "nsock_internal.h" +#include "nsock_log.h" #include "nsock_ssl.h" #include "netutils.h" #if HAVE_OPENSSL +#if OPENSSL_API_LEVEL >= 30000 +#include +#endif /* Disallow anonymous ciphers (Diffie-Hellman key agreement), low bit-strength * ciphers, export-crippled ciphers, and MD5. Prefer ciphers in decreasing order @@ -85,6 +89,15 @@ static SSL_CTX *ssl_init_helper(const SSL_METHOD *method) { #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined LIBRESSL_VERSION_NUMBER SSL_load_error_strings(); SSL_library_init(); +#elif OPENSSL_API_LEVEL >= 30000 + if (NULL == OSSL_PROVIDER_load(NULL, "legacy")) + { + nsock_log_error("OpenSSL legacy provider failed to load.\n"); + } + if (NULL == OSSL_PROVIDER_load(NULL, "default")) + { + nsock_log_error("OpenSSL default provider failed to load.\n"); + } #endif ctx = SSL_CTX_new(method); diff --git a/nsock/src/nsock_ssl.h b/nsock/src/nsock_ssl.h index 7b94b7d5c..877159247 100644 --- a/nsock/src/nsock_ssl.h +++ b/nsock/src/nsock_ssl.h @@ -69,6 +69,24 @@ #include #include +/* OPENSSL_API_LEVEL per OpenSSL 3.0: decimal MMmmpp */ +#ifndef OPENSSL_API_LEVEL +# if OPENSSL_API_COMPAT < 0x900000L +# define OPENSSL_API_LEVEL (OPENSSL_API_COMPAT) +# else +# define OPENSSL_API_LEVEL \ + (((OPENSSL_API_COMPAT >> 28) & 0xF) * 10000 \ + + ((OPENSSL_API_COMPAT >> 20) & 0xFF) * 100 \ + + ((OPENSSL_API_COMPAT >> 12) & 0xFF)) +# endif +#endif + + +#if OPENSSL_API_LEVEL >= 30000 +/* Deprecated in OpenSSL 3.0 */ +#define SSL_get_peer_certificate SSL_get1_peer_certificate +#endif + struct sslinfo { /* SSL_ERROR_NONE, SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_READ, or * SSL_ERROR_WANT_WRITE */