From e508684bf73248d80780c08d6a9fa67e33d93767 Mon Sep 17 00:00:00 2001 From: Benjamin K Date: Thu, 8 Oct 2020 11:37:50 +0200 Subject: [PATCH] Add Apple Watch support to quick unlock * Allow using a paired Apple Watch to authenticate to the secrets store in addition to TouchID. * Closes #5337 --- src/touchid/TouchID.mm | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/src/touchid/TouchID.mm b/src/touchid/TouchID.mm index 3502761310..a2cefecfe7 100644 --- a/src/touchid/TouchID.mm +++ b/src/touchid/TouchID.mm @@ -94,10 +94,20 @@ inline QString hash(const QString& value) // prepare adding secure entry to the macOS KeyChain CFErrorRef error = NULL; - SecAccessControlRef sacObject = SecAccessControlCreateWithFlags(kCFAllocatorDefault, - kSecAttrAccessibleWhenUnlockedThisDeviceOnly, - kSecAccessControlTouchIDCurrentSet, // depr: kSecAccessControlBiometryCurrentSet, - &error); + SecAccessControlRef sacObject; + if (@available(macOS 10.15, *)) { + // kSecAccessControlWatch is only available for macOS 10.15 and later + sacObject = SecAccessControlCreateWithFlags(kCFAllocatorDefault, + kSecAttrAccessibleWhenUnlockedThisDeviceOnly, + kSecAccessControlOr | kSecAccessControlBiometryCurrentSet | kSecAccessControlWatch, + &error); + } else { + sacObject = SecAccessControlCreateWithFlags(kCFAllocatorDefault, + kSecAttrAccessibleWhenUnlockedThisDeviceOnly, + kSecAccessControlTouchIDCurrentSet, // depr: kSecAccessControlBiometryCurrentSet, + &error); + } + if (sacObject == NULL || error != NULL) { NSError* e = (__bridge NSError*) error; @@ -216,12 +226,21 @@ inline QString hash(const QString& value) bool TouchID::isAvailable() { // cache result - if (this->m_available != TOUCHID_UNDEFINED) + if (this->m_available != TOUCHID_UNDEFINED) { return (this->m_available == TOUCHID_AVAILABLE); + } @try { LAContext* context = [[LAContext alloc] init]; - bool canAuthenticate = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:nil]; + + LAPolicy policyCode; + if (@available(macOS 10.15, *)) { + policyCode = LAPolicyDeviceOwnerAuthenticationWithBiometricsOrWatch; + } else { + policyCode = LAPolicyDeviceOwnerAuthenticationWithBiometrics; + } + + bool canAuthenticate = [context canEvaluatePolicy:policyCode error:nil]; [context release]; this->m_available = canAuthenticate ? TOUCHID_AVAILABLE : TOUCHID_NOT_AVAILABLE; return canAuthenticate; @@ -253,7 +272,15 @@ inline QString hash(const QString& value) LAContext* context = [[LAContext alloc] init]; __block TouchIDResult result = kTouchIDResultNone; NSString* authMessage = msg.toNSString(); // autoreleased - [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics + + LAPolicy policyCode; + if (@available(macOS 10.15, *)) { + policyCode = LAPolicyDeviceOwnerAuthenticationWithBiometricsOrWatch; + } else { + policyCode = LAPolicyDeviceOwnerAuthenticationWithBiometrics; + } + + [context evaluatePolicy:policyCode localizedReason:authMessage reply:^(BOOL success, NSError* error) { Q_UNUSED(error); result = success ? kTouchIDResultAllowed : kTouchIDResultFailed;