[WebAuthN] Enable LocalAuthenticator for macOS
authorjiewen_tan@apple.com <jiewen_tan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 6 Aug 2019 19:54:43 +0000 (19:54 +0000)
committerjiewen_tan@apple.com <jiewen_tan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 6 Aug 2019 19:54:43 +0000 (19:54 +0000)
https://bugs.webkit.org/show_bug.cgi?id=182772
<rdar://problem/43347920>

Reviewed by Brent Fulgham.

Source/WebKit:

This patch enables LocalAuthenticator for macOS. The majority
of this patch is to tweak macOS keychain to use the modern one.

* Configurations/WebKit.xcconfig:
* Platform/spi/Cocoa/DeviceIdentitySPI.h:
* UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm:
(WebKit::LocalAuthenticatorInternal::toVector):
(WebKit::LocalAuthenticator::makeCredential):
(WebKit::LocalAuthenticator::continueMakeCredentialAfterUserConsented):
(WebKit::LocalAuthenticator::continueMakeCredentialAfterAttested):
(WebKit::LocalAuthenticator::getAssertion):
(WebKit::LocalAuthenticator::continueGetAssertionAfterUserConsented):
* UIProcess/WebAuthentication/Cocoa/LocalConnection.mm:
(WebKit::LocalConnection::getUserConsent const):
(WebKit::LocalConnection::getAttestation const):
* UIProcess/WebAuthentication/Cocoa/LocalService.mm:
(WebKit::LocalService::isAvailable):
* UIProcess/WebAuthentication/Mock/MockLocalConnection.mm:
(WebKit::MockLocalConnection::getAttestation const):
* config.h:

Source/WTF:

* wtf/Platform.h:
Adds HAVE_DEVICE_IDENTITY.
* wtf/spi/cocoa/SecuritySPI.h:
Adds a SPI for telling macOS keychain to use the modern one.

Tools:

Add an entitlement file to WebKitTestRunner such that it can access
the modern macOS keychain.

* WebKitTestRunner/Configurations/WebKitTestRunner.entitlements: Added.
* WebKitTestRunner/Configurations/WebKitTestRunner.xcconfig:
* WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj:
* WebKitTestRunner/cocoa/TestControllerCocoa.mm:
(WTR::TestController::addTestKeyToKeychain):
(WTR::TestController::cleanUpKeychain):
(WTR::TestController::keyExistsInKeychain):

LayoutTests:

Enable existing local authenticator tests for macOS. Since OpenSource bots
don't have the internal setting to include restricted entitlements, tests
will fail on OpenSource bots.

* platform/mac-wk2/TestExpectations:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@248308 268f45cc-cd09-0410-ab3c-d52691b4dbfc

17 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/mac-wk2/TestExpectations
Source/WTF/ChangeLog
Source/WTF/wtf/Platform.h
Source/WTF/wtf/spi/cocoa/SecuritySPI.h
Source/WebKit/ChangeLog
Source/WebKit/Configurations/WebKit.xcconfig
Source/WebKit/Platform/spi/Cocoa/DeviceIdentitySPI.h
Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm
Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalConnection.mm
Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalService.mm
Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.mm
Tools/ChangeLog
Tools/WebKitTestRunner/Configurations/WebKitTestRunner.entitlements [new file with mode: 0644]
Tools/WebKitTestRunner/Configurations/WebKitTestRunner.xcconfig
Tools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj
Tools/WebKitTestRunner/cocoa/TestControllerCocoa.mm

index 1e5f86e..dcbe1e3 100644 (file)
@@ -1,3 +1,17 @@
+2019-08-06  Jiewen Tan  <jiewen_tan@apple.com>
+
+        [WebAuthN] Enable LocalAuthenticator for macOS
+        https://bugs.webkit.org/show_bug.cgi?id=182772
+        <rdar://problem/43347920>
+
+        Reviewed by Brent Fulgham.
+
+        Enable existing local authenticator tests for macOS. Since OpenSource bots
+        don't have the internal setting to include restricted entitlements, tests
+        will fail on OpenSource bots.
+
+        * platform/mac-wk2/TestExpectations:
+
 2019-08-06  Chris Dumez  <cdumez@apple.com>
 
         Unreviewed, drop change to TestExpectations that landed accidentally with r248276.
index ad73cce..f336fea 100644 (file)
@@ -903,14 +903,14 @@ imported/w3c/web-platform-tests/payment-request/user-accepts-payment-request-alg
 
 webkit.org/b/189598 compositing/backing/backing-store-attachment-fill-forwards-animation.html [ Pass Failure ]
 
