summaryrefslogtreecommitdiffstats
path: root/src/plugins/tls/openssl/qtlskey_openssl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/tls/openssl/qtlskey_openssl.cpp')
-rw-r--r--src/plugins/tls/openssl/qtlskey_openssl.cpp186
1 files changed, 105 insertions, 81 deletions
diff --git a/src/plugins/tls/openssl/qtlskey_openssl.cpp b/src/plugins/tls/openssl/qtlskey_openssl.cpp
index 0d5b698668..294fc2ffcd 100644
--- a/src/plugins/tls/openssl/qtlskey_openssl.cpp
+++ b/src/plugins/tls/openssl/qtlskey_openssl.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtNetwork module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 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
#include "qsslsocket_openssl_symbols_p.h"
#include "qtlsbackend_openssl_p.h"
@@ -85,6 +49,16 @@ void TlsKeyOpenSSL::decodePem(KeyType type, KeyAlgorithm algorithm, const QByteA
void *phrase = const_cast<char *>(passPhrase.data());
+#ifdef OPENSSL_NO_DEPRECATED_3_0
+ if (type == QSsl::PublicKey)
+ genericKey = q_PEM_read_bio_PUBKEY(bio, nullptr, nullptr, phrase);
+ else
+ genericKey = q_PEM_read_bio_PrivateKey(bio, nullptr, nullptr, phrase);
+ keyIsNull = !genericKey;
+ if (keyIsNull)
+ QTlsBackendOpenSSL::logAndClearErrorQueue();
+#else
+
if (algorithm == QSsl::Rsa) {
RSA *result = (type == QSsl::PublicKey)
? q_PEM_read_bio_RSA_PUBKEY(bio, &rsa, nullptr, phrase)
@@ -113,8 +87,10 @@ void TlsKeyOpenSSL::decodePem(KeyType type, KeyAlgorithm algorithm, const QByteA
: q_PEM_read_bio_ECPrivateKey(bio, &ec, nullptr, phrase);
if (ec && ec == result)
keyIsNull = false;
-#endif
+#endif // OPENSSL_NO_EC
}
+
+#endif // OPENSSL_NO_DEPRECATED_3_0
}
QByteArray TlsKeyOpenSSL::derFromPem(const QByteArray &pem, QMap<QByteArray, QByteArray> *headers) const
@@ -125,19 +101,19 @@ QByteArray TlsKeyOpenSSL::derFromPem(const QByteArray &pem, QMap<QByteArray, QBy
QByteArray der(pem);
int headerIndex = der.indexOf(header);
- int footerIndex = der.indexOf(footer, headerIndex + header.length());
+ int footerIndex = der.indexOf(footer, headerIndex + header.size());
if (type() != QSsl::PublicKey) {
if (headerIndex == -1 || footerIndex == -1) {
header = pkcs8Header(true);
footer = pkcs8Footer(true);
headerIndex = der.indexOf(header);
- footerIndex = der.indexOf(footer, headerIndex + header.length());
+ footerIndex = der.indexOf(footer, headerIndex + header.size());
}
if (headerIndex == -1 || footerIndex == -1) {
header = pkcs8Header(false);
footer = pkcs8Footer(false);
headerIndex = der.indexOf(header);
- footerIndex = der.indexOf(footer, headerIndex + header.length());
+ footerIndex = der.indexOf(footer, headerIndex + header.size());
}
}
if (headerIndex == -1 || footerIndex == -1)
@@ -148,7 +124,7 @@ QByteArray TlsKeyOpenSSL::derFromPem(const QByteArray &pem, QMap<QByteArray, QBy
if (der.contains("Proc-Type:")) {
// taken from QHttpNetworkReplyPrivate::parseHeader
int i = 0;
- while (i < der.count()) {
+ while (i < der.size()) {
int j = der.indexOf(':', i); // field-name
if (j == -1)
break;
@@ -167,7 +143,7 @@ QByteArray TlsKeyOpenSSL::derFromPem(const QByteArray &pem, QMap<QByteArray, QBy
int length = i -(hasCR ? 1: 0) - j;
value += der.mid(j, length).trimmed();
j = ++i;
- } while (i < der.count() && (der.at(i) == ' ' || der.at(i) == '\t'));
+ } while (i < der.size() && (der.at(i) == ' ' || der.at(i) == '\t'));
if (i == -1)
break; // something is wrong
@@ -183,6 +159,7 @@ void TlsKeyOpenSSL::clear(bool deep)
{
keyIsNull = true;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
if (algorithm() == QSsl::Rsa && rsa) {
if (deep)
q_RSA_free(rsa);
@@ -205,18 +182,30 @@ void TlsKeyOpenSSL::clear(bool deep)
ec = nullptr;
}
#endif
+#endif // OPENSSL_NO_DEPRECATED_3_0
+
if (algorithm() == QSsl::Opaque && opaque) {
if (deep)
q_EVP_PKEY_free(opaque);
opaque = nullptr;
}
+
+ if (genericKey) {
+ // None of the above cleared it. genericKey is either
+ // initialised by PEM read operation, or from X509, and
+ // we are the owners and not sharing. So we free it.
+ q_EVP_PKEY_free(genericKey);
+ genericKey = nullptr;
+ }
}
Qt::HANDLE TlsKeyOpenSSL::handle() const
{
- switch (keyAlgorithm) {
- case QSsl::Opaque:
+ if (keyAlgorithm == QSsl::Opaque)
return Qt::HANDLE(opaque);
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+ switch (keyAlgorithm) {
case QSsl::Rsa:
return Qt::HANDLE(rsa);
case QSsl::Dsa:
@@ -230,6 +219,11 @@ Qt::HANDLE TlsKeyOpenSSL::handle() const
default:
return Qt::HANDLE(nullptr);
}
+#else
+ qCWarning(lcTlsBackend,
+ "This version of OpenSSL disabled direct manipulation with RSA/DSA/DH/EC_KEY structures, consider using QSsl::Opaque instead.");
+ return Qt::HANDLE(genericKey);
+#endif
}
int TlsKeyOpenSSL::length() const
@@ -237,6 +231,7 @@ int TlsKeyOpenSSL::length() const
if (isNull() || algorithm() == QSsl::Opaque)
return -1;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
switch (algorithm()) {
case QSsl::Rsa:
return q_RSA_bits(rsa);
@@ -251,6 +246,10 @@ int TlsKeyOpenSSL::length() const
default:
return -1;
}
+#else // OPENSSL_NO_DEPRECATED_3_0
+ Q_ASSERT(genericKey);
+ return q_EVP_PKEY_get_bits(genericKey);
+#endif // OPENSSL_NO_DEPRECATED_3_0
}
QByteArray TlsKeyOpenSSL::toPem(const QByteArray &passPhrase) const
@@ -273,54 +272,61 @@ QByteArray TlsKeyOpenSSL::toPem(const QByteArray &passPhrase) const
const auto bioRaii = qScopeGuard([bio]{q_BIO_free(bio);});
- bool fail = false;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+
+#define write_pubkey(alg, key) q_PEM_write_bio_##alg##_PUBKEY(bio, key)
+#define write_privatekey(alg, key) \
+ q_PEM_write_bio_##alg##PrivateKey(bio, key, cipher, (uchar *)passPhrase.data(), \
+ passPhrase.size(), nullptr, nullptr)
+
+#else
+
+#define write_pubkey(alg, key) q_PEM_write_bio_PUBKEY(bio, genericKey)
+#define write_privatekey(alg, key) \
+ q_PEM_write_bio_PrivateKey_traditional(bio, genericKey, cipher, (uchar *)passPhrase.data(), passPhrase.size(), nullptr, nullptr)
+#endif // OPENSSL_NO_DEPRECATED_3_0
+
+ bool fail = false;
if (algorithm() == QSsl::Rsa) {
if (type() == QSsl::PublicKey) {
- if (!q_PEM_write_bio_RSA_PUBKEY(bio, rsa))
- fail = true;
- } else {
- if (!q_PEM_write_bio_RSAPrivateKey(
- bio, rsa, cipher, (uchar *)passPhrase.data(),
- passPhrase.size(), nullptr, nullptr)) {
+ if (!write_pubkey(RSA, rsa))
fail = true;
- }
+ } else if (!write_privatekey(RSA, rsa)) {
+ fail = true;
}
} else if (algorithm() == QSsl::Dsa) {
if (type() == QSsl::PublicKey) {
- if (!q_PEM_write_bio_DSA_PUBKEY(bio, dsa))
+ if (!write_pubkey(DSA, dsa))
fail = true;
- } else {
- if (!q_PEM_write_bio_DSAPrivateKey(
- bio, dsa, cipher, (uchar *)passPhrase.data(),
- passPhrase.size(), nullptr, nullptr)) {
- fail = true;
- }
+ } else if (!write_privatekey(DSA, dsa)) {
+ fail = true;
}
} else if (algorithm() == QSsl::Dh) {
+#ifdef OPENSSL_NO_DEPRECATED_3_0
+ EVP_PKEY *result = genericKey;
+#else
EVP_PKEY *result = q_EVP_PKEY_new();
+ const auto guard = qScopeGuard([result]{if (result) q_EVP_PKEY_free(result);});
if (!result || !q_EVP_PKEY_set1_DH(result, dh)) {
fail = true;
- } else if (type() == QSsl::PublicKey) {
+ } else
+#endif
+ if (type() == QSsl::PublicKey) {
if (!q_PEM_write_bio_PUBKEY(bio, result))
fail = true;
- } else if (!q_PEM_write_bio_PrivateKey(
- bio, result, cipher, (uchar *)passPhrase.data(),
- passPhrase.size(), nullptr, nullptr)) {
+ } else if (!q_PEM_write_bio_PrivateKey(bio, result, cipher, (uchar *)passPhrase.data(),
+ passPhrase.size(), nullptr, nullptr)) {
fail = true;
}
- q_EVP_PKEY_free(result);
#ifndef OPENSSL_NO_EC
} else if (algorithm() == QSsl::Ec) {
if (type() == QSsl::PublicKey) {
- if (!q_PEM_write_bio_EC_PUBKEY(bio, ec))
+ if (!write_pubkey(EC, ec))
fail = true;
} else {
- if (!q_PEM_write_bio_ECPrivateKey(
- bio, ec, cipher, (uchar *)passPhrase.data(),
- passPhrase.size(), nullptr, nullptr)) {
+ if (!write_privatekey(EC, ec))
fail = true;
- }
}
#endif
} else {
@@ -333,6 +339,8 @@ QByteArray TlsKeyOpenSSL::toPem(const QByteArray &passPhrase) const
const long size = q_BIO_get_mem_data(bio, &data);
if (size > 0 && data)
pem = QByteArray(data, size);
+ } else {
+ QTlsBackendOpenSSL::logAndClearErrorQueue();
}
return pem;
@@ -357,34 +365,37 @@ bool TlsKeyOpenSSL::fromEVP_PKEY(EVP_PKEY *pkey)
if (!pkey)
return false;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+#define get_key(key, alg) key = q_EVP_PKEY_get1_##alg(pkey)
+#else
+#define get_key(key, alg) q_EVP_PKEY_up_ref(pkey); genericKey = pkey;
+#endif
+
switch (q_EVP_PKEY_type(q_EVP_PKEY_base_id(pkey))) {
case EVP_PKEY_RSA:
keyIsNull = false;
keyAlgorithm = QSsl::Rsa;
keyType = QSsl::PrivateKey;
- rsa = q_EVP_PKEY_get1_RSA(pkey);
-
+ get_key(rsa, RSA);
return true;
case EVP_PKEY_DSA:
keyIsNull = false;
keyAlgorithm = QSsl::Dsa;
keyType = QSsl::PrivateKey;
- dsa = q_EVP_PKEY_get1_DSA(pkey);
-
+ get_key(dsa, DSA);
return true;
case EVP_PKEY_DH:
keyIsNull = false;
keyAlgorithm = QSsl::Dh;
keyType = QSsl::PrivateKey;
- dh = q_EVP_PKEY_get1_DH(pkey);
+ get_key(dh, DH);
return true;
#ifndef OPENSSL_NO_EC
case EVP_PKEY_EC:
keyIsNull = false;
keyAlgorithm = QSsl::Ec;
keyType = QSsl::PrivateKey;
- ec = q_EVP_PKEY_get1_EC_KEY(pkey);
-
+ get_key(ec, EC_KEY);
return true;
#endif
default:;
@@ -484,21 +495,31 @@ TlsKeyOpenSSL *TlsKeyOpenSSL::publicKeyFromX509(X509 *x)
tlsKey->keyType = QSsl::PublicKey;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+
+#define get_pubkey(keyName, alg) tlsKey->keyName = q_EVP_PKEY_get1_##alg(pkey)
+
+#else
+
+#define get_pubkey(a, b) tlsKey->genericKey = pkey
+
+#endif
+
EVP_PKEY *pkey = q_X509_get_pubkey(x);
Q_ASSERT(pkey);
const int keyType = q_EVP_PKEY_type(q_EVP_PKEY_base_id(pkey));
if (keyType == EVP_PKEY_RSA) {
- tlsKey->rsa = q_EVP_PKEY_get1_RSA(pkey);
+ get_pubkey(rsa, RSA);
tlsKey->keyAlgorithm = QSsl::Rsa;
tlsKey->keyIsNull = false;
} else if (keyType == EVP_PKEY_DSA) {
- tlsKey->dsa = q_EVP_PKEY_get1_DSA(pkey);
+ get_pubkey(dsa, DSA);
tlsKey->keyAlgorithm = QSsl::Dsa;
tlsKey->keyIsNull = false;
#ifndef OPENSSL_NO_EC
} else if (keyType == EVP_PKEY_EC) {
- tlsKey->ec = q_EVP_PKEY_get1_EC_KEY(pkey);
+ get_pubkey(ec, EC_KEY);
tlsKey->keyAlgorithm = QSsl::Ec;
tlsKey->keyIsNull = false;
#endif
@@ -508,7 +529,10 @@ TlsKeyOpenSSL *TlsKeyOpenSSL::publicKeyFromX509(X509 *x)
// error? (key is null)
}
+#ifndef OPENSSL_NO_DEPRECATED_3_0
q_EVP_PKEY_free(pkey);
+#endif
+
return keyRaii.release();
}