Revision control

Copy as Markdown

// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// Qt-Security score:critical reason:execute-external-code
#include <QtMultimedia/private/qsymbolsresolveutils_p.h>
#include <qstringliteral.h>
#include <openssl/bio.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>
#include <openssl/params.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
using namespace Qt::StringLiterals;
[[maybe_unused]] static constexpr auto SHLIB_VERSION =
#if defined(OPENSSL_SHLIB_VERSION)
OPENSSL_SHLIB_VERSION;
#elif defined(SHLIB_VERSION_NUMBER)
SHLIB_VERSION_NUMBER;
#endif
#if !defined(Q_OS_ANDROID)
CHECK_VERSIONS("ssl", SSL_NEEDED_SOVERSION, SHLIB_VERSION);
#endif
static std::unique_ptr<QLibrary> loadLib()
{
auto lib = std::make_unique<QLibrary>();
auto tryLoad = [&](QString sslName, auto version) {
lib->setFileNameAndVersion(sslName, version);
return lib->load();
};
// openssl on Android has specific suffixes
#if defined(Q_OS_ANDROID)
{
auto suffix = qEnvironmentVariable("ANDROID_OPENSSL_SUFFIX");
if (suffix.isEmpty()) {
#if (OPENSSL_VERSION_NUMBER >> 28) < 3 // major version < 3
suffix = "_1_1"_L1;
#elif OPENSSL_VERSION_MAJOR == 3
suffix = "_3"_L1;
#else
static_assert(false, "Unexpected openssl version");
#endif
}
if (tryLoad("ssl"_L1 + suffix, -1))
return lib;
}
#endif
if (tryLoad("ssl"_L1, SSL_NEEDED_SOVERSION ""_L1))
return lib;
return {};
};
BEGIN_INIT_FUNCS("ssl", loadLib)
// ASN1 functions
INIT_FUNC(ASN1_INTEGER_set);
INIT_FUNC(ASN1_INTEGER_set_uint64);
// BN functions
INIT_FUNC(BN_value_one);
INIT_FUNC(BN_mod_word);
INIT_FUNC(BN_div_word)
INIT_FUNC(BN_mul_word)
INIT_FUNC(BN_add_word)
INIT_FUNC(BN_sub_word)
INIT_FUNC(BN_set_word)
INIT_FUNC(BN_new)
INIT_FUNC(BN_cmp)
INIT_FUNC(BN_free);
INIT_FUNC(BN_copy);
INIT_FUNC(BN_CTX_new);
INIT_FUNC(BN_CTX_free);
INIT_FUNC(BN_CTX_start);
INIT_FUNC(BN_CTX_get);
INIT_FUNC(BN_CTX_end);
INIT_FUNC(BN_rand);
INIT_FUNC(BN_mod_exp);
INIT_FUNC(BN_num_bits);
INIT_FUNC(BN_num_bits_word);
INIT_FUNC(BN_bn2hex);
INIT_FUNC(BN_bn2dec);
INIT_FUNC(BN_hex2bn);
INIT_FUNC(BN_dec2bn);
INIT_FUNC(BN_asc2bn);
INIT_FUNC(BN_bn2bin);
INIT_FUNC(BN_bin2bn);
// BIO-related functions
INIT_FUNC(BIO_new);
INIT_FUNC(BIO_new_mem_buf);
INIT_FUNC(BIO_free);
INIT_FUNC(BIO_read);
INIT_FUNC(BIO_write);
INIT_FUNC(BIO_s_mem);
INIT_FUNC(BIO_ctrl);
INIT_FUNC(BIO_set_data);
INIT_FUNC(BIO_get_data);
INIT_FUNC(BIO_set_init);
INIT_FUNC(BIO_set_flags);
INIT_FUNC(BIO_test_flags);
INIT_FUNC(BIO_clear_flags);
INIT_FUNC(BIO_meth_new);
INIT_FUNC(BIO_meth_free);
INIT_FUNC(BIO_meth_set_write);
INIT_FUNC(BIO_meth_set_read);
INIT_FUNC(BIO_meth_set_puts);
INIT_FUNC(BIO_meth_set_gets);
INIT_FUNC(BIO_meth_set_ctrl);
INIT_FUNC(BIO_meth_set_create);
INIT_FUNC(BIO_meth_set_destroy);
INIT_FUNC(BIO_meth_set_callback_ctrl);
INIT_FUNC(BIO_read_ex);
// DTLS functions
INIT_FUNC(DTLS_client_method);
INIT_FUNC(DTLS_get_data_mtu);
INIT_FUNC(DTLS_server_method);
// EVP functions
INIT_FUNC(EVP_PKEY_CTX_free);
INIT_FUNC(EVP_PKEY_CTX_new_from_name);
INIT_FUNC(EVP_PKEY_CTX_set_params);
INIT_FUNC(EVP_PKEY_Q_keygen);
INIT_FUNC(EVP_PKEY_keygen_init);
INIT_FUNC(EVP_PKEY_keygen);
INIT_FUNC(EVP_PKEY_free);
INIT_FUNC(EVP_PKEY_generate);
INIT_FUNC(EVP_sha1);
INIT_FUNC(EVP_sha256);
// PEM functions
INIT_FUNC(PEM_read_bio_PrivateKey);
INIT_FUNC(PEM_read_bio_X509);
INIT_FUNC(PEM_write_bio_PrivateKey);
INIT_FUNC(PEM_write_bio_X509);
// SSL functions
INIT_FUNC(SSL_CTX_ctrl);
INIT_FUNC(SSL_CTX_free);
INIT_FUNC(SSL_CTX_load_verify_locations);
INIT_FUNC(SSL_CTX_new);
INIT_FUNC(SSL_CTX_set_default_verify_paths);
INIT_FUNC(SSL_CTX_set_info_callback);
INIT_FUNC(SSL_CTX_set_options);
INIT_FUNC(SSL_CTX_set_tlsext_use_srtp);
INIT_FUNC(SSL_CTX_set_verify);
INIT_FUNC(SSL_CTX_up_ref);
INIT_FUNC(SSL_CTX_use_PrivateKey);
INIT_FUNC(SSL_CTX_use_PrivateKey_file);
INIT_FUNC(SSL_CTX_use_certificate)
INIT_FUNC(SSL_CTX_use_certificate_chain_file);
INIT_FUNC(SSL_new);
INIT_FUNC(SSL_up_ref);
INIT_FUNC(SSL_free);
INIT_FUNC(SSL_accept);
INIT_FUNC(SSL_do_handshake);
INIT_FUNC(SSL_stateless);
INIT_FUNC(SSL_connect);
INIT_FUNC(SSL_is_init_finished);
INIT_FUNC(SSL_read);
INIT_FUNC(SSL_peek);
INIT_FUNC(SSL_write);
INIT_FUNC(SSL_ctrl);
INIT_FUNC(SSL_get0_param);
INIT_FUNC(SSL_get_ex_data);
INIT_FUNC(SSL_set1_host);
INIT_FUNC(SSL_set_accept_state);
INIT_FUNC(SSL_set_bio);
INIT_FUNC(SSL_set_connect_state);
INIT_FUNC(SSL_set_ex_data);
INIT_FUNC(SSL_set_hostflags);
INIT_FUNC(SSL_set_options);
INIT_FUNC(SSL_shutdown);
INIT_FUNC(SSL_state_string);
INIT_FUNC(SSL_state_string_long);
INIT_FUNC(SSL_export_keying_material);
// options are unsigned long in openssl 1.1.1, and uint64 in 3.x.x
INIT_FUNC(SSL_get_error);
INIT_FUNC(ERR_clear_error);
INIT_FUNC(ERR_get_error);
INIT_FUNC(ERR_error_string);
INIT_FUNC(ERR_error_string_n);
// TLS functions
INIT_FUNC(TLS_client_method);
INIT_FUNC(TLS_server_method);
// RAND functions
INIT_FUNC(RAND_bytes);
// X509 functions
INIT_FUNC(X509_NAME_add_entry_by_txt);
INIT_FUNC(X509_NAME_free);
INIT_FUNC(X509_NAME_new);
INIT_FUNC(X509_VERIFY_PARAM_set1_ip);
INIT_FUNC(X509_digest);
INIT_FUNC(X509_free);
INIT_FUNC(X509_get_serialNumber);
INIT_FUNC(X509_getm_notAfter);
INIT_FUNC(X509_getm_notBefore);
INIT_FUNC(X509_gmtime_adj);
INIT_FUNC(X509_new);
INIT_FUNC(X509_set_issuer_name);
INIT_FUNC(X509_set_pubkey);
INIT_FUNC(X509_set_subject_name);
INIT_FUNC(X509_set_version);
INIT_FUNC(X509_sign);
END_INIT_FUNCS()
//////////// Define
// ASN1 functions
DEFINE_FUNC(ASN1_INTEGER_set, 2);
DEFINE_FUNC(ASN1_INTEGER_set_uint64, 2);
// BN functions
DEFINE_FUNC(BN_value_one, 0);
DEFINE_FUNC(BN_mod_word, 2);
DEFINE_FUNC(BN_div_word, 2)
DEFINE_FUNC(BN_mul_word, 2)
DEFINE_FUNC(BN_add_word, 2)
DEFINE_FUNC(BN_sub_word, 2)
DEFINE_FUNC(BN_set_word, 2)
DEFINE_FUNC(BN_new, 0)
DEFINE_FUNC(BN_cmp, 2)
DEFINE_FUNC(BN_free, 1);
DEFINE_FUNC(BN_copy, 2);
DEFINE_FUNC(BN_CTX_new, 0);
DEFINE_FUNC(BN_CTX_free, 1);
DEFINE_FUNC(BN_CTX_start, 1);
DEFINE_FUNC(BN_CTX_get, 1);
DEFINE_FUNC(BN_CTX_end, 1);
DEFINE_FUNC(BN_rand, 4);
DEFINE_FUNC(BN_mod_exp, 5);
DEFINE_FUNC(BN_num_bits, 1);
DEFINE_FUNC(BN_num_bits_word, 1);
DEFINE_FUNC(BN_bn2hex, 1);
DEFINE_FUNC(BN_bn2dec, 1);
DEFINE_FUNC(BN_hex2bn, 2);
DEFINE_FUNC(BN_dec2bn, 2);
DEFINE_FUNC(BN_asc2bn, 2);
DEFINE_FUNC(BN_bn2bin, 2);
DEFINE_FUNC(BN_bin2bn, 3);
// BIO-related functions
DEFINE_FUNC(BIO_new, 1);
DEFINE_FUNC(BIO_new_mem_buf, 2);
DEFINE_FUNC(BIO_free, 1);
DEFINE_FUNC(BIO_read, 3, -1);
DEFINE_FUNC(BIO_write, 3, -1);
DEFINE_FUNC(BIO_s_mem, 0);
DEFINE_FUNC(BIO_ctrl, 4, -1);
DEFINE_FUNC(BIO_set_data, 2);
DEFINE_FUNC(BIO_get_data, 1);
DEFINE_FUNC(BIO_set_init, 2);
DEFINE_FUNC(BIO_set_flags, 2);
DEFINE_FUNC(BIO_test_flags, 2);
DEFINE_FUNC(BIO_clear_flags, 2);
DEFINE_FUNC(BIO_meth_new, 2);
DEFINE_FUNC(BIO_meth_free, 1);
DEFINE_FUNC(BIO_meth_set_write, 2);
DEFINE_FUNC(BIO_meth_set_read, 2);
DEFINE_FUNC(BIO_meth_set_puts, 2);
DEFINE_FUNC(BIO_meth_set_gets, 2);
DEFINE_FUNC(BIO_meth_set_ctrl, 2);
DEFINE_FUNC(BIO_meth_set_create, 2);
DEFINE_FUNC(BIO_meth_set_destroy, 2);
DEFINE_FUNC(BIO_meth_set_callback_ctrl, 2);
DEFINE_FUNC(BIO_read_ex, 4, 0);
// DTLS functions
DEFINE_FUNC(DTLS_client_method, 0);
DEFINE_FUNC(DTLS_get_data_mtu, 1);
DEFINE_FUNC(DTLS_server_method, 0);
// EVP functions
extern "C" [[maybe_unused]] EXPORT_FUNC EVP_PKEY *EVP_PKEY_Q_keygen(
OSSL_LIB_CTX *libctx,
const char *propq,
const char *type,
...)
{
const auto f = reinterpret_cast<decltype(::EVP_PKEY_Q_keygen)*>(
SymbolsResolverImpl::instance().EVP_PKEY_Q_keygen);
if (!f)
return nullptr;
va_list args;
va_start(args, type);
auto cleanup = qScopeGuard([&] {
va_end(args);
});
if (strcmp(type, "RSA") == 0) {
return f(libctx, propq, type, va_arg(args, size_t));
} else if (strcmp(type, "EC") == 0) {
return f(libctx, propq, type, va_arg(args, char *));
}
return f(libctx, propq, type);
}
DEFINE_FUNC(EVP_PKEY_CTX_free, 1);
DEFINE_FUNC(EVP_PKEY_CTX_new_from_name, 3);
DEFINE_FUNC(EVP_PKEY_CTX_set_params, 2);
DEFINE_FUNC(EVP_PKEY_free, 1);
DEFINE_FUNC(EVP_PKEY_generate, 2);
DEFINE_FUNC(EVP_PKEY_keygen_init, 1);
DEFINE_FUNC(EVP_PKEY_keygen, 2);
DEFINE_FUNC(EVP_sha1, 0);
DEFINE_FUNC(EVP_sha256, 0);
// PEM functions
DEFINE_FUNC(PEM_read_bio_PrivateKey, 4);
DEFINE_FUNC(PEM_read_bio_X509, 4);
DEFINE_FUNC(PEM_write_bio_PrivateKey, 7, 0);
DEFINE_FUNC(PEM_write_bio_X509, 2);
// SSL functions
DEFINE_FUNC(SSL_CTX_ctrl, 4, -1);
DEFINE_FUNC(SSL_CTX_free, 1);
DEFINE_FUNC(SSL_CTX_load_verify_locations, 3, 0);
DEFINE_FUNC(SSL_CTX_new, 1);
DEFINE_FUNC(SSL_CTX_set_default_verify_paths, 1);
DEFINE_FUNC(SSL_CTX_set_info_callback, 2);
DEFINE_FUNC(SSL_CTX_set_options, 2);
DEFINE_FUNC(SSL_CTX_set_tlsext_use_srtp, 2, 1);
DEFINE_FUNC(SSL_CTX_set_verify, 3);
DEFINE_FUNC(SSL_CTX_up_ref, 1);
DEFINE_FUNC(SSL_CTX_use_PrivateKey, 2);
DEFINE_FUNC(SSL_CTX_use_PrivateKey_file, 3);
DEFINE_FUNC(SSL_CTX_use_certificate, 2);
DEFINE_FUNC(SSL_CTX_use_certificate_chain_file, 2);
DEFINE_FUNC(SSL_new, 1);
DEFINE_FUNC(SSL_up_ref, 1);
DEFINE_FUNC(SSL_free, 1);
DEFINE_FUNC(SSL_accept, 1);
DEFINE_FUNC(SSL_do_handshake, 1, -1);
DEFINE_FUNC(SSL_stateless, 1);
DEFINE_FUNC(SSL_connect, 1);
DEFINE_FUNC(SSL_is_init_finished, 1, 0);
DEFINE_FUNC(SSL_read, 3, -1);
DEFINE_FUNC(SSL_peek, 3);
DEFINE_FUNC(SSL_write, 3, -1);
DEFINE_FUNC(SSL_ctrl, 4);
DEFINE_FUNC(SSL_get0_param, 1);
DEFINE_FUNC(SSL_get_ex_data, 2);
DEFINE_FUNC(SSL_set1_host, 2);
DEFINE_FUNC(SSL_set_accept_state, 1);
DEFINE_FUNC(SSL_set_bio, 3);
DEFINE_FUNC(SSL_set_connect_state, 1);
DEFINE_FUNC(SSL_set_ex_data, 3);
DEFINE_FUNC(SSL_set_hostflags, 2);
DEFINE_FUNC(SSL_set_options, 2);
DEFINE_FUNC(SSL_shutdown, 1);
DEFINE_FUNC(SSL_state_string, 1);
DEFINE_FUNC(SSL_state_string_long, 1);
DEFINE_FUNC(SSL_export_keying_material, 8, -1);
// options are unsigned long in openssl 1.1.1, and uint64 in 3.x.x
DEFINE_FUNC(SSL_get_error, 2, SSL_ERROR_SSL);
DEFINE_FUNC(ERR_clear_error, 0);
DEFINE_FUNC(ERR_get_error, 0);
static char ErrorString[] = "Ssl not found";
DEFINE_FUNC(ERR_error_string, 2, ErrorString);
// TODO: We could implement this one when SSL is not linked.
DEFINE_FUNC(ERR_error_string_n, 3);
// TLS functions
DEFINE_FUNC(TLS_client_method, 0);
DEFINE_FUNC(TLS_server_method, 0);
// RAND functions
DEFINE_FUNC(RAND_bytes, 2);
// X509 functions
DEFINE_FUNC(X509_NAME_add_entry_by_txt, 7);
DEFINE_FUNC(X509_NAME_free, 1);
DEFINE_FUNC(X509_NAME_new, 0);
DEFINE_FUNC(X509_VERIFY_PARAM_set1_ip, 3);
DEFINE_FUNC(X509_digest, 4, 0);
DEFINE_FUNC(X509_free, 1);
DEFINE_FUNC(X509_get_serialNumber, 1);
DEFINE_FUNC(X509_getm_notAfter, 1);
DEFINE_FUNC(X509_getm_notBefore, 1);
DEFINE_FUNC(X509_gmtime_adj, 2);
DEFINE_FUNC(X509_new, 0);
DEFINE_FUNC(X509_set_issuer_name, 2);
DEFINE_FUNC(X509_set_pubkey, 2);
DEFINE_FUNC(X509_set_subject_name, 2);
DEFINE_FUNC(X509_set_version, 2);
DEFINE_FUNC(X509_sign, 3);