-# Skip local authenticator tests for mac now.
-http/wpt/webauthn/public-key-credential-create-failure-local.https.html [ Skip ]
-http/wpt/webauthn/public-key-credential-create-success-local.https.html [ Skip ]
-http/wpt/webauthn/public-key-credential-get-failure-local.https.html [ Skip ]
-http/wpt/webauthn/public-key-credential-get-success-local.https.html [ Skip ]
-# The following tests require PublicKeyCredential objects. We can only produce them via local authenticators now.
-http/wpt/credential-management/credentialscontainer-store-basics.https.html [ Skip ]
-http/wpt/webauthn/idl.https.html [ Skip ]
+# Local authenticator tests require restricted keychain entitlement, which cannot be signed with ad hoc signing.
+# Therefore, tests fail on OpenSource bots. They will be covered by Internal bots.
+http/wpt/webauthn/public-key-credential-create-failure-local.https.html [ Failure ]
+http/wpt/webauthn/public-key-credential-create-success-local.https.html [ Failure ]
+http/wpt/webauthn/public-key-credential-get-failure-local.https.html [ Failure ]
+http/wpt/webauthn/public-key-credential-get-success-local.https.html [ Failure ]
+http/wpt/credential-management/credentialscontainer-store-basics.https.html [ Failure ]
+http/wpt/webauthn/idl.https.html [ Failure ]
 
 webkit.org/b/183878 media/modern-media-controls/tracks-panel/tracks-panel-up-click-over-media-does-not-dimiss-media-controls-when-media-is-playing.html [ Pass Timeout ] 
 
index 0c097b9..7ea54ae 100644 (file)
@@ -1,3 +1,16 @@
+2019-08-06  Jiewen Tan  <jiewen_tan@apple.com>
+
+        [WebAuthN] Enable LocalAuthenticator for macOS
+        https://bugs.webkit.org/show_bug.cgi?id=182772
+        <rdar://problem/43347920>
+
+        Reviewed by Brent Fulgham.
+
+        * wtf/Platform.h:
+        Adds HAVE_DEVICE_IDENTITY.
+        * wtf/spi/cocoa/SecuritySPI.h:
+        Adds a SPI for telling macOS keychain to use the modern one.
+
 2019-08-06  Claudio Saavedra  <csaavedra@igalia.com>
 
         FileSystem: silent build warning
index 9836c29..37e8be7 100644 (file)
 #if (PLATFORM(IOS_FAMILY) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 130000) || (PLATFORM(WATCHOS) && __WATCH_OS_VERSION_MIN_REQUIRED >= 60000) || (PLATFORM(APPLETV) && __TV_OS_VERSION_MIN_REQUIRED >= 130000)
 #define USE_HIRAGINO_SANS_WORKAROUND 1
 #endif
+
+#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400) || (PLATFORM(IOS) && !PLATFORM(IOS_SIMULATOR))
+#define HAVE_DEVICE_IDENTITY 1
+#endif
index e3f6aee..77dc830 100644 (file)
@@ -30,6 +30,7 @@
 #include <Security/SecAccessControlPriv.h>
 #include <Security/SecCertificatePriv.h>
 #include <Security/SecIdentityPriv.h>
+#include <Security/SecItemPriv.h>
 #include <Security/SecKeyPriv.h>
 #include <Security/SecTask.h>
 #include <Security/SecTrustPriv.h>
