Skip to content

Commit

Permalink
Properly handle Windows Hello errors
Browse files Browse the repository at this point in the history
The KeyCredentialManager::RequestCreateAsync call can fail because we can end up in a situation where Windows Hello is initially available but then becomes unavailable, such as during a remote desktop session. This commit prevents a crash by moving the call into the try-catch.

Fixes #7890

Also resets quick unlock if there is an unrecoverable error. This will not occur if the user merely canceled the Windows Hello dialog.
  • Loading branch information
Gibstick authored and droidmonkey committed Feb 14, 2023
1 parent b4be71d commit f05a863
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 14 deletions.
7 changes: 6 additions & 1 deletion src/gui/DatabaseOpenWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,12 @@ QSharedPointer<CompositeKey> DatabaseOpenWidget::buildDatabaseKey()
#ifdef Q_CC_MSVC
if (!getWindowsHello()->getKey(m_filename, keyData)) {
// Failed to retrieve Quick Unlock data
m_ui->messageWidget->showMessage(tr("Failed to authenticate with Windows Hello"), MessageWidget::Error);
auto error = getWindowsHello()->errorString();
if (!error.isEmpty()) {
m_ui->messageWidget->showMessage(tr("Failed to authenticate with Windows Hello: %1").arg(error),
MessageWidget::Error);
resetQuickUnlock();
}
return {};
}
#elif defined(Q_OS_MACOS)
Expand Down
28 changes: 15 additions & 13 deletions src/winhello/WindowsHello.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,22 +64,24 @@ namespace
array_view<uint8_t>(reinterpret_cast<uint8_t*>(challenge.data()), challenge.size()));

return AsyncTask::runAndWaitForFuture([&] {
// The first time this is used a key-pair will be generated using the common name
auto result =
KeyCredentialManager::RequestCreateAsync(s_winHelloKeyName, KeyCredentialCreationOption::FailIfExists)
.get();

if (result.Status() == KeyCredentialStatus::CredentialAlreadyExists) {
result = KeyCredentialManager::OpenAsync(s_winHelloKeyName).get();
} else if (result.Status() != KeyCredentialStatus::Success) {
error = QObject::tr("Failed to create Windows Hello credential.");
return false;
}

try {
// The first time this is used a key-pair will be generated using the common name
auto result = KeyCredentialManager::RequestCreateAsync(s_winHelloKeyName,
KeyCredentialCreationOption::FailIfExists)
.get();

if (result.Status() == KeyCredentialStatus::CredentialAlreadyExists) {
result = KeyCredentialManager::OpenAsync(s_winHelloKeyName).get();
} else if (result.Status() != KeyCredentialStatus::Success) {
error = QObject::tr("Failed to create Windows Hello credential.");
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.");
if (signature.Status() != KeyCredentialStatus::UserCanceled) {
error = QObject::tr("Failed to sign challenge using Windows Hello.");
}
return false;
}

Expand Down

0 comments on commit f05a863

Please sign in to comment.