Details
-
Suggestion
-
Resolution: Out of scope
-
Not Evaluated
-
None
-
None
-
None
Description
When I build with OPENSSL_NO_DEPRECATED_3_0,
when I call <Key>.toPem(), it returns empty string.
QByteArray TlsKeyOpenSSL::toPem(const QByteArray &passPhrase) const { if (!QSslSocket::supportsSsl() || isNull() || algorithm() == QSsl::Opaque) return {}; const EVP_CIPHER *cipher = nullptr; if (type() == QSsl::PrivateKey && !passPhrase.isEmpty()) { #ifndef OPENSSL_NO_DES cipher = q_EVP_des_ede3_cbc(); #else return {}; #endif } BIO *bio = q_BIO_new(q_BIO_s_mem()); if (!bio) return {}; const auto bioRaii = qScopeGuard([bio]{q_BIO_free(bio);});#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 (!write_pubkey(RSA, rsa)) fail = true; } else if (!write_privatekey(RSA, rsa)) { fail = true; } } else if (algorithm() == QSsl::Dsa) { if (type() == QSsl::PublicKey) { if (!write_pubkey(DSA, dsa)) 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 #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)) { fail = true; } #ifndef OPENSSL_NO_EC } else if (algorithm() == QSsl::Ec) { if (type() == QSsl::PublicKey) { if (!write_pubkey(EC, ec)) fail = true; } else { if (!write_privatekey(EC, ec)) fail = true; } #endif } else { fail = true; } QByteArray pem; if (!fail) { char *data = nullptr; const long size = q_BIO_get_mem_data(bio, &data); if (size > 0 && data) pem = QByteArray(data, size); } else { QTlsBackendOpenSSL::logAndClearErrorQueue(); } return pem; }void TlsKeyOpenSSL::fromHandle(Qt::HANDLE handle, QSsl::KeyType expectedType) { EVP_PKEY *evpKey = reinterpret_cast<EVP_PKEY *>(handle); if (!evpKey || !fromEVP_PKEY(evpKey)) { opaque = evpKey; keyAlgorithm = QSsl::Opaque; } else { q_EVP_PKEY_free(evpKey); } keyType = expectedType; keyIsNull = !opaque; }
Will it be possible to adapt the implementation, as genericKey is the variable that contains the key (rsa, dsa, ec, these variables are empty):
QByteArray TlsKeyOpenSSL::toPem(const QByteArray &passPhrase) const { if (!QSslSocket::supportsSsl() || isNull() || algorithm() == QSsl::Opaque) return {}; const EVP_CIPHER *cipher = nullptr; if (type() == QSsl::PrivateKey && !passPhrase.isEmpty()) { #ifndef OPENSSL_NO_DES cipher = q_EVP_des_ede3_cbc(); #else return {}; #endif } BIO *bio = q_BIO_new(q_BIO_s_mem()); if (!bio) return {}; const auto bioRaii = qScopeGuard([bio]{q_BIO_free(bio);});#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) bool fail = false; #ifndef OPENSSL_NO_DEPRECATED_3_0 EVP_PKEY *result = genericKey; 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)) { fail = true; } #else if (algorithm() == QSsl::Rsa) { if (type() == QSsl::PublicKey) { 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 (!write_pubkey(DSA, dsa)) fail = true; } else if (!write_privatekey(DSA, dsa)) { fail = true; } } else if (algorithm() == QSsl::Dh) { 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) { 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)) { fail = true; } #ifndef OPENSSL_NO_EC } else if (algorithm() == QSsl::Ec) { if (type() == QSsl::PublicKey) { if (!write_pubkey(EC, ec)) fail = true; } else { if (!write_privatekey(EC, ec)) fail = true; } #endif } else { fail = true; } #endif QByteArray pem; if (!fail) { char *data = nullptr; const long size = q_BIO_get_mem_data(bio, &data); if (size > 0 && data) pem = QByteArray(data, size); } else { QTlsBackendOpenSSL::logAndClearErrorQueue(); } return pem; }