@@ -62,10 +63,11 @@ OSStatus SecTrustedApplicationCreateFromPath(const char* path, SecTrustedApplica
 #endif
 
 SecSignatureHashAlgorithm SecCertificateGetSignatureHashAlgorithm(SecCertificateRef);
+extern const CFStringRef kSecAttrNoLegacy;
 
 WTF_EXTERN_C_END
 
-#endif
+#endif // USE(APPLE_INTERNAL_SDK)
 
 typedef struct __SecTask *SecTaskRef;
 typedef struct __SecTrust *SecTrustRef;
index b7640d7..abd2fbf 100644 (file)
@@ -1,3 +1,32 @@
+2019-08-06  Jiewen Tan  <jiewen_tan@apple.com>
+
+        [WebAuthN] Enable LocalAuthenticator for macOS
+        https://bugs.webkit.org/show_bug.cgi?id=182772
+        <rdar://problem/43347920>
+
+        Reviewed by Brent Fulgham.
+
+        This patch enables LocalAuthenticator for macOS. The majority
+        of this patch is to tweak macOS keychain to use the modern one.
+
+        * Configurations/WebKit.xcconfig:
+        * Platform/spi/Cocoa/DeviceIdentitySPI.h:
+        * UIProcess/WebAuthentication/Cocoa/LocalAuthenticator.mm:
+        (WebKit::LocalAuthenticatorInternal::toVector):
+        (WebKit::LocalAuthenticator::makeCredential):
+        (WebKit::LocalAuthenticator::continueMakeCredentialAfterUserConsented):
+        (WebKit::LocalAuthenticator::continueMakeCredentialAfterAttested):
+        (WebKit::LocalAuthenticator::getAssertion):
+        (WebKit::LocalAuthenticator::continueGetAssertionAfterUserConsented):
+        * UIProcess/WebAuthentication/Cocoa/LocalConnection.mm:
+        (WebKit::LocalConnection::getUserConsent const):
+        (WebKit::LocalConnection::getAttestation const):
+        * UIProcess/WebAuthentication/Cocoa/LocalService.mm:
+        (WebKit::LocalService::isAvailable):
+        * UIProcess/WebAuthentication/Mock/MockLocalConnection.mm:
+        (WebKit::MockLocalConnection::getAttestation const):
+        * config.h:
+
 2019-08-06  Jer Noble  <jer.noble@apple.com>
 
         Add test for behavior introduced in r248174
index e129762..20f3542 100644 (file)
@@ -172,8 +172,10 @@ WK_FRAMEWORK_HEADER_POSTPROCESSING_DISABLED[sdk=iphone*12.*] = YES;
 WK_RELOCATABLE_FRAMEWORK_LDFLAGS = $(WK_RELOCATABLE_FRAMEWORK_LDFLAGS_$(WK_RELOCATABLE_FRAMEWORKS)_$(WK_PLATFORM_NAME));
 WK_RELOCATABLE_FRAMEWORK_LDFLAGS_YES_macosx = -Wl,-not_for_dyld_shared_cache;
 
-WK_HAVE_DEVICE_IDENTITY = $(WK_HAVE_DEVICE_IDENTITY_$(PLATFORM_NAME));
+WK_HAVE_DEVICE_IDENTITY = $(WK_HAVE_DEVICE_IDENTITY_$(WK_PLATFORM_NAME));
 WK_HAVE_DEVICE_IDENTITY_iphoneos = YES;
+WK_HAVE_DEVICE_IDENTITY_macosx = $(WK_HAVE_DEVICE_IDENTITY$(WK_MACOS_1014));
+WK_HAVE_DEVICE_IDENTITY_MACOS_SINCE_1014 = YES;
 
 WK_HAVE_URL_FORMATTING = $(WK_HAVE_URL_FORMATTING_$(WK_PLATFORM_NAME));
 WK_HAVE_URL_FORMATTING_iphoneos = $(WK_HAVE_URL_FORMATTING$(WK_IOS_12));
index 03203e2..7477e40 100644 (file)
@@ -27,7 +27,7 @@
 
 #if ENABLE(WEB_AUTHN)
 
-#if PLATFORM(IOS_FAMILY) && !PLATFORM(IOS_FAMILY_SIMULATOR)
+#if HAVE(DEVICE_IDENTITY)
 
 #if USE(APPLE_INTERNAL_SDK)
 
@@ -54,6 +54,6 @@ void DeviceIdentityIssueClientCertificateWithCompletion(dispatch_queue_t _Nullab
 
 #endif // USE(APPLE_INTERNAL_SDK)
 
-#endif // PLATFORM(IOS_FAMILY) && !PLATFORM(IOS_FAMILY_SIMULATOR)
+#endif // HAVE(DEVICE_IDENTITY)
 
 #endif // ENABLE(WEB_AUTHN)
index 9c0314f..7d7a270 100644 (file)
@@ -41,6 +41,7 @@
 #import <wtf/RetainPtr.h>
 #import <wtf/RunLoop.h>
 #import <wtf/Vector.h>
+#import <wtf/spi/cocoa/SecuritySPI.h>
 #import <wtf/text/StringHash.h>
 
 namespace WebKit {
@@ -54,7 +55,6 @@ const uint8_t getAssertionFlags = 0b00000101; // UP and UV are set.
 // Credential ID is currently SHA-1 of the corresponding public key.
 const uint16_t credentialIdLength = 20;
 
-#if PLATFORM(IOS_FAMILY)
 static inline bool emptyTransportsOrContain(const Vector<AuthenticatorTransport>& transports, AuthenticatorTransport target)
 {
     return transports.isEmpty() ? true : transports.contains(target);
@@ -78,7 +78,6 @@ static inline Vector<uint8_t> toVector(NSData *data)
     result.append(reinterpret_cast<const uint8_t*>(data.bytes), data.length);
     return result;
 }
-#endif // !PLATFORM(IOS_FAMILY)
 
 } // LocalAuthenticatorInternal
 
@@ -89,12 +88,10 @@ LocalAuthenticator::LocalAuthenticator(UniqueRef<LocalConnection>&& connection)
 
 void LocalAuthenticator::makeCredential()
 {
-    // FIXME(182772)
     using namespace LocalAuthenticatorInternal;
     ASSERT(m_state == State::Init);
     m_state = State::RequestReceived;
 
-#if PLATFORM(IOS_FAMILY)
     // The following implements https://www.w3.org/TR/webauthn/#op-make-cred as of 5 December 2017.
     // Skip Step 4-5 as requireResidentKey and requireUserVerification are enforced.
     // Skip Step 9 as extensions are not supported yet.
@@ -122,6 +119,7 @@ void LocalAuthenticator::makeCredential()
             (id)kSecAttrLabel: requestData().creationOptions.rp.id,
             (id)kSecReturnAttributes: @YES,
             (id)kSecMatchLimit: (id)kSecMatchLimitAll,
+            (id)kSecAttrNoLegacy: @YES
         };
         CFTypeRef attributesArrayRef = nullptr;
         OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &attributesArrayRef);
@@ -152,18 +150,15 @@ void LocalAuthenticator::makeCredential()
         weakThis->continueMakeCredentialAfterUserConsented(consent);
     };
     m_connection->getUserConsent(
-        "Allow " + requestData().creationOptions.rp.id + " to create a public key credential for " + requestData().creationOptions.user.name,
+        "allow " + requestData().creationOptions.rp.id + " to create a public key credential for " + requestData().creationOptions.user.name,
         WTFMove(callback));
