WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-203346-20200109143032.patch (text/plain), 33.92 KB, created by
Jiewen Tan
on 2020-01-09 14:30:33 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Jiewen Tan
Created:
2020-01-09 14:30:33 PST
Size:
33.92 KB
patch
obsolete
>Subversion Revision: 254052 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 1f8ab1055afe90e5699594e4becbb5d7277c76f4..95ccbabab183788060b3632a192d6a906cafa9f2 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,26 @@ >+2020-01-09 Jiewen Tan <jiewen_tan@apple.com> >+ >+ [WebAuthn] Support authenticatorGetNextAssertion >+ https://bugs.webkit.org/show_bug.cgi?id=203346 >+ <rdar://problem/56558488> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Covered by new tests within existing test files. >+ >+ * Modules/webauthn/AuthenticatorAssertionResponse.h: >+ (WebCore::AuthenticatorAssertionResponse::setName): >+ (WebCore::AuthenticatorAssertionResponse::name const): >+ (WebCore::AuthenticatorAssertionResponse::setDisplayName): >+ (WebCore::AuthenticatorAssertionResponse::displayName const): >+ (WebCore::AuthenticatorAssertionResponse::setNumberOfCredentials): >+ (WebCore::AuthenticatorAssertionResponse::numberOfCredentials const): >+ Adds new members to store new fields of the response from the authenticator. Field "icon" >+ is omitted given it could be used to track users according to https://github.com/w3c/webauthn/issues/1285. >+ * Modules/webauthn/fido/DeviceResponseConverter.cpp: >+ (fido::readCTAPGetAssertionResponse): >+ Adds new logic to parse above fields from an authenticator response. >+ > 2020-01-06 Per Arne Vollan <pvollan@apple.com> > > [iOS] Issue mach lookup extension to launch services daemon for Mail >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index 99c372701fc3330434419a6da5b366b187a7f7e7..620a619316643ffa7c11fa6a783f8fe9a92d55e5 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,32 @@ >+2020-01-09 Jiewen Tan <jiewen_tan@apple.com> >+ >+ [WebAuthn] Support authenticatorGetNextAssertion >+ https://bugs.webkit.org/show_bug.cgi?id=203346 >+ <rdar://problem/56558488> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ This patch implements authenticatorGetNextAssertion as suggested by the spec: >+ https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#authenticatorGetNextAssertion >+ >+ The work flow is as follow: >+ 1) When a valid assertion response is received, check its numberOfCredentials member; >+ 2) When it is larger then 1, use authenticatorGetNextAssertion to get all remaining responses; >+ 3) Once all responses are gathered, ask UI clients to pick one to return. >+ >+ * UIProcess/API/APIWebAuthenticationPanelClient.h: >+ (API::WebAuthenticationPanelClient::selectAssertionResponses const): >+ * UIProcess/WebAuthentication/Authenticator.h: >+ * UIProcess/WebAuthentication/AuthenticatorManager.cpp: >+ (WebKit::AuthenticatorManager::selectAssertionResponses): >+ * UIProcess/WebAuthentication/AuthenticatorManager.h: >+ * UIProcess/WebAuthentication/Mock/MockHidConnection.cpp: >+ (WebKit::MockHidConnection::parseRequest): >+ * UIProcess/WebAuthentication/fido/CtapAuthenticator.cpp: >+ (WebKit::CtapAuthenticator::continueGetAssertionAfterResponseReceived): >+ (WebKit::CtapAuthenticator::continueGetNextAssertionAfterResponseReceived): >+ * UIProcess/WebAuthentication/fido/CtapAuthenticator.h: >+ > 2020-01-06 Per Arne Vollan <pvollan@apple.com> > > [iOS] Issue mach lookup extension to launch services daemon for Mail >diff --git a/Source/WebCore/Modules/webauthn/AuthenticatorAssertionResponse.h b/Source/WebCore/Modules/webauthn/AuthenticatorAssertionResponse.h >index aba229ecbf426839c0338c2cd54bbb2fc105c708..dc4c8037a356813be52bc379f487f5b5791c8e52 100644 >--- a/Source/WebCore/Modules/webauthn/AuthenticatorAssertionResponse.h >+++ b/Source/WebCore/Modules/webauthn/AuthenticatorAssertionResponse.h >@@ -41,6 +41,13 @@ public: > ArrayBuffer* signature() const { return m_signature.ptr(); } > ArrayBuffer* userHandle() const { return m_userHandle.get(); } > >+ void setName(const String& name) { m_name = name; } >+ String name() const { return m_name; } >+ void setDisplayName(const String& displayName) { m_displayName = displayName; } >+ String displayName() const { return m_displayName; } >+ void setNumberOfCredentials(size_t numberOfCredentials) { m_numberOfCredentials = numberOfCredentials; } >+ size_t numberOfCredentials() const { return m_numberOfCredentials; } >+ > private: > AuthenticatorAssertionResponse(Ref<ArrayBuffer>&&, Ref<ArrayBuffer>&&, Ref<ArrayBuffer>&&, RefPtr<ArrayBuffer>&&); > >@@ -50,6 +57,10 @@ private: > Ref<ArrayBuffer> m_authenticatorData; > Ref<ArrayBuffer> m_signature; > RefPtr<ArrayBuffer> m_userHandle; >+ >+ String m_name; >+ String m_displayName; >+ size_t m_numberOfCredentials { 0 }; > }; > > } // namespace WebCore >diff --git a/Source/WebCore/Modules/webauthn/fido/DeviceResponseConverter.cpp b/Source/WebCore/Modules/webauthn/fido/DeviceResponseConverter.cpp >index 25563a057d0cc0568d3ab0107a2db51a2a94a4e2..b54a3805a83c09eba9e4d41741de33d19586233e 100644 >--- a/Source/WebCore/Modules/webauthn/fido/DeviceResponseConverter.cpp >+++ b/Source/WebCore/Modules/webauthn/fido/DeviceResponseConverter.cpp >@@ -166,6 +166,7 @@ RefPtr<AuthenticatorAssertionResponse> readCTAPGetAssertionResponse(const Vector > return nullptr; > auto& signature = it->second.getByteString(); > >+ RefPtr<AuthenticatorAssertionResponse> response; > it = responseMap.find(CBOR(4)); > if (it != responseMap.end() && it->second.isMap()) { > auto& user = it->second.getMap(); >@@ -173,10 +174,30 @@ RefPtr<AuthenticatorAssertionResponse> readCTAPGetAssertionResponse(const Vector > if (itr == user.end() || !itr->second.isByteString()) > return nullptr; > auto& userHandle = itr->second.getByteString(); >- return AuthenticatorAssertionResponse::create(credentialId, authData, signature, userHandle); >+ response = AuthenticatorAssertionResponse::create(credentialId, authData, signature, userHandle); >+ >+ itr = user.find(CBOR(kEntityNameMapKey)); >+ if (itr != user.end()) { >+ if (!itr->second.isString()) >+ return nullptr; >+ response->setName(itr->second.getString()); >+ } >+ >+ itr = user.find(CBOR(kDisplayNameMapKey)); >+ if (itr != user.end()) { >+ if (!itr->second.isString()) >+ return nullptr; >+ response->setDisplayName(itr->second.getString()); >+ } >+ } else { >+ response = AuthenticatorAssertionResponse::create(credentialId, authData, signature, { }); > } > >- return AuthenticatorAssertionResponse::create(credentialId, authData, signature, { }); >+ it = responseMap.find(CBOR(5)); >+ if (it != responseMap.end() && it->second.isUnsigned()) >+ response->setNumberOfCredentials(it->second.getUnsigned()); >+ >+ return response; > } > > Optional<AuthenticatorGetInfoResponse> readCTAPGetInfoResponse(const Vector<uint8_t>& inBuffer) >diff --git a/Source/WebKit/UIProcess/API/APIWebAuthenticationPanelClient.h b/Source/WebKit/UIProcess/API/APIWebAuthenticationPanelClient.h >index 555b5619fd825cdc5bbc0450b789837662ed2944..226b81e83c08cc574c05927b1ccb91f62b0996cb 100644 >--- a/Source/WebKit/UIProcess/API/APIWebAuthenticationPanelClient.h >+++ b/Source/WebKit/UIProcess/API/APIWebAuthenticationPanelClient.h >@@ -27,6 +27,14 @@ > > #if ENABLE(WEB_AUTHN) > >+#include <wtf/CompletionHandler.h> >+#include <wtf/HashSet.h> >+#include <wtf/RefCounted.h> >+ >+namespace WebCore { >+class AuthenticatorAssertionResponse; >+} >+ > namespace WebKit { > enum class WebAuthenticationStatus : bool; > enum class WebAuthenticationResult : bool; >@@ -41,6 +49,7 @@ public: > > virtual void updatePanel(WebKit::WebAuthenticationStatus) const { } > virtual void dismissPanel(WebKit::WebAuthenticationResult) const { } >+ virtual void selectAssertionResponses(const HashSet<Ref<WebCore::AuthenticatorAssertionResponse>>& responses, CompletionHandler<void(const Ref<WebCore::AuthenticatorAssertionResponse>&)>&& completionHandler) const { completionHandler(*responses.begin()); } > }; > > } // namespace API >diff --git a/Source/WebKit/UIProcess/WebAuthentication/Authenticator.h b/Source/WebKit/UIProcess/WebAuthentication/Authenticator.h >index 0d24713bf73bc09e1730a2921649ccc88eb179b3..afaedd1770601394807341b409d47e2d0ccf386b 100644 >--- a/Source/WebKit/UIProcess/WebAuthentication/Authenticator.h >+++ b/Source/WebKit/UIProcess/WebAuthentication/Authenticator.h >@@ -35,6 +35,10 @@ > #include <wtf/RefCounted.h> > #include <wtf/WeakPtr.h> > >+namespace WebCore { >+class AuthenticatorAssertionResponse; >+} >+ > namespace WebKit { > > class Authenticator : public RefCounted<Authenticator>, public CanMakeWeakPtr<Authenticator> { >@@ -47,6 +51,7 @@ public: > virtual void respondReceived(Respond&&) = 0; > virtual void downgrade(Authenticator* id, Ref<Authenticator>&& downgradedAuthenticator) = 0; > virtual void authenticatorStatusUpdated(WebAuthenticationStatus) = 0; >+ virtual void selectAssertionResponses(const HashSet<Ref<WebCore::AuthenticatorAssertionResponse>>&, CompletionHandler<void(const Ref<WebCore::AuthenticatorAssertionResponse>&)>&&) = 0; > }; > > virtual ~Authenticator() = default; >diff --git a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp b/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp >index 6faede547644ab7d8f96e890d838a1bb13bc089c..eb49db0d8182f2cc26cddc4bb9e788b220f5247c 100644 >--- a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp >+++ b/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp >@@ -273,6 +273,12 @@ void AuthenticatorManager::authenticatorStatusUpdated(WebAuthenticationStatus st > panel->client().updatePanel(status); > } > >+void AuthenticatorManager::selectAssertionResponses(const HashSet<Ref<WebCore::AuthenticatorAssertionResponse>>& responses, CompletionHandler<void(const Ref<WebCore::AuthenticatorAssertionResponse>&)>&& completionHandler) >+{ >+ if (auto* panel = m_pendingRequestData.panel.get()) >+ panel->client().selectAssertionResponses(responses, WTFMove(completionHandler)); >+} >+ > UniqueRef<AuthenticatorTransportService> AuthenticatorManager::createService(AuthenticatorTransport transport, AuthenticatorTransportService::Observer& observer) const > { > return AuthenticatorTransportService::create(transport, observer); >diff --git a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h b/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h >index dc6c4443910010023bb15529809e9eea670efb0e..97ba2c90ef6fc6e0a01f16dfe642347b20210a63 100644 >--- a/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h >+++ b/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h >@@ -81,6 +81,7 @@ private: > void respondReceived(Respond&&) final; > void downgrade(Authenticator* id, Ref<Authenticator>&& downgradedAuthenticator) final; > void authenticatorStatusUpdated(WebAuthenticationStatus) final; >+ void selectAssertionResponses(const HashSet<Ref<WebCore::AuthenticatorAssertionResponse>>&, CompletionHandler<void(const Ref<WebCore::AuthenticatorAssertionResponse>&)>&&) final; > > // Overriden by MockAuthenticatorManager. > virtual UniqueRef<AuthenticatorTransportService> createService(WebCore::AuthenticatorTransport, AuthenticatorTransportService::Observer&) const; >diff --git a/Source/WebKit/UIProcess/WebAuthentication/Mock/MockHidConnection.cpp b/Source/WebKit/UIProcess/WebAuthentication/Mock/MockHidConnection.cpp >index 9e5d8fa706680df6e14f963f23be9e885e744f55..90c1bb005e5b98d7d848e814c8212d81a90fe070 100644 >--- a/Source/WebKit/UIProcess/WebAuthentication/Mock/MockHidConnection.cpp >+++ b/Source/WebKit/UIProcess/WebAuthentication/Mock/MockHidConnection.cpp >@@ -158,7 +158,7 @@ void MockHidConnection::parseRequest() > auto cmd = static_cast<CtapRequestCommand>(payload[0]); > payload.remove(0); > auto requestMap = CBORReader::read(payload); >- ASSERT(requestMap); >+ ASSERT(requestMap || cmd == CtapRequestCommand::kAuthenticatorGetNextAssertion); > > if (cmd == CtapRequestCommand::kAuthenticatorMakeCredential) { > auto it = requestMap->getMap().find(CBORValue(CtapMakeCredentialRequestOptionsKey)); // Find options. >diff --git a/Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.cpp b/Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.cpp >index 9e41eb71adc5844efede40c67dfe233fd86ac5a1..e73995e40a33bd7241e0ef991a4a202964f30596 100644 >--- a/Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.cpp >+++ b/Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.cpp >@@ -100,7 +100,56 @@ void CtapAuthenticator::continueGetAssertionAfterResponseReceived(Vector<uint8_t > receiveRespond(ExceptionData { UnknownError, makeString("Unknown internal error. Error code: ", static_cast<uint8_t>(error)) }); > return; > } >- receiveRespond(response.releaseNonNull()); >+ >+ if (response->numberOfCredentials() <= 1) { >+ receiveRespond(response.releaseNonNull()); >+ return; >+ } >+ >+ m_remainingAssertionResponses = response->numberOfCredentials() - 1; >+ auto addResult = m_assertionResponses.add(response.releaseNonNull()); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ driver().transact(encodeEmptyAuthenticatorRequest(CtapRequestCommand::kAuthenticatorGetNextAssertion), [weakThis = makeWeakPtr(*this)](Vector<uint8_t>&& data) { >+ ASSERT(RunLoop::isMain()); >+ if (!weakThis) >+ return; >+ weakThis->continueGetNextAssertionAfterResponseReceived(WTFMove(data)); >+ }); >+} >+ >+void CtapAuthenticator::continueGetNextAssertionAfterResponseReceived(Vector<uint8_t>&& data) >+{ >+ auto response = readCTAPGetAssertionResponse(data); >+ if (!response) { >+ auto error = getResponseCode(data); >+ receiveRespond(ExceptionData { UnknownError, makeString("Unknown internal error. Error code: ", static_cast<uint8_t>(error)) }); >+ return; >+ } >+ m_remainingAssertionResponses--; >+ auto addResult = m_assertionResponses.add(response.releaseNonNull()); >+ ASSERT_UNUSED(addResult, addResult.isNewEntry); >+ >+ if (!m_remainingAssertionResponses) { >+ if (auto* observer = this->observer()) { >+ observer->selectAssertionResponses(m_assertionResponses, [this, weakThis = makeWeakPtr(*this)] (const Ref<AuthenticatorAssertionResponse>& response) { >+ ASSERT(RunLoop::isMain()); >+ if (!weakThis) >+ return; >+ auto returnResponse = m_assertionResponses.take(response); >+ if (!returnResponse) >+ return; >+ receiveRespond(WTFMove(*returnResponse)); >+ }); >+ } >+ return; >+ } >+ >+ driver().transact(encodeEmptyAuthenticatorRequest(CtapRequestCommand::kAuthenticatorGetNextAssertion), [weakThis = makeWeakPtr(*this)](Vector<uint8_t>&& data) { >+ ASSERT(RunLoop::isMain()); >+ if (!weakThis) >+ return; >+ weakThis->continueGetNextAssertionAfterResponseReceived(WTFMove(data)); >+ }); > } > > bool CtapAuthenticator::tryDowngrade() >diff --git a/Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.h b/Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.h >index ee543d85f94d08fa0c6b7a049cdfedf8ef42fc5c..54ff4941a6803141b180164bb2eb20d93d0743cf 100644 >--- a/Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.h >+++ b/Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.h >@@ -48,12 +48,15 @@ private: > void continueMakeCredentialAfterResponseReceived(Vector<uint8_t>&&) const; > void getAssertion() final; > void continueGetAssertionAfterResponseReceived(Vector<uint8_t>&&); >+ void continueGetNextAssertionAfterResponseReceived(Vector<uint8_t>&&); > > bool tryDowngrade(); > bool processGoogleLegacyAppIdSupportExtension(); > > fido::AuthenticatorGetInfoResponse m_info; > bool m_isDowngraded { false }; >+ size_t m_remainingAssertionResponses { 0 }; >+ HashSet<Ref<WebCore::AuthenticatorAssertionResponse>> m_assertionResponses; > }; > > } // namespace WebKit >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index bff9bdb86b77c649c2fe8642b386bda13c69a4ae..49f0a891f4e9647ddf5e369773e70a678559cc4c 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,16 @@ >+2020-01-09 Jiewen Tan <jiewen_tan@apple.com> >+ >+ [WebAuthn] Support authenticatorGetNextAssertion >+ https://bugs.webkit.org/show_bug.cgi?id=203346 >+ <rdar://problem/56558488> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * TestWebKitAPI/Tests/WebCore/CtapResponseTest.cpp: >+ (TestWebKitAPI::TEST): >+ * TestWebKitAPI/Tests/WebCore/FidoTestData.h: >+ Adds new test case for new logic in DeviceResponseConverter. >+ > 2020-01-06 Per Arne Vollan <pvollan@apple.com> > > [iOS] Issue mach lookup extension to launch services daemon for Mail >diff --git a/Tools/TestWebKitAPI/Tests/WebCore/CtapResponseTest.cpp b/Tools/TestWebKitAPI/Tests/WebCore/CtapResponseTest.cpp >index 408c94edf744623ee2a10365f171c97023635a38..a508e7f8497a0a5940978020acbf716468af7fb8 100644 >--- a/Tools/TestWebKitAPI/Tests/WebCore/CtapResponseTest.cpp >+++ b/Tools/TestWebKitAPI/Tests/WebCore/CtapResponseTest.cpp >@@ -399,7 +399,18 @@ TEST(CTAPResponseTest, TestReadMakeCredentialResponse) > > // Leveraging example 5 of section 6.1 of the CTAP spec. > // https://fidoalliance.org/specs/fido-v2.0-ps-20170927/fido-client-to-authenticator-protocol-v2.0-ps-20170927.html >-TEST(CTAPResponseTest, TestReadGetAssertionResponse) >+TEST(CTAPResponseTest, TestReadGetAssertionResponse1) >+{ >+ auto getAssertionResponse = readCTAPGetAssertionResponse(convertBytesToVector(TestData::kDeviceGetAssertionResponseShort, sizeof(TestData::kDeviceGetAssertionResponseShort))); >+ ASSERT_TRUE(getAssertionResponse); >+ >+ EXPECT_EQ(getAssertionResponse->authenticatorData()->byteLength(), sizeof(TestData::kCtap2GetAssertionAuthData)); >+ EXPECT_EQ(memcmp(getAssertionResponse->authenticatorData()->data(), TestData::kCtap2GetAssertionAuthData, sizeof(TestData::kCtap2GetAssertionAuthData)), 0); >+ EXPECT_EQ(getAssertionResponse->signature()->byteLength(), sizeof(TestData::kCtap2GetAssertionSignature)); >+ EXPECT_EQ(memcmp(getAssertionResponse->signature()->data(), TestData::kCtap2GetAssertionSignature, sizeof(TestData::kCtap2GetAssertionSignature)), 0); >+} >+ >+TEST(CTAPResponseTest, TestReadGetAssertionResponse2) > { > auto getAssertionResponse = readCTAPGetAssertionResponse(convertBytesToVector(TestData::kDeviceGetAssertionResponse, sizeof(TestData::kDeviceGetAssertionResponse))); > ASSERT_TRUE(getAssertionResponse); >@@ -408,6 +419,24 @@ TEST(CTAPResponseTest, TestReadGetAssertionResponse) > EXPECT_EQ(memcmp(getAssertionResponse->authenticatorData()->data(), TestData::kCtap2GetAssertionAuthData, sizeof(TestData::kCtap2GetAssertionAuthData)), 0); > EXPECT_EQ(getAssertionResponse->signature()->byteLength(), sizeof(TestData::kCtap2GetAssertionSignature)); > EXPECT_EQ(memcmp(getAssertionResponse->signature()->data(), TestData::kCtap2GetAssertionSignature, sizeof(TestData::kCtap2GetAssertionSignature)), 0); >+ EXPECT_EQ(getAssertionResponse->userHandle()->byteLength(), sizeof(TestData::kCtap2GetAssertionUserHandle)); >+ EXPECT_EQ(memcmp(getAssertionResponse->userHandle()->data(), TestData::kCtap2GetAssertionUserHandle, sizeof(TestData::kCtap2GetAssertionUserHandle)), 0); >+} >+ >+TEST(CTAPResponseTest, TestReadGetAssertionResponse3) >+{ >+ auto getAssertionResponse = readCTAPGetAssertionResponse(convertBytesToVector(TestData::kDeviceGetAssertionResponseLong, sizeof(TestData::kDeviceGetAssertionResponseLong))); >+ ASSERT_TRUE(getAssertionResponse); >+ >+ EXPECT_EQ(getAssertionResponse->authenticatorData()->byteLength(), sizeof(TestData::kCtap2GetAssertionAuthData)); >+ EXPECT_EQ(memcmp(getAssertionResponse->authenticatorData()->data(), TestData::kCtap2GetAssertionAuthData, sizeof(TestData::kCtap2GetAssertionAuthData)), 0); >+ EXPECT_EQ(getAssertionResponse->signature()->byteLength(), sizeof(TestData::kCtap2GetAssertionSignature)); >+ EXPECT_EQ(memcmp(getAssertionResponse->signature()->data(), TestData::kCtap2GetAssertionSignature, sizeof(TestData::kCtap2GetAssertionSignature)), 0); >+ EXPECT_EQ(getAssertionResponse->userHandle()->byteLength(), sizeof(TestData::kCtap2GetAssertionUserHandle)); >+ EXPECT_EQ(memcmp(getAssertionResponse->userHandle()->data(), TestData::kCtap2GetAssertionUserHandle, sizeof(TestData::kCtap2GetAssertionUserHandle)), 0); >+ EXPECT_STREQ(getAssertionResponse->name().utf8().data(), "johnpsmith@example.com"); >+ EXPECT_STREQ(getAssertionResponse->displayName().utf8().data(), "John P. Smith"); >+ EXPECT_EQ(getAssertionResponse->numberOfCredentials(), 1u); > } > > // Test that U2F register response is properly parsed. >diff --git a/Tools/TestWebKitAPI/Tests/WebCore/FidoTestData.h b/Tools/TestWebKitAPI/Tests/WebCore/FidoTestData.h >index 3c2302b0a88b7219d9ec6adcd13ad7d7b7fedc61..9a704412402a05fae28a639dfefb3571c776116a 100644 >--- a/Tools/TestWebKitAPI/Tests/WebCore/FidoTestData.h >+++ b/Tools/TestWebKitAPI/Tests/WebCore/FidoTestData.h >@@ -960,7 +960,131 @@ constexpr uint8_t kCtap2GetAssertionSignature[] = { > 0x74, 0xc7, 0x47, 0x90, 0xea, 0xab, 0xb1, 0x44, 0x11, 0xe7, 0xa0, > }; > >+constexpr uint8_t kCtap2GetAssertionUserHandle[] = { >+ 0x30, 0x82, 0x01, 0x93, 0x30, 0x82, 0x01, 0x38, 0xa0, 0x03, 0x02, 0x01, >+ 0x02, 0x30, 0x82, 0x01, 0x93, 0x30, 0x82, 0x01, 0x38, 0xa0, 0x03, 0x02, >+ 0x01, 0x02, 0x30, 0x82, 0x01, 0x93, 0x30, 0x82, >+}; >+ >+constexpr uint8_t kDeviceGetAssertionResponseShort[] = { >+ // Success response code >+ 0x00, >+ // map(3) >+ 0xa3, >+ // unsigned(1) - Credential >+ 0x01, >+ // map(2) >+ 0xa2, >+ // text(2) >+ 0x62, >+ // "id" >+ 0x69, 0x64, >+ // bytes(64) >+ 0x58, 0x40, >+ // credential id >+ 0xf2, 0x20, 0x06, 0xde, 0x4f, 0x90, 0x5a, 0xf6, 0x8a, 0x43, 0x94, 0x2f, >+ 0x02, 0x4f, 0x2a, 0x5e, 0xce, 0x60, 0x3d, 0x9c, 0x6d, 0x4b, 0x3d, 0xf8, >+ 0xbe, 0x08, 0xed, 0x01, 0xfc, 0x44, 0x26, 0x46, 0xd0, 0x34, 0x85, 0x8a, >+ 0xc7, 0x5b, 0xed, 0x3f, 0xd5, 0x80, 0xbf, 0x98, 0x08, 0xd9, 0x4f, 0xcb, >+ 0xee, 0x82, 0xb9, 0xb2, 0xef, 0x66, 0x77, 0xaf, 0x0a, 0xdc, 0xc3, 0x58, >+ 0x52, 0xea, 0x6b, 0x9e, >+ // text(4) >+ 0x64, >+ // "type" >+ 0x74, 0x79, 0x70, 0x65, >+ // text(10) >+ 0x6a, >+ // "public-key" >+ 0x70, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x2D, 0x6B, 0x65, 0x79, >+ // unsigned(2) - Auth data >+ 0x02, >+ // bytes(37) >+ 0x58, 0x25, >+ // auth data >+ 0x62, 0x5d, 0xda, 0xdf, 0x74, 0x3f, 0x57, 0x27, 0xe6, 0x6b, 0xba, 0x8c, >+ 0x2e, 0x38, 0x79, 0x22, 0xd1, 0xaf, 0x43, 0xc5, 0x03, 0xd9, 0x11, 0x4a, >+ 0x8f, 0xba, 0x10, 0x4d, 0x84, 0xd0, 0x2b, 0xfa, 0x01, 0x00, 0x00, 0x00, >+ 0x11, >+ // unsigned(3) - signature >+ 0x03, >+ // bytes(71) >+ 0x58, 0x47, >+ // signature >+ 0x30, 0x45, 0x02, 0x20, 0x4a, 0x5a, 0x9d, 0xd3, 0x92, 0x98, 0x14, 0x9d, >+ 0x90, 0x47, 0x69, 0xb5, 0x1a, 0x45, 0x14, 0x33, 0x00, 0x6f, 0x18, 0x2a, >+ 0x34, 0xfb, 0xdf, 0x66, 0xde, 0x5f, 0xc7, 0x17, 0xd7, 0x5f, 0xb3, 0x50, >+ 0x02, 0x21, 0x00, 0xa4, 0x6b, 0x8e, 0xa3, 0xc3, 0xb9, 0x33, 0x82, 0x1c, >+ 0x6e, 0x7f, 0x5e, 0xf9, 0xda, 0xae, 0x94, 0xab, 0x47, 0xf1, 0x8d, 0xb4, >+ 0x74, 0xc7, 0x47, 0x90, 0xea, 0xab, 0xb1, 0x44, 0x11, 0xe7, 0xa0, >+}; >+ > constexpr uint8_t kDeviceGetAssertionResponse[] = { >+ // Success response code >+ 0x00, >+ // map(4) >+ 0xa4, >+ // unsigned(1) - Credential >+ 0x01, >+ // map(2) >+ 0xa2, >+ // text(2) >+ 0x62, >+ // "id" >+ 0x69, 0x64, >+ // bytes(64) >+ 0x58, 0x40, >+ // credential id >+ 0xf2, 0x20, 0x06, 0xde, 0x4f, 0x90, 0x5a, 0xf6, 0x8a, 0x43, 0x94, 0x2f, >+ 0x02, 0x4f, 0x2a, 0x5e, 0xce, 0x60, 0x3d, 0x9c, 0x6d, 0x4b, 0x3d, 0xf8, >+ 0xbe, 0x08, 0xed, 0x01, 0xfc, 0x44, 0x26, 0x46, 0xd0, 0x34, 0x85, 0x8a, >+ 0xc7, 0x5b, 0xed, 0x3f, 0xd5, 0x80, 0xbf, 0x98, 0x08, 0xd9, 0x4f, 0xcb, >+ 0xee, 0x82, 0xb9, 0xb2, 0xef, 0x66, 0x77, 0xaf, 0x0a, 0xdc, 0xc3, 0x58, >+ 0x52, 0xea, 0x6b, 0x9e, >+ // text(4) >+ 0x64, >+ // "type" >+ 0x74, 0x79, 0x70, 0x65, >+ // text(10) >+ 0x6a, >+ // "public-key" >+ 0x70, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x2D, 0x6B, 0x65, 0x79, >+ // unsigned(2) - Auth data >+ 0x02, >+ // bytes(37) >+ 0x58, 0x25, >+ // auth data >+ 0x62, 0x5d, 0xda, 0xdf, 0x74, 0x3f, 0x57, 0x27, 0xe6, 0x6b, 0xba, 0x8c, >+ 0x2e, 0x38, 0x79, 0x22, 0xd1, 0xaf, 0x43, 0xc5, 0x03, 0xd9, 0x11, 0x4a, >+ 0x8f, 0xba, 0x10, 0x4d, 0x84, 0xd0, 0x2b, 0xfa, 0x01, 0x00, 0x00, 0x00, >+ 0x11, >+ // unsigned(3) - signature >+ 0x03, >+ // bytes(71) >+ 0x58, 0x47, >+ // signature >+ 0x30, 0x45, 0x02, 0x20, 0x4a, 0x5a, 0x9d, 0xd3, 0x92, 0x98, 0x14, 0x9d, >+ 0x90, 0x47, 0x69, 0xb5, 0x1a, 0x45, 0x14, 0x33, 0x00, 0x6f, 0x18, 0x2a, >+ 0x34, 0xfb, 0xdf, 0x66, 0xde, 0x5f, 0xc7, 0x17, 0xd7, 0x5f, 0xb3, 0x50, >+ 0x02, 0x21, 0x00, 0xa4, 0x6b, 0x8e, 0xa3, 0xc3, 0xb9, 0x33, 0x82, 0x1c, >+ 0x6e, 0x7f, 0x5e, 0xf9, 0xda, 0xae, 0x94, 0xab, 0x47, 0xf1, 0x8d, 0xb4, >+ 0x74, 0xc7, 0x47, 0x90, 0xea, 0xab, 0xb1, 0x44, 0x11, 0xe7, 0xa0, >+ // unsigned(4) - publicKeyCredentialUserEntity >+ 0x04, >+ // map(1) >+ 0xa1, >+ // text(2) >+ 0x62, >+ // "id" >+ 0x69, 0x64, >+ // bytes(32) - user id >+ 0x58, 0x20, >+ // user id >+ 0x30, 0x82, 0x01, 0x93, 0x30, 0x82, 0x01, 0x38, 0xa0, 0x03, 0x02, 0x01, >+ 0x02, 0x30, 0x82, 0x01, 0x93, 0x30, 0x82, 0x01, 0x38, 0xa0, 0x03, 0x02, >+ 0x01, 0x02, 0x30, 0x82, 0x01, 0x93, 0x30, 0x82, >+}; >+ >+constexpr uint8_t kDeviceGetAssertionResponseLong[] = { > // Success response code > 0x00, > // map(5) >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index d170ad9dddb593daa70f0d84ca5727b9d59bc6bf..fc463b7aad40740dccbaf1eac933554252ba2733 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,17 @@ >+2020-01-09 Jiewen Tan <jiewen_tan@apple.com> >+ >+ [WebAuthn] Support authenticatorGetNextAssertion >+ https://bugs.webkit.org/show_bug.cgi?id=203346 >+ <rdar://problem/56558488> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * 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-hid.https-expected.txt: >+ * http/wpt/webauthn/public-key-credential-get-success-hid.https.html: >+ * http/wpt/webauthn/resources/util.js: >+ > 2020-01-06 Per Arne Vollan <pvollan@apple.com> > > [iOS] Issue mach lookup extension to launch services daemon for Mail >diff --git a/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid.https-expected.txt b/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid.https-expected.txt >index 54bb50867c923cda6fa97b7ace7e004ac895cf0e..c84c54f8ec7b474ea0a7ee5cd64861621cbbb681 100644 >--- a/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid.https-expected.txt >+++ b/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid.https-expected.txt >@@ -5,4 +5,5 @@ PASS PublicKeyCredential's [[get]] with unsupported options in a mock hid authen > PASS PublicKeyCredential's [[get]] with authenticator downgrade failed in a mock hid authenticator. > PASS PublicKeyCredential's [[get]] with authenticator downgrade failed in a mock hid authenticator. 2 > PASS PublicKeyCredential's [[get]] with authenticator downgrade succeeded and then U2F failed in a mock hid authenticator. >+PASS PublicKeyCredential's [[get]] with getNextAssertion failed in a mock hid authenticator. > >diff --git a/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid.https.html b/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid.https.html >index 68e3ce20a7518ee52d2e189fa7e25a24c5895c0e..b17f726f6c068ae1abff5cc4fa1d08af5417555b 100644 >--- a/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid.https.html >+++ b/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid.https.html >@@ -84,4 +84,16 @@ > internals.setMockWebAuthenticationConfiguration({ hid: { stage: "request", subStage: "msg", error: "malicious-payload", canDowngrade: true, payloadBase64: [testCtapErrInvalidCredentialResponseBase64, testU2fApduNoErrorOnlyResponseBase64] } }); > return promiseRejects(t, "UnknownError", navigator.credentials.get(options), "Unknown internal error. Error code: 34"); > }, "PublicKeyCredential's [[get]] with authenticator downgrade succeeded and then U2F failed in a mock hid authenticator."); >+ >+ promise_test(function(t) { >+ const options = { >+ publicKey: { >+ challenge: asciiToUint8Array("123456") >+ } >+ }; >+ >+ if (window.internals) >+ internals.setMockWebAuthenticationConfiguration({ hid: { stage: "request", subStage: "msg", error: "malicious-payload", payloadBase64: [testAssertionMessageLongBase64, testCtapErrNotAllowedResponseBase64] } }); >+ return promiseRejects(t, "UnknownError", navigator.credentials.get(options), "Unknown internal error. Error code: 48"); >+ }, "PublicKeyCredential's [[get]] with getNextAssertion failed in a mock hid authenticator."); > </script> >diff --git a/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-hid.https-expected.txt b/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-hid.https-expected.txt >index 43c306cb015699d2f2207d9bec6f1014adf1fe97..673910745a7ab46a7dc545ecfaf71cbe5ab85c2d 100644 >--- a/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-hid.https-expected.txt >+++ b/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-hid.https-expected.txt >@@ -5,4 +5,5 @@ PASS PublicKeyCredential's [[get]] with userVerification { preferred } in a mock > PASS PublicKeyCredential's [[get]] with userVerification { discouraged } in a mock hid authenticator. > PASS PublicKeyCredential's [[get]] with mixed options in a mock hid authenticator. > PASS PublicKeyCredential's [[get]] with two consecutive requests. >+PASS PublicKeyCredential's [[get]] with multiple accounts in a mock hid authenticator. > >diff --git a/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-hid.https.html b/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-hid.https.html >index d2843d58d2a9530b4f92a4f1862576bdc0c3a175..ec9d6fc28f4f199b878425959cbf12bbdb257f42 100644 >--- a/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-hid.https.html >+++ b/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-hid.https.html >@@ -101,4 +101,19 @@ > return checkCtapGetAssertionResult(credential); > }); > }, "PublicKeyCredential's [[get]] with two consecutive requests."); >+ >+ promise_test(t => { >+ const options = { >+ publicKey: { >+ challenge: Base64URL.parse("MTIzNDU2"), >+ timeout: 100 >+ } >+ }; >+ >+ if (window.internals) >+ internals.setMockWebAuthenticationConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", payloadBase64: [testAssertionMessageLongBase64, testAssertionMessageLongBase64] } }); >+ return navigator.credentials.get(options).then(credential => { >+ return checkCtapGetAssertionResult(credential, "MIIBkzCCATigAwIBAjCCAZMwggE4oAMCAQIwggGTMII="); >+ }); >+ }, "PublicKeyCredential's [[get]] with multiple accounts in a mock hid authenticator."); > </script> >diff --git a/LayoutTests/http/wpt/webauthn/resources/util.js b/LayoutTests/http/wpt/webauthn/resources/util.js >index 6efde8a8a5fa6830418df1a2562a0d357b27e1a2..61d8f725ff2b5178aea18388a7550e3a256369cd 100644 >--- a/LayoutTests/http/wpt/webauthn/resources/util.js >+++ b/LayoutTests/http/wpt/webauthn/resources/util.js >@@ -66,6 +66,15 @@ const testAssertionMessageBase64 = > "Z51VstuQkuHI2eXh0Ct1gPC0gSx3CWLh5I9a2AEAAABQA1hHMEUCIQCSFTuuBWgB" + > "4/F0VB7DlUVM09IHPmxe1MzHUwRoCRZbCAIgGKov6xoAx2MEf6/6qNs8OutzhP2C" + > "QoJ1L7Fe64G9uBc="; >+const testAssertionMessageLongBase64 = >+ "AKUBomJpZFhAKAitzuj+Tslzelf3/vZwIGtDQNgoKeFd5oEieYzhyzA65saf0tK2" + >+ "w/mooa7tQtGgDdwZIjOhjcuZ0pQ1ajoE4GR0eXBlanB1YmxpYy1rZXkCWCVGzH+5" + >+ "Z51VstuQkuHI2eXh0Ct1gPC0gSx3CWLh5I9a2AEAAABQA1hHMEUCIQCSFTuuBWgB" + >+ "4/F0VB7DlUVM09IHPmxe1MzHUwRoCRZbCAIgGKov6xoAx2MEf6/6qNs8OutzhP2C" + >+ "QoJ1L7Fe64G9uBcEpGJpZFggMIIBkzCCATigAwIBAjCCAZMwggE4oAMCAQIwggGT" + >+ "MIJkaWNvbngoaHR0cHM6Ly9waWNzLmFjbWUuY29tLzAwL3AvYUJqampwcVBiLnBu" + >+ "Z2RuYW1ldmpvaG5wc21pdGhAZXhhbXBsZS5jb21rZGlzcGxheU5hbWVtSm9obiBQ" + >+ "LiBTbWl0aAUC"; > const testU2fApduNoErrorOnlyResponseBase64 = "kAA="; > const testU2fApduInsNotSupportedOnlyResponseBase64 = "bQA="; > const testU2fApduWrongDataOnlyResponseBase64 = "aoA="; >@@ -96,6 +105,7 @@ const testU2fSignResponse = > "f4V4LeEAhqeD0effTjY553H19q+jWq1Tc4WOkAA="; > const testCtapErrCredentialExcludedOnlyResponseBase64 = "GQ=="; > const testCtapErrInvalidCredentialResponseBase64 = "Ig=="; >+const testCtapErrNotAllowedResponseBase64 = "MA=="; > const testNfcU2fVersionBase64 = "VTJGX1YykAA="; > const testNfcCtapVersionBase64 = "RklET18yXzCQAA=="; > const testGetInfoResponseApduBase64 = >@@ -394,14 +404,17 @@ function checkU2fMakeCredentialResult(credential, isNoneAttestation = true) > assert_equals(attestationObject.attStmt.x5c.length, 1); > } > >-function checkCtapGetAssertionResult(credential) >+function checkCtapGetAssertionResult(credential, userHandleBase64 = null) > { > // Check respond > assert_array_equals(Base64URL.parse(credential.id), Base64URL.parse(testHidCredentialIdBase64)); > assert_equals(credential.type, 'public-key'); > assert_array_equals(new Uint8Array(credential.rawId), Base64URL.parse(testHidCredentialIdBase64)); > assert_equals(bytesToASCIIString(credential.response.clientDataJSON), '{"type":"webauthn.get","challenge":"MTIzNDU2","origin":"https://localhost:9443"}'); >- assert_equals(credential.response.userHandle, null); >+ if (userHandleBase64 == null) >+ assert_equals(credential.response.userHandle, null); >+ else >+ assert_array_equals(new Uint8Array(credential.response.userHandle), Base64URL.parse(userHandleBase64)); > assert_not_own_property(credential.getClientExtensionResults(), "appid"); > > // Check authData
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 203346
:
387260
| 387273