diff --git a/contrib/epee/include/net/net_ssl.h b/contrib/epee/include/net/net_ssl.h index 108e6771bd6..e36823e9c22 100644 --- a/contrib/epee/include/net/net_ssl.h +++ b/contrib/epee/include/net/net_ssl.h @@ -38,8 +38,10 @@ #include #include #include +#include #define SSL_FINGERPRINT_SIZE 32 +#define SSL_RSA_BITS 4096 namespace epee { @@ -143,7 +145,6 @@ namespace net_utils bool is_ssl(const unsigned char *data, size_t len); bool ssl_support_from_string(ssl_support_t &ssl, boost::string_ref s); - bool create_ec_ssl_certificate(EVP_PKEY *&pkey, X509 *&cert); bool create_rsa_ssl_certificate(EVP_PKEY *&pkey, X509 *&cert); //! Store private key for `ssl` at `base + ".key"` unencrypted and certificate for `ssl` at `base + ".crt"`. diff --git a/contrib/epee/src/net_ssl.cpp b/contrib/epee/src/net_ssl.cpp index 3a5db81878e..2232d9a31e5 100644 --- a/contrib/epee/src/net_ssl.cpp +++ b/contrib/epee/src/net_ssl.cpp @@ -52,15 +52,6 @@ static void add_windows_root_certs(SSL_CTX *ctx) noexcept; namespace { - struct openssl_bio_free - { - void operator()(BIO* ptr) const noexcept - { - BIO_free(ptr); - } - }; - using openssl_bio = std::unique_ptr; - struct openssl_pkey_free { void operator()(EVP_PKEY* ptr) const noexcept @@ -70,55 +61,68 @@ namespace }; using openssl_pkey = std::unique_ptr; - struct openssl_rsa_free + boost::system::error_code load_ca_file(boost::asio::ssl::context& ctx, const std::string& path) { - void operator()(RSA* ptr) const noexcept + SSL_CTX* const ssl_ctx = ctx.native_handle(); // could be moved from context + if (ssl_ctx == nullptr) + return {boost::asio::error::invalid_argument}; + + if (!SSL_CTX_load_verify_locations(ssl_ctx, path.c_str(), nullptr)) { - RSA_free(ptr); + return boost::system::error_code{ + int(::ERR_get_error()), boost::asio::error::get_ssl_category() + }; } - }; - using openssl_rsa = std::unique_ptr; + return boost::system::error_code{}; + } - struct openssl_bignum_free + /** + * @brief Generate a new RSA private key. For OpenSSL >= 3.0, same as EVP_RSA_gen(SSL_RSA_BITS) + */ + EVP_PKEY* gen_rsa_pkey_compat() { - void operator()(BIGNUM* ptr) const noexcept - { - BN_free(ptr); +#if OPENSSL_VERSION_MAJOR >= 3 + return EVP_RSA_gen(SSL_RSA_BITS); +#else + EVP_PKEY* pkey = EVP_PKEY_new(); + if (!pkey) { + MERROR("Error allocating EVP private key"); + return NULL; } - }; - using openssl_bignum = std::unique_ptr; - struct openssl_ec_key_free - { - void operator()(EC_KEY* ptr) const noexcept + std::unique_ptr rsa(RSA_new(), &RSA_free); + if (!rsa) { - EC_KEY_free(ptr); + MERROR("Error allocating RSA private key"); + return NULL; } - }; - using openssl_ec_key = std::unique_ptr; - struct openssl_group_free - { - void operator()(EC_GROUP* ptr) const noexcept + std::unique_ptr exponent(BN_new(), &BN_free); + if (!exponent) { - EC_GROUP_free(ptr); + MERROR("Error allocating exponent"); + return NULL; } - }; - using openssl_group = std::unique_ptr; - boost::system::error_code load_ca_file(boost::asio::ssl::context& ctx, const std::string& path) - { - SSL_CTX* const ssl_ctx = ctx.native_handle(); // could be moved from context - if (ssl_ctx == nullptr) - return {boost::asio::error::invalid_argument}; + BN_set_word(exponent.get(), RSA_F4); - if (!SSL_CTX_load_verify_locations(ssl_ctx, path.c_str(), nullptr)) + if (RSA_generate_key_ex(rsa.get(), SSL_RSA_BITS, exponent.get(), nullptr) != 1) { - return boost::system::error_code{ - int(::ERR_get_error()), boost::asio::error::get_ssl_category() - }; + MERROR("Error generating RSA private key"); + return NULL; } - return boost::system::error_code{}; + + if (EVP_PKEY_assign_RSA(pkey, rsa.get()) <= 0) + { + MERROR("Error assigning RSA private key"); + return NULL; + } + + // the RSA key is now managed by the EVP_PKEY structure + (void)rsa.release(); + + return pkey; +#endif } } @@ -132,125 +136,14 @@ namespace net_utils bool create_rsa_ssl_certificate(EVP_PKEY *&pkey, X509 *&cert) { MINFO("Generating SSL certificate"); - pkey = EVP_PKEY_new(); - if (!pkey) - { - MERROR("Failed to create new private key"); - return false; - } - - openssl_pkey pkey_deleter{pkey}; - openssl_rsa rsa{RSA_new()}; - if (!rsa) - { - MERROR("Error allocating RSA private key"); - return false; - } - - openssl_bignum exponent{BN_new()}; - if (!exponent) - { - MERROR("Error allocating exponent"); - return false; - } - - BN_set_word(exponent.get(), RSA_F4); - - if (RSA_generate_key_ex(rsa.get(), 4096, exponent.get(), nullptr) != 1) - { - MERROR("Error generating RSA private key"); - return false; - } - - if (EVP_PKEY_assign_RSA(pkey, rsa.get()) <= 0) - { - MERROR("Error assigning RSA private key"); - return false; - } - - // the RSA key is now managed by the EVP_PKEY structure - (void)rsa.release(); - - cert = X509_new(); - if (!cert) - { - MERROR("Failed to create new X509 certificate"); - return false; - } - ASN1_INTEGER_set(X509_get_serialNumber(cert), 1); - X509_gmtime_adj(X509_get_notBefore(cert), 0); - X509_gmtime_adj(X509_get_notAfter(cert), 3600 * 24 * 182); // half a year - if (!X509_set_pubkey(cert, pkey)) - { - MERROR("Error setting pubkey on certificate"); - X509_free(cert); - return false; - } - X509_NAME *name = X509_get_subject_name(cert); - X509_set_issuer_name(cert, name); - - if (X509_sign(cert, pkey, EVP_sha256()) == 0) - { - MERROR("Error signing certificate"); - X509_free(cert); - return false; - } - (void)pkey_deleter.release(); - return true; -} - -bool create_ec_ssl_certificate(EVP_PKEY *&pkey, X509 *&cert, int type) -{ - MINFO("Generating SSL certificate"); - pkey = EVP_PKEY_new(); + pkey = gen_rsa_pkey_compat(); if (!pkey) { - MERROR("Failed to create new private key"); + MERROR("Failed to create new private key with gen_rsa_pkey_compat()"); return false; } openssl_pkey pkey_deleter{pkey}; - openssl_ec_key ec_key{EC_KEY_new()}; - if (!ec_key) - { - MERROR("Error allocating EC private key"); - return false; - } - - EC_GROUP *group = EC_GROUP_new_by_curve_name(type); - if (!group) - { - MERROR("Error getting EC group " << type); - return false; - } - openssl_group group_deleter{group}; - - EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); - EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED); - - if (!EC_GROUP_check(group, NULL)) - { - MERROR("Group failed check: " << ERR_reason_error_string(ERR_get_error())); - return false; - } - if (EC_KEY_set_group(ec_key.get(), group) != 1) - { - MERROR("Error setting EC group"); - return false; - } - if (EC_KEY_generate_key(ec_key.get()) != 1) - { - MERROR("Error generating EC private key"); - return false; - } - if (EVP_PKEY_assign_EC_KEY(pkey, ec_key.get()) <= 0) - { - MERROR("Error assigning EC private key"); - return false; - } - - // the key is now managed by the EVP_PKEY structure - (void)ec_key.release(); cert = X509_new(); if (!cert) @@ -362,17 +255,6 @@ boost::asio::ssl::context ssl_options_t::create_context() const X509 *cert; bool ok = false; -#ifdef USE_EXTRA_EC_CERT - CHECK_AND_ASSERT_THROW_MES(create_ec_ssl_certificate(pkey, cert, NID_secp256k1), "Failed to create certificate"); - CHECK_AND_ASSERT_THROW_MES(SSL_CTX_use_certificate(ctx, cert), "Failed to use generated certificate"); - if (!SSL_CTX_use_PrivateKey(ctx, pkey)) - MERROR("Failed to use generated EC private key for " << NID_secp256k1); - else - ok = true; - X509_free(cert); - EVP_PKEY_free(pkey); -#endif - CHECK_AND_ASSERT_THROW_MES(create_rsa_ssl_certificate(pkey, cert), "Failed to create certificate"); CHECK_AND_ASSERT_THROW_MES(SSL_CTX_use_certificate(ctx, cert), "Failed to use generated certificate"); if (!SSL_CTX_use_PrivateKey(ctx, pkey))