add support for TLS 1.3

This commit is contained in:
Günter Obiltschnig
2020-01-10 11:41:49 +01:00
parent a2f8f8fbe1
commit e3d1d03c54
7 changed files with 197 additions and 36 deletions

View File

@@ -32,7 +32,7 @@ class NetSSL_Win_API CertificateHandlerFactoryMgr
/// A CertificateHandlerFactoryMgr manages all existing CertificateHandlerFactories. /// A CertificateHandlerFactoryMgr manages all existing CertificateHandlerFactories.
{ {
public: public:
typedef std::map<std::string, Poco::SharedPtr<CertificateHandlerFactory> > FactoriesMap; using FactoriesMap = std::map<std::string, Poco::SharedPtr<CertificateHandlerFactory>>;
CertificateHandlerFactoryMgr(); CertificateHandlerFactoryMgr();
/// Creates the CertificateHandlerFactoryMgr. /// Creates the CertificateHandlerFactoryMgr.

View File

@@ -50,18 +50,22 @@ class NetSSL_Win_API Context: public Poco::RefCountedObject
/// SSL session caching on the server and client side. /// SSL session caching on the server and client side.
{ {
public: public:
typedef Poco::AutoPtr<Context> Ptr; using Ptr = Poco::AutoPtr<Context>;
enum Usage enum Usage
{ {
CLIENT_USE, /// Context is used by a client. TLS_CLIENT_USE, /// Context is used by a client for TLSv1 or higher. Use requireMinimumProtocol() or disableProtocols() to disable undesired older versions.
SERVER_USE, /// Context is used by a server. TLS_SERVER_USE, /// Context is used by a client for TLSv1 or higher. Use requireMinimumProtocol() or disableProtocols() to disable undesired older versions.
TLSV1_CLIENT_USE, /// Context is used by a client requiring TLSv1. CLIENT_USE, /// DEPRECATED. Context is used by a client.
TLSV1_SERVER_USE, /// Context is used by a server requiring TLSv1. SERVER_USE, /// DEPRECATED. Context is used by a server.
TLSV1_1_CLIENT_USE, /// Context is used by a client requiring TLSv1.1. Not supported on Windows Embedded Compact. TLSV1_CLIENT_USE, /// DEPRECATED. Context is used by a client requiring TLSv1.
TLSV1_1_SERVER_USE, /// Context is used by a server requiring TLSv1.1. Not supported on Windows Embedded Compact. TLSV1_SERVER_USE, /// DEPRECATED. Context is used by a server requiring TLSv1.
TLSV1_2_CLIENT_USE, /// Context is used by a client requiring TLSv1.2. Not supported on Windows Embedded Compact. TLSV1_1_CLIENT_USE, /// DEPRECATED. Context is used by a client requiring TLSv1.1. Not supported on Windows Embedded Compact.
TLSV1_2_SERVER_USE /// Context is used by a server requiring TLSv1.2. Not supported on Windows Embedded Compact. TLSV1_1_SERVER_USE, /// DEPRECATED. Context is used by a server requiring TLSv1.1. Not supported on Windows Embedded Compact.
TLSV1_2_CLIENT_USE, /// DEPRECATED. Context is used by a client requiring TLSv1.2. Not supported on Windows Embedded Compact.
TLSV1_2_SERVER_USE, /// DEPRECATED. Context is used by a server requiring TLSv1.2. Not supported on Windows Embedded Compact.
TLSV1_3_CLIENT_USE, /// DEPRECATED. Context is used by a client requiring TLSv1.3. Not supported on Windows Embedded Compact.
TLSV1_3_SERVER_USE /// DEPRECATED. Context is used by a server requiring TLSv1.3. Not supported on Windows Embedded Compact.
}; };
enum VerificationMode enum VerificationMode
@@ -98,6 +102,16 @@ public:
/// the OpenSSL implementation. /// the OpenSSL implementation.
}; };
enum Protocols
{
PROTO_SSLV2 = 0x01,
PROTO_SSLV3 = 0x02,
PROTO_TLSV1 = 0x04,
PROTO_TLSV1_1 = 0x08,
PROTO_TLSV1_2 = 0x10,
PROTO_TLSV1_3 = 0x20
};
enum Options enum Options
{ {
OPT_PERFORM_REVOCATION_CHECK = 0x01, OPT_PERFORM_REVOCATION_CHECK = 0x01,
@@ -173,6 +187,20 @@ public:
void addTrustedCert(const Poco::Net::X509Certificate& cert); void addTrustedCert(const Poco::Net::X509Certificate& cert);
/// Adds the certificate to the trusted certs. Takes ownership of pCert. /// Adds the certificate to the trusted certs. Takes ownership of pCert.
void disableProtocols(int protocols);
/// Disables the given protocols.
///
/// The protocols to be disabled are specified by OR-ing
/// values from the Protocols enumeration, e.g.:
///
/// context.disableProtocols(PROTO_SSLV2 | PROTO_SSLV3);
void requireMinimumProtocol(Protocols protocol);
/// Disables all protocol version lower than the given one.
/// To require at least TLS 1.2 or later:
///
/// context.requireMinimumProtocol(PROTO_TLSV1_2);
Poco::Net::X509Certificate certificate(); Poco::Net::X509Certificate certificate();
/// Loads or imports and returns the certificate specified in the constructor. /// Loads or imports and returns the certificate specified in the constructor.
/// ///
@@ -201,6 +229,7 @@ protected:
void importCertificate(const char* pBuffer, std::size_t size); void importCertificate(const char* pBuffer, std::size_t size);
void acquireSchannelCredentials(CredHandle& credHandle) const; void acquireSchannelCredentials(CredHandle& credHandle) const;
DWORD proto() const; DWORD proto() const;
DWORD enabledProtocols() const;
private: private:
Context(const Context&); Context(const Context&);
@@ -209,6 +238,7 @@ private:
Usage _usage; Usage _usage;
Context::VerificationMode _mode; Context::VerificationMode _mode;
int _options; int _options;
int _disabledProtocols;
bool _extendedCertificateVerification; bool _extendedCertificateVerification;
std::string _certNameOrPath; std::string _certNameOrPath;
std::string _certStoreName; std::string _certStoreName;
@@ -247,9 +277,11 @@ inline int Context::options() const
inline bool Context::isForServerUse() const inline bool Context::isForServerUse() const
{ {
return _usage == SERVER_USE return _usage == SERVER_USE
|| _usage == TLS_SERVER_USE
|| _usage == TLSV1_SERVER_USE || _usage == TLSV1_SERVER_USE
|| _usage == TLSV1_1_SERVER_USE || _usage == TLSV1_1_SERVER_USE
|| _usage == TLSV1_2_SERVER_USE; || _usage == TLSV1_2_SERVER_USE
|| _usage == TLSV1_3_SERVER_USE;
} }

View File

@@ -32,7 +32,7 @@ class NetSSL_Win_API PrivateKeyFactoryMgr
/// A PrivateKeyFactoryMgr manages all existing PrivateKeyFactories. /// A PrivateKeyFactoryMgr manages all existing PrivateKeyFactories.
{ {
public: public:
typedef std::map<std::string, Poco::SharedPtr<PrivateKeyFactory> > FactoriesMap; using FactoriesMap = std::map<std::string, Poco::SharedPtr<PrivateKeyFactory>>;
PrivateKeyFactoryMgr(); PrivateKeyFactoryMgr();
/// Creates the PrivateKeyFactoryMgr. /// Creates the PrivateKeyFactoryMgr.

View File

@@ -126,8 +126,8 @@ class NetSSL_Win_API SSLManager
/// - requireTLSv1_2 (boolean): Require a TLSv1.2 connection. Not supported on Windows Embedded Compact. /// - requireTLSv1_2 (boolean): Require a TLSv1.2 connection. Not supported on Windows Embedded Compact.
{ {
public: public:
typedef Poco::SharedPtr<PrivateKeyPassphraseHandler> PrivateKeyPassphraseHandlerPtr; using PrivateKeyPassphraseHandlerPtr = Poco::SharedPtr<PrivateKeyPassphraseHandler>;
typedef Poco::SharedPtr<InvalidCertificateHandler> InvalidCertificateHandlerPtr; using InvalidCertificateHandlerPtr = Poco::SharedPtr<InvalidCertificateHandler>;
Poco::BasicEvent<VerificationErrorArgs> ServerVerificationError; Poco::BasicEvent<VerificationErrorArgs> ServerVerificationError;
/// Fired whenever a certificate verification error is detected by the server during a handshake. /// Fired whenever a certificate verification error is detected by the server during a handshake.
@@ -292,6 +292,7 @@ private:
static const std::string CFG_REQUIRE_TLSV1; static const std::string CFG_REQUIRE_TLSV1;
static const std::string CFG_REQUIRE_TLSV1_1; static const std::string CFG_REQUIRE_TLSV1_1;
static const std::string CFG_REQUIRE_TLSV1_2; static const std::string CFG_REQUIRE_TLSV1_2;
static const std::string CFG_REQUIRE_TLSV1_3;
friend class Poco::SingletonHolder<SSLManager>; friend class Poco::SingletonHolder<SSLManager>;
friend class SecureSocketImpl; friend class SecureSocketImpl;

View File

@@ -36,7 +36,7 @@ class NetSSL_Win_API Session: public Poco::RefCountedObject
/// if it wants to reuse it with a future connection. /// if it wants to reuse it with a future connection.
{ {
public: public:
typedef Poco::AutoPtr<Session> Ptr; using Ptr = Poco::AutoPtr<Session>;
protected: protected:
Session(); Session();

View File

@@ -46,6 +46,7 @@ Context::Context(Usage usage,
_usage(usage), _usage(usage),
_mode(verMode), _mode(verMode),
_options(options), _options(options),
_disabledProtocols(0),
_extendedCertificateVerification(true), _extendedCertificateVerification(true),
_certNameOrPath(certNameOrPath), _certNameOrPath(certNameOrPath),
_certStoreName(certStore), _certStoreName(certStore),
@@ -331,69 +332,190 @@ void Context::acquireSchannelCredentials(CredHandle& credHandle) const
DWORD Context::proto() const DWORD Context::proto() const
{ {
DWORD result = 0;
switch (_usage) switch (_usage)
{ {
case Context::TLS_CLIENT_USE:
case Context::CLIENT_USE: case Context::CLIENT_USE:
return SP_PROT_SSL3_CLIENT result = SP_PROT_SSL3_CLIENT
| SP_PROT_TLS1_CLIENT | SP_PROT_TLS1_CLIENT
#if defined(SP_PROT_TLS1_1) #if defined(SP_PROT_TLS1_1)
| SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_1_CLIENT
#endif #endif
#if defined(SP_PROT_TLS1_2) #if defined(SP_PROT_TLS1_2)
| SP_PROT_TLS1_2_CLIENT | SP_PROT_TLS1_2_CLIENT
#endif
#if defined(SP_PROT_TLS1_3)
| SP_PROT_TLS1_3_CLIENT
#endif #endif
; ;
break;
case Context::TLS_SERVER_USE:
case Context::SERVER_USE: case Context::SERVER_USE:
return SP_PROT_SSL3_SERVER result = SP_PROT_SSL3_SERVER
| SP_PROT_TLS1_SERVER | SP_PROT_TLS1_SERVER
#if defined(SP_PROT_TLS1_1) #if defined(SP_PROT_TLS1_1)
| SP_PROT_TLS1_1_SERVER | SP_PROT_TLS1_1_SERVER
#endif #endif
#if defined(SP_PROT_TLS1_2) #if defined(SP_PROT_TLS1_2)
| SP_PROT_TLS1_2_SERVER | SP_PROT_TLS1_2_SERVER
#endif
#if defined(SP_PROT_TLS1_3)
| SP_PROT_TLS1_3_SERVER
#endif #endif
; ;
break;
case Context::TLSV1_CLIENT_USE: case Context::TLSV1_CLIENT_USE:
return SP_PROT_TLS1_CLIENT result = SP_PROT_TLS1_CLIENT
#if defined(SP_PROT_TLS1_1) #if defined(SP_PROT_TLS1_1)
| SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_1_CLIENT
#endif #endif
#if defined(SP_PROT_TLS1_2) #if defined(SP_PROT_TLS1_2)
| SP_PROT_TLS1_2_CLIENT | SP_PROT_TLS1_2_CLIENT
#endif
#if defined(SP_PROT_TLS1_3)
| SP_PROT_TLS1_3_CLIENT
#endif #endif
; ;
break;
case Context::TLSV1_SERVER_USE: case Context::TLSV1_SERVER_USE:
return SP_PROT_TLS1_SERVER result = SP_PROT_TLS1_SERVER
#if defined(SP_PROT_TLS1_1) #if defined(SP_PROT_TLS1_1)
| SP_PROT_TLS1_1_SERVER | SP_PROT_TLS1_1_SERVER
#endif #endif
#if defined(SP_PROT_TLS1_2) #if defined(SP_PROT_TLS1_2)
| SP_PROT_TLS1_2_SERVER | SP_PROT_TLS1_2_SERVER
#endif
#if defined(SP_PROT_TLS1_3)
| SP_PROT_TLS1_3_SERVER
#endif #endif
; ;
break;
#if defined(SP_PROT_TLS1_1) #if defined(SP_PROT_TLS1_1)
case Context::TLSV1_1_CLIENT_USE: case Context::TLSV1_1_CLIENT_USE:
return SP_PROT_TLS1_1_CLIENT result = SP_PROT_TLS1_1_CLIENT
#if defined(SP_PROT_TLS1_2) #if defined(SP_PROT_TLS1_2)
| SP_PROT_TLS1_2_CLIENT | SP_PROT_TLS1_2_CLIENT
#endif
#if defined(SP_PROT_TLS1_3)
| SP_PROT_TLS1_3_CLIENT
#endif #endif
; ;
break;
case Context::TLSV1_1_SERVER_USE: case Context::TLSV1_1_SERVER_USE:
return SP_PROT_TLS1_1_SERVER result = SP_PROT_TLS1_1_SERVER
#if defined(SP_PROT_TLS1_2) #if defined(SP_PROT_TLS1_2)
| SP_PROT_TLS1_2_SERVER | SP_PROT_TLS1_2_SERVER
#endif #endif
; #if defined(SP_PROT_TLS1_3)
| SP_PROT_TLS1_3_SERVER
#endif #endif
;
break;
#endif
#if defined(SP_PROT_TLS1_2) #if defined(SP_PROT_TLS1_2)
case Context::TLSV1_2_CLIENT_USE: case Context::TLSV1_2_CLIENT_USE:
return SP_PROT_TLS1_2_CLIENT; result = SP_PROT_TLS1_2_CLIENT
case Context::TLSV1_2_SERVER_USE: #if defined(SP_PROT_TLS1_3)
return SP_PROT_TLS1_2_SERVER; | SP_PROT_TLS1_3_CLIENT
#endif #endif
;
break;
case Context::TLSV1_2_SERVER_USE:
result = SP_PROT_TLS1_2_SERVER
#if defined(SP_PROT_TLS1_3)
| SP_PROT_TLS1_3_SERVER
#endif
;
break;
#endif
#if defined(SP_PROT_TLS1_3)
case Context::TLSV1_3_CLIENT_USE:
result = SP_PROT_TLS1_3_CLIENT;
break;
case Context::TLSV1_3_SERVER_USE:
result = SP_PROT_TLS1_3_SERVER;
break;
#endif
default: default:
throw Poco::InvalidArgumentException("Unsupported SSL/TLS protocol version"); throw Poco::InvalidArgumentException("Unsupported SSL/TLS protocol version");
} }
return result & enabledProtocols();
} }
DWORD Context::enabledProtocols() const
{
DWORD result = 0;
if (!(_disabledProtocols & PROTO_SSLV3))
{
result |= SP_PROT_SSL3_CLIENT | SP_PROT_SSL3_SERVER;
}
if (!(_disabledProtocols & PROTO_TLSV1))
{
result |= SP_PROT_TLS1_CLIENT | SP_PROT_TLS1_SERVER;
}
if (!(_disabledProtocols & PROTO_TLSV1_1))
{
#ifdef SP_PROT_TLS1_1_CLIENT
result |= SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_1_SERVER;
#endif
}
if (!(_disabledProtocols & PROTO_TLSV1_2))
{
#ifdef SP_PROT_TLS1_2_CLIENT
result |= SP_PROT_TLS1_2_CLIENT | SP_PROT_TLS1_2_SERVER;
#endif
}
if (!(_disabledProtocols & PROTO_TLSV1_3))
{
#ifdef SP_PROT_TLS1_3_CLIENT
result |= SP_PROT_TLS1_3_CLIENT | SP_PROT_TLS1_3_SERVER;
#endif
}
return result;
}
void Context::disableProtocols(int protocols)
{
_disabledProtocols = protocols;
}
void Context::requireMinimumProtocol(Protocols protocol)
{
_disabledProtocols = 0;
switch (protocol)
{
case PROTO_SSLV3:
_disabledProtocols = PROTO_SSLV2;
break;
case PROTO_TLSV1:
_disabledProtocols = PROTO_SSLV2 | PROTO_SSLV3;
break;
case PROTO_TLSV1_1:
_disabledProtocols = PROTO_SSLV2 | PROTO_SSLV3 | PROTO_TLSV1;
break;
case PROTO_TLSV1_2:
_disabledProtocols = PROTO_SSLV2 | PROTO_SSLV3 | PROTO_TLSV1 | PROTO_TLSV1_1;
break;
case PROTO_TLSV1_3:
_disabledProtocols = PROTO_SSLV2 | PROTO_SSLV3 | PROTO_TLSV1 | PROTO_TLSV1_1 | PROTO_TLSV1_2;
break;
}
}
} } // namespace Poco::Net } } // namespace Poco::Net

View File

@@ -52,6 +52,7 @@ const std::string SSLManager::CFG_CLIENT_PREFIX("schannel.client.");
const std::string SSLManager::CFG_REQUIRE_TLSV1("requireTLSv1"); const std::string SSLManager::CFG_REQUIRE_TLSV1("requireTLSv1");
const std::string SSLManager::CFG_REQUIRE_TLSV1_1("requireTLSv1_1"); const std::string SSLManager::CFG_REQUIRE_TLSV1_1("requireTLSv1_1");
const std::string SSLManager::CFG_REQUIRE_TLSV1_2("requireTLSv1_2"); const std::string SSLManager::CFG_REQUIRE_TLSV1_2("requireTLSv1_2");
const std::string SSLManager::CFG_REQUIRE_TLSV1_3("requireTLSv1_3");
SSLManager::SSLManager(): SSLManager::SSLManager():
@@ -195,6 +196,7 @@ void SSLManager::initDefaultContext(bool server)
bool requireTLSv1 = config.getBool(prefix + CFG_REQUIRE_TLSV1, false); bool requireTLSv1 = config.getBool(prefix + CFG_REQUIRE_TLSV1, false);
bool requireTLSv1_1 = config.getBool(prefix + CFG_REQUIRE_TLSV1_1, false); bool requireTLSv1_1 = config.getBool(prefix + CFG_REQUIRE_TLSV1_1, false);
bool requireTLSv1_2 = config.getBool(prefix + CFG_REQUIRE_TLSV1_2, false); bool requireTLSv1_2 = config.getBool(prefix + CFG_REQUIRE_TLSV1_2, false);
bool requireTLSv1_3 = config.getBool(prefix + CFG_REQUIRE_TLSV1_3, false);
// optional options for which we have defaults defined // optional options for which we have defaults defined
Context::VerificationMode verMode = VAL_VER_MODE; Context::VerificationMode verMode = VAL_VER_MODE;
@@ -223,7 +225,9 @@ void SSLManager::initDefaultContext(bool server)
Context::Usage usage; Context::Usage usage;
if (server) if (server)
{ {
if (requireTLSv1_2) if (requireTLSv1_3)
usage = Context::TLSV1_3_SERVER_USE;
else if (requireTLSv1_2)
usage = Context::TLSV1_2_SERVER_USE; usage = Context::TLSV1_2_SERVER_USE;
else if (requireTLSv1_1) else if (requireTLSv1_1)
usage = Context::TLSV1_1_SERVER_USE; usage = Context::TLSV1_1_SERVER_USE;
@@ -235,7 +239,9 @@ void SSLManager::initDefaultContext(bool server)
} }
else else
{ {
if (requireTLSv1_2) if (requireTLSv1_3)
usage = Context::TLSV1_3_CLIENT_USE;
else if (requireTLSv1_2)
usage = Context::TLSV1_2_CLIENT_USE; usage = Context::TLSV1_2_CLIENT_USE;
else if (requireTLSv1_1) else if (requireTLSv1_1)
usage = Context::TLSV1_1_CLIENT_USE; usage = Context::TLSV1_1_CLIENT_USE;