Netssl/openssl3 (#3575)

* feat(Context): DH init openssl3 port (1/2 hardcoded params)

* create poco-1.11.3 branch, bump version

* update copyright date

* #3567: check legacy provider existence for legacy exception #3567

* fix(Placeholder): comparison for zero value

* feat(Context): DH init openssl3 port (2/2 params from file)

* test(HTTPSClientSession): try/catch to understand CI failure

* chore(cmake): copy the DH parameters file

* fix(OpenSSLInitializer): unload provider on uninitialize

* chore(HTTPSClientSessionTest): remove try/catch

* fix(OpenSSLInitializer): fix provider unloading

* feat(CppUnit): make tests exceptions more descriptive

* chore(CppUnit): a more descriptive name for callback

Co-authored-by: Günter Obiltschnig <guenter.obiltschnig@appinf.com>
This commit is contained in:
Aleksandar Fabijanic
2022-04-28 22:24:43 -05:00
committed by GitHub
parent 4dfbcd33db
commit 7db9831f32
31 changed files with 296 additions and 114 deletions

View File

@@ -20,10 +20,17 @@
#include "Poco/File.h"
#include "Poco/Path.h"
#include "Poco/Timestamp.h"
#include "Poco/Format.h"
#include "Poco/Error.h"
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/x509v3.h>
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/core_names.h>
#include <openssl/decoder.h>
#endif // OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <iostream>
namespace Poco {
@@ -727,6 +734,110 @@ void Context::initDH(bool use2048Bits, const std::string& dhParamsFile)
0x6C,0xC4,0x16,0x59,
};
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
EVP_PKEY_CTX* pKeyCtx = NULL;
OSSL_DECODER_CTX* pOSSLDecodeCtx = NULL;
EVP_PKEY* pKey = NULL;
bool freeEVPPKey = true;
if (!dhParamsFile.empty())
{
freeEVPPKey = false;
pOSSLDecodeCtx = OSSL_DECODER_CTX_new_for_pkey(&pKey, NULL, NULL, "DH",
OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, NULL, NULL);
if (!pOSSLDecodeCtx)
{
std::string err = Poco::format(
"Context::initDH(%s):OSSL_DECODER_CTX_new_for_pkey():OSSL_DECODER_CTX*\n", dhParamsFile);
throw Poco::NullPointerException(Poco::Crypto::getError(err));
}
if (!OSSL_DECODER_CTX_get_num_decoders(pOSSLDecodeCtx))
{
OSSL_DECODER_CTX_free(pOSSLDecodeCtx);
throw Poco::Crypto::OpenSSLException(
Poco::format("Context::initDH(%s):OSSL_DECODER_CTX_get_num_decoders()=0",
dhParamsFile));
}
FILE* pFile = fopen(dhParamsFile.c_str(), "r");
if (!pFile)
{
OSSL_DECODER_CTX_free(pOSSLDecodeCtx);
throw Poco::NullPointerException(
Poco::format("Context::initDH(%s):fopen()\n%s",
dhParamsFile, Poco::Error::getMessage(Poco::Error::last())));
}
if (!OSSL_DECODER_from_fp(pOSSLDecodeCtx, pFile))
{
fclose(pFile);
OSSL_DECODER_CTX_free(pOSSLDecodeCtx);
std::string err = Poco::format(
"Context::initDH(%s):OSSL_DECODER_from_fp()\n%s", dhParamsFile);
throw Poco::Crypto::OpenSSLException(Poco::Crypto::getError(err));
}
fclose(pFile);
OSSL_DECODER_CTX_free(pOSSLDecodeCtx);
if (!pKey)
{
std::string err = Poco::format(
"Context::initDH(%s):OSSL_DECODER_CTX_new_for_pkey():EVP_PKEY*\n", dhParamsFile);
throw Poco::NullPointerException(Poco::Crypto::getError(err));
}
}
else
{
pKeyCtx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL);
if (!pKeyCtx)
{
std::string err = "Context::initDH():EVP_PKEY_CTX_new_from_name()\n";
throw Poco::NullPointerException(Poco::Crypto::getError(err));
}
size_t keyLength = use2048Bits ? 256 : 160;
unsigned char* pDH_p = const_cast<unsigned char*>(use2048Bits ? dh2048_p : dh1024_p);
std::size_t sz_p = use2048Bits ? sizeof(dh2048_p) : sizeof(dh1024_p);
unsigned char* pDH_g = const_cast<unsigned char*>(use2048Bits ? dh2048_g : dh1024_g);
std::size_t sz_g = use2048Bits ? sizeof(dh2048_g) : sizeof(dh1024_g);
OSSL_PARAM params[]
{
OSSL_PARAM_size_t(OSSL_PKEY_PARAM_FFC_PBITS, &keyLength),
OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_P, pDH_p, sz_p),
OSSL_PARAM_BN(OSSL_PKEY_PARAM_FFC_G, pDH_g, sz_g),
OSSL_PARAM_END
};
if (1 != EVP_PKEY_fromdata_init(pKeyCtx))
{
EVP_PKEY_CTX_free(pKeyCtx);
std::string err = "Context::initDH():EVP_PKEY_fromdata_init()\n";
throw SSLContextException(Poco::Crypto::getError(err));
}
if (1 != EVP_PKEY_fromdata(pKeyCtx, &pKey, EVP_PKEY_KEYPAIR, params))
{
EVP_PKEY_CTX_free(pKeyCtx);
std::string err = "Context::initDH():EVP_PKEY_fromdata()\n";
throw SSLContextException(Poco::Crypto::getError(err));
}
EVP_PKEY_CTX_free(pKeyCtx);
}
if (!pKey)
{
throw SSLContextException(Poco::format("Context::initDH(%s):EVP_PKEY*", dhParamsFile));
}
SSL_CTX_set0_tmp_dh_pkey(_pSSLContext, pKey);
SSL_CTX_set_options(_pSSLContext, SSL_OP_SINGLE_DH_USE);
if (freeEVPPKey) EVP_PKEY_free(pKey);
#else // OPENSSL_VERSION_NUMBER >= 0x30000000L
DH* dh = 0;
if (!dhParamsFile.empty())
{
@@ -752,7 +863,9 @@ void Context::initDH(bool use2048Bits, const std::string& dhParamsFile)
std::string msg = Utility::getLastError();
throw SSLContextException("Error creating Diffie-Hellman parameters", msg);
}
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
BIGNUM* p = nullptr;
BIGNUM* g = nullptr;
if (use2048Bits)
@@ -774,7 +887,9 @@ void Context::initDH(bool use2048Bits, const std::string& dhParamsFile)
DH_free(dh);
throw SSLContextException("Error creating Diffie-Hellman parameters");
}
#else
#else // OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
if (use2048Bits)
{
dh->p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), 0);
@@ -792,15 +907,23 @@ void Context::initDH(bool use2048Bits, const std::string& dhParamsFile)
DH_free(dh);
throw SSLContextException("Error creating Diffie-Hellman parameters");
}
#endif
#endif // OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
}
SSL_CTX_set_tmp_dh(_pSSLContext, dh);
SSL_CTX_set_options(_pSSLContext, SSL_OP_SINGLE_DH_USE);
DH_free(dh);
#else
#endif // OPENSSL_VERSION_NUMBER >= 0x30000000L
#else // OPENSSL_NO_DH
if (!dhParamsFile.empty())
throw SSLContextException("OpenSSL does not support DH");
#endif
throw SSLContextException("Implementation does not support DH");
#endif // OPENSSL_NO_DH
}

View File

@@ -15,6 +15,7 @@
#include "Poco/Net/Utility.h"
#include "Poco/String.h"
#include "Poco/Util/OptionException.h"
#include "Poco/Crypto/Crypto.h"
#include <openssl/err.h>
@@ -51,14 +52,9 @@ std::string Utility::convertCertificateError(long errCode)
std::string Utility::getLastError()
{
unsigned long errCode = ERR_get_error();
if (errCode != 0)
{
char buffer[256];
ERR_error_string_n(errCode, buffer, sizeof(buffer));
return std::string(buffer);
}
else return "No error";
std::string msg;
Poco::Crypto::getError(msg);
return msg;
}