diff --git a/CMakeLists.txt b/CMakeLists.txt index f3cb26f38f6..46182f634a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -202,6 +202,11 @@ include_directories(${JSON_INCLUDE}) find_package(UTF8CPP) include_directories(${UTF8CPP_INCLUDE}) +if(WIN32) + find_package(BoostWinTLS) + include_directories(${BoostWinTLS_INCLUDE}) +endif() + find_package(Editline) set(HAVE_EDITLINE "${EDITLINE_FOUND}") diff --git a/cmake/FindBoostWinTLS.cmake b/cmake/FindBoostWinTLS.cmake new file mode 100644 index 00000000000..f2e27da9e56 --- /dev/null +++ b/cmake/FindBoostWinTLS.cmake @@ -0,0 +1,8 @@ +FIND_PATH(BoostWinTLS_HEADERS wintls.hpp HINTS "${PROJECT_SOURCE_DIR}/third-party/boost-wintls/include/boost") + +if(BoostWinTLS_HEADERS) + set(BoostWinTLS_INCLUDE "${BoostWinTLS_HEADERS}/..") + message(STATUS "Found Boost.WinTLS: ${BoostWinTLS_INCLUDE}") +else() + message(FATAL_ERROR "Unable to include wintls.hpp") +endif() diff --git a/lib/base/tlsstream.hpp b/lib/base/tlsstream.hpp index f6e52097e11..0ea833df142 100644 --- a/lib/base/tlsstream.hpp +++ b/lib/base/tlsstream.hpp @@ -20,6 +20,10 @@ #include #include +#ifdef _WIN32 +# include +#endif /* _WIN32 */ + namespace icinga { @@ -59,11 +63,34 @@ class SeenStream : public ARS struct UnbufferedAsioTlsStreamParams { boost::asio::io_context& IoContext; - boost::asio::ssl::context& SslContext; + TlsContext& SslContext; const String& Hostname; }; -typedef SeenStream> AsioTcpTlsStream; +#ifdef _WIN32 +template +class TlsStream : public boost::wintls::stream +{ +public: + using boost::wintls::stream::stream; + + typedef typename next_layer_type::lowest_layer_type lowest_layer_type; + typedef boost::wintls::handshake_type handshake_type; + + static constexpr auto client = boost::wintls::handshake_type::client; + static constexpr auto server = boost::wintls::handshake_type::server; + + lowest_layer_type& lowest_layer() + { + return next_layer().lowest_layer(); + } +}; +#else /* _WIN32 */ +template +using TlsStream = boost::asio::ssl::stream; +#endif /* _WIN32 */ + +typedef SeenStream> AsioTcpTlsStream; class UnbufferedAsioTlsStream : public AsioTcpTlsStream { @@ -108,7 +135,7 @@ class AsioTlsStream : public boost::asio::buffered_stream #include #include +#include namespace icinga { @@ -72,18 +73,18 @@ void InitializeOpenSSL() l_SSLInitialized = true; } -static void InitSslContext(const Shared::Ptr& context, const String& pubkey, const String& privkey, const String& cakey) +static void InitSslContext(const Shared::Ptr& context, const String& pubkey, const String& privkey, const String& cakey) { char errbuf[256]; // Enforce TLS v1.2 as minimum context->set_options( - boost::asio::ssl::context::default_workarounds | - boost::asio::ssl::context::no_compression | - boost::asio::ssl::context::no_sslv2 | - boost::asio::ssl::context::no_sslv3 | - boost::asio::ssl::context::no_tlsv1 | - boost::asio::ssl::context::no_tlsv1_1 + TlsContext::default_workarounds | + TlsContext::no_compression | + TlsContext::no_sslv2 | + TlsContext::no_sslv3 | + TlsContext::no_tlsv1 | + TlsContext::no_tlsv1_1 ); // Custom TLS flags @@ -194,33 +195,12 @@ static void InitSslContext(const Shared::Ptr& context } } -/** - * Initializes an SSL context using the specified certificates. - * - * @param pubkey The public key. - * @param privkey The matching private key. - * @param cakey CA certificate chain file. - * @returns An SSL context. - */ -Shared::Ptr MakeAsioSslContext(const String& pubkey, const String& privkey, const String& cakey) -{ - namespace ssl = boost::asio::ssl; - - InitializeOpenSSL(); - - auto context (Shared::Make(ssl::context::tls)); - - InitSslContext(context, pubkey, privkey, cakey); - - return context; -} - /** * Set the cipher list to the specified SSL context. * @param context The ssl context. * @param cipherList The ciper list. **/ -void SetCipherListToSSLContext(const Shared::Ptr& context, const String& cipherList) +void SetCipherListToSSLContext(const Shared::Ptr& context, const String& cipherList) { char errbuf[256]; @@ -264,32 +244,59 @@ void SetCipherListToSSLContext(const Shared::Ptr& con * @param version String of a TLS version, for example "TLSv1.2". * @return The value of the corresponding TLS*_VERSION macro. */ -int ResolveTlsProtocolVersion(const std::string& version) { +TlsProtocolMin ResolveTlsProtocolVersion(const std::string& version) { +#ifdef _WIN32 + if (version == "TLSv1.2") { + return TlsProtocolMin((int)TlsProtocolMin::tlsv12 | (int)TlsProtocolMin::tlsv13); + } else if (version == "TLSv1.3") { + return TlsProtocolMin::tlsv13; +#else /* _WIN32 */ if (version == "TLSv1.2") { return TLS1_2_VERSION; } else if (version == "TLSv1.3") { -#if OPENSSL_VERSION_NUMBER >= 0x10101000L +# if OPENSSL_VERSION_NUMBER >= 0x10101000L return TLS1_3_VERSION; -#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */ +# else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */ throw std::runtime_error("'" + version + "' is only supported with OpenSSL 1.1.1 or newer"); -#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */ +# endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */ +#endif /* _WIN32 */ } else { throw std::runtime_error("Unknown TLS protocol version '" + version + "'"); } } -Shared::Ptr SetupSslContext(String certPath, String keyPath, - String caPath, String crlPath, String cipherList, String protocolmin, DebugInfo di) +Shared::Ptr SetupSslContext(const String& certPath, const String& keyPath, + const String& caPath, const String& crlPath, const String& cipherList, const String& protocolmin, DebugInfo di) { namespace ssl = boost::asio::ssl; - Shared::Ptr context; + Shared::Ptr context; + +#ifdef _WIN32 + auto method (TlsProtocolMin::system_default); +#else /* _WIN32 */ + auto method (TlsContext::tls); +#endif /* _WIN32 */ + + InitializeOpenSSL(); + +#ifdef _WIN32 + if (!protocolmin.IsEmpty()) { + try { + method = ResolveTlsProtocolVersion(protocolmin); + } catch (const std::exception&) { + BOOST_THROW_EXCEPTION(ScriptError("Cannot set minimum TLS protocol version to SSL context with tls_protocolmin: '" + protocolmin + "'.", std::move(di))); + } + } +#endif /* _WIN32 */ try { - context = MakeAsioSslContext(certPath, keyPath, caPath); + context = Shared::Make(method); + + InitSslContext(context, certPath, keyPath, caPath); } catch (const std::exception&) { BOOST_THROW_EXCEPTION(ScriptError("Cannot make SSL context for cert path: '" - + certPath + "' key path: '" + keyPath + "' ca path: '" + caPath + "'.", di)); + + certPath + "' key path: '" + keyPath + "' ca path: '" + caPath + "'.", std::move(di))); } if (!crlPath.IsEmpty()) { @@ -297,7 +304,7 @@ Shared::Ptr SetupSslContext(String certPath, String k AddCRLToSSLContext(context, crlPath); } catch (const std::exception&) { BOOST_THROW_EXCEPTION(ScriptError("Cannot add certificate revocation list to SSL context for crl path: '" - + crlPath + "'.", di)); + + crlPath + "'.", std::move(di))); } } @@ -306,30 +313,33 @@ Shared::Ptr SetupSslContext(String certPath, String k SetCipherListToSSLContext(context, cipherList); } catch (const std::exception&) { BOOST_THROW_EXCEPTION(ScriptError("Cannot set cipher list to SSL context for cipher list: '" - + cipherList + "'.", di)); + + cipherList + "'.", std::move(di))); } } +#ifndef _WIN32 if (!protocolmin.IsEmpty()){ try { SetTlsProtocolminToSSLContext(context, protocolmin); } catch (const std::exception&) { - BOOST_THROW_EXCEPTION(ScriptError("Cannot set minimum TLS protocol version to SSL context with tls_protocolmin: '" + protocolmin + "'.", di)); + BOOST_THROW_EXCEPTION(ScriptError("Cannot set minimum TLS protocol version to SSL context with tls_protocolmin: '" + protocolmin + "'.", std::move(di))); } } +#endif /* _WIN32 */ return context; } +#ifndef _WIN32 /** * Set the minimum TLS protocol version to the specified SSL context. * * @param context The ssl context. * @param tlsProtocolmin The minimum TLS protocol version. */ -void SetTlsProtocolminToSSLContext(const Shared::Ptr& context, const String& tlsProtocolmin) +void SetTlsProtocolminToSSLContext(const Shared::Ptr& context, const String& tlsProtocolmin) { -#if OPENSSL_VERSION_NUMBER >= 0x10100000L +# if OPENSSL_VERSION_NUMBER >= 0x10100000L int ret = SSL_CTX_set_min_proto_version(context->native_handle(), ResolveTlsProtocolVersion(tlsProtocolmin)); if (ret != 1) { @@ -342,12 +352,13 @@ void SetTlsProtocolminToSSLContext(const Shared::Ptr& << boost::errinfo_api_function("SSL_CTX_set_min_proto_version") << errinfo_openssl_error(ERR_peek_error())); } -#else /* OPENSSL_VERSION_NUMBER >= 0x10100000L */ +# else /* OPENSSL_VERSION_NUMBER >= 0x10100000L */ // This should never happen. On this OpenSSL version, ResolveTlsProtocolVersion() should either return TLS 1.2 // or throw an exception, as that's the only TLS version supported by both Icinga and ancient OpenSSL. VERIFY(ResolveTlsProtocolVersion(tlsProtocolmin) == TLS1_2_VERSION); -#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */ +# endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */ } +#endif /* _WIN32 */ /** * Loads a CRL and appends its certificates to the specified Boost SSL context. @@ -355,7 +366,7 @@ void SetTlsProtocolminToSSLContext(const Shared::Ptr& * @param context The SSL context. * @param crlPath The path to the CRL file. */ -void AddCRLToSSLContext(const Shared::Ptr& context, const String& crlPath) +void AddCRLToSSLContext(const Shared::Ptr& context, const String& crlPath) { X509_STORE *x509_store = SSL_CTX_get_cert_store(context->native_handle()); AddCRLToSSLContext(x509_store, crlPath); diff --git a/lib/base/tlsutility.hpp b/lib/base/tlsutility.hpp index b0641202011..b3d4f23f98b 100644 --- a/lib/base/tlsutility.hpp +++ b/lib/base/tlsutility.hpp @@ -22,6 +22,10 @@ #include #include +#ifdef _WIN32 +# include +#endif /* _WIN32 */ + namespace icinga { @@ -38,19 +42,27 @@ const auto LEAF_VALID_FOR = 60 * 60 * 24 * 397; const auto RENEW_THRESHOLD = 60 * 60 * 24 * 30; const auto RENEW_INTERVAL = 60 * 60 * 24; +#ifdef _WIN32 +typedef boost::wintls::context TlsContext; +typedef boost::wintls::method TlsProtocolMin; +#else /* _WIN32 */ +typedef boost::asio::ssl::context TlsContext; +typedef int TlsProtocolMin; + +void SetTlsProtocolminToSSLContext(const Shared::Ptr& context, const String& tlsProtocolmin); +#endif /* _WIN32 */ + void InitializeOpenSSL(); String GetOpenSSLVersion(); -Shared::Ptr MakeAsioSslContext(const String& pubkey = String(), const String& privkey = String(), const String& cakey = String()); -void AddCRLToSSLContext(const Shared::Ptr& context, const String& crlPath); +void AddCRLToSSLContext(const Shared::Ptr& context, const String& crlPath); void AddCRLToSSLContext(X509_STORE *x509_store, const String& crlPath); -void SetCipherListToSSLContext(const Shared::Ptr& context, const String& cipherList); -void SetTlsProtocolminToSSLContext(const Shared::Ptr& context, const String& tlsProtocolmin); -int ResolveTlsProtocolVersion(const std::string& version); +void SetCipherListToSSLContext(const Shared::Ptr& context, const String& cipherList); +TlsProtocolMin ResolveTlsProtocolVersion(const std::string& version); -Shared::Ptr SetupSslContext(String certPath, String keyPath, - String caPath, String crlPath, String cipherList, String protocolmin, DebugInfo di); +Shared::Ptr SetupSslContext(const String& certPath = String(), const String& keyPath = String(), const String& caPath = String(), + const String& crlPath = String(), const String& cipherList = String(), const String& protocolmin = String(), DebugInfo di = {}); String GetCertificateCN(const std::shared_ptr& certificate); std::shared_ptr GetX509Certificate(const String& pemfile); diff --git a/lib/base/win32.hpp b/lib/base/win32.hpp index 064c5d66953..80d8729f36d 100644 --- a/lib/base/win32.hpp +++ b/lib/base/win32.hpp @@ -5,7 +5,7 @@ #define WIN32_LEAN_AND_MEAN #ifndef _WIN32_WINNT -#define _WIN32_WINNT _WIN32_WINNT_VISTA +#define _WIN32_WINNT _WIN32_WINNT_WIN7 #endif /* _WIN32_WINNT */ #define NOMINMAX #include diff --git a/lib/cli/consolecommand.cpp b/lib/cli/consolecommand.cpp index 78906bb2a74..0e7dea49e62 100644 --- a/lib/cli/consolecommand.cpp +++ b/lib/cli/consolecommand.cpp @@ -524,13 +524,12 @@ int ConsoleCommand::RunScriptConsole(ScriptFrame& scriptFrame, const String& con */ Shared::Ptr ConsoleCommand::Connect() { - Shared::Ptr sslContext; + Shared::Ptr sslContext; try { - sslContext = MakeAsioSslContext(Empty, Empty, Empty); //TODO: Add support for cert, key, ca parameters + sslContext = SetupSslContext(); //TODO: Add support for cert, key, ca parameters } catch(const std::exception& ex) { - Log(LogCritical, "DebugConsole") - << "Cannot make SSL context: " << ex.what(); + Log(LogCritical, "DebugConsole") << ex.what(); throw; } diff --git a/lib/icingadb/redisconnection.hpp b/lib/icingadb/redisconnection.hpp index f346ba2854f..a36da7317c9 100644 --- a/lib/icingadb/redisconnection.hpp +++ b/lib/icingadb/redisconnection.hpp @@ -183,7 +183,7 @@ namespace icinga typedef boost::asio::buffered_stream TcpConn; typedef boost::asio::buffered_stream UnixConn; - Shared::Ptr m_TLSContext; + Shared::Ptr m_TLSContext; template static Value ReadRESP(AsyncReadStream& stream, boost::asio::yield_context& yc); diff --git a/lib/methods/ifwapichecktask.cpp b/lib/methods/ifwapichecktask.cpp index 8516d70c033..b3b5d876ae3 100644 --- a/lib/methods/ifwapichecktask.cpp +++ b/lib/methods/ifwapichecktask.cpp @@ -497,11 +497,11 @@ void IfwApiCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckRes auto& io (IoEngine::Get().GetIoContext()); auto strand (Shared::Make(io)); - Shared::Ptr ctx; + Shared::Ptr ctx; double start = Utility::GetTime(); try { - ctx = SetupSslContext(cert, key, ca, crl, DEFAULT_TLS_CIPHERS, DEFAULT_TLS_PROTOCOLMIN, DebugInfo()); + ctx = SetupSslContext(cert, key, ca, crl, DEFAULT_TLS_CIPHERS, DEFAULT_TLS_PROTOCOLMIN); } catch (const std::exception& ex) { ReportIfwCheckResult(checkable, cmdLine, cr, ex.what(), start, Utility::GetTime()); return; diff --git a/lib/perfdata/elasticsearchwriter.cpp b/lib/perfdata/elasticsearchwriter.cpp index 9fb2aa90fe8..f797f3f35c0 100644 --- a/lib/perfdata/elasticsearchwriter.cpp +++ b/lib/perfdata/elasticsearchwriter.cpp @@ -602,13 +602,12 @@ OptionalTlsStream ElasticsearchWriter::Connect() bool tls = GetEnableTls(); if (tls) { - Shared::Ptr sslContext; + Shared::Ptr sslContext; try { - sslContext = MakeAsioSslContext(GetCertPath(), GetKeyPath(), GetCaPath()); - } catch (const std::exception&) { - Log(LogWarning, "ElasticsearchWriter") - << "Unable to create SSL context."; + sslContext = SetupSslContext(GetCertPath(), GetKeyPath(), GetCaPath()); + } catch (const std::exception& ex) { + Log(LogWarning, "ElasticsearchWriter") << ex.what(); throw; } diff --git a/lib/perfdata/gelfwriter.cpp b/lib/perfdata/gelfwriter.cpp index c5b2bbd132e..cac722051d9 100644 --- a/lib/perfdata/gelfwriter.cpp +++ b/lib/perfdata/gelfwriter.cpp @@ -174,13 +174,12 @@ void GelfWriter::ReconnectInternal() bool ssl = GetEnableTls(); if (ssl) { - Shared::Ptr sslContext; + Shared::Ptr sslContext; try { - sslContext = MakeAsioSslContext(GetCertPath(), GetKeyPath(), GetCaPath()); + sslContext = SetupSslContext(GetCertPath(), GetKeyPath(), GetCaPath()); } catch (const std::exception& ex) { - Log(LogWarning, "GelfWriter") - << "Unable to create SSL context."; + Log(LogWarning, "GelfWriter") << ex.what(); throw; } diff --git a/lib/perfdata/influxdbcommonwriter.cpp b/lib/perfdata/influxdbcommonwriter.cpp index a7631083993..34f0f36f876 100644 --- a/lib/perfdata/influxdbcommonwriter.cpp +++ b/lib/perfdata/influxdbcommonwriter.cpp @@ -149,13 +149,12 @@ OptionalTlsStream InfluxdbCommonWriter::Connect() bool ssl = GetSslEnable(); if (ssl) { - Shared::Ptr sslContext; + Shared::Ptr sslContext; try { - sslContext = MakeAsioSslContext(GetSslCert(), GetSslKey(), GetSslCaCert()); + sslContext = SetupSslContext(GetSslCert(), GetSslKey(), GetSslCaCert()); } catch (const std::exception& ex) { - Log(LogWarning, GetReflectionType()->GetName()) - << "Unable to create SSL context."; + Log(LogWarning, GetReflectionType()->GetName()) << ex.what(); throw; } diff --git a/lib/remote/apilistener.hpp b/lib/remote/apilistener.hpp index fced0a8afb1..870294ca826 100644 --- a/lib/remote/apilistener.hpp +++ b/lib/remote/apilistener.hpp @@ -161,7 +161,7 @@ class ApiListener final : public ObjectImpl void ValidateTlsHandshakeTimeout(const Lazy& lvalue, const ValidationUtils& utils) override; private: - Shared::Ptr m_SSLContext; + Shared::Ptr m_SSLContext; boost::shared_mutex m_SSLContextMutex; mutable std::mutex m_AnonymousClientsLock; diff --git a/lib/remote/pkiutility.cpp b/lib/remote/pkiutility.cpp index e4935655975..38ca1cd0bd5 100644 --- a/lib/remote/pkiutility.cpp +++ b/lib/remote/pkiutility.cpp @@ -83,15 +83,13 @@ int PkiUtility::SignCsr(const String& csrfile, const String& certfile) std::shared_ptr PkiUtility::FetchCert(const String& host, const String& port) { - Shared::Ptr sslContext; + Shared::Ptr sslContext; try { - sslContext = MakeAsioSslContext(); + sslContext = SetupSslContext(); } catch (const std::exception& ex) { - Log(LogCritical, "pki") - << "Cannot make SSL context."; - Log(LogDebug, "pki") - << "Cannot make SSL context:\n" << DiagnosticInformation(ex); + Log(LogCritical, "pki") << ex.what(); + Log(LogDebug, "pki") << DiagnosticInformation(ex); return std::shared_ptr(); } @@ -151,15 +149,13 @@ int PkiUtility::GenTicket(const String& cn, const String& salt, std::ostream& ti int PkiUtility::RequestCertificate(const String& host, const String& port, const String& keyfile, const String& certfile, const String& cafile, const std::shared_ptr& trustedCert, const String& ticket) { - Shared::Ptr sslContext; + Shared::Ptr sslContext; try { - sslContext = MakeAsioSslContext(certfile, keyfile); + sslContext = SetupSslContext(certfile, keyfile); } catch (const std::exception& ex) { - Log(LogCritical, "cli") - << "Cannot make SSL context for cert path: '" << certfile << "' key path: '" << keyfile << "' ca path: '" << cafile << "'."; - Log(LogDebug, "cli") - << "Cannot make SSL context for cert path: '" << certfile << "' key path: '" << keyfile << "' ca path: '" << cafile << "':\n" << DiagnosticInformation(ex); + Log(LogCritical, "cli") << ex.what(); + Log(LogDebug, "cli") << DiagnosticInformation(ex); return 1; } diff --git a/plugins/check_nscp_api.cpp b/plugins/check_nscp_api.cpp index aef43fb98d1..bf5521d0066 100644 --- a/plugins/check_nscp_api.cpp +++ b/plugins/check_nscp_api.cpp @@ -176,13 +176,12 @@ static int FormatOutput(const Dictionary::Ptr& result) */ static Shared::Ptr Connect(const String& host, const String& port) { - Shared::Ptr sslContext; + Shared::Ptr sslContext; try { - sslContext = MakeAsioSslContext(Empty, Empty, Empty); //TODO: Add support for cert, key, ca parameters + sslContext = SetupSslContext(); //TODO: Add support for cert, key, ca parameters } catch(const std::exception& ex) { - Log(LogCritical, "DebugConsole") - << "Cannot make SSL context: " << ex.what(); + Log(LogCritical, "DebugConsole") << ex.what(); throw; } diff --git a/third-party/boost-wintls/.clang-format b/third-party/boost-wintls/.clang-format new file mode 100644 index 00000000000..41c853a00f9 --- /dev/null +++ b/third-party/boost-wintls/.clang-format @@ -0,0 +1,65 @@ +Language: Cpp +AlignAfterOpenBracket: Align +AlignEscapedNewlines: Left +AlignOperands: Align +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortEnumsOnASingleLine: false +AllowShortFunctionsOnASingleLine: false +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: None +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: false +BinPackParameters: false +BreakBeforeBraces: Attach +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeComma +BreakInheritanceList: BeforeComma +BreakStringLiterals: true +ColumnLimit: 120 +CompactNamespaces: false +Cpp11BracedListStyle: true +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: Always +FixNamespaceComments: true +IncludeBlocks: Regroup +IndentCaseLabels: true +IndentWidth: 2 +LambdaBodyIndentation: Signature +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +PackConstructorInitializers: Never +PenaltyBreakAssignment: 100 +PenaltyBreakBeforeFirstCallParameter: 100 +PenaltyReturnTypeOnItsOwnLine: 100 +PointerAlignment: Left +QualifierAlignment: Left +ReferenceAlignment: Left +ReflowComments: false +SeparateDefinitionBlocks: Always +ShortNamespaceLines: 0 +SortIncludes: Never +SortUsingDeclarations: true +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpacesInParentheses: false +Standard: c++14 +UseCRLF: false +UseTab: Never diff --git a/third-party/boost-wintls/.codecov.yml b/third-party/boost-wintls/.codecov.yml new file mode 100644 index 00000000000..f58a6226bc8 --- /dev/null +++ b/third-party/boost-wintls/.codecov.yml @@ -0,0 +1,10 @@ +coverage: + status: + project: + default: + target: auto + threshold: 1.0% + patch: off + +comment: + require_changes: true diff --git a/third-party/boost-wintls/.github/workflows/analyze.yml b/third-party/boost-wintls/.github/workflows/analyze.yml new file mode 100644 index 00000000000..f02b2731181 --- /dev/null +++ b/third-party/boost-wintls/.github/workflows/analyze.yml @@ -0,0 +1,48 @@ +--- +name: analyze +on: [push, pull_request] + +jobs: + analyze: + runs-on: windows-2022 + name: Run MSVC static code analyzer + strategy: + fail-fast: false + matrix: + config: [Release, Debug] + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Install Boost + uses: MarkusJx/install-boost@v2.4.4 + id: install-boost + with: + boost_version: 1.83.0 + toolset: msvc + platform_version: 2022 + + - name: Install packages + run: choco install openssl + + - name: Configure + env: + BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} + shell: bash + run: cmake -B build -T v143 -DENABLE_DOCUMENTATION=OFF -DCMAKE_CONFIGURATION_TYPES=${{ matrix.config }} + + - name: Run MSVC static code analyzer + uses: microsoft/msvc-code-analysis-action@v0.1.1 + id: run-analysis + with: + cmakeBuildDirectory: build + buildConfiguration: ${{ matrix.config }} + ruleset: NativeRecommendedRules.ruleset + + - name: Upload SARIF to GitHub + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: ${{ steps.run-analysis.outputs.sarif }} diff --git a/third-party/boost-wintls/.github/workflows/coverage.yml b/third-party/boost-wintls/.github/workflows/coverage.yml new file mode 100644 index 00000000000..4addc59e437 --- /dev/null +++ b/third-party/boost-wintls/.github/workflows/coverage.yml @@ -0,0 +1,48 @@ +--- +name: coverage + +on: + push: + branches: + - master + +jobs: + codecoverage: + runs-on: windows-2022 + name: Generate and upload code coverage + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Install Boost + uses: MarkusJx/install-boost@v2.4.4 + id: install-boost + with: + boost_version: 1.83.0 + toolset: msvc + platform_version: 2022 + + - name: Install packages + run: choco install openssl opencppcoverage + + - name: Configure + env: + BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} + shell: bash + run: cmake -B build -T v143 -DENABLE_DOCUMENTATION=OFF + + - name: Build + run: cmake --build build/ --target unittest + + - name: Generate code coverage + shell: bash + run: exec "${PROGRAMFILES}"/opencppcoverage/opencppcoverage --cover_children --sources="${GITHUB_WORKSPACE}"\\include --modules=unittest.exe --export_type=cobertura:cobertura.xml -- ctest + working-directory: build/ + + - name: Upload code coverage + uses: codecov/codecov-action@v3 + with: + files: build/cobertura.xml + fail_ci_if_error: true diff --git a/third-party/boost-wintls/.github/workflows/coverity.yml b/third-party/boost-wintls/.github/workflows/coverity.yml new file mode 100644 index 00000000000..ec81892ab99 --- /dev/null +++ b/third-party/boost-wintls/.github/workflows/coverity.yml @@ -0,0 +1,63 @@ +--- +name: coverity +on: + push: + branches: + - master + +jobs: + coverity-scan: + name: Build with coverity and upload to coverity scan + runs-on: windows-2022 + defaults: + run: + shell: bash + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Install Coverity Build Tool + run: | + curl -o coverity_tool.zip -d "token=$TOKEN&project=laudrup%2Fboost-wintls" https://scan.coverity.com/download/cxx/win64 + 7z x coverity_tool.zip + echo COV_CONFIGURE_PATH="$(find . -name 'cov-configure.exe')" >> $GITHUB_ENV + echo COV_BUILD_PATH="$(find . -name 'cov-build.exe')" >> $GITHUB_ENV + env: + TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} + + - name: Install packages + run: choco install openssl curl + + - name: Install Boost + uses: MarkusJx/install-boost@v2.4.4 + id: install-boost + with: + boost_version: 1.83.0 + toolset: msvc + platform_version: 2022 + + - name: Configure + env: + BOOST_ROOT: ${{ steps.install-boost.outputs.BOOST_ROOT }} + run: cmake -B build -DENABLE_DOCUMENTATION=OFF -DENABLE_EXAMPLES=OFF + + - name: Configure Coverity + run: ${COV_CONFIGURE_PATH} --msvc + + - name: Build with cov-build + run: | + ${COV_BUILD_PATH} --dir cov-int cmake --build build/ + 7z a boost-wintls.zip cov-int + + - name: Upload to coverity-scan + run: | + curl --form token=$TOKEN \ + --form email=laudrup@stacktrace.dk \ + --form file=@boost-wintls.zip \ + --form version=$GITHUB_SHA \ + --form description=$(git log -1 --pretty=format:"%s") \ + https://scan.coverity.com/builds?project=laudrup%2Fboost-wintls + env: + TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} diff --git a/third-party/boost-wintls/.github/workflows/release.yml b/third-party/boost-wintls/.github/workflows/release.yml new file mode 100644 index 00000000000..f4f979bb117 --- /dev/null +++ b/third-party/boost-wintls/.github/workflows/release.yml @@ -0,0 +1,44 @@ +--- +name: release + +on: + push: + tags: + - "v*" + +jobs: + release: + runs-on: ubuntu-latest + name: Generate and publish release and documentation + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Install APT packages + env: + DEBIAN_FRONTEND: noninteractive + run: sudo apt-get -yq install doxygen libboost-dev libssl-dev python3-pip + - name: Install PIP packages + # TODO: Consider using requirements.txt to ensure specific versions are used + run: sudo pip3 install sphinx breathe sphinx_bootstrap_theme + - name: Configure build system + run: mkdir build && cmake -Bbuild -H. + - name: Build documentation + run: cmake --build build/ --target doc + - name: Copy HTML documentation to source package + run: cp -r build/doc/html doc + - name: Create release package + run: cmake --build build/ --target package_source + - name: Create release + uses: "marvinpinto/action-automatic-releases@latest" + with: + repo_token: "${{ secrets.GITHUB_TOKEN }}" + prerelease: false + files: build/boost-wintls-*.zip + - name: Disable Jekyll templating + run: touch build/doc/html/.nojekyll + - name: Deploy documentation + uses: JamesIves/github-pages-deploy-action@v4 + with: + folder: build/doc/html diff --git a/third-party/boost-wintls/.github/workflows/unittest.yml b/third-party/boost-wintls/.github/workflows/unittest.yml new file mode 100644 index 00000000000..029d43a159b --- /dev/null +++ b/third-party/boost-wintls/.github/workflows/unittest.yml @@ -0,0 +1,150 @@ +--- +name: unittest +on: [push, pull_request] + +jobs: + unittest: + name: "${{matrix.generator}} ${{matrix.toolset}} Boost ${{matrix.boost_version}} ${{matrix.build_type}} ${{matrix.name_args}}" + runs-on: ${{matrix.os}} + defaults: + run: + shell: bash + strategy: + fail-fast: false + matrix: + boost_version: ["1.75.0", "1.76.0", "1.77.0", "1.78.0", "1.79.0", "1.80.0", "1.81.0", "1.82.0", "1.83.0"] + os: [windows-2019, windows-2022] + toolset: [v141, v142, v143, ClangCL] + build_type: [Debug, Release] + generator: ["Visual Studio 16 2019", "Visual Studio 17 2022"] + config_args: [""] + build_args: [""] + name_args: [""] + exclude: + - { os: windows-2019, toolset: v143 } + - { os: windows-2022, toolset: v141 } + - { os: windows-2019, generator: "Visual Studio 17 2022" } + - { os: windows-2022, generator: "Visual Studio 16 2019" } + - { toolset: ClangCL, build_type: Release } + # The following combinations are not available through install-boost + - { boost_version: "1.75.0", toolset: v143 } + - { boost_version: "1.76.0", toolset: v143 } + - { boost_version: "1.77.0", toolset: v143 } + - { boost_version: "1.78.0", toolset: v141 } + - { boost_version: "1.79.0", toolset: v141 } + - { boost_version: "1.80.0", toolset: v141 } + - { boost_version: "1.81.0", toolset: v141 } + - { boost_version: "1.82.0", toolset: v141 } + - { boost_version: "1.83.0", toolset: v141 } + include: + - boost_version: "1.83.0" + os: windows-2022 + toolset: v143 + build_type: Debug + generator: "Visual Studio 17 2022" + config_args: "" + build_args: "-- -p:CharacterSet=Unicode" + name_args: "Unicode" + - boost_version: "1.83.0" + os: windows-2022 + toolset: v143 + build_type: Debug + generator: "Visual Studio 17 2022" + config_args: "-A Win32 -DENABLE_TESTING:BOOL=OFF" + name_args: "32 bit" + - boost_version: "1.83.0" + os: windows-2022 + toolset: "" + build_type: "" + generator: "MinGW Makefiles" + config_args: "" + name_args: "" + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Add boost toolset to environment + if: contains(fromJson('["1.78.0", "1.79.0", "1.80.0", "1.81.0", "1.82.0", "1.83.0"]'), matrix.boost_version) + run: echo BOOST_TOOLSET=$([[ "${{matrix.generator}}" == "MinGW Makefiles" ]] && echo "mingw" || echo "msvc") >> $GITHUB_ENV + + # The platform_version passed to boost-install determines the msvc toolset version for which static libs are installed. + - name: Add boost platform version to environment + run: | + declare -A toolset_to_platform_version=( [mingw]="2019" [v141]="2016" [v142]="2019" [v143]="2022" [ClangCL]="2019" ) + key=$([[ "${{matrix.generator}}" == "MinGW Makefiles" ]] && echo "mingw" || echo "${{matrix.toolset}}") + echo BOOST_PLATFORM_VERSION="${toolset_to_platform_version[$key]}" >> $GITHUB_ENV + + # install-boost does not provide pre-built clang binaries, hence tell cmake/FindBoost that we want to use vc142 binaries. + - name: Add boost compiler arg to environment + if: matrix.toolset == 'ClangCL' + run: echo BOOST_COMPILER_ARG="-DBoost_COMPILER=-vc142" >> $GITHUB_ENV + + - name: Add boost install path to environment + run: echo BOOST_INSTALL_PATH="${GITHUB_WORKSPACE}/boost-${{matrix.boost_version}}${BOOST_TOOLSET}${BOOST_PLATFORM_VERSION}" >> $GITHUB_ENV + + - name: Add build type configuration to environment + if: matrix.generator != 'MinGW Makefiles' + run: echo BUILD_CONFIG_ARG="--config ${{matrix.build_type}}" >> $GITHUB_ENV + + - name: Add test type configuration to environment + if: matrix.generator != 'MinGW Makefiles' + run: echo TEST_CONFIG_ARG="-C ${{matrix.build_type}}" >> $GITHUB_ENV + + - name: Cache Boost installation + id: cache-boost + uses: actions/cache@v3 + with: + path: ${{env.BOOST_INSTALL_PATH}} + key: ${{matrix.boost_version}}${{env.BOOST_TOOLSET}}${{env.BOOST_PLATFORM_VERSION}} + + - name: Install Boost + if: steps.cache-boost.outputs.cache-hit != 'true' + uses: MarkusJx/install-boost@v2.4.4 + with: + boost_version: ${{matrix.boost_version}} + toolset: ${{env.BOOST_TOOLSET}} + boost_install_dir: ${{env.BOOST_INSTALL_PATH}} + platform_version: ${{env.BOOST_PLATFORM_VERSION}} + arch: null + + - name: Increase size of pagefile + if: matrix.generator == 'MinGW Makefiles' + uses: al-cheb/configure-pagefile-action@v1.2 + with: + minimum-size: 16GB + maximum-size: 16GB + disk-root: "C:" + + - name: Install packages + run: choco install openssl + + - name: Create build directory + run: mkdir build + + - name: Configure + working-directory: build + run: | + cmake -T "${{matrix.toolset}}" \ + -G "${{matrix.generator}}" \ + ${{matrix.config_args}} \ + ${BOOST_COMPILER_ARG} \ + "${GITHUB_WORKSPACE}" + env: + BOOST_ROOT: ${{env.BOOST_INSTALL_PATH}}/boost + + - name: Build + working-directory: build + run: | + cmake --build . \ + -j \ + ${BUILD_CONFIG_ARG} \ + ${{matrix.build_args}} + + - name: Run tests + working-directory: build + run: ctest ${TEST_CONFIG_ARG} -V + env: + CTEST_OUTPUT_ON_FAILURE: True diff --git a/third-party/boost-wintls/.gitignore b/third-party/boost-wintls/.gitignore new file mode 100644 index 00000000000..17b25b4b363 --- /dev/null +++ b/third-party/boost-wintls/.gitignore @@ -0,0 +1,9 @@ +__pycache__ +/out/build + +# Visual Studio Code generated files +.vscode + +# Visual Studio generated files +/.vs +/CMakeSettings.json diff --git a/third-party/boost-wintls/CMakeLists.txt b/third-party/boost-wintls/CMakeLists.txt new file mode 100644 index 00000000000..0b66f596bff --- /dev/null +++ b/third-party/boost-wintls/CMakeLists.txt @@ -0,0 +1,166 @@ +cmake_minimum_required(VERSION 3.15) + +set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) + +include(VersionFromGit) + +version_from_git() + +project(boost-wintls + VERSION ${VERSION} + DESCRIPTION "Native Windows TLS stream for Boost.Asio" + HOMEPAGE_URL "https://wintls.dev/" + LANGUAGES CXX +) + +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + message(STATUS "Building for 64 bit platform") +elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) + message(STATUS "Building for 32 bit platform") +endif() + +option(ENABLE_TESTING "Enable Test Builds" ${WIN32}) +option(ENABLE_EXAMPLES "Enable Examples Builds" ${WIN32}) +option(ENABLE_DOCUMENTATION "Enable Documentation Builds" ${UNIX}) +option(ENABLE_ADDRESS_SANITIZER "Enable Address Sanitizer" OFF) +option(WARNINGS_AS_ERRORS "Treat compiler warnings as errors" ON) + +add_library(${PROJECT_NAME} INTERFACE) + +target_include_directories(${PROJECT_NAME} + INTERFACE + $ + $ +) + +target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_14) + +if(WIN32) + set(Boost_USE_STATIC_LIBS ON) + set(Boost_USE_MULTITHREADED ON) + set(Boost_USE_STATIC_RUNTIME OFF) + + target_compile_definitions(${PROJECT_NAME} INTERFACE + BOOST_ALL_NO_LIB # Disable auto linking boost libraries + _CRT_SECURE_NO_WARNINGS # Ignore silly warnings on not using MS specific "secure" C functions + _WIN32_WINNT=0x0601 # Target Windows 7 + ) + + # Based on https://github.com/lefticus/cpp_starter_project + set(MSVC_WARNINGS + /W4 # Baseline reasonable warnings + /w14254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data + /w14263 # 'function': member function does not override any base class virtual member function + /w14287 # 'operator': unsigned/negative constant mismatch + /we4289 # nonstandard extension used: 'variable': loop control variable declared in the for-loop is used outside the for-loop scope + /w14296 # 'operator': expression is always 'boolean_value' + /w14311 # 'variable': pointer truncation from 'type1' to 'type2' + /w14545 # expression before comma evaluates to a function which is missing an argument list + /w14546 # function call before comma missing argument list + /w14547 # 'operator': operator before comma has no effect; expected operator with side-effect + /w14549 # 'operator': operator before comma has no effect; did you intend 'operator'? + /w14555 # expression has no effect; expected expression with side- effect + /w14640 # Enable warning on thread un-safe static member initialization + /w14826 # Conversion from 'type1' to 'type_2' is sign-extended. This may cause unexpected runtime behavior. + /w14905 # wide string literal cast to 'LPSTR' + /w14906 # string literal cast to 'LPWSTR' + /w14928 # illegal copy-initialization; more than one user-defined conversion has been implicitly applied + /w15038 # data member 'member1' will be initialized after data member 'member2' + /w14062 # enumerator 'identifier' in switch of enum 'enumeration' is not handled + /permissive- # standards conformance mode for MSVC compiler. + ) + + if(WARNINGS_AS_ERRORS) + set(CLANG_WARNINGS ${CLANG_WARNINGS} -Werror) + set(MSVC_WARNINGS ${MSVC_WARNINGS} /WX) + endif() + + set(CLANG_WARNINGS + -Wall + -Wextra # reasonable and standard + -Wshadow # warn the user if a variable declaration shadows one from a parent context + -Wnon-virtual-dtor # warn the user if a class with virtual functions has a non-virtual destructor. This helps catch hard to track down memory errors + -Wold-style-cast # warn for c-style casts + -Wcast-align # warn for potential performance problem casts + -Wunused # warn on anything being unused + -Woverloaded-virtual # warn if you overload (not override) a virtual function + -Wpedantic # warn if non-standard C++ is used + -Wconversion # warn on type conversions that may lose data + -Wsign-conversion # warn on sign conversions + -Wnull-dereference # warn if a null dereference is detected + -Wdouble-promotion # warn if float is implicit promoted to double + -Wformat=2 # warn on security issues around functions that format output (ie printf) + -Wimplicit-fallthrough # warn on statements that fallthrough without an explicit annotation + ) + + set(GCC_WARNINGS + ${CLANG_WARNINGS} + -Wmisleading-indentation # warn if indentation implies blocks where blocks do not exist + -Wduplicated-cond # warn if if / else chain has duplicated conditions + -Wduplicated-branches # warn if if / else branches have duplicated code + -Wlogical-op # warn about logical operations being used where bitwise were probably wanted + -Wuseless-cast # warn if you perform a cast to the same type + ) + + if(MSVC) + set(PROJECT_WARNINGS ${MSVC_WARNINGS}) + elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") + set(PROJECT_WARNINGS ${CLANG_WARNINGS}) + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(PROJECT_WARNINGS ${GCC_WARNINGS}) + else() + message(AUTHOR_WARNING "No compiler warnings set for '${CMAKE_CXX_COMPILER_ID}' compiler.") + endif() + + target_compile_options(${PROJECT_NAME} INTERFACE ${PROJECT_WARNINGS}) + + # Generate .pdb files with debug info for release builds + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi") + set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG /OPT:REF /OPT:ICF") +endif() + +find_package(Boost REQUIRED) + +target_link_libraries(${PROJECT_NAME} INTERFACE + Boost::headers +) + +if(MINGW) + target_link_libraries(${PROJECT_NAME} INTERFACE + crypt32 + secur32 + ws2_32 + wsock32 + ) +endif() + +if(ENABLE_ADDRESS_SANITIZER) + message(STATUS "Enabling Address Sanitizer.") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /fsanitize=address") + set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /incremental:no") +endif() + +if(ENABLE_TESTING) + enable_testing() + message(STATUS "Building Tests.") + add_subdirectory(test) +endif() + +if(ENABLE_EXAMPLES) + message(STATUS "Building Examples.") + add_subdirectory(examples) +endif() + +if(ENABLE_DOCUMENTATION) + message(STATUS "Building Documentation.") + add_subdirectory(doc) +endif() +set(CPACK_SOURCE_GENERATOR ZIP) +set(CPACK_SOURCE_PACKAGE_FILE_NAME ${PROJECT_NAME}-${PROJECT_VERSION}) +set(CPACK_SOURCE_IGNORE_FILES + "/\\\\..*$" + "build" + "__pycache__" +) +include(CPack) +include(ClangFormat) diff --git a/third-party/boost-wintls/LICENSE b/third-party/boost-wintls/LICENSE new file mode 100644 index 00000000000..36b7cd93cdf --- /dev/null +++ b/third-party/boost-wintls/LICENSE @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/third-party/boost-wintls/README.md b/third-party/boost-wintls/README.md new file mode 100644 index 00000000000..8c0519da2ba --- /dev/null +++ b/third-party/boost-wintls/README.md @@ -0,0 +1,136 @@ +Boost.Wintls Logo + +# Native Windows TLS stream for Boost.Asio + + + Support Ukraine + + +[wintls.dev](https://wintls.dev/) + +Build | Coverage | Coverity Analysis | +------|----------|-------------------| +[![Build status](https://github.com/laudrup/boost-wintls/workflows/build/badge.svg?branch=master)](https://github.com/laudrup/boost-wintls/actions) | [![Codecov](https://codecov.io/gh/laudrup/boost-wintls/branch/master/graph/badge.svg)](https://codecov.io/gh/laudrup/boost-wintls) | [![Coverity Scan Build Status](https://scan.coverity.com/projects/23473/badge.svg)](https://scan.coverity.com/projects/laudrup-boost-wintls) | + +## Contents + +- [Introduction](#introduction) +- [Requirements](#requirements) +- [Building](#building) +- [Quickstart](#quickstart) +- [Documentation](#documentation) +- [Contributing](#contributing) +- [Thanks](#thanks) + +## Introduction + +Implements a TLS stream wrapper for use with +[Boost.Asio](https://www.boost.org/doc/libs/release/doc/html/boost_asio.html) +similar to +[Boost.Asio.SSL](https://www.boost.org/doc/libs/release/doc/html/boost_asio/overview/ssl.html) +but using native Windows API +([SSPI/Schannel](https://docs.microsoft.com/en-us/windows-server/security/tls/tls-ssl-schannel-ssp-overview)) +functionality instead of OpenSSL for providing TLS encrypted stream functionality. + +## Requirements + +As this library uses Windows specific libraries, it is only supported +on Microsoft Windows although it is intended to be used alongside the +existing Boost.Asio.SSL implementation. + +[Boost](https://www.boost.org) is required. Currently tested with +Boost 1.75 to 1.83 but most newer versions ought to work. + +A working C++ compiler supporting the C++14 standard is required. +Currently tested compilers are: + +- MSVC for Visual Studio 2022 +- MSVC for Visual Studio 2019 +- Clang +- MinGW64 (GCC) + +Only 64 bit builds have been tested. + +## Building + +Boost.Wintls is header-only. To use it just add the necessary `#include` line +to your source files, like this: +```C++ +#include +``` + +CMake may be used to generate a Visual Studio solution for building +the tests and examples, e.g.: + +``` +mkdir build +cd build +cmake .. +cmake --build . +``` + +If the provided CMake scripts are not used and you are using the +MinGW64 compiler the `crypt32`, `secur32`, `ws2_32` and `wsock32` +libraries needs to be linked with your libraries/executables. + + +## Quickstart + +Similar to Boost.Asio.SSL a +[boost::wintls::context](https://laudrup.github.io/boost-wintls/classes.html#context) +is required to hold certificates and options to use for the TLS +stream: + +```C++ + // Set up context to use the systems default TLS methods (e.g. TLS 1.2) + boost::wintls::context ctx{boost::wintls::method::system_default}; +``` + +Using that context a +[boost::wintls::stream](https://laudrup.github.io/boost-wintls/classes.html#stream) +can be constructed using a +[boost::asio::io_context](https://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/io_context.html) +specifying the underlying stream type (most often a TCP stream): + +```C++ + boost::asio::io_context ioc; + + boost::wintls::stream stream(ioc, ctx); +``` + +Although that is all that is required to construct a stream that fully +supports the standard [boost::asio](https://www.boost.org/doc/libs/release/doc/html/boost_asio.html) stream operations like +[write](https://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/write.html) +or +[async_read](https://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/async_read.html) +the underlying stream probably needs to be connected, a handshake has +to be performed and most likely, certificates and keys has to be +handled as well. + +For details on how to do that, please see the +[documentation](https://laudrup.github.io/boost-wintls) and the +[examples](https://laudrup.github.io/boost-wintls/examples.html) + +## Documentation + +Documentation is available [here](https://laudrup.github.io/boost-wintls). + +## Contributing + +Pull requests, issue reporting etc. are very much welcome. + +If you use this library and find it useful, I would love to know. You should also consider donating to one of the funds that help victims of the war in Ukraine: + +[https://www.stopputin.net/](https://www.stopputin.net/) + + +## Thanks + +* [Vinnie Falco](https://github.com/vinniefalco) + For encouraging me to write this library in the first place as well as code reviews and other useful input. +* [Richard Hodges](https://github.com/madmongo1) + For code reviews and other useful input. +* [Damian Jarek](https://github.com/djarek) + For code reviews and other useful input. +* [Marcelo Zimbres](https://github.com/mzimbres) + For coming up with the short and descriptive name for this library diff --git a/third-party/boost-wintls/cmake/ClangFormat.cmake b/third-party/boost-wintls/cmake/ClangFormat.cmake new file mode 100644 index 00000000000..f978a207944 --- /dev/null +++ b/third-party/boost-wintls/cmake/ClangFormat.cmake @@ -0,0 +1,14 @@ +file(GLOB_RECURSE ALL_SOURCE_FILES *.cpp *.hpp) +foreach (SOURCE_FILE ${ALL_SOURCE_FILES}) + string(FIND ${SOURCE_FILE} ${PROJECT_BINARY_DIR} PROJECT_BINARY_DIR_FOUND) + if (NOT ${PROJECT_BINARY_DIR_FOUND} EQUAL -1) + list(REMOVE_ITEM ALL_SOURCE_FILES ${SOURCE_FILE}) + endif () +endforeach () + +add_custom_target( + clangformat + COMMAND clang-format + -i + ${ALL_SOURCE_FILES} +) diff --git a/third-party/boost-wintls/cmake/FindSphinx.cmake b/third-party/boost-wintls/cmake/FindSphinx.cmake new file mode 100644 index 00000000000..5c2309e9ed1 --- /dev/null +++ b/third-party/boost-wintls/cmake/FindSphinx.cmake @@ -0,0 +1,9 @@ +find_program(SPHINX_EXECUTABLE + NAMES sphinx-build + DOC "Path to sphinx-build executable") + +include(FindPackageHandleStandardArgs) + +find_package_handle_standard_args(Sphinx + "Failed to find sphinx-build executable" + SPHINX_EXECUTABLE) diff --git a/third-party/boost-wintls/cmake/VersionFromGit.cmake b/third-party/boost-wintls/cmake/VersionFromGit.cmake new file mode 100644 index 00000000000..15ab0d20f56 --- /dev/null +++ b/third-party/boost-wintls/cmake/VersionFromGit.cmake @@ -0,0 +1,167 @@ +# The MIT License (MIT) +# +# Copyright (c) 2016-2017 Theo Willows +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +cmake_minimum_required( VERSION 3.0.0 ) + +include( CMakeParseArguments ) + +function( version_from_git ) + # Parse arguments + set( options OPTIONAL FAST ) + set( oneValueArgs + GIT_EXECUTABLE + INCLUDE_HASH + LOG + TIMESTAMP + ) + set( multiValueArgs ) + cmake_parse_arguments( ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) + + # Defaults + if( NOT DEFINED ARG_INCLUDE_HASH ) + set( ARG_INCLUDE_HASH ON ) + endif() + + if( DEFINED ARG_GIT_EXECUTABLE ) + set( GIT_EXECUTABLE "${ARG_GIT_EXECUTABLE}" ) + else () + # Find Git or bail out + find_package( Git ) + if( NOT GIT_FOUND ) + message( FATAL_ERROR "[MunkeiVersionFromGit] Git not found" ) + endif( NOT GIT_FOUND ) + endif() + + # Git describe + execute_process( + COMMAND "${GIT_EXECUTABLE}" describe --tags + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE git_result + OUTPUT_VARIABLE git_describe + ERROR_VARIABLE git_error + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_STRIP_TRAILING_WHITESPACE + ) + if( NOT git_result EQUAL 0 ) + message( FATAL_ERROR + "[MunkeiVersionFromGit] Failed to execute Git: ${git_error}" + ) + endif() + + # Get Git tag + execute_process( + COMMAND "${GIT_EXECUTABLE}" describe --tags --abbrev=0 + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE git_result + OUTPUT_VARIABLE git_tag + ERROR_VARIABLE git_error + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_STRIP_TRAILING_WHITESPACE + ) + if( NOT git_result EQUAL 0 ) + message( FATAL_ERROR + "[MunkeiVersionFromGit] Failed to execute Git: ${git_error}" + ) + endif() + + if( git_tag MATCHES "^v(0|[1-9][0-9]*)[.](0|[1-9][0-9]*)[.](0|[1-9][0-9]*)(-[.0-9A-Za-z-]+)?([+][.0-9A-Za-z-]+)?$" ) + set( version_major "${CMAKE_MATCH_1}" ) + set( version_minor "${CMAKE_MATCH_2}" ) + set( version_patch "${CMAKE_MATCH_3}" ) + set( identifiers "${CMAKE_MATCH_4}" ) + set( metadata "${CMAKE_MATCH_5}" ) + else() + message( FATAL_ERROR + "[MunkeiVersionFromGit] Git tag isn't valid semantic version: [${git_tag}]" + ) + endif() + + if( "${git_tag}" STREQUAL "${git_describe}" ) + set( git_at_a_tag ON ) + endif() + + if( NOT git_at_a_tag ) + # Extract the Git hash (if one exists) + string( REGEX MATCH "g[0-9a-f]+$" git_hash "${git_describe}" ) + endif() + + # Construct the version variables + set( version ${version_major}.${version_minor}.${version_patch} ) + set( semver ${version} ) + + # Identifiers + if( identifiers MATCHES ".+" ) + string( SUBSTRING "${identifiers}" 1 -1 identifiers ) + set( semver "${semver}-${identifiers}") + endif() + + # Metadata + # TODO Split and join (add Git hash inbetween) + if( metadata MATCHES ".+" ) + string( SUBSTRING "${metadata}" 1 -1 metadata ) + # Split + string( REPLACE "." ";" metadata "${metadata}" ) + endif() + + if( NOT git_at_a_tag ) + + if( ARG_INCLUDE_HASH ) + list( APPEND metadata "${git_hash}" ) + endif( ARG_INCLUDE_HASH ) + + # Timestamp + if( DEFINED ARG_TIMESTAMP ) + string( TIMESTAMP timestamp "${ARG_TIMESTAMP}" ${ARG_UTC} ) + list( APPEND metadata "${timestamp}" ) + endif( DEFINED ARG_TIMESTAMP ) + + endif() + + # Join + string( REPLACE ";" "." metadata "${metadata}" ) + + if( metadata MATCHES ".+" ) + set( semver "${semver}+${metadata}") + endif() + + # Log the results + if( ARG_LOG ) + message( STATUS + "[MunkeiVersionFromGit] Version: ${version} + Git tag: [${git_tag}] + Git hash: [${git_hash}] + Decorated: [${git_describe}] + Identifiers: [${identifiers}] + Metadata: [${metadata}] + SemVer: [${semver}]" + ) + endif( ARG_LOG ) + + # Set parent scope variables + set( GIT_TAG ${git_tag} PARENT_SCOPE ) + set( SEMVER ${semver} PARENT_SCOPE ) + set( VERSION ${version} PARENT_SCOPE ) + set( VERSION_MAJOR ${version_major} PARENT_SCOPE ) + set( VERSION_MINOR ${version_minor} PARENT_SCOPE ) + set( VERSION_PATCH ${version_patch} PARENT_SCOPE ) + +endfunction( version_from_git ) diff --git a/third-party/boost-wintls/doc/API.rst b/third-party/boost-wintls/doc/API.rst new file mode 100644 index 00000000000..d23cc33719a --- /dev/null +++ b/third-party/boost-wintls/doc/API.rst @@ -0,0 +1,10 @@ +API +=== + +.. toctree:: + :maxdepth: 2 + + classes + enumerations + functions + type_aliases diff --git a/third-party/boost-wintls/doc/CMakeLists.txt b/third-party/boost-wintls/doc/CMakeLists.txt new file mode 100644 index 00000000000..2bc52290f57 --- /dev/null +++ b/third-party/boost-wintls/doc/CMakeLists.txt @@ -0,0 +1,69 @@ +find_package(Doxygen REQUIRED) +find_package(Sphinx REQUIRED) + +set(DOXYGEN_INPUT_DIR ${PROJECT_SOURCE_DIR}/include/boost/wintls/) +set(DOXYGEN_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/doxygen) +set(DOXYGEN_INDEX_FILE ${DOXYGEN_OUTPUT_DIR}/index.xml) +set(DOXYFILE_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in) +set(DOXYFILE_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) + +set(WINTLS_PUBLIC_HEADERS + ${DOXYGEN_INPUT_DIR}/certificate.hpp + ${DOXYGEN_INPUT_DIR}/context.hpp + ${DOXYGEN_INPUT_DIR}/file_format.hpp + ${DOXYGEN_INPUT_DIR}/handshake_type.hpp + ${DOXYGEN_INPUT_DIR}/method.hpp + ${DOXYGEN_INPUT_DIR}/stream.hpp +) + +string(REPLACE ";" " " DOXYGEN_INPUT_FILES "${WINTLS_PUBLIC_HEADERS}") + +configure_file(${DOXYFILE_IN} ${DOXYFILE_OUT} @ONLY) + +add_custom_command(OUTPUT ${DOXYGEN_INDEX_FILE} + DEPENDS ${WINTLS_PUBLIC_HEADERS} + COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE_OUT} + MAIN_DEPENDENCY ${DOXYFILE_OUT} ${DOXYFILE_IN} + COMMENT "Generating docs" + VERBATIM) + +add_custom_target(Doxygen ALL DEPENDS ${DOXYGEN_INDEX_FILE}) + +set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}) +set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR}/html) +set(SPHINX_INDEX_FILE ${SPHINX_BUILD}/index.html) +set(SPHINX_SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/API.rst + ${CMAKE_CURRENT_SOURCE_DIR}/async_https_client.rst + ${CMAKE_CURRENT_SOURCE_DIR}/classes.rst + ${CMAKE_CURRENT_SOURCE_DIR}/echo_client.rst + ${CMAKE_CURRENT_SOURCE_DIR}/echo_server.rst + ${CMAKE_CURRENT_SOURCE_DIR}/enumerations.rst + ${CMAKE_CURRENT_SOURCE_DIR}/examples.rst + ${CMAKE_CURRENT_SOURCE_DIR}/functions.rst + ${CMAKE_CURRENT_SOURCE_DIR}/https_client.rst + ${CMAKE_CURRENT_SOURCE_DIR}/index.rst + ${CMAKE_CURRENT_SOURCE_DIR}/type_aliases.rst + ${CMAKE_CURRENT_SOURCE_DIR}/usage.rst +) + +add_custom_command(OUTPUT ${SPHINX_INDEX_FILE} + COMMAND + ${SPHINX_EXECUTABLE} -b html + -D breathe_projects.boost-wintls=${DOXYGEN_OUTPUT_DIR} + -D version=${PROJECT_VERSION} + ${SPHINX_SOURCE} ${SPHINX_BUILD} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/static/boost-wintls.css + ${CMAKE_CURRENT_SOURCE_DIR}/templates/layout.html + ${CMAKE_CURRENT_SOURCE_DIR}/templates/navbar.html + ${CMAKE_CURRENT_SOURCE_DIR}/extensions/toctree_elements.py + ${CMAKE_CURRENT_SOURCE_DIR}/extensions/remove_inline_specifier.py + ${SPHINX_SOURCE_FILES} + ${DOXYGEN_INDEX_FILE} + MAIN_DEPENDENCY ${SPHINX_SOURCE}/conf.py + COMMENT "Generating documentation with Sphinx" +) + +add_custom_target(doc ALL DEPENDS ${SPHINX_INDEX_FILE}) diff --git a/third-party/boost-wintls/doc/Doxyfile.in b/third-party/boost-wintls/doc/Doxyfile.in new file mode 100644 index 00000000000..755e436afdf --- /dev/null +++ b/third-party/boost-wintls/doc/Doxyfile.in @@ -0,0 +1,16 @@ +INPUT = @DOXYGEN_INPUT_FILES@ +XML_OUTPUT = @DOXYGEN_OUTPUT_DIR@ +RECURSIVE = YES +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = "WindowsTLS" +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +QUIET = YES +JAVADOC_AUTOBRIEF = YES +AUTOLINK_SUPPORT = NO +GENERATE_HTML = NO +GENERATE_XML = YES +MACRO_EXPANSION = YES +EXTRACT_ALL = YES diff --git a/third-party/boost-wintls/doc/async_https_client.rst b/third-party/boost-wintls/doc/async_https_client.rst new file mode 100644 index 00000000000..ea0e8e839d6 --- /dev/null +++ b/third-party/boost-wintls/doc/async_https_client.rst @@ -0,0 +1,9 @@ +Asynchronous HTTPS Client +------------------------- +This example demonstrates a basic asynchronous HTTPS client using +`boost::beast`_. + +.. literalinclude:: ../examples/async_https_client.cpp + :lines: 7- + +.. _boost::beast: https://github.com/boostorg/beast diff --git a/third-party/boost-wintls/doc/classes.rst b/third-party/boost-wintls/doc/classes.rst new file mode 100644 index 00000000000..9fbef46ed03 --- /dev/null +++ b/third-party/boost-wintls/doc/classes.rst @@ -0,0 +1,12 @@ +Classes +======= + +context +------- +.. doxygenclass:: boost::wintls::context + :members: + +stream +------ +.. doxygenclass:: boost::wintls::stream + :members: diff --git a/third-party/boost-wintls/doc/conf.py b/third-party/boost-wintls/doc/conf.py new file mode 100644 index 00000000000..ccc7d83428d --- /dev/null +++ b/third-party/boost-wintls/doc/conf.py @@ -0,0 +1,43 @@ +import sphinx_bootstrap_theme +import os +import sys + +sys.path.append(os.path.abspath("./extensions")) + +project = 'boost-wintls' +copyright = '2021, Kasper Laudrup' +author = 'Kasper Laudrup' + +master_doc = 'index' + +extensions = ['sphinx.ext.autosectionlabel', + 'breathe', + 'toctree_elements', + 'remove_inline_specifier', + ] + +highlight_language = 'c++' + +primary_domain = 'cpp' + +templates_path = ['templates'] + +html_static_path = ['static'] + +html_title = 'boost.wintls' + +html_css_files = [ + project + '.css', +] + +html_theme = 'bootstrap' +html_theme_path = sphinx_bootstrap_theme.get_html_theme_path() + +html_theme_options = { + 'bootswatch_theme': 'flatly', + 'navbar_title': html_title +} + +html_last_updated_fmt = '' + +breathe_default_project = 'boost-wintls' diff --git a/third-party/boost-wintls/doc/echo_client.rst b/third-party/boost-wintls/doc/echo_client.rst new file mode 100644 index 00000000000..b8c21923482 --- /dev/null +++ b/third-party/boost-wintls/doc/echo_client.rst @@ -0,0 +1,6 @@ +Echo Client +----------- +This example demonstrates a basic asynchronous echo client + +.. literalinclude:: ../examples/echo_client.cpp + :lines: 7- diff --git a/third-party/boost-wintls/doc/echo_server.rst b/third-party/boost-wintls/doc/echo_server.rst new file mode 100644 index 00000000000..0036f524614 --- /dev/null +++ b/third-party/boost-wintls/doc/echo_server.rst @@ -0,0 +1,6 @@ +Echo Server +----------- +This example demonstrates a basic asynchronous echo server + +.. literalinclude:: ../examples/echo_server.cpp + :lines: 7- diff --git a/third-party/boost-wintls/doc/enumerations.rst b/third-party/boost-wintls/doc/enumerations.rst new file mode 100644 index 00000000000..57d97285492 --- /dev/null +++ b/third-party/boost-wintls/doc/enumerations.rst @@ -0,0 +1,14 @@ +Enumerations +============ + +handshake_type +-------------- +.. doxygenenum:: boost::wintls::handshake_type + +method +------ +.. doxygenenum:: boost::wintls::method + +file_format +----------- +.. doxygenenum:: boost::wintls::file_format diff --git a/third-party/boost-wintls/doc/examples.rst b/third-party/boost-wintls/doc/examples.rst new file mode 100644 index 00000000000..8a3ef206fa9 --- /dev/null +++ b/third-party/boost-wintls/doc/examples.rst @@ -0,0 +1,14 @@ +Examples +======== + +Full code to the examples can be found in the `examples`_ directory. + +.. toctree:: + :maxdepth: 2 + + https_client + async_https_client + echo_client + echo_server + +.. _examples: https://github.com/laudrup/boost-wintls/tree/master/examples diff --git a/third-party/boost-wintls/doc/extensions/remove_inline_specifier.py b/third-party/boost-wintls/doc/extensions/remove_inline_specifier.py new file mode 100644 index 00000000000..cefc2e7c11b --- /dev/null +++ b/third-party/boost-wintls/doc/extensions/remove_inline_specifier.py @@ -0,0 +1,8 @@ +def doctree_resolved(app, doctree, docname): + for node in doctree.traverse(): + if (node.astext() == 'inline' and node.parent.tagname == 'desc_signature_line'): + node.parent.remove(node) + + +def setup(app): + app.connect('doctree-resolved', doctree_resolved) diff --git a/third-party/boost-wintls/doc/extensions/toctree_elements.py b/third-party/boost-wintls/doc/extensions/toctree_elements.py new file mode 100644 index 00000000000..df3e24d7c11 --- /dev/null +++ b/third-party/boost-wintls/doc/extensions/toctree_elements.py @@ -0,0 +1,51 @@ +from sphinx import addnodes +import docutils.nodes + + +class ToctreeElement: + uri = "" + children = {} + + +def html_page_context(app, pagename, templatename, context, doctree): + if 'toctree' not in context: + return + + builder = app.builder + env = builder.env + doctree = env.get_doctree(env.config.master_doc) + + for node in doctree.traverse(addnodes.toctree): + toctreenode = node + break + + toctree = env.resolve_toctree(pagename, builder, toctreenode, + includehidden=True) + + toctree_elements = {} + for item in toctree.traverse(docutils.nodes.list_item): + if 'toctree-l1' in item['classes']: + element = ToctreeElement() + for ref in item.traverse(docutils.nodes.reference): + if ref['anchorname']: + continue + element.uri = ref["refuri"] + break + children = {} + for child in item.traverse(docutils.nodes.list_item, + include_self=False): + child_element = ToctreeElement() + for ref in child.traverse(docutils.nodes.reference): + if ref['anchorname']: + continue + child_element.link = ref["refuri"] + children[child[0].astext()] = child_element + break + element.children = children + toctree_elements[item[0].astext()] = element + + context['toctree_elements'] = toctree_elements + + +def setup(app): + app.connect('html-page-context', html_page_context) diff --git a/third-party/boost-wintls/doc/functions.rst b/third-party/boost-wintls/doc/functions.rst new file mode 100644 index 00000000000..cd2eb085264 --- /dev/null +++ b/third-party/boost-wintls/doc/functions.rst @@ -0,0 +1,23 @@ +Functions +========= + +x509_to_cert_context +-------------------- +.. doxygenfunction:: boost::wintls::x509_to_cert_context(const net::const_buffer &x509, file_format format) +.. doxygenfunction:: boost::wintls::x509_to_cert_context(const net::const_buffer &x509, file_format format, boost::system::error_code& ec) + +import_private_key +------------------ +.. doxygenfunction:: boost::wintls::import_private_key(const net::const_buffer& private_key, file_format format, const std::string& name) +.. doxygenfunction:: boost::wintls::import_private_key(const net::const_buffer& private_key, file_format format, const std::string& name, boost::system::error_code& ec) + +delete_private_key +------------------ +.. doxygenfunction:: delete_private_key(const std::string& name) +.. doxygenfunction:: delete_private_key(const std::string& name, boost::system::error_code& ec) + +assign_private_key +------------------ +.. doxygenfunction:: assign_private_key(const CERT_CONTEXT* cert, const std::string& name) +.. doxygenfunction:: assign_private_key(const CERT_CONTEXT* cert, const std::string& name, boost::system::error_code& ec) +.. _CERT_CONTEXT: https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cert_context diff --git a/third-party/boost-wintls/doc/https_client.rst b/third-party/boost-wintls/doc/https_client.rst new file mode 100644 index 00000000000..393a5ea5888 --- /dev/null +++ b/third-party/boost-wintls/doc/https_client.rst @@ -0,0 +1,9 @@ +HTTPS Client +------------ +This example demonstrates a basic synchronous HTTPS client using +`boost::beast`_. + +.. literalinclude:: ../examples/https_client.cpp + :lines: 7- + +.. _boost::beast: https://github.com/boostorg/beast diff --git a/third-party/boost-wintls/doc/index.rst b/third-party/boost-wintls/doc/index.rst new file mode 100644 index 00000000000..694e219904f --- /dev/null +++ b/third-party/boost-wintls/doc/index.rst @@ -0,0 +1,55 @@ +.. figure:: logo.jpg + :alt: Boost.Wintls logo + +Overview +======== + +This library implements TLS stream functionality for `boost::asio`_ +using native Windows `SSPI/Schannel`_ implementation. + +To the extend possible it provides the same functionality as the +`OpenSSL`_ implementation used by `boost::asio`_ and provides some +helper :ref:`functions` for converting and managing certificates and keys in +standard formats used by `OpenSSL`_. + +Released under the `Boost Software License`_. Source code available on `GitHub`_. + +Motivation +---------- + +`boost::asio`_ uses `OpenSSL`_ for TLS encryption which has a few +downsides when used on Windows: + +* Requires maintaining a separate copy of trusted certificate + authorities although the operating system already ships with and + maintains a store of trusted certificates. + +* When used as a server, `OpenSSL`_ requires access to the private key + as a file readable by the running process which could potentially + lead to security issues if measures are not taken to ensure the + private key is properly protected. + +* Installing third party libraries and software in general on Windows + is often a complicated process since no central packaging system + exists, so any security updates to `OpenSSL`_ would have to be + maintained by the software using the `boost::asio`_ library. + +This library avoids these issues by using the native Windows TLS +implementation (`SSPI/SChannel`_) which uses the methods for storing +certificates and keys provided by the Windows operating system itself. + +Contents +-------- +.. toctree:: + :maxdepth: 3 + + usage + examples + API + + +.. _SSPI/Schannel: https://docs.microsoft.com/en-us/windows-server/security/tls/tls-ssl-schannel-ssp-overview/ +.. _OpenSSL: https://www.openssl.org/ +.. _boost::asio: https://www.boost.org/doc/libs/release/doc/html/boost_asio.html +.. _Boost Software License: https://www.boost.org/LICENSE_1_0.txt +.. _GitHub: https://github.com/laudrup/boost-wintls diff --git a/third-party/boost-wintls/doc/logo.jpg b/third-party/boost-wintls/doc/logo.jpg new file mode 100644 index 00000000000..d07677e4e89 Binary files /dev/null and b/third-party/boost-wintls/doc/logo.jpg differ diff --git a/third-party/boost-wintls/doc/static/boost-wintls.css b/third-party/boost-wintls/doc/static/boost-wintls.css new file mode 100644 index 00000000000..45044d55051 --- /dev/null +++ b/third-party/boost-wintls/doc/static/boost-wintls.css @@ -0,0 +1,7 @@ +.dropdown-menu > li > a { + text-transform: none; +} + +.content { + max-width: 1000px !important; +} diff --git a/third-party/boost-wintls/doc/static/github.png b/third-party/boost-wintls/doc/static/github.png new file mode 100644 index 00000000000..c1529cadd7c Binary files /dev/null and b/third-party/boost-wintls/doc/static/github.png differ diff --git a/third-party/boost-wintls/doc/support-ukraine.png b/third-party/boost-wintls/doc/support-ukraine.png new file mode 100644 index 00000000000..5d8766b8324 Binary files /dev/null and b/third-party/boost-wintls/doc/support-ukraine.png differ diff --git a/third-party/boost-wintls/doc/templates/layout.html b/third-party/boost-wintls/doc/templates/layout.html new file mode 100644 index 00000000000..0e6460c5e29 --- /dev/null +++ b/third-party/boost-wintls/doc/templates/layout.html @@ -0,0 +1,16 @@ +{% extends '!layout.html' %} + +{% block footer %} + +{% endblock %} diff --git a/third-party/boost-wintls/doc/templates/navbar.html b/third-party/boost-wintls/doc/templates/navbar.html new file mode 100644 index 00000000000..fe4d0ca55de --- /dev/null +++ b/third-party/boost-wintls/doc/templates/navbar.html @@ -0,0 +1,38 @@ + diff --git a/third-party/boost-wintls/doc/type_aliases.rst b/third-party/boost-wintls/doc/type_aliases.rst new file mode 100644 index 00000000000..f920a365ede --- /dev/null +++ b/third-party/boost-wintls/doc/type_aliases.rst @@ -0,0 +1,8 @@ +Type aliases +============ + +cert_context_ptr +---------------- +.. doxygentypedef:: boost::wintls::cert_context_ptr + +.. _CERT_CONTEXT: https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cert_context diff --git a/third-party/boost-wintls/doc/usage.rst b/third-party/boost-wintls/doc/usage.rst new file mode 100644 index 00000000000..1b8c19caed2 --- /dev/null +++ b/third-party/boost-wintls/doc/usage.rst @@ -0,0 +1,114 @@ +.. cpp:namespace:: boost::wintls + +Usage +===== + +This library implements a stream similar to +`boost::asio::ssl::stream`_. Basic knowledge of `boost::asio`_ is +expected as this documentation mainly deals with the specifics of this +library. + +Setting up a context +-------------------- + +Client usage +~~~~~~~~~~~~ + +A :class:`context` is required for +holding certificates and for setting options like which TLS versions +to support. + +To construct a context using the operating system default methods: +:: + + #include + + boost::wintls::context ctx(boost::wintls::method::system_default); + +While that is all which is required to construct a context for +client-side operations, most users would at least want to enable +certificate validation with :func:`context::verify_server_certificate` +in addition to either using the standard operating system certificates +with :func:`context::use_default_certificates` or providing +certificates with :func:`context::add_certificate_authority`. + +For example, initializing a context which will use the certificates +provided by the operating system and verify the server certificate, +would look something like: +:: + + #include + + boost::wintls::context ctx(boost::wintls::method::system_default); + ctx.use_default_certificates(true); + ctx.verify_server_certificate(true); + + +Server usage +~~~~~~~~~~~~ + +When creating a context for server usage, a certificate is required as +well as private key. Unlike `OpenSSL`_ Windows has the concept of a +certificate with an associated private key that must be available to +the process or user running the server process. Such a certificate can +be used using :func:`context::use_certificate`. + +This library provides :ref:`functions` for helping interact +with standard key and certificate formats used by `OpenSSL`_ as +demonstrated in the :ref:`examples`. + +Initializing a stream +--------------------- + +Assuming an underlying TCP stream, once the context has been setup +a :class:`stream` can be constructed like: +:: + + boost::wintl::stream my_stream(my_io_service, ctx); + +In the case of a TCP stream, the underlying stream needs to be +connected before it can be used. To access the underlying stream use +the :func:`stream::next_layer` member function. + +Handshaking +----------- + +Before a TLS stream can be used, a handshake needs to be performed, +either as a server or a client. Similar to the rest of the +`boost::asio`_ functions both a synchronous and asynchronous version +exists. + +When performing a handshake as a client, it is often required to +include the hostname of the server in the handshake with +:func:`stream::set_server_hostname`. + +Performing a synchronous handshake as a client might look +like: +:: + + strean.set_server_hostname("wintls.dev"); + stream.handshake(boost::wintls::handshake_type::client); + +Similar to the `boost::asio`_ functions, this library provides +overloads for accepting a `boost::system`_::error_codes. + +Using the stream +---------------- + +Once the stream has been constructed and a successful handshake has +been done it can be used with all the usual operations provided by the +`boost::asio`_ library. + +Most users would probably not use the member functions on the stream +like :func:`stream::read_some` directly but instead use `boost::asio`_ +functions like `boost::asio::write`_ or `boost::asio::async_read_until`_. + +Please see the :ref:`examples` for full examples on how this +library can be used. + +.. _OpenSSL: https://www.openssl.org/ +.. _boost::asio: https://www.boost.org/doc/libs/release/doc/html/boost_asio.html +.. _boost::asio::ssl::stream: https://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/ssl__stream.html +.. _boost::system: https://www.boost.org/doc/libs/release/libs/system/doc/html/system.html +.. _boost::asio::write: https://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/write.html +.. _boost::asio::async_read_until: https://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/async_read_until.html diff --git a/third-party/boost-wintls/examples/CMakeLists.txt b/third-party/boost-wintls/examples/CMakeLists.txt new file mode 100644 index 00000000000..afa6cb9e2ef --- /dev/null +++ b/third-party/boost-wintls/examples/CMakeLists.txt @@ -0,0 +1,38 @@ +add_executable(https_client https_client.cpp) +add_executable(async_https_client async_https_client.cpp) +add_executable(echo_client echo_client.cpp) +add_executable(echo_server echo_server.cpp) + +target_link_libraries(https_client PRIVATE + boost-wintls +) + +target_link_libraries(async_https_client PRIVATE + boost-wintls +) + +target_link_libraries(echo_server PRIVATE + boost-wintls +) + +target_link_libraries(echo_client PRIVATE + boost-wintls +) + +if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + # Temporary workaround issue https://github.com/boostorg/beast/issues/1582 + target_compile_options(https_client PRIVATE "-wd4702") + target_compile_options(async_https_client PRIVATE "-wd4702") +endif() + +if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + target_compile_options(echo_client PRIVATE -Wno-unused-private-field) + target_compile_options(echo_server PRIVATE -Wno-unused-private-field) + target_compile_options(https_client PRIVATE -Wno-unused-private-field) + target_compile_options(async_https_client PRIVATE -Wno-unused-private-field) +endif() + +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + # Work around string table overflow by enabling optimizations + target_compile_options(async_https_client PRIVATE -Os) +endif() diff --git a/third-party/boost-wintls/examples/async_https_client.cpp b/third-party/boost-wintls/examples/async_https_client.cpp new file mode 100644 index 00000000000..b203c36e5ad --- /dev/null +++ b/third-party/boost-wintls/examples/async_https_client.cpp @@ -0,0 +1,190 @@ +// +// Copyright (c) 2020 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +namespace beast = boost::beast; // from +namespace http = beast::http; // from +namespace net = boost::asio; // from +namespace ssl = boost::wintls; // from + +using tcp = boost::asio::ip::tcp; // from + +//------------------------------------------------------------------------------ + +// Report a failure +void fail(beast::error_code ec, char const* what) { + std::cerr << what << ": " << ec.message() << "\n"; +} + +// Performs an HTTP GET and prints the response +class session : public std::enable_shared_from_this { + tcp::resolver resolver_; + ssl::stream stream_; + beast::flat_buffer buffer_; // (Must persist between reads) + http::request req_; + http::response res_; + +public: + explicit session(net::io_context& ioc, ssl::context& ctx) + : resolver_(net::make_strand(ioc)) + , stream_(net::make_strand(ioc), ctx) { + } + + // Start the asynchronous operation + void run(const std::string& host, const std::string& port, const std::string& path, unsigned version) { + // Set SNI hostname (many hosts need this to handshake successfully) + stream_.set_server_hostname(host); + + // Enable Check whether the Server Certificate was revoked + stream_.set_certificate_revocation_check(true); + + // Set up an HTTP GET request message + req_.version(version); + req_.method(http::verb::get); + req_.target(path); + req_.set(http::field::host, host); + req_.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); + + // Look up the domain name + resolver_.async_resolve(host, port, beast::bind_front_handler(&session::on_resolve, shared_from_this())); + } + + void on_resolve(beast::error_code ec, tcp::resolver::results_type results) { + if (ec) + return fail(ec, "resolve"); + + // Set a timeout on the operation + beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30)); + + // Make the connection on the IP address we get from a lookup + beast::get_lowest_layer(stream_).async_connect(results, beast::bind_front_handler(&session::on_connect, shared_from_this())); + } + + void on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type) { + if (ec) + return fail(ec, "connect"); + + // Perform the SSL handshake + stream_.async_handshake(boost::wintls::handshake_type::client, beast::bind_front_handler(&session::on_handshake, shared_from_this())); + } + + void on_handshake(beast::error_code ec) { + if (ec) + return fail(ec, "handshake"); + + // Set a timeout on the operation + beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30)); + + // Send the HTTP request to the remote host + http::async_write(stream_, req_, beast::bind_front_handler(&session::on_write, shared_from_this())); + } + + void on_write(beast::error_code ec, std::size_t bytes_transferred) { + boost::ignore_unused(bytes_transferred); + + if (ec) + return fail(ec, "write"); + + // Receive the HTTP response + http::async_read(stream_, buffer_, res_, beast::bind_front_handler(&session::on_read, shared_from_this())); + } + + void on_read(beast::error_code ec, std::size_t bytes_transferred) { + boost::ignore_unused(bytes_transferred); + + if (ec) + return fail(ec, "read"); + + // Write the message to standard out + std::cout << res_ << std::endl; + + // Set a timeout on the operation + beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30)); + + // Gracefully close the stream + stream_.async_shutdown(beast::bind_front_handler(&session::on_shutdown, shared_from_this())); + } + + void on_shutdown(beast::error_code ec) { + if (ec == net::error::eof) { + // Rationale: + // http://stackoverflow.com/questions/25587403/boost-asio-ssl-async-shutdown-always-finishes-with-an-error + ec = {}; + } + if (ec) + return fail(ec, "shutdown"); + + // If we get here then the connection is closed gracefully + } +}; + +//------------------------------------------------------------------------------ + +int main(int argc, char** argv) { + // Exactly one command line argument required - the HTTPS URL + if(argc != 2) { + std::cerr << "Usage: " << argv[0] << " [HTTPS_URL]\n\n"; + std::cerr << "Example: " << argv[0] << " https://www.boost.org/LICENSE_1_0.txt\n"; + return EXIT_FAILURE; + } + + const std::string url{argv[1]}; + + // Very basic URL matching. Not a full URL validator. + std::regex re("https://([^/$:]+):?([^/$]*)(/?.*)"); + std::smatch what; + if(!regex_match(url, what, re)) { + std::cerr << "Invalid or unsupported URL: " << url << "\n"; + return EXIT_FAILURE; + } + + // Get the relevant parts of the URL + const std::string host = std::string(what[1]); + // Use default HTTPS port (443) if not specified + const std::string port = what[2].length() > 0 ? what[2].str() : "443"; + // Use default path ('/') if not specified + const std::string path = what[3].length() > 0 ? what[3].str() : "/"; + + // Use HTTP/1.1 + const unsigned version = 11; + + // The io_context is required for all I/O + net::io_context ioc; + + // The SSL context is required, and holds certificates + ssl::context ctx{boost::wintls::method::system_default}; + + // Use the operating systems default certificates for verification + ctx.use_default_certificates(true); + + // Verify the remote server's certificate + ctx.verify_server_certificate(true); + + // Launch the asynchronous operation + // The session is constructed with a strand to + // ensure that handlers do not execute concurrently. + std::make_shared(ioc, ctx)->run(host, port, path, version); + + // Run the I/O service. The call will return when + // the get operation is complete. + ioc.run(); + + return EXIT_SUCCESS; +} diff --git a/third-party/boost-wintls/examples/certificate.hpp b/third-party/boost-wintls/examples/certificate.hpp new file mode 100644 index 00000000000..430e0a4e7f3 --- /dev/null +++ b/third-party/boost-wintls/examples/certificate.hpp @@ -0,0 +1,66 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include + +#ifndef BOOST_WINTLS_EXAMPLES_CERTIFICATE_HPP +#define BOOST_WINTLS_EXAMPLES_CERTIFICATE_HPP + +const std::string x509_certificate = + "-----BEGIN CERTIFICATE-----\n" + "MIIDdzCCAl+gAwIBAgIUSZTPaL6edK/wEZNYf/9Scqlxx+0wDQYJKoZIhvcNAQEL\n" + "BQAwSzELMAkGA1UEBhMCREsxEzARBgNVBAcMCkNvcGVuaGFnZW4xEzARBgNVBAoM\n" + "ClJlcHRpbGljdXMxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xOTA2MDEyMDMyMzRa\n" + "Fw0zOTA2MDEyMDMyMzRaMEsxCzAJBgNVBAYTAkRLMRMwEQYDVQQHDApDb3Blbmhh\n" + "Z2VuMRMwEQYDVQQKDApSZXB0aWxpY3VzMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEi\n" + "MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDasWBBpRZTezyOv+8l2db1BOUH\n" + "D2T4s6MlFoq+Vh6K37XgCGmDjXQP/GaDBxdCuC4HoL0ABXR9/upYPdQzSkniPelC\n" + "3si8S7USA3uEYAvhnprVoAWqZebN0ljgic7kiCJsBLSBjshzVFGga7MygBLA1ozx\n" + "sVLSz4FPH/lcKUmjsZPkhBeEY9ENuyk7JX3bLtAHQy2mLhkTse5LFv+ZE+RyaX2l\n" + "PliDKrScanfXItpbVlJPFVYkRs1l/dA3KJsETzLvYrAseguT0GKU7ticVW+mvhjL\n" + "Q8rNt95xMgo/hy3EESb2yU5hYo9hFidqMoTnbgLvp3dRxBy8kgLTAtCK/+gNAgMB\n" + "AAGjUzBRMB0GA1UdDgQWBBQxSLSxzTHyTEQthNoyMPeCMArBCzAfBgNVHSMEGDAW\n" + "gBQxSLSxzTHyTEQthNoyMPeCMArBCzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3\n" + "DQEBCwUAA4IBAQBME6UTgiWj6FfnjCaAOigkytrDmfEhkZiaXzzSoC0NJt+hyf5s\n" + "Jqimj4/JJlhaFRKd6A+J1T04Sg4JwRMXqmmsXZN7NRZ250OrtPVt3m1+vvNqJOYW\n" + "b24/E2dvhS0feqSbKIar7XnBFcLDw/w4bGmpztoywYmHtZ0USzNIOCuGAogdH/wL\n" + "55GvqpClYgBGDGT39fi75GeFNJqa7KUqvTm7FJeUq6oYkkKs+Z08u1GSKb3kekBb\n" + "nJkQwUG/xoU1XFNaFdeKuTpjVllVITRAFgjYF4Oy5dZJix8QgHJuG3VbD1VYGoeU\n" + "chJ23AD7h+jmt7DOOTGspsFUqxXmMRiM+Q3Y\n" + "-----END CERTIFICATE-----\n"; + +const std::string rsa_key = + "-----BEGIN PRIVATE KEY-----\n" + "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDasWBBpRZTezyO\n" + "v+8l2db1BOUHD2T4s6MlFoq+Vh6K37XgCGmDjXQP/GaDBxdCuC4HoL0ABXR9/upY\n" + "PdQzSkniPelC3si8S7USA3uEYAvhnprVoAWqZebN0ljgic7kiCJsBLSBjshzVFGg\n" + "a7MygBLA1ozxsVLSz4FPH/lcKUmjsZPkhBeEY9ENuyk7JX3bLtAHQy2mLhkTse5L\n" + "Fv+ZE+RyaX2lPliDKrScanfXItpbVlJPFVYkRs1l/dA3KJsETzLvYrAseguT0GKU\n" + "7ticVW+mvhjLQ8rNt95xMgo/hy3EESb2yU5hYo9hFidqMoTnbgLvp3dRxBy8kgLT\n" + "AtCK/+gNAgMBAAECggEASdz07NcMZl/OQUyUQk2EK7def3b0nIdXx/QIImdF45PR\n" + "gvx0XslM9QVDvmeLtK4uZcclbrdo9BFAJ1OiszwZHj/Y5AwI8ogDfTUN59Tkzmxa\n" + "UWK95yKJxOSRviztYwST07X3HXcTPtiwxST7HkhhjR4p9ov0tFz/iLD88OLFC3MT\n" + "8IyCb86m8nShrIfsbgqQrUPHPob78MsbqrzWqXOUv0ryoa2Bj3T3jsU6Sz2Kgqyo\n" + "I0V4fC9fXk7WFBXLiIt9H5CQPmzbMYG3+BjQpqP41NR2uMFT+N+Sgtj61rNl0FA3\n" + "4rHIIKBbsYWcKSg+l6qCTt5xyOiRDRt/vWdGSfNJRQKBgQDutm3wY7eNDFaMMqRb\n" + "nTgtKxjqW4RKbGvub0zJHlP4iCQvZV/v4PAKtnBPPB4UcgIeKAoXqBFQfErZt0E6\n" + "7W6/w3OrmslHYSzwO9HwWpHOCUiwI+sLivpupHgRopRELX39bAmIkd0BcifIzyuC\n" + "Btpd/6aYGc9WYS3NeTm24so2IwKBgQDqh8tKS1ki7VrloJgRgeAfIdRrKmSp9YBO\n" + "jSC3o3IMqIB5n8GBCYCEuu7qky3hH1Byd7qIMge3n12s2iNzTp8nz5Zt3E8rom46\n" + "kgFuSHEYXu7FCRjINcHflgFAlpXOGb/Kc8uv5quFGUe0Ts6HXCDwYsITa7IW2CcN\n" + "Z6zoSCQUDwKBgQDPbJ/dOZi+LFFsI3kjzlqJDSDqS7mJPesPVZFAVWUb2ZivwoP5\n" + "mdibRmoSv6dXlrV2ZM5YPgdFi6sywYUh4jzQztJM9AQgTTVSTnifROPbR7/spllQ\n" + "P2RbDfjzQfVZxLnsopsqG60R25Lsb/BbXP8UnNey5QKACZNWLxdSboDNRwKBgEI3\n" + "5SYs8BX0fl2nYkhPK0CfBKLdbV6venKzVjGDbIg2a0/r027jh+3x+dMxixqtBMHN\n" + "HFWoCpXF4WUUkj3UTQuoiQir0462ZfkTkGPbAFOpOjFXyC9/PiYq7F+YJOP0UTqQ\n" + "R0p7DqKd6Kj4N0fwszwsJi/lkHryvNQEGcXb2JPxAoGAJupWq9v9/LkZ8wTTeze+\n" + "01uqfC6T/qYPBxLjleuzMmfEoKhqzLyFzW+r4K5TnYz7jxP52KUSHR3r2lXdMasQ\n" + "kaTAid5ZjQUt5MkjI3W0N3tJhdzTH+rdkOWb+59ANECfhr1D0/o3GjSx2RW1EhtG\n" + "hSWgRxNM62fdbmxZ+JrxHCE=\n" + "-----END PRIVATE KEY-----\n"; + +#endif // BOOST_WINTLS_EXAMPLES_CERTIFICATE_HPP diff --git a/third-party/boost-wintls/examples/echo_client.cpp b/third-party/boost-wintls/examples/echo_client.cpp new file mode 100644 index 00000000000..e68ee2d825a --- /dev/null +++ b/third-party/boost-wintls/examples/echo_client.cpp @@ -0,0 +1,126 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include "certificate.hpp" + +#include + +#include + +#include +#include +#include +#include + +using boost::asio::ip::tcp; + +constexpr std::size_t max_length = 1024; + +class client { +public: + client(boost::asio::io_context& io_context, + boost::wintls::context& context, + const tcp::resolver::results_type& endpoints) + : stream_(io_context, context) { + connect(endpoints); + } + +private: + void connect(const tcp::resolver::results_type& endpoints) { + boost::asio::async_connect( + stream_.next_layer(), endpoints, [this](const boost::system::error_code& error, + const tcp::endpoint& /*endpoint*/) { + if (!error) { + handshake(); + } else { + std::cerr << "Connect failed: " << error.message() << "\n"; + } + }); + } + + void handshake() { + stream_.async_handshake(boost::wintls::handshake_type::client, + [this](const boost::system::error_code& error) { + if (!error) { + send_request(); + } else { + std::cerr << "Handshake failed: " << error.message() << "\n"; + } + }); + } + + void send_request() { + std::cout << "Enter message: "; + std::cin.getline(request_, max_length); + size_t request_length = std::strlen(request_); + + boost::asio::async_write( + stream_, boost::asio::buffer(request_, request_length), + [this](const boost::system::error_code& error, std::size_t length) { + if (!error) { + receive_response(length); + } else { + std::cerr << "Write failed: " << error.message() << "\n"; + } + }); + } + + void receive_response(std::size_t size) { + boost::asio::async_read( + stream_, boost::asio::buffer(reply_, size), + [this](const boost::system::error_code& ec, std::size_t length) { + if (!ec) { + std::cout << "Reply: "; + std::cout.write(reply_, static_cast(length)); + std::cout << "\n"; + stream_.async_shutdown([](const boost::system::error_code& error) { + if(error) { + std::cerr << "Shutdown failed: " << error.message() << "\n"; + } + }); + } else { + std::cerr << "Read failed: " << ec.message() << "\n"; + } + }); + } + + boost::wintls::stream stream_; + char request_[max_length]; + char reply_[max_length]; +}; + +int main(int argc, char* argv[]) { + try { + if (argc != 3) { + std::cerr << "Usage: client \n"; + return 1; + } + + boost::asio::io_context io_context; + + tcp::resolver resolver(io_context); + auto endpoints = resolver.resolve(argv[1], argv[2]); + + boost::wintls::context ctx(boost::wintls::method::system_default); + + // Convert X509 PEM bytes to Windows CERT_CONTEXT + auto certificate = boost::wintls::x509_to_cert_context(boost::asio::buffer(x509_certificate), + boost::wintls::file_format::pem); + + // Add certifcate as a trusted certifcate authority and verify it on handshake + ctx.add_certificate_authority(certificate.get()); + ctx.verify_server_certificate(true); + + client c(io_context, ctx, endpoints); + + io_context.run(); + } catch (std::exception& e) { + std::cerr << "Exception: " << e.what() << "\n"; + } + + return 0; +} diff --git a/third-party/boost-wintls/examples/echo_server.cpp b/third-party/boost-wintls/examples/echo_server.cpp new file mode 100644 index 00000000000..da0908d5de9 --- /dev/null +++ b/third-party/boost-wintls/examples/echo_server.cpp @@ -0,0 +1,148 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include "certificate.hpp" + +#include + +#include + +#include +#include +#include + +using boost::asio::ip::tcp; + +class session : public std::enable_shared_from_this { +public: + session(boost::wintls::stream stream) + : stream_(std::move(stream)) { + } + + void start() { + do_handshake(); + } + +private: + void do_handshake() { + auto self(shared_from_this()); + stream_.async_handshake(boost::wintls::handshake_type::server, + [this, self](const boost::system::error_code& ec) { + if (!ec) { + do_read(); + } else { + std::cerr << "Handshake failed: " << ec.message() << "\n"; + } + }); + } + + void do_read() { + auto self(shared_from_this()); + stream_.async_read_some(boost::asio::buffer(data_), + [this, self](const boost::system::error_code& ec, std::size_t length) { + if (!ec) { + do_write(length); + } else { + if (ec.value() != SEC_I_CONTEXT_EXPIRED) { // SEC_I_CONTEXT_EXPIRED means the client shutdown the TLS channel + std::cerr << "Read failed: " << ec.message() << "\n"; + } + } + }); + } + + void do_write(std::size_t length) { + auto self(shared_from_this()); + boost::asio::async_write(stream_, boost::asio::buffer(data_, length), + [this, self](const boost::system::error_code& ec, std::size_t /*length*/) { + if (!ec) { + do_read(); + } else { + std::cerr << "Write failed: " << ec.message() << "\n"; + } + }); + } + + boost::wintls::stream stream_; + char data_[1024]; +}; + +class server { +public: + server(boost::asio::io_context& io_context, unsigned short port) + : acceptor_(io_context, tcp::endpoint(tcp::v4(), port)) + , context_(boost::wintls::method::system_default) + , private_key_name_("wintls-echo-server-example") { + + // Convert X509 PEM bytes to Windows CERT_CONTEXT + auto certificate = boost::wintls::x509_to_cert_context(boost::asio::buffer(x509_certificate), + boost::wintls::file_format::pem); + + // Import RSA private key into the default cryptographic provider + boost::system::error_code ec; + boost::wintls::import_private_key(boost::asio::buffer(rsa_key), + boost::wintls::file_format::pem, + private_key_name_, + ec); + + // If the key already exists, assume it's the one already imported + // and ignore that error + if (ec && ec.value() != NTE_EXISTS) { + throw boost::system::system_error(ec); + } + + // Use the imported private key for the certificate + boost::wintls::assign_private_key(certificate.get(), private_key_name_); + + // Use the certificate for encrypting TLS messages + context_.use_certificate(certificate.get()); + + do_accept(); + } + + ~server() { + // Remove the imported private key. Most real applications + // probably only want to import the key once and most likely not + // in the server code. This is just for demonstration purposesq. + boost::system::error_code ec; + boost::wintls::delete_private_key(private_key_name_, ec); + } + +private: + void do_accept() { + acceptor_.async_accept([this](const boost::system::error_code& ec, tcp::socket socket) { + if (!ec) { + std::make_shared(boost::wintls::stream(std::move(socket), context_))->start(); + } else { + std::cerr << "Read failed: " << ec.message() << "\n"; + } + + do_accept(); + }); + } + + tcp::acceptor acceptor_; + boost::wintls::context context_; + std::string private_key_name_; +}; + +int main(int argc, char* argv[]) { + try { + if (argc != 2) { + std::cerr << "Usage: server \n"; + return 1; + } + + boost::asio::io_context io_context; + server s(io_context, static_cast(std::atoi(argv[1]))); + + io_context.run(); + } catch (std::exception& e) { + std::cerr << "Exception: " << e.what() << "\n"; + } + + return 0; +} diff --git a/third-party/boost-wintls/examples/https_client.cpp b/third-party/boost-wintls/examples/https_client.cpp new file mode 100644 index 00000000000..e77ec5c2683 --- /dev/null +++ b/third-party/boost-wintls/examples/https_client.cpp @@ -0,0 +1,115 @@ +// +// Copyright (c) 2020 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include +#include + +#include + +#include +#include +#include + +namespace beast = boost::beast; // from +namespace http = beast::http; // from +namespace net = boost::asio; // from +namespace ssl = boost::wintls; // from + +using tcp = boost::asio::ip::tcp; // from + +//------------------------------------------------------------------------------ + +// Performs an HTTP GET and prints the response +int main(int argc, char** argv) { + try { + // Exactly one command line argument required - the HTTPS URL + if(argc != 2) { + std::cerr << "Usage: " << argv[0] << " [HTTPS_URL]\n\n"; + std::cerr << "Example: " << argv[0] << " https://www.boost.org/LICENSE_1_0.txt\n"; + return EXIT_FAILURE; + } + + const std::string url{argv[1]}; + + // Very basic URL matching. Not a full URL validator. + std::regex re("https://([^/$:]+):?([^/$]*)(/?.*)"); + std::smatch what; + if(!regex_match(url, what, re)) { + std::cerr << "Invalid or unsupported URL: " << url << "\n"; + return EXIT_FAILURE; + } + + // Get the relevant parts of the URL + const std::string host = std::string(what[1]); + // Use default HTTPS port (443) if not specified + const std::string port = what[2].length() > 0 ? what[2].str() : "443"; + // Use default path ('/') if not specified + const std::string path = what[3].length() > 0 ? what[3].str() : "/"; + + // Use HTTP/1.1 + const int version = 11; + + // The io_context is required for all I/O + net::io_context ioc; + + // The SSL context is required, and holds certificates + ssl::context ctx{boost::wintls::method::system_default}; + + // Use the operating systems default certificates for verification + ctx.use_default_certificates(true); + + // Verify the remote server's certificate + ctx.verify_server_certificate(true); + + // Construct the TLS stream with the parameters from the context + ssl::stream stream(ioc, ctx); + + // Set SNI hostname (many hosts need this to handshake successfully) + stream.set_server_hostname(host); + + // Enable Check whether the Server Certificate was revoked + stream.set_certificate_revocation_check(true); + + // Look up the domain name + tcp::resolver resolver(ioc); + auto const results = resolver.resolve(host, port); + + // Make the connection on the IP address we get from a lookup + beast::get_lowest_layer(stream).connect(results); + + // Perform the TLS handshake + stream.handshake(boost::wintls::handshake_type::client); + + // Set up an HTTP GET request message + http::request req{http::verb::get, path, version}; + req.set(http::field::host, host); + req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); + + // Send the HTTP request to the remote host + http::write(stream, req); + + // This buffer is used for reading and must be persisted + beast::flat_buffer buffer; + + // Declare a container to hold the response + http::response res; + + // Receive the HTTP response + http::read(stream, buffer, res); + + // Write the message to standard out + std::cout << res << std::endl; + + // Shutdown the TLS connection + stream.shutdown(); + } catch(std::exception const& e) { + std::cerr << "Error: " << e.what() << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} diff --git a/third-party/boost-wintls/include/boost/wintls.hpp b/third-party/boost-wintls/include/boost/wintls.hpp new file mode 100644 index 00000000000..1d5821b1160 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls.hpp @@ -0,0 +1,21 @@ +// +// Copyright (c) 2020 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_HPP +#define BOOST_WINTLS_HPP + +#include + +#include +#include +#include +#include +#include +#include +#include + +#endif // BOOST_WINTLS_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/certificate.hpp b/third-party/boost-wintls/include/boost/wintls/certificate.hpp new file mode 100644 index 00000000000..8041ffac0a9 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/certificate.hpp @@ -0,0 +1,286 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_CERTIFICATE_HPP +#define BOOST_WINTLS_CERTIFICATE_HPP + +#include +#include + +#include + +#include + +namespace boost { +namespace wintls { + +namespace detail { +struct crypt_context { + crypt_context(const std::string& name) { + if (!CryptAcquireContextA(&ptr, name.c_str(), nullptr, PROV_RSA_FULL, CRYPT_NEWKEYSET | CRYPT_SILENT)) { + detail::throw_last_error("CryptAcquireContextA"); + } + } + + ~crypt_context() { + CryptReleaseContext(ptr, 0); + } + + HCRYPTPROV ptr = 0; +}; + +struct crypt_key { + ~crypt_key() { + CryptDestroyKey(ptr); + } + + HCRYPTKEY ptr = 0; +}; + +struct cert_ctx_deleter { + void operator()(const CERT_CONTEXT* cert_ctx) { + CertFreeCertificateContext(cert_ctx); + } +}; + +} +/** + * @verbatim embed:rst:leading-asterisk + * Custom std::unique_ptr for managing a `CERT_CONTEXT`_ + * @endverbatim + */ +using cert_context_ptr = std::unique_ptr; + +/** + * @verbatim embed:rst:leading-asterisk + * Convert certificate from standard X509 format to Windows `CERT_CONTEXT`_. + * @endverbatim + * + * @param x509 Buffer holding the X509 certificate contents. + * + * @param format The @ref file_format of the X509 contents. + * + * @return A managed cert_context. + * + * @throws boost::system::system_error Thrown on failure. + * + */ +inline cert_context_ptr x509_to_cert_context(const net::const_buffer& x509, file_format format) { + // TODO: Support DER format + BOOST_VERIFY_MSG(format == file_format::pem, "Only PEM format currently implemented"); + + auto data = detail::crypt_string_to_binary(x509); + auto cert = CertCreateCertificateContext(X509_ASN_ENCODING, data.data(), static_cast(data.size())); + if (!cert) { + detail::throw_last_error("CertCreateCertificateContext"); + } + + return cert_context_ptr{cert}; +} + +/** + * @verbatim embed:rst:leading-asterisk + * Convert certificate from standard X509 format to Windows `CERT_CONTEXT`_. + * @endverbatim + * + * @param x509 Buffer holding the X509 certificate contents. + * + * @param format The @ref file_format of the X509 contents. + * + * @param ec Set to indicate what error occurred, if any. + * + * @return A managed cert_context. + * + */ +inline cert_context_ptr x509_to_cert_context(const net::const_buffer& x509, file_format format, boost::system::error_code& ec) { + ec = {}; + try { + return x509_to_cert_context(x509, format); + } catch (const boost::system::system_error& e) { + ec = e.code(); + return cert_context_ptr{}; + } +} + +/** + * Import a private key into the default cryptographic provider using the given name. + * + * This function can be used to import an RSA private key in PKCS#8 + * format in to the default certificate provider under the given name. + * + * The key can be associated with a certificate using the @ref assign_private_key function. + * + * @param private_key The private key to be imported in PKCS#8 format. + * + * @param format The @ref file_format of the private_key. + * + * @param name The name used to associate the key. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note Currently only RSA keys are supported. + */ +inline void import_private_key(const net::const_buffer& private_key, file_format format, const std::string& name) { + // TODO: Handle ASN.1 DER format + BOOST_VERIFY_MSG(format == file_format::pem, "Only PEM format currently implemented"); + auto data = detail::crypt_decode_object_ex(net::buffer(detail::crypt_string_to_binary(private_key)), PKCS_PRIVATE_KEY_INFO); + auto private_key_info = reinterpret_cast(data.data()); + + // TODO: Set proper error code instead of asserting + BOOST_VERIFY_MSG(strcmp(private_key_info->Algorithm.pszObjId, szOID_RSA_RSA) == 0, "Only RSA keys supported"); + auto rsa_private_key = detail::crypt_decode_object_ex(net::buffer(private_key_info->PrivateKey.pbData, + private_key_info->PrivateKey.cbData), + PKCS_RSA_PRIVATE_KEY); + + detail::crypt_context ctx(name); + detail::crypt_key key; + if (!CryptImportKey(ctx.ptr, + rsa_private_key.data(), + static_cast(rsa_private_key.size()), + 0, + 0, + &key.ptr)) { + detail::throw_last_error("CryptImportKey"); + } +} + +/** + * Import a private key into the default cryptographic provider using the given name. + * + * This function can be used to import an RSA private key in PKCS#8 + * format in to the default certificate provider under the given name. + * + * The key can be associated with a certificate using the @ref assign_private_key function. + * + * @param private_key The private key to be imported in PKCS#8 format. + * + * @param format The @ref file_format of the private_key. + * + * @param name The name used to associate the key. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note Currently only RSA keys are supported. + */ +inline void import_private_key(const net::const_buffer& private_key, file_format format, const std::string& name, boost::system::error_code& ec) { + ec = {}; + try { + import_private_key(private_key, format, name); + } catch (const boost::system::system_error& e) { + ec = e.code(); + } +} + +/** + * Delete a private key from the default cryptographic provider. + * + * @param name The name of the container storing the private key to delete. + * + * @throws boost::system::system_error Thrown on failure. + * + */ +inline void delete_private_key(const std::string& name) { + HCRYPTKEY ptr = 0; + if (!CryptAcquireContextA(&ptr, name.c_str(), nullptr, PROV_RSA_FULL, CRYPT_DELETEKEYSET)) { + + throw boost::system::system_error(static_cast(GetLastError()), boost::system::system_category()); + } +} + +/** + * Delete a private key from the default cryptographic provider. + * + * @param name The name of the container storing the private key to delete. + * + * @param ec Set to indicate what error occurred, if any. + * + */ +inline void delete_private_key(const std::string& name, boost::system::error_code& ec) { + ec = {}; + try { + delete_private_key(name); + } catch (const boost::system::system_error& e) { + ec = e.code(); + } +} + +/** + * @verbatim embed:rst:leading-asterisk + * Assigns a private key to a certificate. + * + * In order for a `CERT_CONTEXT`_ to be used by a server in needs to + * have a private key associated with it. + * + * @endverbatim + * + * This function will associate the named key with the given + * certficate in order for it be used by eg. @ref context::use_certificate. + * + * @note No check is done to ensure the key exists. Associating a non + * existing or non accessible key will result in unexpected behavior + * when used with a @ref stream operating as a server. + * + * @param cert The certificate to associate with the private key. + * + * @param name The name of the private key in the default cryptographic key provider. + * + * @throws boost::system::system_error Thrown on failure. + */ +inline void assign_private_key(const CERT_CONTEXT* cert, const std::string& name) { + // TODO: Move to utility function + const auto size = name.size() + 1; + auto wname = std::make_unique(size); + const auto size_converted = mbstowcs(wname.get(), name.c_str(), size); + BOOST_VERIFY_MSG(size_converted == name.size(), "mbstowcs"); + + CRYPT_KEY_PROV_INFO keyProvInfo{}; + keyProvInfo.pwszContainerName = wname.get(); + keyProvInfo.pwszProvName = nullptr; + keyProvInfo.dwFlags = CERT_SET_KEY_PROV_HANDLE_PROP_ID | CERT_SET_KEY_CONTEXT_PROP_ID; + keyProvInfo.dwProvType = PROV_RSA_FULL; + keyProvInfo.dwKeySpec = AT_KEYEXCHANGE; + + if (!CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0, &keyProvInfo)) { + detail::throw_last_error("CertSetCertificateContextProperty"); + } +} + +/** + * @verbatim embed:rst:leading-asterisk + * Assigns a private key to a certificate. + * + * In order for a `CERT_CONTEXT`_ to be used by a server in needs to + * have a private key associated with it. + * + * @endverbatim + * + * This function will associate the named key with the given + * certficate in order for it be used by eg. @ref context::use_certificate. + * + * @note No check is done to ensure the key exists. Associating a non + * existing or non accessible key will result in unexpected behavior + * when used with a @ref stream operating as a server. + * + * @param cert The certificate to associate with the private key. + * + * @param name The name of the private key in the default cryptographic key provider. + * + * @param ec Set to indicate what error occurred, if any. + */ +inline void assign_private_key(const CERT_CONTEXT* cert, const std::string& name, boost::system::error_code& ec) { + ec = {}; + try { + assign_private_key(cert, name); + } catch (const boost::system::system_error& e) { + ec = e.code(); + } +} + +} // namespace wintls +} // namespace boost + +#endif diff --git a/third-party/boost-wintls/include/boost/wintls/context.hpp b/third-party/boost-wintls/include/boost/wintls/context.hpp new file mode 100644 index 00000000000..0623e12583c --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/context.hpp @@ -0,0 +1,160 @@ +// +// Copyright (c) 2020 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_CONTEXT_HPP +#define BOOST_WINTLS_CONTEXT_HPP + +#include + +#include +#include + +#include + +namespace boost { +namespace wintls { + +namespace detail { +class sspi_handshake; +} + +class context { +public: + /** Construct a context. + * + * @param connection_method The @ref method to use for connections. + */ + explicit context(method connection_method) + : method_(connection_method) + , verify_server_certificate_(false) { + } + + /** Add certification authority for performing verification. + * + * This function is used to add one trusted certification authority + * to the contexts certificate store used for certificate validation + * + * @param cert The certficate to add to the certificate store + * + * @throws boost::system::system_error Thrown on failure. + */ + void add_certificate_authority(const CERT_CONTEXT* cert) { + ctx_certs_.add_certificate_authority(cert); + } + + /** Add certification authority for performing verification. + * + * This function is used to add one trusted certification authority + * to the contexts certificate store used for certificate validation + * + * @param cert The certficate to add to the certificate store + * + * @param ec Set to indicate what error occurred, if any. + */ + void add_certificate_authority(const CERT_CONTEXT* cert, boost::system::error_code& ec) { + try { + ctx_certs_.add_certificate_authority(cert); + } catch (const boost::system::system_error& e) { + ec = e.code(); + } + } + + /** Enables/disables remote server certificate verification + * + * This function may be used to enable clients to verify the + * certificate presented by the server with the known trusted + * certificates. + * + * @param verify True if the remote server certificate should be + * verified + */ + void verify_server_certificate(bool verify) { + verify_server_certificate_ = verify; + } + + /** Use the default operating system certificates + * + * This function may be used to verify the server certficates + * against the certficates installed in the operating system when + * performing handshakes as a client. + * + * It is still possible to add additional certificates for + * verification in addition to the ones installed by the operating + * system. + * + * @param use_system_certs True if the default operating system + * certificates should be used for verification. + */ + void use_default_certificates(bool use_system_certs) { + ctx_certs_.use_default_cert_store = use_system_certs; + } + + /** Set the certificate to use when operating as a server + * + * This function sets the certficate to use when using a @ref stream + * as server. + * + * @param cert The private certificate the @ref stream will use for + * encrypting messages when operating as a server. + * + * @note The certificate must be a private certificate, + * ie. containing a reference to a private key. If the certificate + * is imported from a public certificate @ref assign_private_key can + * be used for that. + * + * @throws boost::system::system_error Thrown on failure. + */ + void use_certificate(const CERT_CONTEXT* cert) { + ctx_certs_.use_certificate(cert); + } + + /** Set the certificate to use when operating as a server + * + * This function sets the certficate to use when using a @ref stream + * as server. + * + * @param cert The private certificate the @ref stream will use for + * encrypting messages when operating as a server. + * + * @note The certificate must be a private certificate, + * ie. containing a reference to a private key. If the certificate + * is imported from a public certificate @ref assign_private_key can + * be used for that. + * + * @param ec Set to indicate what error occurred, if any. + */ + void use_certificate(const CERT_CONTEXT* cert, boost::system::error_code& ec) { + try { + ctx_certs_.use_certificate(cert); + } catch (const boost::system::system_error& e) { + ec = e.code(); + } + } + +private: + DWORD verify_certificate(const CERT_CONTEXT* cert, const std::string& server_hostname, bool check_revocation) { + if (!verify_server_certificate_) { + return ERROR_SUCCESS; + } + return static_cast(ctx_certs_.verify_certificate(cert, server_hostname, check_revocation)); + } + + const CERT_CONTEXT* server_cert() const { + return ctx_certs_.server_cert(); + } + + friend class detail::sspi_handshake; + + detail::context_certificates ctx_certs_; + method method_; + bool verify_server_certificate_; +}; + +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_CONTEXT_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/async_handshake.hpp b/third-party/boost-wintls/include/boost/wintls/detail/async_handshake.hpp new file mode 100644 index 00000000000..0a353ae3496 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/async_handshake.hpp @@ -0,0 +1,137 @@ +// +// Copyright (c) 2020 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_ASYNC_HANDSHAKE_HPP +#define BOOST_WINTLS_DETAIL_ASYNC_HANDSHAKE_HPP + +#include + +#include + +#include + +namespace boost { +namespace wintls { +namespace detail { + +template +struct async_handshake : boost::asio::coroutine { + async_handshake(NextLayer& next_layer, detail::sspi_handshake& handshake, handshake_type type) + : next_layer_(next_layer) + , handshake_(handshake) + , entry_count_(0) + , state_(state::idle) { + handshake_(type); + } + + template + void operator()(Self& self, boost::system::error_code ec = {}, std::size_t length = 0) { + if (ec) { + self.complete(ec); + return; + } + + ++entry_count_; + auto is_continuation = [this] { + return entry_count_ > 1; + }; + + switch(state_) { + case state::reading: + handshake_.size_read(length); + state_ = state::idle; + break; + case state::writing: + handshake_.size_written(length); + state_ = state::idle; + break; + case state::idle: + break; + } + + detail::sspi_handshake::state handshake_state; + BOOST_ASIO_CORO_REENTER(*this) { + while((handshake_state = handshake_()) != detail::sspi_handshake::state::done) { + if (handshake_state == detail::sspi_handshake::state::data_needed) { + BOOST_ASIO_CORO_YIELD { + state_ = state::reading; + next_layer_.async_read_some(handshake_.in_buffer(), std::move(self)); + } + continue; + } + + if (handshake_state == detail::sspi_handshake::state::data_available) { + BOOST_ASIO_CORO_YIELD { + state_ = state::writing; + net::async_write(next_layer_, handshake_.out_buffer(), std::move(self)); + } + continue; + } + + if (handshake_state == detail::sspi_handshake::state::error) { + if (!is_continuation()) { + BOOST_ASIO_CORO_YIELD { + auto e = self.get_executor(); + net::post(e, [self = std::move(self), ec, length]() mutable { self(ec, length); }); + } + } + self.complete(handshake_.last_error()); + return; + } + + if (handshake_state == detail::sspi_handshake::state::done_with_data) { + BOOST_ASIO_CORO_YIELD { + state_ = state::writing; + net::async_write(next_layer_, handshake_.out_buffer(), std::move(self)); + } + break; + } + + if (handshake_state == detail::sspi_handshake::state::error_with_data) { + BOOST_ASIO_CORO_YIELD { + state_ = state::writing; + net::async_write(next_layer_, handshake_.out_buffer(), std::move(self)); + } + if (!is_continuation()) { + BOOST_ASIO_CORO_YIELD { + auto e = self.get_executor(); + net::post(e, [self = std::move(self), ec, length]() mutable { self(ec, length); }); + } + } + self.complete(handshake_.last_error()); + return; + } + } + + if (!is_continuation()) { + BOOST_ASIO_CORO_YIELD { + auto e = self.get_executor(); + net::post(e, [self = std::move(self), ec, length]() mutable { self(ec, length); }); + } + } + BOOST_ASSERT(!handshake_.last_error()); + self.complete(handshake_.last_error()); + } + } + +private: + NextLayer& next_layer_; + detail::sspi_handshake& handshake_; + int entry_count_; + std::vector input_; + enum class state { + idle, + reading, + writing + } state_; +}; + +} // namespace detail +} // namespace wintls +} // namespace boost + +#endif //BOOST_WINTLS_DETAIL_ASYNC_HANDSHAKE_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/async_read.hpp b/third-party/boost-wintls/include/boost/wintls/detail/async_read.hpp new file mode 100644 index 00000000000..fda02a35177 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/async_read.hpp @@ -0,0 +1,77 @@ +// +// Copyright (c) 2020 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_ASYNC_READ_HPP +#define BOOST_WINTLS_DETAIL_ASYNC_READ_HPP + +#include + +#include + +namespace boost { +namespace wintls { +namespace detail { + +template +struct async_read : boost::asio::coroutine { + async_read(NextLayer& next_layer, const MutableBufferSequence& buffers, detail::sspi_decrypt& decrypt) + : next_layer_(next_layer) + , buffers_(buffers) + , decrypt_(decrypt) + , entry_count_(0) { + } + + template + void operator()(Self& self, boost::system::error_code ec = {}, std::size_t size_read = 0) { + if (ec) { + self.complete(ec, size_read); + return; + } + + ++entry_count_; + auto is_continuation = [this] { + return entry_count_ > 1; + }; + + detail::sspi_decrypt::state state; + BOOST_ASIO_CORO_REENTER(*this) { + while((state = decrypt_(buffers_)) == detail::sspi_decrypt::state::data_needed) { + BOOST_ASIO_CORO_YIELD { + next_layer_.async_read_some(decrypt_.input_buffer, std::move(self)); + } + decrypt_.size_read(size_read); + continue; + } + + if (state == detail::sspi_decrypt::state::error) { + if (!is_continuation()) { + BOOST_ASIO_CORO_YIELD { + auto e = self.get_executor(); + net::post(e, [self = std::move(self), ec, size_read]() mutable { self(ec, size_read); }); + } + } + ec = decrypt_.last_error(); + self.complete(ec, 0); + return; + } + + self.complete(boost::system::error_code{}, decrypt_.size_decrypted); + } + } + +private: + NextLayer& next_layer_; + MutableBufferSequence buffers_; + detail::sspi_decrypt& decrypt_; + int entry_count_; +}; + +} // namespace detail +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_DETAIL_ASYNC_READ_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/async_shutdown.hpp b/third-party/boost-wintls/include/boost/wintls/detail/async_shutdown.hpp new file mode 100644 index 00000000000..8d61334991e --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/async_shutdown.hpp @@ -0,0 +1,72 @@ +// +// Copyright (c) 2020 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_ASYNC_SHUTDOWN_HPP +#define BOOST_WINTLS_DETAIL_ASYNC_SHUTDOWN_HPP + +#include + +#include + +namespace boost { +namespace wintls { +namespace detail { + +template +struct async_shutdown : boost::asio::coroutine { + async_shutdown(NextLayer& next_layer, detail::sspi_shutdown& shutdown) + : next_layer_(next_layer) + , shutdown_(shutdown) + , entry_count_(0) { + } + + template + void operator()(Self& self, boost::system::error_code ec = {}, std::size_t size_written = 0) { + if (ec) { + self.complete(ec); + return; + } + + ++entry_count_; + auto is_continuation = [this] { + return entry_count_ > 1; + }; + + ec = shutdown_(); + + BOOST_ASIO_CORO_REENTER(*this) { + if (!ec) { + BOOST_ASIO_CORO_YIELD { + net::async_write(next_layer_, shutdown_.buffer(), std::move(self)); + } + shutdown_.size_written(size_written); + self.complete({}); + return; + } else { + if (!is_continuation()) { + BOOST_ASIO_CORO_YIELD { + auto e = self.get_executor(); + net::post(e, [self = std::move(self), ec, size_written]() mutable { self(ec, size_written); }); + } + } + self.complete(ec); + return; + } + } + } + +private: + NextLayer& next_layer_; + detail::sspi_shutdown& shutdown_; + int entry_count_; +}; + +} // namespace detail +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_DETAIL_ASYNC_SHUTDOWN_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/async_write.hpp b/third-party/boost-wintls/include/boost/wintls/detail/async_write.hpp new file mode 100644 index 00000000000..d9568152ab7 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/async_write.hpp @@ -0,0 +1,57 @@ +// +// Copyright (c) 2020 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_ASYNC_WRITE_HPP +#define BOOST_WINTLS_DETAIL_ASYNC_WRITE_HPP + +#include + +#include + +#include + +namespace boost { +namespace wintls { +namespace detail { + +template +struct async_write : boost::asio::coroutine { + async_write(NextLayer& next_layer, const ConstBufferSequence& buffer, detail::sspi_encrypt& encrypt) + : next_layer_(next_layer) + , buffer_(buffer) + , encrypt_(encrypt) { + } + + template + void operator()(Self& self, boost::system::error_code ec = {}, std::size_t length = 0) { + boost::ignore_unused(length); + BOOST_ASIO_CORO_REENTER(*this) { + bytes_consumed_ = encrypt_(buffer_, ec); + if (ec) { + self.complete(ec, 0); + return; + } + + BOOST_ASIO_CORO_YIELD { + net::async_write(next_layer_, encrypt_.buffers, std::move(self)); + } + self.complete(ec, bytes_consumed_); + } + } + +private: + NextLayer& next_layer_; + ConstBufferSequence buffer_; + detail::sspi_encrypt& encrypt_; + size_t bytes_consumed_{0}; +}; + +} // detail +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_DETAIL_ASYNC_WRITE_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/config.hpp b/third-party/boost-wintls/include/boost/wintls/detail/config.hpp new file mode 100644 index 00000000000..ecc81002494 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/config.hpp @@ -0,0 +1,35 @@ +// +// Copyright (c) 2020 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_CONFIG_HPP +#define BOOST_WINTLS_DETAIL_CONFIG_HPP + +#include + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-private-field" +#endif +#include +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#if !defined(__MINGW32__) +#pragma comment(lib, "crypt32") +#pragma comment(lib, "secur32") +#endif // __MINGW32__ + +namespace boost { +namespace wintls { + +namespace net = boost::asio; + +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_DETAIL_CONFIG_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/context_certificates.hpp b/third-party/boost-wintls/include/boost/wintls/detail/context_certificates.hpp new file mode 100644 index 00000000000..4f15fa6bf5c --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/context_certificates.hpp @@ -0,0 +1,180 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_CONTEXT_CERTIFICATES_HPP +#define BOOST_WINTLS_DETAIL_CONTEXT_CERTIFICATES_HPP + +#include + +#include +#include + +#include +#include +#include +#include + +namespace boost { +namespace wintls { +namespace detail { + +struct cert_store_deleter { + void operator()(HCERTSTORE store) { + CertCloseStore(store, 0); + } +}; + +using cert_store_ptr = std::unique_ptr, cert_store_deleter>; + +class context_certificates { +public: + void add_certificate_authority(const CERT_CONTEXT* cert) { + init_cert_store(); + if(!CertAddCertificateContextToStore(cert_store_.get(), + cert, + CERT_STORE_ADD_ALWAYS, + nullptr)) { + throw_last_error("CertAddCertificateContextToStore"); + } + } + + void add_crl(const CRL_CONTEXT* crl_ctx) { + init_cert_store(); + if (!CertAddCRLContextToStore(cert_store_.get(), + crl_ctx, + CERT_STORE_ADD_ALWAYS, + nullptr)) { + throw_last_error("CertAddCRLContextToStore"); + } + } + + HRESULT verify_certificate(const CERT_CONTEXT* cert, const std::string& server_hostname, bool check_revocation) { + HRESULT status = CERT_E_UNTRUSTEDROOT; + + if (cert_store_) { + CERT_CHAIN_ENGINE_CONFIG chain_engine_config{}; + chain_engine_config.cbSize = sizeof(chain_engine_config); + chain_engine_config.hExclusiveRoot = cert_store_.get(); + + struct cert_chain_engine { + ~cert_chain_engine() { + CertFreeCertificateChainEngine(ptr); + } + HCERTCHAINENGINE ptr = nullptr; + } chain_engine; + + if (!CertCreateCertificateChainEngine(&chain_engine_config, &chain_engine.ptr)) { + return static_cast(GetLastError()); + } + + status = static_cast(verify_certificate_chain(cert, chain_engine.ptr, server_hostname, check_revocation)); + } + + if (status != ERROR_SUCCESS && use_default_cert_store) { + // Calling CertGetCertificateChain with a NULL pointer engine uses + // the default system certificate store + status = static_cast(verify_certificate_chain(cert, nullptr, server_hostname, check_revocation)); + } + + return status; + } + + void use_certificate(const CERT_CONTEXT* cert) { + HCRYPTPROV_OR_NCRYPT_KEY_HANDLE unused_0; + DWORD unused_1; + BOOL unused_2; + if (!CryptAcquireCertificatePrivateKey(cert, + CRYPT_ACQUIRE_COMPARE_KEY_FLAG, + nullptr, + &unused_0, + &unused_1, + &unused_2)) { + detail::throw_last_error("CryptAcquireCertificatePrivateKey"); + } + server_cert_ = cert_context_ptr{CertDuplicateCertificateContext(cert)}; + } + + const CERT_CONTEXT* server_cert() const { + return server_cert_.get(); + } + + bool use_default_cert_store = false; + +private: + void init_cert_store() { + if (!cert_store_) { + cert_store_ = cert_store_ptr{CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 0, nullptr)}; + if (!cert_store_) { + throw_last_error("CertOpenStore"); + } + } + } + + DWORD verify_certificate_chain(const CERT_CONTEXT* cert, + HCERTCHAINENGINE engine, + const std::string& server_hostname, + bool check_revocation) { + CERT_CHAIN_PARA chain_parameters{}; + chain_parameters.cbSize = sizeof(chain_parameters); + + const CERT_CHAIN_CONTEXT* chain_ctx_ptr; + DWORD chain_flags = check_revocation ? CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT + : 0; + if(!CertGetCertificateChain(engine, + cert, + nullptr, + cert->hCertStore, + &chain_parameters, + chain_flags, + nullptr, + &chain_ctx_ptr)) { + return GetLastError(); + } + + std::unique_ptr + scoped_chain_ctx{chain_ctx_ptr, &CertFreeCertificateChain}; + // We could return here if (scoped_chain_ctx->TrustStatus.dwErrorStatus != CERT_TRUST_NO_ERROR), + // but we would have to map the error code to a system error ourselves,. + // Instead we rely on CertVerifyCertificateChainPolicy to obtain the appropriate system error. + + HTTPSPolicyCallbackData https_policy{}; + https_policy.cbStruct = sizeof(https_policy); + https_policy.dwAuthType = AUTHTYPE_SERVER; + // add parameter to verify the host name if it was actually set + std::wstring whostname; + if (!server_hostname.empty()) { + whostname.resize(server_hostname.size(), L' '); + whostname.resize(std::mbstowcs(&whostname[0], server_hostname.data(), server_hostname.size())); + https_policy.pwszServerName = &whostname[0]; + } + + CERT_CHAIN_POLICY_PARA policy_params{}; + policy_params.cbSize = sizeof(policy_params); + policy_params.pvExtraPolicyPara = &https_policy; + + CERT_CHAIN_POLICY_STATUS policy_status{}; + policy_status.cbSize = sizeof(policy_status); + + if(!CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL, + scoped_chain_ctx.get(), + &policy_params, + &policy_status)) { + return GetLastError(); + } + + return policy_status.dwError; + } + + cert_store_ptr cert_store_{}; + cert_context_ptr server_cert_{}; +}; + +} // namespace detail +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_DETAIL_CONTEXT_CERTIFICATES_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/context_flags.hpp b/third-party/boost-wintls/include/boost/wintls/detail/context_flags.hpp new file mode 100644 index 00000000000..4c6e9346233 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/context_flags.hpp @@ -0,0 +1,37 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_CONTEXT_FLAGS_HPP +#define BOOST_WINTLS_DETAIL_CONTEXT_FLAGS_HPP + +namespace boost { +namespace wintls { +namespace detail { + +constexpr DWORD client_context_flags = + ISC_REQ_SEQUENCE_DETECT | // Detect messages received out of sequence + ISC_REQ_REPLAY_DETECT | // Detect replayed messages + ISC_REQ_CONFIDENTIALITY | // Encrypt messages + ISC_RET_EXTENDED_ERROR | // When errors occur, the remote party will be notified + ISC_REQ_ALLOCATE_MEMORY | // Allocate buffers. Free them with FreeContextBuffer + ISC_REQ_STREAM | // Support a stream-oriented connection + ISC_REQ_USE_SUPPLIED_CREDS | // Do not auto send client cert. + ISC_REQ_MANUAL_CRED_VALIDATION; // Manually authenticate + +constexpr DWORD server_context_flags = + ASC_REQ_SEQUENCE_DETECT | // Detect messages received out of sequence + ASC_REQ_REPLAY_DETECT | // Detect replayed messages + ASC_REQ_CONFIDENTIALITY | // Encrypt messages + ASC_RET_EXTENDED_ERROR | // When errors occur, the remote party will be notified + ASC_REQ_ALLOCATE_MEMORY | // Allocate buffers. Free them with FreeContextBuffer + ASC_REQ_STREAM; // Support a stream-oriented connection + +} // namespace detail +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_DETAIL_CONTEXT_FLAGS_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/decrypt_buffers.hpp b/third-party/boost-wintls/include/boost/wintls/detail/decrypt_buffers.hpp new file mode 100644 index 00000000000..f15665f440d --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/decrypt_buffers.hpp @@ -0,0 +1,33 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_DECRYPT_BUFFERS_HPP +#define BOOST_WINTLS_DETAIL_DECRYPT_BUFFERS_HPP + +#include + +namespace boost { +namespace wintls { +namespace detail { + +class decrypt_buffers : public sspi_buffer_sequence<4> { +public: + decrypt_buffers() + : sspi_buffer_sequence(std::array { + SECBUFFER_DATA, + SECBUFFER_EMPTY, + SECBUFFER_EMPTY, + SECBUFFER_EMPTY + }) { + } +}; + +} // namespace detail +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_DETAIL_DECRYPT_BUFFERS_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/decrypted_data_buffer.hpp b/third-party/boost-wintls/include/boost/wintls/detail/decrypted_data_buffer.hpp new file mode 100644 index 00000000000..7018ea134d7 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/decrypted_data_buffer.hpp @@ -0,0 +1,51 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_DECRYPTED_DATA_BUFFER_HPP +#define BOOST_WINTLS_DETAIL_DECRYPTED_DATA_BUFFER_HPP + +#include + +#include +#include +#include + +namespace boost { +namespace wintls { +namespace detail { + +template +class decrypted_data_buffer { +public: + std::size_t empty() const { + return available_data_.size() == 0; + } + + template + std::size_t get(const MutableBufferSequence& buffer) { + const auto size = net::buffer_copy(buffer, available_data_); + available_data_ += size; + return size; + } + + template + void fill(const ConstBufferSequence& buffer) { + assert(available_data_.size() == 0); + const auto size = net::buffer_copy(net::buffer(buffer_), buffer); + available_data_ = net::buffer(buffer_.data(), size); + } + +private: + net::mutable_buffer available_data_; + std::array buffer_; +}; + +} // namespace detail +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_DETAIL_DECRYPTED_DATA_BUFFER_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/encrypt_buffers.hpp b/third-party/boost-wintls/include/boost/wintls/detail/encrypt_buffers.hpp new file mode 100644 index 00000000000..57daa195b09 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/encrypt_buffers.hpp @@ -0,0 +1,65 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_ENCRYPT_BUFFERS_HPP +#define BOOST_WINTLS_DETAIL_ENCRYPT_BUFFERS_HPP + +#include +#include +#include + +namespace boost { +namespace wintls { +namespace detail { + +class encrypt_buffers : public sspi_buffer_sequence<4> { +public: + encrypt_buffers(ctxt_handle& ctxt_handle) + : sspi_buffer_sequence(std::array { + SECBUFFER_STREAM_HEADER, + SECBUFFER_DATA, + SECBUFFER_STREAM_TRAILER, + SECBUFFER_EMPTY + }) + , ctxt_handle_(ctxt_handle) { + } + + template std::size_t operator()(const ConstBufferSequence& buffers, SECURITY_STATUS& sc) { + if (data_.empty()) { + sc = sspi_functions::QueryContextAttributes(ctxt_handle_.get(), SECPKG_ATTR_STREAM_SIZES, &stream_sizes_); + if (sc != SEC_E_OK) { + return 0; + } + data_.resize(stream_sizes_.cbHeader + stream_sizes_.cbMaximumMessage + stream_sizes_.cbTrailer); + } + + const auto size_consumed = std::min(net::buffer_size(buffers), static_cast(stream_sizes_.cbMaximumMessage)); + + buffers_[0].pvBuffer = data_.data(); + buffers_[0].cbBuffer = stream_sizes_.cbHeader; + + net::buffer_copy(net::buffer(data_.data() + stream_sizes_.cbHeader, size_consumed), buffers); + buffers_[1].pvBuffer = data_.data() + stream_sizes_.cbHeader; + buffers_[1].cbBuffer = static_cast(size_consumed); + + buffers_[2].pvBuffer = data_.data() + stream_sizes_.cbHeader + size_consumed; + buffers_[2].cbBuffer = stream_sizes_.cbTrailer; + + return size_consumed; + } + +private: + ctxt_handle& ctxt_handle_; + std::vector data_; + SecPkgContext_StreamSizes stream_sizes_{0, 0, 0, 0, 0}; +}; + +} // namespace detail +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_DETAIL_ENCRYPT_BUFFERS_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/error.hpp b/third-party/boost-wintls/include/boost/wintls/detail/error.hpp new file mode 100644 index 00000000000..b5c5d72e9f8 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/error.hpp @@ -0,0 +1,42 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_ERROR_HPP +#define BOOST_WINTLS_DETAIL_ERROR_HPP + +#include +#include + +namespace boost { +namespace wintls { +namespace detail { + +inline boost::system::error_code get_last_error() noexcept { + return boost::system::error_code(static_cast(GetLastError()), boost::system::system_category()); +} + +inline void throw_last_error(const char* msg) { + throw boost::system::system_error(get_last_error(), msg); +} + +inline void throw_last_error() { + throw boost::system::system_error(get_last_error()); +} + +inline void throw_error(const boost::system::error_code& ec) { + throw boost::system::system_error(ec); +} + +inline void throw_error(const boost::system::error_code& ec, const char* msg) { + throw boost::system::system_error(ec, msg); +} + +} // namespace detail +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_DETAIL_ERROR_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/handshake_input_buffers.hpp b/third-party/boost-wintls/include/boost/wintls/detail/handshake_input_buffers.hpp new file mode 100644 index 00000000000..2de324b72de --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/handshake_input_buffers.hpp @@ -0,0 +1,31 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_HANDSHAKE_INPUT_BUFFERS_HPP +#define BOOST_WINTLS_DETAIL_HANDSHAKE_INPUT_BUFFERS_HPP + +#include + +namespace boost { +namespace wintls { +namespace detail { + +class handshake_input_buffers : public sspi_buffer_sequence<2> { +public: + handshake_input_buffers() + : sspi_buffer_sequence(std::array { + SECBUFFER_TOKEN, + SECBUFFER_EMPTY + }) { + } +}; + +} // namespace detail +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_DETAIL_HANDSHAKE_INPUT_BUFFERS_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/handshake_output_buffers.hpp b/third-party/boost-wintls/include/boost/wintls/detail/handshake_output_buffers.hpp new file mode 100644 index 00000000000..9c04992e957 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/handshake_output_buffers.hpp @@ -0,0 +1,30 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_HANDSHAKE_OUTPUT_BUFFERS_HPP +#define BOOST_WINTLS_DETAIL_HANDSHAKE_OUTPUT_BUFFERS_HPP + +#include + +namespace boost { +namespace wintls { +namespace detail { + +class handshake_output_buffers : public sspi_buffer_sequence<1> { +public: + handshake_output_buffers() + : sspi_buffer_sequence(std::array { + SECBUFFER_TOKEN + }) { + } +}; + +} // namespace detail +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_DETAIL_HANDSHAKE_OUTPUT_BUFFERS_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/shutdown_buffers.hpp b/third-party/boost-wintls/include/boost/wintls/detail/shutdown_buffers.hpp new file mode 100644 index 00000000000..193167e4af7 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/shutdown_buffers.hpp @@ -0,0 +1,38 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_SHUTDOWN_BUFFERS_HPP +#define BOOST_WINTLS_DETAIL_SHUTDOWN_BUFFERS_HPP + +#include + +#include + +namespace boost { +namespace wintls { +namespace detail { + +class shutdown_buffers : public sspi_buffer_sequence<1> { +public: + shutdown_buffers() + : sspi_buffer_sequence(std::array { + SECBUFFER_TOKEN + }) { + + buffers_[0].pvBuffer = &shutdown_type; + buffers_[0].cbBuffer = sizeof(shutdown_type); + } + +private: + std::uint32_t shutdown_type = SCHANNEL_SHUTDOWN; +}; + +} // namespace detail +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_DETAIL_SHUTDOWN_BUFFERS_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/sspi_buffer_sequence.hpp b/third-party/boost-wintls/include/boost/wintls/detail/sspi_buffer_sequence.hpp new file mode 100644 index 00000000000..3f4e90246b4 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/sspi_buffer_sequence.hpp @@ -0,0 +1,90 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_WINTLS_DETAIL_SSPI_BUFFER_SEQUENCE_HPP +#define BOOST_WINTLS_DETAIL_SSPI_BUFFER_SEQUENCE_HPP + +#include +#include + +#include + +#include + +namespace boost { +namespace wintls { +namespace detail { + +class sspi_buffer : public SecBuffer { +public: + sspi_buffer(unsigned long type) + : SecBuffer({0, type, nullptr}) { + static_assert(sizeof(*this) == sizeof(SecBuffer), "Invalid SecBuffer"); + } + + operator net::const_buffer() const { + return net::const_buffer(pvBuffer, cbBuffer); + } + + operator net::mutable_buffer() { + return net::mutable_buffer(pvBuffer, cbBuffer); + } +}; + +template +class sspi_buffer_sequence { +public: + using array_type = std::array; + using iterator = typename array_type::iterator; + using const_iterator = typename array_type::const_iterator; + + PSecBufferDesc desc() { + return &sec_buffer_desc_; + } + + iterator begin() { + return buffers_.begin(); + } + + const_iterator begin() const { + return buffers_.begin(); + } + + iterator end() { + return buffers_.end(); + } + + const_iterator end() const { + return buffers_.end(); + } + + sspi_buffer& operator[](size_t i) { + return buffers_[i]; + } + + const sspi_buffer& operator[](size_t i) const { + return buffers_[i]; + } + +protected: + sspi_buffer_sequence(const std::array& buffers) + : buffers_(buffers) { + sec_buffer_desc_.ulVersion = SECBUFFER_VERSION; + sec_buffer_desc_.cBuffers = N; + sec_buffer_desc_.pBuffers = buffers_.data(); + } + + std::array buffers_; + +private: + SecBufferDesc sec_buffer_desc_; +}; + +} // namespace detail +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_DETAIL_SSPI_BUFFER_SEQUENCE_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/sspi_context_buffer.hpp b/third-party/boost-wintls/include/boost/wintls/detail/sspi_context_buffer.hpp new file mode 100644 index 00000000000..ee610bd58bb --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/sspi_context_buffer.hpp @@ -0,0 +1,65 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_SSPI_CONTEXT_BUFFER_HPP +#define BOOST_WINTLS_DETAIL_SSPI_CONTEXT_BUFFER_HPP + +#include +#include + +namespace boost { +namespace wintls { +namespace detail { + +class sspi_context_buffer { + +public: + sspi_context_buffer() = default; + + sspi_context_buffer(const sspi_context_buffer&) = delete; + sspi_context_buffer& operator=(const sspi_context_buffer&) = delete; + + sspi_context_buffer(sspi_context_buffer&& other) { + buffer_ = other.buffer_; + other.buffer_ = net::const_buffer{}; + } + + sspi_context_buffer& operator=(sspi_context_buffer&& other) { + buffer_ = other.buffer_; + other.buffer_ = net::const_buffer{}; + return *this; + } + + sspi_context_buffer(const void* ptr, unsigned long size) + : buffer_(ptr, size) { + } + + ~sspi_context_buffer() { + detail::sspi_functions::FreeContextBuffer(const_cast(buffer_.data())); + } + + net::const_buffer asio_buffer() const { + return buffer_; + } + + std::size_t size() const { + return buffer_.size(); + } + + std::size_t empty() const { + return buffer_.size() == 0; + } + +private: + net::const_buffer buffer_; +}; + +} // namespace detail +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_DETAIL_SSPI_CONTEXT_BUFFER_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/sspi_decrypt.hpp b/third-party/boost-wintls/include/boost/wintls/detail/sspi_decrypt.hpp new file mode 100644 index 00000000000..4349205b9bc --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/sspi_decrypt.hpp @@ -0,0 +1,115 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_SSPI_DECRYPT_HPP +#define BOOST_WINTLS_DETAIL_SSPI_DECRYPT_HPP + +#include +#include +#include +#include + +#include +#include + +namespace boost { +namespace wintls { +namespace detail { + +class sspi_decrypt { +public: + enum class state { + data_needed, + data_available, + error + }; + + sspi_decrypt(ctxt_handle& ctxt_handle) + : size_decrypted(0) + , input_buffer(net::buffer(encrypted_data_)) + , ctxt_handle_(ctxt_handle) + , last_error_(SEC_E_OK) { + buffers_[0].pvBuffer = encrypted_data_.data(); + } + + template + state operator()(const MutableBufferSequence& output_buffers) { + if (!decrypted_data_.empty()) { + size_decrypted = decrypted_data_.get(output_buffers); + return state::data_available; + } + + if (buffers_[0].cbBuffer == 0) { + input_buffer = net::buffer(encrypted_data_); + return state::data_needed; + } + + buffers_[0].BufferType = SECBUFFER_DATA; + buffers_[1].BufferType = SECBUFFER_EMPTY; + buffers_[2].BufferType = SECBUFFER_EMPTY; + buffers_[3].BufferType = SECBUFFER_EMPTY; + + input_buffer = net::buffer(encrypted_data_) + buffers_[0].cbBuffer; + const auto size = buffers_[0].cbBuffer; + last_error_ = detail::sspi_functions::DecryptMessage(ctxt_handle_.get(), buffers_.desc(), 0, nullptr); + + if (last_error_ == SEC_E_INCOMPLETE_MESSAGE) { + buffers_[0].cbBuffer = size; + return state::data_needed; + } + + if (last_error_ != SEC_E_OK) { + return state::error; + } + + if (buffers_[1].BufferType == SECBUFFER_DATA) { + const auto data_ptr = reinterpret_cast(buffers_[1].pvBuffer); + const auto data_size = buffers_[1].cbBuffer; + size_decrypted = net::buffer_copy(output_buffers, net::buffer(data_ptr, data_size)); + if (size_decrypted < data_size) { + decrypted_data_.fill(net::buffer(data_ptr + size_decrypted, data_size - size_decrypted)); + } + } + + if (buffers_[3].BufferType == SECBUFFER_EXTRA) { + const auto extra_size = buffers_[3].cbBuffer; + std::memmove(encrypted_data_.data(), buffers_[3].pvBuffer, extra_size); + buffers_[0].cbBuffer = extra_size; + } else { + buffers_[0].cbBuffer = 0; + } + + return state::data_available; + } + + void size_read(std::size_t size) { + buffers_[0].cbBuffer += static_cast(size); + input_buffer = net::buffer(encrypted_data_) + buffers_[0].cbBuffer; + } + + std::size_t size_decrypted; + net::mutable_buffer input_buffer; + + boost::system::error_code last_error() const { + return error::make_error_code(last_error_); + } + +private: + static constexpr std::size_t buffer_size = 0x10000; + + ctxt_handle& ctxt_handle_; + SECURITY_STATUS last_error_; + decrypt_buffers buffers_; + std::array encrypted_data_; + decrypted_data_buffer decrypted_data_; +}; + +} // namespace detail +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_DETAIL_SSPI_DECRYPT_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/sspi_encrypt.hpp b/third-party/boost-wintls/include/boost/wintls/detail/sspi_encrypt.hpp new file mode 100644 index 00000000000..fd0a777f879 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/sspi_encrypt.hpp @@ -0,0 +1,54 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_SSPI_ENCRYPT_HPP +#define BOOST_WINTLS_DETAIL_SSPI_ENCRYPT_HPP + +#include +#include + +namespace boost { +namespace wintls { +namespace detail { + +class sspi_encrypt { +public: + sspi_encrypt(ctxt_handle& ctxt_handle) + : buffers(ctxt_handle) + , ctxt_handle_(ctxt_handle) { + } + + template + std::size_t operator()(const ConstBufferSequence& buf, boost::system::error_code& ec) { + SECURITY_STATUS sc = SEC_E_OK; + + std::size_t size_encrypted = buffers(buf, sc); + if (sc != SEC_E_OK) { + ec = error::make_error_code(sc); + return 0; + } + + sc = detail::sspi_functions::EncryptMessage(ctxt_handle_.get(), 0, buffers.desc(), 0); + if (sc != SEC_E_OK) { + ec = error::make_error_code(sc); + return 0; + } + + return size_encrypted; + } + + encrypt_buffers buffers; + +private: + ctxt_handle& ctxt_handle_; +}; + +} // namespace detail +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_DETAIL_SSPI_ENCRYPT_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/sspi_functions.hpp b/third-party/boost-wintls/include/boost/wintls/detail/sspi_functions.hpp new file mode 100644 index 00000000000..79d7c27e103 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/sspi_functions.hpp @@ -0,0 +1,123 @@ +// +// Copyright (c) 2020 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_SSPI_FUNCTIONS_HPP +#define BOOST_WINTLS_DETAIL_SSPI_FUNCTIONS_HPP + +#include + +namespace boost { +namespace wintls { +namespace detail { +namespace sspi_functions { + +inline SecurityFunctionTable* sspi_function_table() { + static SecurityFunctionTable* impl = InitSecurityInterface(); + // TODO: Figure out some way to signal this to the user instead of aborting + BOOST_ASSERT_MSG(impl != nullptr, "Unable to initialize SecurityFunctionTable"); + return impl; +} + +inline SECURITY_STATUS AcquireCredentialsHandle(SEC_CHAR* pPrincipal, + SEC_CHAR* pPackage, + unsigned long fCredentialUse, + void* pvLogonId, + void* pAuthData, + SEC_GET_KEY_FN pGetKeyFn, + void* pvGetKeyArgument, + PCredHandle phCredential, + PTimeStamp ptsExpiry) { + return sspi_function_table()->AcquireCredentialsHandle(pPrincipal, + pPackage, + fCredentialUse, + pvLogonId, + pAuthData, + pGetKeyFn, + pvGetKeyArgument, + phCredential, + ptsExpiry); +} + +inline SECURITY_STATUS DeleteSecurityContext(PCtxtHandle phContext) { + return sspi_function_table()->DeleteSecurityContext(phContext); +} + +inline SECURITY_STATUS InitializeSecurityContext(PCredHandle phCredential, + PCtxtHandle phContext, + SEC_CHAR* pTargetName, + unsigned long fContextReq, + unsigned long Reserved1, + unsigned long TargetDataRep, + PSecBufferDesc pInput, + unsigned long Reserved2, + PCtxtHandle phNewContext, + PSecBufferDesc pOutput, + unsigned long* pfContextAttr, + PTimeStamp ptsExpiry) { + return sspi_function_table()->InitializeSecurityContext(phCredential, + phContext, + pTargetName, + fContextReq, + Reserved1, + TargetDataRep, + pInput, + Reserved2, + phNewContext, + pOutput, + pfContextAttr, + ptsExpiry); +} + +inline SECURITY_STATUS FreeContextBuffer(PVOID pvContextBuffer) { + return sspi_function_table()->FreeContextBuffer(pvContextBuffer); +} + +inline SECURITY_STATUS DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, unsigned long MessageSeqNo, unsigned long* pfQOP) { + return sspi_function_table()->DecryptMessage(phContext, pMessage, MessageSeqNo, pfQOP); +} + +inline SECURITY_STATUS QueryContextAttributes(PCtxtHandle phContext, unsigned long ulAttribute, void* pBuffer) { + return sspi_function_table()->QueryContextAttributes(phContext, ulAttribute, pBuffer); +} + +inline SECURITY_STATUS EncryptMessage(PCtxtHandle phContext, unsigned long fQOP, PSecBufferDesc pMessage, unsigned long MessageSeqNo) { + return sspi_function_table()->EncryptMessage(phContext, fQOP, pMessage, MessageSeqNo); +} + +inline SECURITY_STATUS FreeCredentialsHandle(PCredHandle phCredential) { + return sspi_function_table()->FreeCredentialsHandle(phCredential); +} + +inline SECURITY_STATUS ApplyControlToken(PCtxtHandle phContext, PSecBufferDesc pInput) { + return sspi_function_table()->ApplyControlToken(phContext, pInput); +} + +inline SECURITY_STATUS AcceptSecurityContext(PCredHandle phCredential, + PCtxtHandle phContext, + PSecBufferDesc pInput, + unsigned long fContextReq, + unsigned long TargetDataRep, + PCtxtHandle phNewContext, + PSecBufferDesc pOutput, + unsigned long* pfContextAttr, + PTimeStamp ptsExpiry) { + return sspi_function_table()->AcceptSecurityContext(phCredential, + phContext, + pInput, + fContextReq, + TargetDataRep, + phNewContext, + pOutput, + pfContextAttr, + ptsExpiry); +} +} // namespace sspi_functions +} // namespace detail +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_DETAIL_SSPI_FUNCTIONS_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/sspi_handshake.hpp b/third-party/boost-wintls/include/boost/wintls/detail/sspi_handshake.hpp new file mode 100644 index 00000000000..6315513e883 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/sspi_handshake.hpp @@ -0,0 +1,315 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_SSPI_HANDSHAKE_HPP +#define BOOST_WINTLS_DETAIL_SSPI_HANDSHAKE_HPP + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +namespace boost { +namespace wintls { +namespace detail { + +class sspi_handshake { +public: + // TODO: enhancement: done_with_data and error_with_data can be removed if + // we move the manual validate logic out of the handshake loop. + enum class state { + data_needed, // data needs to be read from peer + data_available, // data needs to be write to peer + done_with_data, // handshake success, but there is leftover data to be written to peer + error_with_data, // handshake error, but there is leftover data to be written to peer + done, // handshake success + error // handshake error + }; + + sspi_handshake(context& context, ctxt_handle& ctxt_handle, cred_handle& cred_handle) + : context_(context) + , ctxt_handle_(ctxt_handle) + , cred_handle_(cred_handle) + , last_error_(SEC_E_OK) + , in_buffer_(net::buffer(input_data_)) { + input_buffers_[0].pvBuffer = reinterpret_cast(input_data_.data()); + } + + void operator()(handshake_type type) { + handshake_type_ = type; + + SCHANNEL_CRED creds{}; + creds.dwVersion = SCHANNEL_CRED_VERSION; + creds.grbitEnabledProtocols = static_cast(context_.method_); + creds.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION | SCH_CRED_NO_DEFAULT_CREDS; + // If revocation checking is enables, specify SCH_CRED_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT + // to cause the TLS certificate status request extension (commonly known as OCSP stapling) + // to be sent. This flag matches the CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT + // flag that we pass to the CertGetCertificateChain calls during our manual authentication. + if (check_revocation_) { + creds.dwFlags |= SCH_CRED_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT; + } + + auto usage = [this]() { + switch (handshake_type_) { + case handshake_type::client: + return SECPKG_CRED_OUTBOUND; + case handshake_type::server: + return SECPKG_CRED_INBOUND; + } + BOOST_UNREACHABLE_RETURN(0); + }(); + + auto server_cert = context_.server_cert(); + if (handshake_type_ == handshake_type::server && server_cert != nullptr) { + creds.cCreds = 1; + creds.paCred = &server_cert; + } + + // TODO: rename server_cert field since it is also used for client cert. + // Note: if client cert is set, sspi will auto validate server cert with it. + // Even though verify_server_certificate_ in context is set to false. + if (handshake_type_ == handshake_type::client && server_cert != nullptr) { + creds.cCreds = 1; + creds.paCred = &server_cert; + } + + TimeStamp expiry; + last_error_ = detail::sspi_functions::AcquireCredentialsHandle(nullptr, + const_cast(UNISP_NAME), + static_cast(usage), + nullptr, + &creds, + nullptr, + nullptr, + cred_handle_.get(), + &expiry); + if (last_error_ != SEC_E_OK) { + return; + } + + switch(handshake_type_) { + case handshake_type::client: { + DWORD out_flags = 0; + + handshake_output_buffers buffers; + last_error_ = detail::sspi_functions::InitializeSecurityContext(cred_handle_.get(), + nullptr, + const_cast(server_hostname_.c_str()), + client_context_flags, + 0, + SECURITY_NATIVE_DREP, + nullptr, + 0, + ctxt_handle_.get(), + buffers.desc(), + &out_flags, + nullptr); + if (buffers[0].cbBuffer != 0 && buffers[0].pvBuffer != nullptr) { + out_buffer_ = sspi_context_buffer{buffers[0].pvBuffer, buffers[0].cbBuffer}; + } + break; + } + case handshake_type::server: + last_error_ = SEC_I_CONTINUE_NEEDED; + } + } + + state operator()() { + if (last_error_ != SEC_I_CONTINUE_NEEDED && last_error_ != SEC_E_INCOMPLETE_MESSAGE) { + return state::error; + } + if (!out_buffer_.empty()) { + return state::data_available; + } + if (input_buffers_[0].cbBuffer == 0) { + return state::data_needed; + } + + handshake_output_buffers out_buffers; + DWORD out_flags = 0; + + input_buffers_[1].BufferType = SECBUFFER_EMPTY; + input_buffers_[1].pvBuffer = nullptr; + input_buffers_[1].cbBuffer = 0; + + switch(handshake_type_) { + case handshake_type::client: + last_error_ = detail::sspi_functions::InitializeSecurityContext(cred_handle_.get(), + ctxt_handle_.get(), + const_cast(server_hostname_.c_str()), + client_context_flags, + 0, + SECURITY_NATIVE_DREP, + input_buffers_.desc(), + 0, + nullptr, + out_buffers.desc(), + &out_flags, + nullptr); + break; + case handshake_type::server: { + TimeStamp expiry; + DWORD f_context_req = server_context_flags; + if (context_.verify_server_certificate_) { + f_context_req |= ASC_REQ_MUTUAL_AUTH; + } + last_error_ = detail::sspi_functions::AcceptSecurityContext(cred_handle_.get(), + ctxt_handle_ ? ctxt_handle_.get() : nullptr, + input_buffers_.desc(), + f_context_req, + SECURITY_NATIVE_DREP, + ctxt_handle_.get(), + out_buffers.desc(), + &out_flags, + &expiry); + } + } + if (input_buffers_[1].BufferType == SECBUFFER_EXTRA) { + // Some data needs to be reused for the next call, move that to the front for reuse + const auto previous_size = input_buffers_[0].cbBuffer; + const auto extra_size = input_buffers_[1].cbBuffer; + const auto extra_data_begin = input_data_.begin() + previous_size - extra_size; + const auto extra_data_end = input_data_.begin() + previous_size; + + std::move(extra_data_begin, extra_data_end, input_data_.begin()); + input_buffers_[0].cbBuffer = extra_size; + in_buffer_ = net::buffer(input_data_) + extra_size; + + BOOST_ASSERT_MSG(in_buffer_.size() > 0, "buffer not large enough for tls handshake message"); + return state::data_needed; + } else if (last_error_ == SEC_E_INCOMPLETE_MESSAGE) { + BOOST_ASSERT_MSG(in_buffer_.size() > 0, "buffer not large enough for tls handshake message"); + return state::data_needed; + } else { + input_buffers_[0].cbBuffer = 0; + in_buffer_ = net::buffer(input_data_); + } + + bool has_buffer_output = out_buffers[0].cbBuffer != 0 && out_buffers[0].pvBuffer != nullptr; + if(has_buffer_output){ + out_buffer_ = sspi_context_buffer{out_buffers[0].pvBuffer, out_buffers[0].cbBuffer}; + } + + switch (last_error_) { + case SEC_I_CONTINUE_NEEDED: { + return has_buffer_output ? state::data_available : state::data_needed; + } + case SEC_E_OK: { + // sspi handshake ok. perform manual auth here. + manual_auth(); + if (handshake_type_ == handshake_type::client) { + if (last_error_ != SEC_E_OK) { + return state::error; + } + } else { + // Note: we are not checking (out_flags & ASC_RET_MUTUAL_AUTH) is true, + // but instead rely on our manual cert validation to establish trust. + // "The AcceptSecurityContext function will return ASC_RET_MUTUAL_AUTH if a + // client certificate was received from the client and schannel was + // successfully able to map the certificate to a user account in AD" + // As observed in tests, this check would wrongly reject openssl client with valid certificate. + + // AcceptSecurityContext documentation: + // "If function generated an output token, the token must be sent to the client process." + // This happens when client cert is requested. + if (has_buffer_output) { + return last_error_ == SEC_E_OK ? state::done_with_data : state::error_with_data; + } + } + return state::done; + } + + case SEC_I_INCOMPLETE_CREDENTIALS: + BOOST_ASSERT_MSG(false, "client authentication not implemented"); + + case SEC_I_RENEGOTIATE: + BOOST_ASSERT_MSG(false, "renegotiation not implemented"); + + default: + return state::error; + } + } + + void size_written(std::size_t size) { + BOOST_VERIFY(size == out_buffer_.size()); + out_buffer_ = sspi_context_buffer{}; + } + + void size_read(std::size_t size) { + input_buffers_[0].cbBuffer += static_cast(size); + in_buffer_ = net::buffer(input_data_) + input_buffers_[0].cbBuffer; + } + + net::const_buffer out_buffer() { + return out_buffer_.asio_buffer(); + } + + net::mutable_buffer in_buffer() { + return in_buffer_; + } + + boost::system::error_code last_error() const { + return error::make_error_code(last_error_); + } + + void set_server_hostname(const std::string& hostname) { + server_hostname_ = hostname; + } + + void set_certificate_revocation_check(bool check) { + check_revocation_ = check; + } + +private: + SECURITY_STATUS manual_auth(){ + if (!context_.verify_server_certificate_) { + return SEC_E_OK; + } + const CERT_CONTEXT* ctx_ptr = nullptr; + last_error_ = detail::sspi_functions::QueryContextAttributes(ctxt_handle_.get(), SECPKG_ATTR_REMOTE_CERT_CONTEXT, &ctx_ptr); + if (last_error_ != SEC_E_OK) { + return last_error_; + } + + cert_context_ptr remote_cert{ctx_ptr}; + + last_error_ = static_cast(context_.verify_certificate(remote_cert.get(), server_hostname_, check_revocation_)); + if (last_error_ != SEC_E_OK) { + return last_error_; + } + return last_error_; + } + + context& context_; + ctxt_handle& ctxt_handle_; + cred_handle& cred_handle_; + + SECURITY_STATUS last_error_; + handshake_type handshake_type_ = handshake_type::client; + std::array input_data_; + sspi_context_buffer out_buffer_; + net::mutable_buffer in_buffer_; + handshake_input_buffers input_buffers_; + std::string server_hostname_; + bool check_revocation_ = false; +}; + +} // namespace detail +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_DETAIL_SSPI_HANDSHAKE_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/sspi_sec_handle.hpp b/third-party/boost-wintls/include/boost/wintls/detail/sspi_sec_handle.hpp new file mode 100644 index 00000000000..51f293a35e1 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/sspi_sec_handle.hpp @@ -0,0 +1,59 @@ +// +// Copyright (c) 2020 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_SSPI_SEC_HANDLE_HPP +#define BOOST_WINTLS_DETAIL_SSPI_SEC_HANDLE_HPP + +#include + +namespace boost { +namespace wintls { +namespace detail { + +template +class sspi_sec_handle { + +public: + sspi_sec_handle() = default; + sspi_sec_handle(sspi_sec_handle&&) = delete; + sspi_sec_handle& operator=(sspi_sec_handle&&) = delete; + + operator bool() { + return handle_.dwLower != 0 || handle_.dwUpper != 0; + } + + T* get() { + return &handle_; + } + +private: + T handle_{0, 0}; +}; + +class ctxt_handle : public sspi_sec_handle { +public: + ~ctxt_handle() { + if (*this) { + detail::sspi_functions::DeleteSecurityContext(get()); + } + } +}; + +class cred_handle : public sspi_sec_handle { +public: + ~cred_handle() { + if (*this) { + detail::sspi_functions::FreeCredentialsHandle(get()); + } + } +}; + +} // namespace detail +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_DETAIL_SSPI_SEC_HANDLE_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/sspi_shutdown.hpp b/third-party/boost-wintls/include/boost/wintls/detail/sspi_shutdown.hpp new file mode 100644 index 00000000000..8983493ea75 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/sspi_shutdown.hpp @@ -0,0 +1,79 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_SSPI_SHUTDOWN_HPP +#define BOOST_WINTLS_DETAIL_SSPI_SHUTDOWN_HPP + +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace wintls { +namespace detail { + +class sspi_shutdown { +public: + sspi_shutdown(ctxt_handle& ctxt_handle, cred_handle& cred_handle) + : ctxt_handle_(ctxt_handle) + , cred_handle_(cred_handle) { + } + + boost::system::error_code operator()() { + shutdown_buffers buffers; + + SECURITY_STATUS sc = detail::sspi_functions::ApplyControlToken(ctxt_handle_.get(), buffers.desc()); + if (sc != SEC_E_OK) { + return error::make_error_code(sc); + } + + DWORD out_flags = 0; + sc = detail::sspi_functions::InitializeSecurityContext(cred_handle_.get(), + ctxt_handle_.get(), + nullptr, + client_context_flags, + 0, + SECURITY_NATIVE_DREP, + nullptr, + 0, + ctxt_handle_.get(), + buffers.desc(), + &out_flags, + nullptr); + if (sc != SEC_E_OK) { + return error::make_error_code(sc); + } + + buffer_ = sspi_context_buffer{buffers[0].pvBuffer, buffers[0].cbBuffer}; + return {}; + } + + net::const_buffer buffer() { + return buffer_.asio_buffer(); + } + + void size_written(std::size_t size) { + BOOST_VERIFY(size == buffer_.size()); + buffer_ = sspi_context_buffer{}; + } + +private: + ctxt_handle& ctxt_handle_; + cred_handle& cred_handle_; + sspi_context_buffer buffer_; +}; + +} // namespace detail +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_DETAIL_SSPI_SHUTDOWN_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/sspi_stream.hpp b/third-party/boost-wintls/include/boost/wintls/detail/sspi_stream.hpp new file mode 100644 index 00000000000..22c211ee951 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/sspi_stream.hpp @@ -0,0 +1,48 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_SSPI_STREAM_HPP +#define BOOST_WINTLS_DETAIL_SSPI_STREAM_HPP + +#include +#include +#include +#include +#include + +namespace boost { +namespace wintls { +namespace detail { + +class sspi_stream { +public: + sspi_stream(context& ctx) + : handshake(ctx, ctxt_handle_, cred_handle_) + , encrypt(ctxt_handle_) + , decrypt(ctxt_handle_) + , shutdown(ctxt_handle_, cred_handle_) { + } + + sspi_stream(sspi_stream&&) = delete; + sspi_stream& operator=(sspi_stream&&) = delete; + +private: + ctxt_handle ctxt_handle_; + cred_handle cred_handle_; + +public: + sspi_handshake handshake; + sspi_encrypt encrypt; + sspi_decrypt decrypt; + sspi_shutdown shutdown; +}; + +} // namespace detail +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_DETAIL_SSPI_STREAM_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/sspi_types.hpp b/third-party/boost-wintls/include/boost/wintls/detail/sspi_types.hpp new file mode 100644 index 00000000000..61ff23ef89b --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/sspi_types.hpp @@ -0,0 +1,34 @@ +// +// Copyright (c) 2020 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_SSPI_TYPES_HPP +#define BOOST_WINTLS_DETAIL_SSPI_TYPES_HPP + +#include + +#ifndef SECURITY_WIN32 +#define SECURITY_WIN32 +#define BOOST_WINTLS_SECURITY_WIN32_DEFINED +#endif // SECURITY_WIN32 + +#ifdef UNICODE +#undef UNICODE +#define BOOST_WINTLS_UNICODE_UNDEFINED +#endif // UNICODE + +#include +#include + +#ifdef BOOST_WINTLS_SECURITY_WIN32_DEFINED +#undef SECURITY_WIN32 +#endif // BOOST_WINTLS_SECURITY_WIN32_DEFINED + +#ifdef BOOST_WINTLS_UNICODE_UNDEFINED +#define UNICODE +#endif // BOOST_WINTLS_UNICODE_UNDEFINED + +#endif // BOOST_WINTLS_DETAIL_SSPI_TYPES_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/win32_crypto.hpp b/third-party/boost-wintls/include/boost/wintls/detail/win32_crypto.hpp new file mode 100644 index 00000000000..cd256a5dce2 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/win32_crypto.hpp @@ -0,0 +1,75 @@ +// +// Copyright (c) 2020 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_WIN32_CRYPTO_HPP +#define BOOST_WINTLS_DETAIL_WIN32_CRYPTO_HPP + +#include +#include + +#include + +namespace boost { +namespace wintls { +namespace detail { + +inline std::vector crypt_string_to_binary(const net::const_buffer& crypt_string) { + DWORD size = 0; + if (!CryptStringToBinaryA(reinterpret_cast(crypt_string.data()), + static_cast(crypt_string.size()), + 0, + nullptr, + &size, + nullptr, + nullptr)) { + throw_last_error("CryptStringToBinaryA"); + } + + std::vector data(size); + if (!CryptStringToBinaryA(reinterpret_cast(crypt_string.data()), + static_cast(crypt_string.size()), + 0, + data.data(), + &size, + nullptr, + nullptr)) { + throw_last_error("CryptStringToBinaryA"); + } + return data; +} + +inline std::vector crypt_decode_object_ex(const net::const_buffer& crypt_object, LPCSTR type) { + DWORD size = 0; + if (!CryptDecodeObjectEx(X509_ASN_ENCODING, + type, + reinterpret_cast(crypt_object.data()), + static_cast(crypt_object.size()), + 0, + nullptr, + nullptr, + &size)) { + throw_last_error("CryptDecodeObjectEx"); + } + std::vector data(size); + if (!CryptDecodeObjectEx(X509_ASN_ENCODING, + type, + reinterpret_cast(crypt_object.data()), + static_cast(crypt_object.size()), + 0, + nullptr, + data.data(), + &size)) { + throw_last_error("CryptDecodeObjectEx"); + } + return data; +} + +} // namespace detail +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_DETAIL_WIN32_CRYPTO_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/detail/win_types.hpp b/third-party/boost-wintls/include/boost/wintls/detail/win_types.hpp new file mode 100644 index 00000000000..aa869b0b1f2 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/detail/win_types.hpp @@ -0,0 +1,31 @@ +// +// Copyright (c) 2020 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_DETAIL_WIN_TYPES_H +#define BOOST_WINTLS_DETAIL_WIN_TYPES_H + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#define BOOST_WINTLS_WIN32_LEAN_AND_MEAN_DEFINED +#endif // WIN32_LEAN_AND_MEAN + +#ifndef NOMINMAX +#define NOMINMAX +#define BOOST_WINTLS_NOMINMAX_DEFINED +#endif // NOMINMAX + +#include + +#ifdef BOOST_WINTLS_WIN32_LEAN_AND_MEAN_DEFINED +#undef WIN32_LEAN_AND_MEAN +#endif // BOOST_WINTLS_WIN32_LEAN_AND_MEAN_DEFINED + +#ifdef BOOST_WINTLS_NOMINMAX_DEFINED +#undef NOMINMAX +#endif // BOOST_WINTLS_NOMINMAX_DEFINED + +#endif // BOOST_WINTLS_DETAIL_WIN_TYPES_H diff --git a/third-party/boost-wintls/include/boost/wintls/error.hpp b/third-party/boost-wintls/include/boost/wintls/error.hpp new file mode 100644 index 00000000000..11df01488c7 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/error.hpp @@ -0,0 +1,26 @@ +// +// Copyright (c) 2020 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_ERROR_HPP +#define BOOST_WINTLS_ERROR_HPP + +#include +#include + +namespace boost { +namespace wintls { +namespace error { + +inline boost::system::error_code make_error_code(SECURITY_STATUS sc) { + return boost::system::error_code(static_cast(sc), boost::system::system_category()); +} + +} // namespace error +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_ERROR_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/file_format.hpp b/third-party/boost-wintls/include/boost/wintls/file_format.hpp new file mode 100644 index 00000000000..42de9757689 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/file_format.hpp @@ -0,0 +1,26 @@ +// +// Copyright (c) 2020 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_FILE_FORMAT_HPP +#define BOOST_WINTLS_FILE_FORMAT_HPP + +namespace boost { +namespace wintls { + +/// File format types. +enum class file_format { + /// ASN.1 file. + asn1, + + /// PEM file. + pem +}; + +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_FILE_FORMAT_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/handshake_type.hpp b/third-party/boost-wintls/include/boost/wintls/handshake_type.hpp new file mode 100644 index 00000000000..8eb8588b3b2 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/handshake_type.hpp @@ -0,0 +1,26 @@ +// +// Copyright (c) 2020 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_HANDSHAKE_TYPE_HPP +#define BOOST_WINTLS_HANDSHAKE_TYPE_HPP + +namespace boost { +namespace wintls { + +/// Different handshake types. +enum class handshake_type { + /// Perform handshaking as a client. + client, + + /// Perform handshaking as a server. + server +}; + +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_HANDSHAKE_TYPE_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/method.hpp b/third-party/boost-wintls/include/boost/wintls/method.hpp new file mode 100644 index 00000000000..efa83a41495 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/method.hpp @@ -0,0 +1,94 @@ +// +// Copyright (c) 2020 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_METHOD_HPP +#define BOOST_WINTLS_METHOD_HPP + +#include + +#ifndef SP_PROT_TLS1_1_SERVER +#define SP_PROT_TLS1_1_SERVER 0x100 +#endif + +#ifndef SP_PROT_TLS1_1_CLIENT +#define SP_PROT_TLS1_1_CLIENT 0x200 +#endif + +#ifndef SP_PROT_TLS1_2_SERVER +#define SP_PROT_TLS1_2_SERVER 0x400 +#endif + +#ifndef SP_PROT_TLS1_2_CLIENT +#define SP_PROT_TLS1_2_CLIENT 0x800 +#endif + +#ifndef SP_PROT_TLS1_3_SERVER +#define SP_PROT_TLS1_3_SERVER 0x1000 +#endif + +#ifndef SP_PROT_TLS1_3_CLIENT +#define SP_PROT_TLS1_3_CLIENT 0x2000 +#endif + +namespace boost { +namespace wintls { + +/// Different methods supported by a context. +enum class method { + /// Operating system defaults. + system_default = 0, + + /// Generic SSL version 3. + sslv3 = SP_PROT_SSL3_SERVER | SP_PROT_SSL3_CLIENT, + + /// SSL version 3 client. + sslv3_client = SP_PROT_SSL3_CLIENT, + + /// SSL version 3 server. + sslv3_server = SP_PROT_SSL3_SERVER, + + /// Generic TLS version 1. + tlsv1 = SP_PROT_TLS1_SERVER | SP_PROT_TLS1_CLIENT, + + /// TLS version 1 client. + tlsv1_client = SP_PROT_TLS1_CLIENT, + + /// TLS version 1 server. + tlsv1_server = SP_PROT_TLS1_SERVER, + + /// Generic TLS version 1.1. + tlsv11 = SP_PROT_TLS1_1_SERVER | SP_PROT_TLS1_1_CLIENT, + + /// TLS version 1.1 client. + tlsv11_client = SP_PROT_TLS1_1_CLIENT, + + /// TLS version 1.1 server. + tlsv11_server = SP_PROT_TLS1_1_SERVER, + + /// Generic TLS version 1.2. + tlsv12 = SP_PROT_TLS1_2_SERVER | SP_PROT_TLS1_2_CLIENT, + + /// TLS version 1.2 client. + tlsv12_client = SP_PROT_TLS1_2_CLIENT, + + /// TLS version 1.2 server. + tlsv12_server = SP_PROT_TLS1_2_SERVER, + + /// Generic TLS version 1.3. + tlsv13 = SP_PROT_TLS1_3_SERVER | SP_PROT_TLS1_3_CLIENT, + + /// TLS version 1.3 client. + tlsv13_client = SP_PROT_TLS1_3_CLIENT, + + /// TLS version 1.3 server. + tlsv13_server = SP_PROT_TLS1_3_SERVER +}; + +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_METHOD_HPP diff --git a/third-party/boost-wintls/include/boost/wintls/stream.hpp b/third-party/boost-wintls/include/boost/wintls/stream.hpp new file mode 100644 index 00000000000..0e1e0747137 --- /dev/null +++ b/third-party/boost-wintls/include/boost/wintls/stream.hpp @@ -0,0 +1,479 @@ +// +// Copyright (c) 2020 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_STREAM_HPP +#define BOOST_WINTLS_STREAM_HPP + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +namespace boost { +namespace wintls { + +/** Provides stream-oriented functionality using Windows SSPI/Schannel. + * + * The stream class template provides asynchronous and blocking + * stream-oriented functionality using Windows SSPI/Schannel. + * + * @tparam NextLayer The type representing the next layer, to which + * data will be read and written during operations. For synchronous + * operations, the type must support the SyncStream concept. + * For asynchronous operations, the type must support the + * AsyncStream concept. + */ +template +class stream { +public: + /// The type of the next layer. + using next_layer_type = typename std::remove_reference::type; + + /// The type of the executor associated with the object. + using executor_type = typename std::remove_reference::type::executor_type; + + /** Construct a stream. + * + * This constructor creates a stream and initialises the underlying + * stream object. + * + * @param arg The argument to be passed to initialise the + * underlying stream. + * @param ctx The wintls @ref context to be used for the stream. + */ + template + stream(Arg&& arg, context& ctx) + : next_layer_(std::forward(arg)) + , sspi_stream_(std::make_unique(ctx)) { + } + + /** Get the executor associated with the object. + * + * This function may be used to obtain the executor object that the + * stream uses to dispatch handlers for asynchronous operations. + * + * @return A copy of the executor that stream will use to dispatch + * handlers. + */ + executor_type get_executor() { + return next_layer().get_executor(); + } + + /** Get a reference to the next layer. + * + * This function returns a reference to the next layer in a stack of + * stream layers. + * + * @return A reference to the next layer in the stack of stream + * layers. Ownership is not transferred to the caller. + */ + const next_layer_type& next_layer() const { + return next_layer_; + } + + /** Get a reference to the next layer. + * + * This function returns a reference to the next layer in a stack of + * stream layers. + * + * @return A reference to the next layer in the stack of stream + * layers. Ownership is not transferred to the caller. + */ + next_layer_type& next_layer() { + return next_layer_; + } + + /** Set SNI hostname + * + * Sets the SNI hostname the client will use for requesting and + * validating the server certificate. + * + * Only used when handshake is performed as @ref + * handshake_type::client + * + * @param hostname The hostname to use in certificate validation + */ + void set_server_hostname(const std::string& hostname) { + sspi_stream_->handshake.set_server_hostname(hostname); + } + + /** Set revocation checking + * + * Enable revocation checking for remote certificates. + * + * Enabling this also causes the TLS certificate status request extension + * to be sent during the handshake. (I.e. we request OCSP stapling from the remote.) + * + * @param check Whether to enable revocation checking + */ + void set_certificate_revocation_check(bool check) { + sspi_stream_->handshake.set_certificate_revocation_check(check); + } + + /** Perform TLS handshaking. + * + * This function is used to perform TLS handshaking on the + * stream. The function call will block until handshaking is + * complete or an error occurs. + * + * @param type The @ref handshake_type to be performed, i.e. client + * or server. + * @param ec Set to indicate what error occurred, if any. + */ + void handshake(handshake_type type, boost::system::error_code& ec) { + sspi_stream_->handshake(type); + + detail::sspi_handshake::state state; + while((state = sspi_stream_->handshake()) != detail::sspi_handshake::state::done) { + switch (state) { + case detail::sspi_handshake::state::data_needed: { + std::size_t size_read = next_layer_.read_some(sspi_stream_->handshake.in_buffer(), ec); + if (ec) { + return; + } + sspi_stream_->handshake.size_read(size_read); + continue; + } + case detail::sspi_handshake::state::data_available: { + std::size_t size_written = net::write(next_layer_, sspi_stream_->handshake.out_buffer(), ec); + if (ec) { + return; + } + sspi_stream_->handshake.size_written(size_written); + continue; + } + case detail::sspi_handshake::state::error: + ec = sspi_stream_->handshake.last_error(); + return; + case detail::sspi_handshake::state::done_with_data:{ + std::size_t size_written = net::write(next_layer_, sspi_stream_->handshake.out_buffer(), ec); + if (ec) { + return; + } + sspi_stream_->handshake.size_written(size_written); + return; + } + case detail::sspi_handshake::state::error_with_data:{ + std::size_t size_written = net::write(next_layer_, sspi_stream_->handshake.out_buffer(), ec); + if (ec) { + return; + } + sspi_stream_->handshake.size_written(size_written); + return; + } + case detail::sspi_handshake::state::done: + BOOST_UNREACHABLE_RETURN(0); + } + } + } + + /** Perform TLS handshaking. + * + * This function is used to perform TLS handshaking on the + * stream. The function call will block until handshaking is + * complete or an error occurs. + * + * @param type The @ref handshake_type to be performed, i.e. client + * or server. + * + * @throws boost::system::system_error Thrown on failure. + */ + void handshake(handshake_type type) { + boost::system::error_code ec{}; + handshake(type, ec); + if (ec) { + detail::throw_error(ec); + } + } + + /** Start an asynchronous TLS handshake. + * + * This function is used to asynchronously perform an TLS + * handshake on the stream. This function call always returns + * immediately. + * + * @param type The @ref handshake_type to be performed, i.e. client + * or server. + * @param handler The handler to be called when the operation + * completes. The implementation takes ownership of the handler by + * performing a decay-copy. The handler must be invocable with this + * signature: + * @code + * void handler( + * boost::system::error_code // Result of operation. + * ); + * @endcode + * + * @note Regardless of whether the asynchronous operation completes + * immediately or not, the handler will not be invoked from within + * this function. Invocation of the handler will be performed in a + * manner equivalent to using `net::post`. + */ + template + auto async_handshake(handshake_type type, CompletionToken&& handler) { + return boost::asio::async_compose( + detail::async_handshake{next_layer_, sspi_stream_->handshake, type}, handler); + } + + /** Read some data from the stream. + * + * This function is used to read data from the stream. The function + * call will block until one or more bytes of data has been read + * successfully, or until an error occurs. + * + * @param ec Set to indicate what error occurred, if any. + * @param buffers The buffers into which the data will be read. + * + * @returns The number of bytes read. + * + * @note The `read_some` operation may not read all of the requested + * number of bytes. Consider using the `net::read` function if you + * need to ensure that the requested amount of data is read before + * the blocking operation completes. + */ + template + size_t read_some(const MutableBufferSequence& buffers, boost::system::error_code& ec) { + detail::sspi_decrypt::state state; + while((state = sspi_stream_->decrypt(buffers)) == detail::sspi_decrypt::state::data_needed) { + std::size_t size_read = next_layer_.read_some(sspi_stream_->decrypt.input_buffer, ec); + if (ec) { + return 0; + } + sspi_stream_->decrypt.size_read(size_read); + continue; + } + + if (state == detail::sspi_decrypt::state::error) { + ec = sspi_stream_->decrypt.last_error(); + return 0; + } + + return sspi_stream_->decrypt.size_decrypted; + } + + /** Read some data from the stream. + * + * This function is used to read data from the stream. The function + * call will block until one or more bytes of data has been read + * successfully, or until an error occurs. + * + * @param buffers The buffers into which the data will be read. + * + * @returns The number of bytes read. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The `read_some` operation may not read all of the requested + * number of bytes. Consider using the `net::read` function if you + * need to ensure that the requested amount of data is read before + * the blocking operation completes. + */ + template + size_t read_some(const MutableBufferSequence& buffers) { + boost::system::error_code ec{}; + auto read = read_some(buffers, ec); + if (ec) { + detail::throw_error(ec); + } + return read; + } + + /** Start an asynchronous read. + * + * This function is used to asynchronously read one or more bytes of + * data from the stream. The function call always returns + * immediately. + * + * @param buffers The buffers into which the data will be + * read. Although the buffers object may be copied as necessary, + * ownership of the underlying buffers is retained by the caller, + * which must guarantee that they remain valid until the handler is + * called. + * @param handler The handler to be called when the read operation + * completes. Copies will be made of the handler as required. The + * equivalent function signature of the handler must be: + * @code + * void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes read. + * ); @endcode + * + * @note The `async_read_some` operation may not read all of the + * requested number of bytes. Consider using the `net::async_read` + * function if you need to ensure that the requested amount of data + * is read before the asynchronous operation completes. + */ + template + auto async_read_some(const MutableBufferSequence& buffers, CompletionToken&& handler) { + return boost::asio::async_compose( + detail::async_read{next_layer_, buffers, sspi_stream_->decrypt}, handler); + } + + /** Write some data to the stream. + * + * This function is used to write data on the stream. The function + * call will block until one or more bytes of data has been written + * successfully, or until an error occurs. + * + * @param buffers The data to be written. + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. + * + * @note The `write_some` operation may not transmit all of the data + * to the peer. Consider using the `net::write` function if you need + * to ensure that all data is written before the blocking operation + * completes. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers, boost::system::error_code& ec) { + std::size_t bytes_consumed = sspi_stream_->encrypt(buffers, ec); + if (ec) { + return 0; + } + + net::write(next_layer_, sspi_stream_->encrypt.buffers, ec); + if (ec) { + return 0; + } + + return bytes_consumed; + } + + /** Write some data to the stream. + * + * This function is used to write data on the stream. The function + * call will block until one or more bytes of data has been written + * successfully, or until an error occurs. + * + * @param buffers The data to be written. + * + * @returns The number of bytes written. + * + * @throws boost::system::system_error Thrown on failure. + * + * @note The `write_some` operation may not transmit all of the data + * to the peer. Consider using the `net::write` function if you need + * to ensure that all data is written before the blocking operation + * completes. + */ + template + std::size_t write_some(const ConstBufferSequence& buffers) { + boost::system::error_code ec{}; + auto wrote = write_some(buffers, ec); + if (ec) { + detail::throw_error(ec); + } + return wrote; + } + + + /** Start an asynchronous write. + * + * This function is used to asynchronously write one or more bytes + * of data to the stream. The function call always returns + * immediately. + * + * @param buffers The data to be written to the stream. Although the + * buffers object may be copied as necessary, ownership of the + * underlying buffers is retained by the caller, which must + * guarantee that they remain valid until the handler is called. + * @param handler The handler to be called when the write operation + * completes. Copies will be made of the handler as required. The + * equivalent function signature of the handler must be: + * @code + * void handler( + * const boost::system::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes written. + * ); + * @endcode + * + * @note The `async_write_some` operation may not transmit all of + * the data to the peer. Consider using the `net::async_write` + * function if you need to ensure that all data is written before + * the asynchronous operation completes. + */ + template + auto async_write_some(const ConstBufferSequence& buffers, CompletionToken&& handler) { + return boost::asio::async_compose( + detail::async_write{next_layer_, buffers, sspi_stream_->encrypt}, handler); + } + + /** Shut down TLS on the stream. + * + * This function is used to shut down TLS on the stream. The + * function call will block until TLS has been shut down or an + * error occurs. + * + * @param ec Set to indicate what error occurred, if any. + */ + void shutdown(boost::system::error_code& ec) { + ec = sspi_stream_->shutdown(); + if (ec) { + return; + } + std::size_t size_written = net::write(next_layer_, sspi_stream_->shutdown.buffer(), ec); + if (!ec) { + sspi_stream_->shutdown.size_written(size_written); + } + } + + /** Shut down TLS on the stream. + * + * This function is used to shut down TLS on the stream. The + * function call will block until TLS has been shut down or an error + * occurs. + * + * @throws boost::system::system_error Thrown on failure. + */ + void shutdown() { + boost::system::error_code ec{}; + shutdown(ec); + if (ec) { + detail::throw_error(ec); + } + } + + /** Asynchronously shut down TLS on the stream. + * + * This function is used to asynchronously shut down TLS on the + * stream. This function call always returns immediately. + * + * @param handler The handler to be called when the handshake + * operation completes. Copies will be made of the handler as + * required. The equivalent function signature of the handler must + * be: + * @code void handler( + * const boost::system::error_code& error // Result of operation. + *); + * @endcode + */ + template + auto async_shutdown(CompletionToken&& handler) { + return boost::asio::async_compose( + detail::async_shutdown{next_layer_, sspi_stream_->shutdown}, handler); + } + +private: + NextLayer next_layer_; + std::unique_ptr sspi_stream_; +}; + +} // namespace wintls +} // namespace boost + +#endif // BOOST_WINTLS_STREAM_HPP diff --git a/third-party/boost-wintls/test/CMakeLists.txt b/third-party/boost-wintls/test/CMakeLists.txt new file mode 100644 index 00000000000..df0de2ba1c4 --- /dev/null +++ b/third-party/boost-wintls/test/CMakeLists.txt @@ -0,0 +1,74 @@ +Include(FetchContent) + +find_package(Boost COMPONENTS filesystem) +find_package(OpenSSL COMPONENTS SSL Crypto) +find_package(Threads) + +if(NOT OPENSSL_FOUND) + message(SEND_ERROR "OpenSSL not found. Cannot build tests.") + return() +endif() + +if(NOT Threads_FOUND) + message(SEND_ERROR "Threads library not found. Cannot build tests.") + return() +endif() + +FetchContent_Declare( + Catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + GIT_TAG v2.13.6 +) + +FetchContent_MakeAvailable(Catch2) +list(APPEND CMAKE_MODULE_PATH ${Catch2_SOURCE_DIR}/contrib) + +set(test_sources + main.cpp + echo_test.cpp + tls_record.cpp + error_test.cpp + handshake_test.cpp + certificate_test.cpp + sspi_buffer_sequence_test.cpp + stream_test.cpp + decrypted_data_buffer_test.cpp +) + +add_executable(unittest + ${test_sources} +) + +if(ENABLE_ADDRESS_SANITIZER) + # Workaround for: https://github.com/catchorg/Catch2/issues/898 + target_compile_definitions(unittest PRIVATE CATCH_CONFIG_NO_WINDOWS_SEH) +endif() + +if(MSVC) + target_compile_options(unittest PRIVATE "-bigobj") +endif() + +target_compile_definitions(unittest PRIVATE + TEST_CERTIFICATES_PATH="${CMAKE_CURRENT_LIST_DIR}/test_certificates/gen/" +) + +target_link_libraries(unittest PRIVATE + OpenSSL::SSL + OpenSSL::Crypto + Threads::Threads + Catch2::Catch2 + Boost::filesystem + boost-wintls +) + +if(MSVC AND ${Boost_VERSION} VERSION_LESS "1.79" AND ${OPENSSL_VERSION} VERSION_GREATER_EQUAL "3.0") + # A bit of a hack. Older Boost.Asio versions use OpenSSL functions + # deprecated in version 3.0 so disable warnings on use of deprecated + # functions on MSVC where OpenSSL headers are not included as system + # headers. + target_compile_options(unittest PRIVATE /wd4996) +endif() + +include(CTest) +include(Catch) +catch_discover_tests(unittest TEST_SPEC "*") diff --git a/third-party/boost-wintls/test/asio_ssl_client_stream.hpp b/third-party/boost-wintls/test/asio_ssl_client_stream.hpp new file mode 100644 index 00000000000..3a8c8e095e1 --- /dev/null +++ b/third-party/boost-wintls/test/asio_ssl_client_stream.hpp @@ -0,0 +1,54 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef ASIO_SSL_CLIENT_STREAM_HPP +#define ASIO_SSL_CLIENT_STREAM_HPP + +#include "unittest.hpp" +#include "certificate.hpp" + +struct asio_ssl_client_context : public asio_ssl::context { + asio_ssl_client_context() + : asio_ssl::context(asio_ssl::context_base::tls) + , is_authority_loaded_(false) { + } + + void with_test_cert_authority() { + if(!is_authority_loaded_) { + add_certificate_authority(net::buffer(test_certificate)); + is_authority_loaded_ = true; + } + } + + void with_test_client_cert() { + with_test_cert_authority(); + use_certificate(net::buffer(test_certificate), asio_ssl::context_base::pem); + use_private_key(net::buffer(test_key), asio_ssl::context_base::pem); + } + + void enable_server_verify() { + set_verify_mode(boost::asio::ssl::verify_peer); + } + +private: + bool is_authority_loaded_; +}; + +struct asio_ssl_client_stream { + using handshake_type = asio_ssl::stream_base::handshake_type; + + template + asio_ssl_client_stream(Args&&... args) + : tst(std::forward(args)...) + , stream(tst, ctx) { + } + + asio_ssl_client_context ctx; + test_stream tst; + asio_ssl::stream stream; +}; + +#endif // ASIO_SSL_CLIENT_STREAM_HPP diff --git a/third-party/boost-wintls/test/asio_ssl_server_stream.hpp b/third-party/boost-wintls/test/asio_ssl_server_stream.hpp new file mode 100644 index 00000000000..db62ae08088 --- /dev/null +++ b/third-party/boost-wintls/test/asio_ssl_server_stream.hpp @@ -0,0 +1,40 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef ASIO_SSL_SERVER_STREAM_HPP +#define ASIO_SSL_SERVER_STREAM_HPP + +#include "certificate.hpp" +#include "unittest.hpp" + +struct asio_ssl_server_context : public asio_ssl::context { + asio_ssl_server_context() + : asio_ssl::context(asio_ssl::context_base::tls) { + use_certificate(net::buffer(test_certificate), asio_ssl::context_base::pem); + use_private_key(net::buffer(test_key), asio_ssl::context_base::pem); + } + + void enable_client_verify() { + set_verify_mode(asio_ssl::verify_peer | asio_ssl::verify_fail_if_no_peer_cert); + add_certificate_authority(net::buffer(test_certificate)); + } +}; + +struct asio_ssl_server_stream { + using handshake_type = asio_ssl::stream_base::handshake_type; + + template + asio_ssl_server_stream(Args&&... args) + : tst(std::forward(args)...) + , stream(tst, ctx) { + } + + asio_ssl_server_context ctx; + test_stream tst; + asio_ssl::stream stream; +}; + +#endif // ASIO_SSL_SERVER_STREAM_HPP diff --git a/third-party/boost-wintls/test/async_echo_client.hpp b/third-party/boost-wintls/test/async_echo_client.hpp new file mode 100644 index 00000000000..34d866e14ca --- /dev/null +++ b/third-party/boost-wintls/test/async_echo_client.hpp @@ -0,0 +1,67 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_TEST_ASYNC_ECHO_CLIENT_HPP +#define BOOST_WINTLS_TEST_ASYNC_ECHO_CLIENT_HPP + +#include "unittest.hpp" + +template +struct async_echo_client : public Stream { +public: + using Stream::stream; + + async_echo_client(net::io_context& context, const std::string& message) + : Stream(context) + , message_(message) { + } + + void run() { + do_handshake(); + } + + std::string received_message() const { + return std::string(net::buffers_begin(recv_buffer_.data()), + net::buffers_begin(recv_buffer_.data()) + static_cast(recv_buffer_.size())); + } + +private: + void do_handshake() { + stream.async_handshake(Stream::handshake_type::client, + [this](const boost::system::error_code& ec) { + REQUIRE_FALSE(ec); + do_write(); + }); + } + + void do_write() { + net::async_write(stream, net::buffer(message_), + [this](const boost::system::error_code& ec, std::size_t) { + REQUIRE_FALSE(ec); + do_read(); + }); + } + + void do_read() { + net::async_read_until(stream, recv_buffer_, '\0', + [this](const boost::system::error_code& ec, std::size_t) { + REQUIRE_FALSE(ec); + do_shutdown(); + }); + } + + void do_shutdown() { + stream.async_shutdown([](const boost::system::error_code& ec) { + REQUIRE_FALSE(ec); + }); + } + + std::string message_; + net::streambuf recv_buffer_; +}; + +#endif // BOOST_WINTLS_TEST_ASYNC_ECHO_CLIENT_HPP diff --git a/third-party/boost-wintls/test/async_echo_server.hpp b/third-party/boost-wintls/test/async_echo_server.hpp new file mode 100644 index 00000000000..37fc0eb400f --- /dev/null +++ b/third-party/boost-wintls/test/async_echo_server.hpp @@ -0,0 +1,61 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_TEST_ASYNC_ECHO_SERVER_HPP +#define BOOST_WINTLS_TEST_ASYNC_ECHO_SERVER_HPP + +#include "unittest.hpp" + +template +class async_echo_server : public Stream { +public: + using Stream::stream; + + async_echo_server(net::io_context& context) + : Stream(context) { + } + + void run() { + do_handshake(); + } + + virtual ~async_echo_server() = default; + + virtual void do_handshake() { + stream.async_handshake(Stream::handshake_type::server, + [this](const boost::system::error_code& ec) { + REQUIRE_FALSE(ec); + do_read(); + }); + } + + virtual void do_read() { + net::async_read_until(stream, recv_buffer_, '\0', + [this](const boost::system::error_code& ec, std::size_t) { + REQUIRE_FALSE(ec); + do_write(); + }); + } + + virtual void do_write() { + net::async_write(stream, recv_buffer_, + [this](const boost::system::error_code& ec, std::size_t) { + REQUIRE_FALSE(ec); + do_shutdown(); + }); + } + + virtual void do_shutdown() { + stream.async_shutdown([](const boost::system::error_code& ec) { + REQUIRE_FALSE(ec); + }); + } + + boost::asio::streambuf recv_buffer_; +}; + +#endif // BOOST_WINTLS_TEST_ASYNC_ECHO_SERVER_HPP diff --git a/third-party/boost-wintls/test/certificate.hpp b/third-party/boost-wintls/test/certificate.hpp new file mode 100644 index 00000000000..11b96622d11 --- /dev/null +++ b/third-party/boost-wintls/test/certificate.hpp @@ -0,0 +1,66 @@ +// +// Copyright (c) 2022 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef WINTLS_CERTIFICATE_HPP +#define WINTLS_CERTIFICATE_HPP + +#include + +const std::string test_certificate = + "-----BEGIN CERTIFICATE-----\n" + "MIIDbzCCAlegAwIBAgIUaIFyQGvp8/q1J7Lun753bvRBjKQwDQYJKoZIhvcNAQEL\n" + "BQAwRzELMAkGA1UEBhMCREsxEzARBgNVBAcMCkNvcGVuaGFnZW4xDzANBgNVBAoM\n" + "BldpblRMUzESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIyMDYyNTIwMzg0OVoXDTQ5\n" + "MTExMDIwMzg0OVowRzELMAkGA1UEBhMCREsxEzARBgNVBAcMCkNvcGVuaGFnZW4x\n" + "DzANBgNVBAoMBldpblRMUzESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG\n" + "9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy6b79MKE2mdt1h7GtfFmol68HI/Q3tOsPHaJ\n" + "cDv7PfflJofqlae1SPFAs4OspQ7IAjcwuictiyE9MbPo5vgiAEctZ2aP2PbF99AP\n" + "XAtkeLLLF5zxqVTbQtmEt147aycALe7WddVNQqlAFQ7gd6VCo/1jZMRlwNHPT1Oi\n" + "PkowAfVpDYCIwuL/0Rc6bRkh8p6J5Oi6S4sWcT7e6oo81NOKwyK6h2WJ8c01tFWp\n" + "G26XySopaH3u2HT+3Elg0lIdaaAm4EhZMysYIsPli+o2OiM4Dm2qGwK/VxeZz83W\n" + "aFS8jYPZQkB2fWOAk3Lm/hLLkSj5Z0qcin4543DOREO3b9J4ZQIDAQABo1MwUTAd\n" + "BgNVHQ4EFgQU8TcsJp8OfaZJvBIfCOz5fqnhztwwHwYDVR0jBBgwFoAU8TcsJp8O\n" + "faZJvBIfCOz5fqnhztwwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC\n" + "AQEAsUryE+jjeg/8xhwvthH+GJVjQSVvAbJjd1PQMLo3Yy578a1UN6aBOELwRe4W\n" + "FgR3ASRKhrc/mnSju0eLSF69lSWStjJC+ZNlZRuwOS/Ik9A6BAe6sOARpKPV1rV2\n" + "uWs8PxsWqPuTdICri91bEpmq1jntNTRgXmFW/hQR2ndy03h9hUHd0Xn70mlESayJ\n" + "2s6qnAMp+OzlTtWO6eSYYajYQdmsmIpby5eGjPzPNhoIVPKtSUa6eN5GltlW74qu\n" + "75w4XWlNO3J0AX4ZoWc7fztsWkgTX41Vv48lkxPLqLxQQTQsN6wdZ/c/sdSAXK0x\n" + "GinlCF73ogVSHXdtNMGrQP1n8w==\n" + "-----END CERTIFICATE-----\n"; + +const std::string test_key = + "-----BEGIN PRIVATE KEY-----\n" + "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDLpvv0woTaZ23W\n" + "Hsa18WaiXrwcj9De06w8dolwO/s99+Umh+qVp7VI8UCzg6ylDsgCNzC6Jy2LIT0x\n" + "s+jm+CIARy1nZo/Y9sX30A9cC2R4sssXnPGpVNtC2YS3XjtrJwAt7tZ11U1CqUAV\n" + "DuB3pUKj/WNkxGXA0c9PU6I+SjAB9WkNgIjC4v/RFzptGSHynonk6LpLixZxPt7q\n" + "ijzU04rDIrqHZYnxzTW0VakbbpfJKilofe7YdP7cSWDSUh1poCbgSFkzKxgiw+WL\n" + "6jY6IzgObaobAr9XF5nPzdZoVLyNg9lCQHZ9Y4CTcub+EsuRKPlnSpyKfjnjcM5E\n" + "Q7dv0nhlAgMBAAECggEBAKRhZa/7rsang5W4g8ZqUuCuvQIE56BklPq851TrZXFw\n" + "fctrG+OuWfrFmOcNWrZkRvba2372jqFltAJBaLW+BZvZ2AFFXMjQ75yGmU8/dtqh\n" + "3qJxsPJwJwc/kgt8iVOFSHTK+tpj0JgFC0+0EWUhxLefmLHGgSdxcvdh12yV70g0\n" + "APtKnCax/QznmW1XbXiEqP9n5mspOeC2LcJLKdH6PRiCeN+AnYAI5tzMm0L5Z8KS\n" + "JepiCYc/Saxdd3FkIus+VSaqKPBF3XcwfIglkZe5AzOTpQQZuSOEvKasvf2Lm+bT\n" + "ZgWCujDmg5Fdrjake4jZRQE2ZZirFJMc6wu4XCSnwqECgYEA5PoqcmfYs14/Mf3Z\n" + "XDSeAKqsOB61NA/A0ylvaCJixzRUylt8IgTJ9XJ0qiPOFCEcKr3DOlehZXLCieCO\n" + "XeHDOHRSfRn4clMAQOs3EgOWRCF1IjdS99FismwPAToY3kbrCfvqN/h+cqd1lJSL\n" + "NhboOMOPZmH1mJ29h9ukqMac4j0CgYEA46+0V6b+fd/AbfX6oLnOQcS3cyJKyPC6\n" + "nljzjbsx123+zgAlhqStE3wL3PjzJMepS0H4h2w4owobfOcrGhpxVbWTdQRSUqpX\n" + "X04Q+9YjDWg7OsPTQYXN1e/NCbw25WH8jPhtrZcaHwAtqPVsh94WCmKREiXg4VrU\n" + "5MZ6z4zWGUkCgYAeBrgePIPsMYWz9ofUUYoOqFLhIRW99/rfNeXIEApH+RLNXmXO\n" + "yDX7m8C0tvFFLnpVGIFLW0Zs2TmtfubsZLiG5KoUgZ1U0JGN8cpM8G96C7EihYK5\n" + "wJlisEzfalDshPw5WPGD2XArdM40Z65Br4tQNkTNtjbQho7eC+1xvGnCOQKBgCzw\n" + "NfEC5cHkUq+hWAk3Aw2aDPctcoM8eCjet5tmsgyqChuQjdeIUxzAY/sGK787pR9U\n" + "cwAPjRIo4YoCelBZnbrj7qmu46yrMDmAR/vcpOh1hRMxKVYKWbj67oYYXuFhOJ5+\n" + "Pe+AHki2GUz6u6QJYmJEWAuz7DGuYsyQnBaw3mT5AoGBAK83Z0rszmsS2F2xM0J3\n" + "3xtHxaXmvJdDQto29M2+CT0vYvTBZGPT8BOPuRzkWJzDSpoSduqZNnsrh1idWL5Q\n" + "IVNc0eS7mhAa/9QZkkU9JyyTfbzCEvchZkMD6uyFhS9zaDFUrBQjDcx0SXeoUP9i\n" + "hOHwm+u6yzjHKIsf0M/ATOru\n" + "-----END PRIVATE KEY-----\n"; + +const std::string test_key_name="boost-wintls-test-key"; +#endif diff --git a/third-party/boost-wintls/test/certificate_test.cpp b/third-party/boost-wintls/test/certificate_test.cpp new file mode 100644 index 00000000000..7370b9c0e39 --- /dev/null +++ b/third-party/boost-wintls/test/certificate_test.cpp @@ -0,0 +1,264 @@ +// +// Copyright (c) 2020 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include "certificate.hpp" +#include "ocsp_responder.hpp" +#include "unittest.hpp" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace { +std::string get_cert_name(const CERT_CONTEXT* cert) { + auto size = CertGetNameStringA(cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nullptr, nullptr, 0); + REQUIRE(size > 0); + std::vector str(size); + CertGetNameStringA(cert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nullptr, str.data(), size); + return {str.data()}; +} + +bool container_exists(const std::string& name) { + HCRYPTKEY ptr = 0; + if (!CryptAcquireContextA(&ptr, name.c_str(), nullptr, PROV_RSA_FULL, CRYPT_SILENT)) { + auto last_error = GetLastError(); + if (last_error == static_cast(NTE_BAD_KEYSET)) { + return false; + } + throw boost::system::system_error(static_cast(last_error), boost::system::system_category()); + } + CryptReleaseContext(ptr, 0); + return true; +} + +// Add a certificate from the PEM formatted string cert_str to the given store. +// If get_handle is true, a handle to the certificate in the store is returned. +// Otherwise, the certificate will be owned by the store and nullptr is returned. +boost::wintls::cert_context_ptr add_cert_str_to_store(HCERTSTORE store, + const net::const_buffer& cert_str, + bool get_handle) { + PCCERT_CONTEXT cert_in_store = nullptr; + const auto cert_data = boost::wintls::detail::crypt_string_to_binary(cert_str); + if (!CertAddEncodedCertificateToStore(store, + X509_ASN_ENCODING, + cert_data.data(), + static_cast(cert_data.size()), + CERT_STORE_ADD_ALWAYS, + get_handle ? &cert_in_store : nullptr)) { + boost::wintls::detail::throw_last_error("CertAddEncodedCertificateToStore"); + } + if (get_handle) { + return boost::wintls::cert_context_ptr{cert_in_store}; + } + return boost::wintls::cert_context_ptr{}; +} + +// Load a PEM formatted certificate chain from the given file. +// Assumes that the first certificate in the file is the leaf certificate +// and returns a context for this certificate which internally holds a store +// containing all remaining certificates from the file. +boost::wintls::cert_context_ptr load_chain_file(const std::string& path) { + std::ifstream ifs(path); + if (ifs.fail()) { + throw std::runtime_error("Failed to open file " + path); + } + constexpr auto begin_cert_str = "-----BEGIN CERTIFICATE-----"; + constexpr auto end_cert_str = "-----END CERTIFICATE-----"; + constexpr std::size_t end_cert_str_size = 25; + // find the first certificate in the file + std::string str{std::istreambuf_iterator{ifs}, {}}; + auto cert_begin = str.find(begin_cert_str, 0); + auto cert_end = str.find(end_cert_str, cert_begin); + if (cert_begin == std::string::npos || cert_end == std::string::npos) { + throw std::runtime_error("Error parsing certificate chain in PEM format from file " + path); + } + // Open a temporary store for the chain. + // Use CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, so the context of the leaf certificate can take ownership. + const auto chain_store = boost::wintls::detail::cert_store_ptr{ + CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, nullptr)}; + auto leaf_ctx = add_cert_str_to_store(chain_store.get(), + net::buffer(&str[cert_begin], cert_end + end_cert_str_size - cert_begin), + true); + // add any remaining certificates to the chain_store + for (cert_begin = str.find(begin_cert_str, cert_end); + cert_begin != std::string::npos; + cert_begin = str.find(begin_cert_str, cert_end)) { + cert_end = str.find(end_cert_str, cert_begin); + if (cert_end == std::string::npos) { + throw std::runtime_error("Error parsing certificate chain in PEM format from file " + path); + } + add_cert_str_to_store(chain_store.get(), + net::buffer(&str[cert_begin], cert_end + end_cert_str_size - cert_begin), + false); + } + return leaf_ctx; +} + +struct crl_ctx_deleter { + void operator()(const CRL_CONTEXT* crl_ctx) { + CertFreeCRLContext(crl_ctx); + } +}; + +using crl_ctx_ptr = std::unique_ptr; + +crl_ctx_ptr x509_to_crl_context(const net::const_buffer& x509) { + const auto data = boost::wintls::detail::crypt_string_to_binary(x509); + const auto crl = CertCreateCRLContext(X509_ASN_ENCODING, data.data(), static_cast(data.size())); + if (!crl) { + boost::wintls::detail::throw_last_error("CertCreateCRLContext"); + } + return crl_ctx_ptr{crl}; +} + +crl_ctx_ptr crl_from_file(const std::string& path) { + const auto crl_bytes = bytes_from_file(path); + return x509_to_crl_context(net::buffer(crl_bytes)); +} + +boost::wintls::cert_context_ptr cert_from_file(const std::string& path) { + const auto cert_bytes = bytes_from_file(path); + return boost::wintls::x509_to_cert_context(net::buffer(cert_bytes), boost::wintls::file_format::pem); +} +} + +TEST_CASE("certificate conversion") { + SECTION("valid cert bytes") { + const auto cert = boost::wintls::x509_to_cert_context(net::buffer(test_certificate), boost::wintls::file_format::pem); + CHECK(get_cert_name(cert.get()) == "localhost"); + } + + SECTION("invalid cert bytes") { + const std::vector cert_bytes; + CHECK_THROWS(boost::wintls::x509_to_cert_context(net::buffer(cert_bytes), boost::wintls::file_format::pem)); + auto error = boost::system::errc::make_error_code(boost::system::errc::success); + const auto cert = boost::wintls::x509_to_cert_context(net::buffer(cert_bytes), boost::wintls::file_format::pem, error); + CHECK(error); + CHECK_FALSE(cert); + } +} + +TEST_CASE("import private key") { + const std::string name{"boost::wintls crypto test container"}; + REQUIRE_FALSE(container_exists(name)); + + boost::wintls::import_private_key(net::buffer(test_key), boost::wintls::file_format::pem, name); + CHECK(container_exists(name)); + + boost::system::error_code ec; + boost::wintls::import_private_key(net::buffer(test_key), boost::wintls::file_format::pem, name, ec); + CHECK(ec.value() == NTE_EXISTS); + + boost::wintls::delete_private_key(name); + CHECK_FALSE(container_exists(name)); + + boost::wintls::delete_private_key(name, ec); + CHECK(ec.value() == NTE_BAD_KEYSET); +} + +TEST_CASE("verify certificate host name") { + boost::wintls::detail::context_certificates ctx_certs; + ctx_certs.add_certificate_authority(cert_from_file(TEST_CERTIFICATES_PATH "ca_root.crt").get()); + + const auto cert = load_chain_file(TEST_CERTIFICATES_PATH "leaf_chain.pem"); + + // success case: host name is not verified when parameter is empty string + CHECK(ctx_certs.verify_certificate(cert.get(), "", false) == ERROR_SUCCESS); + // success case: certificate contains the common name "wintls.test" + CHECK(ctx_certs.verify_certificate(cert.get(), "wintls.test", false) == ERROR_SUCCESS); + // success case: certificate allows alternative names "*.wintls.test" + CHECK(ctx_certs.verify_certificate(cert.get(), "subdomain.wintls.test", false) == ERROR_SUCCESS); + // fail case: incorrect host name + CHECK(ctx_certs.verify_certificate(cert.get(), "wrong.host", false) == CERT_E_CN_NO_MATCH); +} + +TEST_CASE("check certificate revocation") { + SECTION("single self signed certificate") { + const auto cert = boost::wintls::x509_to_cert_context(net::buffer(test_certificate), boost::wintls::file_format::pem); + boost::wintls::detail::context_certificates ctx_certs; + ctx_certs.add_certificate_authority(cert.get()); + // It appears that there is no revocation check done in this case, + // otherwise this should fail with CRYPT_E_NO_REVOCATION_CHECK + // as the certificate does not supply any information how to check for revocation. + // Note that this does not depend on whether we pass CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT + // or CERT_CHAIN_REVOCATION_CHECK_CHAIN to CertGetCertificateChain. + // So apparently root certificates are never checked for revocation, which probably makes sense. + CHECK(ctx_certs.verify_certificate(cert.get(), "", true) == ERROR_SUCCESS); + } + + SECTION("certificate chain with CRLs") { + boost::wintls::detail::context_certificates ctx_certs; + ctx_certs.add_certificate_authority(cert_from_file(TEST_CERTIFICATES_PATH "ca_root.crt").get()); + + const auto cert = load_chain_file(TEST_CERTIFICATES_PATH "leaf_chain.pem"); + + // fail case: cannot check for revocation (no CRL or OCSP endpoint specified and no local CRL available) + CHECK(ctx_certs.verify_certificate(cert.get(), "", true) == CRYPT_E_NO_REVOCATION_CHECK); + + // success case: empty CRLs available + ctx_certs.add_crl(crl_from_file(TEST_CERTIFICATES_PATH "ca_intermediate_empty.crl.pem").get()); + ctx_certs.add_crl(crl_from_file(TEST_CERTIFICATES_PATH "ca_root_empty.crl.pem").get()); + CHECK(ctx_certs.verify_certificate(cert.get(), "", true) == ERROR_SUCCESS); + + // fail case: CRL of ca_intermediate with revoked leaf certificate + ctx_certs.add_crl(crl_from_file(TEST_CERTIFICATES_PATH "ca_intermediate_leaf_revoked.crl.pem").get()); + CHECK(ctx_certs.verify_certificate(cert.get(), "", true) == CRYPT_E_REVOKED); + } +} + +// This test takes about 15 seconds to run, as the OCSP responder takes that long to become available. +// Therefore it is marked as integration test and not run by default. +TEST_CASE("check certificate revocation (integration test)", "[.integration]") { + SECTION("certificate chain with OCSP") { + boost::wintls::detail::context_certificates ctx_certs; + ctx_certs.add_certificate_authority(cert_from_file(TEST_CERTIFICATES_PATH "ca_root.crt").get()); + + // fail case: OCSP responder is not running + const auto cert_ocsp = load_chain_file(TEST_CERTIFICATES_PATH "leaf_ocsp_chain.pem"); + const auto res_without_responder = ctx_certs.verify_certificate(cert_ocsp.get(), "", true); + // NOTE: We start the openssl OCSP responder with '-nmin 1' + // which causes the OCSP response to be cached by windows for one minute. + // This is the smallest possible value. If we do not pass -nmin or -ndays to openssl, + // it will seemingly consider the OCSP response to be valid indefinitely. + // Therefore we allow a successful response here and print a warning in that case. + if (res_without_responder == ERROR_SUCCESS) { + WARN("Validation of the test certificate was successful even though the OCSP responder was not yet started.\n" + "This may happen if the unit test was run twice within one minute."); + } else { + CHECK(res_without_responder == CRYPT_E_REVOCATION_OFFLINE); + } + + // success case: cert_ocsp is fine + auto ocsp_responder = start_ocsp_responder(); + // 'running()' does not mean that it is responding yet, but that we did start the process correctly + CHECK(ocsp_responder.running()); + // It takes a few seconds for the OCSP responder to become available. + // Therefore, we try to verify the certificate in a loop, but for at most 30 seconds. + auto res_with_responder = CRYPT_E_REVOCATION_OFFLINE; + const auto start = std::chrono::system_clock::now(); + while (res_with_responder == CRYPT_E_REVOCATION_OFFLINE) { + res_with_responder = ctx_certs.verify_certificate(cert_ocsp.get(), "", true); + if (std::chrono::system_clock::now() - start > std::chrono::seconds(30)) { + WARN("OCSP responder did not provide a response within 30 seconds."); + break; + } + } + CHECK(res_with_responder == ERROR_SUCCESS); + + // fail case: cert_ocsp_revoked is revoked + const auto cert_ocsp_revoked = load_chain_file(TEST_CERTIFICATES_PATH "leaf_ocsp_revoked_chain.pem"); + CHECK(ctx_certs.verify_certificate(cert_ocsp_revoked.get(), "", true) == CRYPT_E_REVOKED); + } +} diff --git a/third-party/boost-wintls/test/decrypted_data_buffer_test.cpp b/third-party/boost-wintls/test/decrypted_data_buffer_test.cpp new file mode 100644 index 00000000000..52c43ede637 --- /dev/null +++ b/third-party/boost-wintls/test/decrypted_data_buffer_test.cpp @@ -0,0 +1,42 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include "unittest.hpp" + +#include + +#include + +TEST_CASE("decrypted data buffer") { + boost::wintls::detail::decrypted_data_buffer<25> test_buffer; + CHECK(test_buffer.empty()); + + std::string input_str{"abc"}; + test_buffer.fill(net::buffer(input_str)); + CHECK_FALSE(test_buffer.empty()); + + std::string output_str(1, '\0'); + + test_buffer.get(net::buffer(output_str)); + CHECK_FALSE(test_buffer.empty()); + CHECK(output_str == "a"); + + test_buffer.get(net::buffer(output_str)); + CHECK_FALSE(test_buffer.empty()); + CHECK(output_str == "b"); + + test_buffer.get(net::buffer(output_str)); + CHECK(test_buffer.empty()); + CHECK(output_str == "c"); + + test_buffer.fill(net::buffer(input_str)); + output_str = "defg"; + const auto size = test_buffer.get(net::buffer(output_str)); + CHECK(size == 3); + CHECK(test_buffer.empty()); + CHECK(output_str == "abcg"); +} diff --git a/third-party/boost-wintls/test/echo_client.hpp b/third-party/boost-wintls/test/echo_client.hpp new file mode 100644 index 00000000000..fc31a2d6ab1 --- /dev/null +++ b/third-party/boost-wintls/test/echo_client.hpp @@ -0,0 +1,48 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_TEST_ECHO_CLIENT_HPP +#define BOOST_WINTLS_TEST_ECHO_CLIENT_HPP + +#include "unittest.hpp" + +template +class echo_client : public Stream { +public: + using Stream::stream; + + echo_client(net::io_context& context) + : Stream(context) { + } + + void handshake() { + stream.handshake(Stream::handshake_type::client); + } + + void shutdown() { + stream.shutdown(); + } + + void read() { + net::read_until(stream, buffer_, '\0'); + } + + template + void write(const T& data) { + net::write(stream, net::buffer(data)); + } + + template + T data() const { + return T(net::buffers_begin(buffer_.data()), net::buffers_begin(buffer_.data()) + static_cast(buffer_.size())); + } + +private: + net::streambuf buffer_; +}; + +#endif // BOOST_WINTLS_TEST_ECHO_CLIENT_HPP diff --git a/third-party/boost-wintls/test/echo_server.hpp b/third-party/boost-wintls/test/echo_server.hpp new file mode 100644 index 00000000000..4bac7d5a079 --- /dev/null +++ b/third-party/boost-wintls/test/echo_server.hpp @@ -0,0 +1,52 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_TEST_ECHO_SERVER_HPP +#define BOOST_WINTLS_TEST_ECHO_SERVER_HPP + +#include "unittest.hpp" + +#include + +template +class echo_server : public Stream { +public: + using Stream::stream; + + echo_server(net::io_context& context) + : Stream(context) { + } + + std::future handshake() { + return std::async(std::launch::async, [this]() { + boost::system::error_code ec{}; + stream.handshake(Stream::handshake_type::server, ec); + return ec; + }); + } + + std::future shutdown() { + return std::async(std::launch::async, [this]() { + boost::system::error_code ec{}; + stream.shutdown(ec); + return ec; + }); + } + + void read() { + net::read_until(stream, buffer_, '\0'); + } + + void write() { + net::write(stream, buffer_); + } + +private: + net::streambuf buffer_; +}; + +#endif // BOOST_WINTLS_TEST_ECHO_SERVER_HPP diff --git a/third-party/boost-wintls/test/echo_test.cpp b/third-party/boost-wintls/test/echo_test.cpp new file mode 100644 index 00000000000..f7265622e72 --- /dev/null +++ b/third-party/boost-wintls/test/echo_test.cpp @@ -0,0 +1,83 @@ +// +// Copyright (c) 2020 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include "echo_server.hpp" +#include "echo_client.hpp" +#include "async_echo_server.hpp" +#include "async_echo_client.hpp" +#include "asio_ssl_client_stream.hpp" +#include "asio_ssl_server_stream.hpp" +#include "wintls_client_stream.hpp" +#include "wintls_server_stream.hpp" +#include "unittest.hpp" + +#include + +#include +#include +#include + +namespace { +std::string generate_data(std::size_t size) { + std::string ret(size, '\0'); + for (std::size_t i = 0; i < size - 1; ++i) { + ret[i] = static_cast(i % 26 + 65); + } + return ret; +} + +} + +using TestTypes = std::tuple, + std::tuple, + std::tuple, + std::tuple>; + +TEMPLATE_LIST_TEST_CASE("echo test", "", TestTypes) { + using ClientStream = typename std::tuple_element<0, TestType>::type; + using ServerStream = typename std::tuple_element<1, TestType>::type; + + auto test_data_size = GENERATE(0x100, 0x100 - 1, 0x100 + 1, + 0x1000, 0x1000 - 1, 0x1000 + 1, + 0x10000, 0x10000 - 1, 0x10000 + 1, + 0x100000, 0x100000 - 1, 0x100000 + 1); + const std::string test_data = generate_data(static_cast(test_data_size)); + + net::io_context io_context; + + SECTION("sync test") { + echo_client client(io_context); + echo_server server(io_context); + + client.stream.next_layer().connect(server.stream.next_layer()); + + auto handshake_result = server.handshake(); + client.handshake(); + REQUIRE_FALSE(handshake_result.get()); + + client.write(test_data); + server.read(); + server.write(); + client.read(); + + auto shutdown_result = server.shutdown(); + client.shutdown(); + REQUIRE_FALSE(shutdown_result.get()); + + CHECK(client.template data() == test_data); + } + + SECTION("async test") { + async_echo_server server(io_context); + async_echo_client client(io_context, test_data); + client.stream.next_layer().connect(server.stream.next_layer()); + server.run(); + client.run(); + io_context.run(); + CHECK(client.received_message() == test_data); + } +} diff --git a/third-party/boost-wintls/test/error_test.cpp b/third-party/boost-wintls/test/error_test.cpp new file mode 100644 index 00000000000..74c688722fd --- /dev/null +++ b/third-party/boost-wintls/test/error_test.cpp @@ -0,0 +1,34 @@ +// +// Copyright (c) 2020 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include "unittest.hpp" + +#include + +extern "C" __declspec(dllimport) void __stdcall SetLastError(unsigned long); + +TEST_CASE("SECURITY_STATUS error code") { + auto sc = static_cast(0x80090326); + auto ec = boost::wintls::error::make_error_code(sc); + CHECK(ec.value() == sc); + CHECK(ec.message() == "The message received was unexpected or badly formatted"); +} + +TEST_CASE("throw last error") { + boost::system::system_error error{boost::system::error_code{}}; + REQUIRE_FALSE(error.code()); + + ::SetLastError(0x00000053); + try { + boost::wintls::detail::throw_last_error("YetAnotherUglyWindowsAPIFunctionEx3"); + } catch (const boost::system::system_error& ex) { + error = ex; + } + CHECK(error.code().value() == 0x00000053); + CHECK(error.code().message() == "Fail on INT 24"); + CHECK_THAT(error.what(), Catch::Contains("YetAnotherUglyWindowsAPIFunctionEx3: Fail on INT 24")); +} diff --git a/third-party/boost-wintls/test/handshake_test.cpp b/third-party/boost-wintls/test/handshake_test.cpp new file mode 100644 index 00000000000..44c79e69559 --- /dev/null +++ b/third-party/boost-wintls/test/handshake_test.cpp @@ -0,0 +1,612 @@ +// +// Copyright (c) 2020 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include "async_echo_client.hpp" +#include "async_echo_server.hpp" +#include "certificate.hpp" +#include "tls_record.hpp" +#include "unittest.hpp" + +#include +#include "asio_ssl_server_stream.hpp" +#include "asio_ssl_client_stream.hpp" +#include "wintls_client_stream.hpp" +#include "wintls_server_stream.hpp" + +#include +#include + +namespace boost { +namespace wintls { + +std::ostream& operator<<(std::ostream& os, const method meth) { + switch (meth) { + case method::system_default: + return os << "system_default"; + case method::sslv3: + return os << "sslv3"; + case method::sslv3_client: + return os << "sslv3_client"; + case method::sslv3_server: + return os << "sslv3_server"; + case method::tlsv1: + return os << "tlsv1"; + case method::tlsv1_client: + return os << "tlsv1_client"; + case method::tlsv1_server: + return os << "tlsv1_server"; + case method::tlsv11: + return os << "tlsv11"; + case method::tlsv11_client: + return os << "tlsv11_client"; + case method::tlsv11_server: + return os << "tlsv11_server"; + case method::tlsv12: + return os << "tlsv12"; + case method::tlsv12_client: + return os << "tlsv12_client"; + case method::tlsv12_server: + return os << "tlsv12_server"; + case method::tlsv13: + return os << "tlsv13"; + case method::tlsv13_client: + return os << "tlsv13_client"; + case method::tlsv13_server: + return os << "tlsv13_server"; + } + BOOST_UNREACHABLE_RETURN(0); +} + +} // namespace wintls +} // namespace boost + +namespace { + +std::string wchar_to_string(const wchar_t* input) { + const auto length = static_cast(std::wcslen(input)); + + const auto size_needed = WideCharToMultiByte(CP_UTF8, 0, input, length, nullptr, 0, nullptr, nullptr); + if (size_needed == 0) { + boost::wintls::detail::throw_last_error("WideCharToMultiByte"); + } + + std::string output(size_needed, '\0'); + const auto size_written = WideCharToMultiByte(CP_UTF8, 0, input, length, &output[0], size_needed, nullptr, nullptr); + if (size_written == 0) { + boost::wintls::detail::throw_last_error("WideCharToMultiByte"); + } + return output; +} + +std::vector string_to_x509_name(const std::string& str) { + DWORD size = 0; + std::vector ret; + if (!CertStrToName(X509_ASN_ENCODING, str.c_str(), CERT_X500_NAME_STR, nullptr, nullptr, &size, nullptr)) { + boost::wintls::detail::throw_last_error("CertStrToName"); + } + ret.resize(size); + if (!CertStrToName(X509_ASN_ENCODING, str.c_str(), CERT_X500_NAME_STR, nullptr, ret.data(), &size, nullptr)) { + boost::wintls::detail::throw_last_error("CertStrToName"); + } + return ret; +} + +struct cert_name_blob { + cert_name_blob(const std::string& str) + : data_(string_to_x509_name(str)) { + blob.pbData = data_.data(); + blob.cbData = static_cast(data_.size()); + } + + CERT_NAME_BLOB blob; +private: + std::vector data_; +}; + +boost::wintls::cert_context_ptr create_self_signed_cert(const std::string& subject) { + cert_name_blob cert_subject(subject); + SYSTEMTIME expiry_date; + GetSystemTime(&expiry_date); + expiry_date.wYear += 1; + + auto cert = CertCreateSelfSignCertificate(0, + &cert_subject.blob, + 0, + 0, + nullptr, + 0, + &expiry_date, + 0); + if (!cert) { + boost::wintls::detail::throw_last_error("CertCreateSelfSignCertificate"); + } + return boost::wintls::cert_context_ptr{cert}; +} + +std::string cert_container_name(const CERT_CONTEXT* cert) { + DWORD size = 0; + if (!CertGetCertificateContextProperty(cert, + CERT_KEY_PROV_INFO_PROP_ID, + nullptr, + &size)) { + boost::wintls::detail::throw_last_error("CertGetCertificateContextProperty"); + } + + std::vector data(size); + if (!CertGetCertificateContextProperty(cert, + CERT_KEY_PROV_INFO_PROP_ID, + data.data(), + &size)) { + boost::wintls::detail::throw_last_error("CertGetCertificateContextProperty"); + } + const auto info = reinterpret_cast(data.data()); + return wchar_to_string(info->pwszContainerName); +} +} // namespace + +TEST_CASE("certificates") { + using namespace std::string_literals; + using namespace boost::system; + + net::io_context io_context; + boost::wintls::context client_ctx(boost::wintls::method::system_default); + boost::wintls::stream client_stream(io_context, client_ctx); + + SECTION("invalid certificate data") { + // TODO: Instead of returning an error when given a null pointer + // or other easily detectable invalid input, the Windows crypto + // libraries cause the Windows equivalent of a segfault. This is + // pretty consistent with the rest of the Windows API though. + // + // Figure out a way to generate invalid data that doesn't make the + // test crash. + /* + using namespace boost::system; + + auto error = errc::make_error_code(errc::not_supported); + + CERT_INFO cert_info{}; + const CERT_CONTEXT bad_cert{ + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + nullptr, + 0, + &cert_info, + 0}; + client_ctx.add_certificate_authority(&bad_cert, error); + + CHECK(error.category() == boost::system::system_category()); + CHECK(error.value() == CRYPT_E_ASN1_EOD); + */ + } + + SECTION("server cert without private key") { + boost::wintls::context server_ctx(boost::wintls::method::system_default); + auto cert = x509_to_cert_context(net::buffer(test_certificate), boost::wintls::file_format::pem); + + CHECK_THROWS_WITH(server_ctx.use_certificate(cert.get()), + Catch::Matchers::Contains("Cannot find the certificate and private key for decryption")); + + boost::system::error_code ec{}; + server_ctx.use_certificate(cert.get(), ec); + CHECK(ec.category() == system_category()); + CHECK(ec.value() & NTE_BAD_SIGNATURE); + } + + SECTION("wintl server") { + boost::wintls::context server_ctx(boost::wintls::method::system_default); + const auto cert = create_self_signed_cert("CN=WinTLS, T=Test"); + server_ctx.use_certificate(cert.get()); + boost::wintls::stream server_stream(io_context, server_ctx); + + client_stream.next_layer().connect(server_stream.next_layer()); + + SECTION("no certificate validation") { + auto client_error = errc::make_error_code(errc::not_supported); + client_stream.async_handshake(boost::wintls::handshake_type::client, + [&client_error, &io_context](const boost::system::error_code& ec) { + client_error = ec; + io_context.stop(); + }); + + auto server_error = errc::make_error_code(errc::not_supported); + server_stream.async_handshake(boost::wintls::handshake_type::server, + [&server_error](const boost::system::error_code& ec) { + server_error = ec; + }); + io_context.run(); + CHECK_FALSE(client_error); + CHECK_FALSE(server_error); + } + + SECTION("no trusted certificate") { + client_ctx.verify_server_certificate(true); + + auto client_error = errc::make_error_code(errc::not_supported); + client_stream.async_handshake(boost::wintls::handshake_type::client, + [&client_error](const boost::system::error_code& ec) { + client_error = ec; + }); + + auto server_error = errc::make_error_code(errc::not_supported); + server_stream.async_handshake(boost::wintls::handshake_type::server, + [&server_error](const boost::system::error_code& ec) { + server_error = ec; + }); + + io_context.run(); + CHECK(client_error.category() == system_category()); + CHECK(client_error.value() == CERT_E_UNTRUSTEDROOT); + CHECK_FALSE(server_error); + } + + SECTION("trusted certificate verified") { + client_ctx.verify_server_certificate(true); + client_ctx.add_certificate_authority(cert.get()); + + auto client_error = errc::make_error_code(errc::not_supported); + client_stream.async_handshake(boost::wintls::handshake_type::client, + [&client_error, &io_context](const boost::system::error_code& ec) { + client_error = ec; + io_context.stop(); + }); + + auto server_error = errc::make_error_code(errc::not_supported); + server_stream.async_handshake(boost::wintls::handshake_type::server, + [&server_error](const boost::system::error_code& ec) { + server_error = ec; + }); + io_context.run(); + CHECK_FALSE(client_error); + CHECK_FALSE(server_error); + } + + boost::wintls::delete_private_key(cert_container_name(cert.get())); + } + + SECTION("asio::ssl server") { + boost::asio::ssl::context server_ctx(boost::asio::ssl::context::tls_server); + server_ctx.use_certificate_chain(net::buffer(test_certificate)); + server_ctx.use_private_key(net::buffer(test_key), boost::asio::ssl::context::pem); + + boost::asio::ssl::stream server_stream(io_context, server_ctx); + + client_stream.next_layer().connect(server_stream.next_layer()); + + SECTION("no certificate validation") { + auto client_error = errc::make_error_code(errc::not_supported); + client_stream.async_handshake(boost::wintls::handshake_type::client, + [&client_error, &io_context](const boost::system::error_code& ec) { + client_error = ec; + io_context.stop(); + }); + + auto server_error = errc::make_error_code(errc::not_supported); + server_stream.async_handshake(asio_ssl::stream_base::server, + [&server_error](const boost::system::error_code& ec) { + server_error = ec; + }); + io_context.run(); + CHECK_FALSE(client_error); + CHECK_FALSE(server_error); + } + + SECTION("no trusted certificate") { + client_ctx.verify_server_certificate(true); + + auto client_error = errc::make_error_code(errc::not_supported); + client_stream.async_handshake(boost::wintls::handshake_type::client, + [&client_error](const boost::system::error_code& ec) { + client_error = ec; + }); + + auto server_error = errc::make_error_code(errc::not_supported); + server_stream.async_handshake(asio_ssl::stream_base::server, + [&server_error](const boost::system::error_code& ec) { + server_error = ec; + }); + + io_context.run(); + CHECK(client_error.category() == system_category()); + CHECK(client_error.value() == CERT_E_UNTRUSTEDROOT); + CHECK_FALSE(server_error); + } + + SECTION("trusted certificate verified") { + client_ctx.verify_server_certificate(true); + + const auto cert_ptr = x509_to_cert_context(net::buffer(test_certificate), boost::wintls::file_format::pem); + client_ctx.add_certificate_authority(cert_ptr.get()); + + auto client_error = errc::make_error_code(errc::not_supported); + client_stream.async_handshake(boost::wintls::handshake_type::client, + [&client_error, &io_context](const boost::system::error_code& ec) { + client_error = ec; + io_context.stop(); + }); + + auto server_error = errc::make_error_code(errc::not_supported); + server_stream.async_handshake(asio_ssl::stream_base::server, + [&server_error](const boost::system::error_code& ec) { + server_error = ec; + }); + io_context.run(); + CHECK_FALSE(client_error); + CHECK_FALSE(server_error); + } + } +} + +TEST_CASE("client certificates") { + using namespace std::string_literals; + + SECTION("wintls client certificate missing with openssl server") { + using namespace boost::system; + wintls_client_context client_ctx; + asio_ssl_server_context server_ctx; + server_ctx.enable_client_verify(); + + net::io_context io_context; + boost::wintls::stream client_stream(io_context, client_ctx); + boost::asio::ssl::stream server_stream(io_context, server_ctx); + + client_stream.next_layer().connect(server_stream.next_layer()); + + auto client_error = errc::make_error_code(errc::not_supported); + client_stream.async_handshake(boost::wintls::handshake_type::client, + [&client_error](const boost::system::error_code& ec) { + client_error = ec; + }); + + auto server_error = errc::make_error_code(errc::not_supported); + server_stream.async_handshake(asio_ssl::stream_base::server, + [&server_error](const boost::system::error_code& ec) { + server_error = ec; + }); + io_context.run(); + // client handshake is failed by server + CHECK(client_error); + // Note: The server error code is 0xa0000c7 or 0xc0c7 depends on the int size + // and expected error code is 199. Error message is correct. + // Seems like the error code lower bits are right, take the lower 2 bytes of the int. + // It is unclear why this happens. + CHECK_THAT(server_error.message(), Catch::Contains("peer did not return a certificate")); + CHECK((server_error.value() & 0xff) == SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); + } + + SECTION("trusted wintls client certificate verified on openssl server") { + using namespace boost::system; + + wintls_client_context client_ctx; + client_ctx.with_test_client_cert(); // Note that if client cert is supplied, sspi will verify server cert with it. + client_ctx.verify_server_certificate(true); + + asio_ssl_server_context server_ctx; + server_ctx.enable_client_verify(); + + net::io_context io_context; + boost::wintls::stream client_stream(io_context, client_ctx); + boost::asio::ssl::stream server_stream(io_context, server_ctx); + + client_stream.next_layer().connect(server_stream.next_layer()); + + auto client_error = errc::make_error_code(errc::not_supported); + client_stream.async_handshake(boost::wintls::handshake_type::client, + [&client_error](const boost::system::error_code& ec) { + client_error = ec; + }); + + auto server_error = errc::make_error_code(errc::not_supported); + server_stream.async_handshake(asio_ssl::stream_base::server, + [&server_error](const boost::system::error_code& ec) { + server_error = ec; + }); + io_context.run(); + CHECK_FALSE(client_error); + CHECK_FALSE(server_error); + } + + SECTION("trusted openssl client certificate verified on openssl server") { + using namespace boost::system; + asio_ssl_client_context client_ctx; + client_ctx.with_test_client_cert(); + client_ctx.enable_server_verify(); + + asio_ssl_server_context server_ctx; + server_ctx.enable_client_verify(); + + net::io_context io_context; + boost::asio::ssl::stream client_stream(io_context, client_ctx); + boost::asio::ssl::stream server_stream(io_context, server_ctx); + + client_stream.next_layer().connect(server_stream.next_layer()); + + auto client_error = errc::make_error_code(errc::not_supported); + client_stream.async_handshake(asio_ssl::stream_base::client, + [&client_error](const boost::system::error_code& ec) { + client_error = ec; + }); + + auto server_error = errc::make_error_code(errc::not_supported); + server_stream.async_handshake(asio_ssl::stream_base::server, + [&server_error](const boost::system::error_code& ec) { + server_error = ec; + }); + io_context.run(); + CHECK_FALSE(client_error); + CHECK_FALSE(server_error); + } + + SECTION("trusted openssl client certificate verified on wintls server") { + using namespace boost::system; + asio_ssl_client_context client_ctx; + client_ctx.with_test_client_cert(); + client_ctx.enable_server_verify(); + + wintls_server_context server_ctx; + server_ctx.enable_client_verify(); + + net::io_context io_context; + boost::asio::ssl::stream client_stream(io_context, client_ctx); + boost::wintls::stream server_stream(io_context, server_ctx); + + client_stream.next_layer().connect(server_stream.next_layer()); + + auto client_error = errc::make_error_code(errc::not_supported); + client_stream.async_handshake(asio_ssl::stream_base::client, + [&client_error](const boost::system::error_code& ec) { + client_error = ec; + }); + + auto server_error = errc::make_error_code(errc::not_supported); + server_stream.async_handshake(boost::wintls::handshake_type::server, + [&server_error](const boost::system::error_code& ec) { + server_error = ec; + }); + io_context.run(); + CHECK_FALSE(client_error); + CHECK_FALSE(server_error); + } + + SECTION("openssl client missing certificate on wintls server") { + using namespace boost::system; + asio_ssl_client_context client_ctx; + + wintls_server_context server_ctx; + server_ctx.enable_client_verify(); + + net::io_context io_context; + boost::asio::ssl::stream client_stream(io_context, client_ctx); + boost::wintls::stream server_stream(io_context, server_ctx); + + client_stream.next_layer().connect(server_stream.next_layer()); + + auto client_error = errc::make_error_code(errc::not_supported); + client_stream.async_handshake(asio_ssl::stream_base::client, + [&client_error](const boost::system::error_code& ec) { + client_error = ec; + }); + + auto server_error = errc::make_error_code(errc::not_supported); + server_stream.async_handshake(boost::wintls::handshake_type::server, + [&server_error](const boost::system::error_code& ec) { + server_error = ec; + }); + io_context.run(); + CHECK_FALSE(client_error); + CHECK(server_error.value() == SEC_E_NO_CREDENTIALS); + } + + SECTION("trusted wintls client certificate verified on wintls server") { + using namespace boost::system; + wintls_client_context client_ctx; + client_ctx.with_test_client_cert(); + client_ctx.enable_server_verify(); + + wintls_server_context server_ctx; + server_ctx.enable_client_verify(); + + net::io_context io_context; + boost::wintls::stream client_stream(io_context, client_ctx); + boost::wintls::stream server_stream(io_context, server_ctx); + + client_stream.next_layer().connect(server_stream.next_layer()); + + auto client_error = errc::make_error_code(errc::not_supported); + client_stream.async_handshake(boost::wintls::handshake_type::client, + [&client_error](const boost::system::error_code& ec) { + client_error = ec; + }); + + auto server_error = errc::make_error_code(errc::not_supported); + server_stream.async_handshake(boost::wintls::handshake_type::server, + [&server_error](const boost::system::error_code& ec) { + server_error = ec; + }); + io_context.run(); + CHECK_FALSE(client_error); + CHECK_FALSE(server_error); + } +} + +TEST_CASE("failing handshakes") { + boost::wintls::context client_ctx(boost::wintls::method::system_default); + net::io_context io_context; + boost::wintls::stream client_stream(io_context, client_ctx); + test_stream server_stream(io_context); + + client_stream.next_layer().connect(server_stream); + + SECTION("invalid server reply") { + using namespace boost::system; + + auto error = errc::make_error_code(errc::not_supported); + client_stream.async_handshake(boost::wintls::handshake_type::client, + [&error](const boost::system::error_code& ec) { + error = ec; + }); + + std::array buffer; + server_stream.async_read_some(net::buffer(buffer, buffer.size()), + [&buffer, &server_stream](const boost::system::error_code&, std::size_t length) { + tls_record rec(net::buffer(buffer, length)); + REQUIRE(rec.type == tls_record::record_type::handshake); + auto handshake = boost::get(rec.message); + REQUIRE(handshake.type == tls_handshake::handshake_type::client_hello); + // Echoing the client_hello message back should cause the handshake to fail + net::write(server_stream, net::buffer(buffer)); + }); + + io_context.run(); + CHECK(error.category() == boost::system::system_category()); + CHECK(error.value() == SEC_E_ILLEGAL_MESSAGE); + } +} + +TEST_CASE("ssl/tls versions") { + const auto value = GENERATE(values>({ + { boost::wintls::method::tlsv1, tls_version::tls_1_0 }, + { boost::wintls::method::tlsv1_client, tls_version::tls_1_0 }, + { boost::wintls::method::tlsv11, tls_version::tls_1_1 }, + { boost::wintls::method::tlsv11_client, tls_version::tls_1_1 }, + { boost::wintls::method::tlsv12, tls_version::tls_1_2 }, + { boost::wintls::method::tlsv12_client, tls_version::tls_1_2 }, + { boost::wintls::method::tlsv13, tls_version::tls_1_3 }, + { boost::wintls::method::tlsv13_client, tls_version::tls_1_3 } + }) + ); + + const auto method = value.first; + const auto version = value.second; + + boost::wintls::context client_ctx(method); + net::io_context io_context; + boost::wintls::stream client_stream(io_context, client_ctx); + test_stream server_stream(io_context); + + client_stream.next_layer().connect(server_stream); + + client_stream.async_handshake(boost::wintls::handshake_type::client, + [method, &io_context](const boost::system::error_code& ec) { + if (ec.value() == SEC_E_ALGORITHM_MISMATCH) { + WARN("Protocol not supported: " << method); + io_context.stop(); + return; + } + REQUIRE(ec == net::error::eof); + }); + + std::array buffer; + server_stream.async_read_some(net::buffer(buffer, buffer.size()), + [&buffer, &server_stream, &version](const boost::system::error_code&, std::size_t length) { + tls_record rec(net::buffer(buffer, length)); + REQUIRE(rec.type == tls_record::record_type::handshake); + CHECK(rec.version == version); + server_stream.close(); + }); + + io_context.run(); +} diff --git a/third-party/boost-wintls/test/main.cpp b/third-party/boost-wintls/test/main.cpp new file mode 100644 index 00000000000..6313742aa59 --- /dev/null +++ b/third-party/boost-wintls/test/main.cpp @@ -0,0 +1,34 @@ +#define CATCH_CONFIG_RUNNER +#include + +#include "certificate.hpp" +#include "unittest.hpp" + +#include + +#include +#include + +int main(int argc, char* argv[]) { + // Ensure the test are using US English locale. Some tests depend on + // comparing potentially localized message strings. + SetThreadUILanguage(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT)); + + boost::system::error_code ec; + boost::wintls::delete_private_key(test_key_name, ec); + boost::wintls::import_private_key(net::buffer(test_key), boost::wintls::file_format::pem, test_key_name, ec); + if (ec) { + std::cerr << "Unable to import private test key: " << ec.message() << "\n"; + return EXIT_FAILURE; + } + + int result = Catch::Session().run(argc, argv); + + boost::wintls::delete_private_key(test_key_name, ec); + if (ec) { + std::cerr << "Unable to delete private test key: " << ec.message() << "\n"; + return EXIT_FAILURE; + } + + return result; +} diff --git a/third-party/boost-wintls/test/ocsp_responder.hpp b/third-party/boost-wintls/test/ocsp_responder.hpp new file mode 100644 index 00000000000..2552d71cadc --- /dev/null +++ b/third-party/boost-wintls/test/ocsp_responder.hpp @@ -0,0 +1,31 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_WINTLS_OCSP_RESPONDER_HPP +#define BOOST_WINTLS_OCSP_RESPONDER_HPP + +// Boost.Process misses an algorithm include in Boost 1.77, +// see https://github.com/boostorg/process/issues/213. +#include +#include + +// Start an OCSP responder at http://localhost:5000 that can provide OCSP responses for +// test certificates signed by test_certificates/ca_intermediate.crt. +inline boost::process::child start_ocsp_responder() { + auto path = boost::process::search_path("openssl.exe"); + auto args = boost::process::args({"ocsp", + "-CApath", TEST_CERTIFICATES_PATH, + "-index", TEST_CERTIFICATES_PATH "certindex", + "-port", "5000", + "-nmin", "1", + "-rkey", TEST_CERTIFICATES_PATH "ocsp_signer_ca_intermediate.key", + "-rsigner", TEST_CERTIFICATES_PATH "ocsp_signer_ca_intermediate.crt", + "-CA", TEST_CERTIFICATES_PATH "ca_intermediate.crt"}); + return boost::process::child(path, args, boost::process::std_out > boost::process::null); +} + +#endif diff --git a/third-party/boost-wintls/test/sspi_buffer_sequence_test.cpp b/third-party/boost-wintls/test/sspi_buffer_sequence_test.cpp new file mode 100644 index 00000000000..7286ce544ee --- /dev/null +++ b/third-party/boost-wintls/test/sspi_buffer_sequence_test.cpp @@ -0,0 +1,44 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include "unittest.hpp" + +#include + +#include + +using boost::wintls::detail::sspi_buffer; +using boost::wintls::detail::sspi_buffer_sequence; + +class test_buffer_sequence : public sspi_buffer_sequence<4> { +public: + test_buffer_sequence() + : sspi_buffer_sequence(std::array { + SECBUFFER_EMPTY, + SECBUFFER_EMPTY, + SECBUFFER_EMPTY, + SECBUFFER_EMPTY + }) { + } +}; + +static_assert(boost::wintls::net::is_const_buffer_sequence::value, + "ConstBufferSequence type requirements not met"); + +static_assert(boost::wintls::net::is_mutable_buffer_sequence::value, + "MutableBufferSequence type requirements not met"); + +TEST_CASE("sspi buffer sequence") { + test_buffer_sequence sequence; + CHECK(std::distance(sequence.begin(), sequence.end()) == 4); + CHECK(std::all_of(sequence.begin(), sequence.end(), [](const auto& buffer) { + return buffer.cbBuffer == 0; + })); + CHECK(std::all_of(sequence.begin(), sequence.end(), [](const auto& buffer) { + return buffer.pvBuffer == nullptr; + })); +} diff --git a/third-party/boost-wintls/test/stream_test.cpp b/third-party/boost-wintls/test/stream_test.cpp new file mode 100644 index 00000000000..2e636a728f0 --- /dev/null +++ b/third-party/boost-wintls/test/stream_test.cpp @@ -0,0 +1,254 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include "unittest.hpp" +#include "asio_ssl_server_stream.hpp" +#include "wintls_client_stream.hpp" +#include "wintls_server_stream.hpp" +#include "echo_client.hpp" +#include "echo_server.hpp" +#include "async_echo_client.hpp" +#include "async_echo_server.hpp" + +#include +#include + +#include + +#include +#include +#include + +class test_server : public async_echo_server { +public: + test_server(net::io_context& context) + : async_echo_server(context) { + } + + void do_read() final { + } +}; + +TEST_CASE("moved stream") { + boost::asio::io_context ioc; + + wintls_server_context server_ctx; + boost::wintls::stream moved_server_stream(ioc, server_ctx); + boost::wintls::stream server_stream(std::move(moved_server_stream)); + + wintls_client_context client_ctx; + boost::wintls::stream moved_client_stream(ioc, client_ctx); + boost::wintls::stream client_stream(std::move(moved_client_stream)); + + client_stream.next_layer().connect(server_stream.next_layer()); + + boost::system::error_code client_ec{}; + boost::system::error_code server_ec{}; + + server_stream.async_handshake(boost::wintls::handshake_type::server, + [&server_ec, &server_stream](const boost::system::error_code& ec) { + server_ec = ec; + if (ec) { + server_stream.next_layer().close(); + } + }); + + client_stream.async_handshake(boost::wintls::handshake_type::client, + [&client_ec, &client_stream](const boost::system::error_code& ec) { + client_ec = ec; + if (ec) { + client_stream.next_layer().close(); + } + }); + ioc.run(); + CHECK_FALSE(client_ec); + CHECK_FALSE(server_ec); +} + +TEST_CASE("handshake not done") { + boost::wintls::context ctx{boost::wintls::method::system_default}; + boost::asio::io_context ioc; + std::array buf{}; + + boost::wintls::stream stream(ioc, ctx); + boost::system::error_code ec{}; + + SECTION("write fails") { + boost::wintls::net::write(stream, boost::wintls::net::buffer(buf), ec); + CHECK(ec); + } + + SECTION("async_write fails") { + boost::wintls::net::async_write(stream, boost::wintls::net::buffer(buf), + [&ec](const boost::system::error_code& error, std::size_t) { + ec = error; + }); + ioc.run_one(); + CHECK(ec); + } + + SECTION("read fails") { + boost::wintls::net::read(stream, boost::wintls::net::buffer(buf), ec); + CHECK(ec); + } + + SECTION("async_read fails") { + boost::wintls::net::async_read(stream, boost::wintls::net::buffer(buf), + [&ec](const boost::system::error_code& error, std::size_t) { + ec = error; + }); + ioc.run_one(); + CHECK(ec); + } +} + +TEST_CASE("underlying stream errors") { + SECTION("sync test") { + net::io_context io_context; + echo_server server(io_context); + boost::system::error_code client_ec{}; + + SECTION("handshake error") { + boost::beast::test::fail_count fc(4); + wintls_client_stream client(io_context, fc); + + client.stream.next_layer().connect(server.stream.next_layer()); + + auto handshake_result = server.handshake(); + client.stream.handshake(wintls_client_stream::handshake_type::client, client_ec); + REQUIRE_FALSE(handshake_result.get()); + CHECK(client_ec.value() == 1); + } + + SECTION("failing read/write") { + boost::beast::test::fail_count fc(5); + wintls_client_stream client(io_context, fc); + + client.stream.next_layer().connect(server.stream.next_layer()); + + auto handshake_result = server.handshake(); + client.stream.handshake(wintls_client_stream::handshake_type::client, client_ec); + REQUIRE_FALSE(handshake_result.get()); + REQUIRE_FALSE(client_ec); + + SECTION("read error") { + net::streambuf client_data; + net::read(client.stream, client_data, client_ec); + CHECK(client_ec.value() == 1); + } + + SECTION("write error") { + std::string str{"abcd"}; + net::write(client.stream, net::buffer(str), client_ec); + CHECK(client_ec.value() == 1); + } + } + } + + SECTION("async test") { + net::io_context io_context; + boost::system::error_code client_ec{}; + + test_server server(io_context); + + SECTION("handshake error") { + boost::beast::test::fail_count fc(4); + wintls_client_stream client(io_context, fc); + client.stream.next_layer().connect(server.stream.next_layer()); + server.run(); + client.stream.async_handshake(wintls_client_stream::handshake_type::client, + [&client_ec](const boost::system::error_code& ec) { + client_ec = ec; + }); + io_context.run(); + CHECK(client_ec.value() == 1); + } + + SECTION("failing read/write") { + boost::beast::test::fail_count fc(5); + wintls_client_stream client(io_context, fc); + client.stream.next_layer().connect(server.stream.next_layer()); + boost::asio::streambuf buffer; + server.run(); + + SECTION("read error") { + client.stream.async_handshake(wintls_client_stream::handshake_type::client, + [&client_ec, &client, &buffer](const boost::system::error_code& ec) { + REQUIRE_FALSE(ec); + net::async_read(client.stream, buffer, [&client_ec](const boost::system::error_code& error, std::size_t) { + client_ec = error; + }); + }); + io_context.run(); + CHECK(client_ec.value() == 1); + } + + SECTION("write error") { + client.stream.async_handshake(wintls_client_stream::handshake_type::client, + [&client_ec, &client, &buffer](const boost::system::error_code& ec) { + REQUIRE_FALSE(ec); + net::async_write(client.stream, buffer, [&client_ec](const boost::system::error_code& error, std::size_t) { + client_ec = error; + }); + }); + io_context.run(); + CHECK(client_ec.value() == 1); + } + } + } +} + +TEST_CASE("small reads") { + using namespace std::string_literals; + + net::io_context io_context; + const auto test_data = "Der er et yndigt land\0"s; + + SECTION("async client test") { + async_echo_server server(io_context); + async_echo_client client(io_context, test_data); + client.stream.next_layer().read_size(0x20); + client.stream.next_layer().connect(server.stream.next_layer()); + server.run(); + client.run(); + io_context.run(); + CHECK(client.received_message() == test_data); + } + + SECTION("async server test") { + async_echo_server server(io_context); + async_echo_client client(io_context, test_data); + server.stream.next_layer().read_size(0x20); + client.stream.next_layer().connect(server.stream.next_layer()); + server.run(); + client.run(); + io_context.run(); + CHECK(client.received_message() == test_data); + } + + SECTION("sync test") { + echo_server server(io_context); + echo_client client(io_context); + client.stream.next_layer().read_size(0x20); + client.stream.next_layer().connect(server.stream.next_layer()); + + auto handshake_result = server.handshake(); + client.handshake(); + REQUIRE_FALSE(handshake_result.get()); + + client.write(test_data); + server.read(); + server.write(); + client.read(); + + auto shutdown_result = server.shutdown(); + client.shutdown(); + REQUIRE_FALSE(shutdown_result.get()); + + CHECK(client.data() == test_data); + } +} diff --git a/third-party/boost-wintls/test/test_certificates/conf/ca_intermediate.conf b/third-party/boost-wintls/test/test_certificates/conf/ca_intermediate.conf new file mode 100644 index 00000000000..506adaf30f0 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/conf/ca_intermediate.conf @@ -0,0 +1,58 @@ +[ ca ] +default_ca = myca + +[ myca ] +dir = gen +certs = $dir # Where the issued certs are kept +crl_dir = $dir # Where the issued crls are kept +database = $dir/certindex # database index file. +new_certs_dir = $dir/newcerts # default place for new certs. +certificate = $dir/ca_intermediate.crt # The CA certificate +private_key = $dir/ca_intermediate.key +serial = $dir/certserial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + +unique_subject = no +default_days = 36525 +default_md = sha1 +x509_extensions = myca_extensions +default_crl_days = 36525 # this is required to generate CRL from this config +policy = myca_policy + +[ myca_policy ] +countryName = optional +stateOrProvinceName = optional +localityName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + + +[ myca_extensions ] +basicConstraints = CA:false +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always +keyUsage = digitalSignature,keyEncipherment +extendedKeyUsage = serverAuth +#crlDistributionPoints = URI:localhost/root.crl # will make certificate revocation fail if this endpoint does not exist + +[ req ] +default_bits = 4096 +default_md = sha256 +distinguished_name = req_distinguished_name +encrypt_key = no +prompt = no +x509_extensions = req_v3_ca + +[ req_distinguished_name ] +countryName = DK +localityName = Copenhagen +organizationName = WinTLS +commonName = WinTLS Intermediate Certificate Authority + +[ req_v3_ca ] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +basicConstraints = CA:true +keyUsage = cRLSign, keyCertSign diff --git a/third-party/boost-wintls/test/test_certificates/conf/ca_root.conf b/third-party/boost-wintls/test/test_certificates/conf/ca_root.conf new file mode 100644 index 00000000000..aac24f5c137 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/conf/ca_root.conf @@ -0,0 +1,47 @@ +[ ca ] +default_ca = myca + +[ myca ] +dir = gen +certs = $dir # Where the issued certs are kept +crl_dir = $dir # Where the issued crls are kept +database = $dir/certindex # database index file. +new_certs_dir = $dir/newcerts # default place for new certs. +certificate = $dir/ca_root.crt # The CA certificate +private_key = $dir/ca_root.key +serial = $dir/certserial # The current serial number +crlnumber = $dir/crlnumber # the current crl number + +unique_subject = no +default_days = 36525 +default_md = sha1 +x509_extensions = myca_extensions +default_crl_days = 36525 # this is required to generate CRL from this config + +[ myca_extensions ] +basicConstraints = CA:false +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always +keyUsage = digitalSignature,keyEncipherment +extendedKeyUsage = serverAuth +#crlDistributionPoints = URI:localhost/root.crl # will make certificate revocation fail if this endpoint does not exist + +[ req ] +default_bits = 4096 +default_md = sha256 +distinguished_name = req_distinguished_name +encrypt_key = no +prompt = no +x509_extensions = req_v3_ca + +[ req_distinguished_name ] +countryName = DK +localityName = Copenhagen +organizationName = WinTLS +commonName = WinTLS Root Certificate Authority + +[ req_v3_ca ] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +basicConstraints = CA:true +keyUsage = cRLSign, keyCertSign diff --git a/third-party/boost-wintls/test/test_certificates/conf/leaf.conf b/third-party/boost-wintls/test/test_certificates/conf/leaf.conf new file mode 100644 index 00000000000..324a8e3381a --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/conf/leaf.conf @@ -0,0 +1,21 @@ +[ req ] +default_bits = 2048 +distinguished_name = req_distinguished_name +encrypt_key = no +prompt = no +req_extensions = req_v3_usr + +[ req_distinguished_name ] +countryName = DK +localityName = Copenhagen +organizationName = WinTLS +commonName = wintls.test + +[ req_v3_usr ] +basicConstraints = CA:FALSE +subjectAltName = @alt_names +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +[ alt_names ] +DNS.1 = wintls.test +DNS.2 = *.wintls.test diff --git a/third-party/boost-wintls/test/test_certificates/conf/leaf_ocsp.conf b/third-party/boost-wintls/test/test_certificates/conf/leaf_ocsp.conf new file mode 100644 index 00000000000..f2085459de1 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/conf/leaf_ocsp.conf @@ -0,0 +1,22 @@ +[ req ] +default_bits = 2048 +distinguished_name = req_distinguished_name +encrypt_key = no +prompt = no +req_extensions = req_v3_usr + +[ req_distinguished_name ] +countryName = DK +localityName = Copenhagen +organizationName = WinTLS +commonName = wintls.test + +[ req_v3_usr ] +basicConstraints = CA:FALSE +subjectAltName = @alt_names +authorityInfoAccess = OCSP;URI:http://localhost:5000 +keyUsage = nonRepudiation, digitalSignature, keyEncipherment + +[ alt_names ] +DNS.1 = wintls.test +DNS.2 = *.wintls.test diff --git a/third-party/boost-wintls/test/test_certificates/conf/ocsp_signer_ca_intermediate.conf b/third-party/boost-wintls/test/test_certificates/conf/ocsp_signer_ca_intermediate.conf new file mode 100644 index 00000000000..2a96c919383 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/conf/ocsp_signer_ca_intermediate.conf @@ -0,0 +1,18 @@ +[ req ] +default_bits = 4096 +default_md = sha256 +distinguished_name = req_distinguished_name +encrypt_key = no +prompt = no +req_extensions = req_v3_usr + +[ req_distinguished_name ] +countryName = DK +localityName = Copenhagen +organizationName = WinTLS +commonName = WinTLS Intermediate Certificate Authority OCSP signer + +[ req_v3_usr ] +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +extendedKeyUsage = OCSPSigning diff --git a/third-party/boost-wintls/test/test_certificates/gen/ca_intermediate.crt b/third-party/boost-wintls/test/test_certificates/gen/ca_intermediate.crt new file mode 100644 index 00000000000..5d72470b631 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/ca_intermediate.crt @@ -0,0 +1,36 @@ +-----BEGIN CERTIFICATE----- +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 +HBQcQokDeg== +-----END CERTIFICATE----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/ca_intermediate.csr b/third-party/boost-wintls/test/test_certificates/gen/ca_intermediate.csr new file mode 100644 index 00000000000..2596dfdb7b2 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/ca_intermediate.csr @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIErDCCApQCAQAwZzELMAkGA1UEBhMCREsxEzARBgNVBAcMCkNvcGVuaGFnZW4x +DzANBgNVBAoMBldpblRMUzEyMDAGA1UEAwwpV2luVExTIEludGVybWVkaWF0ZSBD +ZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQDC4QuQ1EZaGTNn9+WY0cKOG574afRIUn6O+b/l4f+9vij8EvMh7c62SUGQ +wXOzeO23SjxMAnlmXVmVFT8mHzuLV1D5sR+N57UxtY2QXmn49Ki/+B3WARvXlTAo +IIHQmlhw5HbV/7dcvPXyjCVAX0nwBJvVbyMpgZ7N+z4XCACoscNzBSFuMyhnqFh5 +RyLHRu2gXOYrVGuXss5TiNqA1BXhC1/1Em2NFPYmMtJvz9aBeXQVfAr2HkYQG9dI +NrjNV+GzNRvW5ey4xuOfE3yqXftkpRvwNEN1XUQdcff+faqnkUCb0vFy7aIgZ9fY +wJaUgG4owwnt6ZBklSBaEHqaOvw/9hc3K1WGR2UES1EYFiBebzLbuLgNNSE6pmKl +PXsHRAEbDeZfcYzSlsoEJOCkLBLhqq4QJ2BK3aieF9IYVNEo8FF2wayJgA2xNUZx +6LPlj2ouZS8HIKe7tPWMUjI96sADxhhDP7UTXBEufDKoenLlX3As9vKunxyhgh0H +98GA5fEJmtAvwpz9BIqktA9KcQ9VeSq6GtNSiPZOE3SnjNxdlHgOoNgswKM7Aohb +xt5EOlexhurwpbs55ACTWUV7UL5MqUgAE4/EpDTALqvNGn7PAs4xHkI7io6tsgij +AyrZcl9F85Zy3aG9xtXQDyb7MSFGQv3DXwSCQxrISK3xLMt+5wIDAQABoAAwDQYJ +KoZIhvcNAQELBQADggIBAEFoqmGMexA4efoE9sOHBewwVZmaP0dniXat+Zf2LPOD +C+TU9RihPCfP1HNpJmktiE1xK+s+FzAZCmobFiiR6T7D6u17uoGOfvkEcmKSNvvu +H/Wl+E72y8+DNX4IUDqUftCcE+e8v9KLB0VNY8MDVb3qDC1Y6GxwOIfX7VyzkiH+ +Luf/BllALy/byhzdpj9L0LibH9v0em7QeaPAbbiXMzcgePQymWipZm/XzV4A2tMQ +e1C/u1ZCuv3p4zePFl39QOkKtHwH2SMe6jHSDJgx1IUuTMnbJaK6nlfq14pKTLkd +lmXxnEYegbvcQLFDKNRxHoDXMDZoa2/+Ht0IDPv1K8LMS+87m/KJJQJZMW5DdZSu +N2xWrUMSSKZgz4gfivZXsxYswlodHGfFI9thppZzTn7TWDKPoLaNR2ZpEHKuhILY +01pgNER6fLgHaPnKs8lSE/AIsv78KHt/OXzZnbrKZkpGbZeZZreCyw8l/idmjzvv +xX3zxS+sjOu/CKozD6r/0D8CNR0hSKbbqyxu3LMoNObaWiqwPXZaKSXDRG+caExa +93lljSFlDeHJV2aJo7M73244hDw9vxY3OiNQkmuOtH048SqGTEW6XUJQ+VBS9R4u +gHSvWvQO04cRnSnUUV87eZQ9B8sCEbaF9sZhMMiJfV2vyh/XLxaRf3T6Q2Iz6den +-----END CERTIFICATE REQUEST----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/ca_intermediate.key b/third-party/boost-wintls/test/test_certificates/gen/ca_intermediate.key new file mode 100644 index 00000000000..fc7c02a929e --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/ca_intermediate.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +76mjsECzPPzp8O9e0JTilkWV7uy/Ewc= +-----END PRIVATE KEY----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/ca_intermediate_empty.crl.pem b/third-party/boost-wintls/test/test_certificates/gen/ca_intermediate_empty.crl.pem new file mode 100644 index 00000000000..268567e8f00 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/ca_intermediate_empty.crl.pem @@ -0,0 +1,17 @@ +-----BEGIN X509 CRL----- +MIICwjCBqwIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJESzETMBEGA1UE +BwwKQ29wZW5oYWdlbjEPMA0GA1UECgwGV2luVExTMTIwMAYDVQQDDClXaW5UTFMg +SW50ZXJtZWRpYXRlIENlcnRpZmljYXRlIEF1dGhvcml0eRcNMjIwODE3MDg1OTQ5 +WhgPMjEyMjA4MTgwODU5NDlaoA4wDDAKBgNVHRQEAwIBAjANBgkqhkiG9w0BAQUF +AAOCAgEAE9HEQXWXZ+02IUMWPZD2oPmfY13unhvK5+sucqk5W5P3QZfO/9Hggtug +oQr9IHk2Aenr5MvcACUvQDHtuotFnL538BGw4O7pOlCZgqgYkI9p2e0TfZAR5oWj +ItCi3wKlo/VqJNlWcbaDz2w4ARIs3RPTEROeM5jEog+0yFWuoACMRirztHSiqE4h +wUj4LGcHuhX+F9SplQ0nLAfNzidQwvLdOY4H1EjhyQkYM7HFEROgwwafuECtMeY1 +mzh8JweejVKkfPqlt3aCIugsmmqQkh2JT1CBxjLF90BhrT4K5bJ8fgPvsBeY9nmr +goXpaU40wcps88LSyWURwoFfnZ3r/0d2OZghK455Nd5gC4FKTbrc+Q1oxSV4/+lg +O3un+303Cqlf7abVC67VS/obrlkCJMzkGJUeEN+cD4l+f6KcBprxg5oMDAnWUzR0 +H9bA9Qb13ugQmq9zzDIx5dIJkraWxeryG8fXZjHa0+BRRfP5EN477EfflBalCPVT +zRD9OjkWr7Dct4vqeW9gNxTdwm+XlIdIA1UnKNWRPnz8WcGUXyFlAKkJKyET5tZu +DuLs6VcCzjU4glADp5KJH0f76H8zYWEgn2Ne4E+O3ClidjmOQjZ4eERV4xCPEqP1 +ATgWtVluGsl7iMEMj9VrQhgKPk0E/kKeGlIFEWVvZR1BU4VnplU= +-----END X509 CRL----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/ca_intermediate_leaf_revoked.crl.pem b/third-party/boost-wintls/test/test_certificates/gen/ca_intermediate_leaf_revoked.crl.pem new file mode 100644 index 00000000000..723ddd69821 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/ca_intermediate_leaf_revoked.crl.pem @@ -0,0 +1,18 @@ +-----BEGIN X509 CRL----- +MIIC7DCB1QIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJESzETMBEGA1UE +BwwKQ29wZW5oYWdlbjEPMA0GA1UECgwGV2luVExTMTIwMAYDVQQDDClXaW5UTFMg +SW50ZXJtZWRpYXRlIENlcnRpZmljYXRlIEF1dGhvcml0eRcNMjIwODE3MDg1OTQ5 +WhgPMjEyMjA4MTgwODU5NDlaMCgwEgIBARcNMjIwODE3MDg1OTQ5WjASAgEDFw0y +MjA4MTcwODU5NDlaoA4wDDAKBgNVHRQEAwIBAzANBgkqhkiG9w0BAQUFAAOCAgEA +YS5Hq50Dwc1UVeMew+jsMrcIbkB2MJijYEVpRqZH/fUJYKUctO+p2A7wjL1nnoSq +y2miEz5RcIx39cNXdZnSAKKLn17ecOV1b9moFJriSirtJ7bgMKjdnq91uqDd+0r5 +DbMbc3rPKFA5GW5b3/C5TgRGCTrRxAJuTZxndRXzY5vdAL/TvO9CiDL/2qNYtWMN +gGUArVL7h2HiX5vs+57R0G0QOTIEgx7wp18JTdhxVSBFNe5FHgqjfUTGMjrs+uU0 +oNAA7xxHtoYpRObcQlBxX3YpNzs8z/6R/hCOb11WrBzmXD9owXkVdt0mrG/bMZt8 +hbhZmwTKFxir8bQWdqMf/nFvXVYvjNOv5nrlZ7cFQN0o5Kq9GKfsi81eD+hySTI5 +sAD3NZtwvdRYZXlPsstFN6iMnRmMFQvkgBJE6OJNO9AotDjSmTgYLy1B7hTsctY0 +JVG6Pds0klaiBGh/yRu2VoKphoRm9RxkUwYzhIhcvxcnWIenCu8JX2agnrReeKim +8L5QDCH8oetdJpEQn9xw6jVtXG9JwhhYpRXybhVgU4wm+V8Q8ANVHGm0GS7vwucZ +4Twmmph55zotkJaQQ2CeyFAadqQdG4lPEXex5JFu1DE8aTAawp+/yS23Tn2f0cEN +W/m+t4JG4L65+xpiwUqmSebZzCO4xxei4y4HcbOCAeI= +-----END X509 CRL----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/ca_root.crt b/third-party/boost-wintls/test/test_certificates/gen/ca_root.crt new file mode 100644 index 00000000000..80e24730a25 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/ca_root.crt @@ -0,0 +1,35 @@ +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/ca_root.key b/third-party/boost-wintls/test/test_certificates/gen/ca_root.key new file mode 100644 index 00000000000..3056bad06f0 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/ca_root.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDA7qd/UIiTVlW+ +lr551aMLXowrEI+YOalvKGJwkCVkW4n871V4FpSrepGxk6Uz+XKZ66irzNZq3XJ8 +2VW8Xg8HAisxA1xr/1d1GYvC6WhZ/dTWyU8RhviiRAX8q4+tBU3CTikA8lUZQhPM +KOVCIljlO5U9xlqBwy87yZ99EcpO5KAwvy3sW70DN9Pl/Cx7iIxlTYp0P6mSB/Dt +NwJjkE3prvScLmMChCRjh4/v1O8ksRQsO0oN56Ix1xo8r/qVrinWuGJSXx7brFru +KoSkE0sZonNntXG5ftbto+1/AKgwQfGplT7AbG10bAKaK7hkFkxRDqY0BRW1ZXt0 +fZRUw29BvyCPSrGZMMdvRGeVeYCCsUUIYbf8zqO9ZtZCFDtiAA1RDyXl6191r1JQ +wtk6PSxopVLNw7wU6krrWJCK7RK8K2rDw8ZyOzxtpYVAGlpv6aFUWSYJMhoBYeRO +AH5Z/yK/RHzidhj8U96adrK+DmAVWQim7r3RCN9m+RlDYBTWwWeIVaX3p7hDzL3z +TiRMTqgl5IpPNg/9Ita0ZkWCGrxaZ3SlUcSavDuAUipQVvoA807aI/VBwZazvxAp +8Ucx40AyHwYEkhupOV3j6IdM5p1BrNRLFsLxavbx9k6H9M30pEhmKRXk0WKRBLfF +eZj+luaER7lAAAsnsxZ4y/+rwSEuuQIDAQABAoICAH4GJmEygNQFTCMforJAy6zs +iJDE05dy6utSLOMsNVCVvs/6ohC8Z0aP3MVrFTmbErHaTqZSOik6F8PXz3oo0pYY +Y5AzitZ8x2sVUcby4hgOh035120yhgywdFy00DgLw9xNY9lbchz6naX5fK+zce/i ++LyOaaZjkeHy9Pwkd8sK6lyNNPk0f4WvnPmYvJHBAzxU50DCKQjbqRO6oBPbOhmQ +D/ZJEqGdIYvmDC50H/YOuYee/uOQT9FQmbHUndHSH0BD1u3JdoW10vvJyDTI6YCI +LewriGrLoKdAMi2Ih1Rmbu4AMCpPaTvoJdcBAgRW0GkOMaC/RYvlCzxvn0mzE2Ny +HRqzgBx5WKDPfPN4HER3FVnEcTM0meN8ELo7VAs9yNOaH9bPv1cectYTRU2zztuy +vH4oVUFTkToA6gywWheXT3tMQe4xbJIJytyKW+zgV6gtRhDMsVhqzGtqqwgpJ7Pt +Cn87dvY9PeBQF5CG1CtskmXGg+JWS8c0vDT517U8XH0sgrvAHb970kRybHqAJN69 +X6Uj6VLPPZsPnyMsz3aW3c/xSI0U2DmjoJ7hOzkHf3CbYNcXDcMSGlmReRXnx5lA +M6sSJJAi51W1FWKNDoI7/ZEkVwGwLi/1Z5vRY7EfAFgPAONTUNf/jrIDRjb5zW+v +M77kEPxW7yI1T61OiYrVAoIBAQD10LcDNBkix8m48RhEMlGfcHxYaMuQ7djGDXYp +bHI0FLXKeoVTGB8d6mDvNn3Mh94p/yN4OLZEJOT2NEnDsbgVXWOYTfiH3V4gZGum +Smwn9OYCnuY0De1MJ5EuToQgQKNlEuhoI2FRjOQYcIpFpjYaXzQn2EGwP+yFMIua +eunTH/Gfa08uDMZq08NS4n/hcO7/jq4hrgtZiDs3oojRnajPrwefCBYNRbUtLCDF +TW2FLl+1gJVkvLk1JqARZZbdzKHekO3gq7dyygg7Ms1JQ00Uu+Zibsnp+P1Phn7v +UK7V/L1tniKTFRLdWO+5F4G/XwlA7U3UtITHkHXHDn5cZJ3/AoIBAQDI7QaOJUnk +AAdIM16HuuTDGRdcX1i4+IQtFMDdofUUAyvDtoZHEZQLT0KPYIsGs+mh/JinpTT2 +kKC9jkrAURdnwFM2bLjOV8APmM/IGPEE+dDUcT/PymYeTsHWeMyO/x4cXDDtfhcI +uqcpPwXuxFj7cnvOrcXfB6dfMRJ9LDujyazwjyF4dXyAAH3NPbDRqQ6u4pTpsbhT +n2TD0dvMXcHHZQiJhmDzRLchUdHczo8YqDya1L75JygNvvZrZFbTWoA7gBouPLYw +C39Rk92ESeQrf64WD0/R/I+9lf4q6+Hz6cuTcxq0fc3CASLY00gDmAAjf5L97sEn +12fJVvEvYKNHAoIBAQDev3oH2h7o6HgAMeEWcy6Jt0nGZ3gH5a/okGxBzzaRwS6W +w32rNZGE701Vl2BZhcko7z06BNINYA1mmS06uwGfwpesfQM4Qr23xqfR8WCeuInx +WAIsq24b80LY3mdWPpyRy5d0PpNCbdSH3Ps/cAVY0mqVrJ6h0ttGOh5XJwhZu3md +R4Vhqkvmo+w8YGkXZdn9FFLwzCEWyZ83o/4tTJubTvUuBArPjhpGS9WKVMZoyAQM +me9GcMm3wz+LZC5Y4MTRxSz5yUEcML1Sv49M00K3BioXimNHtMv+U1cVD1zPJg6V +lZWpCJCmqZ/ZbtaxDrJ49lDv7YDgwiQn9BdHLBoLAoIBADDMiHQLkGekriAWAdZ7 +SMYtmOPhcF30Vb3RNYpepHRI1N9CvFgUZ91bUbIa44ksNwkVnUnSMQvVUoTXQ0Z0 +K3gSWON2AmhzHX1sQsK5dAgeWF7QZowj/ytLO37Idf4g7gI7TdLQde2zz5eP6/Py +kh33zyQCRnWFmVvgQjpOfOmpuKvwR1PHTQaVl/g6DHDPW3aUJ1CezkLZCpMYrAZ1 +mvO/kRQ9o9xRixy3j33OWSjG63k7RGqk3PCBub2ZcBEDAPPyh+lE64a9tB1vCTTw +8U6zQueurlc0vQBxpnpsMcOYu83C/fBqQYfl2L3Kisn8p8P3Xw73ZsgzY8ydphQ4 +p08CggEAXUOQFXX7/e4soClXvqFdHSkoE9KvB8ITctxSUODuCNnNae1rhzMN5yG1 +Kauk8Mu0zaqmjvZyBUN9xplg5Ohkzni4A6vhRo6JZXks4zcq30SEjMeMAu14ma59 +yUFQt57unw+2A61EIK+1OXdudBCRjp3FrEs7wYw3opmnkVB0eLsPst13+oTrXR30 +qurphbJlhWs2R3/fKk52wK71fXB3HFXNZOQiPMNKdReoaGYSNZ9rfYfBI+fRXwlZ +x0v8sZ05/BGRDLmGREmfDl9h9l1ArH2LGjJdzh3SZYv7YfbqXIfGz/baN5oO0M4u +KN5fw7t2iHHqzY5EuqtORZJwdAQEUg== +-----END PRIVATE KEY----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/ca_root.srl b/third-party/boost-wintls/test/test_certificates/gen/ca_root.srl new file mode 100644 index 00000000000..80d7fe1c533 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/ca_root.srl @@ -0,0 +1 @@ +64FA361CB1C0E15061C3F51F5A6C9A77DED5D886 diff --git a/third-party/boost-wintls/test/test_certificates/gen/ca_root_empty.crl.pem b/third-party/boost-wintls/test/test_certificates/gen/ca_root_empty.crl.pem new file mode 100644 index 00000000000..5c387a92158 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/ca_root_empty.crl.pem @@ -0,0 +1,17 @@ +-----BEGIN X509 CRL----- +MIICujCBowIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJESzETMBEGA1UE +BwwKQ29wZW5oYWdlbjEPMA0GA1UECgwGV2luVExTMSowKAYDVQQDDCFXaW5UTFMg +Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkXDTIyMDgxNzA4NTk0OVoYDzIxMjIw +ODE4MDg1OTQ5WqAOMAwwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEFBQADggIBAMCf +EnoWuMttPeUnQ4eFaDXCfJznL+Bw/5BcuZSuQRwHuLLiSQ9qZ4XgjioUFdNgee7P +zvKf+yJ0ZLi+eYMdWP4ver2uCGZL4FIR6erTPJRCzxDdRDeGzHsTTiPGcdg1fMEx +8xSf3sLSoruyv1vJFuDC1attJrP6S6zqPAGfQTfpvHp+1TapH/eeqgKuxCYOFr1I +hGP5QNSOwZOhvm/CNE2Y7tqYFYo6JHGSKJvghUakjfJ5w7SzqfryekWj0IhFEauG +8783kGMmTfgyc9pPZqMHrQ51/MM47FnUAOwyb1eU+7nBwsBhpl08rSHX/f8fT8Zu +DhYdPSFmXgNYuEZ5KAf+LKPqpbCCDTTsWBlG/RqIotF6yASEuAl5I5r3EuylXMnQ +4pTwbvLqe1F6CGiF+SwgnYDCTEoDr+WE7dKuyzPbjwv1F0QLEMPuiWI0uJrFbP4k +7OQ8nE5eIND8tObMca2xbdXg29V8TmB3/8s8f5aBoPOre92rnJkd7IBbNUxsB8kc +/z//2q6ykIpVPO74JLHM3jysApdzJJbNZz96mtKYmSx79h4E/gZh+DAYm1DtehGP +GLvztuo5vKgS6b4TQRtJKCuxZUYJlvIP9GOOL4fTP7+VLfTm7Tf0XhgF93/6ae3m +tKrJONtwRXWO2Gy/se5NdWloK3cXUQfqcib2Vo9m +-----END X509 CRL----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/certindex b/third-party/boost-wintls/test/test_certificates/gen/certindex new file mode 100644 index 00000000000..74fb16f00ba --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/certindex @@ -0,0 +1,4 @@ +R 21220818085948Z 220817085949Z 01 unknown /C=DK/L=Copenhagen/O=WinTLS/CN=wintls.test +V 21220818085948Z 02 unknown /C=DK/L=Copenhagen/O=WinTLS/CN=wintls.test +R 21220818085948Z 220817085949Z 03 unknown /C=DK/L=Copenhagen/O=WinTLS/CN=wintls.test +V 21220818085948Z 04 unknown /C=DK/L=Copenhagen/O=WinTLS/CN=WinTLS Intermediate Certificate Authority OCSP signer diff --git a/third-party/boost-wintls/test/test_certificates/gen/certindex.attr b/third-party/boost-wintls/test/test_certificates/gen/certindex.attr new file mode 100644 index 00000000000..3a7e39e6ee6 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/certindex.attr @@ -0,0 +1 @@ +unique_subject = no diff --git a/third-party/boost-wintls/test/test_certificates/gen/certindex.attr.old b/third-party/boost-wintls/test/test_certificates/gen/certindex.attr.old new file mode 100644 index 00000000000..3a7e39e6ee6 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/certindex.attr.old @@ -0,0 +1 @@ +unique_subject = no diff --git a/third-party/boost-wintls/test/test_certificates/gen/certindex.old b/third-party/boost-wintls/test/test_certificates/gen/certindex.old new file mode 100644 index 00000000000..64d7d6a5138 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/certindex.old @@ -0,0 +1,4 @@ +R 21220818085948Z 220817085949Z 01 unknown /C=DK/L=Copenhagen/O=WinTLS/CN=wintls.test +V 21220818085948Z 02 unknown /C=DK/L=Copenhagen/O=WinTLS/CN=wintls.test +V 21220818085948Z 03 unknown /C=DK/L=Copenhagen/O=WinTLS/CN=wintls.test +V 21220818085948Z 04 unknown /C=DK/L=Copenhagen/O=WinTLS/CN=WinTLS Intermediate Certificate Authority OCSP signer diff --git a/third-party/boost-wintls/test/test_certificates/gen/certserial b/third-party/boost-wintls/test/test_certificates/gen/certserial new file mode 100644 index 00000000000..eeee65ec419 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/certserial @@ -0,0 +1 @@ +05 diff --git a/third-party/boost-wintls/test/test_certificates/gen/certserial.old b/third-party/boost-wintls/test/test_certificates/gen/certserial.old new file mode 100644 index 00000000000..64969239d5f --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/certserial.old @@ -0,0 +1 @@ +04 diff --git a/third-party/boost-wintls/test/test_certificates/gen/crlnumber b/third-party/boost-wintls/test/test_certificates/gen/crlnumber new file mode 100644 index 00000000000..64969239d5f --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/crlnumber @@ -0,0 +1 @@ +04 diff --git a/third-party/boost-wintls/test/test_certificates/gen/crlnumber.old b/third-party/boost-wintls/test/test_certificates/gen/crlnumber.old new file mode 100644 index 00000000000..75016ea3625 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/crlnumber.old @@ -0,0 +1 @@ +03 diff --git a/third-party/boost-wintls/test/test_certificates/gen/leaf.crt b/third-party/boost-wintls/test/test_certificates/gen/leaf.crt new file mode 100644 index 00000000000..a58e91ceaea --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/leaf.crt @@ -0,0 +1,96 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DK, L=Copenhagen, O=WinTLS, CN=WinTLS Intermediate Certificate Authority + Validity + Not Before: Aug 17 08:59:48 2022 GMT + Not After : Aug 18 08:59:48 2122 GMT + Subject: C=DK, L=Copenhagen, O=WinTLS, CN=wintls.test + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:b4:97:8c:f2:fd:42:fe:d8:bf:2d:40:39:7f:b0: + c0:fa:6c:bf:c7:69:cf:a1:1d:f3:14:d7:a5:ef:38: + d2:cd:f2:73:45:4c:92:72:4c:4f:3f:77:53:47:c4: + 54:e6:9d:a4:40:d2:72:a9:c5:7b:a6:86:08:f3:fe: + d1:cc:95:d9:85:7f:ea:1d:4d:50:dc:07:44:4b:d9: + 87:d9:d6:16:a7:54:89:bd:ec:ea:81:93:8a:f1:3b: + 8f:09:95:51:cd:8a:fd:5b:cc:31:0e:5c:19:65:25: + 5d:66:ca:ba:81:c0:83:b3:6b:a8:ac:8d:38:76:25: + d9:d6:a4:9a:9c:68:e4:15:1c:97:92:43:11:0c:8f: + 44:fc:22:d0:c0:f8:7b:1e:d5:10:58:f2:3d:e1:41: + 11:91:e4:d3:d2:f0:91:73:a9:3d:bb:e8:06:04:6d: + ec:3e:89:f2:88:57:89:f5:d9:29:55:2f:e8:ec:ba: + 14:26:d8:81:d4:9b:2f:28:46:4f:10:8f:9c:03:9b: + e5:71:4e:59:ba:4e:4e:e1:34:9c:da:ed:4b:e4:fc: + 04:5f:48:d8:21:db:92:aa:57:cf:39:7d:f1:f2:69: + 86:4f:05:a1:15:e9:d0:74:59:7c:46:e7:05:1e:8c: + 57:2a:50:56:9b:ed:60:8e:d6:bf:9f:45:29:37:cd: + fb:b1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Subject Alternative Name: + DNS:wintls.test, DNS:*.wintls.test + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Signature Algorithm: sha1WithRSAEncryption + a1:49:09:a6:70:13:39:cb:a8:60:35:ff:70:22:2e:ea:c8:ad: + 14:8c:6e:af:a7:86:19:13:8e:7f:2f:6b:93:8b:2a:25:73:df: + ae:4d:10:84:73:3f:57:27:67:64:49:76:fb:79:05:2f:9b:48: + b8:e0:db:90:be:78:dc:cd:e3:87:b9:1b:09:1b:64:bf:0c:79: + c1:30:19:71:bf:a5:74:00:16:1a:0c:dd:6d:f2:ca:c7:66:96: + 86:64:bb:2c:c4:5e:69:1c:fd:b9:ea:60:03:69:e3:ab:b8:af: + b1:7f:22:79:d5:aa:e6:7e:94:28:03:d7:c0:0f:94:84:86:f1: + df:03:6e:34:20:5a:01:6a:d2:61:f7:e3:a4:af:c2:ab:cf:50: + 04:56:c6:91:f9:0a:b8:fe:1d:d0:49:57:3b:d1:a6:23:7f:cb: + 2e:b6:2c:db:1e:fd:3e:83:3f:52:10:60:05:da:cf:b1:66:94: + 44:ff:ae:de:f2:2f:29:4b:4f:fd:b1:76:de:7e:55:83:9e:4b: + ac:50:b5:c4:07:af:60:5e:35:bb:23:cd:bc:6c:5c:f9:f4:c4: + ae:f9:d9:d9:da:cf:18:a0:ee:34:98:ff:b3:a6:7c:bd:be:6f: + e7:10:be:6c:0a:87:e7:02:dd:bc:3b:7e:aa:df:3c:d8:c7:79: + 84:89:ef:46:84:f0:7a:61:da:a0:ec:03:77:bf:5a:07:bf:8b: + fa:c1:e4:f8:20:c7:97:5e:a6:d0:48:f9:e2:8b:3c:6b:c9:01: + 9d:2d:d4:6a:2e:1b:6e:b7:61:b8:1d:a0:fd:0f:df:72:10:99: + 29:d8:0d:e0:26:6d:ee:52:0a:56:3b:ea:d9:ca:c0:6f:b9:c9: + 37:fe:0e:ea:0b:74:42:5a:4c:93:72:87:39:2e:00:27:e5:26: + 92:89:5a:c0:0c:1a:c8:41:6a:b5:9a:91:67:81:ea:47:20:30: + 6f:03:ec:9f:b6:c7:60:6e:cf:d8:96:7b:01:71:e5:8f:79:b3: + f6:63:e1:a5:4c:56:8d:7a:f6:e2:e1:74:60:d3:41:49:12:e1: + 28:df:13:61:d1:10:d2:92:b6:88:b4:19:27:41:4f:41:48:77: + e1:57:76:75:f1:e1:84:da:41:01:dd:42:4c:b7:0a:9a:e3:23: + a1:2f:cc:d8:84:a6:a2:f8:cd:77:c1:79:49:28:9c:60:f6:37: + 92:51:46:f9:a4:b0:d6:3d:86:73:33:86:8f:30:29:cd:df:45: + 24:f8:2e:f9:84:4f:87:df:ac:09:c1:db:29:8d:df:62:d5:72: + 8a:f3:90:24:80:04:17:13:60:3d:9b:1f:6f:17:d9:33:c6:1f: + d0:46:9f:a2:f8:64:26:ee +-----BEGIN CERTIFICATE----- +MIIEbjCCAlagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJESzET +MBEGA1UEBwwKQ29wZW5oYWdlbjEPMA0GA1UECgwGV2luVExTMTIwMAYDVQQDDClX +aW5UTFMgSW50ZXJtZWRpYXRlIENlcnRpZmljYXRlIEF1dGhvcml0eTAgFw0yMjA4 +MTcwODU5NDhaGA8yMTIyMDgxODA4NTk0OFowSTELMAkGA1UEBhMCREsxEzARBgNV +BAcMCkNvcGVuaGFnZW4xDzANBgNVBAoMBldpblRMUzEUMBIGA1UEAwwLd2ludGxz +LnRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0l4zy/UL+2L8t +QDl/sMD6bL/Hac+hHfMU16XvONLN8nNFTJJyTE8/d1NHxFTmnaRA0nKpxXumhgjz +/tHMldmFf+odTVDcB0RL2YfZ1hanVIm97OqBk4rxO48JlVHNiv1bzDEOXBllJV1m +yrqBwIOza6isjTh2JdnWpJqcaOQVHJeSQxEMj0T8ItDA+Hse1RBY8j3hQRGR5NPS +8JFzqT276AYEbew+ifKIV4n12SlVL+jsuhQm2IHUmy8oRk8Qj5wDm+VxTlm6Tk7h +NJza7Uvk/ARfSNgh25KqV885ffHyaYZPBaEV6dB0WXxG5wUejFcqUFab7WCO1r+f +RSk3zfuxAgMBAAGjQTA/MAkGA1UdEwQCMAAwJQYDVR0RBB4wHIILd2ludGxzLnRl +c3SCDSoud2ludGxzLnRlc3QwCwYDVR0PBAQDAgXgMA0GCSqGSIb3DQEBBQUAA4IC +AQChSQmmcBM5y6hgNf9wIi7qyK0UjG6vp4YZE45/L2uTiyolc9+uTRCEcz9XJ2dk +SXb7eQUvm0i44NuQvnjczeOHuRsJG2S/DHnBMBlxv6V0ABYaDN1t8srHZpaGZLss +xF5pHP256mADaeOruK+xfyJ51armfpQoA9fAD5SEhvHfA240IFoBatJh9+Okr8Kr +z1AEVsaR+Qq4/h3QSVc70aYjf8sutizbHv0+gz9SEGAF2s+xZpRE/67e8i8pS0/9 +sXbeflWDnkusULXEB69gXjW7I828bFz59MSu+dnZ2s8YoO40mP+zpny9vm/nEL5s +CofnAt28O36q3zzYx3mEie9GhPB6Ydqg7AN3v1oHv4v6weT4IMeXXqbQSPniizxr +yQGdLdRqLhtut2G4HaD9D99yEJkp2A3gJm3uUgpWO+rZysBvuck3/g7qC3RCWkyT +coc5LgAn5SaSiVrADBrIQWq1mpFngepHIDBvA+yftsdgbs/YlnsBceWPebP2Y+Gl +TFaNevbi4XRg00FJEuEo3xNh0RDSkraItBknQU9BSHfhV3Z18eGE2kEB3UJMtwqa +4yOhL8zYhKai+M13wXlJKJxg9jeSUUb5pLDWPYZzM4aPMCnN30Uk+C75hE+H36wJ +wdspjd9i1XKK85AkgAQXE2A9mx9vF9kzxh/QRp+i+GQm7g== +-----END CERTIFICATE----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/leaf.csr b/third-party/boost-wintls/test/test_certificates/gen/leaf.csr new file mode 100644 index 00000000000..68d2d8d62bc --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/leaf.csr @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIC3jCCAcYCAQAwSTELMAkGA1UEBhMCREsxEzARBgNVBAcMCkNvcGVuaGFnZW4x +DzANBgNVBAoMBldpblRMUzEUMBIGA1UEAwwLd2ludGxzLnRlc3QwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0l4zy/UL+2L8tQDl/sMD6bL/Hac+hHfMU +16XvONLN8nNFTJJyTE8/d1NHxFTmnaRA0nKpxXumhgjz/tHMldmFf+odTVDcB0RL +2YfZ1hanVIm97OqBk4rxO48JlVHNiv1bzDEOXBllJV1myrqBwIOza6isjTh2JdnW +pJqcaOQVHJeSQxEMj0T8ItDA+Hse1RBY8j3hQRGR5NPS8JFzqT276AYEbew+ifKI +V4n12SlVL+jsuhQm2IHUmy8oRk8Qj5wDm+VxTlm6Tk7hNJza7Uvk/ARfSNgh25Kq +V885ffHyaYZPBaEV6dB0WXxG5wUejFcqUFab7WCO1r+fRSk3zfuxAgMBAAGgUDBO +BgkqhkiG9w0BCQ4xQTA/MAkGA1UdEwQCMAAwJQYDVR0RBB4wHIILd2ludGxzLnRl +c3SCDSoud2ludGxzLnRlc3QwCwYDVR0PBAQDAgXgMA0GCSqGSIb3DQEBCwUAA4IB +AQBYStpagr76UuEEkZl4XB5Q3urQJRbGY7vQqcZPp5zhtrZBPrs0ZfEHYe8MWDYc +IsKFM0CZoAQrJ7UumNg7A/bYO5XIjbrO+Lm1VRBP4zBBJuldIvJfV7T/7uh/29Yk +X1wfXL/r2BsQINgEWi1uXDkPSKAtGGTJbG0AD3BLdoUUJRoZIdSit60g3dxxtTaR +FjlZM+IbIC8Lr5iBxc31KWfg5o2eYTZErxcQgxj2Cf0GfRtxkhNDydZlrbD8I0dB +RjjR0qnoUsLiYs1j6+1RqmResR43gufS6oYY/fDvTJuX04trn7Py2Qcsl8j1i0S4 +JaqLeh0VeuBVuxX9rGVmODYT +-----END CERTIFICATE REQUEST----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/leaf.key b/third-party/boost-wintls/test/test_certificates/gen/leaf.key new file mode 100644 index 00000000000..63d5d4487c8 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/leaf.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC0l4zy/UL+2L8t +QDl/sMD6bL/Hac+hHfMU16XvONLN8nNFTJJyTE8/d1NHxFTmnaRA0nKpxXumhgjz +/tHMldmFf+odTVDcB0RL2YfZ1hanVIm97OqBk4rxO48JlVHNiv1bzDEOXBllJV1m +yrqBwIOza6isjTh2JdnWpJqcaOQVHJeSQxEMj0T8ItDA+Hse1RBY8j3hQRGR5NPS +8JFzqT276AYEbew+ifKIV4n12SlVL+jsuhQm2IHUmy8oRk8Qj5wDm+VxTlm6Tk7h +NJza7Uvk/ARfSNgh25KqV885ffHyaYZPBaEV6dB0WXxG5wUejFcqUFab7WCO1r+f +RSk3zfuxAgMBAAECggEARhwsAU3ni47UMZokeHlDgjVkAuQGUpORAn9yETxrQr8k +lzvSAwOzJH2L3GnRWDLNSMkq8NQVXCHfKfK8uoNWjmiJmFSi1rkPf670+dIOu2mr +jAuFQ0bngx3POzY4KucR02ijhuKkjUsDRtvfqm3181sRgePVjrDFMHp4984U9kib +ES8xv9lzYfRAASeUjQ23bIIr11eTfcjFP/wV/h5b2UdC4FEoin+jST+5dWxVkLBo +3HhHMQmwLMfsmNHPYY2B3OXssnp/kd/dEsA4//Xocs/HLXcjLvVXqGBBbiDRIyyi +t2dzbSqTy9dPAyyocXYCgzKfgd3fZIFFIxyBlu8ZrQKBgQDl18wd9hJ6gW62g0Jj +sBb57KzFN+lpyIbHimluqAPK2WAtdV0KSDjK81sSmwYF2sJApUDMOFL5aJS048Es +hU30OmKIvCRYrCsh5c1drPh5B61JucRc1yPhXoncEzxHRAdhqfsd2JZAzeLYaDYE +6bPBftRq1BBhlcQ62jF0MiH3XwKBgQDJJOJ6zLkbyKzmE7zvu5dVzKLrwyLsdtQc +mIZujEtTjm8NZaljrl+/Cr+QzzXqGyynNr/yoBoU8GVn8BP/xF4qhhWd8Ze8kk26 +KWcHJ3KFPcG8CFm5D0muhZwgTXHCTmB5V/80evl1fFBbVxppPUiC5xaXsKrOOvCN +zSj9mlY27wKBgG7i98UUrMGRpFpFZUg28j7NYmUbnm68odmu+0K5qGq7CN2lm6eU +RGIVmkCVrggxDDqn/2UHX3CYdfX3U4EpJvzHFjalnltxZLXL6pJhGtc5Tu8cwpGP +8e2O8K/OT+yJ8424tkAl+Ad3zRNe44DnRyP5Dn4jpWuPF8bU8br/XMe9AoGAY/v6 +vHIBXcc98sxC8aP9EQA8yBbiyEo1G9XRlSgV1X4Kw80SC2PFYlB0cwYdVbaWVrRH +a9KbxGbO8YCMYGn7KQYnvrA17d2H1473EL5SFdth7xbziqMHzEHMHt6AOsb8+7R7 +PloWoIjf5NeCYGe/IJrARzzhWsw/gS1HP/C1BG8CgYAX7uz65vPDxslIV8M/LdrF +TXghBH0oqofCOabIF7EULHImCTX4x/rlxkl2ZEHiGYXDiWLJ7EdESO2lAn4+R6LR +uysMPuAsbx6jMamM3xSepGgGlwPIYfhyhWZwVZniNxyiho+Vf2tQoqYfSa0i6xac +z25kGNwmP21xY5pnSW7Wnw== +-----END PRIVATE KEY----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/leaf_chain.pem b/third-party/boost-wintls/test/test_certificates/gen/leaf_chain.pem new file mode 100644 index 00000000000..489f7e35bb4 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/leaf_chain.pem @@ -0,0 +1,167 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DK, L=Copenhagen, O=WinTLS, CN=WinTLS Intermediate Certificate Authority + Validity + Not Before: Aug 17 08:59:48 2022 GMT + Not After : Aug 18 08:59:48 2122 GMT + Subject: C=DK, L=Copenhagen, O=WinTLS, CN=wintls.test + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:b4:97:8c:f2:fd:42:fe:d8:bf:2d:40:39:7f:b0: + c0:fa:6c:bf:c7:69:cf:a1:1d:f3:14:d7:a5:ef:38: + d2:cd:f2:73:45:4c:92:72:4c:4f:3f:77:53:47:c4: + 54:e6:9d:a4:40:d2:72:a9:c5:7b:a6:86:08:f3:fe: + d1:cc:95:d9:85:7f:ea:1d:4d:50:dc:07:44:4b:d9: + 87:d9:d6:16:a7:54:89:bd:ec:ea:81:93:8a:f1:3b: + 8f:09:95:51:cd:8a:fd:5b:cc:31:0e:5c:19:65:25: + 5d:66:ca:ba:81:c0:83:b3:6b:a8:ac:8d:38:76:25: + d9:d6:a4:9a:9c:68:e4:15:1c:97:92:43:11:0c:8f: + 44:fc:22:d0:c0:f8:7b:1e:d5:10:58:f2:3d:e1:41: + 11:91:e4:d3:d2:f0:91:73:a9:3d:bb:e8:06:04:6d: + ec:3e:89:f2:88:57:89:f5:d9:29:55:2f:e8:ec:ba: + 14:26:d8:81:d4:9b:2f:28:46:4f:10:8f:9c:03:9b: + e5:71:4e:59:ba:4e:4e:e1:34:9c:da:ed:4b:e4:fc: + 04:5f:48:d8:21:db:92:aa:57:cf:39:7d:f1:f2:69: + 86:4f:05:a1:15:e9:d0:74:59:7c:46:e7:05:1e:8c: + 57:2a:50:56:9b:ed:60:8e:d6:bf:9f:45:29:37:cd: + fb:b1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Subject Alternative Name: + DNS:wintls.test, DNS:*.wintls.test + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Signature Algorithm: sha1WithRSAEncryption + a1:49:09:a6:70:13:39:cb:a8:60:35:ff:70:22:2e:ea:c8:ad: + 14:8c:6e:af:a7:86:19:13:8e:7f:2f:6b:93:8b:2a:25:73:df: + ae:4d:10:84:73:3f:57:27:67:64:49:76:fb:79:05:2f:9b:48: + b8:e0:db:90:be:78:dc:cd:e3:87:b9:1b:09:1b:64:bf:0c:79: + c1:30:19:71:bf:a5:74:00:16:1a:0c:dd:6d:f2:ca:c7:66:96: + 86:64:bb:2c:c4:5e:69:1c:fd:b9:ea:60:03:69:e3:ab:b8:af: + b1:7f:22:79:d5:aa:e6:7e:94:28:03:d7:c0:0f:94:84:86:f1: + df:03:6e:34:20:5a:01:6a:d2:61:f7:e3:a4:af:c2:ab:cf:50: + 04:56:c6:91:f9:0a:b8:fe:1d:d0:49:57:3b:d1:a6:23:7f:cb: + 2e:b6:2c:db:1e:fd:3e:83:3f:52:10:60:05:da:cf:b1:66:94: + 44:ff:ae:de:f2:2f:29:4b:4f:fd:b1:76:de:7e:55:83:9e:4b: + ac:50:b5:c4:07:af:60:5e:35:bb:23:cd:bc:6c:5c:f9:f4:c4: + ae:f9:d9:d9:da:cf:18:a0:ee:34:98:ff:b3:a6:7c:bd:be:6f: + e7:10:be:6c:0a:87:e7:02:dd:bc:3b:7e:aa:df:3c:d8:c7:79: + 84:89:ef:46:84:f0:7a:61:da:a0:ec:03:77:bf:5a:07:bf:8b: + fa:c1:e4:f8:20:c7:97:5e:a6:d0:48:f9:e2:8b:3c:6b:c9:01: + 9d:2d:d4:6a:2e:1b:6e:b7:61:b8:1d:a0:fd:0f:df:72:10:99: + 29:d8:0d:e0:26:6d:ee:52:0a:56:3b:ea:d9:ca:c0:6f:b9:c9: + 37:fe:0e:ea:0b:74:42:5a:4c:93:72:87:39:2e:00:27:e5:26: + 92:89:5a:c0:0c:1a:c8:41:6a:b5:9a:91:67:81:ea:47:20:30: + 6f:03:ec:9f:b6:c7:60:6e:cf:d8:96:7b:01:71:e5:8f:79:b3: + f6:63:e1:a5:4c:56:8d:7a:f6:e2:e1:74:60:d3:41:49:12:e1: + 28:df:13:61:d1:10:d2:92:b6:88:b4:19:27:41:4f:41:48:77: + e1:57:76:75:f1:e1:84:da:41:01:dd:42:4c:b7:0a:9a:e3:23: + a1:2f:cc:d8:84:a6:a2:f8:cd:77:c1:79:49:28:9c:60:f6:37: + 92:51:46:f9:a4:b0:d6:3d:86:73:33:86:8f:30:29:cd:df:45: + 24:f8:2e:f9:84:4f:87:df:ac:09:c1:db:29:8d:df:62:d5:72: + 8a:f3:90:24:80:04:17:13:60:3d:9b:1f:6f:17:d9:33:c6:1f: + d0:46:9f:a2:f8:64:26:ee +-----BEGIN CERTIFICATE----- +MIIEbjCCAlagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJESzET +MBEGA1UEBwwKQ29wZW5oYWdlbjEPMA0GA1UECgwGV2luVExTMTIwMAYDVQQDDClX +aW5UTFMgSW50ZXJtZWRpYXRlIENlcnRpZmljYXRlIEF1dGhvcml0eTAgFw0yMjA4 +MTcwODU5NDhaGA8yMTIyMDgxODA4NTk0OFowSTELMAkGA1UEBhMCREsxEzARBgNV +BAcMCkNvcGVuaGFnZW4xDzANBgNVBAoMBldpblRMUzEUMBIGA1UEAwwLd2ludGxz +LnRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0l4zy/UL+2L8t +QDl/sMD6bL/Hac+hHfMU16XvONLN8nNFTJJyTE8/d1NHxFTmnaRA0nKpxXumhgjz +/tHMldmFf+odTVDcB0RL2YfZ1hanVIm97OqBk4rxO48JlVHNiv1bzDEOXBllJV1m +yrqBwIOza6isjTh2JdnWpJqcaOQVHJeSQxEMj0T8ItDA+Hse1RBY8j3hQRGR5NPS +8JFzqT276AYEbew+ifKIV4n12SlVL+jsuhQm2IHUmy8oRk8Qj5wDm+VxTlm6Tk7h +NJza7Uvk/ARfSNgh25KqV885ffHyaYZPBaEV6dB0WXxG5wUejFcqUFab7WCO1r+f +RSk3zfuxAgMBAAGjQTA/MAkGA1UdEwQCMAAwJQYDVR0RBB4wHIILd2ludGxzLnRl +c3SCDSoud2ludGxzLnRlc3QwCwYDVR0PBAQDAgXgMA0GCSqGSIb3DQEBBQUAA4IC +AQChSQmmcBM5y6hgNf9wIi7qyK0UjG6vp4YZE45/L2uTiyolc9+uTRCEcz9XJ2dk +SXb7eQUvm0i44NuQvnjczeOHuRsJG2S/DHnBMBlxv6V0ABYaDN1t8srHZpaGZLss +xF5pHP256mADaeOruK+xfyJ51armfpQoA9fAD5SEhvHfA240IFoBatJh9+Okr8Kr +z1AEVsaR+Qq4/h3QSVc70aYjf8sutizbHv0+gz9SEGAF2s+xZpRE/67e8i8pS0/9 +sXbeflWDnkusULXEB69gXjW7I828bFz59MSu+dnZ2s8YoO40mP+zpny9vm/nEL5s +CofnAt28O36q3zzYx3mEie9GhPB6Ydqg7AN3v1oHv4v6weT4IMeXXqbQSPniizxr +yQGdLdRqLhtut2G4HaD9D99yEJkp2A3gJm3uUgpWO+rZysBvuck3/g7qC3RCWkyT +coc5LgAn5SaSiVrADBrIQWq1mpFngepHIDBvA+yftsdgbs/YlnsBceWPebP2Y+Gl +TFaNevbi4XRg00FJEuEo3xNh0RDSkraItBknQU9BSHfhV3Z18eGE2kEB3UJMtwqa +4yOhL8zYhKai+M13wXlJKJxg9jeSUUb5pLDWPYZzM4aPMCnN30Uk+C75hE+H36wJ +wdspjd9i1XKK85AkgAQXE2A9mx9vF9kzxh/QRp+i+GQm7g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIGMzCCBBugAwIBAgIUZPo2HLHA4VBhw/UfWmyad97V2IYwDQYJKoZIhvcNAQEL +BQAwXzELMAkGA1UEBhMCREsxEzARBgNVBAcMCkNvcGVuaGFnZW4xDzANBgNVBAoM +BldpblRMUzEqMCgGA1UEAwwhV2luVExTIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9y +aXR5MCAXDTIyMDgxNzA4NTk0OFoYDzIxMjIwODE4MDg1OTQ4WjBnMQswCQYDVQQG +EwJESzETMBEGA1UEBwwKQ29wZW5oYWdlbjEPMA0GA1UECgwGV2luVExTMTIwMAYD +VQQDDClXaW5UTFMgSW50ZXJtZWRpYXRlIENlcnRpZmljYXRlIEF1dGhvcml0eTCC +AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMLhC5DURloZM2f35ZjRwo4b +nvhp9EhSfo75v+Xh/72+KPwS8yHtzrZJQZDBc7N47bdKPEwCeWZdWZUVPyYfO4tX +UPmxH43ntTG1jZBeafj0qL/4HdYBG9eVMCgggdCaWHDkdtX/t1y89fKMJUBfSfAE +m9VvIymBns37PhcIAKixw3MFIW4zKGeoWHlHIsdG7aBc5itUa5eyzlOI2oDUFeEL +X/USbY0U9iYy0m/P1oF5dBV8CvYeRhAb10g2uM1X4bM1G9bl7LjG458TfKpd+2Sl +G/A0Q3VdRB1x9/59qqeRQJvS8XLtoiBn19jAlpSAbijDCe3pkGSVIFoQepo6/D/2 +FzcrVYZHZQRLURgWIF5vMtu4uA01ITqmYqU9ewdEARsN5l9xjNKWygQk4KQsEuGq +rhAnYErdqJ4X0hhU0SjwUXbBrImADbE1RnHos+WPai5lLwcgp7u09YxSMj3qwAPG +GEM/tRNcES58Mqh6cuVfcCz28q6fHKGCHQf3wYDl8Qma0C/CnP0EiqS0D0pxD1V5 +Kroa01KI9k4TdKeM3F2UeA6g2CzAozsCiFvG3kQ6V7GG6vCluznkAJNZRXtQvkyp +SAATj8SkNMAuq80afs8CzjEeQjuKjq2yCKMDKtlyX0XzlnLdob3G1dAPJvsxIUZC +/cNfBIJDGshIrfEsy37nAgMBAAGjgdwwgdkwHQYDVR0OBBYEFP2fXHN4oDNY9BY4 +7N4ZqlXTSu2HMIGcBgNVHSMEgZQwgZGAFAaUb1BxnOngKFR/E+SSyoX1z6C2oWOk +YTBfMQswCQYDVQQGEwJESzETMBEGA1UEBwwKQ29wZW5oYWdlbjEPMA0GA1UECgwG +V2luVExTMSowKAYDVQQDDCFXaW5UTFMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3Jp +dHmCFAWSPkjxA+P2vOdCwnlx1XayPacaMAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQD +AgEGMA0GCSqGSIb3DQEBCwUAA4ICAQASF0P49gjruM0dgbfnFUkdLclC5klkSnOu +bHjgzD96is+l/IhC0cEcXtFJ1goJ8gYUELZJaqKtO4tWiTt9rbLsYxdxM/qyYYXq +TSlu2nWaqT4DnLDUtybIrQlf6GNeC24TL+0kww4zl1UhB0Lp73Hj4uZdMGXumjiz +EwXMdjFC02kp2TPVdAFpupPfccCr8jGwjGqQPb0wahVB87BqFFJCu2lseDgYYiDi +Eb0GMZSvfAg0GE0su+rbMBgjy5DSWMxCCVJpgyrJm3IGAugTTT/FD1YHF6ecozE8 +dQCqGLYDVxi/MWjQ6Ns2tU1qWsgmWBTWx0YIZ5PgCujuo5Z9ekAZPUqp9voSEYFB +QUq0+8HEfbOd1Eq+0ArplNJrHmG864vTQMeh2AdXRKx/eOFHs/t1QLBjFzNp762p +4vTYWq1Fd6kCtajCrATMrx0Pr7ObTZqa3qHdRn1leFogA4Z9j2qUmFZSXs3wU1zr +wyKoNBJ6+Fon0coa6sFMjV7d/mpqG6V5vM7rrx0z8CVYQxDpKKf3CKh/7trbC45+ +J0rNDliapTlsU0jo2bRt8xWx3gma2v2QNf/T+cRSQsfqFkyiWL6Cqvftb0g8cK8m +Jn/63MXOoOdULNqoFL5S5JsKuDZXHQWI0y2IRedIZ+a4Y/HTj+bE9U5QtRhk29rl +HBQcQokDeg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/leaf_ocsp.crt b/third-party/boost-wintls/test/test_certificates/gen/leaf_ocsp.crt new file mode 100644 index 00000000000..48e71767841 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/leaf_ocsp.crt @@ -0,0 +1,100 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DK, L=Copenhagen, O=WinTLS, CN=WinTLS Intermediate Certificate Authority + Validity + Not Before: Aug 17 08:59:48 2022 GMT + Not After : Aug 18 08:59:48 2122 GMT + Subject: C=DK, L=Copenhagen, O=WinTLS, CN=wintls.test + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:df:7f:eb:a0:1b:78:9f:a1:f7:13:8e:68:40:e0: + 50:f9:00:cd:8f:f0:92:a3:fb:33:d2:5a:27:1a:62: + 35:7c:82:2f:fb:73:27:e2:e7:2f:f8:d1:f4:89:8e: + f0:a8:9b:47:86:a9:d9:28:50:a8:c4:75:2e:bf:e7: + 59:a4:bb:f3:0d:87:7d:a3:cf:8a:e0:53:c2:b7:0c: + 0a:c7:36:74:db:0f:77:08:92:42:02:eb:16:52:97: + ee:f3:ec:2c:9b:9d:d3:da:6e:3a:4e:89:d4:f6:27: + 48:1f:2a:ab:a1:51:18:a5:e6:94:3d:56:20:1c:35: + 91:ca:ec:62:21:f5:c4:1c:6e:6a:f2:1f:32:1d:06: + ea:ae:a8:af:89:02:c5:ec:18:9d:ba:92:96:d8:96: + f6:94:6b:ba:52:cc:55:2e:c5:5e:56:1d:82:fa:33: + 34:3e:2e:8e:45:0b:94:4a:bb:25:74:f2:4b:3c:5d: + 9b:c4:06:7e:76:f5:f8:7a:b6:ec:db:28:80:71:bf: + 29:46:09:1c:22:a8:9d:96:61:a8:62:db:9d:f2:b9: + ea:8b:45:65:ab:37:b2:cd:71:28:7c:69:d2:63:f7: + af:11:f0:a5:80:43:06:ee:5d:31:af:b6:af:86:f4: + c4:a4:e5:8e:45:e2:e1:fb:20:6d:ff:e3:34:55:3e: + c8:23 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Subject Alternative Name: + DNS:wintls.test, DNS:*.wintls.test + Authority Information Access: + OCSP - URI:http://localhost:5000 + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Signature Algorithm: sha1WithRSAEncryption + aa:8a:0f:88:d8:84:8e:90:fe:88:b5:ed:65:55:00:2d:f2:e0: + eb:6d:07:89:70:64:bb:1c:be:29:d4:ad:ff:94:b7:71:08:3d: + 9e:e8:c3:55:56:67:e1:9d:e0:d2:c7:ef:d8:74:c3:a0:30:f9: + fb:9d:f8:10:28:c7:60:77:7a:db:cd:96:ef:02:e2:b9:b4:e1: + 1b:96:ab:8c:ab:f1:86:1c:3f:07:2b:fc:2b:97:fc:c1:30:a7: + cd:63:f3:16:19:9d:b2:71:ee:bd:72:21:d2:0e:59:b3:c4:a4: + 30:af:c7:9f:f0:d7:14:5e:35:28:d8:3f:d3:ca:68:24:1d:31: + ca:84:80:10:50:54:c1:62:84:b6:fa:21:4b:9a:16:1d:f0:a4: + 75:e9:5a:e4:2c:3d:91:3c:68:42:e6:4f:25:e6:a0:b8:f2:a9: + e1:00:59:80:a3:c7:7a:8b:77:0e:4b:7a:38:f1:e3:a3:50:62: + 73:73:97:4e:a0:52:65:07:de:73:ae:d1:f2:f3:fd:ae:46:3b: + d0:39:91:db:2a:66:e5:c3:07:60:7c:26:6a:a7:8c:03:8c:ca: + 1c:92:2d:63:dc:46:0c:6f:37:6a:77:52:17:d0:6c:b9:c3:d7: + 24:d1:8c:50:fd:15:c1:f2:9f:76:34:bc:4d:b7:a9:27:17:d5: + 72:84:3d:fe:fb:4f:a6:b3:80:48:ae:c7:58:d6:dd:b8:7e:d5: + 9e:21:3e:d3:b7:e0:cc:c8:9d:a7:9b:cb:57:89:c1:c5:2e:73: + bf:fa:3d:10:d8:b2:5c:7a:d4:6a:03:24:ae:92:38:95:3e:db: + 4d:c1:31:69:17:ae:39:23:30:02:e1:bc:17:a9:ac:60:cb:a6: + 96:92:f3:0a:6c:08:64:9f:3d:ff:05:4c:bb:f9:13:fe:71:f3: + 19:75:ae:36:fe:5f:d6:6c:60:96:b6:c3:40:1d:ca:87:84:2b: + 94:87:59:0a:ae:4e:43:bd:10:59:47:49:c5:d0:36:c8:92:dc: + 79:d2:12:10:cb:8d:fa:d3:c3:22:af:66:eb:d0:c9:f6:41:64: + 16:b9:a9:7a:f1:49:4e:dc:e9:a5:14:e7:5a:f7:a6:e4:d8:4e: + ce:73:24:f7:47:7c:ba:5c:cf:6e:be:ab:d4:3c:33:f0:64:17: + b8:a5:3c:8e:8f:43:25:5d:12:60:8f:78:44:24:4f:fb:f5:6c: + 73:1d:2f:3e:ed:4f:71:84:b4:55:a0:07:1d:c5:84:1b:e7:5b: + c6:0c:78:30:c4:d9:20:8d:94:54:4b:e4:4d:b9:09:d8:93:74: + 6d:70:67:9e:5c:3e:d8:41:8a:df:9c:90:49:61:f1:80:6d:93: + 85:15:c6:bb:bb:3e:39:de +-----BEGIN CERTIFICATE----- +MIIEoTCCAomgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJESzET +MBEGA1UEBwwKQ29wZW5oYWdlbjEPMA0GA1UECgwGV2luVExTMTIwMAYDVQQDDClX +aW5UTFMgSW50ZXJtZWRpYXRlIENlcnRpZmljYXRlIEF1dGhvcml0eTAgFw0yMjA4 +MTcwODU5NDhaGA8yMTIyMDgxODA4NTk0OFowSTELMAkGA1UEBhMCREsxEzARBgNV +BAcMCkNvcGVuaGFnZW4xDzANBgNVBAoMBldpblRMUzEUMBIGA1UEAwwLd2ludGxz +LnRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDff+ugG3ifofcT +jmhA4FD5AM2P8JKj+zPSWicaYjV8gi/7cyfi5y/40fSJjvCom0eGqdkoUKjEdS6/ +51mku/MNh32jz4rgU8K3DArHNnTbD3cIkkIC6xZSl+7z7CybndPabjpOidT2J0gf +KquhURil5pQ9ViAcNZHK7GIh9cQcbmryHzIdBuquqK+JAsXsGJ26kpbYlvaUa7pS +zFUuxV5WHYL6MzQ+Lo5FC5RKuyV08ks8XZvEBn529fh6tuzbKIBxvylGCRwiqJ2W +Yahi253yueqLRWWrN7LNcSh8adJj968R8KWAQwbuXTGvtq+G9MSk5Y5F4uH7IG3/ +4zRVPsgjAgMBAAGjdDByMAkGA1UdEwQCMAAwJQYDVR0RBB4wHIILd2ludGxzLnRl +c3SCDSoud2ludGxzLnRlc3QwMQYIKwYBBQUHAQEEJTAjMCEGCCsGAQUFBzABhhVo +dHRwOi8vbG9jYWxob3N0OjUwMDAwCwYDVR0PBAQDAgXgMA0GCSqGSIb3DQEBBQUA +A4ICAQCqig+I2ISOkP6Ite1lVQAt8uDrbQeJcGS7HL4p1K3/lLdxCD2e6MNVVmfh +neDSx+/YdMOgMPn7nfgQKMdgd3rbzZbvAuK5tOEblquMq/GGHD8HK/wrl/zBMKfN +Y/MWGZ2yce69ciHSDlmzxKQwr8ef8NcUXjUo2D/TymgkHTHKhIAQUFTBYoS2+iFL +mhYd8KR16VrkLD2RPGhC5k8l5qC48qnhAFmAo8d6i3cOS3o48eOjUGJzc5dOoFJl +B95zrtHy8/2uRjvQOZHbKmblwwdgfCZqp4wDjMocki1j3EYMbzdqd1IX0Gy5w9ck +0YxQ/RXB8p92NLxNt6knF9VyhD3++0+ms4BIrsdY1t24ftWeIT7Tt+DMyJ2nm8tX +icHFLnO/+j0Q2LJcetRqAySukjiVPttNwTFpF645IzAC4bwXqaxgy6aWkvMKbAhk +nz3/BUy7+RP+cfMZda42/l/WbGCWtsNAHcqHhCuUh1kKrk5DvRBZR0nF0DbIktx5 +0hIQy43608Mir2br0Mn2QWQWual68UlO3OmlFOda96bk2E7OcyT3R3y6XM9uvqvU +PDPwZBe4pTyOj0MlXRJgj3hEJE/79WxzHS8+7U9xhLRVoAcdxYQb51vGDHgwxNkg +jZRUS+RNuQnYk3RtcGeeXD7YQYrfnJBJYfGAbZOFFca7uz453g== +-----END CERTIFICATE----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/leaf_ocsp.csr b/third-party/boost-wintls/test/test_certificates/gen/leaf_ocsp.csr new file mode 100644 index 00000000000..031f5afd433 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/leaf_ocsp.csr @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIDEzCCAfsCAQAwSTELMAkGA1UEBhMCREsxEzARBgNVBAcMCkNvcGVuaGFnZW4x +DzANBgNVBAoMBldpblRMUzEUMBIGA1UEAwwLd2ludGxzLnRlc3QwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDff+ugG3ifofcTjmhA4FD5AM2P8JKj+zPS +WicaYjV8gi/7cyfi5y/40fSJjvCom0eGqdkoUKjEdS6/51mku/MNh32jz4rgU8K3 +DArHNnTbD3cIkkIC6xZSl+7z7CybndPabjpOidT2J0gfKquhURil5pQ9ViAcNZHK +7GIh9cQcbmryHzIdBuquqK+JAsXsGJ26kpbYlvaUa7pSzFUuxV5WHYL6MzQ+Lo5F +C5RKuyV08ks8XZvEBn529fh6tuzbKIBxvylGCRwiqJ2WYahi253yueqLRWWrN7LN +cSh8adJj968R8KWAQwbuXTGvtq+G9MSk5Y5F4uH7IG3/4zRVPsgjAgMBAAGggYQw +gYEGCSqGSIb3DQEJDjF0MHIwCQYDVR0TBAIwADAlBgNVHREEHjAcggt3aW50bHMu +dGVzdIINKi53aW50bHMudGVzdDAxBggrBgEFBQcBAQQlMCMwIQYIKwYBBQUHMAGG +FWh0dHA6Ly9sb2NhbGhvc3Q6NTAwMDALBgNVHQ8EBAMCBeAwDQYJKoZIhvcNAQEL +BQADggEBAJX6NYQ948gDDfalR8a2MgJ4BPVziwTnbg2liHjefA0hIV5g0de5hZ4u +AxqVaDwTglwjngx4VEnUco8DJhkdNTkMU5Ps28vYmUfe+zrvopxyV4ygHMJSmYtW +XFco/ME0PCyuAHcLaF5bQU+vAiHma+UqsT0jwev86x+8fUwrPuUOvNiAzp4cHCvd +ub7MvnC+rv8ePdqLHnjuAe5k+kl5QaRoV7RuD9rFgpoJkEhn28rK8HmOLDGIvmMD +hvkpwYwKQj3LfuwswGUmkMFLobx3eXSlGmGHMvbYL1frow1jAHQCbq7TXmVFxDZ2 +on7jzQEv35J23k7whhkqlSgqQpmsFYI= +-----END CERTIFICATE REQUEST----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/leaf_ocsp.key b/third-party/boost-wintls/test/test_certificates/gen/leaf_ocsp.key new file mode 100644 index 00000000000..fa9d9f7d98f --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/leaf_ocsp.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDff+ugG3ifofcT +jmhA4FD5AM2P8JKj+zPSWicaYjV8gi/7cyfi5y/40fSJjvCom0eGqdkoUKjEdS6/ +51mku/MNh32jz4rgU8K3DArHNnTbD3cIkkIC6xZSl+7z7CybndPabjpOidT2J0gf +KquhURil5pQ9ViAcNZHK7GIh9cQcbmryHzIdBuquqK+JAsXsGJ26kpbYlvaUa7pS +zFUuxV5WHYL6MzQ+Lo5FC5RKuyV08ks8XZvEBn529fh6tuzbKIBxvylGCRwiqJ2W +Yahi253yueqLRWWrN7LNcSh8adJj968R8KWAQwbuXTGvtq+G9MSk5Y5F4uH7IG3/ +4zRVPsgjAgMBAAECggEBAKsz+DCLGpldnkByw9V+f0henxh1tj66vHWT7YQ+Wq5n +o43AJnufkJXPbry4rAzb9axoCxrgvobPJOKHu5l/B64DbfC/mKhCQVOqe88iHd14 +OTxtnPdTUaQvEjHzZjBGc/RMn4lt954fdRW6wAIwdusOd9uMT8iMGIQTExDkjDch +x2YfmSdjdHr5g/dNeMZsGGDY5joxQ/WK4LzHVSNLeA9tiMzkMIOTHcQRDquSTpfs +UV0jYmhSNVMJwRXQwbq8MHY3NSLj/BmHjw/bPWo+LrlWHsxpiShlKjfM7o1ezgzs +JV9+O5f+koWDVi+YE9LF2eZ+WTwmxbK2qMcURpfs+EECgYEA9OO+6PECXM/58Teg +60W1i2cb5UzS1+nHnTMtsITNaNPpyRloHbc5dEGWxKm4oOFzozyzEpuLUY+kDqHX +al8TcRLJozHA1tdBssevfsTb4Jv+7jL8ZeEGJLSQUGlHKKzB/Cg+VbOUiy4SkMXX +nmk6Y9UKerVQGnSI1S2SecCh+LMCgYEA6aO+G7X76AEvZX4OS4Kn+xQCqqLEV+iF +6egrIc9nwFZzh1ILwFvWu6NUFFCL6kw7KgvcL5LKT0cCgUf1jTdna19JgQKKd009 +UtFV/VOR+agsd5BjFGblfUOlbI63rjb4FiDsznUNe4lZ8EFlZe9oIbM0wX4SnKR2 +bt1ycp3lStECgYA0lB1uOCjQspqwbsgvG4VyC85Seh8e2oPQPafGqYzMwAsG8VyI +XMmKK3bqfKI2cJF6b9Lm4NyVw2hu99KfdRBgi68dSdZkik0BzJvidPPcksG2dN36 +JclC4j3F9gSgOA9iS2Wu0uLGyzqTONclnOQ7gQdB92HefDzQwHsdhv1/vwKBgQDI +3dXbzSG93Qb6ot13XeU9n36LZVSYn3hCGTC76KyyV6ELfiZMQqjiuRDYRkeEL/XN +uFSdMf5tGge1TkB2IGPxlAKFv8F7wBQw13iuSuL9WPCh+qi0KaKzhyz5n9mbFfdE +TxpIhaoJw5RnUlHyyVklYATDNbiao2qO9iQnFkjDgQKBgA6rtAbor9TBx37ykjAT +x0d/SeWhEQMmmJAHJeDlCfZVUwJenN8vaO5mXK8Ti7V8Il6+uo3tKik/FEp5dJsY +0+bPJMAcSumk78j0E/0YSh8dg3X5btD42oLzPBhp4ZwrRU88SUmuOiOWeAfkXaw6 +AkvdeDPDS4CO7pj53MU//PJZ +-----END PRIVATE KEY----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/leaf_ocsp_chain.pem b/third-party/boost-wintls/test/test_certificates/gen/leaf_ocsp_chain.pem new file mode 100644 index 00000000000..8cf0727c227 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/leaf_ocsp_chain.pem @@ -0,0 +1,171 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DK, L=Copenhagen, O=WinTLS, CN=WinTLS Intermediate Certificate Authority + Validity + Not Before: Aug 17 08:59:48 2022 GMT + Not After : Aug 18 08:59:48 2122 GMT + Subject: C=DK, L=Copenhagen, O=WinTLS, CN=wintls.test + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:df:7f:eb:a0:1b:78:9f:a1:f7:13:8e:68:40:e0: + 50:f9:00:cd:8f:f0:92:a3:fb:33:d2:5a:27:1a:62: + 35:7c:82:2f:fb:73:27:e2:e7:2f:f8:d1:f4:89:8e: + f0:a8:9b:47:86:a9:d9:28:50:a8:c4:75:2e:bf:e7: + 59:a4:bb:f3:0d:87:7d:a3:cf:8a:e0:53:c2:b7:0c: + 0a:c7:36:74:db:0f:77:08:92:42:02:eb:16:52:97: + ee:f3:ec:2c:9b:9d:d3:da:6e:3a:4e:89:d4:f6:27: + 48:1f:2a:ab:a1:51:18:a5:e6:94:3d:56:20:1c:35: + 91:ca:ec:62:21:f5:c4:1c:6e:6a:f2:1f:32:1d:06: + ea:ae:a8:af:89:02:c5:ec:18:9d:ba:92:96:d8:96: + f6:94:6b:ba:52:cc:55:2e:c5:5e:56:1d:82:fa:33: + 34:3e:2e:8e:45:0b:94:4a:bb:25:74:f2:4b:3c:5d: + 9b:c4:06:7e:76:f5:f8:7a:b6:ec:db:28:80:71:bf: + 29:46:09:1c:22:a8:9d:96:61:a8:62:db:9d:f2:b9: + ea:8b:45:65:ab:37:b2:cd:71:28:7c:69:d2:63:f7: + af:11:f0:a5:80:43:06:ee:5d:31:af:b6:af:86:f4: + c4:a4:e5:8e:45:e2:e1:fb:20:6d:ff:e3:34:55:3e: + c8:23 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Subject Alternative Name: + DNS:wintls.test, DNS:*.wintls.test + Authority Information Access: + OCSP - URI:http://localhost:5000 + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Signature Algorithm: sha1WithRSAEncryption + aa:8a:0f:88:d8:84:8e:90:fe:88:b5:ed:65:55:00:2d:f2:e0: + eb:6d:07:89:70:64:bb:1c:be:29:d4:ad:ff:94:b7:71:08:3d: + 9e:e8:c3:55:56:67:e1:9d:e0:d2:c7:ef:d8:74:c3:a0:30:f9: + fb:9d:f8:10:28:c7:60:77:7a:db:cd:96:ef:02:e2:b9:b4:e1: + 1b:96:ab:8c:ab:f1:86:1c:3f:07:2b:fc:2b:97:fc:c1:30:a7: + cd:63:f3:16:19:9d:b2:71:ee:bd:72:21:d2:0e:59:b3:c4:a4: + 30:af:c7:9f:f0:d7:14:5e:35:28:d8:3f:d3:ca:68:24:1d:31: + ca:84:80:10:50:54:c1:62:84:b6:fa:21:4b:9a:16:1d:f0:a4: + 75:e9:5a:e4:2c:3d:91:3c:68:42:e6:4f:25:e6:a0:b8:f2:a9: + e1:00:59:80:a3:c7:7a:8b:77:0e:4b:7a:38:f1:e3:a3:50:62: + 73:73:97:4e:a0:52:65:07:de:73:ae:d1:f2:f3:fd:ae:46:3b: + d0:39:91:db:2a:66:e5:c3:07:60:7c:26:6a:a7:8c:03:8c:ca: + 1c:92:2d:63:dc:46:0c:6f:37:6a:77:52:17:d0:6c:b9:c3:d7: + 24:d1:8c:50:fd:15:c1:f2:9f:76:34:bc:4d:b7:a9:27:17:d5: + 72:84:3d:fe:fb:4f:a6:b3:80:48:ae:c7:58:d6:dd:b8:7e:d5: + 9e:21:3e:d3:b7:e0:cc:c8:9d:a7:9b:cb:57:89:c1:c5:2e:73: + bf:fa:3d:10:d8:b2:5c:7a:d4:6a:03:24:ae:92:38:95:3e:db: + 4d:c1:31:69:17:ae:39:23:30:02:e1:bc:17:a9:ac:60:cb:a6: + 96:92:f3:0a:6c:08:64:9f:3d:ff:05:4c:bb:f9:13:fe:71:f3: + 19:75:ae:36:fe:5f:d6:6c:60:96:b6:c3:40:1d:ca:87:84:2b: + 94:87:59:0a:ae:4e:43:bd:10:59:47:49:c5:d0:36:c8:92:dc: + 79:d2:12:10:cb:8d:fa:d3:c3:22:af:66:eb:d0:c9:f6:41:64: + 16:b9:a9:7a:f1:49:4e:dc:e9:a5:14:e7:5a:f7:a6:e4:d8:4e: + ce:73:24:f7:47:7c:ba:5c:cf:6e:be:ab:d4:3c:33:f0:64:17: + b8:a5:3c:8e:8f:43:25:5d:12:60:8f:78:44:24:4f:fb:f5:6c: + 73:1d:2f:3e:ed:4f:71:84:b4:55:a0:07:1d:c5:84:1b:e7:5b: + c6:0c:78:30:c4:d9:20:8d:94:54:4b:e4:4d:b9:09:d8:93:74: + 6d:70:67:9e:5c:3e:d8:41:8a:df:9c:90:49:61:f1:80:6d:93: + 85:15:c6:bb:bb:3e:39:de +-----BEGIN CERTIFICATE----- +MIIEoTCCAomgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJESzET +MBEGA1UEBwwKQ29wZW5oYWdlbjEPMA0GA1UECgwGV2luVExTMTIwMAYDVQQDDClX +aW5UTFMgSW50ZXJtZWRpYXRlIENlcnRpZmljYXRlIEF1dGhvcml0eTAgFw0yMjA4 +MTcwODU5NDhaGA8yMTIyMDgxODA4NTk0OFowSTELMAkGA1UEBhMCREsxEzARBgNV +BAcMCkNvcGVuaGFnZW4xDzANBgNVBAoMBldpblRMUzEUMBIGA1UEAwwLd2ludGxz +LnRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDff+ugG3ifofcT +jmhA4FD5AM2P8JKj+zPSWicaYjV8gi/7cyfi5y/40fSJjvCom0eGqdkoUKjEdS6/ +51mku/MNh32jz4rgU8K3DArHNnTbD3cIkkIC6xZSl+7z7CybndPabjpOidT2J0gf +KquhURil5pQ9ViAcNZHK7GIh9cQcbmryHzIdBuquqK+JAsXsGJ26kpbYlvaUa7pS +zFUuxV5WHYL6MzQ+Lo5FC5RKuyV08ks8XZvEBn529fh6tuzbKIBxvylGCRwiqJ2W +Yahi253yueqLRWWrN7LNcSh8adJj968R8KWAQwbuXTGvtq+G9MSk5Y5F4uH7IG3/ +4zRVPsgjAgMBAAGjdDByMAkGA1UdEwQCMAAwJQYDVR0RBB4wHIILd2ludGxzLnRl +c3SCDSoud2ludGxzLnRlc3QwMQYIKwYBBQUHAQEEJTAjMCEGCCsGAQUFBzABhhVo +dHRwOi8vbG9jYWxob3N0OjUwMDAwCwYDVR0PBAQDAgXgMA0GCSqGSIb3DQEBBQUA +A4ICAQCqig+I2ISOkP6Ite1lVQAt8uDrbQeJcGS7HL4p1K3/lLdxCD2e6MNVVmfh +neDSx+/YdMOgMPn7nfgQKMdgd3rbzZbvAuK5tOEblquMq/GGHD8HK/wrl/zBMKfN +Y/MWGZ2yce69ciHSDlmzxKQwr8ef8NcUXjUo2D/TymgkHTHKhIAQUFTBYoS2+iFL +mhYd8KR16VrkLD2RPGhC5k8l5qC48qnhAFmAo8d6i3cOS3o48eOjUGJzc5dOoFJl +B95zrtHy8/2uRjvQOZHbKmblwwdgfCZqp4wDjMocki1j3EYMbzdqd1IX0Gy5w9ck +0YxQ/RXB8p92NLxNt6knF9VyhD3++0+ms4BIrsdY1t24ftWeIT7Tt+DMyJ2nm8tX +icHFLnO/+j0Q2LJcetRqAySukjiVPttNwTFpF645IzAC4bwXqaxgy6aWkvMKbAhk +nz3/BUy7+RP+cfMZda42/l/WbGCWtsNAHcqHhCuUh1kKrk5DvRBZR0nF0DbIktx5 +0hIQy43608Mir2br0Mn2QWQWual68UlO3OmlFOda96bk2E7OcyT3R3y6XM9uvqvU +PDPwZBe4pTyOj0MlXRJgj3hEJE/79WxzHS8+7U9xhLRVoAcdxYQb51vGDHgwxNkg +jZRUS+RNuQnYk3RtcGeeXD7YQYrfnJBJYfGAbZOFFca7uz453g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +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 +HBQcQokDeg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/leaf_ocsp_revoked.crt b/third-party/boost-wintls/test/test_certificates/gen/leaf_ocsp_revoked.crt new file mode 100644 index 00000000000..225237c5cb3 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/leaf_ocsp_revoked.crt @@ -0,0 +1,100 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DK, L=Copenhagen, O=WinTLS, CN=WinTLS Intermediate Certificate Authority + Validity + Not Before: Aug 17 08:59:48 2022 GMT + Not After : Aug 18 08:59:48 2122 GMT + Subject: C=DK, L=Copenhagen, O=WinTLS, CN=wintls.test + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:a3:0c:47:50:fa:c7:b5:0d:db:1d:6e:fb:a5:c4: + 53:21:96:1e:7b:ad:7e:f9:df:84:23:a8:1a:88:69: + 90:1f:5a:66:46:08:58:da:3f:ba:59:69:f8:af:da: + a3:a4:3f:47:c9:f8:6b:3b:7d:91:83:1f:7d:14:24: + 96:d3:8c:62:5d:b9:e4:cc:12:c0:63:78:d3:71:bd: + 83:04:7d:33:c9:38:e0:73:44:af:dc:e2:4a:04:5e: + 98:0d:47:78:9d:20:c3:62:fd:8c:33:9e:f4:67:f7: + e5:47:ab:c7:b9:34:e0:48:9c:f9:c9:a7:7e:9c:fa: + b8:47:d7:32:af:31:5b:90:2d:85:da:46:86:dd:43: + 65:0d:a2:1d:4f:9b:9e:9e:d5:6a:b5:af:85:64:22: + 00:19:5a:86:41:43:c0:ea:95:4a:86:e8:77:b7:61: + 46:11:19:08:23:98:29:a2:04:6c:e8:a0:09:ea:25: + 66:ff:e6:a1:67:63:de:d6:62:2a:3a:fc:c7:3a:75: + 7a:fd:c2:01:75:dd:20:e2:6c:f2:e0:59:88:aa:c6: + 15:67:1a:e4:d8:f6:7d:27:dd:c9:32:d5:6e:95:2a: + 36:17:6a:ed:0a:a2:05:4b:76:cf:1f:f0:5c:49:96: + 50:c1:da:2d:93:ec:9f:69:8b:dd:63:03:7e:07:9c: + f8:b1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Subject Alternative Name: + DNS:wintls.test, DNS:*.wintls.test + Authority Information Access: + OCSP - URI:http://localhost:5000 + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Signature Algorithm: sha1WithRSAEncryption + b1:fd:37:03:95:e5:36:cc:08:b6:eb:b8:ab:73:74:9f:f3:9e: + 6c:7b:d2:37:12:47:b7:e7:2b:46:2b:23:34:cb:5e:44:42:b1: + e4:a5:31:3a:f9:bd:d0:c9:ed:24:40:7c:02:51:46:48:b9:bc: + 6c:32:94:e5:50:80:a2:59:d5:4e:98:0d:ca:b3:3f:e8:f3:9d: + 3c:fd:b0:51:a5:1f:5b:2b:06:d5:06:e3:f2:ec:ca:b7:76:e4: + 61:6b:15:a2:32:70:87:8c:0e:81:9f:35:2c:2d:ff:5e:f0:4f: + 89:ae:ba:19:3b:de:60:e1:af:b6:06:05:19:d1:88:3e:03:2d: + d5:f4:a2:d2:cb:6e:f3:fc:fd:9e:77:09:67:85:28:f9:f3:ec: + a3:6e:fa:0d:14:0e:3b:54:1f:14:78:c3:ba:fc:f8:fa:8e:52: + c4:cd:58:a6:65:9f:8e:02:1a:d4:30:30:7e:5d:a4:6c:16:0d: + cc:6b:4b:1f:4a:74:72:b4:12:da:74:96:17:9e:a8:88:a6:49: + 3f:5b:93:97:2e:45:fe:e6:11:6f:84:b0:b7:51:6f:da:88:cc: + 67:3d:86:96:9a:15:8e:5f:7d:f3:53:8f:80:2a:2b:88:57:35: + 5c:b9:66:f8:6f:90:11:c6:6c:38:de:19:42:ac:7c:3d:70:b5: + d2:ef:b2:c6:d2:8f:80:34:d6:c4:58:57:11:c0:d5:46:5a:42: + 30:73:dd:2c:7f:da:5d:5e:9a:49:93:00:86:9f:16:51:a2:9d: + ad:bf:a9:cb:7c:0c:6a:14:b3:c9:22:5c:21:28:98:7a:78:ae: + 23:e3:b6:86:ce:47:b1:cb:01:72:5f:bc:07:89:63:91:0f:ab: + 89:85:9f:f6:dc:f1:9a:21:97:51:9b:80:5c:b1:a1:ba:5c:ee: + 96:30:ef:6e:49:2e:32:1e:4b:88:ed:3c:09:5d:cb:d4:c6:bf: + 96:cb:fc:07:b2:ba:15:73:9c:2d:c9:60:70:c1:a4:1c:61:a7: + 10:55:a1:1b:3b:51:0d:a0:6f:c1:8e:7b:0b:59:73:1f:cf:64: + 35:2f:23:af:69:91:3c:26:49:dc:89:b6:2c:67:b0:b4:c6:0b: + 82:fe:a8:3e:81:2d:23:8b:94:17:ba:e0:3b:76:1a:7e:fb:07: + c1:1d:27:49:84:74:ef:2c:1d:d2:39:52:4e:f7:70:2f:75:73: + 7a:f7:e7:13:05:0c:28:06:64:c5:5b:d1:dd:e7:3b:6d:f6:da: + a6:7c:9e:0a:00:8c:58:01:f4:a7:61:82:55:1b:f6:d6:59:7e: + 9c:4e:c7:87:02:bd:23:0d:17:62:f6:9a:dd:6d:52:a9:fc:20: + 72:4c:7d:97:be:19:3a:19 +-----BEGIN CERTIFICATE----- +MIIEoTCCAomgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJESzET +MBEGA1UEBwwKQ29wZW5oYWdlbjEPMA0GA1UECgwGV2luVExTMTIwMAYDVQQDDClX +aW5UTFMgSW50ZXJtZWRpYXRlIENlcnRpZmljYXRlIEF1dGhvcml0eTAgFw0yMjA4 +MTcwODU5NDhaGA8yMTIyMDgxODA4NTk0OFowSTELMAkGA1UEBhMCREsxEzARBgNV +BAcMCkNvcGVuaGFnZW4xDzANBgNVBAoMBldpblRMUzEUMBIGA1UEAwwLd2ludGxz +LnRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCjDEdQ+se1Ddsd +bvulxFMhlh57rX7534QjqBqIaZAfWmZGCFjaP7pZafiv2qOkP0fJ+Gs7fZGDH30U +JJbTjGJdueTMEsBjeNNxvYMEfTPJOOBzRK/c4koEXpgNR3idIMNi/YwznvRn9+VH +q8e5NOBInPnJp36c+rhH1zKvMVuQLYXaRobdQ2UNoh1Pm56e1Wq1r4VkIgAZWoZB +Q8DqlUqG6He3YUYRGQgjmCmiBGzooAnqJWb/5qFnY97WYio6/Mc6dXr9wgF13SDi +bPLgWYiqxhVnGuTY9n0n3cky1W6VKjYXau0KogVLds8f8FxJllDB2i2T7J9pi91j +A34HnPixAgMBAAGjdDByMAkGA1UdEwQCMAAwJQYDVR0RBB4wHIILd2ludGxzLnRl +c3SCDSoud2ludGxzLnRlc3QwMQYIKwYBBQUHAQEEJTAjMCEGCCsGAQUFBzABhhVo +dHRwOi8vbG9jYWxob3N0OjUwMDAwCwYDVR0PBAQDAgXgMA0GCSqGSIb3DQEBBQUA +A4ICAQCx/TcDleU2zAi267irc3Sf855se9I3Eke35ytGKyM0y15EQrHkpTE6+b3Q +ye0kQHwCUUZIubxsMpTlUICiWdVOmA3Ksz/o8508/bBRpR9bKwbVBuPy7Mq3duRh +axWiMnCHjA6BnzUsLf9e8E+JrroZO95g4a+2BgUZ0Yg+Ay3V9KLSy27z/P2edwln +hSj58+yjbvoNFA47VB8UeMO6/Pj6jlLEzVimZZ+OAhrUMDB+XaRsFg3Ma0sfSnRy +tBLadJYXnqiIpkk/W5OXLkX+5hFvhLC3UW/aiMxnPYaWmhWOX33zU4+AKiuIVzVc +uWb4b5ARxmw43hlCrHw9cLXS77LG0o+ANNbEWFcRwNVGWkIwc90sf9pdXppJkwCG +nxZRop2tv6nLfAxqFLPJIlwhKJh6eK4j47aGzkexywFyX7wHiWORD6uJhZ/23PGa +IZdRm4BcsaG6XO6WMO9uSS4yHkuI7TwJXcvUxr+Wy/wHsroVc5wtyWBwwaQcYacQ +VaEbO1ENoG/BjnsLWXMfz2Q1LyOvaZE8JkncibYsZ7C0xguC/qg+gS0ji5QXuuA7 +dhp++wfBHSdJhHTvLB3SOVJO93AvdXN69+cTBQwoBmTFW9Hd5ztt9tqmfJ4KAIxY +AfSnYYJVG/bWWX6cTseHAr0jDRdi9prdbVKp/CByTH2Xvhk6GQ== +-----END CERTIFICATE----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/leaf_ocsp_revoked.csr b/third-party/boost-wintls/test/test_certificates/gen/leaf_ocsp_revoked.csr new file mode 100644 index 00000000000..cf15ec65b78 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/leaf_ocsp_revoked.csr @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIDEzCCAfsCAQAwSTELMAkGA1UEBhMCREsxEzARBgNVBAcMCkNvcGVuaGFnZW4x +DzANBgNVBAoMBldpblRMUzEUMBIGA1UEAwwLd2ludGxzLnRlc3QwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCjDEdQ+se1DdsdbvulxFMhlh57rX7534Qj +qBqIaZAfWmZGCFjaP7pZafiv2qOkP0fJ+Gs7fZGDH30UJJbTjGJdueTMEsBjeNNx +vYMEfTPJOOBzRK/c4koEXpgNR3idIMNi/YwznvRn9+VHq8e5NOBInPnJp36c+rhH +1zKvMVuQLYXaRobdQ2UNoh1Pm56e1Wq1r4VkIgAZWoZBQ8DqlUqG6He3YUYRGQgj +mCmiBGzooAnqJWb/5qFnY97WYio6/Mc6dXr9wgF13SDibPLgWYiqxhVnGuTY9n0n +3cky1W6VKjYXau0KogVLds8f8FxJllDB2i2T7J9pi91jA34HnPixAgMBAAGggYQw +gYEGCSqGSIb3DQEJDjF0MHIwCQYDVR0TBAIwADAlBgNVHREEHjAcggt3aW50bHMu +dGVzdIINKi53aW50bHMudGVzdDAxBggrBgEFBQcBAQQlMCMwIQYIKwYBBQUHMAGG +FWh0dHA6Ly9sb2NhbGhvc3Q6NTAwMDALBgNVHQ8EBAMCBeAwDQYJKoZIhvcNAQEL +BQADggEBAHbhUG9aXv57o8fkHsb8enSw8kU2l8KNiguaag+L8q7GKhnoZ0D/bsIH +XqBT9uP0gh2x6+6z4XCqLvx0johceMMOeCw/qEhqqcWrtI9IQd2Jc26i4xFEhz9X +16t6wUh7bW2tAZzg8bi+ezKke78x3TxigTVh0Ln2KetjjJw4ZTqiDC4DOyIW2k80 +p5z5mE0IZS+eveBpwgSIDTXOTehyjDyAOF39UacWq5+sTGB553zNSTnmN1KlfZ9o +mygpSLtxidPKBpr9DOSJmRLgngnTkncxccBujsziytcKXAQVUsEjaAr5Kmzjr0Pf +RmZKVxKm8+sy3hgMvzh+Qp5n1gy4TZc= +-----END CERTIFICATE REQUEST----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/leaf_ocsp_revoked.key b/third-party/boost-wintls/test/test_certificates/gen/leaf_ocsp_revoked.key new file mode 100644 index 00000000000..1094d939299 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/leaf_ocsp_revoked.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCjDEdQ+se1Ddsd +bvulxFMhlh57rX7534QjqBqIaZAfWmZGCFjaP7pZafiv2qOkP0fJ+Gs7fZGDH30U +JJbTjGJdueTMEsBjeNNxvYMEfTPJOOBzRK/c4koEXpgNR3idIMNi/YwznvRn9+VH +q8e5NOBInPnJp36c+rhH1zKvMVuQLYXaRobdQ2UNoh1Pm56e1Wq1r4VkIgAZWoZB +Q8DqlUqG6He3YUYRGQgjmCmiBGzooAnqJWb/5qFnY97WYio6/Mc6dXr9wgF13SDi +bPLgWYiqxhVnGuTY9n0n3cky1W6VKjYXau0KogVLds8f8FxJllDB2i2T7J9pi91j +A34HnPixAgMBAAECggEAJ+pdmymJsn1N4wrEeHRzlYlWtRhoOWvKwZ/pvvN44PQU +jZiFiAiJ6lHTG9n+rbsALCWwusOm197hlAjRE8EOY7uak4sTpkZyHSoz5OlxwBU4 +fX+XPg/35tHxj26rzGu06YsAw7JqSvmZG86l+mVDcwNa808Z4/xNGOlJ8zG2JLlc +MxfoAWL7wmsSPPk4Y6GycTPSrtJNarZxrofxVvDz6teG0QCDQBH6GyjYW/qYME5A +WWEn1AP5TuY8AVYKNL3b2e7mcQxPRIdNaa9v/vfg2AcA5lvYuk/696YCadZ4Gg7C +7D1cxwsQDVtLF5rpWNWipKuoBO1IOhgwdwoywszX8QKBgQDSrEU8Km0V5Wh8luWS +uwUqVr3L0ZZre6jSqOfzhixLSe1gOVXYBDweYNbnqnn0FY/210ctL2mF6QPz51um +fwSAz791I38SUS/ue2CXf7wuRlgE5wyetPiZQjEGrFFfl0ZT5qzPIN0K9LBfl3U7 +neALjaCe6H148dy2UG0TAFt2UwKBgQDGINsC8HGjxBpoPHQYERh3uWlFHUiwTLP+ +ML7cJ0slN5CK0JSVrQr1rYSh0XRSe8aaIdfCoqp3KeDcUyIoa73NaLBFzjfziKYE +fzlj5DkGJT8C0e4/qO1GgwzpE+/TwRVlTUSD1Zp8NxCXskEIOuL0rz3i6J8ADhyi +dSdmCLrsawKBgD3Q6qfS0xtfqx8Tr900HznjJeHOZ9K2AD1/7j+YmRqmYI6hhDzU +UUegpq5naU1jnlCRroLlrJLsYoqI0m2yS4H4c3dNqRWY2PWjIh6SDoeNgHo/yYYw +F9nwgC4zFdV0r+AiiYZlYDa8wZvq9y09D+aT8hNuqJJ6dYbRZo/yxOOdAoGBAJlu +WCyuh1KLSuft6Pm6Q3hz3VHom6HrxHfUx/k1dLwdi5H0dRx0JUicV1n5GlvF/sbd +7niL//bIN5pnxswGo7WunNNyH2I5MFfLLmZtFrvrnCBS8m3aI+W3FwhoqBEUNb19 +WNG/WSNYgUD4ieQVtixGiWZvPrKMOyCUGS6rFBaBAoGBAICMxWxG2mYzVd5GZ2CY +j/sO3DFKwRAqExDlPUUTCW48I11mnZkb0BlNGc4cTWv1Nt2tinyTwgLoslTIfXbC +b5A0pXsswtOgfABrAjvSlsOv++5VpnASsJGFSZ/4RL9s1x6gnfSYpyVtHgdym2Yw +arbCikI4ujmAQeeGfqBWsmdl +-----END PRIVATE KEY----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/leaf_ocsp_revoked_chain.pem b/third-party/boost-wintls/test/test_certificates/gen/leaf_ocsp_revoked_chain.pem new file mode 100644 index 00000000000..d0b9f6129ef --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/leaf_ocsp_revoked_chain.pem @@ -0,0 +1,171 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DK, L=Copenhagen, O=WinTLS, CN=WinTLS Intermediate Certificate Authority + Validity + Not Before: Aug 17 08:59:48 2022 GMT + Not After : Aug 18 08:59:48 2122 GMT + Subject: C=DK, L=Copenhagen, O=WinTLS, CN=wintls.test + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:a3:0c:47:50:fa:c7:b5:0d:db:1d:6e:fb:a5:c4: + 53:21:96:1e:7b:ad:7e:f9:df:84:23:a8:1a:88:69: + 90:1f:5a:66:46:08:58:da:3f:ba:59:69:f8:af:da: + a3:a4:3f:47:c9:f8:6b:3b:7d:91:83:1f:7d:14:24: + 96:d3:8c:62:5d:b9:e4:cc:12:c0:63:78:d3:71:bd: + 83:04:7d:33:c9:38:e0:73:44:af:dc:e2:4a:04:5e: + 98:0d:47:78:9d:20:c3:62:fd:8c:33:9e:f4:67:f7: + e5:47:ab:c7:b9:34:e0:48:9c:f9:c9:a7:7e:9c:fa: + b8:47:d7:32:af:31:5b:90:2d:85:da:46:86:dd:43: + 65:0d:a2:1d:4f:9b:9e:9e:d5:6a:b5:af:85:64:22: + 00:19:5a:86:41:43:c0:ea:95:4a:86:e8:77:b7:61: + 46:11:19:08:23:98:29:a2:04:6c:e8:a0:09:ea:25: + 66:ff:e6:a1:67:63:de:d6:62:2a:3a:fc:c7:3a:75: + 7a:fd:c2:01:75:dd:20:e2:6c:f2:e0:59:88:aa:c6: + 15:67:1a:e4:d8:f6:7d:27:dd:c9:32:d5:6e:95:2a: + 36:17:6a:ed:0a:a2:05:4b:76:cf:1f:f0:5c:49:96: + 50:c1:da:2d:93:ec:9f:69:8b:dd:63:03:7e:07:9c: + f8:b1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Subject Alternative Name: + DNS:wintls.test, DNS:*.wintls.test + Authority Information Access: + OCSP - URI:http://localhost:5000 + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Signature Algorithm: sha1WithRSAEncryption + b1:fd:37:03:95:e5:36:cc:08:b6:eb:b8:ab:73:74:9f:f3:9e: + 6c:7b:d2:37:12:47:b7:e7:2b:46:2b:23:34:cb:5e:44:42:b1: + e4:a5:31:3a:f9:bd:d0:c9:ed:24:40:7c:02:51:46:48:b9:bc: + 6c:32:94:e5:50:80:a2:59:d5:4e:98:0d:ca:b3:3f:e8:f3:9d: + 3c:fd:b0:51:a5:1f:5b:2b:06:d5:06:e3:f2:ec:ca:b7:76:e4: + 61:6b:15:a2:32:70:87:8c:0e:81:9f:35:2c:2d:ff:5e:f0:4f: + 89:ae:ba:19:3b:de:60:e1:af:b6:06:05:19:d1:88:3e:03:2d: + d5:f4:a2:d2:cb:6e:f3:fc:fd:9e:77:09:67:85:28:f9:f3:ec: + a3:6e:fa:0d:14:0e:3b:54:1f:14:78:c3:ba:fc:f8:fa:8e:52: + c4:cd:58:a6:65:9f:8e:02:1a:d4:30:30:7e:5d:a4:6c:16:0d: + cc:6b:4b:1f:4a:74:72:b4:12:da:74:96:17:9e:a8:88:a6:49: + 3f:5b:93:97:2e:45:fe:e6:11:6f:84:b0:b7:51:6f:da:88:cc: + 67:3d:86:96:9a:15:8e:5f:7d:f3:53:8f:80:2a:2b:88:57:35: + 5c:b9:66:f8:6f:90:11:c6:6c:38:de:19:42:ac:7c:3d:70:b5: + d2:ef:b2:c6:d2:8f:80:34:d6:c4:58:57:11:c0:d5:46:5a:42: + 30:73:dd:2c:7f:da:5d:5e:9a:49:93:00:86:9f:16:51:a2:9d: + ad:bf:a9:cb:7c:0c:6a:14:b3:c9:22:5c:21:28:98:7a:78:ae: + 23:e3:b6:86:ce:47:b1:cb:01:72:5f:bc:07:89:63:91:0f:ab: + 89:85:9f:f6:dc:f1:9a:21:97:51:9b:80:5c:b1:a1:ba:5c:ee: + 96:30:ef:6e:49:2e:32:1e:4b:88:ed:3c:09:5d:cb:d4:c6:bf: + 96:cb:fc:07:b2:ba:15:73:9c:2d:c9:60:70:c1:a4:1c:61:a7: + 10:55:a1:1b:3b:51:0d:a0:6f:c1:8e:7b:0b:59:73:1f:cf:64: + 35:2f:23:af:69:91:3c:26:49:dc:89:b6:2c:67:b0:b4:c6:0b: + 82:fe:a8:3e:81:2d:23:8b:94:17:ba:e0:3b:76:1a:7e:fb:07: + c1:1d:27:49:84:74:ef:2c:1d:d2:39:52:4e:f7:70:2f:75:73: + 7a:f7:e7:13:05:0c:28:06:64:c5:5b:d1:dd:e7:3b:6d:f6:da: + a6:7c:9e:0a:00:8c:58:01:f4:a7:61:82:55:1b:f6:d6:59:7e: + 9c:4e:c7:87:02:bd:23:0d:17:62:f6:9a:dd:6d:52:a9:fc:20: + 72:4c:7d:97:be:19:3a:19 +-----BEGIN CERTIFICATE----- +MIIEoTCCAomgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJESzET +MBEGA1UEBwwKQ29wZW5oYWdlbjEPMA0GA1UECgwGV2luVExTMTIwMAYDVQQDDClX +aW5UTFMgSW50ZXJtZWRpYXRlIENlcnRpZmljYXRlIEF1dGhvcml0eTAgFw0yMjA4 +MTcwODU5NDhaGA8yMTIyMDgxODA4NTk0OFowSTELMAkGA1UEBhMCREsxEzARBgNV +BAcMCkNvcGVuaGFnZW4xDzANBgNVBAoMBldpblRMUzEUMBIGA1UEAwwLd2ludGxz +LnRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCjDEdQ+se1Ddsd +bvulxFMhlh57rX7534QjqBqIaZAfWmZGCFjaP7pZafiv2qOkP0fJ+Gs7fZGDH30U +JJbTjGJdueTMEsBjeNNxvYMEfTPJOOBzRK/c4koEXpgNR3idIMNi/YwznvRn9+VH +q8e5NOBInPnJp36c+rhH1zKvMVuQLYXaRobdQ2UNoh1Pm56e1Wq1r4VkIgAZWoZB +Q8DqlUqG6He3YUYRGQgjmCmiBGzooAnqJWb/5qFnY97WYio6/Mc6dXr9wgF13SDi +bPLgWYiqxhVnGuTY9n0n3cky1W6VKjYXau0KogVLds8f8FxJllDB2i2T7J9pi91j +A34HnPixAgMBAAGjdDByMAkGA1UdEwQCMAAwJQYDVR0RBB4wHIILd2ludGxzLnRl +c3SCDSoud2ludGxzLnRlc3QwMQYIKwYBBQUHAQEEJTAjMCEGCCsGAQUFBzABhhVo +dHRwOi8vbG9jYWxob3N0OjUwMDAwCwYDVR0PBAQDAgXgMA0GCSqGSIb3DQEBBQUA +A4ICAQCx/TcDleU2zAi267irc3Sf855se9I3Eke35ytGKyM0y15EQrHkpTE6+b3Q +ye0kQHwCUUZIubxsMpTlUICiWdVOmA3Ksz/o8508/bBRpR9bKwbVBuPy7Mq3duRh +axWiMnCHjA6BnzUsLf9e8E+JrroZO95g4a+2BgUZ0Yg+Ay3V9KLSy27z/P2edwln +hSj58+yjbvoNFA47VB8UeMO6/Pj6jlLEzVimZZ+OAhrUMDB+XaRsFg3Ma0sfSnRy +tBLadJYXnqiIpkk/W5OXLkX+5hFvhLC3UW/aiMxnPYaWmhWOX33zU4+AKiuIVzVc +uWb4b5ARxmw43hlCrHw9cLXS77LG0o+ANNbEWFcRwNVGWkIwc90sf9pdXppJkwCG +nxZRop2tv6nLfAxqFLPJIlwhKJh6eK4j47aGzkexywFyX7wHiWORD6uJhZ/23PGa +IZdRm4BcsaG6XO6WMO9uSS4yHkuI7TwJXcvUxr+Wy/wHsroVc5wtyWBwwaQcYacQ +VaEbO1ENoG/BjnsLWXMfz2Q1LyOvaZE8JkncibYsZ7C0xguC/qg+gS0ji5QXuuA7 +dhp++wfBHSdJhHTvLB3SOVJO93AvdXN69+cTBQwoBmTFW9Hd5ztt9tqmfJ4KAIxY +AfSnYYJVG/bWWX6cTseHAr0jDRdi9prdbVKp/CByTH2Xvhk6GQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +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 +HBQcQokDeg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/newcerts/01.pem b/third-party/boost-wintls/test/test_certificates/gen/newcerts/01.pem new file mode 100644 index 00000000000..a58e91ceaea --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/newcerts/01.pem @@ -0,0 +1,96 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 1 (0x1) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DK, L=Copenhagen, O=WinTLS, CN=WinTLS Intermediate Certificate Authority + Validity + Not Before: Aug 17 08:59:48 2022 GMT + Not After : Aug 18 08:59:48 2122 GMT + Subject: C=DK, L=Copenhagen, O=WinTLS, CN=wintls.test + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:b4:97:8c:f2:fd:42:fe:d8:bf:2d:40:39:7f:b0: + c0:fa:6c:bf:c7:69:cf:a1:1d:f3:14:d7:a5:ef:38: + d2:cd:f2:73:45:4c:92:72:4c:4f:3f:77:53:47:c4: + 54:e6:9d:a4:40:d2:72:a9:c5:7b:a6:86:08:f3:fe: + d1:cc:95:d9:85:7f:ea:1d:4d:50:dc:07:44:4b:d9: + 87:d9:d6:16:a7:54:89:bd:ec:ea:81:93:8a:f1:3b: + 8f:09:95:51:cd:8a:fd:5b:cc:31:0e:5c:19:65:25: + 5d:66:ca:ba:81:c0:83:b3:6b:a8:ac:8d:38:76:25: + d9:d6:a4:9a:9c:68:e4:15:1c:97:92:43:11:0c:8f: + 44:fc:22:d0:c0:f8:7b:1e:d5:10:58:f2:3d:e1:41: + 11:91:e4:d3:d2:f0:91:73:a9:3d:bb:e8:06:04:6d: + ec:3e:89:f2:88:57:89:f5:d9:29:55:2f:e8:ec:ba: + 14:26:d8:81:d4:9b:2f:28:46:4f:10:8f:9c:03:9b: + e5:71:4e:59:ba:4e:4e:e1:34:9c:da:ed:4b:e4:fc: + 04:5f:48:d8:21:db:92:aa:57:cf:39:7d:f1:f2:69: + 86:4f:05:a1:15:e9:d0:74:59:7c:46:e7:05:1e:8c: + 57:2a:50:56:9b:ed:60:8e:d6:bf:9f:45:29:37:cd: + fb:b1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Subject Alternative Name: + DNS:wintls.test, DNS:*.wintls.test + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Signature Algorithm: sha1WithRSAEncryption + a1:49:09:a6:70:13:39:cb:a8:60:35:ff:70:22:2e:ea:c8:ad: + 14:8c:6e:af:a7:86:19:13:8e:7f:2f:6b:93:8b:2a:25:73:df: + ae:4d:10:84:73:3f:57:27:67:64:49:76:fb:79:05:2f:9b:48: + b8:e0:db:90:be:78:dc:cd:e3:87:b9:1b:09:1b:64:bf:0c:79: + c1:30:19:71:bf:a5:74:00:16:1a:0c:dd:6d:f2:ca:c7:66:96: + 86:64:bb:2c:c4:5e:69:1c:fd:b9:ea:60:03:69:e3:ab:b8:af: + b1:7f:22:79:d5:aa:e6:7e:94:28:03:d7:c0:0f:94:84:86:f1: + df:03:6e:34:20:5a:01:6a:d2:61:f7:e3:a4:af:c2:ab:cf:50: + 04:56:c6:91:f9:0a:b8:fe:1d:d0:49:57:3b:d1:a6:23:7f:cb: + 2e:b6:2c:db:1e:fd:3e:83:3f:52:10:60:05:da:cf:b1:66:94: + 44:ff:ae:de:f2:2f:29:4b:4f:fd:b1:76:de:7e:55:83:9e:4b: + ac:50:b5:c4:07:af:60:5e:35:bb:23:cd:bc:6c:5c:f9:f4:c4: + ae:f9:d9:d9:da:cf:18:a0:ee:34:98:ff:b3:a6:7c:bd:be:6f: + e7:10:be:6c:0a:87:e7:02:dd:bc:3b:7e:aa:df:3c:d8:c7:79: + 84:89:ef:46:84:f0:7a:61:da:a0:ec:03:77:bf:5a:07:bf:8b: + fa:c1:e4:f8:20:c7:97:5e:a6:d0:48:f9:e2:8b:3c:6b:c9:01: + 9d:2d:d4:6a:2e:1b:6e:b7:61:b8:1d:a0:fd:0f:df:72:10:99: + 29:d8:0d:e0:26:6d:ee:52:0a:56:3b:ea:d9:ca:c0:6f:b9:c9: + 37:fe:0e:ea:0b:74:42:5a:4c:93:72:87:39:2e:00:27:e5:26: + 92:89:5a:c0:0c:1a:c8:41:6a:b5:9a:91:67:81:ea:47:20:30: + 6f:03:ec:9f:b6:c7:60:6e:cf:d8:96:7b:01:71:e5:8f:79:b3: + f6:63:e1:a5:4c:56:8d:7a:f6:e2:e1:74:60:d3:41:49:12:e1: + 28:df:13:61:d1:10:d2:92:b6:88:b4:19:27:41:4f:41:48:77: + e1:57:76:75:f1:e1:84:da:41:01:dd:42:4c:b7:0a:9a:e3:23: + a1:2f:cc:d8:84:a6:a2:f8:cd:77:c1:79:49:28:9c:60:f6:37: + 92:51:46:f9:a4:b0:d6:3d:86:73:33:86:8f:30:29:cd:df:45: + 24:f8:2e:f9:84:4f:87:df:ac:09:c1:db:29:8d:df:62:d5:72: + 8a:f3:90:24:80:04:17:13:60:3d:9b:1f:6f:17:d9:33:c6:1f: + d0:46:9f:a2:f8:64:26:ee +-----BEGIN CERTIFICATE----- +MIIEbjCCAlagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJESzET +MBEGA1UEBwwKQ29wZW5oYWdlbjEPMA0GA1UECgwGV2luVExTMTIwMAYDVQQDDClX +aW5UTFMgSW50ZXJtZWRpYXRlIENlcnRpZmljYXRlIEF1dGhvcml0eTAgFw0yMjA4 +MTcwODU5NDhaGA8yMTIyMDgxODA4NTk0OFowSTELMAkGA1UEBhMCREsxEzARBgNV +BAcMCkNvcGVuaGFnZW4xDzANBgNVBAoMBldpblRMUzEUMBIGA1UEAwwLd2ludGxz +LnRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0l4zy/UL+2L8t +QDl/sMD6bL/Hac+hHfMU16XvONLN8nNFTJJyTE8/d1NHxFTmnaRA0nKpxXumhgjz +/tHMldmFf+odTVDcB0RL2YfZ1hanVIm97OqBk4rxO48JlVHNiv1bzDEOXBllJV1m +yrqBwIOza6isjTh2JdnWpJqcaOQVHJeSQxEMj0T8ItDA+Hse1RBY8j3hQRGR5NPS +8JFzqT276AYEbew+ifKIV4n12SlVL+jsuhQm2IHUmy8oRk8Qj5wDm+VxTlm6Tk7h +NJza7Uvk/ARfSNgh25KqV885ffHyaYZPBaEV6dB0WXxG5wUejFcqUFab7WCO1r+f +RSk3zfuxAgMBAAGjQTA/MAkGA1UdEwQCMAAwJQYDVR0RBB4wHIILd2ludGxzLnRl +c3SCDSoud2ludGxzLnRlc3QwCwYDVR0PBAQDAgXgMA0GCSqGSIb3DQEBBQUAA4IC +AQChSQmmcBM5y6hgNf9wIi7qyK0UjG6vp4YZE45/L2uTiyolc9+uTRCEcz9XJ2dk +SXb7eQUvm0i44NuQvnjczeOHuRsJG2S/DHnBMBlxv6V0ABYaDN1t8srHZpaGZLss +xF5pHP256mADaeOruK+xfyJ51armfpQoA9fAD5SEhvHfA240IFoBatJh9+Okr8Kr +z1AEVsaR+Qq4/h3QSVc70aYjf8sutizbHv0+gz9SEGAF2s+xZpRE/67e8i8pS0/9 +sXbeflWDnkusULXEB69gXjW7I828bFz59MSu+dnZ2s8YoO40mP+zpny9vm/nEL5s +CofnAt28O36q3zzYx3mEie9GhPB6Ydqg7AN3v1oHv4v6weT4IMeXXqbQSPniizxr +yQGdLdRqLhtut2G4HaD9D99yEJkp2A3gJm3uUgpWO+rZysBvuck3/g7qC3RCWkyT +coc5LgAn5SaSiVrADBrIQWq1mpFngepHIDBvA+yftsdgbs/YlnsBceWPebP2Y+Gl +TFaNevbi4XRg00FJEuEo3xNh0RDSkraItBknQU9BSHfhV3Z18eGE2kEB3UJMtwqa +4yOhL8zYhKai+M13wXlJKJxg9jeSUUb5pLDWPYZzM4aPMCnN30Uk+C75hE+H36wJ +wdspjd9i1XKK85AkgAQXE2A9mx9vF9kzxh/QRp+i+GQm7g== +-----END CERTIFICATE----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/newcerts/02.pem b/third-party/boost-wintls/test/test_certificates/gen/newcerts/02.pem new file mode 100644 index 00000000000..48e71767841 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/newcerts/02.pem @@ -0,0 +1,100 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2 (0x2) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DK, L=Copenhagen, O=WinTLS, CN=WinTLS Intermediate Certificate Authority + Validity + Not Before: Aug 17 08:59:48 2022 GMT + Not After : Aug 18 08:59:48 2122 GMT + Subject: C=DK, L=Copenhagen, O=WinTLS, CN=wintls.test + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:df:7f:eb:a0:1b:78:9f:a1:f7:13:8e:68:40:e0: + 50:f9:00:cd:8f:f0:92:a3:fb:33:d2:5a:27:1a:62: + 35:7c:82:2f:fb:73:27:e2:e7:2f:f8:d1:f4:89:8e: + f0:a8:9b:47:86:a9:d9:28:50:a8:c4:75:2e:bf:e7: + 59:a4:bb:f3:0d:87:7d:a3:cf:8a:e0:53:c2:b7:0c: + 0a:c7:36:74:db:0f:77:08:92:42:02:eb:16:52:97: + ee:f3:ec:2c:9b:9d:d3:da:6e:3a:4e:89:d4:f6:27: + 48:1f:2a:ab:a1:51:18:a5:e6:94:3d:56:20:1c:35: + 91:ca:ec:62:21:f5:c4:1c:6e:6a:f2:1f:32:1d:06: + ea:ae:a8:af:89:02:c5:ec:18:9d:ba:92:96:d8:96: + f6:94:6b:ba:52:cc:55:2e:c5:5e:56:1d:82:fa:33: + 34:3e:2e:8e:45:0b:94:4a:bb:25:74:f2:4b:3c:5d: + 9b:c4:06:7e:76:f5:f8:7a:b6:ec:db:28:80:71:bf: + 29:46:09:1c:22:a8:9d:96:61:a8:62:db:9d:f2:b9: + ea:8b:45:65:ab:37:b2:cd:71:28:7c:69:d2:63:f7: + af:11:f0:a5:80:43:06:ee:5d:31:af:b6:af:86:f4: + c4:a4:e5:8e:45:e2:e1:fb:20:6d:ff:e3:34:55:3e: + c8:23 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Subject Alternative Name: + DNS:wintls.test, DNS:*.wintls.test + Authority Information Access: + OCSP - URI:http://localhost:5000 + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Signature Algorithm: sha1WithRSAEncryption + aa:8a:0f:88:d8:84:8e:90:fe:88:b5:ed:65:55:00:2d:f2:e0: + eb:6d:07:89:70:64:bb:1c:be:29:d4:ad:ff:94:b7:71:08:3d: + 9e:e8:c3:55:56:67:e1:9d:e0:d2:c7:ef:d8:74:c3:a0:30:f9: + fb:9d:f8:10:28:c7:60:77:7a:db:cd:96:ef:02:e2:b9:b4:e1: + 1b:96:ab:8c:ab:f1:86:1c:3f:07:2b:fc:2b:97:fc:c1:30:a7: + cd:63:f3:16:19:9d:b2:71:ee:bd:72:21:d2:0e:59:b3:c4:a4: + 30:af:c7:9f:f0:d7:14:5e:35:28:d8:3f:d3:ca:68:24:1d:31: + ca:84:80:10:50:54:c1:62:84:b6:fa:21:4b:9a:16:1d:f0:a4: + 75:e9:5a:e4:2c:3d:91:3c:68:42:e6:4f:25:e6:a0:b8:f2:a9: + e1:00:59:80:a3:c7:7a:8b:77:0e:4b:7a:38:f1:e3:a3:50:62: + 73:73:97:4e:a0:52:65:07:de:73:ae:d1:f2:f3:fd:ae:46:3b: + d0:39:91:db:2a:66:e5:c3:07:60:7c:26:6a:a7:8c:03:8c:ca: + 1c:92:2d:63:dc:46:0c:6f:37:6a:77:52:17:d0:6c:b9:c3:d7: + 24:d1:8c:50:fd:15:c1:f2:9f:76:34:bc:4d:b7:a9:27:17:d5: + 72:84:3d:fe:fb:4f:a6:b3:80:48:ae:c7:58:d6:dd:b8:7e:d5: + 9e:21:3e:d3:b7:e0:cc:c8:9d:a7:9b:cb:57:89:c1:c5:2e:73: + bf:fa:3d:10:d8:b2:5c:7a:d4:6a:03:24:ae:92:38:95:3e:db: + 4d:c1:31:69:17:ae:39:23:30:02:e1:bc:17:a9:ac:60:cb:a6: + 96:92:f3:0a:6c:08:64:9f:3d:ff:05:4c:bb:f9:13:fe:71:f3: + 19:75:ae:36:fe:5f:d6:6c:60:96:b6:c3:40:1d:ca:87:84:2b: + 94:87:59:0a:ae:4e:43:bd:10:59:47:49:c5:d0:36:c8:92:dc: + 79:d2:12:10:cb:8d:fa:d3:c3:22:af:66:eb:d0:c9:f6:41:64: + 16:b9:a9:7a:f1:49:4e:dc:e9:a5:14:e7:5a:f7:a6:e4:d8:4e: + ce:73:24:f7:47:7c:ba:5c:cf:6e:be:ab:d4:3c:33:f0:64:17: + b8:a5:3c:8e:8f:43:25:5d:12:60:8f:78:44:24:4f:fb:f5:6c: + 73:1d:2f:3e:ed:4f:71:84:b4:55:a0:07:1d:c5:84:1b:e7:5b: + c6:0c:78:30:c4:d9:20:8d:94:54:4b:e4:4d:b9:09:d8:93:74: + 6d:70:67:9e:5c:3e:d8:41:8a:df:9c:90:49:61:f1:80:6d:93: + 85:15:c6:bb:bb:3e:39:de +-----BEGIN CERTIFICATE----- +MIIEoTCCAomgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJESzET +MBEGA1UEBwwKQ29wZW5oYWdlbjEPMA0GA1UECgwGV2luVExTMTIwMAYDVQQDDClX +aW5UTFMgSW50ZXJtZWRpYXRlIENlcnRpZmljYXRlIEF1dGhvcml0eTAgFw0yMjA4 +MTcwODU5NDhaGA8yMTIyMDgxODA4NTk0OFowSTELMAkGA1UEBhMCREsxEzARBgNV +BAcMCkNvcGVuaGFnZW4xDzANBgNVBAoMBldpblRMUzEUMBIGA1UEAwwLd2ludGxz +LnRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDff+ugG3ifofcT +jmhA4FD5AM2P8JKj+zPSWicaYjV8gi/7cyfi5y/40fSJjvCom0eGqdkoUKjEdS6/ +51mku/MNh32jz4rgU8K3DArHNnTbD3cIkkIC6xZSl+7z7CybndPabjpOidT2J0gf +KquhURil5pQ9ViAcNZHK7GIh9cQcbmryHzIdBuquqK+JAsXsGJ26kpbYlvaUa7pS +zFUuxV5WHYL6MzQ+Lo5FC5RKuyV08ks8XZvEBn529fh6tuzbKIBxvylGCRwiqJ2W +Yahi253yueqLRWWrN7LNcSh8adJj968R8KWAQwbuXTGvtq+G9MSk5Y5F4uH7IG3/ +4zRVPsgjAgMBAAGjdDByMAkGA1UdEwQCMAAwJQYDVR0RBB4wHIILd2ludGxzLnRl +c3SCDSoud2ludGxzLnRlc3QwMQYIKwYBBQUHAQEEJTAjMCEGCCsGAQUFBzABhhVo +dHRwOi8vbG9jYWxob3N0OjUwMDAwCwYDVR0PBAQDAgXgMA0GCSqGSIb3DQEBBQUA +A4ICAQCqig+I2ISOkP6Ite1lVQAt8uDrbQeJcGS7HL4p1K3/lLdxCD2e6MNVVmfh +neDSx+/YdMOgMPn7nfgQKMdgd3rbzZbvAuK5tOEblquMq/GGHD8HK/wrl/zBMKfN +Y/MWGZ2yce69ciHSDlmzxKQwr8ef8NcUXjUo2D/TymgkHTHKhIAQUFTBYoS2+iFL +mhYd8KR16VrkLD2RPGhC5k8l5qC48qnhAFmAo8d6i3cOS3o48eOjUGJzc5dOoFJl +B95zrtHy8/2uRjvQOZHbKmblwwdgfCZqp4wDjMocki1j3EYMbzdqd1IX0Gy5w9ck +0YxQ/RXB8p92NLxNt6knF9VyhD3++0+ms4BIrsdY1t24ftWeIT7Tt+DMyJ2nm8tX +icHFLnO/+j0Q2LJcetRqAySukjiVPttNwTFpF645IzAC4bwXqaxgy6aWkvMKbAhk +nz3/BUy7+RP+cfMZda42/l/WbGCWtsNAHcqHhCuUh1kKrk5DvRBZR0nF0DbIktx5 +0hIQy43608Mir2br0Mn2QWQWual68UlO3OmlFOda96bk2E7OcyT3R3y6XM9uvqvU +PDPwZBe4pTyOj0MlXRJgj3hEJE/79WxzHS8+7U9xhLRVoAcdxYQb51vGDHgwxNkg +jZRUS+RNuQnYk3RtcGeeXD7YQYrfnJBJYfGAbZOFFca7uz453g== +-----END CERTIFICATE----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/newcerts/03.pem b/third-party/boost-wintls/test/test_certificates/gen/newcerts/03.pem new file mode 100644 index 00000000000..225237c5cb3 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/newcerts/03.pem @@ -0,0 +1,100 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 3 (0x3) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DK, L=Copenhagen, O=WinTLS, CN=WinTLS Intermediate Certificate Authority + Validity + Not Before: Aug 17 08:59:48 2022 GMT + Not After : Aug 18 08:59:48 2122 GMT + Subject: C=DK, L=Copenhagen, O=WinTLS, CN=wintls.test + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:a3:0c:47:50:fa:c7:b5:0d:db:1d:6e:fb:a5:c4: + 53:21:96:1e:7b:ad:7e:f9:df:84:23:a8:1a:88:69: + 90:1f:5a:66:46:08:58:da:3f:ba:59:69:f8:af:da: + a3:a4:3f:47:c9:f8:6b:3b:7d:91:83:1f:7d:14:24: + 96:d3:8c:62:5d:b9:e4:cc:12:c0:63:78:d3:71:bd: + 83:04:7d:33:c9:38:e0:73:44:af:dc:e2:4a:04:5e: + 98:0d:47:78:9d:20:c3:62:fd:8c:33:9e:f4:67:f7: + e5:47:ab:c7:b9:34:e0:48:9c:f9:c9:a7:7e:9c:fa: + b8:47:d7:32:af:31:5b:90:2d:85:da:46:86:dd:43: + 65:0d:a2:1d:4f:9b:9e:9e:d5:6a:b5:af:85:64:22: + 00:19:5a:86:41:43:c0:ea:95:4a:86:e8:77:b7:61: + 46:11:19:08:23:98:29:a2:04:6c:e8:a0:09:ea:25: + 66:ff:e6:a1:67:63:de:d6:62:2a:3a:fc:c7:3a:75: + 7a:fd:c2:01:75:dd:20:e2:6c:f2:e0:59:88:aa:c6: + 15:67:1a:e4:d8:f6:7d:27:dd:c9:32:d5:6e:95:2a: + 36:17:6a:ed:0a:a2:05:4b:76:cf:1f:f0:5c:49:96: + 50:c1:da:2d:93:ec:9f:69:8b:dd:63:03:7e:07:9c: + f8:b1 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Subject Alternative Name: + DNS:wintls.test, DNS:*.wintls.test + Authority Information Access: + OCSP - URI:http://localhost:5000 + + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + Signature Algorithm: sha1WithRSAEncryption + b1:fd:37:03:95:e5:36:cc:08:b6:eb:b8:ab:73:74:9f:f3:9e: + 6c:7b:d2:37:12:47:b7:e7:2b:46:2b:23:34:cb:5e:44:42:b1: + e4:a5:31:3a:f9:bd:d0:c9:ed:24:40:7c:02:51:46:48:b9:bc: + 6c:32:94:e5:50:80:a2:59:d5:4e:98:0d:ca:b3:3f:e8:f3:9d: + 3c:fd:b0:51:a5:1f:5b:2b:06:d5:06:e3:f2:ec:ca:b7:76:e4: + 61:6b:15:a2:32:70:87:8c:0e:81:9f:35:2c:2d:ff:5e:f0:4f: + 89:ae:ba:19:3b:de:60:e1:af:b6:06:05:19:d1:88:3e:03:2d: + d5:f4:a2:d2:cb:6e:f3:fc:fd:9e:77:09:67:85:28:f9:f3:ec: + a3:6e:fa:0d:14:0e:3b:54:1f:14:78:c3:ba:fc:f8:fa:8e:52: + c4:cd:58:a6:65:9f:8e:02:1a:d4:30:30:7e:5d:a4:6c:16:0d: + cc:6b:4b:1f:4a:74:72:b4:12:da:74:96:17:9e:a8:88:a6:49: + 3f:5b:93:97:2e:45:fe:e6:11:6f:84:b0:b7:51:6f:da:88:cc: + 67:3d:86:96:9a:15:8e:5f:7d:f3:53:8f:80:2a:2b:88:57:35: + 5c:b9:66:f8:6f:90:11:c6:6c:38:de:19:42:ac:7c:3d:70:b5: + d2:ef:b2:c6:d2:8f:80:34:d6:c4:58:57:11:c0:d5:46:5a:42: + 30:73:dd:2c:7f:da:5d:5e:9a:49:93:00:86:9f:16:51:a2:9d: + ad:bf:a9:cb:7c:0c:6a:14:b3:c9:22:5c:21:28:98:7a:78:ae: + 23:e3:b6:86:ce:47:b1:cb:01:72:5f:bc:07:89:63:91:0f:ab: + 89:85:9f:f6:dc:f1:9a:21:97:51:9b:80:5c:b1:a1:ba:5c:ee: + 96:30:ef:6e:49:2e:32:1e:4b:88:ed:3c:09:5d:cb:d4:c6:bf: + 96:cb:fc:07:b2:ba:15:73:9c:2d:c9:60:70:c1:a4:1c:61:a7: + 10:55:a1:1b:3b:51:0d:a0:6f:c1:8e:7b:0b:59:73:1f:cf:64: + 35:2f:23:af:69:91:3c:26:49:dc:89:b6:2c:67:b0:b4:c6:0b: + 82:fe:a8:3e:81:2d:23:8b:94:17:ba:e0:3b:76:1a:7e:fb:07: + c1:1d:27:49:84:74:ef:2c:1d:d2:39:52:4e:f7:70:2f:75:73: + 7a:f7:e7:13:05:0c:28:06:64:c5:5b:d1:dd:e7:3b:6d:f6:da: + a6:7c:9e:0a:00:8c:58:01:f4:a7:61:82:55:1b:f6:d6:59:7e: + 9c:4e:c7:87:02:bd:23:0d:17:62:f6:9a:dd:6d:52:a9:fc:20: + 72:4c:7d:97:be:19:3a:19 +-----BEGIN CERTIFICATE----- +MIIEoTCCAomgAwIBAgIBAzANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJESzET +MBEGA1UEBwwKQ29wZW5oYWdlbjEPMA0GA1UECgwGV2luVExTMTIwMAYDVQQDDClX +aW5UTFMgSW50ZXJtZWRpYXRlIENlcnRpZmljYXRlIEF1dGhvcml0eTAgFw0yMjA4 +MTcwODU5NDhaGA8yMTIyMDgxODA4NTk0OFowSTELMAkGA1UEBhMCREsxEzARBgNV +BAcMCkNvcGVuaGFnZW4xDzANBgNVBAoMBldpblRMUzEUMBIGA1UEAwwLd2ludGxz +LnRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCjDEdQ+se1Ddsd +bvulxFMhlh57rX7534QjqBqIaZAfWmZGCFjaP7pZafiv2qOkP0fJ+Gs7fZGDH30U +JJbTjGJdueTMEsBjeNNxvYMEfTPJOOBzRK/c4koEXpgNR3idIMNi/YwznvRn9+VH +q8e5NOBInPnJp36c+rhH1zKvMVuQLYXaRobdQ2UNoh1Pm56e1Wq1r4VkIgAZWoZB +Q8DqlUqG6He3YUYRGQgjmCmiBGzooAnqJWb/5qFnY97WYio6/Mc6dXr9wgF13SDi +bPLgWYiqxhVnGuTY9n0n3cky1W6VKjYXau0KogVLds8f8FxJllDB2i2T7J9pi91j +A34HnPixAgMBAAGjdDByMAkGA1UdEwQCMAAwJQYDVR0RBB4wHIILd2ludGxzLnRl +c3SCDSoud2ludGxzLnRlc3QwMQYIKwYBBQUHAQEEJTAjMCEGCCsGAQUFBzABhhVo +dHRwOi8vbG9jYWxob3N0OjUwMDAwCwYDVR0PBAQDAgXgMA0GCSqGSIb3DQEBBQUA +A4ICAQCx/TcDleU2zAi267irc3Sf855se9I3Eke35ytGKyM0y15EQrHkpTE6+b3Q +ye0kQHwCUUZIubxsMpTlUICiWdVOmA3Ksz/o8508/bBRpR9bKwbVBuPy7Mq3duRh +axWiMnCHjA6BnzUsLf9e8E+JrroZO95g4a+2BgUZ0Yg+Ay3V9KLSy27z/P2edwln +hSj58+yjbvoNFA47VB8UeMO6/Pj6jlLEzVimZZ+OAhrUMDB+XaRsFg3Ma0sfSnRy +tBLadJYXnqiIpkk/W5OXLkX+5hFvhLC3UW/aiMxnPYaWmhWOX33zU4+AKiuIVzVc +uWb4b5ARxmw43hlCrHw9cLXS77LG0o+ANNbEWFcRwNVGWkIwc90sf9pdXppJkwCG +nxZRop2tv6nLfAxqFLPJIlwhKJh6eK4j47aGzkexywFyX7wHiWORD6uJhZ/23PGa +IZdRm4BcsaG6XO6WMO9uSS4yHkuI7TwJXcvUxr+Wy/wHsroVc5wtyWBwwaQcYacQ +VaEbO1ENoG/BjnsLWXMfz2Q1LyOvaZE8JkncibYsZ7C0xguC/qg+gS0ji5QXuuA7 +dhp++wfBHSdJhHTvLB3SOVJO93AvdXN69+cTBQwoBmTFW9Hd5ztt9tqmfJ4KAIxY +AfSnYYJVG/bWWX6cTseHAr0jDRdi9prdbVKp/CByTH2Xvhk6GQ== +-----END CERTIFICATE----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/newcerts/04.pem b/third-party/boost-wintls/test/test_certificates/gen/newcerts/04.pem new file mode 100644 index 00000000000..f1246bcf507 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/newcerts/04.pem @@ -0,0 +1,119 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4 (0x4) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DK, L=Copenhagen, O=WinTLS, CN=WinTLS Intermediate Certificate Authority + Validity + Not Before: Aug 17 08:59:48 2022 GMT + Not After : Aug 18 08:59:48 2122 GMT + Subject: C=DK, L=Copenhagen, O=WinTLS, CN=WinTLS Intermediate Certificate Authority OCSP signer + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (4096 bit) + Modulus: + 00:e5:91:4c:ec:60:03:5d:08:59:3b:8a:3e:7e:4c: + 49:b1:a4:91:f9:6f:36:1a:18:db:41:d0:1d:d0:53: + dd:16:da:85:bc:fc:26:73:ca:ac:22:a9:f2:7a:83: + 77:65:24:94:2a:8a:0a:95:3a:c2:5b:bb:c5:aa:fc: + b9:56:82:f5:a5:99:1d:2c:07:18:a8:61:97:7e:94: + db:b7:a8:92:9a:f2:6b:d6:57:f2:06:a6:b6:f9:36: + ea:0f:81:16:48:ef:34:d4:70:db:91:ef:2d:0a:41: + 21:55:70:2d:d8:11:f7:34:db:44:54:64:bc:c3:2f: + 94:33:14:e2:c5:2c:1b:a9:89:26:b0:bf:96:9c:73: + a0:e4:f0:9a:d9:c7:c4:10:f3:28:3f:6f:e3:f3:b4: + 24:0e:21:24:7a:bf:61:ff:82:88:e1:ec:58:65:07: + 00:51:3c:c4:6b:08:d4:4f:81:34:63:c4:ba:31:bf: + df:ef:ea:05:ce:d7:0e:06:53:39:87:82:b8:d2:dd: + 0f:b2:85:d6:9c:a5:17:26:ba:10:bc:c9:16:a0:10: + 6e:d3:a6:08:92:5e:48:5f:18:7e:ee:fd:b3:b4:56: + 6f:cb:c1:25:6b:4c:df:fa:73:a2:75:b1:ed:a9:54: + 21:57:22:eb:97:d1:c1:3e:be:6f:50:da:4a:fd:52: + 4c:9a:94:bc:6b:ec:04:c1:e3:78:3f:ba:29:63:bc: + 91:16:8a:75:f3:67:f7:00:2f:dd:fa:eb:ec:ac:a3: + a7:7d:bd:31:a4:df:75:7e:33:fc:a1:c5:1e:a1:59: + 26:19:a6:c8:46:85:8b:0e:ec:7d:aa:54:4d:44:11: + 75:15:6f:c6:93:ff:01:9e:2b:4c:2b:04:32:3c:18: + c0:db:10:73:b4:25:86:54:ca:74:9c:2a:31:5c:00: + 38:42:7d:b4:59:92:df:0a:35:0d:e0:1b:3d:d9:2e: + 54:c7:8f:73:93:27:06:d6:c9:50:62:4f:e5:2b:71: + db:ec:e2:e9:05:0c:22:56:49:ef:99:c7:e2:f8:93: + e8:39:36:1c:07:3e:bd:e8:72:df:62:88:73:c6:ba: + ae:31:df:86:74:69:e1:d4:e6:fc:81:4c:2e:a7:bf: + 61:4e:6e:96:e8:8e:30:63:0e:d7:51:73:c4:d3:5e: + c1:27:a4:24:94:e0:80:da:ac:e7:75:49:e4:25:b8: + a1:c8:2f:d2:a8:8e:68:1a:17:86:be:f0:0b:d5:a2: + a1:f4:d9:e2:93:b9:51:11:f3:9c:87:67:6b:ae:0a: + ed:59:83:c7:32:6e:b6:34:51:6a:d7:d0:2b:3a:fa: + 5e:b9:19:1d:fc:99:b2:3d:11:aa:37:e6:b7:35:36: + a9:5b:c9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Extended Key Usage: + OCSP Signing + Signature Algorithm: sha1WithRSAEncryption + 5c:04:b3:8a:53:cb:8e:c2:bb:fa:8a:1c:2c:fc:1a:8f:f0:11: + ee:b5:f4:c7:66:b7:99:72:63:30:5e:48:ea:e5:59:37:c0:ea: + e1:c1:81:7e:6d:26:ea:f7:c7:eb:42:3c:a3:1c:92:70:d2:4d: + 6c:03:06:8c:bb:3a:af:70:e0:b5:bd:4a:a8:39:84:10:d9:43: + aa:77:7d:25:9a:bc:72:79:03:ea:8a:c1:db:15:a8:34:13:a5: + 30:66:55:66:6a:06:bd:12:0a:67:c3:0a:4d:06:e0:15:53:59: + ed:be:9b:90:07:9d:0b:92:ed:74:76:99:67:e3:d5:fe:74:e3: + 82:08:13:0d:ea:57:dc:af:73:19:40:b1:f4:60:71:d5:4e:66: + 67:ae:32:af:40:fc:79:2a:65:da:56:36:f8:f6:26:72:42:e5: + 42:18:41:15:2f:46:f8:82:d0:57:50:51:c5:10:4c:0e:a2:82: + 44:3b:44:85:b4:c5:a3:93:3a:72:fc:75:62:9a:30:c2:b8:ba: + b6:0d:d5:d9:be:e6:bb:1a:da:42:6a:f4:48:de:30:b4:6c:cc: + ed:9b:b8:a0:12:54:9d:26:78:0b:5d:ec:38:9a:c4:ad:1c:60: + b1:01:fc:3e:2a:5a:ac:b6:ed:5e:f0:8c:30:66:52:db:9b:61: + 8c:5d:df:36:14:2c:fe:4d:82:a8:13:df:a5:e1:1c:fe:02:f0: + 2c:88:fe:39:51:e7:a4:80:4b:2d:28:95:b7:6c:8d:2f:a0:e2: + f5:44:16:eb:39:09:0e:d5:27:8f:f4:92:b6:7f:34:0f:ca:ed: + 29:38:52:77:95:b5:06:23:ec:23:57:fe:a8:4c:77:2b:24:d0: + bb:f4:12:3e:f9:fa:59:45:50:8c:76:c7:23:0d:9c:23:0c:ab: + e1:6d:55:62:ce:dd:55:41:77:f2:40:8e:25:c6:a8:d5:a5:b8: + fc:51:d7:b9:e1:17:8d:4c:82:45:b0:7c:9c:4c:f0:d0:40:3e: + 14:18:04:17:f6:ae:b3:c5:db:db:86:7a:e4:b9:79:6d:a4:8c: + dd:e2:95:56:6f:82:a1:4e:cc:aa:76:0a:eb:4d:d2:f5:ed:9b: + f4:34:a1:d7:7a:95:57:c7:6b:e0:b9:f6:b1:17:f6:8a:73:c4: + 8a:97:ac:c9:5c:28:30:56:66:3a:44:74:1c:07:43:5f:a8:36: + 11:f1:95:9f:6c:34:c9:2c:2a:24:5e:4f:3f:9f:7f:58:95:f3: + 35:a9:d8:67:a7:3d:1f:ae:3e:26:0d:87:c2:f6:9d:19:cf:ac: + d4:12:a5:4a:1f:dc:cb:c2:7a:c1:8e:93:9a:98:8a:2c:20:52: + 1f:02:da:63:ce:ae:7c:e3 +-----BEGIN CERTIFICATE----- +MIIFhjCCA26gAwIBAgIBBDANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJESzET +MBEGA1UEBwwKQ29wZW5oYWdlbjEPMA0GA1UECgwGV2luVExTMTIwMAYDVQQDDClX +aW5UTFMgSW50ZXJtZWRpYXRlIENlcnRpZmljYXRlIEF1dGhvcml0eTAgFw0yMjA4 +MTcwODU5NDhaGA8yMTIyMDgxODA4NTk0OFowczELMAkGA1UEBhMCREsxEzARBgNV +BAcMCkNvcGVuaGFnZW4xDzANBgNVBAoMBldpblRMUzE+MDwGA1UEAww1V2luVExT +IEludGVybWVkaWF0ZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgT0NTUCBzaWduZXIw +ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDlkUzsYANdCFk7ij5+TEmx +pJH5bzYaGNtB0B3QU90W2oW8/CZzyqwiqfJ6g3dlJJQqigqVOsJbu8Wq/LlWgvWl +mR0sBxioYZd+lNu3qJKa8mvWV/IGprb5NuoPgRZI7zTUcNuR7y0KQSFVcC3YEfc0 +20RUZLzDL5QzFOLFLBupiSawv5acc6Dk8JrZx8QQ8yg/b+PztCQOISR6v2H/gojh +7FhlBwBRPMRrCNRPgTRjxLoxv9/v6gXO1w4GUzmHgrjS3Q+yhdacpRcmuhC8yRag +EG7TpgiSXkhfGH7u/bO0Vm/LwSVrTN/6c6J1se2pVCFXIuuX0cE+vm9Q2kr9Ukya +lLxr7ATB43g/uiljvJEWinXzZ/cAL9366+yso6d9vTGk33V+M/yhxR6hWSYZpshG +hYsO7H2qVE1EEXUVb8aT/wGeK0wrBDI8GMDbEHO0JYZUynScKjFcADhCfbRZkt8K +NQ3gGz3ZLlTHj3OTJwbWyVBiT+Urcdvs4ukFDCJWSe+Zx+L4k+g5NhwHPr3oct9i +iHPGuq4x34Z0aeHU5vyBTC6nv2FObpbojjBjDtdRc8TTXsEnpCSU4IDarOd1SeQl +uKHIL9KojmgaF4a+8AvVoqH02eKTuVER85yHZ2uuCu1Zg8cybrY0UWrX0Cs6+l65 +GR38mbI9Eao35rc1NqlbyQIDAQABoy8wLTAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF +4DATBgNVHSUEDDAKBggrBgEFBQcDCTANBgkqhkiG9w0BAQUFAAOCAgEAXASzilPL +jsK7+oocLPwaj/AR7rX0x2a3mXJjMF5I6uVZN8Dq4cGBfm0m6vfH60I8oxyScNJN +bAMGjLs6r3Dgtb1KqDmEENlDqnd9JZq8cnkD6orB2xWoNBOlMGZVZmoGvRIKZ8MK +TQbgFVNZ7b6bkAedC5LtdHaZZ+PV/nTjgggTDepX3K9zGUCx9GBx1U5mZ64yr0D8 +eSpl2lY2+PYmckLlQhhBFS9G+ILQV1BRxRBMDqKCRDtEhbTFo5M6cvx1Ypowwri6 +tg3V2b7muxraQmr0SN4wtGzM7Zu4oBJUnSZ4C13sOJrErRxgsQH8PiparLbtXvCM +MGZS25thjF3fNhQs/k2CqBPfpeEc/gLwLIj+OVHnpIBLLSiVt2yNL6Di9UQW6zkJ +DtUnj/SStn80D8rtKThSd5W1BiPsI1f+qEx3KyTQu/QSPvn6WUVQjHbHIw2cIwyr +4W1VYs7dVUF38kCOJcao1aW4/FHXueEXjUyCRbB8nEzw0EA+FBgEF/aus8Xb24Z6 +5Ll5baSM3eKVVm+CoU7MqnYK603S9e2b9DSh13qVV8dr4Ln2sRf2inPEipesyVwo +MFZmOkR0HAdDX6g2EfGVn2w0ySwqJF5PP59/WJXzNanYZ6c9H64+Jg2HwvadGc+s +1BKlSh/cy8J6wY6TmpiKLCBSHwLaY86ufOM= +-----END CERTIFICATE----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/ocsp_signer_ca_intermediate.crt b/third-party/boost-wintls/test/test_certificates/gen/ocsp_signer_ca_intermediate.crt new file mode 100644 index 00000000000..f1246bcf507 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/ocsp_signer_ca_intermediate.crt @@ -0,0 +1,119 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 4 (0x4) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=DK, L=Copenhagen, O=WinTLS, CN=WinTLS Intermediate Certificate Authority + Validity + Not Before: Aug 17 08:59:48 2022 GMT + Not After : Aug 18 08:59:48 2122 GMT + Subject: C=DK, L=Copenhagen, O=WinTLS, CN=WinTLS Intermediate Certificate Authority OCSP signer + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (4096 bit) + Modulus: + 00:e5:91:4c:ec:60:03:5d:08:59:3b:8a:3e:7e:4c: + 49:b1:a4:91:f9:6f:36:1a:18:db:41:d0:1d:d0:53: + dd:16:da:85:bc:fc:26:73:ca:ac:22:a9:f2:7a:83: + 77:65:24:94:2a:8a:0a:95:3a:c2:5b:bb:c5:aa:fc: + b9:56:82:f5:a5:99:1d:2c:07:18:a8:61:97:7e:94: + db:b7:a8:92:9a:f2:6b:d6:57:f2:06:a6:b6:f9:36: + ea:0f:81:16:48:ef:34:d4:70:db:91:ef:2d:0a:41: + 21:55:70:2d:d8:11:f7:34:db:44:54:64:bc:c3:2f: + 94:33:14:e2:c5:2c:1b:a9:89:26:b0:bf:96:9c:73: + a0:e4:f0:9a:d9:c7:c4:10:f3:28:3f:6f:e3:f3:b4: + 24:0e:21:24:7a:bf:61:ff:82:88:e1:ec:58:65:07: + 00:51:3c:c4:6b:08:d4:4f:81:34:63:c4:ba:31:bf: + df:ef:ea:05:ce:d7:0e:06:53:39:87:82:b8:d2:dd: + 0f:b2:85:d6:9c:a5:17:26:ba:10:bc:c9:16:a0:10: + 6e:d3:a6:08:92:5e:48:5f:18:7e:ee:fd:b3:b4:56: + 6f:cb:c1:25:6b:4c:df:fa:73:a2:75:b1:ed:a9:54: + 21:57:22:eb:97:d1:c1:3e:be:6f:50:da:4a:fd:52: + 4c:9a:94:bc:6b:ec:04:c1:e3:78:3f:ba:29:63:bc: + 91:16:8a:75:f3:67:f7:00:2f:dd:fa:eb:ec:ac:a3: + a7:7d:bd:31:a4:df:75:7e:33:fc:a1:c5:1e:a1:59: + 26:19:a6:c8:46:85:8b:0e:ec:7d:aa:54:4d:44:11: + 75:15:6f:c6:93:ff:01:9e:2b:4c:2b:04:32:3c:18: + c0:db:10:73:b4:25:86:54:ca:74:9c:2a:31:5c:00: + 38:42:7d:b4:59:92:df:0a:35:0d:e0:1b:3d:d9:2e: + 54:c7:8f:73:93:27:06:d6:c9:50:62:4f:e5:2b:71: + db:ec:e2:e9:05:0c:22:56:49:ef:99:c7:e2:f8:93: + e8:39:36:1c:07:3e:bd:e8:72:df:62:88:73:c6:ba: + ae:31:df:86:74:69:e1:d4:e6:fc:81:4c:2e:a7:bf: + 61:4e:6e:96:e8:8e:30:63:0e:d7:51:73:c4:d3:5e: + c1:27:a4:24:94:e0:80:da:ac:e7:75:49:e4:25:b8: + a1:c8:2f:d2:a8:8e:68:1a:17:86:be:f0:0b:d5:a2: + a1:f4:d9:e2:93:b9:51:11:f3:9c:87:67:6b:ae:0a: + ed:59:83:c7:32:6e:b6:34:51:6a:d7:d0:2b:3a:fa: + 5e:b9:19:1d:fc:99:b2:3d:11:aa:37:e6:b7:35:36: + a9:5b:c9 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: + Digital Signature, Non Repudiation, Key Encipherment + X509v3 Extended Key Usage: + OCSP Signing + Signature Algorithm: sha1WithRSAEncryption + 5c:04:b3:8a:53:cb:8e:c2:bb:fa:8a:1c:2c:fc:1a:8f:f0:11: + ee:b5:f4:c7:66:b7:99:72:63:30:5e:48:ea:e5:59:37:c0:ea: + e1:c1:81:7e:6d:26:ea:f7:c7:eb:42:3c:a3:1c:92:70:d2:4d: + 6c:03:06:8c:bb:3a:af:70:e0:b5:bd:4a:a8:39:84:10:d9:43: + aa:77:7d:25:9a:bc:72:79:03:ea:8a:c1:db:15:a8:34:13:a5: + 30:66:55:66:6a:06:bd:12:0a:67:c3:0a:4d:06:e0:15:53:59: + ed:be:9b:90:07:9d:0b:92:ed:74:76:99:67:e3:d5:fe:74:e3: + 82:08:13:0d:ea:57:dc:af:73:19:40:b1:f4:60:71:d5:4e:66: + 67:ae:32:af:40:fc:79:2a:65:da:56:36:f8:f6:26:72:42:e5: + 42:18:41:15:2f:46:f8:82:d0:57:50:51:c5:10:4c:0e:a2:82: + 44:3b:44:85:b4:c5:a3:93:3a:72:fc:75:62:9a:30:c2:b8:ba: + b6:0d:d5:d9:be:e6:bb:1a:da:42:6a:f4:48:de:30:b4:6c:cc: + ed:9b:b8:a0:12:54:9d:26:78:0b:5d:ec:38:9a:c4:ad:1c:60: + b1:01:fc:3e:2a:5a:ac:b6:ed:5e:f0:8c:30:66:52:db:9b:61: + 8c:5d:df:36:14:2c:fe:4d:82:a8:13:df:a5:e1:1c:fe:02:f0: + 2c:88:fe:39:51:e7:a4:80:4b:2d:28:95:b7:6c:8d:2f:a0:e2: + f5:44:16:eb:39:09:0e:d5:27:8f:f4:92:b6:7f:34:0f:ca:ed: + 29:38:52:77:95:b5:06:23:ec:23:57:fe:a8:4c:77:2b:24:d0: + bb:f4:12:3e:f9:fa:59:45:50:8c:76:c7:23:0d:9c:23:0c:ab: + e1:6d:55:62:ce:dd:55:41:77:f2:40:8e:25:c6:a8:d5:a5:b8: + fc:51:d7:b9:e1:17:8d:4c:82:45:b0:7c:9c:4c:f0:d0:40:3e: + 14:18:04:17:f6:ae:b3:c5:db:db:86:7a:e4:b9:79:6d:a4:8c: + dd:e2:95:56:6f:82:a1:4e:cc:aa:76:0a:eb:4d:d2:f5:ed:9b: + f4:34:a1:d7:7a:95:57:c7:6b:e0:b9:f6:b1:17:f6:8a:73:c4: + 8a:97:ac:c9:5c:28:30:56:66:3a:44:74:1c:07:43:5f:a8:36: + 11:f1:95:9f:6c:34:c9:2c:2a:24:5e:4f:3f:9f:7f:58:95:f3: + 35:a9:d8:67:a7:3d:1f:ae:3e:26:0d:87:c2:f6:9d:19:cf:ac: + d4:12:a5:4a:1f:dc:cb:c2:7a:c1:8e:93:9a:98:8a:2c:20:52: + 1f:02:da:63:ce:ae:7c:e3 +-----BEGIN CERTIFICATE----- +MIIFhjCCA26gAwIBAgIBBDANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJESzET +MBEGA1UEBwwKQ29wZW5oYWdlbjEPMA0GA1UECgwGV2luVExTMTIwMAYDVQQDDClX +aW5UTFMgSW50ZXJtZWRpYXRlIENlcnRpZmljYXRlIEF1dGhvcml0eTAgFw0yMjA4 +MTcwODU5NDhaGA8yMTIyMDgxODA4NTk0OFowczELMAkGA1UEBhMCREsxEzARBgNV +BAcMCkNvcGVuaGFnZW4xDzANBgNVBAoMBldpblRMUzE+MDwGA1UEAww1V2luVExT +IEludGVybWVkaWF0ZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgT0NTUCBzaWduZXIw +ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDlkUzsYANdCFk7ij5+TEmx +pJH5bzYaGNtB0B3QU90W2oW8/CZzyqwiqfJ6g3dlJJQqigqVOsJbu8Wq/LlWgvWl +mR0sBxioYZd+lNu3qJKa8mvWV/IGprb5NuoPgRZI7zTUcNuR7y0KQSFVcC3YEfc0 +20RUZLzDL5QzFOLFLBupiSawv5acc6Dk8JrZx8QQ8yg/b+PztCQOISR6v2H/gojh +7FhlBwBRPMRrCNRPgTRjxLoxv9/v6gXO1w4GUzmHgrjS3Q+yhdacpRcmuhC8yRag +EG7TpgiSXkhfGH7u/bO0Vm/LwSVrTN/6c6J1se2pVCFXIuuX0cE+vm9Q2kr9Ukya +lLxr7ATB43g/uiljvJEWinXzZ/cAL9366+yso6d9vTGk33V+M/yhxR6hWSYZpshG +hYsO7H2qVE1EEXUVb8aT/wGeK0wrBDI8GMDbEHO0JYZUynScKjFcADhCfbRZkt8K +NQ3gGz3ZLlTHj3OTJwbWyVBiT+Urcdvs4ukFDCJWSe+Zx+L4k+g5NhwHPr3oct9i +iHPGuq4x34Z0aeHU5vyBTC6nv2FObpbojjBjDtdRc8TTXsEnpCSU4IDarOd1SeQl +uKHIL9KojmgaF4a+8AvVoqH02eKTuVER85yHZ2uuCu1Zg8cybrY0UWrX0Cs6+l65 +GR38mbI9Eao35rc1NqlbyQIDAQABoy8wLTAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF +4DATBgNVHSUEDDAKBggrBgEFBQcDCTANBgkqhkiG9w0BAQUFAAOCAgEAXASzilPL +jsK7+oocLPwaj/AR7rX0x2a3mXJjMF5I6uVZN8Dq4cGBfm0m6vfH60I8oxyScNJN +bAMGjLs6r3Dgtb1KqDmEENlDqnd9JZq8cnkD6orB2xWoNBOlMGZVZmoGvRIKZ8MK +TQbgFVNZ7b6bkAedC5LtdHaZZ+PV/nTjgggTDepX3K9zGUCx9GBx1U5mZ64yr0D8 +eSpl2lY2+PYmckLlQhhBFS9G+ILQV1BRxRBMDqKCRDtEhbTFo5M6cvx1Ypowwri6 +tg3V2b7muxraQmr0SN4wtGzM7Zu4oBJUnSZ4C13sOJrErRxgsQH8PiparLbtXvCM +MGZS25thjF3fNhQs/k2CqBPfpeEc/gLwLIj+OVHnpIBLLSiVt2yNL6Di9UQW6zkJ +DtUnj/SStn80D8rtKThSd5W1BiPsI1f+qEx3KyTQu/QSPvn6WUVQjHbHIw2cIwyr +4W1VYs7dVUF38kCOJcao1aW4/FHXueEXjUyCRbB8nEzw0EA+FBgEF/aus8Xb24Z6 +5Ll5baSM3eKVVm+CoU7MqnYK603S9e2b9DSh13qVV8dr4Ln2sRf2inPEipesyVwo +MFZmOkR0HAdDX6g2EfGVn2w0ySwqJF5PP59/WJXzNanYZ6c9H64+Jg2HwvadGc+s +1BKlSh/cy8J6wY6TmpiKLCBSHwLaY86ufOM= +-----END CERTIFICATE----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/ocsp_signer_ca_intermediate.csr b/third-party/boost-wintls/test/test_certificates/gen/ocsp_signer_ca_intermediate.csr new file mode 100644 index 00000000000..54671044862 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/ocsp_signer_ca_intermediate.csr @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIE9jCCAt4CAQAwczELMAkGA1UEBhMCREsxEzARBgNVBAcMCkNvcGVuaGFnZW4x +DzANBgNVBAoMBldpblRMUzE+MDwGA1UEAww1V2luVExTIEludGVybWVkaWF0ZSBD +ZXJ0aWZpY2F0ZSBBdXRob3JpdHkgT0NTUCBzaWduZXIwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQDlkUzsYANdCFk7ij5+TEmxpJH5bzYaGNtB0B3QU90W +2oW8/CZzyqwiqfJ6g3dlJJQqigqVOsJbu8Wq/LlWgvWlmR0sBxioYZd+lNu3qJKa +8mvWV/IGprb5NuoPgRZI7zTUcNuR7y0KQSFVcC3YEfc020RUZLzDL5QzFOLFLBup +iSawv5acc6Dk8JrZx8QQ8yg/b+PztCQOISR6v2H/gojh7FhlBwBRPMRrCNRPgTRj +xLoxv9/v6gXO1w4GUzmHgrjS3Q+yhdacpRcmuhC8yRagEG7TpgiSXkhfGH7u/bO0 +Vm/LwSVrTN/6c6J1se2pVCFXIuuX0cE+vm9Q2kr9UkyalLxr7ATB43g/uiljvJEW +inXzZ/cAL9366+yso6d9vTGk33V+M/yhxR6hWSYZpshGhYsO7H2qVE1EEXUVb8aT +/wGeK0wrBDI8GMDbEHO0JYZUynScKjFcADhCfbRZkt8KNQ3gGz3ZLlTHj3OTJwbW +yVBiT+Urcdvs4ukFDCJWSe+Zx+L4k+g5NhwHPr3oct9iiHPGuq4x34Z0aeHU5vyB +TC6nv2FObpbojjBjDtdRc8TTXsEnpCSU4IDarOd1SeQluKHIL9KojmgaF4a+8AvV +oqH02eKTuVER85yHZ2uuCu1Zg8cybrY0UWrX0Cs6+l65GR38mbI9Eao35rc1Nqlb +yQIDAQABoD4wPAYJKoZIhvcNAQkOMS8wLTAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF +4DATBgNVHSUEDDAKBggrBgEFBQcDCTANBgkqhkiG9w0BAQsFAAOCAgEAjQqhDZ1e +WEptPQxJvpSvrerDhkmFPgVbkWYWNrSax3gTNqbRXWShAGeVV/ZbZm1W+QvT6p/M +oRrJ2RegI9yO2d6dkdabUsROMHgc2/KKeHt3bCOkRn1nYhUBsELcY9KHm6ViAnVK +IDFupJD6KTlYmIsJhGn3c2BTa6tekGzMfKC/3GE8HQU7JeOTCITlbANPIRpZ5IwT +kWfXUjyLRc5+XcVpEGgFNjoWvYkoTGxWv1i98e2CrG9IILJNmbXbdO1RkU0IfiTJ +7+hdDXI6f8PyFvslFTE3p/MJ5flkdJpkStBva4htMnjUBhySpkMXwgzhVvssPwT7 +azcutyCF5V0SxVj6trs+tfasASUZLa1FExIxHKO+0IVT8ipkEWdXl9+HicjHKiGh +DzjsVY61/OJsETNQZYB0pWeLeQwgWOfwADoLhzYthN9iayCbu+3wzN1m0FOXD7kx +3JFVZnmYtyiERFXQTXLRRgNwFyvTFXpmXIHUkBt5gh2pTXRIMp/PGtlXOUexSBhv +YYHiHj/e3WXRC6rfTCgQiM04CgXSGx0JWXlAwz/WUTBi/iawjo6QWN5YIRsr0gVf +CXnp4+eSyc6Sgkd6l5twTEBCY/fcG01AgEdOEZYv2hNn/w5CyDRb/ylPmwkJ2XcC +ueRlA4OJPZhG2FQEbMUUSX1ljT99QoyWXFE= +-----END CERTIFICATE REQUEST----- diff --git a/third-party/boost-wintls/test/test_certificates/gen/ocsp_signer_ca_intermediate.key b/third-party/boost-wintls/test/test_certificates/gen/ocsp_signer_ca_intermediate.key new file mode 100644 index 00000000000..20ac32f3f5d --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/gen/ocsp_signer_ca_intermediate.key @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDlkUzsYANdCFk7 +ij5+TEmxpJH5bzYaGNtB0B3QU90W2oW8/CZzyqwiqfJ6g3dlJJQqigqVOsJbu8Wq +/LlWgvWlmR0sBxioYZd+lNu3qJKa8mvWV/IGprb5NuoPgRZI7zTUcNuR7y0KQSFV +cC3YEfc020RUZLzDL5QzFOLFLBupiSawv5acc6Dk8JrZx8QQ8yg/b+PztCQOISR6 +v2H/gojh7FhlBwBRPMRrCNRPgTRjxLoxv9/v6gXO1w4GUzmHgrjS3Q+yhdacpRcm +uhC8yRagEG7TpgiSXkhfGH7u/bO0Vm/LwSVrTN/6c6J1se2pVCFXIuuX0cE+vm9Q +2kr9UkyalLxr7ATB43g/uiljvJEWinXzZ/cAL9366+yso6d9vTGk33V+M/yhxR6h +WSYZpshGhYsO7H2qVE1EEXUVb8aT/wGeK0wrBDI8GMDbEHO0JYZUynScKjFcADhC +fbRZkt8KNQ3gGz3ZLlTHj3OTJwbWyVBiT+Urcdvs4ukFDCJWSe+Zx+L4k+g5NhwH +Pr3oct9iiHPGuq4x34Z0aeHU5vyBTC6nv2FObpbojjBjDtdRc8TTXsEnpCSU4IDa +rOd1SeQluKHIL9KojmgaF4a+8AvVoqH02eKTuVER85yHZ2uuCu1Zg8cybrY0UWrX +0Cs6+l65GR38mbI9Eao35rc1NqlbyQIDAQABAoICAC1OXcYQtNk5epLbl7XJTIn4 +lq6Jmj3QRgVZE2k4A9wsyFQh11zm1M4KiEZRh9C4RV2X3LrS2+TKzBoQwmsmcWB7 +NVypEd65U/KxYiN+62AVE987gBJ7+IR6p/rjWQiP3PdIRq0obNUnQXLhLssD0Kvn +0jZtoytKSo9CQfbz24m7/ZzIUusRjuFf8s+kMze9JWZPqMdB+BOpys9G0gphMq6T +vGZD2XYu7fzJw0zljPdbrft/iKyKnRbTLntlFWd/DwbeheiPrWlA067a7c60SPjS +BW1TyUFJxjKuXO7BtyOSI4Is3jus8k81XwynTuYqKmJOC/zscpz1bHaifkY8Zc2E +Xx8gaunYk/fwdt8mF60IwvhO8pPs/ndLBjxd2P4yc4a5i5fQ+WOr0w1+uP9px16m +ip0l4EICd9pvyVITsH4Snfm5mKI+0euWyyiXUJyTloh2V6a7ye0xkllros19nWj0 +/PIBVN4P1bRaUy07Vcbkm7Br54oJLXjYoo8wFvJQsvNMjMf0EGxwdAQLJrBYVVOU +IgW5h7xL1gjfhWQl5C5/ylk466X3aSEqC3E1C9f0ZxmYtqDPakI69GeXGDVomNWn +eeyzaVxAZdwpYgr1W2ZmDmqMiqdu350+zrkG+olGsegYHI1l4bK06sYyLGzZ2O+l +6nKDEHDl7ASjn+o+ZbLhAoIBAQD90cCrlsMDtWSp5llJVRxUPxYzNV9HA3YvYZhf +UIdTMDeJTH4P0JShKCDpAXuG/Ik2zEXaxHJPLfYNitrdm0+0ksBmpFd6bkVOzuZ7 +EjkfdICCcB+8BcelvB/8MrCabiO34ij/qFNLEuIgntwjTji2i0oJAyzs0+RUKxEd +vvTSbXomodOC2CTCUalO7MRVq0Y2vo3HghaBXZU57ZfwfJMbQfyKrdwacSSmUTfI +lYb89eBMS+11tXCXAyRR40F0KIKDxNHFz4gwh8UavUF3XL68x0mrPGh0OQ1iFii5 +hVEjvwBpERo757KxhvfImkRYLyTpOnqv7tyCxfPPgv1QAf8lAoIBAQDnijV0PxTa +qIVkSTlM5ixRhz3ByEL7QM1OlXZwA+k+OrlHtING8aZaLkqRB2acHmK8zsi+K4tV +U01jmR7hcprNiiJMn/3TjLvpM/TuL+HIsKVGoTlDwtEMT/orIFYcDNsy/UL/a+QW +aBe0v5XApKltQEPKHBtnJ2ygucKiYZdjsMFi8fax+IQ5gvHYVAVgHBV7R9mtHdHn +ys1sFE8bd1UnXhncr1oKsc7Ev1FEVgn0Wl61gaqkp7dxOPD94CFK+wx1WzyxES+c +qCYiEpkTD4ZXkUPYSgOncXqatZlFmbhcaP+PtqiO+tSflW8c2dwbFZ7l3Jxx9VW+ +frfETQBlVCrVAoIBAQD2k7W8PEsZqDexwkDNN+y8f0ke2GPGBjvjTcmMFxxQGZBq +RrBUxsoNQYGvOqx5d44JeSsHmz59Y2Ycw99Z2A73mnVlgZQmMUgNhnxr5UkvIKvT +i/+YVnkcrgTYqZndfNAgTIqNy0WXsjGRhSLQ/aWk2O5EkRwsurCff/Mx1ZfbcVVw +gFeNTlNvn4t+TA90Nl6Qwk/UGLGqXXKiAwpPK4ZxvYoMY1hnK7FyDYbGy1SHHIoZ +NM3sQyas3fWDw+WLZetc/XDY3YMtukgmcONPhP8bP/N2ccn71o0E1AgeKsCnnF9W +srGsrqtvQXIoJI3uqWYPWatkjQUV2h7AYj2aY0YtAoIBAQCH+grachF1OHLeKoKU +PrjYSGxkWY+8rpnkBLLBpgpcmXAmRES0bUYcwALamVYRaWbjKy2JQVlaislwLISO +MhfnjbAHAA65JnVUx0aYe1ZF3jex+wz+VnMen/lzSlJHtuUkVMf76QjSf98sLzdr +I0i8+HjXQRp2whhxa6Z6ZoXZ7fwkd6VBb4l3nQca3H0rrFKRS+jyWgjj754kUukC +YFqJ/CGEERb4IOQld5XqY/0Em+3y+muUt0psG9yru+zRdA4k/afu9QDZJ4b9i56K +KxviYVVOuGjc9S/jm7KfxV8YJjGv3L2w+m3UKpZOg0NYRKJErALUihgI/7I8flw1 +JfDhAoIBAQCIZN/p8C1Fzx1jYDkT7kl+EraOl43u4JicyhiBpl2qT0FJfasTEtaL +xbKk27SzOjGwsn4heZxRxjgP6ipOMyTWmI7mRvQihkfsfcbXRqRyh97nEZIe6Yp6 +5TyTYCmthTGSpTuPpELiNAChYucIsgz+s/sPzynE7N+bXZmh809KTOqd8wWVOUw2 +qqnzNHvVX7LiYLIcYOCNN2RgSNwwDzbyNzrgrNECifQbK0xhfRGIZ+US/rGSpYMr +mrzYLCo5e4cK+y53XTz6kAedBw5k7zp5GoWC1dq3RLx6pAix/br2H07Ooaixp2FK +NKx71EPxILyltr5oWlsq8WL+9EJ32wE8 +-----END PRIVATE KEY----- diff --git a/third-party/boost-wintls/test/test_certificates/generate_certs.sh b/third-party/boost-wintls/test/test_certificates/generate_certs.sh new file mode 100644 index 00000000000..7636583afc5 --- /dev/null +++ b/third-party/boost-wintls/test/test_certificates/generate_certs.sh @@ -0,0 +1,47 @@ +# This script is used to generate all the files in ./gen using the config files from ./conf. +# These files are used from the unit tests in certificate_test.cpp + +# Clear all previously generated files +rm -rf gen +mkdir -p gen + +# Generate self signed Root certificate valid for 100 years +openssl req -days 36525 -nodes -new -x509 -keyout gen/ca_root.key -out gen/ca_root.crt -config conf/ca_root.conf +# Request intermediate certificate +openssl req -nodes -new -keyout gen/ca_intermediate.key -out gen/ca_intermediate.csr -config conf/ca_intermediate.conf +# Request leaf certificates +openssl req -nodes -new -keyout gen/leaf.key -out gen/leaf.csr -config conf/leaf.conf +openssl req -nodes -new -keyout gen/leaf_ocsp.key -out gen/leaf_ocsp.csr -config conf/leaf_ocsp.conf +openssl req -nodes -new -keyout gen/leaf_ocsp_revoked.key -out gen/leaf_ocsp_revoked.csr -config conf/leaf_ocsp.conf +openssl req -nodes -new -keyout gen/ocsp_signer_ca_intermediate.key -out gen/ocsp_signer_ca_intermediate.csr -config conf/ocsp_signer_ca_intermediate.conf + +# Setup for signing the subordinate certificates +touch gen/certindex +echo 01 > gen/certserial +echo 01 > gen/crlnumber +mkdir -p gen/newcerts + +# Sign intermediate certificate +openssl x509 -req -CA gen/ca_root.crt -CAkey gen/ca_root.key -CAcreateserial -days 36525 -extensions req_v3_ca -extfile conf/ca_intermediate.conf -in gen/ca_intermediate.csr -out gen/ca_intermediate.crt +# Sign leaf certificates +SIGN_LEAF_COMMON_PARAMS="ca -config conf/ca_intermediate.conf -extensions req_v3_usr -batch" +openssl $SIGN_LEAF_COMMON_PARAMS -extfile conf/leaf.conf -in gen/leaf.csr -out gen/leaf.crt +openssl $SIGN_LEAF_COMMON_PARAMS -extfile conf/leaf_ocsp.conf -in gen/leaf_ocsp.csr -out gen/leaf_ocsp.crt +openssl $SIGN_LEAF_COMMON_PARAMS -extfile conf/leaf_ocsp.conf -in gen/leaf_ocsp_revoked.csr -out gen/leaf_ocsp_revoked.crt +openssl $SIGN_LEAF_COMMON_PARAMS -extfile conf/ocsp_signer_ca_intermediate.conf -in gen/ocsp_signer_ca_intermediate.csr -out gen/ocsp_signer_ca_intermediate.crt + +# Create certificate chains for the leaf certificates +cat gen/leaf.crt gen/ca_intermediate.crt gen/ca_root.crt > gen/leaf_chain.pem +cat gen/leaf_ocsp.crt gen/ca_intermediate.crt gen/ca_root.crt > gen/leaf_ocsp_chain.pem +cat gen/leaf_ocsp_revoked.crt gen/ca_intermediate.crt gen/ca_root.crt > gen/leaf_ocsp_revoked_chain.pem + +# Generate empty CRL +openssl ca -config conf/ca_root.conf -gencrl -out gen/ca_root_empty.crl.pem +openssl ca -config conf/ca_intermediate.conf -gencrl -out gen/ca_intermediate_empty.crl.pem + +# Revoke leaf.crt and leaf_ocsp_revoked.crt +openssl ca -config conf/ca_intermediate.conf -revoke gen/leaf.crt +openssl ca -config conf/ca_intermediate.conf -revoke gen/leaf_ocsp_revoked.crt + +# Generate CRL including the revoked certificates +openssl ca -config conf/ca_intermediate.conf -gencrl -out gen/ca_intermediate_leaf_revoked.crl.pem diff --git a/third-party/boost-wintls/test/tls_record.cpp b/third-party/boost-wintls/test/tls_record.cpp new file mode 100644 index 00000000000..0ab48215504 --- /dev/null +++ b/third-party/boost-wintls/test/tls_record.cpp @@ -0,0 +1,92 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include "tls_record.hpp" + +namespace { +std::uint8_t net_to_host(std::uint8_t value) { + return value; +} + +std::uint16_t net_to_host(std::uint16_t value) { + return ntohs(value); +} + +std::uint32_t net_to_host(std::uint32_t value) { + return ntohl(value); +} + +template +SizeType read_value(net::const_buffer& buffer) { + BOOST_ASSERT(buffer.size() >= sizeof(SizeType)); + SizeType ret = *reinterpret_cast(buffer.data()); + buffer += sizeof(SizeType); + return net_to_host(ret); +} + +std::uint32_t read_three_byte_value(net::const_buffer& buffer) { + BOOST_ASSERT(buffer.size() >= 3); + std::array value{}; + std::copy_n(reinterpret_cast(buffer.data()), 3, value.begin() + 1); + buffer += 3; + return net_to_host(*reinterpret_cast(value.data())); +} + +tls_record::message_type read_message(tls_record::record_type type, net::const_buffer& buffer) { + switch(type) { + case tls_record::record_type::change_cipher_spec: + return tls_change_cipher_spec{}; + case tls_record::record_type::alert: + return tls_alert{}; + case tls_record::record_type::handshake: + return tls_handshake{buffer}; + case tls_record::record_type::application_data: + return tls_application_data{}; + } + BOOST_UNREACHABLE_RETURN(0); +} + +tls_handshake::message_type read_message(tls_handshake::handshake_type t, net::const_buffer&) { + switch(t) { + case tls_handshake::handshake_type::hello_request: + return tls_handshake::hello_request{}; + case tls_handshake::handshake_type::client_hello: + return tls_handshake::client_hello{}; + case tls_handshake::handshake_type::server_hello: + return tls_handshake::server_hello{}; + case tls_handshake::handshake_type::certificate: + return tls_handshake::certificate{}; + case tls_handshake::handshake_type::server_key_exchange: + return tls_handshake::server_key_exchange{}; + case tls_handshake::handshake_type::certificate_request: + return tls_handshake::certificate_request{}; + case tls_handshake::handshake_type::server_done: + return tls_handshake::server_done{}; + case tls_handshake::handshake_type::certificate_verify: + return tls_handshake::certificate_verify{}; + case tls_handshake::handshake_type::client_key_exchange: + return tls_handshake::client_key_exchange{}; + case tls_handshake::handshake_type::finished: + return tls_handshake::finished{}; + } + BOOST_UNREACHABLE_RETURN(0); +} + +} // namespace + +tls_handshake::tls_handshake(net::const_buffer data) + : type(static_cast(read_value(data))) + , size(read_three_byte_value(data)) + , message(read_message(type, data)) { +} + +tls_record::tls_record(net::const_buffer data) + : type(static_cast(read_value(data))) + , version(static_cast(read_value(data))) + , size(read_value(data)) + , message(read_message(type, data)) { +} diff --git a/third-party/boost-wintls/test/tls_record.hpp b/third-party/boost-wintls/test/tls_record.hpp new file mode 100644 index 00000000000..c2e16418816 --- /dev/null +++ b/third-party/boost-wintls/test/tls_record.hpp @@ -0,0 +1,128 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_WINTLS_TEST_TLS_RECORD_HPP +#define BOOST_WINTLS_TEST_TLS_RECORD_HPP + +#include "unittest.hpp" + +#include + +#include + +enum class tls_version : std::uint16_t { + ssl_3_0 = 0x0300, + tls_1_0 = 0x0301, + tls_1_1 = 0x0302, + tls_1_2 = 0x0303, + tls_1_3 = 0x0304 +}; + +struct tls_change_cipher_spec { + // TODO: Implement +}; + +struct tls_alert { + // TODO: Implement +}; + +struct tls_handshake { + enum class handshake_type : std::uint8_t { + hello_request = 0x00, + client_hello = 0x01, + server_hello = 0x02, + certificate = 0x0b, + server_key_exchange = 0x0c, + certificate_request = 0x0d, + server_done = 0x0e, + certificate_verify = 0x0f, + client_key_exchange = 0x10, + finished = 0x14 + }; + + struct hello_request { + // TODO: Implement + }; + + struct client_hello { + // TODO: Implement + }; + + struct server_hello { + // TODO: Implement + }; + + struct certificate { + // TODO: Implement + }; + + struct server_key_exchange { + // TODO: Implement + }; + + struct certificate_request { + // TODO: Implement + }; + + struct server_done { + // TODO: Implement + }; + + struct certificate_verify { + // TODO: Implement + }; + + struct client_key_exchange { + // TODO: Implement + }; + + struct finished { + // TODO: Implement + }; + + using message_type = boost::variant; + + tls_handshake(net::const_buffer data); + + handshake_type type; + std::uint32_t size; + message_type message; +}; + +struct tls_application_data { + // TODO: Implement +}; + +struct tls_record { + enum class record_type : std::uint8_t { + change_cipher_spec = 0x14, + alert = 0x15, + handshake = 0x16, + application_data = 0x17 + }; + + using message_type = boost::variant; + tls_record(net::const_buffer data); + + record_type type; + tls_version version; + std::uint16_t size; + message_type message; +}; + +#endif // BOOST_WINTLS_TEST_TLS_RECORD_HPP diff --git a/third-party/boost-wintls/test/unittest.hpp b/third-party/boost-wintls/test/unittest.hpp new file mode 100644 index 00000000000..e462c5c4197 --- /dev/null +++ b/third-party/boost-wintls/test/unittest.hpp @@ -0,0 +1,50 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef BOOST_WINTLS_UNITTEST_HPP +#define BOOST_WINTLS_UNITTEST_HPP + +#include + +// Workaround missing include in boost 1.76 and 1.77 in beast::test::stream +#if (BOOST_VERSION / 100 % 1000) == 77 || (BOOST_VERSION / 100 % 1000) == 76 +#include +#endif + +#include +#include + +#include + +#include +#include +#include +#include + +namespace Catch { +template<> +struct StringMaker { + static std::string convert(const boost::system::error_code& ec) { + std::ostringstream oss; + oss << ec.message() << " (0x" << std::hex << ec.value() << ")"; + return oss.str(); + } +}; +} + +inline std::vector bytes_from_file(const std::string& path) { + std::ifstream ifs{path}; + if (ifs.fail()) { + throw std::runtime_error("Failed to open file " + path); + } + return {std::istreambuf_iterator{ifs}, {}}; +} + +namespace net = boost::wintls::net; +namespace asio_ssl = boost::asio::ssl; +using test_stream = boost::beast::test::stream; + +#endif // BOOST_WINTLS_UNITTEST_HPP diff --git a/third-party/boost-wintls/test/wintls_client_stream.hpp b/third-party/boost-wintls/test/wintls_client_stream.hpp new file mode 100644 index 00000000000..8cb3a000374 --- /dev/null +++ b/third-party/boost-wintls/test/wintls_client_stream.hpp @@ -0,0 +1,77 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef WINTLS_CLIENT_STREAM_HPP +#define WINTLS_CLIENT_STREAM_HPP + +#include "certificate.hpp" +#include "unittest.hpp" + +#include + +#include +#include + +const std::string test_key_name_client = test_key_name + "-client"; + +struct wintls_client_context : public boost::wintls::context { + wintls_client_context() + : boost::wintls::context(boost::wintls::method::system_default) + , needs_private_key_clean_up_(false) + , authority_ptr_() { + } + + void with_test_cert_authority() { + if(!authority_ptr_) { + authority_ptr_ = x509_to_cert_context(net::buffer(test_certificate), boost::wintls::file_format::pem); + add_certificate_authority(authority_ptr_.get()); + } + } + + void with_test_client_cert() { + with_test_cert_authority(); + + // delete key in case last test run has dangling key. + boost::system::error_code dummy; + boost::wintls::delete_private_key(test_key_name_client, dummy); + + boost::wintls::import_private_key(net::buffer(test_key), boost::wintls::file_format::pem, test_key_name_client); + needs_private_key_clean_up_ = true; + boost::wintls::assign_private_key(authority_ptr_.get(), test_key_name_client); + use_certificate(authority_ptr_.get()); + } + + void enable_server_verify() { + verify_server_certificate(true); + } + + ~wintls_client_context() { + if(needs_private_key_clean_up_) { + boost::wintls::delete_private_key(test_key_name_client); + needs_private_key_clean_up_ = false; + } + } + +private: + bool needs_private_key_clean_up_; + boost::wintls::cert_context_ptr authority_ptr_; +}; + +struct wintls_client_stream { + using handshake_type = boost::wintls::handshake_type; + + template + wintls_client_stream(Args&&... args) + : tst(std::forward(args)...) + , stream(tst, ctx) { + } + + wintls_client_context ctx; + test_stream tst; + boost::wintls::stream stream; +}; + +#endif // WINTLS_CLIENT_STREAM_HPP diff --git a/third-party/boost-wintls/test/wintls_server_stream.hpp b/third-party/boost-wintls/test/wintls_server_stream.hpp new file mode 100644 index 00000000000..3b040c537fa --- /dev/null +++ b/third-party/boost-wintls/test/wintls_server_stream.hpp @@ -0,0 +1,62 @@ +// +// Copyright (c) 2021 Kasper Laudrup (laudrup at stacktrace dot dk) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef WINTLS_SERVER_STREAM_HPP +#define WINTLS_SERVER_STREAM_HPP + +#include "unittest.hpp" +#include "certificate.hpp" + +#include + +const std::string test_key_name_server = test_key_name + "-server"; + +struct wintls_server_context : public boost::wintls::context { + wintls_server_context() + : boost::wintls::context(boost::wintls::method::system_default) + , needs_private_key_clean_up_(false) { + // delete key in case last test run has dangling key. + boost::system::error_code dummy; + boost::wintls::delete_private_key(test_key_name_server, dummy); + + auto cert_ptr = x509_to_cert_context(net::buffer(test_certificate), boost::wintls::file_format::pem); + boost::wintls::import_private_key(net::buffer(test_key), boost::wintls::file_format::pem, test_key_name_server); + needs_private_key_clean_up_ = true; + boost::wintls::assign_private_key(cert_ptr.get(), test_key_name_server); + add_certificate_authority(cert_ptr.get()); + use_certificate(cert_ptr.get()); + } + + void enable_client_verify() { + verify_server_certificate(true); + } + + ~wintls_server_context() { + if(needs_private_key_clean_up_) { + boost::wintls::delete_private_key(test_key_name_server); + needs_private_key_clean_up_ = false; + } + } + +private: + bool needs_private_key_clean_up_; +}; + +struct wintls_server_stream { + using handshake_type = boost::wintls::handshake_type; + + template + wintls_server_stream(Args&&... args) + : tst(std::forward(args)...) + , stream(tst, ctx) { + } + + wintls_server_context ctx; + test_stream tst; + boost::wintls::stream stream; +}; + +#endif // WINTLS_SERVER_STREAM_HPP