-#endif // !PLATFORM(IOS_FAMILY)
 }
 
 void LocalAuthenticator::continueMakeCredentialAfterUserConsented(LocalConnection::UserConsent consent)
 {
-    // FIXME(182772)
     ASSERT(m_state == State::RequestReceived);
     m_state = State::UserConsented;
 
-#if PLATFORM(IOS_FAMILY)
     if (consent == LocalConnection::UserConsent::No) {
         receiveRespond(ExceptionData { NotAllowedError, "Couldn't get user consent."_s });
         return;
@@ -176,6 +171,7 @@ void LocalAuthenticator::continueMakeCredentialAfterUserConsented(LocalConnectio
         (id)kSecClass: (id)kSecClassKey,
         (id)kSecAttrLabel: requestData().creationOptions.rp.id,
         (id)kSecAttrApplicationTag: [NSData dataWithBytes:requestData().creationOptions.user.idVector.data() length:requestData().creationOptions.user.idVector.size()],
+        (id)kSecAttrNoLegacy: @YES
     };
     OSStatus status = SecItemDelete((__bridge CFDictionaryRef)deleteQuery);
     if (status && status != errSecItemNotFound) {
@@ -192,18 +188,15 @@ void LocalAuthenticator::continueMakeCredentialAfterUserConsented(LocalConnectio
         weakThis->continueMakeCredentialAfterAttested(privateKey, certificates, error);
     };
     m_connection->getAttestation(requestData().creationOptions.rp.id, requestData().creationOptions.user.name, requestData().hash, WTFMove(callback));
-#endif // !PLATFORM(IOS_FAMILY)
 }
 
 void LocalAuthenticator::continueMakeCredentialAfterAttested(SecKeyRef privateKey, NSArray *certificates, NSError *error)
 {
-    // FIXME(182772)
     using namespace LocalAuthenticatorInternal;
 
     ASSERT(m_state == State::UserConsented);
     m_state = State::Attested;
 
-#if PLATFORM(IOS_FAMILY)
     if (error) {
         LOG_ERROR("Couldn't attest: %@", error);
         receiveRespond(ExceptionData { UnknownError, "Unknown internal error."_s });
@@ -227,13 +220,14 @@ void LocalAuthenticator::continueMakeCredentialAfterAttested(SecKeyRef privateKe
     // FIXME(183533): DeviceIdentity.Framework would insert certificates into Keychain as well. We should update those as well.
     Vector<uint8_t> credentialId;
     {
-        // -rk is added by DeviceIdentity.Framework.
-        String label = makeString(requestData().creationOptions.user.name, "@", requestData().creationOptions.rp.id, "-rk");
+        // -rk-ucrt is added by DeviceIdentity.Framework.
+        String label = makeString(requestData().creationOptions.user.name, "@", requestData().creationOptions.rp.id, "-rk-ucrt");
         NSDictionary *credentialIdQuery = @{
             (id)kSecClass: (id)kSecClassKey,
             (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate,
             (id)kSecAttrLabel: label,
-            (id)kSecReturnAttributes: @YES
+            (id)kSecReturnAttributes: @YES,
+            (id)kSecAttrNoLegacy: @YES
         };
         CFTypeRef attributesRef = nullptr;
         OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)credentialIdQuery, &attributesRef);
@@ -251,6 +245,7 @@ void LocalAuthenticator::continueMakeCredentialAfterAttested(SecKeyRef privateKe
             (id)kSecClass: (id)kSecClassKey,
             (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate,
             (id)kSecAttrApplicationLabel: nsAttributes[(id)kSecAttrApplicationLabel],
+            (id)kSecAttrNoLegacy: @YES
         };
         NSDictionary *updateParams = @{
             (id)kSecAttrLabel: requestData().creationOptions.rp.id,
@@ -327,17 +322,14 @@ void LocalAuthenticator::continueMakeCredentialAfterAttested(SecKeyRef privateKe
     auto attestationObject = buildAttestationObject(WTFMove(authData), "Apple", WTFMove(attestationStatementMap), requestData().creationOptions.attestation);
 
     receiveRespond(PublicKeyCredentialData { ArrayBuffer::create(credentialId.data(), credentialId.size()), true, nullptr, ArrayBuffer::create(attestationObject.data(), attestationObject.size()), nullptr, nullptr, nullptr, WTF::nullopt });
-#endif // !PLATFORM(IOS_FAMILY)
 }
 
 void LocalAuthenticator::getAssertion()
 {
-    // FIXME(182772)
     using namespace LocalAuthenticatorInternal;
     ASSERT(m_state == State::Init);
     m_state = State::RequestReceived;
 
-#if PLATFORM(IOS_FAMILY)
     // The following implements https://www.w3.org/TR/webauthn/#op-get-assertion as of 5 December 2017.
     // Skip Step 2 as requireUserVerification is enforced.
     // Skip Step 8 as extensions are not supported yet.
@@ -355,7 +347,8 @@ void LocalAuthenticator::getAssertion()
         (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate,
         (id)kSecAttrLabel: requestData().requestOptions.rpId,
         (id)kSecReturnAttributes: @YES,
-        (id)kSecMatchLimit: (id)kSecMatchLimitAll
+        (id)kSecMatchLimit: (id)kSecMatchLimitAll,
+        (id)kSecAttrNoLegacy: @YES
     };
     CFTypeRef attributesArrayRef = nullptr;
     OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &attributesArrayRef);
@@ -401,22 +394,19 @@ void LocalAuthenticator::getAssertion()
         weakThis->continueGetAssertionAfterUserConsented(consent, context, credentialId, userhandle);
     };
     NSData *idData = selectedCredentialAttributes[(id)kSecAttrApplicationTag];
-    StringView idStringView { static_cast<const LChar*>([idData bytes]), static_cast<unsigned>([idData length]) };
+    StringView idStringView { static_cast<const UChar*>([idData bytes]), static_cast<unsigned>([idData length]) };
     m_connection->getUserConsent(
-        makeString("Log into ", requestData().requestOptions.rpId, " with ", idStringView, '.'),
+        makeString("log into ", requestData().requestOptions.rpId, " with ", idStringView),
         (__bridge SecAccessControlRef)selectedCredentialAttributes[(id)kSecAttrAccessControl],
         WTFMove(callback));
-#endif // PLATFORM(IOS_FAMILY)
 }
 
 void LocalAuthenticator::continueGetAssertionAfterUserConsented(LocalConnection::UserConsent consent, LAContext *context, const Vector<uint8_t>& credentialId, const Vector<uint8_t>& userhandle)
 {
-    // FIXME(182772)
     using namespace LocalAuthenticatorInternal;
     ASSERT(m_state == State::RequestReceived);
     m_state = State::UserConsented;
 
-#if PLATFORM(IOS_FAMILY)
     if (consent == LocalConnection::UserConsent::No) {
         receiveRespond(ExceptionData { NotAllowedError, "Couldn't get user consent."_s });
         return;
@@ -437,6 +427,7 @@ void LocalAuthenticator::continueGetAssertionAfterUserConsented(LocalConnection:
             (id)kSecAttrApplicationLabel: [NSData dataWithBytes:credentialId.data() length:credentialId.size()],
             (id)kSecUseAuthenticationContext: context,
             (id)kSecReturnRef: @YES,
+            (id)kSecAttrNoLegacy: @YES
         };
         CFTypeRef privateKeyRef = nullptr;
         OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &privateKeyRef);
@@ -464,7 +455,6 @@ void LocalAuthenticator::continueGetAssertionAfterUserConsented(LocalConnection:
 
     // Step 13.
     receiveRespond(PublicKeyCredentialData { ArrayBuffer::create(credentialId.data(), credentialId.size()), false, nullptr, nullptr, ArrayBuffer::create(authData.data(), authData.size()), ArrayBuffer::create(signature.data(), signature.size()), ArrayBuffer::create(userhandle.data(), userhandle.size()), WTF::nullopt });
-#endif // !PLATFORM(IOS_FAMILY)
 }
 
 } // namespace WebKit
index 7aad4c6..5c2c9a3 100644 (file)
@@ -39,8 +39,6 @@ namespace WebKit {
 
 void LocalConnection::getUserConsent(const String& reason, UserConsentCallback&& completionHandler) const
 {
-    // FIXME(182772)
-#if PLATFORM(IOS_FAMILY)
     auto context = adoptNS([allocLAContextInstance() init]);
     auto reply = makeBlockPtr([completionHandler = WTFMove(completionHandler)] (BOOL success, NSError *error) mutable {
         ASSERT(!RunLoop::isMain());
@@ -55,13 +53,10 @@ void LocalConnection::getUserConsent(const String& reason, UserConsentCallback&&
         });
     });
     [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:reason reply:reply.get()];
-#endif
 }
 
 void LocalConnection::getUserConsent(const String& reason, SecAccessControlRef accessControl, UserConsentContextCallback&& completionHandler) const
 {
-    // FIXME(182772)
-#if PLATFORM(IOS_FAMILY)
     auto context = adoptNS([allocLAContextInstance() init]);
     auto reply = makeBlockPtr([context, completionHandler = WTFMove(completionHandler)] (BOOL success, NSError *error) mutable {
         ASSERT(!RunLoop::isMain());
@@ -76,13 +71,11 @@ void LocalConnection::getUserConsent(const String& reason, SecAccessControlRef a
         });
     });
     [context evaluateAccessControl:accessControl operation:LAAccessControlOperationUseKeySign localizedReason:reason reply:reply.get()];
-#endif
 }
 
 void LocalConnection::getAttestation(const String& rpId, const String& username, const Vector<uint8_t>& hash, AttestationCallback&& completionHandler) const
 {
-    // DeviceIdentity.Framework is not avaliable in iOS simulator.
-#if PLATFORM(IOS_FAMILY) && !PLATFORM(IOS_FAMILY_SIMULATOR)
+#if HAVE(DEVICE_IDENTITY)
     // Apple Attestation
     ASSERT(hash.size() <= 32);
 
@@ -114,7 +107,7 @@ void LocalConnection::getAttestation(const String& rpId, const String& username,
 
     // FIXME(183652): Reduce prompt for biometrics
     DeviceIdentityIssueClientCertificateWithCompletion(dispatch_get_main_queue(), options, makeBlockPtr(WTFMove(completionHandler)).get());
-#endif
+#endif // HAVE(DEVICE_IDENTITY)
 }
 
 } // namespace WebKit
index f40696c..3249b0e 100644 (file)
@@ -41,12 +41,10 @@ LocalService::LocalService(Observer& observer)
 {
 }
 
+// FIXME(rdar://problem/51048542)
 bool LocalService::isAvailable()
 {
-// FIXME(182772)
-#if !PLATFORM(IOS_FAMILY)
-    return false;
-#else
+    // FIXME(198176)
     if (!WebCore::RuntimeEnabledFeatures::sharedFeatures().webAuthenticationLocalAuthenticatorEnabled())
         return false;
 
@@ -57,7 +55,6 @@ bool LocalService::isAvailable()
         return false;
     }
     return true;
-#endif
 }
 
 void LocalService::startDiscoveryInternal()
index ca765e5..86e0790 100644 (file)
@@ -92,7 +92,7 @@ void MockLocalConnection::getAttestation(const String& rpId, const String& usern
         ASSERT(!errorRef);
 
         // Mock what DeviceIdentity would do.
-        String label = makeString(username, "@", rpId, "-rk");
+        String label = makeString(username, "@", rpId, "-rk-ucrt");
         NSDictionary* addQuery = @{
             (id)kSecValueRef: (id)key.get(),
             (id)kSecClass: (id)kSecClassKey,
index 474929b..9443f2f 100644 (file)
@@ -1,3 +1,22 @@
+2019-08-06  Jiewen Tan  <jiewen_tan@apple.com>
+
+        [WebAuthN] Enable LocalAuthenticator for macOS
+        https://bugs.webkit.org/show_bug.cgi?id=182772
+        <rdar://problem/43347920>
+
+        Reviewed by Brent Fulgham.
+
+        Add an entitlement file to WebKitTestRunner such that it can access
+        the modern macOS keychain.
+
+        * WebKitTestRunner/Configurations/WebKitTestRunner.entitlements: Added.
+        * WebKitTestRunner/Configurations/WebKitTestRunner.xcconfig:
+        * WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj:
+        * WebKitTestRunner/cocoa/TestControllerCocoa.mm:
+        (WTR::TestController::addTestKeyToKeychain):
+        (WTR::TestController::cleanUpKeychain):
+        (WTR::TestController::keyExistsInKeychain):
+
 2019-08-06  Zhifei Fang  <zhifei_fang@apple.com>
 
         [results.webkit.org Timeline] Performance improvements
diff --git a/Tools/WebKitTestRunner/Configurations/WebKitTestRunner.entitlements b/Tools/WebKitTestRunner/Configurations/WebKitTestRunner.entitlements
new file mode 100644 (file)
index 0000000..1fb4827
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+    <dict>
+        <key>keychain-access-groups</key>
+        <array>
+            <string>com.apple.WebKitTestRunner</string>
+        </array>
+    </dict>
+</plist>
index 4e51923..fa62eb4 100644 (file)
@@ -34,3 +34,8 @@ STRIP_STYLE = debugging;
 SKIP_INSTALL[sdk=iphone*] = YES;
 EXCLUDED_SOURCE_FILE_NAMES[sdk=iphone*] = mac/*;
 INCLUDED_SOURCE_FILE_NAMES[sdk=iphone*] = mac/main.mm;
+
+CODE_SIGN_ENTITLEMENTS[sdk=macosx*] = Configurations/WebKitTestRunner.entitlements;
+
+CODE_SIGN_IDENTITY[sdk=macosx*] = $(CODE_SIGN_IDENTITY_$(USE_INTERNAL_SDK));
+CODE_SIGN_IDENTITY_YES = $(WK_ENGINEERING_CODE_SIGN_IDENTITY);
index 143ddb2..1643d40 100644 (file)
                5641E2D014335E95008307E5 /* JSTextInputController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5641E2CE14335E95008307E5 /* JSTextInputController.cpp */; };
                5664A49A14326384008881BE /* TextInputController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5664A49814326384008881BE /* TextInputController.cpp */; };
                5670B8281386FCA5002EB355 /* EventSenderProxy.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5670B8271386FCA5002EB355 /* EventSenderProxy.mm */; };
-               570E75A82152DB4F00324B6E /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 570E75A42152DA2C00324B6E /* Security.framework */; };
+               57A0062E22976EEB00AD08BD /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 570E75A42152DA2C00324B6E /* Security.framework */; };
+               57A0062F22976EF800AD08BD /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 570E75A42152DA2C00324B6E /* Security.framework */; };
                6510A78211EC643800410867 /* AHEM____.TTF in Resources */ = {isa = PBXBuildFile; fileRef = 6510A77711EC643800410867 /* AHEM____.TTF */; };
                6510A78411EC643800410867 /* WebKitWeightWatcher100.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6510A77911EC643800410867 /* WebKitWeightWatcher100.ttf */; };
                6510A78511EC643800410867 /* WebKitWeightWatcher200.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 6510A77A11EC643800410867 /* WebKitWeightWatcher200.ttf */; };
                5670B8261386FC13002EB355 /* EventSenderProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventSenderProxy.h; sourceTree = "<group>"; };
                5670B8271386FCA5002EB355 /* EventSenderProxy.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = EventSenderProxy.mm; sourceTree = "<group>"; };
                570E75A42152DA2C00324B6E /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
+               57A0062C22976E4D00AD08BD /* WebKitTestRunner.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = WebKitTestRunner.entitlements; sourceTree = "<group>"; };
                583913D014335E95008307E5 /* JSAccessibilityController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSAccessibilityController.cpp; sourceTree = "<group>"; };
                583913D114335E95008307E5 /* JSAccessibilityController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSAccessibilityController.h; sourceTree = "<group>"; };
                6510A77711EC643800410867 /* AHEM____.TTF */ = {isa = PBXFileReference; lastKnownFileType = file; name = "AHEM____.TTF"; path = "fonts/AHEM____.TTF"; sourceTree = "<group>"; };
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
-                               570E75A82152DB4F00324B6E /* Security.framework in Frameworks */,
+                               57A0062F22976EF800AD08BD /* Security.framework in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        buildActionMask = 2147483647;
                        files = (
                                51058AD51D678820009A538C /* libWebCoreTestSupport.dylib in Frameworks */,
+                               57A0062E22976EEB00AD08BD /* Security.framework in Frameworks */,
                                51058AD61D678825009A538C /* WebKit.framework in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                                BC793427118F7DAF005EA8E2 /* DebugRelease.xcconfig */,
                                BC25197111D15E61002EBC01 /* InjectedBundle.xcconfig */,
                                A1B89B94221E026B00EB4CEA /* SDKVariant.xcconfig */,
+                               57A0062C22976E4D00AD08BD /* WebKitTestRunner.entitlements */,
                                A18510381B9ADF2200744AEB /* WebKitTestRunner.xcconfig */,
                                9B0D132E2036D346008FC8FB /* WebKitTestRunnerApp-iOS.entitlements */,
                                311183AA212B1AC70077BCE0 /* WebKitTestRunnerApp-watchOS.entitlements */,
index fd28758..aaa38b1 100644 (file)
@@ -51,6 +51,7 @@
 #import <WebKit/_WKUserContentExtensionStore.h>
 #import <WebKit/_WKUserContentExtensionStorePrivate.h>
 #import <wtf/MainThread.h>
+#import <wtf/spi/cocoa/SecuritySPI.h>
 
 namespace WTR {
 
@@ -329,8 +330,6 @@ void TestController::injectUserScript(WKStringRef script)
 
 void TestController::addTestKeyToKeychain(const String& privateKeyBase64, const String& attrLabel, const String& applicationTagBase64)
 {
-    // FIXME(182772)
-#if PLATFORM(IOS_FAMILY)
     NSDictionary* options = @{
         (id)kSecAttrKeyType: (id)kSecAttrKeyTypeECSECPrimeRandom,
         (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate,
@@ -348,40 +347,36 @@ void TestController::addTestKeyToKeychain(const String& privateKeyBase64, const
         (id)kSecValueRef: (id)key.get(),
         (id)kSecClass: (id)kSecClassKey,
         (id)kSecAttrLabel: attrLabel,
-        (id)kSecAttrApplicationTag: adoptNS([[NSData alloc] initWithBase64EncodedString:applicationTagBase64 options:NSDataBase64DecodingIgnoreUnknownCharacters]).get()
+        (id)kSecAttrApplicationTag: adoptNS([[NSData alloc] initWithBase64EncodedString:applicationTagBase64 options:NSDataBase64DecodingIgnoreUnknownCharacters]).get(),
+        (id)kSecAttrNoLegacy: @YES
     };
     OSStatus status = SecItemAdd((__bridge CFDictionaryRef)addQuery, NULL);
     ASSERT_UNUSED(status, !status);
-#endif
 }
 
 void TestController::cleanUpKeychain(const String& attrLabel)
 {
-    // FIXME(182772)
-#if PLATFORM(IOS_FAMILY)
     NSDictionary* deleteQuery = @{
         (id)kSecClass: (id)kSecClassKey,
-        (id)kSecAttrLabel: attrLabel
+        (id)kSecAttrLabel: attrLabel,
+        (id)kSecAttrNoLegacy: @YES
     };
     SecItemDelete((__bridge CFDictionaryRef)deleteQuery);
-#endif
 }
 
 bool TestController::keyExistsInKeychain(const String& attrLabel, const String& applicationTagBase64)
 {
-    // FIXME(182772)
-#if PLATFORM(IOS_FAMILY)
     NSDictionary *query = @{
         (id)kSecClass: (id)kSecClassKey,
         (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate,
         (id)kSecAttrLabel: attrLabel,
         (id)kSecAttrApplicationTag: adoptNS([[NSData alloc] initWithBase64EncodedString:applicationTagBase64 options:NSDataBase64DecodingIgnoreUnknownCharacters]).get(),
+        (id)kSecAttrNoLegacy: @YES
     };
     OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, NULL);
     if (!status)
         return true;
     ASSERT(status == errSecItemNotFound);
-#endif
     return false;
 }