diff options
author | comex <comexk@gmail.com> | 2023-07-02 00:02:25 +0200 |
---|---|---|
committer | comex <comexk@gmail.com> | 2023-07-02 02:27:35 +0200 |
commit | 0e191c271125321589dfdbb09731413550710c9a (patch) | |
tree | e0d9e826197d2fd66cc9b7fd8d11cc8c7fd6e3ac /src/core/hle/service/ssl/ssl_backend_schannel.cpp | |
parent | Merge remote-tracking branch 'origin/master' into ssl (diff) | |
download | yuzu-0e191c271125321589dfdbb09731413550710c9a.tar yuzu-0e191c271125321589dfdbb09731413550710c9a.tar.gz yuzu-0e191c271125321589dfdbb09731413550710c9a.tar.bz2 yuzu-0e191c271125321589dfdbb09731413550710c9a.tar.lz yuzu-0e191c271125321589dfdbb09731413550710c9a.tar.xz yuzu-0e191c271125321589dfdbb09731413550710c9a.tar.zst yuzu-0e191c271125321589dfdbb09731413550710c9a.zip |
Diffstat (limited to 'src/core/hle/service/ssl/ssl_backend_schannel.cpp')
-rw-r--r-- | src/core/hle/service/ssl/ssl_backend_schannel.cpp | 207 |
1 files changed, 106 insertions, 101 deletions
diff --git a/src/core/hle/service/ssl/ssl_backend_schannel.cpp b/src/core/hle/service/ssl/ssl_backend_schannel.cpp index 775d5cc07..a1d6a186e 100644 --- a/src/core/hle/service/ssl/ssl_backend_schannel.cpp +++ b/src/core/hle/service/ssl/ssl_backend_schannel.cpp @@ -48,6 +48,12 @@ static void OneTimeInit() { return; } + if (getenv("SSLKEYLOGFILE")) { + LOG_CRITICAL(Service_SSL, "SSLKEYLOGFILE was set but Schannel does not support exporting " + "keys; not logging keys!"); + // Not fatal. + } + one_time_init_success = true; } @@ -70,25 +76,25 @@ public: return ResultSuccess; } - void SetSocket(std::shared_ptr<Network::SocketBase> socket) override { - socket_ = socket; + void SetSocket(std::shared_ptr<Network::SocketBase> socket_in) override { + socket = std::move(socket_in); } - Result SetHostName(const std::string& hostname) override { - hostname_ = hostname; + Result SetHostName(const std::string& hostname_in) override { + hostname = hostname_in; return ResultSuccess; } Result DoHandshake() override { while (1) { Result r; - switch (handshake_state_) { + switch (handshake_state) { case HandshakeState::Initial: if ((r = FlushCiphertextWriteBuf()) != ResultSuccess || (r = CallInitializeSecurityContext()) != ResultSuccess) { return r; } - // CallInitializeSecurityContext updated `handshake_state_`. + // CallInitializeSecurityContext updated `handshake_state`. continue; case HandshakeState::ContinueNeeded: case HandshakeState::IncompleteMessage: @@ -96,20 +102,20 @@ public: (r = FillCiphertextReadBuf()) != ResultSuccess) { return r; } - if (ciphertext_read_buf_.empty()) { + if (ciphertext_read_buf.empty()) { LOG_ERROR(Service_SSL, "SSL handshake failed because server hung up"); return ResultInternalError; } if ((r = CallInitializeSecurityContext()) != ResultSuccess) { return r; } - // CallInitializeSecurityContext updated `handshake_state_`. + // CallInitializeSecurityContext updated `handshake_state`. continue; case HandshakeState::DoneAfterFlush: if ((r = FlushCiphertextWriteBuf()) != ResultSuccess) { return r; } - handshake_state_ = HandshakeState::Connected; + handshake_state = HandshakeState::Connected; return ResultSuccess; case HandshakeState::Connected: LOG_ERROR(Service_SSL, "Called DoHandshake but we already handshook"); @@ -121,24 +127,24 @@ public: } Result FillCiphertextReadBuf() { - const size_t fill_size = read_buf_fill_size_ ? read_buf_fill_size_ : 4096; - read_buf_fill_size_ = 0; + const size_t fill_size = read_buf_fill_size ? read_buf_fill_size : 4096; + read_buf_fill_size = 0; // This unnecessarily zeroes the buffer; oh well. - const size_t offset = ciphertext_read_buf_.size(); + const size_t offset = ciphertext_read_buf.size(); ASSERT_OR_EXECUTE(offset + fill_size >= offset, { return ResultInternalError; }); - ciphertext_read_buf_.resize(offset + fill_size, 0); - const auto read_span = std::span(ciphertext_read_buf_).subspan(offset, fill_size); - const auto [actual, err] = socket_->Recv(0, read_span); + ciphertext_read_buf.resize(offset + fill_size, 0); + const auto read_span = std::span(ciphertext_read_buf).subspan(offset, fill_size); + const auto [actual, err] = socket->Recv(0, read_span); switch (err) { case Network::Errno::SUCCESS: ASSERT(static_cast<size_t>(actual) <= fill_size); - ciphertext_read_buf_.resize(offset + actual); + ciphertext_read_buf.resize(offset + actual); return ResultSuccess; case Network::Errno::AGAIN: - ciphertext_read_buf_.resize(offset); + ciphertext_read_buf.resize(offset); return ResultWouldBlock; default: - ciphertext_read_buf_.resize(offset); + ciphertext_read_buf.resize(offset); LOG_ERROR(Service_SSL, "Socket recv returned Network::Errno {}", err); return ResultInternalError; } @@ -146,13 +152,13 @@ public: // Returns success if the write buffer has been completely emptied. Result FlushCiphertextWriteBuf() { - while (!ciphertext_write_buf_.empty()) { - const auto [actual, err] = socket_->Send(ciphertext_write_buf_, 0); + while (!ciphertext_write_buf.empty()) { + const auto [actual, err] = socket->Send(ciphertext_write_buf, 0); switch (err) { case Network::Errno::SUCCESS: - ASSERT(static_cast<size_t>(actual) <= ciphertext_write_buf_.size()); - ciphertext_write_buf_.erase(ciphertext_write_buf_.begin(), - ciphertext_write_buf_.begin() + actual); + ASSERT(static_cast<size_t>(actual) <= ciphertext_write_buf.size()); + ciphertext_write_buf.erase(ciphertext_write_buf.begin(), + ciphertext_write_buf.begin() + actual); break; case Network::Errno::AGAIN: return ResultWouldBlock; @@ -175,9 +181,9 @@ public: // only used if `initial_call_done` { // [0] - .cbBuffer = static_cast<unsigned long>(ciphertext_read_buf_.size()), + .cbBuffer = static_cast<unsigned long>(ciphertext_read_buf.size()), .BufferType = SECBUFFER_TOKEN, - .pvBuffer = ciphertext_read_buf_.data(), + .pvBuffer = ciphertext_read_buf.data(), }, { // [1] (will be replaced by SECBUFFER_MISSING when SEC_E_INCOMPLETE_MESSAGE is @@ -211,30 +217,30 @@ public: .pBuffers = output_buffers.data(), }; ASSERT_OR_EXECUTE_MSG( - input_buffers[0].cbBuffer == ciphertext_read_buf_.size(), + input_buffers[0].cbBuffer == ciphertext_read_buf.size(), { return ResultInternalError; }, "read buffer too large"); - bool initial_call_done = handshake_state_ != HandshakeState::Initial; + bool initial_call_done = handshake_state != HandshakeState::Initial; if (initial_call_done) { LOG_DEBUG(Service_SSL, "Passing {} bytes into InitializeSecurityContext", - ciphertext_read_buf_.size()); + ciphertext_read_buf.size()); } const SECURITY_STATUS ret = - InitializeSecurityContextA(&cred_handle, initial_call_done ? &ctxt_ : nullptr, + InitializeSecurityContextA(&cred_handle, initial_call_done ? &ctxt : nullptr, // Caller ensured we have set a hostname: - const_cast<char*>(hostname_.value().c_str()), req, + const_cast<char*>(hostname.value().c_str()), req, 0, // Reserved1 0, // TargetDataRep not used with Schannel initial_call_done ? &input_desc : nullptr, 0, // Reserved2 - initial_call_done ? nullptr : &ctxt_, &output_desc, &attr, + initial_call_done ? nullptr : &ctxt, &output_desc, &attr, nullptr); // ptsExpiry if (output_buffers[0].pvBuffer) { const std::span span(static_cast<u8*>(output_buffers[0].pvBuffer), output_buffers[0].cbBuffer); - ciphertext_write_buf_.insert(ciphertext_write_buf_.end(), span.begin(), span.end()); + ciphertext_write_buf.insert(ciphertext_write_buf.end(), span.begin(), span.end()); FreeContextBuffer(output_buffers[0].pvBuffer); } @@ -251,64 +257,64 @@ public: LOG_DEBUG(Service_SSL, "InitializeSecurityContext => SEC_I_CONTINUE_NEEDED"); if (input_buffers[1].BufferType == SECBUFFER_EXTRA) { LOG_DEBUG(Service_SSL, "EXTRA of size {}", input_buffers[1].cbBuffer); - ASSERT(input_buffers[1].cbBuffer <= ciphertext_read_buf_.size()); - ciphertext_read_buf_.erase(ciphertext_read_buf_.begin(), - ciphertext_read_buf_.end() - input_buffers[1].cbBuffer); + ASSERT(input_buffers[1].cbBuffer <= ciphertext_read_buf.size()); + ciphertext_read_buf.erase(ciphertext_read_buf.begin(), + ciphertext_read_buf.end() - input_buffers[1].cbBuffer); } else { ASSERT(input_buffers[1].BufferType == SECBUFFER_EMPTY); - ciphertext_read_buf_.clear(); + ciphertext_read_buf.clear(); } - handshake_state_ = HandshakeState::ContinueNeeded; + handshake_state = HandshakeState::ContinueNeeded; return ResultSuccess; case SEC_E_INCOMPLETE_MESSAGE: LOG_DEBUG(Service_SSL, "InitializeSecurityContext => SEC_E_INCOMPLETE_MESSAGE"); ASSERT(input_buffers[1].BufferType == SECBUFFER_MISSING); - read_buf_fill_size_ = input_buffers[1].cbBuffer; - handshake_state_ = HandshakeState::IncompleteMessage; + read_buf_fill_size = input_buffers[1].cbBuffer; + handshake_state = HandshakeState::IncompleteMessage; return ResultSuccess; case SEC_E_OK: LOG_DEBUG(Service_SSL, "InitializeSecurityContext => SEC_E_OK"); - ciphertext_read_buf_.clear(); - handshake_state_ = HandshakeState::DoneAfterFlush; + ciphertext_read_buf.clear(); + handshake_state = HandshakeState::DoneAfterFlush; return GrabStreamSizes(); default: LOG_ERROR(Service_SSL, "InitializeSecurityContext failed (probably certificate/protocol issue): {}", Common::NativeErrorToString(ret)); - handshake_state_ = HandshakeState::Error; + handshake_state = HandshakeState::Error; return ResultInternalError; } } Result GrabStreamSizes() { const SECURITY_STATUS ret = - QueryContextAttributes(&ctxt_, SECPKG_ATTR_STREAM_SIZES, &stream_sizes_); + QueryContextAttributes(&ctxt, SECPKG_ATTR_STREAM_SIZES, &stream_sizes); if (ret != SEC_E_OK) { LOG_ERROR(Service_SSL, "QueryContextAttributes(SECPKG_ATTR_STREAM_SIZES) failed: {}", Common::NativeErrorToString(ret)); - handshake_state_ = HandshakeState::Error; + handshake_state = HandshakeState::Error; return ResultInternalError; } return ResultSuccess; } ResultVal<size_t> Read(std::span<u8> data) override { - if (handshake_state_ != HandshakeState::Connected) { + if (handshake_state != HandshakeState::Connected) { LOG_ERROR(Service_SSL, "Called Read but we did not successfully handshake"); return ResultInternalError; } - if (data.size() == 0 || got_read_eof_) { + if (data.size() == 0 || got_read_eof) { return size_t(0); } while (1) { - if (!cleartext_read_buf_.empty()) { - const size_t read_size = std::min(cleartext_read_buf_.size(), data.size()); - std::memcpy(data.data(), cleartext_read_buf_.data(), read_size); - cleartext_read_buf_.erase(cleartext_read_buf_.begin(), - cleartext_read_buf_.begin() + read_size); + if (!cleartext_read_buf.empty()) { + const size_t read_size = std::min(cleartext_read_buf.size(), data.size()); + std::memcpy(data.data(), cleartext_read_buf.data(), read_size); + cleartext_read_buf.erase(cleartext_read_buf.begin(), + cleartext_read_buf.begin() + read_size); return read_size; } - if (!ciphertext_read_buf_.empty()) { + if (!ciphertext_read_buf.empty()) { SecBuffer empty{ .cbBuffer = 0, .BufferType = SECBUFFER_EMPTY, @@ -316,16 +322,16 @@ public: }; std::array<SecBuffer, 5> buffers{{ { - .cbBuffer = static_cast<unsigned long>(ciphertext_read_buf_.size()), + .cbBuffer = static_cast<unsigned long>(ciphertext_read_buf.size()), .BufferType = SECBUFFER_DATA, - .pvBuffer = ciphertext_read_buf_.data(), + .pvBuffer = ciphertext_read_buf.data(), }, empty, empty, empty, }}; ASSERT_OR_EXECUTE_MSG( - buffers[0].cbBuffer == ciphertext_read_buf_.size(), + buffers[0].cbBuffer == ciphertext_read_buf.size(), { return ResultInternalError; }, "read buffer too large"); SecBufferDesc desc{ .ulVersion = SECBUFFER_VERSION, @@ -333,7 +339,7 @@ public: .pBuffers = buffers.data(), }; SECURITY_STATUS ret = - DecryptMessage(&ctxt_, &desc, /*MessageSeqNo*/ 0, /*pfQOP*/ nullptr); + DecryptMessage(&ctxt, &desc, /*MessageSeqNo*/ 0, /*pfQOP*/ nullptr); switch (ret) { case SEC_E_OK: ASSERT_OR_EXECUTE(buffers[0].BufferType == SECBUFFER_STREAM_HEADER, @@ -342,24 +348,23 @@ public: { return ResultInternalError; }); ASSERT_OR_EXECUTE(buffers[2].BufferType == SECBUFFER_STREAM_TRAILER, { return ResultInternalError; }); - cleartext_read_buf_.assign(static_cast<u8*>(buffers[1].pvBuffer), - static_cast<u8*>(buffers[1].pvBuffer) + - buffers[1].cbBuffer); + cleartext_read_buf.assign(static_cast<u8*>(buffers[1].pvBuffer), + static_cast<u8*>(buffers[1].pvBuffer) + + buffers[1].cbBuffer); if (buffers[3].BufferType == SECBUFFER_EXTRA) { - ASSERT(buffers[3].cbBuffer <= ciphertext_read_buf_.size()); - ciphertext_read_buf_.erase(ciphertext_read_buf_.begin(), - ciphertext_read_buf_.end() - - buffers[3].cbBuffer); + ASSERT(buffers[3].cbBuffer <= ciphertext_read_buf.size()); + ciphertext_read_buf.erase(ciphertext_read_buf.begin(), + ciphertext_read_buf.end() - buffers[3].cbBuffer); } else { ASSERT(buffers[3].BufferType == SECBUFFER_EMPTY); - ciphertext_read_buf_.clear(); + ciphertext_read_buf.clear(); } continue; case SEC_E_INCOMPLETE_MESSAGE: break; case SEC_I_CONTEXT_EXPIRED: // Server hung up by sending close_notify. - got_read_eof_ = true; + got_read_eof = true; return size_t(0); default: LOG_ERROR(Service_SSL, "DecryptMessage failed: {}", @@ -371,43 +376,43 @@ public: if (r != ResultSuccess) { return r; } - if (ciphertext_read_buf_.empty()) { - got_read_eof_ = true; + if (ciphertext_read_buf.empty()) { + got_read_eof = true; return size_t(0); } } } ResultVal<size_t> Write(std::span<const u8> data) override { - if (handshake_state_ != HandshakeState::Connected) { + if (handshake_state != HandshakeState::Connected) { LOG_ERROR(Service_SSL, "Called Write but we did not successfully handshake"); return ResultInternalError; } if (data.size() == 0) { return size_t(0); } - data = data.subspan(0, std::min<size_t>(data.size(), stream_sizes_.cbMaximumMessage)); - if (!cleartext_write_buf_.empty()) { + data = data.subspan(0, std::min<size_t>(data.size(), stream_sizes.cbMaximumMessage)); + if (!cleartext_write_buf.empty()) { // Already in the middle of a write. It wouldn't make sense to not // finish sending the entire buffer since TLS has // header/MAC/padding/etc. - if (data.size() != cleartext_write_buf_.size() || - std::memcmp(data.data(), cleartext_write_buf_.data(), data.size())) { + if (data.size() != cleartext_write_buf.size() || + std::memcmp(data.data(), cleartext_write_buf.data(), data.size())) { LOG_ERROR(Service_SSL, "Called Write but buffer does not match previous buffer"); return ResultInternalError; } return WriteAlreadyEncryptedData(); } else { - cleartext_write_buf_.assign(data.begin(), data.end()); + cleartext_write_buf.assign(data.begin(), data.end()); } - std::vector<u8> header_buf(stream_sizes_.cbHeader, 0); - std::vector<u8> tmp_data_buf = cleartext_write_buf_; - std::vector<u8> trailer_buf(stream_sizes_.cbTrailer, 0); + std::vector<u8> header_buf(stream_sizes.cbHeader, 0); + std::vector<u8> tmp_data_buf = cleartext_write_buf; + std::vector<u8> trailer_buf(stream_sizes.cbTrailer, 0); std::array<SecBuffer, 3> buffers{{ { - .cbBuffer = stream_sizes_.cbHeader, + .cbBuffer = stream_sizes.cbHeader, .BufferType = SECBUFFER_STREAM_HEADER, .pvBuffer = header_buf.data(), }, @@ -417,7 +422,7 @@ public: .pvBuffer = tmp_data_buf.data(), }, { - .cbBuffer = stream_sizes_.cbTrailer, + .cbBuffer = stream_sizes.cbTrailer, .BufferType = SECBUFFER_STREAM_TRAILER, .pvBuffer = trailer_buf.data(), }, @@ -431,17 +436,17 @@ public: .pBuffers = buffers.data(), }; - const SECURITY_STATUS ret = EncryptMessage(&ctxt_, /*fQOP*/ 0, &desc, /*MessageSeqNo*/ 0); + const SECURITY_STATUS ret = EncryptMessage(&ctxt, /*fQOP*/ 0, &desc, /*MessageSeqNo*/ 0); if (ret != SEC_E_OK) { LOG_ERROR(Service_SSL, "EncryptMessage failed: {}", Common::NativeErrorToString(ret)); return ResultInternalError; } - ciphertext_write_buf_.insert(ciphertext_write_buf_.end(), header_buf.begin(), - header_buf.end()); - ciphertext_write_buf_.insert(ciphertext_write_buf_.end(), tmp_data_buf.begin(), - tmp_data_buf.end()); - ciphertext_write_buf_.insert(ciphertext_write_buf_.end(), trailer_buf.begin(), - trailer_buf.end()); + ciphertext_write_buf.insert(ciphertext_write_buf.end(), header_buf.begin(), + header_buf.end()); + ciphertext_write_buf.insert(ciphertext_write_buf.end(), tmp_data_buf.begin(), + tmp_data_buf.end()); + ciphertext_write_buf.insert(ciphertext_write_buf.end(), trailer_buf.begin(), + trailer_buf.end()); return WriteAlreadyEncryptedData(); } @@ -451,15 +456,15 @@ public: return r; } // write buf is empty - const size_t cleartext_bytes_written = cleartext_write_buf_.size(); - cleartext_write_buf_.clear(); + const size_t cleartext_bytes_written = cleartext_write_buf.size(); + cleartext_write_buf.clear(); return cleartext_bytes_written; } ResultVal<std::vector<std::vector<u8>>> GetServerCerts() override { PCCERT_CONTEXT returned_cert = nullptr; const SECURITY_STATUS ret = - QueryContextAttributes(&ctxt_, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &returned_cert); + QueryContextAttributes(&ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &returned_cert); if (ret != SEC_E_OK) { LOG_ERROR(Service_SSL, "QueryContextAttributes(SECPKG_ATTR_REMOTE_CERT_CONTEXT) failed: {}", @@ -480,8 +485,8 @@ public: } ~SSLConnectionBackendSchannel() { - if (handshake_state_ != HandshakeState::Initial) { - DeleteSecurityContext(&ctxt_); + if (handshake_state != HandshakeState::Initial) { + DeleteSecurityContext(&ctxt); } } @@ -509,21 +514,21 @@ public: // Another error was returned and we shouldn't allow initialization // to continue. Error, - } handshake_state_ = HandshakeState::Initial; + } handshake_state = HandshakeState::Initial; - CtxtHandle ctxt_; - SecPkgContext_StreamSizes stream_sizes_; + CtxtHandle ctxt; + SecPkgContext_StreamSizes stream_sizes; - std::shared_ptr<Network::SocketBase> socket_; - std::optional<std::string> hostname_; + std::shared_ptr<Network::SocketBase> socket; + std::optional<std::string> hostname; - std::vector<u8> ciphertext_read_buf_; - std::vector<u8> ciphertext_write_buf_; - std::vector<u8> cleartext_read_buf_; - std::vector<u8> cleartext_write_buf_; + std::vector<u8> ciphertext_read_buf; + std::vector<u8> ciphertext_write_buf; + std::vector<u8> cleartext_read_buf; + std::vector<u8> cleartext_write_buf; - bool got_read_eof_ = false; - size_t read_buf_fill_size_ = 0; + bool got_read_eof = false; + size_t read_buf_fill_size = 0; }; ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend() { |