Replace QCA with a simple OpenSSL wrapper
This commit is contained in:
parent
956c88c964
commit
d948d882aa
6 changed files with 182 additions and 86 deletions
|
@ -10,7 +10,6 @@ project(kdeconnect VERSION ${RELEASE_SERVICE_VERSION})
|
||||||
|
|
||||||
set(KF_MIN_VERSION "5.101.0")
|
set(KF_MIN_VERSION "5.101.0")
|
||||||
set(QT_MIN_VERSION "5.15.2")
|
set(QT_MIN_VERSION "5.15.2")
|
||||||
set(QCA_MIN_VERSION "2.1.0")
|
|
||||||
|
|
||||||
find_package(ECM ${KF_MIN_VERSION} REQUIRED NO_MODULE)
|
find_package(ECM ${KF_MIN_VERSION} REQUIRED NO_MODULE)
|
||||||
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
|
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
|
||||||
|
@ -58,9 +57,6 @@ ecm_set_disabled_deprecation_versions(
|
||||||
add_library(kdeconnectversion INTERFACE)
|
add_library(kdeconnectversion INTERFACE)
|
||||||
target_include_directories(kdeconnectversion INTERFACE ${CMAKE_CURRENT_BINARY_DIR})
|
target_include_directories(kdeconnectversion INTERFACE ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
find_package(Qca-qt${QT_MAJOR_VERSION} ${QCA_MIN_VERSION} REQUIRED)
|
|
||||||
set(Qca_LIBRARY qca-qt${QT_MAJOR_VERSION})
|
|
||||||
|
|
||||||
set(KF5_REQUIRED_COMPONENTS I18n ConfigWidgets DBusAddons IconThemes Notifications KIO KCMUtils Service Solid Kirigami2 People WindowSystem GuiAddons DocTools)
|
set(KF5_REQUIRED_COMPONENTS I18n ConfigWidgets DBusAddons IconThemes Notifications KIO KCMUtils Service Solid Kirigami2 People WindowSystem GuiAddons DocTools)
|
||||||
|
|
||||||
set_package_properties(KF${QT_MAJOR_VERSION}Kirigami2 PROPERTIES
|
set_package_properties(KF${QT_MAJOR_VERSION}Kirigami2 PROPERTIES
|
||||||
|
|
|
@ -42,6 +42,7 @@ target_sources(kdeconnectcore PRIVATE
|
||||||
compositefiletransferjob.cpp
|
compositefiletransferjob.cpp
|
||||||
daemon.cpp
|
daemon.cpp
|
||||||
device.cpp
|
device.cpp
|
||||||
|
sslhelper.cpp
|
||||||
core_debug.cpp
|
core_debug.cpp
|
||||||
notificationserverinfo.cpp
|
notificationserverinfo.cpp
|
||||||
openconfig.cpp
|
openconfig.cpp
|
||||||
|
@ -55,13 +56,16 @@ ecm_qt_declare_logging_category(kdeconnectcore
|
||||||
|
|
||||||
target_include_directories(kdeconnectcore PUBLIC ${PROJECT_SOURCE_DIR})
|
target_include_directories(kdeconnectcore PUBLIC ${PROJECT_SOURCE_DIR})
|
||||||
|
|
||||||
|
find_package(OpenSSL REQUIRED)
|
||||||
|
|
||||||
target_link_libraries(kdeconnectcore
|
target_link_libraries(kdeconnectcore
|
||||||
PUBLIC
|
PUBLIC
|
||||||
Qt::Network
|
Qt::Network
|
||||||
KF${QT_MAJOR_VERSION}::CoreAddons
|
KF${QT_MAJOR_VERSION}::CoreAddons
|
||||||
${Qca_LIBRARY}
|
|
||||||
KF${QT_MAJOR_VERSION}::KIOCore
|
KF${QT_MAJOR_VERSION}::KIOCore
|
||||||
KF${QT_MAJOR_VERSION}::KIOGui
|
KF${QT_MAJOR_VERSION}::KIOGui
|
||||||
|
OpenSSL::Crypto
|
||||||
|
OpenSSL::SSL
|
||||||
PRIVATE
|
PRIVATE
|
||||||
Qt::DBus
|
Qt::DBus
|
||||||
KF${QT_MAJOR_VERSION}::I18n
|
KF${QT_MAJOR_VERSION}::I18n
|
||||||
|
|
|
@ -19,23 +19,19 @@
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
#include <QtCrypto>
|
|
||||||
|
|
||||||
#include "core_debug.h"
|
#include "core_debug.h"
|
||||||
#include "daemon.h"
|
#include "daemon.h"
|
||||||
#include "dbushelper.h"
|
#include "dbushelper.h"
|
||||||
#include "deviceinfo.h"
|
#include "deviceinfo.h"
|
||||||
#include "pluginloader.h"
|
#include "pluginloader.h"
|
||||||
|
#include "sslhelper.h"
|
||||||
|
|
||||||
const QFile::Permissions strictPermissions = QFile::ReadOwner | QFile::WriteOwner | QFile::ReadUser | QFile::WriteUser;
|
const QFile::Permissions strictPermissions = QFile::ReadOwner | QFile::WriteOwner | QFile::ReadUser | QFile::WriteUser;
|
||||||
|
|
||||||
struct KdeConnectConfigPrivate {
|
struct KdeConnectConfigPrivate {
|
||||||
// The Initializer object sets things up, and also does cleanup when it goes out of scope
|
EVP_PKEY *m_privateKey;
|
||||||
// Note it's not being used anywhere. That's intended
|
QSslCertificate m_certificate;
|
||||||
QCA::Initializer m_qcaInitializer;
|
|
||||||
|
|
||||||
QCA::PrivateKey m_privateKey;
|
|
||||||
QSslCertificate m_certificate; // Use QSslCertificate instead of QCA::Certificate due to compatibility with QSslSocket
|
|
||||||
|
|
||||||
QSettings *m_config;
|
QSettings *m_config;
|
||||||
QSettings *m_trustedDevices;
|
QSettings *m_trustedDevices;
|
||||||
|
@ -59,15 +55,6 @@ KdeConnectConfig &KdeConnectConfig::instance()
|
||||||
KdeConnectConfig::KdeConnectConfig()
|
KdeConnectConfig::KdeConnectConfig()
|
||||||
: d(new KdeConnectConfigPrivate)
|
: d(new KdeConnectConfigPrivate)
|
||||||
{
|
{
|
||||||
// qCDebug(KDECONNECT_CORE) << "QCA supported capabilities:" << QCA::supportedFeatures().join(",");
|
|
||||||
if (!QCA::isSupported("rsa")) {
|
|
||||||
qCritical() << "Could not find support for RSA in your QCA installation";
|
|
||||||
Daemon::instance()->reportError(i18n("KDE Connect failed to start"),
|
|
||||||
i18n("Could not find support for RSA in your QCA installation. If your "
|
|
||||||
"distribution provides separate packets for QCA-ossl and QCA-gnupg, "
|
|
||||||
"make sure you have them installed and try again."));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure base directory exists
|
// Make sure base directory exists
|
||||||
QDir().mkpath(baseConfigDir().path());
|
QDir().mkpath(baseConfigDir().path());
|
||||||
|
|
||||||
|
@ -75,8 +62,7 @@ KdeConnectConfig::KdeConnectConfig()
|
||||||
d->m_config = new QSettings(baseConfigDir().absoluteFilePath(QStringLiteral("config")), QSettings::IniFormat);
|
d->m_config = new QSettings(baseConfigDir().absoluteFilePath(QStringLiteral("config")), QSettings::IniFormat);
|
||||||
d->m_trustedDevices = new QSettings(baseConfigDir().absoluteFilePath(QStringLiteral("trusted_devices")), QSettings::IniFormat);
|
d->m_trustedDevices = new QSettings(baseConfigDir().absoluteFilePath(QStringLiteral("trusted_devices")), QSettings::IniFormat);
|
||||||
|
|
||||||
loadPrivateKey();
|
loadOrGeneratePrivateKeyAndCertificate(privateKeyPath(), certificatePath());
|
||||||
loadCertificate();
|
|
||||||
|
|
||||||
if (name().isEmpty()) {
|
if (name().isEmpty()) {
|
||||||
setName(getDefaultDeviceName());
|
setName(getDefaultDeviceName());
|
||||||
|
@ -260,56 +246,48 @@ QDir KdeConnectConfig::pluginConfigDir(const QString &deviceId, const QString &p
|
||||||
return QDir(pluginConfigDir);
|
return QDir(pluginConfigDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KdeConnectConfig::loadPrivateKey()
|
bool KdeConnectConfig::loadPrivateKey(const QString &keyPath)
|
||||||
{
|
{
|
||||||
QString keyPath = privateKeyPath();
|
|
||||||
QFile privKey(keyPath);
|
QFile privKey(keyPath);
|
||||||
|
|
||||||
bool needsToGenerateKey = false;
|
|
||||||
if (privKey.exists() && privKey.open(QIODevice::ReadOnly)) {
|
if (privKey.exists() && privKey.open(QIODevice::ReadOnly)) {
|
||||||
QCA::ConvertResult result;
|
d->m_privateKey = SslHelper::pemToRsaPrivateKey(privKey.readAll());
|
||||||
d->m_privateKey = QCA::PrivateKey::fromPEM(QString::fromLatin1(privKey.readAll()), QCA::SecureArray(), &result);
|
if (d->m_privateKey == nullptr) {
|
||||||
if (result != QCA::ConvertResult::ConvertGood) {
|
qCWarning(KDECONNECT_CORE) << "Private key from" << keyPath << "is not valid!";
|
||||||
qCWarning(KDECONNECT_CORE) << "Private key from" << keyPath << "is not valid";
|
|
||||||
needsToGenerateKey = true;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return (d->m_privateKey == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KdeConnectConfig::loadCertificate(const QString &certPath)
|
||||||
|
{
|
||||||
|
QFile cert(certPath);
|
||||||
|
if (cert.exists() && cert.open(QIODevice::ReadOnly)) {
|
||||||
|
auto loadedCerts = QSslCertificate::fromData(cert.readAll());
|
||||||
|
if (loadedCerts.empty()) {
|
||||||
|
qCWarning(KDECONNECT_CORE) << "Certificate from" << certPath << "is not valid";
|
||||||
} else {
|
} else {
|
||||||
needsToGenerateKey = true;
|
d->m_certificate = loadedCerts.at(0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return d->m_certificate.isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KdeConnectConfig::loadOrGeneratePrivateKeyAndCertificate(const QString &keyPath, const QString &certPath)
|
||||||
|
{
|
||||||
|
bool needsToGenerateKey = loadPrivateKey(keyPath);
|
||||||
|
bool needsToGenerateCert = needsToGenerateKey || loadCertificate(certPath);
|
||||||
|
|
||||||
if (needsToGenerateKey) {
|
if (needsToGenerateKey) {
|
||||||
generatePrivateKey(keyPath);
|
generatePrivateKey(keyPath);
|
||||||
}
|
}
|
||||||
|
if (needsToGenerateCert) {
|
||||||
|
generateCertificate(certPath);
|
||||||
|
}
|
||||||
|
|
||||||
// Extra security check
|
// Extra security check
|
||||||
if (QFile::permissions(keyPath) != strictPermissions) {
|
if (QFile::permissions(keyPath) != strictPermissions) {
|
||||||
qCWarning(KDECONNECT_CORE) << "Warning: KDE Connect private key file has too open permissions " << keyPath;
|
qCWarning(KDECONNECT_CORE) << "Warning: KDE Connect private key file has too open permissions " << keyPath;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void KdeConnectConfig::loadCertificate()
|
|
||||||
{
|
|
||||||
QString certPath = certificatePath();
|
|
||||||
QFile cert(certPath);
|
|
||||||
|
|
||||||
bool needsToGenerateCert = false;
|
|
||||||
if (cert.exists() && cert.open(QIODevice::ReadOnly)) {
|
|
||||||
auto loadedCerts = QSslCertificate::fromPath(certPath);
|
|
||||||
if (loadedCerts.empty()) {
|
|
||||||
qCWarning(KDECONNECT_CORE) << "Certificate from" << certPath << "is not valid";
|
|
||||||
needsToGenerateCert = true;
|
|
||||||
} else {
|
|
||||||
d->m_certificate = loadedCerts.at(0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
needsToGenerateCert = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needsToGenerateCert) {
|
|
||||||
generateCertificate(certPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extra security check
|
|
||||||
if (QFile::permissions(certPath) != strictPermissions) {
|
if (QFile::permissions(certPath) != strictPermissions) {
|
||||||
qCWarning(KDECONNECT_CORE) << "Warning: KDE Connect certificate file has too open permissions " << certPath;
|
qCWarning(KDECONNECT_CORE) << "Warning: KDE Connect certificate file has too open permissions " << certPath;
|
||||||
}
|
}
|
||||||
|
@ -319,16 +297,16 @@ void KdeConnectConfig::generatePrivateKey(const QString &keyPath)
|
||||||
{
|
{
|
||||||
qCDebug(KDECONNECT_CORE) << "Generating private key";
|
qCDebug(KDECONNECT_CORE) << "Generating private key";
|
||||||
|
|
||||||
bool error = false;
|
d->m_privateKey = SslHelper::generateRsaPrivateKey();
|
||||||
|
QByteArray keyPem = SslHelper::privateKeyToPEM(d->m_privateKey);
|
||||||
d->m_privateKey = QCA::KeyGenerator().createRSA(2048);
|
|
||||||
|
|
||||||
QFile privKey(keyPath);
|
QFile privKey(keyPath);
|
||||||
|
bool error = false;
|
||||||
if (!privKey.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
|
if (!privKey.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
|
||||||
error = true;
|
error = true;
|
||||||
} else {
|
} else {
|
||||||
privKey.setPermissions(strictPermissions);
|
privKey.setPermissions(strictPermissions);
|
||||||
int written = privKey.write(d->m_privateKey.toPEM().toLatin1());
|
int written = privKey.write(keyPem);
|
||||||
if (written <= 0) {
|
if (written <= 0) {
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
|
@ -343,37 +321,22 @@ void KdeConnectConfig::generateCertificate(const QString &certPath)
|
||||||
{
|
{
|
||||||
qCDebug(KDECONNECT_CORE) << "Generating certificate";
|
qCDebug(KDECONNECT_CORE) << "Generating certificate";
|
||||||
|
|
||||||
bool error = false;
|
|
||||||
|
|
||||||
QString uuid = QUuid::createUuid().toString();
|
QString uuid = QUuid::createUuid().toString();
|
||||||
DBusHelper::filterNonExportableCharacters(uuid);
|
DBusHelper::filterNonExportableCharacters(uuid);
|
||||||
qCDebug(KDECONNECT_CORE) << "My id:" << uuid;
|
qCDebug(KDECONNECT_CORE) << "My id:" << uuid;
|
||||||
|
|
||||||
// FIXME: We only use QCA here to generate the cert and key, would be nice to get rid of it completely.
|
X509 *certificate = SslHelper::generateSelfSignedCertificate(d->m_privateKey, uuid);
|
||||||
// The same thing we are doing with QCA could be done invoking openssl (although it's potentially less portable):
|
QByteArray pemCertificate = SslHelper::certificateToPEM(certificate);
|
||||||
// openssl req -new -x509 -sha256 -newkey rsa:2048 -nodes -keyout privateKey.pem -days 3650 -out certificate.pem -subj "/O=KDE/OU=KDE
|
X509_free(certificate);
|
||||||
// Connect/CN=_e6e29ad4_2b31_4b6d_8f7a_9872dbaa9095_"
|
d->m_certificate = QSslCertificate(pemCertificate);
|
||||||
|
|
||||||
QCA::CertificateOptions certificateOptions = QCA::CertificateOptions();
|
|
||||||
QDateTime startTime = QDateTime::currentDateTime().addYears(-1);
|
|
||||||
QDateTime endTime = startTime.addYears(10);
|
|
||||||
QCA::CertificateInfo certificateInfo;
|
|
||||||
certificateInfo.insert(QCA::CommonName, uuid);
|
|
||||||
certificateInfo.insert(QCA::Organization, QStringLiteral("KDE"));
|
|
||||||
certificateInfo.insert(QCA::OrganizationalUnit, QStringLiteral("Kde connect"));
|
|
||||||
certificateOptions.setInfo(certificateInfo);
|
|
||||||
certificateOptions.setFormat(QCA::PKCS10);
|
|
||||||
certificateOptions.setSerialNumber(QCA::BigInteger(10));
|
|
||||||
certificateOptions.setValidityPeriod(startTime, endTime);
|
|
||||||
|
|
||||||
d->m_certificate = QSslCertificate(QCA::Certificate(certificateOptions, d->m_privateKey).toPEM().toLatin1());
|
|
||||||
|
|
||||||
QFile cert(certPath);
|
QFile cert(certPath);
|
||||||
|
bool error = false;
|
||||||
if (!cert.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
|
if (!cert.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
|
||||||
error = true;
|
error = true;
|
||||||
} else {
|
} else {
|
||||||
cert.setPermissions(strictPermissions);
|
cert.setPermissions(strictPermissions);
|
||||||
int written = cert.write(d->m_certificate.toPem());
|
int written = cert.write(pemCertificate);
|
||||||
if (written <= 0) {
|
if (written <= 0) {
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,9 +68,10 @@ public:
|
||||||
private:
|
private:
|
||||||
KdeConnectConfig();
|
KdeConnectConfig();
|
||||||
|
|
||||||
void loadPrivateKey();
|
void loadOrGeneratePrivateKeyAndCertificate(const QString &keyPath, const QString &certPath);
|
||||||
|
bool loadPrivateKey(const QString &path);
|
||||||
|
bool loadCertificate(const QString &path);
|
||||||
void generatePrivateKey(const QString &path);
|
void generatePrivateKey(const QString &path);
|
||||||
void loadCertificate();
|
|
||||||
void generateCertificate(const QString &path);
|
void generateCertificate(const QString &path);
|
||||||
|
|
||||||
struct KdeConnectConfigPrivate *d;
|
struct KdeConnectConfigPrivate *d;
|
||||||
|
|
100
core/sslhelper.cpp
Normal file
100
core/sslhelper.cpp
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
/**
|
||||||
|
* SPDX-FileCopyrightText: 2023 Albert Vaca <albertvaka@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sslhelper.h"
|
||||||
|
|
||||||
|
#include <openssl/bn.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/rsa.h>
|
||||||
|
#include <openssl/x509v3.h>
|
||||||
|
|
||||||
|
namespace SslHelper
|
||||||
|
{
|
||||||
|
|
||||||
|
X509 *generateSelfSignedCertificate(EVP_PKEY *privateKey, const QString &commonName)
|
||||||
|
{
|
||||||
|
X509 *x509 = X509_new();
|
||||||
|
X509_set_version(x509, 2);
|
||||||
|
|
||||||
|
// Generate a random serial number for the certificate
|
||||||
|
BIGNUM *serialNumber = BN_new();
|
||||||
|
BN_rand(serialNumber, 160, -1, 0);
|
||||||
|
ASN1_INTEGER *serial = X509_get_serialNumber(x509);
|
||||||
|
BN_to_ASN1_INTEGER(serialNumber, serial);
|
||||||
|
BN_free(serialNumber);
|
||||||
|
|
||||||
|
// Set the certificate subject and issuer (self-signed)
|
||||||
|
X509_NAME *name = X509_NAME_new();
|
||||||
|
X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, reinterpret_cast<const unsigned char *>(commonName.toLatin1().data()), -1, -1, 0); // Common Name
|
||||||
|
X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, reinterpret_cast<const unsigned char *>("KDE"), -1, -1, 0); // Organization
|
||||||
|
X509_NAME_add_entry_by_txt(name, "OU", MBSTRING_ASC, reinterpret_cast<const unsigned char *>("KDE Connect"), -1, -1, 0); // Organizational Unit
|
||||||
|
X509_set_subject_name(x509, name);
|
||||||
|
X509_set_issuer_name(x509, name);
|
||||||
|
X509_NAME_free(name);
|
||||||
|
|
||||||
|
// Set the certificate validity period
|
||||||
|
time_t now = time(nullptr);
|
||||||
|
int a_year_in_seconds = 356 * 24 * 60 * 60;
|
||||||
|
ASN1_TIME_set(X509_get_notBefore(x509), now - a_year_in_seconds);
|
||||||
|
ASN1_TIME_set(X509_get_notAfter(x509), now + 10 * a_year_in_seconds);
|
||||||
|
|
||||||
|
// Set the public key for the certificate
|
||||||
|
X509_set_pubkey(x509, privateKey);
|
||||||
|
|
||||||
|
// Sign the certificate with the private key
|
||||||
|
X509_sign(x509, privateKey, EVP_sha256());
|
||||||
|
|
||||||
|
return x509;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_PKEY *generateRsaPrivateKey()
|
||||||
|
{
|
||||||
|
EVP_PKEY *privateKey = EVP_PKEY_new();
|
||||||
|
RSA *rsa = RSA_new();
|
||||||
|
|
||||||
|
BIGNUM *exponent = BN_new();
|
||||||
|
BN_set_word(exponent, RSA_F4);
|
||||||
|
|
||||||
|
RSA_generate_key_ex(rsa, 2048, exponent, nullptr);
|
||||||
|
EVP_PKEY_assign_RSA(privateKey, rsa);
|
||||||
|
|
||||||
|
BN_free(exponent);
|
||||||
|
|
||||||
|
return privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray certificateToPEM(X509 *certificate)
|
||||||
|
{
|
||||||
|
BIO *bio = BIO_new(BIO_s_mem());
|
||||||
|
PEM_write_bio_X509(bio, certificate);
|
||||||
|
BUF_MEM *mem = nullptr;
|
||||||
|
BIO_get_mem_ptr(bio, &mem);
|
||||||
|
QByteArray pemData(mem->data, mem->length);
|
||||||
|
BIO_free_all(bio);
|
||||||
|
return pemData;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray privateKeyToPEM(EVP_PKEY *privateKey)
|
||||||
|
{
|
||||||
|
BIO *bio = BIO_new(BIO_s_mem());
|
||||||
|
PEM_write_bio_PrivateKey(bio, privateKey, nullptr, nullptr, 0, nullptr, nullptr);
|
||||||
|
BUF_MEM *mem = nullptr;
|
||||||
|
BIO_get_mem_ptr(bio, &mem);
|
||||||
|
QByteArray pemData(mem->data, mem->length);
|
||||||
|
BIO_free_all(bio);
|
||||||
|
return pemData;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_PKEY *pemToRsaPrivateKey(const QByteArray &privateKeyPem)
|
||||||
|
{
|
||||||
|
const char *pemData = privateKeyPem.constData();
|
||||||
|
BIO *bio = BIO_new_mem_buf(pemData, -1);
|
||||||
|
EVP_PKEY *privateKey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
|
||||||
|
BIO_free(bio);
|
||||||
|
return privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace SslHelper
|
32
core/sslhelper.h
Normal file
32
core/sslhelper.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/**
|
||||||
|
* SPDX-FileCopyrightText: 2023 Albert Vaca <albertvaka@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SSLHELPER_H
|
||||||
|
#define SSLHELPER_H
|
||||||
|
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/x509.h>
|
||||||
|
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace SslHelper
|
||||||
|
{
|
||||||
|
|
||||||
|
// Delete with X509_free(certificate);
|
||||||
|
X509 *generateSelfSignedCertificate(EVP_PKEY *privateKey, const QString &commonName);
|
||||||
|
|
||||||
|
// Delete with EVP_PKEY_free(privateKey);
|
||||||
|
EVP_PKEY *generateRsaPrivateKey();
|
||||||
|
|
||||||
|
QByteArray certificateToPEM(X509 *certificate);
|
||||||
|
|
||||||
|
QByteArray privateKeyToPEM(EVP_PKEY *privateKey);
|
||||||
|
EVP_PKEY *pemToRsaPrivateKey(const QByteArray &privateKeyPem);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue