Diff
Modified: trunk/LayoutTests/ChangeLog (245499 => 245500)
--- trunk/LayoutTests/ChangeLog 2019-05-18 07:12:17 UTC (rev 245499)
+++ trunk/LayoutTests/ChangeLog 2019-05-19 00:42:16 UTC (rev 245500)
@@ -1,3 +1,19 @@
+2019-05-18 Jiewen Tan <[email protected]>
+
+ [WebAuthN] Allow authenticators that support both CTAP and U2F to try U2F if CTAP fails in authenticatorGetAssertion
+ https://bugs.webkit.org/show_bug.cgi?id=197974
+ <rdar://problem/50879746>
+
+ Reviewed by Brent Fulgham.
+
+ * http/wpt/webauthn/public-key-credential-get-failure-hid-silent.https-expected.txt:
+ * http/wpt/webauthn/public-key-credential-get-failure-hid-silent.https.html:
+ * http/wpt/webauthn/public-key-credential-get-failure-hid.https-expected.txt:
+ * http/wpt/webauthn/public-key-credential-get-failure-hid.https.html:
+ * http/wpt/webauthn/public-key-credential-get-success-u2f.https-expected.txt:
+ * http/wpt/webauthn/public-key-credential-get-success-u2f.https.html:
+ * http/wpt/webauthn/resources/util.js:
+
2019-05-17 Joonghun Park <[email protected]>
Implement CSS `display: flow-root` (modern clearfix)
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid-silent.https-expected.txt (245499 => 245500)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid-silent.https-expected.txt 2019-05-18 07:12:17 UTC (rev 245499)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid-silent.https-expected.txt 2019-05-19 00:42:16 UTC (rev 245500)
@@ -1,4 +1,7 @@
PASS PublicKeyCredential's [[get]] with malicious payload in a mock hid authenticator.
PASS PublicKeyCredential's [[get]] with unsupported options in a mock hid authenticator.
+PASS PublicKeyCredential's [[get]] with invalid credential in a mock hid authenticator.
+PASS PublicKeyCredential's [[get]] with authenticator downgrade in a mock hid authenticator.
+PASS PublicKeyCredential's [[get]] with authenticator downgrade in a mock hid authenticator. 2
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid-silent.https.html (245499 => 245500)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid-silent.https.html 2019-05-18 07:12:17 UTC (rev 245499)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid-silent.https.html 2019-05-19 00:42:16 UTC (rev 245500)
@@ -30,4 +30,44 @@
testRunner.setWebAuthenticationMockConfiguration({ silentFailure: true, hid: { stage: "request", subStage: "msg", error: "unsupported-options" } });
return promiseRejects(t, "NotAllowedError", navigator.credentials.get(options), "Operation timed out.");
}, "PublicKeyCredential's [[get]] with unsupported options in a mock hid authenticator.");
+
+ promise_test(function(t) {
+ const options = {
+ publicKey: {
+ challenge: asciiToUint8Array("123456"),
+ timeout: 10
+ }
+ };
+
+ if (window.testRunner)
+ testRunner.setWebAuthenticationMockConfiguration({ silentFailure: true, hid: { stage: "request", subStage: "msg", error: "malicious-payload", payloadBase64: [testCtapErrInvalidCredentialResponseBase64] } });
+ return promiseRejects(t, "NotAllowedError", navigator.credentials.get(options), "Operation timed out.");
+ }, "PublicKeyCredential's [[get]] with invalid credential in a mock hid authenticator.");
+
+ promise_test(function(t) {
+ const options = {
+ publicKey: {
+ challenge: asciiToUint8Array("123456"),
+ timeout: 10
+ }
+ };
+
+ if (window.testRunner)
+ testRunner.setWebAuthenticationMockConfiguration({ silentFailure: true, hid: { stage: "request", subStage: "msg", error: "malicious-payload", canDowngrade: true, payloadBase64: [testCtapErrInvalidCredentialResponseBase64] } });
+ return promiseRejects(t, "NotAllowedError", navigator.credentials.get(options), "Operation timed out.");
+ }, "PublicKeyCredential's [[get]] with authenticator downgrade in a mock hid authenticator.");
+
+ promise_test(function(t) {
+ const options = {
+ publicKey: {
+ challenge: asciiToUint8Array("123456"),
+ extensions: { appid: "" },
+ timeout: 10
+ }
+ };
+
+ if (window.testRunner)
+ testRunner.setWebAuthenticationMockConfiguration({ silentFailure: true, hid: { stage: "request", subStage: "msg", error: "malicious-payload", canDowngrade: true, payloadBase64: [testCtapErrInvalidCredentialResponseBase64] } });
+ return promiseRejects(t, "NotAllowedError", navigator.credentials.get(options), "Operation timed out.");
+ }, "PublicKeyCredential's [[get]] with authenticator downgrade in a mock hid authenticator. 2");
</script>
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid.https-expected.txt (245499 => 245500)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid.https-expected.txt 2019-05-18 07:12:17 UTC (rev 245499)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid.https-expected.txt 2019-05-19 00:42:16 UTC (rev 245500)
@@ -2,4 +2,6 @@
PASS PublicKeyCredential's [[get]] with timeout in a mock hid authenticator.
PASS PublicKeyCredential's [[get]] with malicious payload in a mock hid authenticator.
PASS PublicKeyCredential's [[get]] with unsupported options in a mock hid authenticator.
+PASS PublicKeyCredential's [[get]] with authenticator downgrade failed in a mock hid authenticator.
+PASS PublicKeyCredential's [[get]] with authenticator downgrade succeeded and then U2F failed in a mock hid authenticator. 2
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid.https.html (245499 => 245500)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid.https.html 2019-05-18 07:12:17 UTC (rev 245499)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid.https.html 2019-05-19 00:42:16 UTC (rev 245500)
@@ -33,7 +33,7 @@
if (window.testRunner)
testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "malicious-payload", payloadBase64: [testDummyMessagePayloadBase64] } });
- return promiseRejects(t, "UnknownError", navigator.credentials.get(options), "Unknown internal error. Error code: -1");
+ return promiseRejects(t, "UnknownError", navigator.credentials.get(options), "Unknown internal error. Error code: 255");
}, "PublicKeyCredential's [[get]] with malicious payload in a mock hid authenticator.");
promise_test(function(t) {
@@ -48,4 +48,29 @@
testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "unsupported-options" } });
return promiseRejects(t, "UnknownError", navigator.credentials.get(options), "Unknown internal error. Error code: 43");
}, "PublicKeyCredential's [[get]] with unsupported options in a mock hid authenticator.");
+
+ promise_test(function(t) {
+ const options = {
+ publicKey: {
+ challenge: asciiToUint8Array("123456")
+ }
+ };
+
+ if (window.testRunner)
+ testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "malicious-payload", payloadBase64: [testCtapErrInvalidCredentialResponseBase64] } });
+ return promiseRejects(t, "UnknownError", navigator.credentials.get(options), "Unknown internal error. Error code: 34");
+ }, "PublicKeyCredential's [[get]] with authenticator downgrade failed in a mock hid authenticator.");
+
+ promise_test(function(t) {
+ const options = {
+ publicKey: {
+ challenge: asciiToUint8Array("123456"),
+ extensions: { appid: "" }
+ }
+ };
+
+ if (window.testRunner)
+ testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "malicious-payload", canDowngrade: true, payloadBase64: [testCtapErrInvalidCredentialResponseBase64] } });
+ return promiseRejects(t, "NotSupportedError", navigator.credentials.get(options), "Cannot convert the request to U2F command.");
+ }, "PublicKeyCredential's [[get]] with authenticator downgrade succeeded and then U2F failed in a mock hid authenticator. 2");
</script>
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-u2f.https-expected.txt (245499 => 245500)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-u2f.https-expected.txt 2019-05-18 07:12:17 UTC (rev 245499)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-u2f.https-expected.txt 2019-05-19 00:42:16 UTC (rev 245500)
@@ -8,4 +8,6 @@
PASS PublicKeyCredential's [[get]] with an AppID in a mock hid authenticator.
PASS PublicKeyCredential's [[get]] with multiple credentials and AppID is not used in a mock hid authenticator.
PASS PublicKeyCredential's [[get]] with multiple credentials and AppID is used in a mock hid authenticator.
+PASS PublicKeyCredential's [[get]] with downgraded authenticator in a mock hid authenticator.
+PASS PublicKeyCredential's [[get]] with downgraded authenticator in a mock hid authenticator. (AppID)
Modified: trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-u2f.https.html (245499 => 245500)
--- trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-u2f.https.html 2019-05-18 07:12:17 UTC (rev 245499)
+++ trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-u2f.https.html 2019-05-19 00:42:16 UTC (rev 245500)
@@ -181,4 +181,38 @@
});
}, "PublicKeyCredential's [[get]] with multiple credentials and AppID is used in a mock hid authenticator.");
+ promise_test(t => {
+ const options = {
+ publicKey: {
+ challenge: Base64URL.parse("MTIzNDU2"),
+ allowCredentials: [{ type: "public-key", id: Base64URL.parse(testU2fCredentialIdBase64) }],
+ timeout: 100,
+ extensions: { appid: "https://localhost:666/appid" }
+ }
+ };
+
+ if (window.testRunner)
+ testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", canDowngrade: true, payloadBase64: [testCtapErrInvalidCredentialResponseBase64, testU2fSignResponse] } });
+ return navigator.credentials.get(options).then(credential => {
+ return checkResult(credential);
+ });
+ }, "PublicKeyCredential's [[get]] with downgraded authenticator in a mock hid authenticator.");
+
+ promise_test(t => {
+ const options = {
+ publicKey: {
+ challenge: Base64URL.parse("MTIzNDU2"),
+ allowCredentials: [{ type: "public-key", id: Base64URL.parse(testU2fCredentialIdBase64) }],
+ timeout: 100,
+ extensions: { appid: "https://localhost:666/appid" }
+ }
+ };
+
+ if (window.testRunner)
+ testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", canDowngrade: true, payloadBase64: [testCtapErrInvalidCredentialResponseBase64, testU2fApduWrongDataOnlyResponseBase64, testU2fSignResponse] } });
+ return navigator.credentials.get(options).then(credential => {
+ return checkResult(credential, true, "7eabc5cc3251bdc59115ef87b5f7ee74cb03747e39ba8341748565cc129c0719");
+ });
+ }, "PublicKeyCredential's [[get]] with downgraded authenticator in a mock hid authenticator. (AppID)");
+
</script>
Modified: trunk/LayoutTests/http/wpt/webauthn/resources/util.js (245499 => 245500)
--- trunk/LayoutTests/http/wpt/webauthn/resources/util.js 2019-05-18 07:12:17 UTC (rev 245499)
+++ trunk/LayoutTests/http/wpt/webauthn/resources/util.js 2019-05-19 00:42:16 UTC (rev 245500)
@@ -98,6 +98,7 @@
"AQAAADswRAIge94KUqwfTIsn4AOjcM1mpMcRjdItVEeDX0W5nGhCP/cCIDxRe0eH" +
"f4V4LeEAhqeD0effTjY553H19q+jWq1Tc4WOkAA=";
const testCtapErrCredentialExcludedOnlyResponseBase64 = "GQ==";
+const testCtapErrInvalidCredentialResponseBase64 = "Ig==";
const RESOURCES_DIR = "/WebKit/webauthn/resources/";
Modified: trunk/Source/WebKit/ChangeLog (245499 => 245500)
--- trunk/Source/WebKit/ChangeLog 2019-05-18 07:12:17 UTC (rev 245499)
+++ trunk/Source/WebKit/ChangeLog 2019-05-19 00:42:16 UTC (rev 245500)
@@ -1,3 +1,38 @@
+2019-05-18 Jiewen Tan <[email protected]>
+
+ [WebAuthN] Allow authenticators that support both CTAP and U2F to try U2F if CTAP fails in authenticatorGetAssertion
+ https://bugs.webkit.org/show_bug.cgi?id=197974
+ <rdar://problem/50879746>
+
+ Reviewed by Brent Fulgham.
+
+ Authenticators that support both CTAP and U2F protocols can be used in a U2F enabled browser to create a credential in
+ U2F format. When such authenticator is used to login in WebKit, it will be treated as a CTAP authenticator. Since the
+ previous credential is in U2F format, the authenticator will not consider that as a valid credential when CTAP requests
+ come along for that U2F credential. Therefore the previous created U2F credential will not be asked at all, and users
+ will not be able to login. This situation is not well documented in the CTAP/WebAuthN spec yet.
+
+ To workaround the above issue, an authenticator that supports both protocols will be downgraded to a U2F authenticator
+ to ask a potential U2F credential once a valid error is returned regarding to the first CTAP request.
+
+ * UIProcess/API/C/WKWebsiteDataStoreRef.cpp:
+ (WKWebsiteDataStoreSetWebAuthenticationMockConfiguration):
+ * UIProcess/WebAuthentication/Authenticator.h:
+ * UIProcess/WebAuthentication/AuthenticatorManager.cpp:
+ (WebKit::AuthenticatorManager::downgrade):
+ * UIProcess/WebAuthentication/AuthenticatorManager.h:
+ * UIProcess/WebAuthentication/Mock/MockHidConnection.cpp:
+ (WebKit::MockHidConnection::parseRequest):
+ (WebKit::MockHidConnection::feedReports):
+ * UIProcess/WebAuthentication/Mock/MockWebAuthenticationConfiguration.h:
+ * UIProcess/WebAuthentication/fido/CtapHidAuthenticator.cpp:
+ (WebKit::CtapHidAuthenticator::makeCredential):
+ (WebKit::CtapHidAuthenticator::getAssertion):
+ (WebKit::CtapHidAuthenticator::continueGetAssertionAfterResponseReceived):
+ (WebKit::CtapHidAuthenticator::tryDowngrade):
+ (WebKit::CtapHidAuthenticator::continueGetAssertionAfterResponseReceived const): Deleted.
+ * UIProcess/WebAuthentication/fido/CtapHidAuthenticator.h:
+
2019-05-17 Don Olmstead <[email protected]>
[CMake] Use builtin FindICU
Modified: trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp (245499 => 245500)
--- trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp 2019-05-18 07:12:17 UTC (rev 245499)
+++ trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp 2019-05-19 00:42:16 UTC (rev 245500)
@@ -652,6 +652,9 @@
if (auto continueAfterErrorData = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(hidRef, adoptWK(WKStringCreateWithUTF8CString("ContinueAfterErrorData")).get())))
hid.continueAfterErrorData = WKBooleanGetValue(continueAfterErrorData);
+ if (auto canDowngrade = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(hidRef, adoptWK(WKStringCreateWithUTF8CString("CanDowngrade")).get())))
+ hid.canDowngrade = WKBooleanGetValue(canDowngrade);
+
configuration.hid = WTFMove(hid);
}
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Authenticator.h (245499 => 245500)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/Authenticator.h 2019-05-18 07:12:17 UTC (rev 245499)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Authenticator.h 2019-05-19 00:42:16 UTC (rev 245500)
@@ -44,6 +44,7 @@
public:
virtual ~Observer() = default;
virtual void respondReceived(Respond&&) = 0;
+ virtual void downgrade(Authenticator* id, Ref<Authenticator>&& downgradedAuthenticator) = 0;
};
virtual ~Authenticator() = default;
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp (245499 => 245500)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp 2019-05-18 07:12:17 UTC (rev 245499)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp 2019-05-19 00:42:16 UTC (rev 245500)
@@ -208,6 +208,17 @@
respondReceivedInternal(WTFMove(respond));
}
+void AuthenticatorManager::downgrade(Authenticator* id, Ref<Authenticator>&& downgradedAuthenticator)
+{
+ RunLoop::main().dispatch([weakThis = makeWeakPtr(*this), id] {
+ if (!weakThis)
+ return;
+ auto removed = weakThis->m_authenticators.remove(id);
+ ASSERT_UNUSED(removed, removed);
+ });
+ authenticatorAdded(WTFMove(downgradedAuthenticator));
+}
+
UniqueRef<AuthenticatorTransportService> AuthenticatorManager::createService(WebCore::AuthenticatorTransport transport, AuthenticatorTransportService::Observer& observer) const
{
return AuthenticatorTransportService::create(transport, observer);
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h (245499 => 245500)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h 2019-05-18 07:12:17 UTC (rev 245499)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h 2019-05-19 00:42:16 UTC (rev 245500)
@@ -70,6 +70,7 @@
// Authenticator::Observer
void respondReceived(Respond&&) final;
+ void downgrade(Authenticator* id, Ref<Authenticator>&& downgradedAuthenticator) final;
// Overriden by MockAuthenticatorManager.
virtual UniqueRef<AuthenticatorTransportService> createService(WebCore::AuthenticatorTransport, AuthenticatorTransportService::Observer&) const;
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockHidConnection.cpp (245499 => 245500)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockHidConnection.cpp 2019-05-18 07:12:17 UTC (rev 245499)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockHidConnection.cpp 2019-05-19 00:42:16 UTC (rev 245500)
@@ -132,6 +132,8 @@
if (m_stage == Mock::Stage::Request && m_subStage == Mock::SubStage::Msg) {
// Make sure we issue different msg cmd for CTAP and U2F.
+ if (m_configuration.hid->canDowngrade && !m_configuration.hid->isU2f)
+ m_configuration.hid->isU2f = m_requestMessage->cmd() == FidoHidDeviceCommand::kMsg;
ASSERT(m_configuration.hid->isU2f ^ (m_requestMessage->cmd() != FidoHidDeviceCommand::kMsg));
// Set options.
@@ -208,7 +210,11 @@
Optional<FidoHidMessage> message;
if (m_stage == Mock::Stage::Info && m_subStage == Mock::SubStage::Msg) {
- auto infoData = encodeAsCBOR(AuthenticatorGetInfoResponse({ ProtocolVersion::kCtap }, Vector<uint8_t>(aaguidLength, 0u)));
+ Vector<uint8_t> infoData;
+ if (m_configuration.hid->canDowngrade)
+ infoData = encodeAsCBOR(AuthenticatorGetInfoResponse({ ProtocolVersion::kCtap, ProtocolVersion::kU2f }, Vector<uint8_t>(aaguidLength, 0u)));
+ else
+ infoData = encodeAsCBOR(AuthenticatorGetInfoResponse({ ProtocolVersion::kCtap }, Vector<uint8_t>(aaguidLength, 0u)));
infoData.insert(0, static_cast<uint8_t>(CtapDeviceResponseCode::kSuccess)); // Prepend status code.
if (stagesMatch() && m_configuration.hid->error == Mock::Error::WrongChannelId)
message = FidoHidMessage::create(m_currentChannel - 1, FidoHidDeviceCommand::kCbor, infoData);
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockWebAuthenticationConfiguration.h (245499 => 245500)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockWebAuthenticationConfiguration.h 2019-05-18 07:12:17 UTC (rev 245499)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockWebAuthenticationConfiguration.h 2019-05-19 00:42:16 UTC (rev 245500)
@@ -69,6 +69,7 @@
bool keepAlive { false };
bool fastDataArrival { false };
bool continueAfterErrorData { false };
+ bool canDowngrade { false };
};
bool silentFailure { false };
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapHidAuthenticator.cpp (245499 => 245500)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapHidAuthenticator.cpp 2019-05-18 07:12:17 UTC (rev 245499)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapHidAuthenticator.cpp 2019-05-19 00:42:16 UTC (rev 245500)
@@ -29,6 +29,7 @@
#if ENABLE(WEB_AUTHN) && PLATFORM(MAC)
#include "CtapHidDriver.h"
+#include "U2fHidAuthenticator.h"
#include <WebCore/DeviceRequestConverter.h>
#include <WebCore/DeviceResponseConverter.h>
#include <WebCore/ExceptionData.h>
@@ -49,6 +50,7 @@
void CtapHidAuthenticator::makeCredential()
{
+ ASSERT(!m_isDowngraded);
auto cborCmd = encodeMakeCredenitalRequestAsCBOR(requestData().hash, requestData().creationOptions, m_info.options().userVerificationAvailability());
m_driver->transact(WTFMove(cborCmd), [weakThis = makeWeakPtr(*this)](Vector<uint8_t>&& data) {
ASSERT(RunLoop::isMain());
@@ -74,6 +76,7 @@
void CtapHidAuthenticator::getAssertion()
{
+ ASSERT(!m_isDowngraded);
auto cborCmd = encodeGetAssertionRequestAsCBOR(requestData().hash, requestData().requestOptions, m_info.options().userVerificationAvailability());
m_driver->transact(WTFMove(cborCmd), [weakThis = makeWeakPtr(*this)](Vector<uint8_t>&& data) {
ASSERT(RunLoop::isMain());
@@ -83,16 +86,32 @@
});
}
-void CtapHidAuthenticator::continueGetAssertionAfterResponseReceived(Vector<uint8_t>&& data) const
+void CtapHidAuthenticator::continueGetAssertionAfterResponseReceived(Vector<uint8_t>&& data)
{
auto response = readCTAPGetAssertionResponse(data);
if (!response) {
- receiveRespond(ExceptionData { UnknownError, makeString("Unknown internal error. Error code: ", data.size() == 1 ? data[0] : -1) });
+ auto error = getResponseCode(data);
+ if (error != CtapDeviceResponseCode::kCtap2ErrInvalidCBOR && tryDowngrade())
+ return;
+ receiveRespond(ExceptionData { UnknownError, makeString("Unknown internal error. Error code: ", static_cast<uint8_t>(error)) });
return;
}
receiveRespond(WTFMove(*response));
}
+bool CtapHidAuthenticator::tryDowngrade()
+{
+ if (m_info.versions().find(ProtocolVersion::kU2f) == m_info.versions().end())
+ return false;
+ if (!observer())
+ return false;
+
+ m_isDowngraded = true;
+ m_driver->setProtocol(ProtocolVersion::kU2f);
+ observer()->downgrade(this, U2fHidAuthenticator::create(WTFMove(m_driver)));
+ return true;
+}
+
} // namespace WebKit
#endif // ENABLE(WEB_AUTHN) && PLATFORM(MAC)
Modified: trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapHidAuthenticator.h (245499 => 245500)
--- trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapHidAuthenticator.h 2019-05-18 07:12:17 UTC (rev 245499)
+++ trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapHidAuthenticator.h 2019-05-19 00:42:16 UTC (rev 245500)
@@ -47,10 +47,13 @@
void makeCredential() final;
void continueMakeCredentialAfterResponseReceived(Vector<uint8_t>&&) const;
void getAssertion() final;
- void continueGetAssertionAfterResponseReceived(Vector<uint8_t>&&) const;
+ void continueGetAssertionAfterResponseReceived(Vector<uint8_t>&&);
+ bool tryDowngrade();
+
std::unique_ptr<CtapHidDriver> m_driver;
fido::AuthenticatorGetInfoResponse m_info;
+ bool m_isDowngraded { false };
};
} // namespace WebKit
Modified: trunk/Tools/ChangeLog (245499 => 245500)
--- trunk/Tools/ChangeLog 2019-05-18 07:12:17 UTC (rev 245499)
+++ trunk/Tools/ChangeLog 2019-05-19 00:42:16 UTC (rev 245500)
@@ -1,3 +1,16 @@
+2019-05-18 Jiewen Tan <[email protected]>
+
+ [WebAuthN] Allow authenticators that support both CTAP and U2F to try U2F if CTAP fails in authenticatorGetAssertion
+ https://bugs.webkit.org/show_bug.cgi?id=197974
+ <rdar://problem/50879746>
+
+ Reviewed by Brent Fulgham.
+
+ Add a canDowngrade option for mock hid devices to simulate the situation.
+
+ * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+ (WTR::TestRunner::setWebAuthenticationMockConfiguration):
+
2019-05-18 Tadeu Zagallo <[email protected]>
Add extra information to dumpJITMemory
Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp (245499 => 245500)
--- trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp 2019-05-18 07:12:17 UTC (rev 245499)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp 2019-05-19 00:42:16 UTC (rev 245500)
@@ -2692,6 +2692,16 @@
hidValues.append(adoptWK(WKBooleanCreate(continueAfterErrorData)).get());
}
+ JSRetainPtr<JSStringRef> canDowngradePropertyName(Adopt, JSStringCreateWithUTF8CString("canDowngrade"));
+ JSValueRef canDowngradeValue = JSObjectGetProperty(context, hid, canDowngradePropertyName.get(), 0);
+ if (!JSValueIsUndefined(context, canDowngradeValue) && !JSValueIsNull(context, canDowngradeValue)) {
+ if (!JSValueIsBoolean(context, canDowngradeValue))
+ return;
+ bool canDowngrade = JSValueToBoolean(context, canDowngradeValue);
+ hidKeys.append(adoptWK(WKStringCreateWithUTF8CString("CanDowngrade")));
+ hidValues.append(adoptWK(WKBooleanCreate(canDowngrade)).get());
+ }
+
Vector<WKStringRef> rawHidKeys;
Vector<WKTypeRef> rawHidValues;
rawHidKeys.resize(hidKeys.size());