From ed693e146d9bac64cdae1e50d76f7e13ab03b1f6 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Thu, 11 Aug 2022 21:59:12 -0400 Subject: [PATCH] Fix Windows Hello bugs * Fix #7977 - wrap key signing request in try/catch block to prevent crashes on some machines. * Fix #8120 - try 3 times to bring Windows Hello prompt to front. This may be necessary on older machines that are slow to bring up the prompt window. Also remove defunct code on macOS to prevent window focus issues. --- src/gui/Application.cpp | 6 ------ src/winhello/WindowsHello.cpp | 30 ++++++++++++++++++++---------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/gui/Application.cpp b/src/gui/Application.cpp index 7f3aa848..cfe29cf9 100644 --- a/src/gui/Application.cpp +++ b/src/gui/Application.cpp @@ -209,12 +209,6 @@ bool Application::event(QEvent* event) emit openFile(static_cast(event)->file()); return true; } -#ifdef Q_OS_MACOS - // restore main window when clicking on the docker icon - else if (event->type() == QEvent::ApplicationActivate) { - emit applicationActivated(); - } -#endif return QApplication::event(event); } diff --git a/src/winhello/WindowsHello.cpp b/src/winhello/WindowsHello.cpp index 7095c72e..99e798c5 100644 --- a/src/winhello/WindowsHello.cpp +++ b/src/winhello/WindowsHello.cpp @@ -41,6 +41,7 @@ using namespace Windows::Storage::Streams; namespace { const std::wstring s_winHelloKeyName{L"keepassxc_winhello"}; + int g_promptFocusCount = 0; void queueSecurityPromptFocus(int delay = 500) { @@ -48,7 +49,11 @@ namespace auto hWnd = ::FindWindowA("Credential Dialog Xaml Host", nullptr); if (hWnd) { ::SetForegroundWindow(hWnd); + } else if (++g_promptFocusCount <= 3) { + queueSecurityPromptFocus(); + return; } + g_promptFocusCount = 0; }); } @@ -71,18 +76,23 @@ namespace return false; } - const auto signature = result.Credential().RequestSignAsync(challengeBuffer).get(); - if (signature.Status() != KeyCredentialStatus::Success) { - error = QObject::tr("Failed to sign challenge using Windows Hello."); + try { + const auto signature = result.Credential().RequestSignAsync(challengeBuffer).get(); + if (signature.Status() != KeyCredentialStatus::Success) { + error = QObject::tr("Failed to sign challenge using Windows Hello."); + return false; + } + + // Use the SHA-256 hash of the challenge signature as the encryption key + const auto response = signature.Result(); + CryptoHash hasher(CryptoHash::Sha256); + hasher.addData({reinterpret_cast(response.data()), static_cast(response.Length())}); + key = hasher.result(); + return true; + } catch (winrt::hresult_error const& ex) { + error = QString::fromStdString(winrt::to_string(ex.message())); return false; } - - // Use the SHA-256 hash of the challenge signature as the encryption key - const auto response = signature.Result(); - CryptoHash hasher(CryptoHash::Sha256); - hasher.addData({reinterpret_cast(response.data()), static_cast(response.Length())}); - key = hasher.result(); - return true; }); } } // namespace