diff --git a/src/network/ssl/qsslcontext_openssl.cpp b/src/network/ssl/qsslcontext_openssl.cpp index b3786f9..d37975c 100644 --- a/src/network/ssl/qsslcontext_openssl.cpp +++ b/src/network/ssl/qsslcontext_openssl.cpp @@ -71,6 +71,13 @@ static DH *get_dh1024() return dh; } +static bool q_enableECSetCurves() { + // The ability to select elliptic curves is + // present in OpenSSL 1.0.2+ but not in LibreSSL. + // RFC4492 Section 5.1.1 "Supported Elliptic Curves Extension" + return q_SSLeay() >= 0x10002000L && !q_LibreSSL(); +} + QSslContext::QSslContext() : ctx(0), pkey(0), @@ -346,9 +353,9 @@ init_context: const QVector qcurves = sslContext->sslConfiguration.ellipticCurves(); if (!qcurves.isEmpty()) { -#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_EC) +#if defined(SSL_CTRL_SET_CURVES) && !defined(OPENSSL_NO_EC) // Set the curves to be used - if (q_SSLeay() >= 0x10002000L) { + if (q_enableECSetCurves()) { // SSL_CTX_ctrl wants a non-const pointer as last argument, // but let's avoid a copy into a temporary array if (!q_SSL_CTX_ctrl(sslContext->ctx, @@ -359,10 +366,10 @@ init_context: sslContext->errorCode = QSslError::UnspecifiedError; } } else -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_EC) +#endif // defined(SSL_CTRL_SET_CURVES) && !defined(OPENSSL_NO_EC) { // specific curves requested, but not possible to set -> error - sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocket::tr("OpenSSL version too old, need at least v1.0.2")); + sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocket::tr("This version of OpenSSL lacks support for selecting specific elliptic curves.")); sslContext->errorCode = QSslError::UnspecifiedError; } } diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 4f62f53..cedba5b 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -98,6 +98,13 @@ bool QSslSocketPrivate::s_loadRootCertsOnDemand = false; int QSslSocketBackendPrivate::s_indexForSSLExtraData = -1; #endif +static bool q_enableGetServerTmpKey() { + // The ability to get the ephemeral server key is + // present in OpenSSL 1.0.2+ but not in LibreSSL. + // RFC4492 Section 5.4 "Server Key Exchange" + return q_SSLeay() >= 0x10002000L && !q_LibreSSL(); +} + /* \internal From OpenSSL's thread(3) manual page: @@ -1579,13 +1586,13 @@ void QSslSocketBackendPrivate::continueHandshake() } #endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ... -#if OPENSSL_VERSION_NUMBER >= 0x10002000L - if (q_SSLeay() >= 0x10002000L && mode == QSslSocket::SslClientMode) { +#if defined(SSL_CTRL_GET_SERVER_TMP_KEY) + if (q_enableGetServerTmpKey() && mode == QSslSocket::SslClientMode) { EVP_PKEY *key; if (q_SSL_get_server_tmp_key(ssl, &key)) configuration.ephemeralServerKey = QSslKey(key, QSsl::PublicKey); } -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ... +#endif // defined(SSL_CTRL_GET_SERVER_TMP_KEY) ... connectionEncrypted = true; emit q->encrypted(); diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index d098237..bd9a8a4 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -1006,6 +1006,11 @@ bool q_resolveOpenSslSymbols() #endif return true; } + +bool q_LibreSSL() +{ + return strncmp(q_SSLeay_version(SSLEAY_VERSION), "LibreSSL", 8) == 0; +} #endif // !defined QT_LINKED_OPENSSL //============================================================================== diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h index 36e041b..3ac4e3f 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols_p.h +++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h @@ -215,6 +215,7 @@ QT_BEGIN_NAMESPACE #endif // !defined QT_LINKED_OPENSSL bool q_resolveOpenSslSymbols(); +bool q_LibreSSL(); long q_ASN1_INTEGER_get(ASN1_INTEGER *a); unsigned char * q_ASN1_STRING_data(ASN1_STRING *a); int q_ASN1_STRING_length(ASN1_STRING *a); @@ -489,9 +490,9 @@ size_t q_EC_get_builtin_curves(EC_builtin_curve *r, size_t nitems); int q_EC_curve_nist2nid(const char *name); #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L #endif // OPENSSL_NO_EC -#if OPENSSL_VERSION_NUMBER >= 0x10002000L +#if defined(SSL_CTRL_GET_SERVER_TMP_KEY) #define q_SSL_get_server_tmp_key(ssl, key) q_SSL_ctrl((ssl), SSL_CTRL_GET_SERVER_TMP_KEY, 0, (char *)key) -#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L +#endif // defined(SSL_CTRL_GET_SERVER_TMP_KEY) // PKCS#12 support int q_PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca);