[WebAuthN] Support CTAP HID authenticators on macOS
authorjiewen_tan@apple.com <jiewen_tan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 14 Nov 2018 06:54:32 +0000 (06:54 +0000)
committerjiewen_tan@apple.com <jiewen_tan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 14 Nov 2018 06:54:32 +0000 (06:54 +0000)
commit64bb2277bcc3f475c6d548d3048ab5c29a136381
tree9b2f95cf3ffaf45ba8a0c9ae15739e24eaabc1d1
parent2ed195503b9baf7a843e451e54a91cfda30afcfc
[WebAuthN] Support CTAP HID authenticators on macOS
https://bugs.webkit.org/show_bug.cgi?id=188623
<rdar://problem/43353777>

Reviewed by Brent Fulgham and Chris Dumez.

Source/WebCore:

This patch removes AuthenticatorCoordinatorClient::~AuthenticatorCoordinatorClient to ignore
any incompleted CompletionHandlers as calling them in destructors could cause unexpected cyclic
dependency. Also, it adds a hack to temporarily deal with nullable userhandle.

Tests: http/wpt/webauthn/ctap-hid-failure.https.html
       http/wpt/webauthn/ctap-hid-success.https.html
       http/wpt/webauthn/public-key-credential-create-failure-hid-silent.https.html
       http/wpt/webauthn/public-key-credential-create-failure-hid.https.html
       http/wpt/webauthn/public-key-credential-create-success-hid.https.html
       http/wpt/webauthn/public-key-credential-get-failure-hid-silent.https.html
       http/wpt/webauthn/public-key-credential-get-failure-hid.https.html
       http/wpt/webauthn/public-key-credential-get-success-hid.https.html

* Modules/webauthn/AuthenticatorCoordinatorClient.cpp:
(WebCore::AuthenticatorCoordinatorClient::~AuthenticatorCoordinatorClient): Deleted.
* Modules/webauthn/AuthenticatorCoordinatorClient.h:
* Modules/webauthn/PublicKeyCredentialCreationOptions.h:
* Modules/webauthn/fido/DeviceResponseConverter.cpp:
(fido::readCTAPGetAssertionResponse):
* Modules/webauthn/fido/FidoConstants.h:

Source/WebKit:

This patch introduces a primitive support of CTAP HID authenticators for WebAuthN in macOS.
It involves low level HID device management&communication, high level CTAP HID authenticator
management&communication, and mock testing. The above three aspects will be covered in details:
1) Low level HID device management&communication: HidService&HidConnection
It relies on IOHIDManager to discover appropriate hid devices by passing a matching dictionary:
{ PrimaryUsagePage: 0xf1d0, PrimaryUsage: 0x01}. For communication, it utilizes HID reports.
To send a report, it calls IOHIDDeviceSetReport since the async version is not implemented.
To recieve a report, it calls IOHIDDeviceRegisterInputReportCallback to asynchronously wait
for incoming reports.
Here is the corresponding reference:
https://developer.apple.com/library/archive/documentation/DeviceDrivers/Conceptual/HID/new_api_10_5/tn2187.html#//apple_ref/doc/uid/TP40000970-CH214-SW2
2) High level CTAP HID authenticator management&communication: HidService&CtapHidDriver
Whenever an appropriate hid device is discovered by IOHIDManager, an AuthenticatorGetInfo command
is sent to the device to determine properties of the authenticator, says, which version of protocol
it supports, i.e. CTAP or U2F. So far, we only support CTAP authenticators. Once the authenticator
is determined to support CTAP, we then instantiate CtapHidAuthenticator which will then take care
of even higher level WebAuthN requests&responses.
Binaries are constructed and packaged according to the CTAP HID porotocol. CtapHidDriver takes care
of concurrency and channels, i.e. allocating channel and establishing the actual request/response
transaction. At the meantime, CtapHidDriver::Worker is then responsible for each single transaction.
Here is the corresponding reference:
https://fidoalliance.org/specs/fido-v2.0-ps-20170927/fido-client-to-authenticator-protocol-v2.0-ps-20170927.html#usb.
3) Mock Testing: MockHidService & MockHidConnection
A CTAP hid authenticator is simulated within MockHidConnection with options of specifying specific
error scenarios and of course could take care of successful cases. Four stages are presented in the
simulated authenticator to reflect: a) allocating channel for AuthenticatorGetInfo, b) sending
AuthenticatorGetInfo, c) allocating channel for actual request, and d) sending the actual request.

Besides implementing the above, it also does a few other things:
1) Make AuthenticatorManager::clearState asynchronous to avoid cyclic dependency:
Authenticator::returnResponse => AuthenticatorManager::respondReceived => AuthenticatorManager::clearState
=> Authenticator::~Authenticator.
2) Reorganize unified build sources to make it clear that which files are .mm and which are .cpp.
3) Import LocalAuthentication.framework in LocalAuthenticationSoftLink instead of being scattered.

* Sources.txt:
* SourcesCocoa.txt:
* Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.h:
* UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
(WKWebsiteDataStoreSetWebAuthenticationMockConfiguration):
* UIProcess/WebAuthentication/AuthenticatorManager.cpp:
(WebKit::AuthenticatorManagerInternal::collectTransports):
(WebKit::AuthenticatorManager::clearStateAsync):
(WebKit::AuthenticatorManager::respondReceived):
(WebKit::AuthenticatorManager::initTimeOutTimer):
* UIProcess/WebAuthentication/AuthenticatorManager.h:
* UIProcess/WebAuthentication/AuthenticatorTransportService.cpp:
(WebKit::AuthenticatorTransportService::create):
(WebKit::AuthenticatorTransportService::createMock):
(WebKit::AuthenticatorTransportService::startDiscovery):
(WebKit::AuthenticatorTransportService::startDiscovery const): Deleted.
* UIProcess/WebAuthentication/AuthenticatorTransportService.h:
* UIProcess/WebAuthentication/Cocoa/HidConnection.h: Copied from Source/WebKit/UIProcess/WebAuthentication/AuthenticatorTransportService.h.
* UIProcess/WebAuthentication/Cocoa/HidConnection.mm: Added.
(WebKit::reportReceived):
(WebKit::HidConnection::HidConnection):
(WebKit::HidConnection::~HidConnection):
(WebKit::HidConnection::initialize):
(WebKit::HidConnection::terminate):
(WebKit::HidConnection::send):
(WebKit::HidConnection::registerDataReceivedCallback):
(WebKit::HidConnection::unregisterDataReceivedCallback):
(WebKit::HidConnection::receiveReport):
(WebKit::HidConnection::consumeReports):
(WebKit::HidConnection::registerDataReceivedCallbackInternal):
* UIProcess/WebAuthentication/Cocoa/HidService.h: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalService.h.
* UIProcess/WebAuthentication/Cocoa/HidService.mm: Added.
(WebKit::deviceAddedCallback):
(WebKit::deviceRemovedCallback):
(WebKit::HidService::HidService):
(WebKit::HidService::~HidService):
(WebKit::HidService::startDiscoveryInternal):
(WebKit::HidService::platformStartDiscovery):
(WebKit::HidService::createHidConnection const):
(WebKit::HidService::deviceAdded):
(WebKit::HidService::continueAddDeviceAfterGetInfo):
* UIProcess/WebAuthentication/Cocoa/LocalAuthenticationSoftLink.h:
* UIProcess/WebAuthentication/Cocoa/LocalConnection.mm:
* UIProcess/WebAuthentication/Cocoa/LocalService.h:
* UIProcess/WebAuthentication/Cocoa/LocalService.mm:
(WebKit::LocalService::startDiscoveryInternal):
(WebKit::LocalService::startDiscoveryInternal const): Deleted.
* UIProcess/WebAuthentication/Mock/MockAuthenticatorManager.cpp:
(WebKit::MockAuthenticatorManager::respondReceivedInternal):
* UIProcess/WebAuthentication/Mock/MockHidConnection.cpp: Added.
(WebKit::MockHidConnection::MockHidConnection):
(WebKit::MockHidConnection::initialize):
(WebKit::MockHidConnection::terminate):
(WebKit::MockHidConnection::send):
(WebKit::MockHidConnection::registerDataReceivedCallbackInternal):
(WebKit::MockHidConnection::assembleRequest):
(WebKit::MockHidConnection::parseRequest):
(WebKit::MockHidConnection::feedReports):
(WebKit::MockHidConnection::stagesMatch const):
(WebKit::MockHidConnection::shouldContinueFeedReports):
(WebKit::MockHidConnection::continueFeedReports):
* UIProcess/WebAuthentication/Mock/MockHidConnection.h: Copied from Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.h.
* UIProcess/WebAuthentication/Mock/MockHidService.cpp: Copied from Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalService.cpp.
(WebKit::MockHidService::MockHidService):
(WebKit::MockHidService::platformStartDiscovery):
(WebKit::MockHidService::createHidConnection const):
* UIProcess/WebAuthentication/Mock/MockHidService.h: Copied from Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.h.
* UIProcess/WebAuthentication/Mock/MockLocalConnection.h:
* UIProcess/WebAuthentication/Mock/MockLocalConnection.mm:
* UIProcess/WebAuthentication/Mock/MockLocalService.mm: Renamed from Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalService.cpp.
(WebKit::MockLocalService::MockLocalService):
(WebKit::MockLocalService::platformStartDiscovery const):
(WebKit::MockLocalService::createLocalConnection const):
* UIProcess/WebAuthentication/Mock/MockWebAuthenticationConfiguration.h:
* UIProcess/WebAuthentication/fido/CtapHidAuthenticator.cpp: Added.
(WebKit::CtapHidAuthenticator::CtapHidAuthenticator):
(WebKit::CtapHidAuthenticator::makeCredential):
(WebKit::CtapHidAuthenticator::continueMakeCredentialAfterResponseReceived const):
(WebKit::CtapHidAuthenticator::getAssertion):
(WebKit::CtapHidAuthenticator::continueGetAssertionAfterResponseReceived const):
* UIProcess/WebAuthentication/fido/CtapHidAuthenticator.h: Copied from Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalService.h.
* UIProcess/WebAuthentication/fido/CtapHidDriver.cpp: Added.
(WebKit::CtapHidDriver::Worker::Worker):
(WebKit::CtapHidDriver::Worker::~Worker):
(WebKit::CtapHidDriver::Worker::transact):
(WebKit::CtapHidDriver::Worker::write):
(WebKit::CtapHidDriver::Worker::read):
(WebKit::CtapHidDriver::Worker::returnMessage):
(WebKit::CtapHidDriver::CtapHidDriver):
(WebKit::CtapHidDriver::transact):
(WebKit::CtapHidDriver::continueAfterChannelAllocated):
(WebKit::CtapHidDriver::continueAfterResponseReceived):
(WebKit::CtapHidDriver::returnResponse):
* UIProcess/WebAuthentication/fido/CtapHidDriver.h: Added.
* UIProcess/mac/WebDataListSuggestionsDropdownMac.mm:
* WebProcess/WebPage/CoordinatedGraphics/ThreadedCoordinatedLayerTreeHost.h:
* WebKit.xcodeproj/project.pbxproj:

