Add support for Windows Hello

* Special thanks to @HexF and @smlu for their contributions towards this feature.

* Add MVP support for Windows Hello as a Quick Unlock solution using the WinRT API. This works by signing a random challenge vector with the Windows Hello protected key store (typically from TPM). The signed challenge is hashed using SHA-256 and then used as the encryption key to encrypt the database credentials. Credentials are encrypted using AES-256/GCM. This ensures the database password can only be decrypted following a successful authentication with Windows Hello in the future.

* Unify Touch ID and Windows Hello behavior under the Quick Unlock branding. Remove all timeout features of Touch ID as they are unnecessary and complicate the feature for no security gain.

* Quick Unlock is automatically reset only when the database key is changed vice whenever database settings are modified.

* Don't set database unlock dialog as always on top. This allows Touch ID and Windows Hello prompts to appear above the dialog properly.

* Prevent quick unlock when using AutoOpen or opening from the command line.
This commit is contained in:
Jonathan White 2022-02-21 20:40:01 -05:00
parent a76daeb4c5
commit 4f0710350f
33 changed files with 1058 additions and 734 deletions

View file

@ -36,13 +36,14 @@
class AdaptiveIconEngine : public QIconEngine
{
public:
explicit AdaptiveIconEngine(QIcon baseIcon);
explicit AdaptiveIconEngine(QIcon baseIcon, QColor overrideColor = {});
void paint(QPainter* painter, const QRect& rect, QIcon::Mode mode, QIcon::State state) override;
QPixmap pixmap(const QSize& size, QIcon::Mode mode, QIcon::State state) override;
QIconEngine* clone() const override;
private:
QIcon m_baseIcon;
QColor m_overrideColor;
};
Icons* Icons::m_instance(nullptr);
@ -113,9 +114,10 @@ QIcon Icons::trayIconUnlocked()
return trayIcon("unlocked");
}
AdaptiveIconEngine::AdaptiveIconEngine(QIcon baseIcon)
AdaptiveIconEngine::AdaptiveIconEngine(QIcon baseIcon, QColor overrideColor)
: QIconEngine()
, m_baseIcon(std::move(baseIcon))
, m_overrideColor(overrideColor)
{
}
@ -133,7 +135,10 @@ void AdaptiveIconEngine::paint(QPainter* painter, const QRect& rect, QIcon::Mode
m_baseIcon.paint(&p, img.rect(), Qt::AlignCenter, mode, state);
if (getMainWindow()) {
if (m_overrideColor.isValid()) {
p.setCompositionMode(QPainter::CompositionMode_SourceIn);
p.fillRect(img.rect(), m_overrideColor);
} else if (getMainWindow()) {
QPalette palette = getMainWindow()->palette();
p.setCompositionMode(QPainter::CompositionMode_SourceIn);
@ -188,7 +193,7 @@ QIcon Icons::icon(const QString& name, bool recolor, const QColor& overrideColor
icon = QIcon::fromTheme(name);
if (recolor) {
icon = QIcon(new AdaptiveIconEngine(icon));
icon = QIcon(new AdaptiveIconEngine(icon, overrideColor));
#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
icon.setIsMask(true);
#endif