Changeset 238246 in webkit
- Timestamp:
- Nov 15, 2018 1:24:51 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r238245 r238246 1 2018-11-15 Jiewen Tan <jiewen_tan@apple.com> 2 3 [WebAuthN] Use a real nonce for CTAPHID_INIT 4 https://bugs.webkit.org/show_bug.cgi?id=191533 5 <rdar://problem/46103502> 6 7 Reviewed by Brent Fulgham. 8 9 * http/wpt/webauthn/ctap-hid-failure.https-expected.txt: 10 * http/wpt/webauthn/ctap-hid-failure.https.html: 11 * http/wpt/webauthn/ctap-hid-success.https-expected.txt: 12 * http/wpt/webauthn/ctap-hid-success.https.html: 13 1 14 2018-11-15 Justin Fan <justin_fan@apple.com> 2 15 -
trunk/LayoutTests/http/wpt/webauthn/ctap-hid-failure.https-expected.txt
r238166 r238246 3 3 PASS CTAP HID with init sub stage empty report error in a mock hid authenticator. 4 4 PASS CTAP HID with init sub stage wrong channel id error in a mock hid authenticator. 5 PASS CTAP HID with init sub stage wrong nonce error in a mock hid authenticator. 5 6 PASS CTAP HID with msg sub stage data not sent error in a mock hid authenticator. 6 7 PASS CTAP HID with msg sub stage empty report error in a mock hid authenticator. -
trunk/LayoutTests/http/wpt/webauthn/ctap-hid-failure.https.html
r238166 r238246 41 41 promise_test(function(t) { 42 42 if (window.testRunner) 43 testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "info", subStage: "init", error: "wrong-nonce" } }); 44 return promiseRejects(t, "NotAllowedError", navigator.credentials.create(defaultOptions), "Operation timed out."); 45 }, "CTAP HID with init sub stage wrong nonce error in a mock hid authenticator."); 46 47 promise_test(function(t) { 48 if (window.testRunner) 43 49 testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "info", subStage: "msg", error: "data-not-sent" } }); 44 50 return promiseRejects(t, "NotAllowedError", navigator.credentials.create(defaultOptions), "Operation timed out."); -
trunk/LayoutTests/http/wpt/webauthn/ctap-hid-success.https-expected.txt
r238166 r238246 4 4 PASS CTAP HID with continue after empty report in a mock hid authenticator. 5 5 PASS CTAP HID with continue after wrong channel id in a mock hid authenticator. 6 PASS CTAP HID with continue after wrong nonce error in a mock hid authenticator. 6 7 -
trunk/LayoutTests/http/wpt/webauthn/ctap-hid-success.https.html
r238166 r238246 55 55 }); 56 56 }, "CTAP HID with continue after wrong channel id in a mock hid authenticator."); 57 58 promise_test(function(t) { 59 if (window.testRunner) 60 testRunner.setWebAuthenticationMockConfiguration({ hid: { stage: "info", subStage: "init", error: "wrong-nonce", payloadBase64: testCreationMessageBase64, continueAfterErrorData: true } }); 61 return navigator.credentials.create(defaultOptions).then(credential => { 62 assert_not_equals(credential, undefined); 63 assert_not_equals(credential, null); 64 }); 65 }, "CTAP HID with continue after wrong nonce error in a mock hid authenticator."); 57 66 </script> -
trunk/Source/WebCore/ChangeLog
r238245 r238246 1 2018-11-15 Jiewen Tan <jiewen_tan@apple.com> 2 3 [WebAuthN] Use a real nonce for CTAPHID_INIT 4 https://bugs.webkit.org/show_bug.cgi?id=191533 5 <rdar://problem/46103502> 6 7 Reviewed by Brent Fulgham. 8 9 New tests are added into existing test files. 10 11 * Modules/webauthn/fido/FidoConstants.h: 12 1 13 2018-11-15 Justin Fan <justin_fan@apple.com> 2 14 -
trunk/Source/WebCore/Modules/webauthn/fido/FidoConstants.h
r238166 r238246 161 161 const size_t kHidContinuationPacketDataSize = kHidMaxPacketSize - kHidContinuationPacketHeader; 162 162 const size_t kHidInitResponseSize = 17; 163 const size_t kHidInitNonceLength = 8; 163 164 164 165 const uint8_t kHidMaxLockSeconds = 10; -
trunk/Source/WebKit/ChangeLog
r238244 r238246 1 2018-11-15 Jiewen Tan <jiewen_tan@apple.com> 2 3 [WebAuthN] Use a real nonce for CTAPHID_INIT 4 https://bugs.webkit.org/show_bug.cgi?id=191533 5 <rdar://problem/46103502> 6 7 Reviewed by Brent Fulgham. 8 9 Use a real nonce for CTAPHID_INIT request according to: 10 https://fidoalliance.org/specs/fido-v2.0-ps-20170927/fido-client-to-authenticator-protocol-v2.0-ps-20170927.html#ctaphid_init-0x06. 11 The challenge here is the new transaction needs to start in the next runloop otherwise a dead lock will form: 12 wrong nonce -> new transaction -> new nonce -> write init request -> read init response from last run as it 13 piped in the run loop -> wrong nonce of course -> ... 14 To break the above dead lock, we have to start the new transaction in the next run. However, that isn't 15 sufficient as the arrived init response will be piped in HidConnection::m_inputReports, which is designed 16 on purpose to store any data packets within (initialized, terminated) time interval to prevent data loss in 17 the case when HidConnection::registerDataReceivedCallback is called after the first data packet's arrival. 18 In order to break the dead lock completely, HidConnection::invalidateCache will bnnne called prior to every 19 send to delete any potential init response from last run. HidConnection::invalidateCache is not necessary 20 for other protocols though. The above scenario is more or less a design flaw in CTAP HID. 21 22 Of course, all above scenarios are covered in our mock tests. 23 24 * UIProcess/API/C/WKWebsiteDataStoreRef.cpp: 25 (WKWebsiteDataStoreSetWebAuthenticationMockConfiguration): 26 * UIProcess/WebAuthentication/Cocoa/HidConnection.h: 27 (WebKit::HidConnection::invalidateCache): 28 * UIProcess/WebAuthentication/Mock/MockHidConnection.cpp: 29 (WebKit::MockHidConnection::send): 30 (WebKit::MockHidConnection::parseRequest): 31 (WebKit::MockHidConnection::feedReports): 32 * UIProcess/WebAuthentication/Mock/MockHidConnection.h: 33 * UIProcess/WebAuthentication/Mock/MockWebAuthenticationConfiguration.h: 34 * UIProcess/WebAuthentication/fido/CtapHidDriver.cpp: 35 (WebKit::CtapHidDriver::Worker::transact): 36 (WebKit::CtapHidDriver::CtapHidDriver): 37 (WebKit::CtapHidDriver::transact): 38 (WebKit::CtapHidDriver::continueAfterChannelAllocated): 39 (WebKit::CtapHidDriver::returnResponse): 40 * UIProcess/WebAuthentication/fido/CtapHidDriver.h: 41 1 42 2018-11-15 Oriol Brufau <obrufau@igalia.com> 2 43 -
trunk/Source/WebKit/UIProcess/API/C/WKWebsiteDataStoreRef.cpp
r238166 r238246 626 626 if (error == "unsupported-options") 627 627 hid.error = MockWebAuthenticationConfiguration::Hid::Error::UnsupportedOptions; 628 if (error == "wrong-nonce") 629 hid.error = MockWebAuthenticationConfiguration::Hid::Error::WrongNonce; 628 630 629 631 if (auto payloadBase64 = static_cast<WKStringRef>(WKDictionaryGetItemForKey(hidRef, adoptWK(WKStringCreateWithUTF8CString("PayloadBase64")).get()))) -
trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/HidConnection.h
r238166 r238246 60 60 void registerDataReceivedCallback(DataReceivedCallback&&); 61 61 void unregisterDataReceivedCallback(); 62 void invalidateCache() { m_inputReports.clear(); } 62 63 63 64 void receiveReport(Vector<uint8_t>&&); -
trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockHidConnection.cpp
r238166 r238246 71 71 { 72 72 ASSERT(m_initialized); 73 assembleRequest(WTFMove(data)); 74 75 auto sent = DataSent::Yes; 76 if (stagesMatch() && m_configuration.hid->error == Mock::Error::DataNotSent) 77 sent = DataSent::No; 78 79 auto task = BlockPtr<void()>::fromCallable([callback = WTFMove(callback), sent]() mutable { 73 auto task = BlockPtr<void()>::fromCallable([weakThis = makeWeakPtr(*this), data = WTFMove(data), callback = WTFMove(callback)]() mutable { 80 74 ASSERT(!RunLoop::isMain()); 81 RunLoop::main().dispatch([callback = WTFMove(callback), sent]() mutable { 75 RunLoop::main().dispatch([weakThis, data = WTFMove(data), callback = WTFMove(callback)]() mutable { 76 if (!weakThis) 77 return; 78 79 weakThis->assembleRequest(WTFMove(data)); 80 81 auto sent = DataSent::Yes; 82 if (weakThis->stagesMatch() && weakThis->m_configuration.hid->error == Mock::Error::DataNotSent) 83 sent = DataSent::No; 82 84 callback(sent); 83 85 }); … … 164 166 } 165 167 168 // Store nonce. 169 if (m_subStage == Mock::SubStage::Init) { 170 m_nonce = m_requestMessage->getMessagePayload(); 171 ASSERT(m_nonce.size() == kHidInitNonceLength); 172 } 173 166 174 m_currentChannel = m_requestMessage->channelId(); 167 175 m_requestMessage = std::nullopt; … … 177 185 Vector<uint8_t> payload; 178 186 payload.reserveInitialCapacity(kHidInitResponseSize); 179 // FIXME(191533): Use a real nonce. 180 payload.appendVector(Vector<uint8_t>({ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 })); 187 payload.appendVector(m_nonce); 188 if (stagesMatch() && m_configuration.hid->error == Mock::Error::WrongNonce) 189 payload[0]--; 181 190 payload.grow(kHidInitResponseSize); 182 191 cryptographicallyRandomValues(payload.data() + payload.size(), CtapChannelIdSize); … … 192 201 std::optional<FidoHidMessage> message; 193 202 if (m_stage == Mock::Stage::Info && m_subStage == Mock::SubStage::Msg) { 194 auto infoData = encodeAsCBOR(AuthenticatorGetInfoResponse({ ProtocolVersion::kCtap }, Vector<uint8_t>(kAaguidLength )));203 auto infoData = encodeAsCBOR(AuthenticatorGetInfoResponse({ ProtocolVersion::kCtap }, Vector<uint8_t>(kAaguidLength, 0u))); 195 204 infoData.insert(0, static_cast<uint8_t>(CtapDeviceResponseCode::kSuccess)); // Prepend status code. 196 205 if (stagesMatch() && m_configuration.hid->error == Mock::Error::WrongChannelId) -
trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockHidConnection.h
r238166 r238246 66 66 bool m_requireResidentKey { false }; 67 67 bool m_requireUserVerification { false }; 68 Vector<uint8_t> m_nonce; 68 69 }; 69 70 -
trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockWebAuthenticationConfiguration.h
r238166 r238246 58 58 WrongChannelId, 59 59 MaliciousPayload, 60 UnsupportedOptions 60 UnsupportedOptions, 61 WrongNonce 61 62 }; 62 63 -
trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapHidDriver.cpp
r238166 r238246 30 30 31 31 #include <WebCore/FidoConstants.h> 32 #include <wtf/CryptographicallyRandomNumber.h> 32 33 #include <wtf/RunLoop.h> 34 #include <wtf/Vector.h> 33 35 #include <wtf/text/Base64.h> 34 36 … … 55 57 m_callback = WTFMove(callback); 56 58 59 // HidConnection could hold data from other applications, and thereofore invalidate it before each transaction. 60 m_connection->invalidateCache(); 57 61 m_connection->send(m_requestMessage->popNextPacket(), [weakThis = makeWeakPtr(*this)](HidConnection::DataSent sent) mutable { 58 62 ASSERT(RunLoop::isMain()); … … 130 134 CtapHidDriver::CtapHidDriver(UniqueRef<HidConnection>&& connection) 131 135 : m_worker(makeUniqueRef<Worker>(WTFMove(connection))) 136 , m_nonce(kHidInitNonceLength) 132 137 { 133 138 } … … 137 142 ASSERT(m_state == State::Idle); 138 143 m_state = State::AllocateChannel; 144 m_channelId = kHidBroadcastChannel; 139 145 m_requestData = WTFMove(data); 140 146 m_responseCallback = WTFMove(callback); 141 147 142 148 // Allocate a channel. 143 // FIXME(191533): Get a real nonce. 144 auto initCommand = FidoHidMessage::create(kHidBroadcastChannel, FidoHidDeviceCommand::kInit, { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }); 149 ASSERT(m_nonce.size() == kHidInitNonceLength); 150 cryptographicallyRandomValues(m_nonce.data(), m_nonce.size()); 151 auto initCommand = FidoHidMessage::create(m_channelId, FidoHidDeviceCommand::kInit, m_nonce); 145 152 ASSERT(initCommand); 146 153 m_worker->transact(WTFMove(*initCommand), [weakThis = makeWeakPtr(*this)](std::optional<FidoHidMessage>&& response) mutable { … … 159 166 return; 160 167 } 168 ASSERT(message->channelId() == m_channelId); 169 170 auto payload = message->getMessagePayload(); 171 ASSERT(payload.size() == kHidInitResponseSize); 172 // Restart the transaction in the next run loop when nonce mismatches. 173 if (memcmp(payload.data(), m_nonce.data(), m_nonce.size())) { 174 m_state = State::Idle; 175 RunLoop::main().dispatch([weakThis = makeWeakPtr(*this), data = WTFMove(m_requestData), callback = WTFMove(m_responseCallback)]() mutable { 176 if (!weakThis) 177 return; 178 weakThis->transact(WTFMove(data), WTFMove(callback)); 179 }); 180 return; 181 } 182 161 183 m_state = State::Ready; 162 ASSERT(message->channelId() == m_channelId); 163 164 // FIXME(191534): Check Payload including nonce and everything 165 auto payload = message->getMessagePayload(); 166 size_t index = 8; 167 ASSERT(payload.size() == kHidInitResponseSize); 184 auto index = kHidInitNonceLength; 168 185 m_channelId = static_cast<uint32_t>(payload[index++]) << 24; 169 186 m_channelId |= static_cast<uint32_t>(payload[index++]) << 16; 170 187 m_channelId |= static_cast<uint32_t>(payload[index++]) << 8; 171 188 m_channelId |= static_cast<uint32_t>(payload[index]); 189 // FIXME(191534): Check the reset of the payload. 172 190 auto cmd = FidoHidMessage::create(m_channelId, FidoHidDeviceCommand::kCbor, m_requestData); 173 191 ASSERT(cmd); … … 191 209 // Reset state before calling the response callback to avoid being deleted. 192 210 m_state = State::Idle; 193 m_channelId = fido::kHidBroadcastChannel;194 m_requestData = { };195 211 m_responseCallback(WTFMove(response)); 196 212 } -
trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapHidDriver.h
r238166 r238246 63 63 // Worker is the helper that maintains the transaction. 64 64 // https://fidoalliance.org/specs/fido-v2.0-ps-20170927/fido-client-to-authenticator-protocol-v2.0-ps-20170927.html#arbitration 65 // FSM: Idle => Write => Read 65 // FSM: Idle => Write => Read. 66 66 class Worker : public CanMakeWeakPtr<Worker> { 67 67 WTF_MAKE_FAST_ALLOCATED; … … 103 103 Vector<uint8_t> m_requestData; 104 104 ResponseCallback m_responseCallback; 105 Vector<uint8_t> m_nonce; 105 106 }; 106 107
Note: See TracChangeset
for help on using the changeset viewer.