Changeset 245500 in webkit
- Timestamp:
- May 18, 2019, 5:42:16 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 19 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid-silent.https-expected.txt (modified) (1 diff)
-
LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid-silent.https.html (modified) (1 diff)
-
LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid.https-expected.txt (modified) (1 diff)
-
LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid.https.html (modified) (2 diffs)
-
LayoutTests/http/wpt/webauthn/public-key-credential-get-success-u2f.https-expected.txt (modified) (1 diff)
-
LayoutTests/http/wpt/webauthn/public-key-credential-get-success-u2f.https.html (modified) (1 diff)
-
LayoutTests/http/wpt/webauthn/resources/util.js (modified) (1 diff)
-
Source/WebKit/ChangeLog (modified) (1 diff)
-
Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp (modified) (1 diff)
-
Source/WebKit/UIProcess/WebAuthentication/Authenticator.h (modified) (1 diff)
-
Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp (modified) (1 diff)
-
Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h (modified) (1 diff)
-
Source/WebKit/UIProcess/WebAuthentication/Mock/MockHidConnection.cpp (modified) (2 diffs)
-
Source/WebKit/UIProcess/WebAuthentication/Mock/MockWebAuthenticationConfiguration.h (modified) (1 diff)
-
Source/WebKit/UIProcess/WebAuthentication/fido/CtapHidAuthenticator.cpp (modified) (5 diffs)
-
Source/WebKit/UIProcess/WebAuthentication/fido/CtapHidAuthenticator.h (modified) (1 diff)
-
Tools/ChangeLog (modified) (1 diff)
-
Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r245494 r245500 1 2019-05-18 Jiewen Tan <jiewen_tan@apple.com> 2 3 [WebAuthN] Allow authenticators that support both CTAP and U2F to try U2F if CTAP fails in authenticatorGetAssertion 4 https://bugs.webkit.org/show_bug.cgi?id=197974 5 <rdar://problem/50879746> 6 7 Reviewed by Brent Fulgham. 8 9 * http/wpt/webauthn/public-key-credential-get-failure-hid-silent.https-expected.txt: 10 * http/wpt/webauthn/public-key-credential-get-failure-hid-silent.https.html: 11 * http/wpt/webauthn/public-key-credential-get-failure-hid.https-expected.txt: 12 * http/wpt/webauthn/public-key-credential-get-failure-hid.https.html: 13 * http/wpt/webauthn/public-key-credential-get-success-u2f.https-expected.txt: 14 * http/wpt/webauthn/public-key-credential-get-success-u2f.https.html: 15 * http/wpt/webauthn/resources/util.js: 16 1 17 2019-05-17 Joonghun Park <pjh0718@gmail.com> 2 18 -
trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid-silent.https-expected.txt
r238166 r245500 2 2 PASS PublicKeyCredential's [[get]] with malicious payload in a mock hid authenticator. 3 3 PASS PublicKeyCredential's [[get]] with unsupported options in a mock hid authenticator. 4 PASS PublicKeyCredential's [[get]] with invalid credential in a mock hid authenticator. 5 PASS PublicKeyCredential's [[get]] with authenticator downgrade in a mock hid authenticator. 6 PASS PublicKeyCredential's [[get]] with authenticator downgrade in a mock hid authenticator. 2 4 7 -
trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid-silent.https.html
r239752 r245500 31 31 return promiseRejects(t, "NotAllowedError", navigator.credentials.get(options), "Operation timed out."); 32 32 }, "PublicKeyCredential's [[get]] with unsupported options in a mock hid authenticator."); 33 34 promise_test(function(t) { 35 const options = { 36 publicKey: { 37 challenge: asciiToUint8Array("123456"), 38 timeout: 10 39 } 40 }; 41 42 if (window.testRunner) 43 testRunner.setWebAuthenticationMockConfiguration({ silentFailure: true, hid: { stage: "request", subStage: "msg", error: "malicious-payload", payloadBase64: [testCtapErrInvalidCredentialResponseBase64] } }); 44 return promiseRejects(t, "NotAllowedError", navigator.credentials.get(options), "Operation timed out."); 45 }, "PublicKeyCredential's [[get]] with invalid credential in a mock hid authenticator."); 46 47 promise_test(function(t) { 48 const options = { 49 publicKey: { 50 challenge: asciiToUint8Array("123456"), 51 timeout: 10 52 } 53 }; 54 55 if (window.testRunner) 56 testRunner.setWebAuthenticationMockConfiguration({ silentFailure: true, hid: { stage: "request", subStage: "msg", error: "malicious-payload", canDowngrade: true, payloadBase64: [testCtapErrInvalidCredentialResponseBase64] } }); 57 return promiseRejects(t, "NotAllowedError", navigator.credentials.get(options), "Operation timed out."); 58 }, "PublicKeyCredential's [[get]] with authenticator downgrade in a mock hid authenticator."); 59 60 promise_test(function(t) { 61 const options = { 62 publicKey: { 63 challenge: asciiToUint8Array("123456"), 64 extensions: { appid: "" }, 65 timeout: 10 66 } 67 }; 68 69 if (window.testRunner) 70 testRunner.setWebAuthenticationMockConfiguration({ silentFailure: true, hid: { stage: "request", subStage: "msg", error: "malicious-payload", canDowngrade: true, payloadBase64: [testCtapErrInvalidCredentialResponseBase64] } }); 71 return promiseRejects(t, "NotAllowedError", navigator.credentials.get(options), "Operation timed out."); 72 }, "PublicKeyCredential's [[get]] with authenticator downgrade in a mock hid authenticator. 2"); 33 73 </script> -
trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid.https-expected.txt
r238166 r245500 3 3 PASS PublicKeyCredential's [[get]] with malicious payload in a mock hid authenticator. 4 4 PASS PublicKeyCredential's [[get]] with unsupported options in a mock hid authenticator. 5 PASS PublicKeyCredential's [[get]] with authenticator downgrade failed in a mock hid authenticator. 6 PASS PublicKeyCredential's [[get]] with authenticator downgrade succeeded and then U2F failed in a mock hid authenticator. 2 5 7 -
trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-failure-hid.https.html
r239752 r245500 34 34 if (window.testRunner) 35 35 testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "malicious-payload", payloadBase64: [testDummyMessagePayloadBase64] } }); 36 return promiseRejects(t, "UnknownError", navigator.credentials.get(options), "Unknown internal error. Error code: -1");36 return promiseRejects(t, "UnknownError", navigator.credentials.get(options), "Unknown internal error. Error code: 255"); 37 37 }, "PublicKeyCredential's [[get]] with malicious payload in a mock hid authenticator."); 38 38 … … 49 49 return promiseRejects(t, "UnknownError", navigator.credentials.get(options), "Unknown internal error. Error code: 43"); 50 50 }, "PublicKeyCredential's [[get]] with unsupported options in a mock hid authenticator."); 51 52 promise_test(function(t) { 53 const options = { 54 publicKey: { 55 challenge: asciiToUint8Array("123456") 56 } 57 }; 58 59 if (window.testRunner) 60 testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "malicious-payload", payloadBase64: [testCtapErrInvalidCredentialResponseBase64] } }); 61 return promiseRejects(t, "UnknownError", navigator.credentials.get(options), "Unknown internal error. Error code: 34"); 62 }, "PublicKeyCredential's [[get]] with authenticator downgrade failed in a mock hid authenticator."); 63 64 promise_test(function(t) { 65 const options = { 66 publicKey: { 67 challenge: asciiToUint8Array("123456"), 68 extensions: { appid: "" } 69 } 70 }; 71 72 if (window.testRunner) 73 testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "malicious-payload", canDowngrade: true, payloadBase64: [testCtapErrInvalidCredentialResponseBase64] } }); 74 return promiseRejects(t, "NotSupportedError", navigator.credentials.get(options), "Cannot convert the request to U2F command."); 75 }, "PublicKeyCredential's [[get]] with authenticator downgrade succeeded and then U2F failed in a mock hid authenticator. 2"); 51 76 </script> -
trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-u2f.https-expected.txt
r243193 r245500 9 9 PASS PublicKeyCredential's [[get]] with multiple credentials and AppID is not used in a mock hid authenticator. 10 10 PASS PublicKeyCredential's [[get]] with multiple credentials and AppID is used in a mock hid authenticator. 11 PASS PublicKeyCredential's [[get]] with downgraded authenticator in a mock hid authenticator. 12 PASS PublicKeyCredential's [[get]] with downgraded authenticator in a mock hid authenticator. (AppID) 11 13 -
trunk/LayoutTests/http/wpt/webauthn/public-key-credential-get-success-u2f.https.html
r243193 r245500 182 182 }, "PublicKeyCredential's [[get]] with multiple credentials and AppID is used in a mock hid authenticator."); 183 183 184 promise_test(t => { 185 const options = { 186 publicKey: { 187 challenge: Base64URL.parse("MTIzNDU2"), 188 allowCredentials: [{ type: "public-key", id: Base64URL.parse(testU2fCredentialIdBase64) }], 189 timeout: 100, 190 extensions: { appid: "https://localhost:666/appid" } 191 } 192 }; 193 194 if (window.testRunner) 195 testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", canDowngrade: true, payloadBase64: [testCtapErrInvalidCredentialResponseBase64, testU2fSignResponse] } }); 196 return navigator.credentials.get(options).then(credential => { 197 return checkResult(credential); 198 }); 199 }, "PublicKeyCredential's [[get]] with downgraded authenticator in a mock hid authenticator."); 200 201 promise_test(t => { 202 const options = { 203 publicKey: { 204 challenge: Base64URL.parse("MTIzNDU2"), 205 allowCredentials: [{ type: "public-key", id: Base64URL.parse(testU2fCredentialIdBase64) }], 206 timeout: 100, 207 extensions: { appid: "https://localhost:666/appid" } 208 } 209 }; 210 211 if (window.testRunner) 212 testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "request", subStage: "msg", error: "success", canDowngrade: true, payloadBase64: [testCtapErrInvalidCredentialResponseBase64, testU2fApduWrongDataOnlyResponseBase64, testU2fSignResponse] } }); 213 return navigator.credentials.get(options).then(credential => { 214 return checkResult(credential, true, "7eabc5cc3251bdc59115ef87b5f7ee74cb03747e39ba8341748565cc129c0719"); 215 }); 216 }, "PublicKeyCredential's [[get]] with downgraded authenticator in a mock hid authenticator. (AppID)"); 217 184 218 </script> -
trunk/LayoutTests/http/wpt/webauthn/resources/util.js
r245262 r245500 99 99 "f4V4LeEAhqeD0effTjY553H19q+jWq1Tc4WOkAA="; 100 100 const testCtapErrCredentialExcludedOnlyResponseBase64 = "GQ=="; 101 const testCtapErrInvalidCredentialResponseBase64 = "Ig=="; 101 102 102 103 const RESOURCES_DIR = "/WebKit/webauthn/resources/"; -
trunk/Source/WebKit/ChangeLog
r245492 r245500 1 2019-05-18 Jiewen Tan <jiewen_tan@apple.com> 2 3 [WebAuthN] Allow authenticators that support both CTAP and U2F to try U2F if CTAP fails in authenticatorGetAssertion 4 https://bugs.webkit.org/show_bug.cgi?id=197974 5 <rdar://problem/50879746> 6 7 Reviewed by Brent Fulgham. 8 9 Authenticators that support both CTAP and U2F protocols can be used in a U2F enabled browser to create a credential in 10 U2F format. When such authenticator is used to login in WebKit, it will be treated as a CTAP authenticator. Since the 11 previous credential is in U2F format, the authenticator will not consider that as a valid credential when CTAP requests 12 come along for that U2F credential. Therefore the previous created U2F credential will not be asked at all, and users 13 will not be able to login. This situation is not well documented in the CTAP/WebAuthN spec yet. 14 15 To workaround the above issue, an authenticator that supports both protocols will be downgraded to a U2F authenticator 16 to ask a potential U2F credential once a valid error is returned regarding to the first CTAP request. 17 18 * UIProcess/API/C/WKWebsiteDataStoreRef.cpp: 19 (WKWebsiteDataStoreSetWebAuthenticationMockConfiguration): 20 * UIProcess/WebAuthentication/Authenticator.h: 21 * UIProcess/WebAuthentication/AuthenticatorManager.cpp: 22 (WebKit::AuthenticatorManager::downgrade): 23 * UIProcess/WebAuthentication/AuthenticatorManager.h: 24 * UIProcess/WebAuthentication/Mock/MockHidConnection.cpp: 25 (WebKit::MockHidConnection::parseRequest): 26 (WebKit::MockHidConnection::feedReports): 27 * UIProcess/WebAuthentication/Mock/MockWebAuthenticationConfiguration.h: 28 * UIProcess/WebAuthentication/fido/CtapHidAuthenticator.cpp: 29 (WebKit::CtapHidAuthenticator::makeCredential): 30 (WebKit::CtapHidAuthenticator::getAssertion): 31 (WebKit::CtapHidAuthenticator::continueGetAssertionAfterResponseReceived): 32 (WebKit::CtapHidAuthenticator::tryDowngrade): 33 (WebKit::CtapHidAuthenticator::continueGetAssertionAfterResponseReceived const): Deleted. 34 * UIProcess/WebAuthentication/fido/CtapHidAuthenticator.h: 35 1 36 2019-05-17 Don Olmstead <don.olmstead@sony.com> 2 37 -
trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp
r244572 r245500 653 653 hid.continueAfterErrorData = WKBooleanGetValue(continueAfterErrorData); 654 654 655 if (auto canDowngrade = static_cast<WKBooleanRef>(WKDictionaryGetItemForKey(hidRef, adoptWK(WKStringCreateWithUTF8CString("CanDowngrade")).get()))) 656 hid.canDowngrade = WKBooleanGetValue(canDowngrade); 657 655 658 configuration.hid = WTFMove(hid); 656 659 } -
trunk/Source/WebKit/UIProcess/WebAuthentication/Authenticator.h
r236481 r245500 45 45 virtual ~Observer() = default; 46 46 virtual void respondReceived(Respond&&) = 0; 47 virtual void downgrade(Authenticator* id, Ref<Authenticator>&& downgradedAuthenticator) = 0; 47 48 }; 48 49 -
trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp
r245262 r245500 209 209 } 210 210 211 void AuthenticatorManager::downgrade(Authenticator* id, Ref<Authenticator>&& downgradedAuthenticator) 212 { 213 RunLoop::main().dispatch([weakThis = makeWeakPtr(*this), id] { 214 if (!weakThis) 215 return; 216 auto removed = weakThis->m_authenticators.remove(id); 217 ASSERT_UNUSED(removed, removed); 218 }); 219 authenticatorAdded(WTFMove(downgradedAuthenticator)); 220 } 221 211 222 UniqueRef<AuthenticatorTransportService> AuthenticatorManager::createService(WebCore::AuthenticatorTransport transport, AuthenticatorTransportService::Observer& observer) const 212 223 { -
trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h
r245043 r245500 71 71 // Authenticator::Observer 72 72 void respondReceived(Respond&&) final; 73 void downgrade(Authenticator* id, Ref<Authenticator>&& downgradedAuthenticator) final; 73 74 74 75 // Overriden by MockAuthenticatorManager. -
trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockHidConnection.cpp
r239852 r245500 133 133 if (m_stage == Mock::Stage::Request && m_subStage == Mock::SubStage::Msg) { 134 134 // Make sure we issue different msg cmd for CTAP and U2F. 135 if (m_configuration.hid->canDowngrade && !m_configuration.hid->isU2f) 136 m_configuration.hid->isU2f = m_requestMessage->cmd() == FidoHidDeviceCommand::kMsg; 135 137 ASSERT(m_configuration.hid->isU2f ^ (m_requestMessage->cmd() != FidoHidDeviceCommand::kMsg)); 136 138 … … 209 211 Optional<FidoHidMessage> message; 210 212 if (m_stage == Mock::Stage::Info && m_subStage == Mock::SubStage::Msg) { 211 auto infoData = encodeAsCBOR(AuthenticatorGetInfoResponse({ ProtocolVersion::kCtap }, Vector<uint8_t>(aaguidLength, 0u))); 213 Vector<uint8_t> infoData; 214 if (m_configuration.hid->canDowngrade) 215 infoData = encodeAsCBOR(AuthenticatorGetInfoResponse({ ProtocolVersion::kCtap, ProtocolVersion::kU2f }, Vector<uint8_t>(aaguidLength, 0u))); 216 else 217 infoData = encodeAsCBOR(AuthenticatorGetInfoResponse({ ProtocolVersion::kCtap }, Vector<uint8_t>(aaguidLength, 0u))); 212 218 infoData.insert(0, static_cast<uint8_t>(CtapDeviceResponseCode::kSuccess)); // Prepend status code. 213 219 if (stagesMatch() && m_configuration.hid->error == Mock::Error::WrongChannelId) -
trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockWebAuthenticationConfiguration.h
r239752 r245500 70 70 bool fastDataArrival { false }; 71 71 bool continueAfterErrorData { false }; 72 bool canDowngrade { false }; 72 73 }; 73 74 -
trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapHidAuthenticator.cpp
r245262 r245500 30 30 31 31 #include "CtapHidDriver.h" 32 #include "U2fHidAuthenticator.h" 32 33 #include <WebCore/DeviceRequestConverter.h> 33 34 #include <WebCore/DeviceResponseConverter.h> … … 50 51 void CtapHidAuthenticator::makeCredential() 51 52 { 53 ASSERT(!m_isDowngraded); 52 54 auto cborCmd = encodeMakeCredenitalRequestAsCBOR(requestData().hash, requestData().creationOptions, m_info.options().userVerificationAvailability()); 53 55 m_driver->transact(WTFMove(cborCmd), [weakThis = makeWeakPtr(*this)](Vector<uint8_t>&& data) { … … 75 77 void CtapHidAuthenticator::getAssertion() 76 78 { 79 ASSERT(!m_isDowngraded); 77 80 auto cborCmd = encodeGetAssertionRequestAsCBOR(requestData().hash, requestData().requestOptions, m_info.options().userVerificationAvailability()); 78 81 m_driver->transact(WTFMove(cborCmd), [weakThis = makeWeakPtr(*this)](Vector<uint8_t>&& data) { … … 84 87 } 85 88 86 void CtapHidAuthenticator::continueGetAssertionAfterResponseReceived(Vector<uint8_t>&& data) const89 void CtapHidAuthenticator::continueGetAssertionAfterResponseReceived(Vector<uint8_t>&& data) 87 90 { 88 91 auto response = readCTAPGetAssertionResponse(data); 89 92 if (!response) { 90 receiveRespond(ExceptionData { UnknownError, makeString("Unknown internal error. Error code: ", data.size() == 1 ? data[0] : -1) }); 93 auto error = getResponseCode(data); 94 if (error != CtapDeviceResponseCode::kCtap2ErrInvalidCBOR && tryDowngrade()) 95 return; 96 receiveRespond(ExceptionData { UnknownError, makeString("Unknown internal error. Error code: ", static_cast<uint8_t>(error)) }); 91 97 return; 92 98 } … … 94 100 } 95 101 102 bool CtapHidAuthenticator::tryDowngrade() 103 { 104 if (m_info.versions().find(ProtocolVersion::kU2f) == m_info.versions().end()) 105 return false; 106 if (!observer()) 107 return false; 108 109 m_isDowngraded = true; 110 m_driver->setProtocol(ProtocolVersion::kU2f); 111 observer()->downgrade(this, U2fHidAuthenticator::create(WTFMove(m_driver))); 112 return true; 113 } 114 96 115 } // namespace WebKit 97 116 -
trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapHidAuthenticator.h
r238247 r245500 48 48 void continueMakeCredentialAfterResponseReceived(Vector<uint8_t>&&) const; 49 49 void getAssertion() final; 50 void continueGetAssertionAfterResponseReceived(Vector<uint8_t>&&) const; 50 void continueGetAssertionAfterResponseReceived(Vector<uint8_t>&&); 51 52 bool tryDowngrade(); 51 53 52 54 std::unique_ptr<CtapHidDriver> m_driver; 53 55 fido::AuthenticatorGetInfoResponse m_info; 56 bool m_isDowngraded { false }; 54 57 }; 55 58 -
trunk/Tools/ChangeLog
r245499 r245500 1 2019-05-18 Jiewen Tan <jiewen_tan@apple.com> 2 3 [WebAuthN] Allow authenticators that support both CTAP and U2F to try U2F if CTAP fails in authenticatorGetAssertion 4 https://bugs.webkit.org/show_bug.cgi?id=197974 5 <rdar://problem/50879746> 6 7 Reviewed by Brent Fulgham. 8 9 Add a canDowngrade option for mock hid devices to simulate the situation. 10 11 * WebKitTestRunner/InjectedBundle/TestRunner.cpp: 12 (WTR::TestRunner::setWebAuthenticationMockConfiguration): 13 1 14 2019-05-18 Tadeu Zagallo <tzagallo@apple.com> 2 15 -
trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp
r244898 r245500 2693 2693 } 2694 2694 2695 JSRetainPtr<JSStringRef> canDowngradePropertyName(Adopt, JSStringCreateWithUTF8CString("canDowngrade")); 2696 JSValueRef canDowngradeValue = JSObjectGetProperty(context, hid, canDowngradePropertyName.get(), 0); 2697 if (!JSValueIsUndefined(context, canDowngradeValue) && !JSValueIsNull(context, canDowngradeValue)) { 2698 if (!JSValueIsBoolean(context, canDowngradeValue)) 2699 return; 2700 bool canDowngrade = JSValueToBoolean(context, canDowngradeValue); 2701 hidKeys.append(adoptWK(WKStringCreateWithUTF8CString("CanDowngrade"))); 2702 hidValues.append(adoptWK(WKBooleanCreate(canDowngrade)).get()); 2703 } 2704 2695 2705 Vector<WKStringRef> rawHidKeys; 2696 2706 Vector<WKTypeRef> rawHidValues;
Note:
See TracChangeset
for help on using the changeset viewer.