Tools:

This patch adds support for the mock testing and entitlements to allow minibrowser to talk
to hid devices.

* MiniBrowser/MiniBrowser.entitlements:
* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::setWebAuthenticationMockConfiguration):

LayoutTests:

* http/wpt/webauthn/ctap-hid-failure.https-expected.txt: Added.
* http/wpt/webauthn/ctap-hid-failure.https.html: Added.
* http/wpt/webauthn/ctap-hid-success.https-expected.txt: Added.
* http/wpt/webauthn/ctap-hid-success.https.html: Added.
* http/wpt/webauthn/public-key-credential-create-failure-hid-silent.https-expected.txt: Added.
* http/wpt/webauthn/public-key-credential-create-failure-hid-silent.https.html: Added.
* http/wpt/webauthn/public-key-credential-create-failure-hid.https-expected.txt: Added.
* http/wpt/webauthn/public-key-credential-create-failure-hid.https.html: Added.
* http/wpt/webauthn/public-key-credential-create-success-hid.https-expected.txt: Added.
* http/wpt/webauthn/public-key-credential-create-success-hid.https.html: Added.
* http/wpt/webauthn/public-key-credential-get-failure-hid-silent.https-expected.txt: Added.
* http/wpt/webauthn/public-key-credential-get-failure-hid-silent.https.html: Added.
* http/wpt/webauthn/public-key-credential-get-failure-hid.https-expected.txt: Added.
* http/wpt/webauthn/public-key-credential-get-failure-hid.https.html: Added.
* http/wpt/webauthn/public-key-credential-get-success-hid.https-expected.txt: Added.
* http/wpt/webauthn/public-key-credential-get-success-hid.https.html: Added.
* http/wpt/webauthn/resources/util.js:
* platform/ios-wk2/TestExpectations:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@238166 268f45cc-cd09-0410-ab3c-d52691b4dbfc
60 files changed:
LayoutTests/ChangeLog
LayoutTests/http/wpt/webauthn/ctap-hid-failure.https-expected.txt [new file with mode: 0644]
LayoutTests/http/wpt/webauthn/ctap-hid-failure.https.html [new file with mode: 0644]
LayoutTests/http/wpt/webauthn/ctap-hid-success.https-expected.txt [new file with mode: 0644]
LayoutTests/http/wpt/webauthn/ctap-hid-success.https.html [new file with mode: 0644]
LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-hid-silent.https-expected.txt [new file with mode: 0644]
LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-hid-silent.https.html [new file with mode: 0644]
LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-hid.https-expected.txt [new file with mode: 0644]
LayoutTests/http/wpt/webauthn/public-key-credential-create-failure-hid.https.html [new file with mode: 0644]
LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https-expected.txt [new file with mode: 0644]
LayoutTests/http/wpt/webauthn/public-key-credential-create-success-hid.https.html [new file with mode: 0644]
LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid-silent.https-expected.txt [new file with mode: 0644]
LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid-silent.https.html [new file with mode: 0644]
LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid.https-expected.txt [new file with mode: 0644]
LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid.https.html [new file with mode: 0644]
LayoutTests/http/wpt/webauthn/public-key-credential-get-success-hid.https-expected.txt [new file with mode: 0644]
LayoutTests/http/wpt/webauthn/public-key-credential-get-success-hid.https.html [new file with mode: 0644]
LayoutTests/http/wpt/webauthn/resources/util.js
LayoutTests/platform/ios-wk2/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/Modules/webauthn/AuthenticatorCoordinatorClient.cpp
Source/WebCore/Modules/webauthn/AuthenticatorCoordinatorClient.h
Source/WebCore/Modules/webauthn/PublicKeyCredentialCreationOptions.h
Source/WebCore/Modules/webauthn/fido/DeviceResponseConverter.cpp
Source/WebCore/Modules/webauthn/fido/FidoConstants.h
Source/WebKit/ChangeLog
Source/WebKit/Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.h
Source/WebKit/Sources.txt
Source/WebKit/SourcesCocoa.txt
Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp
Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp
Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h
Source/WebKit/UIProcess/WebAuthentication/AuthenticatorTransportService.cpp
Source/WebKit/UIProcess/WebAuthentication/AuthenticatorTransportService.h
Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidConnection.h [new file with mode: 0644]
Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidConnection.mm [new file with mode: 0644]
Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidService.h [new file with mode: 0644]
Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidService.mm [new file with mode: 0644]
Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalAuthenticationSoftLink.h
Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalConnection.mm
Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalService.h
Source/WebKit/UIProcess/WebAuthentication/Cocoa/LocalService.mm
Source/WebKit/UIProcess/WebAuthentication/Mock/MockAuthenticatorManager.cpp
Source/WebKit/UIProcess/WebAuthentication/Mock/MockHidConnection.cpp [new file with mode: 0644]
Source/WebKit/UIProcess/WebAuthentication/Mock/MockHidConnection.h [new file with mode: 0644]
Source/WebKit/UIProcess/WebAuthentication/Mock/MockHidService.cpp [new file with mode: 0644]
Source/WebKit/UIProcess/WebAuthentication/Mock/MockHidService.h [new file with mode: 0644]
Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalConnection.h
Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalService.mm [moved from Source/WebKit/UIProcess/WebAuthentication/Mock/MockLocalService.cpp with 95% similarity]
Source/WebKit/UIProcess/WebAuthentication/Mock/MockWebAuthenticationConfiguration.h
Source/WebKit/UIProcess/WebAuthentication/fido/CtapHidAuthenticator.cpp [new file with mode: 0644]
Source/WebKit/UIProcess/WebAuthentication/fido/CtapHidAuthenticator.h [new file with mode: 0644]
Source/WebKit/UIProcess/WebAuthentication/fido/CtapHidDriver.cpp [new file with mode: 0644]
Source/WebKit/UIProcess/WebAuthentication/fido/CtapHidDriver.h [new file with mode: 0644]
Source/WebKit/UIProcess/mac/WebDataListSuggestionsDropdownMac.mm
Source/WebKit/WebKit.xcodeproj/project.pbxproj
Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/ThreadedCoordinatedLayerTreeHost.h
Tools/ChangeLog
Tools/MiniBrowser/MiniBrowser.entitlements
Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp