Changeset 254439 in webkit
- Timestamp:
- Jan 13, 2020 10:53:59 AM (4 years ago)
- Location:
- trunk
- Files:
-
- 5 added
- 24 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r254438 r254439 1 2020-01-06 Jiewen Tan <jiewen_tan@apple.com> 2 3 [WebAuthn] Support CTAP Client Pin 4 https://bugs.webkit.org/show_bug.cgi?id=191516 5 <rdar://problem/56558558> 6 7 Reviewed by Brent Fulgham. 8 9 Covered by API tests. 10 11 * Modules/webauthn/fido/DeviceRequestConverter.cpp: 12 (fido::encodeMakeCredenitalRequestAsCBOR): 13 (fido::encodeGetAssertionRequestAsCBOR): 14 * Modules/webauthn/fido/Pin.cpp: 15 (fido::pin::RetriesResponse::parse): 16 (fido::pin::TokenResponse::parse): 17 (fido::pin::TokenRequest::tryCreate): 18 (fido::pin::encodeAsCBOR): 19 * Modules/webauthn/fido/Pin.h: 20 * crypto/algorithms/CryptoAlgorithmAES_CBC.h: 21 * crypto/gcrypt/CryptoAlgorithmAES_CBCGCrypt.cpp: 22 (WebCore::CryptoAlgorithmAES_CBC::platformEncrypt): 23 (WebCore::CryptoAlgorithmAES_CBC::platformDecrypt): 24 * crypto/mac/CryptoAlgorithmAES_CBCMac.cpp: 25 (WebCore::transformAES_CBC): 26 (WebCore::CryptoAlgorithmAES_CBC::platformEncrypt): 27 (WebCore::CryptoAlgorithmAES_CBC::platformDecrypt): 28 * testing/MockWebAuthenticationConfiguration.h: 29 (WebCore::MockWebAuthenticationConfiguration::HidConfiguration::encode const): 30 (WebCore::MockWebAuthenticationConfiguration::HidConfiguration::decode): 31 * testing/MockWebAuthenticationConfiguration.idl: 32 1 33 2020-01-13 Zalan Bujtas <zalan@apple.com> 2 34 -
trunk/Source/WebCore/Modules/webauthn/fido/DeviceRequestConverter.cpp
r253811 r254439 127 127 if (pin) { 128 128 ASSERT(pin->protocol >= 0); 129 cborMap[CBORValue(8)] = CBORValue( pin->protocol);130 cborMap[CBORValue(9)] = CBORValue( WTFMove(pin->auth));129 cborMap[CBORValue(8)] = CBORValue(WTFMove(pin->auth)); 130 cborMap[CBORValue(9)] = CBORValue(pin->protocol); 131 131 } 132 132 … … 173 173 if (pin) { 174 174 ASSERT(pin->protocol >= 0); 175 cborMap[CBORValue( 8)] = CBORValue(pin->protocol);176 cborMap[CBORValue( 9)] = CBORValue(WTFMove(pin->auth));175 cborMap[CBORValue(6)] = CBORValue(WTFMove(pin->auth)); 176 cborMap[CBORValue(7)] = CBORValue(pin->protocol); 177 177 } 178 178 -
trunk/Source/WebCore/Modules/webauthn/fido/Pin.cpp
r254079 r254439 132 132 133 133 RetriesResponse ret; 134 ret.retries = static_cast< int64_t>(it->second.getUnsigned());134 ret.retries = static_cast<uint64_t>(it->second.getUnsigned()); 135 135 return ret; 136 136 } … … 233 233 const auto& encryptedToken = it->second.getByteString(); 234 234 235 auto tokenResult = CryptoAlgorithmAES_CBC::platformDecrypt({ }, sharedKey, encryptedToken );235 auto tokenResult = CryptoAlgorithmAES_CBC::platformDecrypt({ }, sharedKey, encryptedToken, CryptoAlgorithmAES_CBC::Padding::No); 236 236 if (tokenResult.hasException()) 237 237 return WTF::nullopt; … … 273 273 auto keyPair = keyPairResult.releaseReturnValue(); 274 274 275 // 2. Use ECDH to compute the shared AES-CBC key.275 // 2. Use ECDH and SHA-256 to compute the shared AES-CBC key. 276 276 auto sharedKeyResult = CryptoAlgorithmECDH::platformDeriveBits(downcast<CryptoKeyEC>(*keyPair.privateKey), peerKey); 277 277 if (!sharedKeyResult) 278 278 return WTF::nullopt; 279 auto sharedKey = CryptoKeyAES::importRaw(CryptoAlgorithmIdentifier::AES_CBC, WTFMove(*sharedKeyResult), true, CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt); 279 280 auto crypto = PAL::CryptoDigest::create(PAL::CryptoDigest::Algorithm::SHA_256); 281 crypto->addBytes(sharedKeyResult->data(), sharedKeyResult->size()); 282 auto sharedKeyHash = crypto->computeHash(); 283 284 auto sharedKey = CryptoKeyAES::importRaw(CryptoAlgorithmIdentifier::AES_CBC, WTFMove(sharedKeyHash), true, CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt); 280 285 ASSERT(sharedKey); 281 286 … … 286 291 287 292 // The following calculates a SHA-256 digest of the PIN, and shrink to the left 16 bytes. 288 autocrypto = PAL::CryptoDigest::create(PAL::CryptoDigest::Algorithm::SHA_256);293 crypto = PAL::CryptoDigest::create(PAL::CryptoDigest::Algorithm::SHA_256); 289 294 crypto->addBytes(pin.data(), pin.length()); 290 295 auto pinHash = crypto->computeHash(); … … 308 313 Vector<uint8_t> encodeAsCBOR(const TokenRequest& request) 309 314 { 310 auto result = CryptoAlgorithmAES_CBC::platformEncrypt({ }, request.sharedKey(), request.m_pinHash );315 auto result = CryptoAlgorithmAES_CBC::platformEncrypt({ }, request.sharedKey(), request.m_pinHash, CryptoAlgorithmAES_CBC::Padding::No); 311 316 ASSERT(!result.hasException()); 312 317 -
trunk/Source/WebCore/Modules/webauthn/fido/Pin.h
r253811 r254439 80 80 // kProtocolVersion is the version of the PIN protocol that this code 81 81 // implements. 82 constexpr int kProtocolVersion = 1;82 constexpr int64_t kProtocolVersion = 1; 83 83 84 84 // encodeCOSEPublicKey takes a raw ECDH256 public key and returns it as a COSE structure. … … 111 111 // retries is the number of PIN attempts remaining before the authenticator 112 112 // locks. 113 int retries;113 uint64_t retries; 114 114 115 115 private: … … 146 146 // sharedKey returns the shared ECDH key that was used to encrypt the PIN. 147 147 // This is needed to decrypt the response. 148 const WebCore::CryptoKeyAES& sharedKey() const;148 WEBCORE_EXPORT const WebCore::CryptoKeyAES& sharedKey() const; 149 149 150 150 friend Vector<uint8_t> encodeAsCBOR(const TokenRequest&); -
trunk/Source/WebCore/crypto/algorithms/CryptoAlgorithmAES_CBC.h
r253811 r254439 37 37 class CryptoAlgorithmAES_CBC final : public CryptoAlgorithm { 38 38 public: 39 enum class Padding : uint8_t { 40 Yes, 41 No 42 }; 43 39 44 static constexpr const char* s_name = "AES-CBC"; 40 45 static constexpr CryptoAlgorithmIdentifier s_identifier = CryptoAlgorithmIdentifier::AES_CBC; … … 42 47 43 48 // Operations can be performed directly. 44 WEBCORE_EXPORT static ExceptionOr<Vector<uint8_t>> platformEncrypt(const CryptoAlgorithmAesCbcCfbParams&, const CryptoKeyAES&, const Vector<uint8_t>& );45 WEBCORE_EXPORT static ExceptionOr<Vector<uint8_t>> platformDecrypt(const CryptoAlgorithmAesCbcCfbParams&, const CryptoKeyAES&, const Vector<uint8_t>& );49 WEBCORE_EXPORT static ExceptionOr<Vector<uint8_t>> platformEncrypt(const CryptoAlgorithmAesCbcCfbParams&, const CryptoKeyAES&, const Vector<uint8_t>&, Padding padding = Padding::Yes); 50 WEBCORE_EXPORT static ExceptionOr<Vector<uint8_t>> platformDecrypt(const CryptoAlgorithmAesCbcCfbParams&, const CryptoKeyAES&, const Vector<uint8_t>&, Padding padding = Padding::Yes); 46 51 47 52 private: -
trunk/Source/WebCore/crypto/gcrypt/CryptoAlgorithmAES_CBCGCrypt.cpp
r239427 r254439 167 167 } 168 168 169 ExceptionOr<Vector<uint8_t>> CryptoAlgorithmAES_CBC::platformEncrypt(const CryptoAlgorithmAesCbcCfbParams& parameters, const CryptoKeyAES& key, const Vector<uint8_t>& plainText )169 ExceptionOr<Vector<uint8_t>> CryptoAlgorithmAES_CBC::platformEncrypt(const CryptoAlgorithmAesCbcCfbParams& parameters, const CryptoKeyAES& key, const Vector<uint8_t>& plainText, Padding) 170 170 { 171 171 auto output = gcryptEncrypt(key.key(), parameters.ivVector(), Vector<uint8_t>(plainText)); … … 175 175 } 176 176 177 ExceptionOr<Vector<uint8_t>> CryptoAlgorithmAES_CBC::platformDecrypt(const CryptoAlgorithmAesCbcCfbParams& parameters, const CryptoKeyAES& key, const Vector<uint8_t>& cipherText )177 ExceptionOr<Vector<uint8_t>> CryptoAlgorithmAES_CBC::platformDecrypt(const CryptoAlgorithmAesCbcCfbParams& parameters, const CryptoKeyAES& key, const Vector<uint8_t>& cipherText, Padding) 178 178 { 179 179 auto output = gcryptDecrypt(key.key(), parameters.ivVector(), cipherText); -
trunk/Source/WebCore/crypto/mac/CryptoAlgorithmAES_CBCMac.cpp
r253811 r254439 35 35 namespace WebCore { 36 36 37 static ExceptionOr<Vector<uint8_t>> transformAES_CBC(CCOperation operation, const Vector<uint8_t>& iv, const Vector<uint8_t>& key, const Vector<uint8_t>& data )37 static ExceptionOr<Vector<uint8_t>> transformAES_CBC(CCOperation operation, const Vector<uint8_t>& iv, const Vector<uint8_t>& key, const Vector<uint8_t>& data, CryptoAlgorithmAES_CBC::Padding padding) 38 38 { 39 CCOptions options = padding == CryptoAlgorithmAES_CBC::Padding::Yes ? kCCOptionPKCS7Padding : 0; 39 40 CCCryptorRef cryptor; 40 CCCryptorStatus status = CCCryptorCreate(operation, kCCAlgorithmAES, kCCOptionPKCS7Padding, key.data(), key.size(), iv.data(), &cryptor);41 CCCryptorStatus status = CCCryptorCreate(operation, kCCAlgorithmAES, options, key.data(), key.size(), iv.data(), &cryptor); 41 42 if (status) 42 43 return Exception { OperationError }; … … 50 51 51 52 uint8_t* p = result.data() + bytesWritten; 52 status = CCCryptorFinal(cryptor, p, result.end() - p, &bytesWritten); 53 p += bytesWritten; 54 if (status) 55 return Exception { OperationError }; 53 if (padding == CryptoAlgorithmAES_CBC::Padding::Yes) { 54 status = CCCryptorFinal(cryptor, p, result.end() - p, &bytesWritten); 55 p += bytesWritten; 56 if (status) 57 return Exception { OperationError }; 58 } 56 59 57 60 ASSERT(p <= result.end()); … … 63 66 } 64 67 65 ExceptionOr<Vector<uint8_t>> CryptoAlgorithmAES_CBC::platformEncrypt(const CryptoAlgorithmAesCbcCfbParams& parameters, const CryptoKeyAES& key, const Vector<uint8_t>& plainText )68 ExceptionOr<Vector<uint8_t>> CryptoAlgorithmAES_CBC::platformEncrypt(const CryptoAlgorithmAesCbcCfbParams& parameters, const CryptoKeyAES& key, const Vector<uint8_t>& plainText, Padding padding) 66 69 { 67 70 ASSERT(parameters.ivVector().size() == kCCBlockSizeAES128 || parameters.ivVector().isEmpty()); 68 return transformAES_CBC(kCCEncrypt, parameters.ivVector(), key.key(), plainText); 71 ASSERT(padding == Padding::Yes || !(plainText.size() % kCCBlockSizeAES128)); 72 return transformAES_CBC(kCCEncrypt, parameters.ivVector(), key.key(), plainText, padding); 69 73 } 70 74 71 ExceptionOr<Vector<uint8_t>> CryptoAlgorithmAES_CBC::platformDecrypt(const CryptoAlgorithmAesCbcCfbParams& parameters, const CryptoKeyAES& key, const Vector<uint8_t>& cipherText )75 ExceptionOr<Vector<uint8_t>> CryptoAlgorithmAES_CBC::platformDecrypt(const CryptoAlgorithmAesCbcCfbParams& parameters, const CryptoKeyAES& key, const Vector<uint8_t>& cipherText, Padding padding) 72 76 { 73 77 ASSERT(parameters.ivVector().size() == kCCBlockSizeAES128 || parameters.ivVector().isEmpty()); 74 return transformAES_CBC(kCCDecrypt, parameters.ivVector(), key.key(), cipherText); 78 ASSERT(padding == Padding::Yes || !(cipherText.size() % kCCBlockSizeAES128)); 79 return transformAES_CBC(kCCDecrypt, parameters.ivVector(), key.key(), cipherText, padding); 75 80 } 76 81 -
trunk/Source/WebCore/testing/MockWebAuthenticationConfiguration.h
r251645 r254439 85 85 bool canDowngrade { false }; 86 86 bool expectCancel { false }; 87 bool supportClientPin { false }; 87 88 88 89 template<class Encoder> void encode(Encoder&) const; … … 162 163 void MockWebAuthenticationConfiguration::HidConfiguration::encode(Encoder& encoder) const 163 164 { 164 encoder << payloadBase64 << stage << subStage << error << isU2f << keepAlive << fastDataArrival << continueAfterErrorData << canDowngrade << expectCancel ;165 encoder << payloadBase64 << stage << subStage << error << isU2f << keepAlive << fastDataArrival << continueAfterErrorData << canDowngrade << expectCancel << supportClientPin; 165 166 } 166 167 … … 188 189 return WTF::nullopt; 189 190 if (!decoder.decode(result.expectCancel)) 191 return WTF::nullopt; 192 if (!decoder.decode(result.supportClientPin)) 190 193 return WTF::nullopt; 191 194 return result; -
trunk/Source/WebCore/testing/MockWebAuthenticationConfiguration.idl
r251645 r254439 93 93 boolean canDowngrade = false; 94 94 boolean expectCancel = false; 95 boolean supportClientPin = false; 95 96 }; 96 97 -
trunk/Source/WebKit/ChangeLog
r254436 r254439 1 2020-01-06 Jiewen Tan <jiewen_tan@apple.com> 2 3 [WebAuthn] Support CTAP Client Pin 4 https://bugs.webkit.org/show_bug.cgi?id=191516 5 <rdar://problem/56558558> 6 7 Reviewed by Brent Fulgham. 8 9 This patch implements authenticatorClientPIN from the spec: 10 https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#authenticatorClientPIN 11 Specifically, it implements section 5.5.1, 5.5.3, 5.5.4, 5.5.7, and 5.5.8. 12 13 Here is the flow how makeCredential/getAssertion works with a PIN in our implementation: 14 1. Determine if the connected authenticator has a PIN; 15 2. If yes, send the makeCredential/getAssertion request to the authenticator with an empty pinAuth 16 such that the authenticator will wink for user gestures. This step intends to confirm the authenticator 17 is the one the user wants to use. Otherwise, we don't know which authenticator to send the PIN 18 if multiple are connected; 19 3. Once the user confirms the authetnicator, it will return either CTAP2_ERR_PIN_INVALID or 20 CTAP2_ERR_PIN_AUTH_INVALID. Some authenticators return CTAP2_ERR_PIN_AUTH_INVALID even though 21 it is not suggested by the spec; 22 4. Get retries from the authenticator; 23 5. Get key agreement from the authenticator; 24 6. Ask the UI client for the PIN and at the meantime inform it the retries; 25 7. Get pin token from the authenticator; 26 8. Resend the makeCredential/getAssertion request with the desired pinAuth. 27 28 Besides implementating the above flow, this patch also fixes some bugs within the PIN commands encoder: 29 1. pinAuth/pinProtocol are wrongly encoded for makeCredential/getAssertion; 30 2. AES CBC should be called without any padding. Therefore, CryptoAlgorithmAES_CBC adds a no padding mode; 31 3. The sharedSecret is the SHA256 digest of the ECDH key agreement instead of the raw key agreement. 32 33 * UIProcess/API/APIWebAuthenticationPanelClient.h: 34 (API::WebAuthenticationPanelClient::requestPin const): 35 * UIProcess/WebAuthentication/Authenticator.h: 36 * UIProcess/WebAuthentication/AuthenticatorManager.cpp: 37 (WebKit::AuthenticatorManager::requestPin): 38 * UIProcess/WebAuthentication/AuthenticatorManager.h: 39 * UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.h: 40 * UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm: 41 (WebKit::WebAuthenticationPanelClient::WebAuthenticationPanelClient): 42 (WebKit::WebAuthenticationPanelClient::requestPin const): 43 * UIProcess/WebAuthentication/Mock/MockHidConnection.cpp: 44 (WebKit::MockHidConnection::feedReports): 45 * UIProcess/WebAuthentication/fido/CtapAuthenticator.cpp: 46 (WebKit::CtapAuthenticator::makeCredential): 47 (WebKit::CtapAuthenticator::continueMakeCredentialAfterResponseReceived): 48 (WebKit::CtapAuthenticator::getAssertion): 49 (WebKit::CtapAuthenticator::continueGetAssertionAfterResponseReceived): 50 (WebKit::CtapAuthenticator::getRetries): 51 (WebKit::CtapAuthenticator::continueGetKeyAgreementAfterGetRetries): 52 (WebKit::CtapAuthenticator::continueRequestPinAfterGetKeyAgreement): 53 (WebKit::CtapAuthenticator::continueGetPinTokenAfterRequestPin): 54 (WebKit::CtapAuthenticator::continueRequestAfterGetPinToken): 55 (WebKit::CtapAuthenticator::continueMakeCredentialAfterResponseReceived const): Deleted. 56 * UIProcess/WebAuthentication/fido/CtapAuthenticator.h: 57 1 58 2020-01-13 Brent Fulgham <bfulgham@apple.com> 2 59 -
trunk/Source/WebKit/UIProcess/API/APIWebAuthenticationPanelClient.h
r254356 r254439 31 31 #include <wtf/HashSet.h> 32 32 #include <wtf/RefCounted.h> 33 #include <wtf/text/WTFString.h> 33 34 34 35 namespace WebCore { … … 51 52 virtual void dismissPanel(WebKit::WebAuthenticationResult) const { } 52 53 virtual void selectAssertionResponses(const HashSet<Ref<WebCore::AuthenticatorAssertionResponse>>& responses, CompletionHandler<void(const Ref<WebCore::AuthenticatorAssertionResponse>&)>&& completionHandler) const { completionHandler(*responses.begin()); } 54 virtual void requestPin(uint64_t, CompletionHandler<void(const WTF::String&)>&& completionHandler) const { completionHandler(emptyString()); } 53 55 }; 54 56 -
trunk/Source/WebKit/UIProcess/WebAuthentication/Authenticator.h
r254356 r254439 53 53 virtual void authenticatorStatusUpdated(WebAuthenticationStatus) = 0; 54 54 virtual void selectAssertionResponses(const HashSet<Ref<WebCore::AuthenticatorAssertionResponse>>&, CompletionHandler<void(const Ref<WebCore::AuthenticatorAssertionResponse>&)>&&) = 0; 55 virtual void requestPin(uint64_t retries, CompletionHandler<void(const WTF::String&)>&&) = 0; 55 56 }; 56 57 -
trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.cpp
r254356 r254439 280 280 } 281 281 282 void AuthenticatorManager::requestPin(uint64_t retries, CompletionHandler<void(const WTF::String&)>&& completionHandler) 283 { 284 if (auto* panel = m_pendingRequestData.panel.get()) 285 panel->client().requestPin(retries, WTFMove(completionHandler)); 286 } 287 282 288 UniqueRef<AuthenticatorTransportService> AuthenticatorManager::createService(AuthenticatorTransport transport, AuthenticatorTransportService::Observer& observer) const 283 289 { -
trunk/Source/WebKit/UIProcess/WebAuthentication/AuthenticatorManager.h
r254356 r254439 83 83 void authenticatorStatusUpdated(WebAuthenticationStatus) final; 84 84 void selectAssertionResponses(const HashSet<Ref<WebCore::AuthenticatorAssertionResponse>>&, CompletionHandler<void(const Ref<WebCore::AuthenticatorAssertionResponse>&)>&&) final; 85 void requestPin(uint64_t retries, CompletionHandler<void(const WTF::String&)>&&) final; 85 86 86 87 // Overriden by MockAuthenticatorManager. -
trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.h
r251317 r254439 50 50 void updatePanel(WebAuthenticationStatus) const final; 51 51 void dismissPanel(WebAuthenticationResult) const final; 52 void requestPin(uint64_t, CompletionHandler<void(const WTF::String&)>&&) const final; 52 53 53 54 _WKWebAuthenticationPanel *m_panel; … … 57 58 bool panelUpdateWebAuthenticationPanel : 1; 58 59 bool panelDismissWebAuthenticationPanelWithResult : 1; 60 bool panelRequestPinWithRemainingRetriesCompletionHandler : 1; 59 61 } m_delegateMethods; 60 62 }; -
trunk/Source/WebKit/UIProcess/WebAuthentication/Cocoa/WebAuthenticationPanelClient.mm
r252035 r254439 29 29 #if ENABLE(WEB_AUTHN) 30 30 31 #import "CompletionHandlerCallChecker.h" 31 32 #import "WebAuthenticationFlags.h" 32 33 #import "_WKWebAuthenticationPanel.h" 34 #import <wtf/BlockPtr.h> 33 35 #import <wtf/RunLoop.h> 34 36 … … 41 43 m_delegateMethods.panelUpdateWebAuthenticationPanel = [delegate respondsToSelector:@selector(panel:updateWebAuthenticationPanel:)]; 42 44 m_delegateMethods.panelDismissWebAuthenticationPanelWithResult = [delegate respondsToSelector:@selector(panel:dismissWebAuthenticationPanelWithResult:)]; 45 m_delegateMethods.panelRequestPinWithRemainingRetriesCompletionHandler = [delegate respondsToSelector:@selector(panel:requestPINWithRemainingRetries:completionHandler:)]; 43 46 } 44 47 … … 108 111 } 109 112 113 void WebAuthenticationPanelClient::requestPin(uint64_t retries, CompletionHandler<void(const WTF::String&)>&& completionHandler) const 114 { 115 // Call delegates in the next run loop to prevent clients' reentrance that would potentially modify the state 116 // of the current run loop in unexpected ways. 117 RunLoop::main().dispatch([weakThis = makeWeakPtr(*this), this, retries, completionHandler = WTFMove(completionHandler)] () mutable { 118 if (!weakThis) { 119 completionHandler(emptyString()); 120 return; 121 } 122 123 if (!m_delegateMethods.panelRequestPinWithRemainingRetriesCompletionHandler) { 124 completionHandler(emptyString()); 125 return; 126 } 127 128 auto delegate = m_delegate.get(); 129 if (!delegate) { 130 completionHandler(emptyString()); 131 return; 132 } 133 134 auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(panel:requestPINWithRemainingRetries:completionHandler:)); 135 [delegate panel:m_panel requestPINWithRemainingRetries:retries completionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)](NSString *pin) mutable { 136 if (checker->completionHandlerHasBeenCalled()) 137 return; 138 checker->didCallCompletionHandler(); 139 completionHandler(pin); 140 }).get()]; 141 }); 142 } 143 110 144 } // namespace WebKit 111 145 -
trunk/Source/WebKit/UIProcess/WebAuthentication/Mock/MockHidConnection.cpp
r254356 r254439 32 32 #include <WebCore/CBORReader.h> 33 33 #include <WebCore/FidoConstants.h> 34 #include <WebCore/Pin.h> 34 35 #include <WebCore/WebAuthenticationConstants.h> 35 36 #include <wtf/BlockPtr.h> … … 224 225 Optional<FidoHidMessage> message; 225 226 if (m_stage == Mock::HidStage::Info && m_subStage == Mock::HidSubStage::Msg) { 227 // FIXME(205839): 226 228 Vector<uint8_t> infoData; 227 229 if (m_configuration.hid->canDowngrade) 228 230 infoData = encodeAsCBOR(AuthenticatorGetInfoResponse({ ProtocolVersion::kCtap, ProtocolVersion::kU2f }, Vector<uint8_t>(aaguidLength, 0u))); 229 else 231 else if (m_configuration.hid->supportClientPin) { 232 AuthenticatorGetInfoResponse infoResponse({ ProtocolVersion::kCtap }, Vector<uint8_t>(aaguidLength, 0u)); 233 infoResponse.setPinProtocols({ pin::kProtocolVersion }); 234 AuthenticatorSupportedOptions options; 235 options.setClientPinAvailability(AuthenticatorSupportedOptions::ClientPinAvailability::kSupportedAndPinSet); 236 infoResponse.setOptions(WTFMove(options)); 237 infoData = encodeAsCBOR(infoResponse); 238 } else 230 239 infoData = encodeAsCBOR(AuthenticatorGetInfoResponse({ ProtocolVersion::kCtap }, Vector<uint8_t>(aaguidLength, 0u))); 231 240 infoData.insert(0, static_cast<uint8_t>(CtapDeviceResponseCode::kSuccess)); // Prepend status code. -
trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.cpp
r254356 r254439 32 32 #include "CtapHidDriver.h" 33 33 #include "U2fAuthenticator.h" 34 #include <WebCore/CryptoKeyAES.h> 35 #include <WebCore/CryptoKeyEC.h> 36 #include <WebCore/CryptoKeyHMAC.h> 34 37 #include <WebCore/DeviceRequestConverter.h> 35 38 #include <WebCore/DeviceResponseConverter.h> 36 39 #include <WebCore/ExceptionData.h> 40 #include <WebCore/Pin.h> 37 41 #include <WebCore/U2fCommandConstructor.h> 38 42 #include <wtf/RunLoop.h> … … 54 58 if (processGoogleLegacyAppIdSupportExtension()) 55 59 return; 56 auto cborCmd = encodeMakeCredenitalRequestAsCBOR(requestData().hash, WTF::get<PublicKeyCredentialCreationOptions>(requestData().options), m_info.options().userVerificationAvailability()); 60 Vector<uint8_t> cborCmd; 61 if (m_info.options().clientPinAvailability() == AuthenticatorSupportedOptions::ClientPinAvailability::kSupportedAndPinSet) 62 cborCmd = encodeMakeCredenitalRequestAsCBOR(requestData().hash, WTF::get<PublicKeyCredentialCreationOptions>(requestData().options), m_info.options().userVerificationAvailability(), PinParameters { pin::kProtocolVersion, m_pinAuth }); 63 else 64 cborCmd = encodeMakeCredenitalRequestAsCBOR(requestData().hash, WTF::get<PublicKeyCredentialCreationOptions>(requestData().options), m_info.options().userVerificationAvailability()); 57 65 driver().transact(WTFMove(cborCmd), [weakThis = makeWeakPtr(*this)](Vector<uint8_t>&& data) { 58 66 ASSERT(RunLoop::isMain()); … … 63 71 } 64 72 65 void CtapAuthenticator::continueMakeCredentialAfterResponseReceived(Vector<uint8_t>&& data) const73 void CtapAuthenticator::continueMakeCredentialAfterResponseReceived(Vector<uint8_t>&& data) 66 74 { 67 75 auto response = readCTAPMakeCredentialResponse(data, WTF::get<PublicKeyCredentialCreationOptions>(requestData().options).attestation); … … 70 78 if (error == CtapDeviceResponseCode::kCtap2ErrCredentialExcluded) 71 79 receiveRespond(ExceptionData { InvalidStateError, "At least one credential matches an entry of the excludeCredentials list in the authenticator."_s }); 80 // FIXME(205837) 81 else if (error == CtapDeviceResponseCode::kCtap2ErrPinInvalid || error == CtapDeviceResponseCode::kCtap2ErrPinAuthInvalid) 82 getRetries(); 72 83 else 73 84 receiveRespond(ExceptionData { UnknownError, makeString("Unknown internal error. Error code: ", static_cast<uint8_t>(error)) }); … … 80 91 { 81 92 ASSERT(!m_isDowngraded); 82 auto cborCmd = encodeGetAssertionRequestAsCBOR(requestData().hash, WTF::get<PublicKeyCredentialRequestOptions>(requestData().options), m_info.options().userVerificationAvailability()); 93 Vector<uint8_t> cborCmd; 94 if (m_info.options().clientPinAvailability() == AuthenticatorSupportedOptions::ClientPinAvailability::kSupportedAndPinSet) 95 cborCmd = encodeGetAssertionRequestAsCBOR(requestData().hash, WTF::get<PublicKeyCredentialRequestOptions>(requestData().options), m_info.options().userVerificationAvailability(), PinParameters { pin::kProtocolVersion, m_pinAuth }); 96 else 97 cborCmd = encodeGetAssertionRequestAsCBOR(requestData().hash, WTF::get<PublicKeyCredentialRequestOptions>(requestData().options), m_info.options().userVerificationAvailability()); 83 98 driver().transact(WTFMove(cborCmd), [weakThis = makeWeakPtr(*this)](Vector<uint8_t>&& data) { 84 99 ASSERT(RunLoop::isMain()); … … 94 109 if (!response) { 95 110 auto error = getResponseCode(data); 111 // FIXME(205837) 112 if (error == CtapDeviceResponseCode::kCtap2ErrPinInvalid || error == CtapDeviceResponseCode::kCtap2ErrPinAuthInvalid) { 113 getRetries(); 114 return; 115 } 96 116 if (error != CtapDeviceResponseCode::kCtap2ErrInvalidCBOR && tryDowngrade()) 97 117 return; … … 153 173 } 154 174 175 void CtapAuthenticator::getRetries() 176 { 177 auto cborCmd = encodeAsCBOR(pin::RetriesRequest { }); 178 driver().transact(WTFMove(cborCmd), [weakThis = makeWeakPtr(*this)](Vector<uint8_t>&& data) { 179 ASSERT(RunLoop::isMain()); 180 if (!weakThis) 181 return; 182 weakThis->continueGetKeyAgreementAfterGetRetries(WTFMove(data)); 183 }); 184 } 185 186 void CtapAuthenticator::continueGetKeyAgreementAfterGetRetries(Vector<uint8_t>&& data) 187 { 188 auto retries = pin::RetriesResponse::parse(data); 189 if (!retries) { 190 auto error = getResponseCode(data); 191 receiveRespond(ExceptionData { UnknownError, makeString("Unknown internal error. Error code: ", static_cast<uint8_t>(error)) }); 192 return; 193 } 194 195 auto cborCmd = encodeAsCBOR(pin::KeyAgreementRequest { }); 196 driver().transact(WTFMove(cborCmd), [weakThis = makeWeakPtr(*this), retries = retries->retries] (Vector<uint8_t>&& data) { 197 ASSERT(RunLoop::isMain()); 198 if (!weakThis) 199 return; 200 weakThis->continueRequestPinAfterGetKeyAgreement(WTFMove(data), retries); 201 }); 202 } 203 204 void CtapAuthenticator::continueRequestPinAfterGetKeyAgreement(Vector<uint8_t>&& data, uint64_t retries) 205 { 206 auto keyAgreement = pin::KeyAgreementResponse::parse(data); 207 if (!keyAgreement) { 208 auto error = getResponseCode(data); 209 receiveRespond(ExceptionData { UnknownError, makeString("Unknown internal error. Error code: ", static_cast<uint8_t>(error)) }); 210 return; 211 } 212 213 if (auto* observer = this->observer()) { 214 observer->requestPin(retries, [weakThis = makeWeakPtr(*this), keyAgreement = WTFMove(*keyAgreement)] (const String& pin) { 215 ASSERT(RunLoop::isMain()); 216 if (!weakThis) 217 return; 218 weakThis->continueGetPinTokenAfterRequestPin(pin, keyAgreement.peerKey); 219 }); 220 } 221 } 222 223 void CtapAuthenticator::continueGetPinTokenAfterRequestPin(const String& pin, const CryptoKeyEC& peerKey) 224 { 225 auto pinUtf8 = pin::validateAndConvertToUTF8(pin); 226 if (!pinUtf8) { 227 receiveRespond(ExceptionData { UnknownError, makeString("Pin is not valid: ", pin) }); 228 return; 229 } 230 auto tokenRequest = pin::TokenRequest::tryCreate(*pinUtf8, peerKey); 231 if (!tokenRequest) { 232 receiveRespond(ExceptionData { UnknownError, "Cannot create a TokenRequest."_s }); 233 return; 234 } 235 236 auto cborCmd = encodeAsCBOR(*tokenRequest); 237 driver().transact(WTFMove(cborCmd), [weakThis = makeWeakPtr(*this), tokenRequest = WTFMove(*tokenRequest)] (Vector<uint8_t>&& data) { 238 ASSERT(RunLoop::isMain()); 239 if (!weakThis) 240 return; 241 weakThis->continueRequestAfterGetPinToken(WTFMove(data), tokenRequest); 242 }); 243 } 244 245 void CtapAuthenticator::continueRequestAfterGetPinToken(Vector<uint8_t>&& data, const fido::pin::TokenRequest& tokenRequest) 246 { 247 auto token = pin::TokenResponse::parse(tokenRequest.sharedKey(), data); 248 if (!token) { 249 auto error = getResponseCode(data); 250 receiveRespond(ExceptionData { UnknownError, makeString("Unknown internal error. Error code: ", static_cast<uint8_t>(error)) }); 251 return; 252 } 253 254 m_pinAuth = token->pinAuth(requestData().hash); 255 WTF::switchOn(requestData().options, [&](const PublicKeyCredentialCreationOptions& options) { 256 makeCredential(); 257 }, [&](const PublicKeyCredentialRequestOptions& options) { 258 getAssertion(); 259 }); 260 } 261 155 262 bool CtapAuthenticator::tryDowngrade() 156 263 { -
trunk/Source/WebKit/UIProcess/WebAuthentication/fido/CtapAuthenticator.h
r254356 r254439 31 31 #include <WebCore/AuthenticatorGetInfoResponse.h> 32 32 33 namespace fido { 34 namespace pin { 35 class TokenRequest; 36 } 37 } 38 39 namespace WebCore { 40 class CryptoKeyEC; 41 } 42 33 43 namespace WebKit { 34 44 … … 46 56 47 57 void makeCredential() final; 48 void continueMakeCredentialAfterResponseReceived(Vector<uint8_t>&&) const;58 void continueMakeCredentialAfterResponseReceived(Vector<uint8_t>&&); 49 59 void getAssertion() final; 50 60 void continueGetAssertionAfterResponseReceived(Vector<uint8_t>&&); 51 61 void continueGetNextAssertionAfterResponseReceived(Vector<uint8_t>&&); 62 63 void getRetries(); 64 void continueGetKeyAgreementAfterGetRetries(Vector<uint8_t>&&); 65 void continueRequestPinAfterGetKeyAgreement(Vector<uint8_t>&&, uint64_t retries); 66 void continueGetPinTokenAfterRequestPin(const String& pin, const CryptoKeyEC&); 67 void continueRequestAfterGetPinToken(Vector<uint8_t>&&, const fido::pin::TokenRequest&); 52 68 53 69 bool tryDowngrade(); … … 58 74 size_t m_remainingAssertionResponses { 0 }; 59 75 HashSet<Ref<WebCore::AuthenticatorAssertionResponse>> m_assertionResponses; 76 Vector<uint8_t> m_pinAuth; 60 77 }; 61 78 -
trunk/Tools/ChangeLog
r254409 r254439 1 2020-01-06 Jiewen Tan <jiewen_tan@apple.com> 2 3 [WebAuthn] Support CTAP Client Pin 4 https://bugs.webkit.org/show_bug.cgi?id=191516 5 <rdar://problem/56558558> 6 7 Reviewed by Brent Fulgham. 8 9 * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: 10 * TestWebKitAPI/Tests/WebCore/CtapPinTest.cpp: 11 (TestWebKitAPI::TEST): 12 * TestWebKitAPI/Tests/WebCore/FidoTestData.h: 13 * TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm: 14 (-[TestWebAuthenticationPanelDelegate panel:requestPINWithRemainingRetries:completionHandler:]): 15 (TestWebKitAPI::TEST): 16 * TestWebKitAPI/Tests/WebKitCocoa/web-authentication-get-assertion-hid-pin.html: Added. 17 * TestWebKitAPI/Tests/WebKitCocoa/web-authentication-make-credential-hid-pin-get-key-agreement-error.html: Added. 18 * TestWebKitAPI/Tests/WebKitCocoa/web-authentication-make-credential-hid-pin-get-pin-token-error.html: Added. 19 * TestWebKitAPI/Tests/WebKitCocoa/web-authentication-make-credential-hid-pin-get-retries-error.html: Added. 20 * TestWebKitAPI/Tests/WebKitCocoa/web-authentication-make-credential-hid-pin.html: Added. 21 1 22 2020-01-11 Alex Christensen <achristensen@webkit.org> 2 23 -
trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
r254389 r254439 328 328 55A81800218102210004A39A /* 400x400-green.png in Copy Resources */ = {isa = PBXBuildFile; fileRef = 55A817FD218101DF0004A39A /* 400x400-green.png */; }; 329 329 55F9D2E52205031800A9AB38 /* AdditionalSupportedImageTypes.mm in Sources */ = {isa = PBXBuildFile; fileRef = 55F9D2E42205031800A9AB38 /* AdditionalSupportedImageTypes.mm */; }; 330 570D26F423C3CA6A00D5CF67 /* web-authentication-make-credential-hid-pin-get-key-agreement-error.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 570D26F323C3CA5500D5CF67 /* web-authentication-make-credential-hid-pin-get-key-agreement-error.html */; }; 331 570D26F623C3D33000D5CF67 /* web-authentication-make-credential-hid-pin.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 570D26F523C3D32700D5CF67 /* web-authentication-make-credential-hid-pin.html */; }; 332 570D26FA23C3F25100D5CF67 /* web-authentication-make-credential-hid-pin-get-pin-token-error.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 570D26F923C3F24500D5CF67 /* web-authentication-make-credential-hid-pin-get-pin-token-error.html */; }; 333 570D26FC23C3F87000D5CF67 /* web-authentication-get-assertion-hid-pin.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 570D26FB23C3F86500D5CF67 /* web-authentication-get-assertion-hid-pin.html */; }; 330 334 5714ECB91CA8B5B000051AC8 /* DownloadRequestOriginalURL.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5714ECB81CA8B58800051AC8 /* DownloadRequestOriginalURL.html */; }; 331 335 5714ECBB1CA8BFE400051AC8 /* DownloadRequestOriginalURLFrame.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5714ECBA1CA8BFD100051AC8 /* DownloadRequestOriginalURLFrame.html */; }; … … 344 348 574F55D2204D47F0002948C6 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 574F55D0204D471C002948C6 /* Security.framework */; }; 345 349 5758597F23A2527A00C74572 /* CtapPinTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5758597E23A2527A00C74572 /* CtapPinTest.cpp */; }; 350 5758598423C3C3A400C74572 /* web-authentication-make-credential-hid-pin-get-retries-error.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5758598323C3C36200C74572 /* web-authentication-make-credential-hid-pin-get-retries-error.html */; }; 346 351 57599E211F07191900A3FB8C /* IndexedDBStructuredCloneBackwardCompatibility.mm in Sources */ = {isa = PBXBuildFile; fileRef = 57599E201F07191700A3FB8C /* IndexedDBStructuredCloneBackwardCompatibility.mm */; }; 347 352 57599E271F071AA000A3FB8C /* IndexedDBStructuredCloneBackwardCompatibility.sqlite3 in Copy Resources */ = {isa = PBXBuildFile; fileRef = 57599E241F07192C00A3FB8C /* IndexedDBStructuredCloneBackwardCompatibility.sqlite3 */; }; … … 1481 1486 57663DF32357E48900E85E09 /* web-authentication-get-assertion-hid-cancel.html in Copy Resources */, 1482 1487 577454D02359B378008E1ED7 /* web-authentication-get-assertion-hid-no-credentials.html in Copy Resources */, 1488 570D26FC23C3F87000D5CF67 /* web-authentication-get-assertion-hid-pin.html in Copy Resources */, 1483 1489 57663DEC234F1F9300E85E09 /* web-authentication-get-assertion-hid.html in Copy Resources */, 1484 1490 579833922368FA37008E5547 /* web-authentication-get-assertion-nfc-multiple-tags.html in Copy Resources */, … … 1486 1492 577454D22359BB01008E1ED7 /* web-authentication-get-assertion-u2f-no-credentials.html in Copy Resources */, 1487 1493 57C624502346C21E00383FE7 /* web-authentication-get-assertion.html in Copy Resources */, 1494 570D26F423C3CA6A00D5CF67 /* web-authentication-make-credential-hid-pin-get-key-agreement-error.html in Copy Resources */, 1495 570D26FA23C3F25100D5CF67 /* web-authentication-make-credential-hid-pin-get-pin-token-error.html in Copy Resources */, 1496 5758598423C3C3A400C74572 /* web-authentication-make-credential-hid-pin-get-retries-error.html in Copy Resources */, 1497 570D26F623C3D33000D5CF67 /* web-authentication-make-credential-hid-pin.html in Copy Resources */, 1488 1498 5798337E236019A4008E5547 /* web-authentication-make-credential-hid.html in Copy Resources */, 1489 1499 1C2B81861C89259D00A5529F /* webfont.html in Copy Resources */, … … 1894 1904 55A817FE218101DF0004A39A /* 100x100-red.tga */ = {isa = PBXFileReference; lastKnownFileType = file; path = "100x100-red.tga"; sourceTree = "<group>"; }; 1895 1905 55F9D2E42205031800A9AB38 /* AdditionalSupportedImageTypes.mm */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; path = AdditionalSupportedImageTypes.mm; sourceTree = "<group>"; }; 1906 570D26F323C3CA5500D5CF67 /* web-authentication-make-credential-hid-pin-get-key-agreement-error.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "web-authentication-make-credential-hid-pin-get-key-agreement-error.html"; sourceTree = "<group>"; }; 1907 570D26F523C3D32700D5CF67 /* web-authentication-make-credential-hid-pin.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "web-authentication-make-credential-hid-pin.html"; sourceTree = "<group>"; }; 1908 570D26F923C3F24500D5CF67 /* web-authentication-make-credential-hid-pin-get-pin-token-error.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "web-authentication-make-credential-hid-pin-get-pin-token-error.html"; sourceTree = "<group>"; }; 1909 570D26FB23C3F86500D5CF67 /* web-authentication-get-assertion-hid-pin.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "web-authentication-get-assertion-hid-pin.html"; sourceTree = "<group>"; }; 1896 1910 5714ECB81CA8B58800051AC8 /* DownloadRequestOriginalURL.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = DownloadRequestOriginalURL.html; sourceTree = "<group>"; }; 1897 1911 5714ECBA1CA8BFD100051AC8 /* DownloadRequestOriginalURLFrame.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = DownloadRequestOriginalURLFrame.html; sourceTree = "<group>"; }; … … 1912 1926 5758597D23A2527A00C74572 /* CtapPinTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CtapPinTest.h; sourceTree = "<group>"; }; 1913 1927 5758597E23A2527A00C74572 /* CtapPinTest.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CtapPinTest.cpp; sourceTree = "<group>"; }; 1928 5758598323C3C36200C74572 /* web-authentication-make-credential-hid-pin-get-retries-error.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "web-authentication-make-credential-hid-pin-get-retries-error.html"; sourceTree = "<group>"; }; 1914 1929 57599E201F07191700A3FB8C /* IndexedDBStructuredCloneBackwardCompatibility.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = IndexedDBStructuredCloneBackwardCompatibility.mm; sourceTree = "<group>"; }; 1915 1930 57599E231F07192C00A3FB8C /* IndexedDBStructuredCloneBackwardCompatibilityWrite.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = IndexedDBStructuredCloneBackwardCompatibilityWrite.html; sourceTree = "<group>"; }; … … 3488 3503 57663DF22357E45D00E85E09 /* web-authentication-get-assertion-hid-cancel.html */, 3489 3504 577454CF2359B338008E1ED7 /* web-authentication-get-assertion-hid-no-credentials.html */, 3505 570D26FB23C3F86500D5CF67 /* web-authentication-get-assertion-hid-pin.html */, 3490 3506 57663DEB234F1F8000E85E09 /* web-authentication-get-assertion-hid.html */, 3491 3507 5798337B235EB65C008E5547 /* web-authentication-get-assertion-nfc-multiple-tags.html */, … … 3493 3509 577454D12359BAD5008E1ED7 /* web-authentication-get-assertion-u2f-no-credentials.html */, 3494 3510 57C6244F2346C1EC00383FE7 /* web-authentication-get-assertion.html */, 3511 570D26F323C3CA5500D5CF67 /* web-authentication-make-credential-hid-pin-get-key-agreement-error.html */, 3512 570D26F923C3F24500D5CF67 /* web-authentication-make-credential-hid-pin-get-pin-token-error.html */, 3513 5758598323C3C36200C74572 /* web-authentication-make-credential-hid-pin-get-retries-error.html */, 3514 570D26F523C3D32700D5CF67 /* web-authentication-make-credential-hid-pin.html */, 3495 3515 5798337D2360196D008E5547 /* web-authentication-make-credential-hid.html */, 3496 3516 51714EB21CF8C761004723C4 /* WebProcessKillIDBCleanup-1.html */, -
trunk/Tools/TestWebKitAPI/Tests/WebCore/CtapPinTest.cpp
r253811 r254439 42 42 #include <WebCore/WebAuthenticationConstants.h> 43 43 #include <WebCore/WebAuthenticationUtils.h> 44 #include < wtf/text/Base64.h>44 #include <pal/crypto/CryptoDigest.h> 45 45 46 46 namespace TestWebKitAPI { … … 99 99 result = RetriesResponse::parse(convertBytesToVector(TestData::kCtapClientPinRetriesResponse, sizeof(TestData::kCtapClientPinRetriesResponse))); 100 100 EXPECT_TRUE(result); 101 EXPECT_EQ(result->retries, 8 );101 EXPECT_EQ(result->retries, 8u); 102 102 } 103 103 … … 125 125 result = KeyAgreementResponse::parse(convertBytesToVector(TestData::kCtapClientPinTokenResponse, sizeof(TestData::kCtapClientPinTokenResponse))); // wrong response 126 126 EXPECT_FALSE(result); 127 128 #if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400) || PLATFORM(IOS) 129 result = KeyAgreementResponse::parse(convertBytesToVector(TestData::kCtapClientPinInvalidKeyAgreementResponse, sizeof(TestData::kCtapClientPinInvalidKeyAgreementResponse))); // The point is not on the curve. 130 EXPECT_FALSE(result); 131 #endif 127 132 128 133 // Test COSE … … 177 182 EXPECT_TRUE(token); 178 183 auto result = encodeAsCBOR(*token); 179 EXPECT_EQ(result.size(), 1 20u);184 EXPECT_EQ(result.size(), 103u); 180 185 EXPECT_EQ(result[0], static_cast<uint8_t>(CtapRequestCommand::kAuthenticatorClientPin)); 181 186 … … 225 230 auto sharedKeyResult = CryptoAlgorithmECDH::platformDeriveBits(downcast<CryptoKeyEC>(*keyPair.privateKey), *cosePublicKey); 226 231 EXPECT_TRUE(sharedKeyResult); 227 auto aesKey = CryptoKeyAES::importRaw(CryptoAlgorithmIdentifier::AES_CBC, WTFMove(*sharedKeyResult), true, CryptoKeyUsageDecrypt); 232 233 auto crypto = PAL::CryptoDigest::create(PAL::CryptoDigest::Algorithm::SHA_256); 234 crypto->addBytes(sharedKeyResult->data(), sharedKeyResult->size()); 235 auto sharedKeyHash = crypto->computeHash(); 236 237 auto aesKey = CryptoKeyAES::importRaw(CryptoAlgorithmIdentifier::AES_CBC, WTFMove(sharedKeyHash), true, CryptoKeyUsageDecrypt); 228 238 EXPECT_TRUE(aesKey); 229 239 230 240 const auto& it6 = responseMap.find(CBORValue(static_cast<uint8_t>(RequestKey::kPinHashEnc))); 231 241 EXPECT_NE(it6, responseMap.end()); 232 auto pinHashResult = CryptoAlgorithmAES_CBC::platformDecrypt({ }, *aesKey, it6->second.getByteString() );242 auto pinHashResult = CryptoAlgorithmAES_CBC::platformDecrypt({ }, *aesKey, it6->second.getByteString(), CryptoAlgorithmAES_CBC::Padding::No); 233 243 EXPECT_FALSE(pinHashResult.hasException()); 234 244 auto pinHash = pinHashResult.releaseReturnValue(); … … 241 251 { 242 252 const uint8_t sharedKeyData[] = { 243 0x 03, 0xac, 0x67, 0x42, 0x16, 0xf3, 0xe1, 0x5c,244 0x 76, 0x1e, 0xe1, 0xa5, 0xe2, 0x55, 0xf0, 0x67,245 0x 95, 0x36, 0x23, 0xc8, 0xb3, 0x88, 0xb4, 0x45,246 0x 9e, 0x13, 0xf9, 0x78, 0xd7, 0xc8, 0x46, 0xf4, };253 0x29, 0x9E, 0x65, 0xB8, 0xE7, 0x71, 0xB8, 0x1D, 254 0xB1, 0xC4, 0x8D, 0xBE, 0xCE, 0x50, 0x2A, 0x84, 255 0x05, 0x44, 0x7F, 0x46, 0x2D, 0xE6, 0x81, 0xFA, 256 0xEF, 0x0A, 0x6C, 0x67, 0xA7, 0x2B, 0xB5, 0x0F, }; 247 257 auto sharedKey = CryptoKeyAES::importRaw(CryptoAlgorithmIdentifier::AES_CBC, convertBytesToVector(sharedKeyData, sizeof(sharedKeyData)), true, CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt); 248 258 ASSERT_TRUE(sharedKey); … … 275 285 // 1. Generate the token. 276 286 const uint8_t sharedKeyData[] = { 277 0x 03, 0xac, 0x67, 0x42, 0x16, 0xf3, 0xe1, 0x5c,278 0x 76, 0x1e, 0xe1, 0xa5, 0xe2, 0x55, 0xf0, 0x67,279 0x 95, 0x36, 0x23, 0xc8, 0xb3, 0x88, 0xb4, 0x45,280 0x 9e, 0x13, 0xf9, 0x78, 0xd7, 0xc8, 0x46, 0xf4, };287 0x29, 0x9E, 0x65, 0xB8, 0xE7, 0x71, 0xB8, 0x1D, 288 0xB1, 0xC4, 0x8D, 0xBE, 0xCE, 0x50, 0x2A, 0x84, 289 0x05, 0x44, 0x7F, 0x46, 0x2D, 0xE6, 0x81, 0xFA, 290 0xEF, 0x0A, 0x6C, 0x67, 0xA7, 0x2B, 0xB5, 0x0F, }; 281 291 auto sharedKey = CryptoKeyAES::importRaw(CryptoAlgorithmIdentifier::AES_CBC, convertBytesToVector(sharedKeyData, sizeof(sharedKeyData)), true, CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt); 282 292 ASSERT_TRUE(sharedKey); … … 286 296 // 2. Generate the pinAuth. 287 297 auto pinAuth = result->pinAuth(convertBytesToVector(sharedKeyData, sizeof(sharedKeyData))); // sharedKeyData pretends to be clientDataHash 288 const uint8_t expectedPinAuth[] = { 0x b3, 0xc2, 0x65, 0x1c, 0xfd, 0xc8, 0x42, 0xb4, 0x60, 0x16, 0xed, 0x20, 0x64, 0x53, 0xaf, 0x84};298 const uint8_t expectedPinAuth[] = { 0x0b, 0xec, 0x9d, 0xba, 0x69, 0xb0, 0x0f, 0x45, 0x0b, 0xec, 0x66, 0xb4, 0x75, 0x7f, 0x93, 0x85 }; 289 299 EXPECT_EQ(pinAuth.size(), 16u); 290 300 EXPECT_EQ(memcmp(pinAuth.data(), expectedPinAuth, pinAuth.size()), 0); -
trunk/Tools/TestWebKitAPI/Tests/WebCore/FidoTestData.h
r254356 r254439 613 613 // True(21) 614 614 0xf5, 615 // key(8) - pin Protocol615 // key(8) - pinAuth 616 616 0x08, 617 // value - 1618 0x01,619 // key(9) - pinAuth620 0x09,621 617 // bytes(16) 622 618 0x50, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 623 0x0b, 0x0c, 0x0d, 0x0e, 0x0f 619 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 620 // key(9) - pinProtocol 621 0x09, 622 // value - 1 623 0x01, 624 624 }; 625 625 … … 746 746 // value - True(21) 747 747 0xf5, 748 // key(8) - pinProtocol 749 0x08, 750 // value - 1 751 0x01, 752 // key(9) - pinAuth 753 0x09, 748 // key(6) - pinAuth 749 0x06, 754 750 // bytes(16) 755 751 0x50, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 756 0x0b, 0x0c, 0x0d, 0x0e, 0x0f 752 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 753 // key(7) - pinProtocol 754 0x07, 755 // value - 1 756 0x01, 757 757 }; 758 758 … … 1228 1228 // key(2) - pinToken 1229 1229 0x02, 1230 // bytes( 32)1231 0x5 8, 0x20,1230 // bytes(16) 1231 0x50, 1232 1232 // encrypted token 1233 0x48, 0xb9, 0x5d, 0x3d, 0x9e, 0xee, 0xe5, 0x00, 0xab, 0x51, 0x13, 0x2b, 1234 0x35, 0x77, 0x66, 0x5c, 0x41, 0x7a, 0x56, 0x3e, 0xb3, 0xe2, 0x3c, 0xb7, 1235 0x6a, 0x37, 0xb3, 0xde, 0x57, 0x2b, 0xca, 0xaa, 1233 0x13, 0xA4, 0xEE, 0xB7, 0x0E, 0xC9, 0x1A, 0xEA, 0x00, 0x1E, 0x93, 0x16, 1234 0xF6, 0x1E, 0x41, 0xF7, 1236 1235 }; 1237 1236 … … 1269 1268 }; 1270 1269 1270 constexpr uint8_t kCtapClientPinInvalidKeyAgreementResponse[] = { 1271 // Success 1272 0x00, 1273 // map(1) 1274 0xA1, 1275 // key(1) - keyAgreement 1276 0x01, 1277 // Map(5) 1278 0xA5, 1279 // kty: EC key type 1280 0x01, 0x02, 1281 // alg: ECDH256 signature algorithm 1282 0x03, 0x38, 0x18, 1283 // crv: P-256 curve 1284 0x20, 0x01, 1285 // x-coordinate 1286 0x21, 1287 // Bytes(32) 1288 0x58, 0x20, 1289 // Byte array content 1290 0xE8, 0x76, 0x25, 0x89, 0x6E, 0xE4, 0xE4, 0x66, 0xC0, 0x32, 0x76, 0x6E, 1291 0x80, 0x87, 0x96, 0x2F, 0x36, 0xDF, 0x9D, 0xFF, 0x8B, 0x56, 0x7F, 0x37, 1292 0x63, 0x01, 0x5B, 0x19, 0x90, 0xA6, 0x0E, 0x14, 1293 // y-coordinate 1294 0x22, 1295 // Bytes(32) 1296 0x58, 0x20, 1297 // Byte array content 1298 0x27, 0xDE, 0x61, 0x2D, 0x66, 0x41, 0x8B, 0xDA, 0x19, 0x50, 0x58, 0x1E, 1299 0xBC, 0x5C, 0x8C, 0x1D, 0xAD, 0x71, 0x0C, 0xB1, 0x4C, 0x22, 0xF8, 0xC9, 1300 0x70, 0x45, 0xF4, 0x61, 0x2F, 0xB2, 0x0C, 0x91, 1301 }; 1302 1271 1303 constexpr uint8_t kCtapClientPinRetriesResponse[] = { 1272 1304 // Success -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/_WKWebAuthenticationPanel.mm
r252248 r254439 46 46 static bool webAuthenticationPanelUpdateNoCredentialsFound = false; 47 47 static bool webAuthenticationPanelCancelImmediately = false; 48 static String webAuthenticationPanelPin; 48 49 49 50 @interface TestWebAuthenticationPanelDelegate : NSObject <_WKWebAuthenticationPanelDelegate> … … 82 83 return; 83 84 } 85 } 86 87 - (void)panel:(_WKWebAuthenticationPanel *)panel requestPINWithRemainingRetries:(NSUInteger)retries completionHandler:(void (^)(NSString *))completionHandler 88 { 89 ASSERT_NE(panel, nil); 90 EXPECT_EQ(retries, 8ul); 91 completionHandler(webAuthenticationPanelPin); 84 92 } 85 93 … … 741 749 } 742 750 751 TEST(WebAuthenticationPanel, PinGetRetriesError) 752 { 753 reset(); 754 RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-hid-pin-get-retries-error" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; 755 756 auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; 757 [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()]; 758 759 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]); 760 [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; 761 [webView waitForMessage:@"Unknown internal error. Error code: 2"]; 762 } 763 764 TEST(WebAuthenticationPanel, PinGetKeyAgreementError) 765 { 766 reset(); 767 RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-hid-pin-get-key-agreement-error" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; 768 769 auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; 770 [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()]; 771 772 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]); 773 [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; 774 [webView waitForMessage:@"Unknown internal error. Error code: 2"]; 775 } 776 777 TEST(WebAuthenticationPanel, PinRequestPinErrorNoDelegate) 778 { 779 reset(); 780 RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-hid-pin" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; 781 782 auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; 783 [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()]; 784 785 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]); 786 [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; 787 [webView waitForMessage:@"Pin is not valid: "]; 788 } 789 790 TEST(WebAuthenticationPanel, PinRequestPinErrorNullDelegate) 791 { 792 reset(); 793 RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-hid-pin" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; 794 795 auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; 796 [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()]; 797 798 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]); 799 auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]); 800 [delegate setIsNull:true]; 801 [webView setUIDelegate:delegate.get()]; 802 803 [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; 804 [webView waitForMessage:@"Pin is not valid: "]; 805 } 806 807 TEST(WebAuthenticationPanel, PinRequestPinError) 808 { 809 reset(); 810 RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-hid-pin" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; 811 812 auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; 813 [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()]; 814 815 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]); 816 auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]); 817 [webView setUIDelegate:delegate.get()]; 818 819 webAuthenticationPanelPin = "123"; 820 [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; 821 [webView waitForMessage:@"Pin is not valid: 123"]; 822 } 823 824 TEST(WebAuthenticationPanel, PinGetPinTokenError) 825 { 826 reset(); 827 RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-hid-pin-get-pin-token-error" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; 828 829 auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; 830 [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()]; 831 832 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]); 833 auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]); 834 [webView setUIDelegate:delegate.get()]; 835 836 webAuthenticationPanelPin = "1234"; 837 [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; 838 [webView waitForMessage:@"Unknown internal error. Error code: 2"]; 839 } 840 841 TEST(WebAuthenticationPanel, MakeCredentialPin) 842 { 843 reset(); 844 RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-make-credential-hid-pin" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; 845 846 auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; 847 [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()]; 848 849 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]); 850 auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]); 851 [webView setUIDelegate:delegate.get()]; 852 853 webAuthenticationPanelPin = "1234"; 854 [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; 855 [webView waitForMessage:@"Succeeded!"]; 856 } 857 858 TEST(WebAuthenticationPanel, GetAssertionPin) 859 { 860 reset(); 861 RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"web-authentication-get-assertion-hid-pin" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]; 862 863 auto *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES]; 864 [[configuration preferences] _setEnabled:YES forExperimentalFeature:webAuthenticationExperimentalFeature()]; 865 866 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSZeroRect configuration:configuration]); 867 auto delegate = adoptNS([[TestWebAuthenticationPanelUIDelegate alloc] init]); 868 [webView setUIDelegate:delegate.get()]; 869 870 webAuthenticationPanelPin = "1234"; 871 [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]]; 872 [webView waitForMessage:@"Succeeded!"]; 873 } 874 743 875 } // namespace TestWebKitAPI 744 876
Note: See TracChangeset
for help on using the changeset viewer.