Source/WebCore/ChangeLog

 12019-12-17 Jiewen Tan <jiewen_tan@apple.com>
 2
 3 [WebAuthn] Implement coders for CTAP ClientPIN requests and responses
 4 https://bugs.webkit.org/show_bug.cgi?id=205376
 5 <rdar://problem/58034395>
 6
 7 Reviewed by NOBODY (OOPS!).
 8
 9 This patch implements coders for authenticatorClientPIN requests and responses
 10 following the spec:
 11 https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#authenticatorClientPIN
 12
 13 Specifically, it
 14 i) implements authenticatorClientPIN subCommand: getRetries, getKeyAgreement and getPINToken;
 15 ii) adds pinAuth/pinProtocol to authenticatorMakeCredential/authenticatorGetAssertion.
 16
 17 For the first part, it refers a Chromium patch:
 18 https://chromium-review.googlesource.com/c/chromium/src/+/1457004
 19 Specifically, it takes the interfaces from that patch. Given authenticatorClientPIN largely
 20 depends on crypto to function, this patch rewrites all crypto part of the Chromium patch
 21 which bases on BoringSSL by using WebCore's WebCrypto implementation. This allows us to
 22 focus on high level crypto interfaces, and let WebCrypto handles the underneath crypto library.
 23 Also, the original patch doesn't have any tests, this patch also introduces a large set
 24 of API tests.
 25
 26 To allow WebCrypto to be used in both the implementation and the API tests, part of it that
 27 includes AES CBC, ECDH, and HMAC has moved platform* operations to public such that callers
 28 can use those static methods directly without roundtrips to WebCrypto's web interfaces, and
 29 made headers private for TestWebKitAPI.
 30
 31 Covered by API tests.
 32
 33 * Modules/webauthn/WebAuthenticationConstants.h:
 34 * Modules/webauthn/cbor/CBORReader.cpp:
 35 (cbor::CBORReader::readCBORMap):
 36 Let CBORReader recognize negative map keys.
 37 * Modules/webauthn/fido/DeviceRequestConverter.cpp:
 38 (fido::encodeMakeCredenitalRequestAsCBOR):
 39 (fido::encodeGetAssertionRequestAsCBOR):
 40 * Modules/webauthn/fido/DeviceRequestConverter.h:
 41 * Modules/webauthn/fido/Pin.cpp: Added.
 42 (fido::pin::hasAtLeastFourCodepoints):
 43 (fido::pin::makePinAuth):
 44 (fido::pin::encodeRawPublicKey):
 45 (fido::pin::validateAndConvertToUTF8):
 46 (fido::pin::encodePinCommand):
 47 (fido::pin::RetriesResponse::parse):
 48 (fido::pin::KeyAgreementResponse::KeyAgreementResponse):
 49 (fido::pin::KeyAgreementResponse::parse):
 50 (fido::pin::KeyAgreementResponse::parseFromCOSE):
 51 (fido::pin::encodeCOSEPublicKey):
 52 (fido::pin::TokenResponse::TokenResponse):
 53 (fido::pin::TokenResponse::parse):
 54 (fido::pin::TokenResponse::pinAuth const):
 55 (fido::pin::TokenResponse::token const):
 56 (fido::pin::encodeAsCBOR):
 57 (fido::pin::TokenRequest::tryCreate):
 58 (fido::pin::TokenRequest::TokenRequest):
 59 (fido::pin::TokenRequest::sharedKey const):
 60 * Modules/webauthn/fido/Pin.h: Added.
 61 * Sources.txt:
 62 * WebCore.xcodeproj/project.pbxproj:
 63 * crypto/CryptoAlgorithm.h:
 64 * crypto/algorithms/CryptoAlgorithmAES_CBC.h:
 65 * crypto/algorithms/CryptoAlgorithmECDH.h:
 66 * crypto/algorithms/CryptoAlgorithmHMAC.h:
 67 * crypto/keys/CryptoKeyAES.cpp:
 68 * crypto/keys/CryptoKeyAES.h:
 69 * crypto/keys/CryptoKeyEC.h:
 70 * crypto/mac/CryptoAlgorithmAES_CBCMac.cpp:
 71 (WebCore::CryptoAlgorithmAES_CBC::platformEncrypt):
 72 (WebCore::CryptoAlgorithmAES_CBC::platformDecrypt):
 73 * crypto/mac/CryptoKeyRSAMac.cpp:
 74 (WebCore::CryptoKeyRSA::algorithm const):
 75
1762019-12-12 youenn fablet <youenn@apple.com>
277
378 Remove debug ASSERT in PeerConnectionBackend

Source/WebCore/Modules/webauthn/WebAuthenticationConstants.h

@@const int64_t y = -3;
3838// Values
3939const int64_t EC2 = 2;
4040const int64_t ES256 = -7;
 41const int64_t ECDH256 = -25;
4142const int64_t P_256 = 1;
4243
4344} // namespace COSE

Source/WebCore/Modules/webauthn/cbor/CBORReader.cpp

@@Optional<CBORValue> CBORReader::readCBORMap(uint64_t length, int maxNestingLevel
269269 return WTF::nullopt;
270270
271271 // Only CBOR maps with integer or string type keys are allowed.
272  if (key.value().type() != CBORValue::Type::String && key.value().type() != CBORValue::Type::Unsigned) {
 272 if (key->isString() && key->isInteger()) {
273273 m_errorCode = DecoderError::IncorrectMapKeyType;
274274 return WTF::nullopt;
275275 }

Source/WebCore/Modules/webauthn/fido/DeviceRequestConverter.cpp

@@static CBORValue convertDescriptorToCBOR(const PublicKeyCredentialDescriptor& de
8787 return CBORValue(WTFMove(cborDescriptorMap));
8888}
8989
90 Vector<uint8_t> encodeMakeCredenitalRequestAsCBOR(const Vector<uint8_t>& hash, const PublicKeyCredentialCreationOptions& options, UVAvailability uvCapability)
 90Vector<uint8_t> encodeMakeCredenitalRequestAsCBOR(const Vector<uint8_t>& hash, const PublicKeyCredentialCreationOptions& options, UVAvailability uvCapability, Optional<PinParameters> pin)
9191{
9292 CBORValue::MapValue cborMap;
9393 cborMap[CBORValue(1)] = CBORValue(hash);

@@Vector<uint8_t> encodeMakeCredenitalRequestAsCBOR(const Vector<uint8_t>& hash, c
124124 if (!optionMap.empty())
125125 cborMap[CBORValue(7)] = CBORValue(WTFMove(optionMap));
126126
 127 if (pin) {
 128 ASSERT(pin->protocol >= 0);
 129 cborMap[CBORValue(8)] = CBORValue(pin->protocol);
 130 cborMap[CBORValue(9)] = CBORValue(WTFMove(pin->auth));
 131 }
 132
127133 auto serializedParam = CBORWriter::write(CBORValue(WTFMove(cborMap)));
128134 ASSERT(serializedParam);
129135

@@Vector<uint8_t> encodeMakeCredenitalRequestAsCBOR(const Vector<uint8_t>& hash, c
132138 return cborRequest;
133139}
134140
135 Vector<uint8_t> encodeGetAssertionRequestAsCBOR(const Vector<uint8_t>& hash, const PublicKeyCredentialRequestOptions& options, UVAvailability uvCapability)
 141Vector<uint8_t> encodeGetAssertionRequestAsCBOR(const Vector<uint8_t>& hash, const PublicKeyCredentialRequestOptions& options, UVAvailability uvCapability, Optional<PinParameters> pin)
136142{
137143 CBORValue::MapValue cborMap;
138144 cborMap[CBORValue(1)] = CBORValue(options.rpId);

@@Vector<uint8_t> encodeGetAssertionRequestAsCBOR(const Vector<uint8_t>& hash, con
164170 if (!optionMap.empty())
165171 cborMap[CBORValue(5)] = CBORValue(WTFMove(optionMap));
166172
 173 if (pin) {
 174 ASSERT(pin->protocol >= 0);
 175 cborMap[CBORValue(8)] = CBORValue(pin->protocol);
 176 cborMap[CBORValue(9)] = CBORValue(WTFMove(pin->auth));
 177 }
 178
167179 auto serializedParam = CBORWriter::write(CBORValue(WTFMove(cborMap)));
168180 ASSERT(serializedParam);
169181

Source/WebCore/Modules/webauthn/fido/DeviceRequestConverter.h

@@struct PublicKeyCredentialRequestOptions;
4242
4343namespace fido {
4444
 45struct PinParameters {
 46 int protocol;
 47 Vector<uint8_t> auth;
 48};
 49
4550// Serializes MakeCredential request parameter into CBOR encoded map with
4651// integer keys and CBOR encoded values as defined by the CTAP spec.
4752// https://fidoalliance.org/specs/fido-v2.0-ps-20170927/fido-client-to-authenticator-protocol-v2.0-ps-20170927.html#authenticatorMakeCredential
48 WEBCORE_EXPORT Vector<uint8_t> encodeMakeCredenitalRequestAsCBOR(const Vector<uint8_t>& hash, const WebCore::PublicKeyCredentialCreationOptions&, AuthenticatorSupportedOptions::UserVerificationAvailability);
 53WEBCORE_EXPORT Vector<uint8_t> encodeMakeCredenitalRequestAsCBOR(const Vector<uint8_t>& hash, const WebCore::PublicKeyCredentialCreationOptions&, AuthenticatorSupportedOptions::UserVerificationAvailability, Optional<PinParameters> pin = WTF::nullopt);
4954
5055// Serializes GetAssertion request parameter into CBOR encoded map with
5156// integer keys and CBOR encoded values as defined by the CTAP spec.
5257// https://fidoalliance.org/specs/fido-v2.0-ps-20170927/fido-client-to-authenticator-protocol-v2.0-ps-20170927.html#authenticatorGetAssertion
53 WEBCORE_EXPORT Vector<uint8_t> encodeGetAssertionRequestAsCBOR(const Vector<uint8_t>& hash, const WebCore::PublicKeyCredentialRequestOptions&, AuthenticatorSupportedOptions::UserVerificationAvailability);
 58WEBCORE_EXPORT Vector<uint8_t> encodeGetAssertionRequestAsCBOR(const Vector<uint8_t>& hash, const WebCore::PublicKeyCredentialRequestOptions&, AuthenticatorSupportedOptions::UserVerificationAvailability, Optional<PinParameters> pin = WTF::nullopt);
5459
5560// Represents CTAP requests with empty parameters, including
5661// AuthenticatorGetInfo, AuthenticatorReset and AuthenticatorGetNextAssertion commands.

Source/WebCore/Modules/webauthn/fido/Pin.cpp

 1// Copyright 2019 The Chromium Authors. All rights reserved.
 2// Copyright (C) 2019 Apple Inc. All rights reserved.
 3//
 4// Redistribution and use in source and binary forms, with or without
 5// modification, are permitted provided that the following conditions are
 6// met:
 7//
 8// * Redistributions of source code must retain the above copyright
 9// notice, this list of conditions and the following disclaimer.
 10// * Redistributions in binary form must reproduce the above
 11// copyright notice, this list of conditions and the following disclaimer
 12// in the documentation and/or other materials provided with the
 13// distribution.
 14// * Neither the name of Google Inc. nor the names of its
 15// contributors may be used to endorse or promote products derived from
 16// this software without specific prior written permission.
 17//
 18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 29
 30#include "config.h"
 31#include "Pin.h"
 32
 33#if ENABLE(WEB_AUTHN)
 34
 35#include "CBORReader.h"
 36#include "CBORWriter.h"
 37#include "CryptoAlgorithmAES_CBC.h"
 38#include "CryptoAlgorithmAesCbcCfbParams.h"
 39#include "CryptoAlgorithmECDH.h"
 40#include "CryptoAlgorithmHMAC.h"
 41#include "CryptoKeyAES.h"
 42#include "CryptoKeyEC.h"
 43#include "CryptoKeyHMAC.h"
 44#include <pal/crypto/CryptoDigest.h>
 45
 46namespace fido {
 47namespace pin {
 48using namespace cbor;
 49
 50// hasAtLeastFourCodepoints returns true if |pin| contains
 51// four or more code points. This reflects the "4 Unicode characters"
 52// requirement in CTAP2.
 53static bool hasAtLeastFourCodepoints(const String& pin)
 54{
 55 return pin.length() >= 4;
 56}
 57
 58// makePinAuth returns `LEFT(HMAC-SHA-256(secret, data), 16)`.
 59static Vector<uint8_t> makePinAuth(const CryptoKeyHMAC& key, const Vector<uint8_t>& data)
 60{
 61 auto result = CryptoAlgorithmHMAC::platformSign(key, data);
 62 ASSERT(!result.hasException());
 63 auto pinAuth = result.releaseReturnValue();
 64 pinAuth.shrink(16);
 65 return pinAuth;
 66}
 67
 68Vector<uint8_t> encodeRawPublicKey(const Vector<uint8_t>& x, const Vector<uint8_t>& y)
 69{
 70 Vector<uint8_t> rawKey;
 71 rawKey.reserveCapacity(1 + x.size() + y.size());
 72 rawKey.append(0x04);
 73 rawKey.appendVector(x);
 74 rawKey.appendVector(y);
 75 return rawKey;
 76}
 77
 78Optional<CString> validateAndConvertToUTF8(const String& pin)
 79{
 80 if (!hasAtLeastFourCodepoints(pin))
 81 return WTF::nullopt;
 82 auto result = pin.utf8();
 83 if (result.length() < kMinBytes || result.length() > kMaxBytes)
 84 return WTF::nullopt;
 85 return result;
 86}
 87
 88// encodePINCommand returns a CTAP2 PIN command for the operation |subcommand|.
 89// Additional elements of the top-level CBOR map can be added with the optional
 90// |addAdditional| callback.
 91static Vector<uint8_t> encodePinCommand(Subcommand subcommand, Function<void(CBORValue::MapValue*)> addAdditional = nullptr)
 92{
 93 CBORValue::MapValue map;
 94 map.emplace(static_cast<int>(RequestKey::kProtocol), kProtocolVersion);
 95 map.emplace(static_cast<int>(RequestKey::kSubcommand), static_cast<int>(subcommand));
 96
 97 if (addAdditional)
 98 addAdditional(&map);
 99
 100 // FIXME(205375)
 101 auto serializedParam = CBORWriter::write(CBORValue(WTFMove(map)));
 102 ASSERT(serializedParam);
 103
 104 Vector<uint8_t> cborRequest({ static_cast<uint8_t>(CtapRequestCommand::kAuthenticatorClientPin) });
 105 cborRequest.appendVector(*serializedParam);
 106 return cborRequest;
 107}
 108
 109RetriesResponse::RetriesResponse() = default;
 110
 111// static
 112Optional<RetriesResponse> RetriesResponse::parse(const Vector<uint8_t>& inBuffer)
 113{
 114 // FIXME(205375)
 115 if (inBuffer.size() <= kResponseCodeLength || getResponseCode(inBuffer) != CtapDeviceResponseCode::kSuccess)
 116 return WTF::nullopt;
 117
 118 Vector<uint8_t> buffer;
 119 buffer.append(inBuffer.data() + 1, inBuffer.size() - 1);
 120 Optional<CBOR> decodedResponse = cbor::CBORReader::read(buffer);
 121 if (!decodedResponse || !decodedResponse->isMap())
 122 return WTF::nullopt;
 123 const auto& responseMap = decodedResponse->getMap();
 124
 125 auto it = responseMap.find(CBORValue(static_cast<int>(ResponseKey::kRetries)));
 126 if (it == responseMap.end() || !it->second.isUnsigned())
 127 return WTF::nullopt;
 128
 129 RetriesResponse ret;
 130 ret.retries = static_cast<int>(it->second.getUnsigned());
 131 return ret;
 132}
 133
 134KeyAgreementResponse::KeyAgreementResponse(Ref<CryptoKeyEC>&& peerKey)
 135 : peerKey(WTFMove(peerKey))
 136{
 137}
 138
 139// static
 140Optional<KeyAgreementResponse> KeyAgreementResponse::parse(const Vector<uint8_t>& inBuffer)
 141{
 142 // FIXME(205375)
 143 if (inBuffer.size() <= kResponseCodeLength || getResponseCode(inBuffer) != CtapDeviceResponseCode::kSuccess)
 144 return WTF::nullopt;
 145
 146 Vector<uint8_t> buffer;
 147 buffer.append(inBuffer.data() + 1, inBuffer.size() - 1);
 148 auto decodedResponse = cbor::CBORReader::read(buffer);
 149 if (!decodedResponse || !decodedResponse->isMap())
 150 return WTF::nullopt;
 151 const auto& responseMap = decodedResponse->getMap();
 152
 153 // The ephemeral key is encoded as a COSE structure.
 154 auto it = responseMap.find(CBORValue(static_cast<int>(ResponseKey::kKeyAgreement)));
 155 if (it == responseMap.end() || !it->second.isMap())
 156 return WTF::nullopt;
 157 const auto& coseKey = it->second.getMap();
 158
 159 return parseFromCOSE(coseKey);
 160}
 161
 162// static
 163Optional<KeyAgreementResponse> KeyAgreementResponse::parseFromCOSE(const CBORValue::MapValue& coseKey)
 164{
 165 // The COSE key must be a P-256 point. See
 166 // https://tools.ietf.org/html/rfc8152#section-7.1
 167 for (const auto& pair : Vector<std::pair<int, int>>({
 168 {1 /* key type */, 2 /* elliptic curve, uncompressed */},
 169 {3 /* algorithm */, -25 /* ECDH, ephemeral–static, HKDF-SHA-256 */},
 170 {-1 /* curve */, 1 /* P-256 */},
 171 })) {
 172 auto it = coseKey.find(CBORValue(pair.first));
 173 if (it == coseKey.end() || !it->second.isInteger() || it->second.getInteger() != pair.second)
 174 return WTF::nullopt;
 175 }
 176
 177 // See https://tools.ietf.org/html/rfc8152#section-13.1.1
 178 const auto& xIt = coseKey.find(CBORValue(-2));
 179 const auto& yIt = coseKey.find(CBORValue(-3));
 180 if (xIt == coseKey.end() || yIt == coseKey.end() || !xIt->second.isByteString() || !yIt->second.isByteString())
 181 return WTF::nullopt;
 182
 183 const auto& x = xIt->second.getByteString();
 184 const auto& y = yIt->second.getByteString();
 185 auto peerKey = CryptoKeyEC::importRaw(CryptoAlgorithmIdentifier::ECDH, "P-256", encodeRawPublicKey(x, y), true, CryptoKeyUsageDeriveBits);
 186 if (!peerKey)
 187 return WTF::nullopt;
 188
 189 return KeyAgreementResponse(peerKey.releaseNonNull());
 190}
 191
 192cbor::CBORValue::MapValue encodeCOSEPublicKey(const Vector<uint8_t>& rawPublicKey)
 193{
 194 ASSERT(rawPublicKey.size() == 65);
 195 Vector<uint8_t> x;
 196 x.append(rawPublicKey.data() + 1, ES256FieldElementLength);
 197 Vector<uint8_t> y;
 198 y.append(rawPublicKey.data() + 1 + ES256FieldElementLength, ES256FieldElementLength);
 199
 200 cbor::CBORValue::MapValue publicKeyMap;
 201 publicKeyMap[cbor::CBORValue(COSE::kty)] = cbor::CBORValue(COSE::EC2);
 202 publicKeyMap[cbor::CBORValue(COSE::alg)] = cbor::CBORValue(COSE::ECDH256);
 203 publicKeyMap[cbor::CBORValue(COSE::crv)] = cbor::CBORValue(COSE::P_256);
 204 publicKeyMap[cbor::CBORValue(COSE::x)] = cbor::CBORValue(WTFMove(x));
 205 publicKeyMap[cbor::CBORValue(COSE::y)] = cbor::CBORValue(WTFMove(y));
 206
 207 return publicKeyMap;
 208}
 209
 210TokenResponse::TokenResponse(Ref<WebCore::CryptoKeyHMAC>&& token)
 211 : m_token(WTFMove(token))
 212{
 213}
 214
 215Optional<TokenResponse> TokenResponse::parse(const WebCore::CryptoKeyAES& sharedKey, const Vector<uint8_t>& inBuffer)
 216{
 217 // FIXME(205375)
 218 if (inBuffer.size() <= kResponseCodeLength || getResponseCode(inBuffer) != CtapDeviceResponseCode::kSuccess)
 219 return WTF::nullopt;
 220
 221 Vector<uint8_t> buffer;
 222 buffer.append(inBuffer.data() + 1, inBuffer.size() - 1);
 223 auto decodedResponse = cbor::CBORReader::read(buffer);
 224 if (!decodedResponse || !decodedResponse->isMap())
 225 return WTF::nullopt;
 226 const auto& responseMap = decodedResponse->getMap();
 227
 228 auto it = responseMap.find(CBORValue(static_cast<int>(ResponseKey::kPinToken)));
 229 if (it == responseMap.end() || !it->second.isByteString())
 230 return WTF::nullopt;
 231 const auto& encryptedToken = it->second.getByteString();
 232
 233 auto tokenResult = CryptoAlgorithmAES_CBC::platformDecrypt({ }, sharedKey, encryptedToken);
 234 if (tokenResult.hasException())
 235 return WTF::nullopt;
 236 auto token = tokenResult.releaseReturnValue();
 237
 238 auto tokenKey = CryptoKeyHMAC::importRaw(token.size() * 8, CryptoAlgorithmIdentifier::SHA_256, WTFMove(token), true, CryptoKeyUsageSign);
 239 ASSERT(tokenKey);
 240
 241 return TokenResponse(tokenKey.releaseNonNull());
 242}
 243
 244Vector<uint8_t> TokenResponse::pinAuth(const Vector<uint8_t>& clientDataHash) const
 245{
 246 return makePinAuth(m_token, clientDataHash);
 247}
 248
 249const Vector<uint8_t>& TokenResponse::token() const
 250{
 251 return m_token->key();
 252}
 253
 254// static
 255Vector<uint8_t> encodeAsCBOR(const RetriesRequest&)
 256{
 257 return encodePinCommand(Subcommand::kGetRetries);
 258}
 259
 260// static
 261Vector<uint8_t> encodeAsCBOR(const KeyAgreementRequest&)
 262{
 263 return encodePinCommand(Subcommand::kGetKeyAgreement);
 264}
 265
 266Optional<TokenRequest> TokenRequest::tryCreate(const CString& pin, const CryptoKeyEC& peerKey)
 267{
 268 // The following implements Section 5.5.4 Getting sharedSecret from Authenticator.
 269 // https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#gettingSharedSecret
 270 // 1. Generate a P256 key pair.
 271 auto keyPairResult = CryptoKeyEC::generatePair(CryptoAlgorithmIdentifier::ECDH, "P-256", true, CryptoKeyUsageDeriveBits);
 272 ASSERT(!keyPairResult.hasException());
 273 auto keyPair = keyPairResult.releaseReturnValue();
 274
 275 // 2. Use ECDH to compute the shared AES-CBC key.
 276 auto sharedKeyResult = CryptoAlgorithmECDH::platformDeriveBits(downcast<CryptoKeyEC>(*keyPair.privateKey), peerKey);
 277 if (!sharedKeyResult)
 278 return WTF::nullopt;
 279 auto sharedKey = CryptoKeyAES::importRaw(CryptoAlgorithmIdentifier::AES_CBC, WTFMove(*sharedKeyResult), true, CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt);
 280 ASSERT(sharedKey);
 281
 282 // The following encodes the public key of the above key pair into COSE format.
 283 auto rawPublicKeyResult = downcast<CryptoKeyEC>(*keyPair.publicKey).exportRaw();
 284 ASSERT(!rawPublicKeyResult.hasException());
 285 auto coseKey = encodeCOSEPublicKey(rawPublicKeyResult.returnValue());
 286
 287 // The following calculates a SHA-256 digest of the PIN, and shrink to the left 16 bytes.
 288 auto crypto = PAL::CryptoDigest::create(PAL::CryptoDigest::Algorithm::SHA_256);
 289 crypto->addBytes(pin.data(), pin.length());
 290 auto pinHash = crypto->computeHash();
 291 pinHash.shrink(16);
 292
 293 return TokenRequest(sharedKey.releaseNonNull(), WTFMove(coseKey), WTFMove(pinHash));
 294}
 295
 296TokenRequest::TokenRequest(Ref<WebCore::CryptoKeyAES>&& sharedKey, cbor::CBORValue::MapValue&& coseKey, Vector<uint8_t>&& pinHash)
 297 : m_sharedKey(WTFMove(sharedKey))
 298 , m_coseKey(WTFMove(coseKey))
 299 , m_pinHash(WTFMove(pinHash))
 300{
 301}
 302
 303const CryptoKeyAES& TokenRequest::sharedKey() const
 304{
 305 return m_sharedKey;
 306}
 307
 308// static
 309Vector<uint8_t> encodeAsCBOR(const TokenRequest& request)
 310{
 311 auto result = CryptoAlgorithmAES_CBC::platformEncrypt({ }, request.sharedKey(), request.m_pinHash);
 312 ASSERT(!result.hasException());
 313
 314 return encodePinCommand(Subcommand::kGetPinToken, [coseKey = WTFMove(request.m_coseKey), encryptedPin = result.releaseReturnValue()] (CBORValue::MapValue* map) mutable {
 315 map->emplace(static_cast<int>(RequestKey::kKeyAgreement), WTFMove(coseKey));
 316 map->emplace(static_cast<int>(RequestKey::kPinHashEnc), WTFMove(encryptedPin));
 317 });
 318}
 319
 320} // namespace pin
 321} // namespace fido
 322
 323#endif // ENABLE(WEB_AUTHN)

Source/WebCore/Modules/webauthn/fido/Pin.h

 1// Copyright 2019 The Chromium Authors. All rights reserved.
 2// Copyright (C) 2019 Apple Inc. All rights reserved.
 3//
 4// Redistribution and use in source and binary forms, with or without
 5// modification, are permitted provided that the following conditions are
 6// met:
 7//
 8// * Redistributions of source code must retain the above copyright
 9// notice, this list of conditions and the following disclaimer.
 10// * Redistributions in binary form must reproduce the above
 11// copyright notice, this list of conditions and the following disclaimer
 12// in the documentation and/or other materials provided with the
 13// distribution.
 14// * Neither the name of Google Inc. nor the names of its
 15// contributors may be used to endorse or promote products derived from
 16// this software without specific prior written permission.
 17//
 18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 29
 30// This file contains structures to implement the CTAP2 PIN protocol, version
 31// one. See
 32// https://fidoalliance.org/specs/fido-v2.0-rd-20180702/fido-client-to-authenticator-protocol-v2.0-rd-20180702.html#authenticatorClientPIN
 33
 34#pragma once
 35
 36#if ENABLE(WEB_AUTHN)
 37
 38#include "CBORValue.h"
 39#include "FidoConstants.h"
 40
 41namespace WebCore {
 42class CryptoKeyAES;
 43class CryptoKeyEC;
 44class CryptoKeyHMAC;
 45}
 46
 47namespace fido {
 48namespace pin {
 49
 50// Subcommand enumerates the subcommands to the main |authenticatorClientPIN|
 51// command. See
 52// https://fidoalliance.org/specs/fido-v2.0-rd-20180702/fido-client-to-authenticator-protocol-v2.0-rd-20180702.html#authenticatorClientPIN
 53enum class Subcommand : uint8_t {
 54 kGetRetries = 0x01,
 55 kGetKeyAgreement = 0x02,
 56 kSetPin = 0x03,
 57 kChangePin = 0x04,
 58 kGetPinToken = 0x05,
 59};
 60
 61// RequestKey enumerates the keys in the top-level CBOR map for all PIN
 62// commands.
 63enum class RequestKey : int {
 64 kProtocol = 1,
 65 kSubcommand = 2,
 66 kKeyAgreement = 3,
 67 kPinAuth = 4,
 68 kNewPinEnc = 5,
 69 kPinHashEnc = 6,
 70};
 71
 72// ResponseKey enumerates the keys in the top-level CBOR map for all PIN
 73// responses.
 74enum class ResponseKey : int {
 75 kKeyAgreement = 1,
 76 kPinToken = 2,
 77 kRetries = 3,
 78};
 79
 80// kProtocolVersion is the version of the PIN protocol that this code
 81// implements.
 82constexpr int kProtocolVersion = 1;
 83
 84// encodeCOSEPublicKey takes a raw ECDH256 public key and returns it as a COSE structure.
 85WEBCORE_EXPORT cbor::CBORValue::MapValue encodeCOSEPublicKey(const Vector<uint8_t>& key);
 86
 87// encodeRawPublicKey takes X & Y and returns them as a 0x04 || X || Y byte array.
 88WEBCORE_EXPORT Vector<uint8_t> encodeRawPublicKey(const Vector<uint8_t>& X, const Vector<uint8_t>& Y);
 89
 90// validateAndConvertToUTF8 convert the input to a UTF8 CString if it is a syntactically valid PIN.
 91WEBCORE_EXPORT Optional<CString> validateAndConvertToUTF8(const String& pin);
 92
 93// kMinBytes is the minimum number of *bytes* of PIN data that a CTAP2 device
 94// will accept. Since the PIN is UTF-8 encoded, this could be a single code
 95// point. However, the platform is supposed to additionally enforce a 4
 96// *character* minimum
 97constexpr size_t kMinBytes = 4;
 98// kMaxBytes is the maximum number of bytes of PIN data that a CTAP2 device will
 99// accept.
 100constexpr size_t kMaxBytes = 63;
 101
 102// RetriesRequest asks an authenticator for the number of remaining PIN attempts
 103// before the device is locked.
 104struct RetriesRequest {
 105};
 106
 107// RetriesResponse reflects an authenticator's response to a |RetriesRequest|.
 108struct RetriesResponse {
 109 WEBCORE_EXPORT static Optional<RetriesResponse> parse(const Vector<uint8_t>&);
 110
 111 // retries is the number of PIN attempts remaining before the authenticator
 112 // locks.
 113 int retries;
 114
 115private:
 116 RetriesResponse();
 117};
 118
 119// KeyAgreementRequest asks an authenticator for an ephemeral ECDH key for
 120// encrypting PIN material in future requests.
 121struct KeyAgreementRequest {
 122};
 123
 124// KeyAgreementResponse reflects an authenticator's response to a
 125// |KeyAgreementRequest| and is also used as representation of the
 126// authenticator's ephemeral key.
 127struct KeyAgreementResponse {
 128 WEBCORE_EXPORT static Optional<KeyAgreementResponse> parse(const Vector<uint8_t>&);
 129 WEBCORE_EXPORT static Optional<KeyAgreementResponse> parseFromCOSE(const cbor::CBORValue::MapValue&);
 130
 131 Ref<WebCore::CryptoKeyEC> peerKey;
 132
 133private:
 134 explicit KeyAgreementResponse(Ref<WebCore::CryptoKeyEC>&&);
 135};
 136
 137// TokenRequest requests a pin-token from an authenticator. These tokens can be
 138// used to show user-verification in other operations, e.g. when getting an
 139// assertion.
 140class TokenRequest {
 141 WTF_MAKE_NONCOPYABLE(TokenRequest);
 142public:
 143 WEBCORE_EXPORT static Optional<TokenRequest> tryCreate(const CString& pin, const WebCore::CryptoKeyEC&);
 144 TokenRequest(TokenRequest&&) = default;
 145
 146 // sharedKey returns the shared ECDH key that was used to encrypt the PIN.
 147 // This is needed to decrypt the response.
 148 const WebCore::CryptoKeyAES& sharedKey() const;
 149
 150 friend Vector<uint8_t> encodeAsCBOR(const TokenRequest&);
 151
 152private:
 153 TokenRequest(Ref<WebCore::CryptoKeyAES>&& sharedKey, cbor::CBORValue::MapValue&& coseKey, Vector<uint8_t>&& pinHash);
 154
 155 Ref<WebCore::CryptoKeyAES> m_sharedKey;
 156 mutable cbor::CBORValue::MapValue m_coseKey;
 157 Vector<uint8_t> m_pinHash; // Only the left 16 bytes are kept.
 158};
 159
 160// TokenResponse represents the response to a pin-token request. In order to
 161// decrypt a response, the shared key from the request is needed. Once a pin-
 162// token has been decrypted, it can be used to calculate the pinAuth parameters
 163// needed to show user-verification in future operations.
 164class TokenResponse {
 165public:
 166 WEBCORE_EXPORT static Optional<TokenResponse> parse(const WebCore::CryptoKeyAES& sharedKey, const Vector<uint8_t>& inBuffer);
 167
 168 // pinAuth returns a pinAuth parameter for a request that will use the given
 169 // client-data hash.
 170 WEBCORE_EXPORT Vector<uint8_t> pinAuth(const Vector<uint8_t>& clientDataHash) const;
 171
 172 WEBCORE_EXPORT const Vector<uint8_t>& token() const;
 173
 174private:
 175 explicit TokenResponse(Ref<WebCore::CryptoKeyHMAC>&&);
 176
 177 Ref<WebCore::CryptoKeyHMAC> m_token;
 178};
 179
 180WEBCORE_EXPORT Vector<uint8_t> encodeAsCBOR(const RetriesRequest&);
 181WEBCORE_EXPORT Vector<uint8_t> encodeAsCBOR(const KeyAgreementRequest&);
 182WEBCORE_EXPORT Vector<uint8_t> encodeAsCBOR(const TokenRequest&);
 183
 184} // namespace pin
 185} // namespace fido
 186
 187#endif // ENABLE(WEB_AUTHN)

Source/WebCore/Sources.txt

@@Modules/webauthn/fido/FidoConstants.cpp
286286Modules/webauthn/fido/FidoHidMessage.cpp
287287Modules/webauthn/fido/FidoHidPacket.cpp
288288Modules/webauthn/fido/FidoParsingUtils.cpp
 289Modules/webauthn/fido/Pin.cpp
289290Modules/webauthn/fido/U2fCommandConstructor.cpp
290291Modules/webauthn/fido/U2fResponseConverter.cpp
291292

Source/WebCore/WebCore.xcodeproj/project.pbxproj

17591759 57156114234C7FD6008FC7AB /* JSMockWebAuthenticationConfiguration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 57156111234C7FBC008FC7AB /* JSMockWebAuthenticationConfiguration.cpp */; };
17601760 57156115234C7FDC008FC7AB /* JSMockWebAuthenticationConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 57156110234C7FBC008FC7AB /* JSMockWebAuthenticationConfiguration.h */; };
17611761 571F21891DA57C54005C9EFD /* JSSubtleCrypto.h in Headers */ = {isa = PBXBuildFile; fileRef = 571F21881DA57C54005C9EFD /* JSSubtleCrypto.h */; };
1762  572093D31DDCEB9A00310AB0 /* CryptoAlgorithmAesCbcCfbParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 572093D21DDCEB9A00310AB0 /* CryptoAlgorithmAesCbcCfbParams.h */; };
 1762 572093D31DDCEB9A00310AB0 /* CryptoAlgorithmAesCbcCfbParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 572093D21DDCEB9A00310AB0 /* CryptoAlgorithmAesCbcCfbParams.h */; settings = {ATTRIBUTES = (Private, ); }; };
17631763 5721A9871ECE53B10081295A /* CryptoDigestAlgorithm.h in Headers */ = {isa = PBXBuildFile; fileRef = 5721A9861ECE53B10081295A /* CryptoDigestAlgorithm.h */; };
17641764 5721A98B1ECE57040081295A /* CryptoAlgorithmRsaPssParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 5721A9881ECE57040081295A /* CryptoAlgorithmRsaPssParams.h */; };
 1765 572576D623A8872B00909540 /* CryptoKeyFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C9ACAC91F40B96A00F3AA09 /* CryptoKeyFormat.h */; settings = {ATTRIBUTES = (Private, ); }; };
17651766 572A7F211C6E5719009C6149 /* SimulatedClick.h in Headers */ = {isa = PBXBuildFile; fileRef = 572A7F201C6E5719009C6149 /* SimulatedClick.h */; };
17661767 572B401F21757A64000AD43E /* DeviceRequestConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = 572B401D21757A64000AD43E /* DeviceRequestConverter.h */; settings = {ATTRIBUTES = (Private, ); }; };
17671768 572B402C21769020000AD43E /* JSUserVerificationRequirement.h in Headers */ = {isa = PBXBuildFile; fileRef = 572B402A2176901F000AD43E /* JSUserVerificationRequirement.h */; };

17881789 57303C2C2009B4A800355965 /* AuthenticatorAssertionResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 57303C272009B2FC00355965 /* AuthenticatorAssertionResponse.h */; settings = {ATTRIBUTES = (Private, ); }; };
17891790 57303C2F2009B7E100355965 /* JSAuthenticatorAssertionResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 57303C2D2009B7D900355965 /* JSAuthenticatorAssertionResponse.h */; };
17901791 57303C4620105D2F00355965 /* AuthenticatorCoordinator.h in Headers */ = {isa = PBXBuildFile; fileRef = 57303C4320105B3D00355965 /* AuthenticatorCoordinator.h */; settings = {ATTRIBUTES = (Private, ); }; };
1791  573489391DAC6B6E00DC0667 /* CryptoAlgorithmParameters.h in Headers */ = {isa = PBXBuildFile; fileRef = 573489381DAC6B6D00DC0667 /* CryptoAlgorithmParameters.h */; };
 1792 573489391DAC6B6E00DC0667 /* CryptoAlgorithmParameters.h in Headers */ = {isa = PBXBuildFile; fileRef = 573489381DAC6B6D00DC0667 /* CryptoAlgorithmParameters.h */; settings = {ATTRIBUTES = (Private, ); }; };
17921793 5739E12F1DAC7F7800E14383 /* JSCryptoAlgorithmParameters.h in Headers */ = {isa = PBXBuildFile; fileRef = 5739E12E1DAC7F7800E14383 /* JSCryptoAlgorithmParameters.h */; };
17931794 573F5332216806E10045587A /* FidoHidMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = 57BAF28A2167D303008E954E /* FidoHidMessage.h */; settings = {ATTRIBUTES = (Private, ); }; };
17941795 573F533721680D150045587A /* FidoParsingUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 573F533521680D140045587A /* FidoParsingUtils.h */; settings = {ATTRIBUTES = (Private, ); }; };
17951796 574F55E1204F3B23002948C6 /* WebAuthenticationConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 574F55DC204F3732002948C6 /* WebAuthenticationConstants.h */; settings = {ATTRIBUTES = (Private, ); }; };
1796  5750A9751E68D00000705C4A /* CryptoKeyEC.h in Headers */ = {isa = PBXBuildFile; fileRef = 5750A9731E68D00000705C4A /* CryptoKeyEC.h */; };
 1797 5750A9751E68D00000705C4A /* CryptoKeyEC.h in Headers */ = {isa = PBXBuildFile; fileRef = 5750A9731E68D00000705C4A /* CryptoKeyEC.h */; settings = {ATTRIBUTES = (Private, ); }; };
17971798 5750A97E1E6A13EF00705C4A /* CryptoAlgorithmEcKeyParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 5750A97D1E6A13EF00705C4A /* CryptoAlgorithmEcKeyParams.h */; };
17981799 5750A9821E6A150800705C4A /* JSEcKeyParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 5750A9801E6A150800705C4A /* JSEcKeyParams.h */; };
1799  5750A9871E6A216800705C4A /* CryptoAlgorithmECDH.h in Headers */ = {isa = PBXBuildFile; fileRef = 5750A9851E6A216800705C4A /* CryptoAlgorithmECDH.h */; };
 1800 5750A9871E6A216800705C4A /* CryptoAlgorithmECDH.h in Headers */ = {isa = PBXBuildFile; fileRef = 5750A9851E6A216800705C4A /* CryptoAlgorithmECDH.h */; settings = {ATTRIBUTES = (Private, ); }; };
18001801 5754719F1ECE628300DD63B2 /* JSRsaPssParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 575471991ECE5D2A00DD63B2 /* JSRsaPssParams.h */; };
18011802 57585961239F124D00C74572 /* JSAuthenticationExtensionsClientOutputs.h in Headers */ = {isa = PBXBuildFile; fileRef = 5758595E239F117300C74572 /* JSAuthenticationExtensionsClientOutputs.h */; };
18021803 5758596C239F321C00C74572 /* AuthenticationExtensionsClientOutputs.h in Headers */ = {isa = PBXBuildFile; fileRef = 57585965239F14CC00C74572 /* AuthenticationExtensionsClientOutputs.h */; settings = {ATTRIBUTES = (Private, ); }; };
 1804 5758597C23A1FCF300C74572 /* Pin.h in Headers */ = {isa = PBXBuildFile; fileRef = 5758597923A1FCF200C74572 /* Pin.h */; settings = {ATTRIBUTES = (Private, ); }; };
18031805 5760827220215A5500116678 /* AuthenticatorCoordinatorClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 576082702021513F00116678 /* AuthenticatorCoordinatorClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
18041806 5768142A1E6F99C100E77754 /* CryptoAlgorithmEcdhKeyDeriveParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 576814291E6F99C100E77754 /* CryptoAlgorithmEcdhKeyDeriveParams.h */; };
18051807 576814411E709FA400E77754 /* JSEcdhKeyDeriveParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 5768143E1E709C3600E77754 /* JSEcdhKeyDeriveParams.h */; };

18351837 57E1E5AD1E8DD09B00EE37C9 /* JSAesCtrParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 57E1E5AB1E8DD09B00EE37C9 /* JSAesCtrParams.h */; };
18361838 57E2335B1DC7D5E500F28D01 /* JSJsonWebKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 57E2335A1DC7D5E500F28D01 /* JSJsonWebKey.h */; };
18371839 57E2335D1DC7D60800F28D01 /* JSRsaOtherPrimesInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 57E2335C1DC7D60800F28D01 /* JSRsaOtherPrimesInfo.h */; };
1838  57E233631DC7DA2400F28D01 /* RsaOtherPrimesInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 57E233621DC7DA2400F28D01 /* RsaOtherPrimesInfo.h */; };
1839  57E233651DC7DB1F00F28D01 /* JsonWebKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 57E233641DC7DB1F00F28D01 /* JsonWebKey.h */; };
 1840 57E233631DC7DA2400F28D01 /* RsaOtherPrimesInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 57E233621DC7DA2400F28D01 /* RsaOtherPrimesInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
 1841 57E233651DC7DB1F00F28D01 /* JsonWebKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 57E233641DC7DB1F00F28D01 /* JsonWebKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
18401842 57E233671DCAB21C00F28D01 /* JSHmacKeyParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 57E233661DCAB21C00F28D01 /* JSHmacKeyParams.h */; };
18411843 57E2336E1DCD43FD00F28D01 /* CryptoAlgorithmRsaHashedImportParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 57E2336D1DCD43FD00F28D01 /* CryptoAlgorithmRsaHashedImportParams.h */; };
18421844 57E233711DCD468F00F28D01 /* JSRsaHashedImportParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 57E233701DCD468F00F28D01 /* JSRsaHashedImportParams.h */; };

22932295 7C8E34C71E4A33B00054CE23 /* JSDOMConvertXPathNSResolver.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C8E34AC1E4A338E0054CE23 /* JSDOMConvertXPathNSResolver.h */; settings = {ATTRIBUTES = (Private, ); }; };
22942296 7C93F34A1AA6BA5E00A98BAB /* CompiledContentExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C93F3481AA6BA5E00A98BAB /* CompiledContentExtension.h */; settings = {ATTRIBUTES = (Private, ); }; };
22952297 7C93F34E1AA6BF0700A98BAB /* ContentExtensionCompiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C93F34C1AA6BF0700A98BAB /* ContentExtensionCompiler.h */; settings = {ATTRIBUTES = (Private, ); }; };
2296  7C9ACA921F3CC0AA00F3AA09 /* CryptoKeyAlgorithm.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C9ACA8F1F3CC0AA00F3AA09 /* CryptoKeyAlgorithm.h */; };
2297  7C9ACA981F3CCDAD00F3AA09 /* CryptoAesKeyAlgorithm.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C9ACA961F3CCDAD00F3AA09 /* CryptoAesKeyAlgorithm.h */; };
2298  7C9ACA9C1F3CCDF200F3AA09 /* CryptoEcKeyAlgorithm.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C9ACA9A1F3CCDF200F3AA09 /* CryptoEcKeyAlgorithm.h */; };
2299  7C9ACAA01F3CCE3000F3AA09 /* CryptoHmacKeyAlgorithm.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C9ACA9E1F3CCE3000F3AA09 /* CryptoHmacKeyAlgorithm.h */; };
2300  7C9ACAA41F3CCE6900F3AA09 /* CryptoRsaKeyAlgorithm.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C9ACAA21F3CCE6900F3AA09 /* CryptoRsaKeyAlgorithm.h */; };
2301  7C9ACAA81F3CCEB400F3AA09 /* CryptoRsaHashedKeyAlgorithm.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C9ACAA61F3CCEB400F3AA09 /* CryptoRsaHashedKeyAlgorithm.h */; };
 2298 7C9ACA921F3CC0AA00F3AA09 /* CryptoKeyAlgorithm.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C9ACA8F1F3CC0AA00F3AA09 /* CryptoKeyAlgorithm.h */; settings = {ATTRIBUTES = (Private, ); }; };
 2299 7C9ACA981F3CCDAD00F3AA09 /* CryptoAesKeyAlgorithm.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C9ACA961F3CCDAD00F3AA09 /* CryptoAesKeyAlgorithm.h */; settings = {ATTRIBUTES = (Private, ); }; };
 2300 7C9ACA9C1F3CCDF200F3AA09 /* CryptoEcKeyAlgorithm.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C9ACA9A1F3CCDF200F3AA09 /* CryptoEcKeyAlgorithm.h */; settings = {ATTRIBUTES = (Private, ); }; };
 2301 7C9ACAA01F3CCE3000F3AA09 /* CryptoHmacKeyAlgorithm.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C9ACA9E1F3CCE3000F3AA09 /* CryptoHmacKeyAlgorithm.h */; settings = {ATTRIBUTES = (Private, ); }; };
 2302 7C9ACAA41F3CCE6900F3AA09 /* CryptoRsaKeyAlgorithm.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C9ACAA21F3CCE6900F3AA09 /* CryptoRsaKeyAlgorithm.h */; settings = {ATTRIBUTES = (Private, ); }; };
 2303 7C9ACAA81F3CCEB400F3AA09 /* CryptoRsaHashedKeyAlgorithm.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C9ACAA61F3CCEB400F3AA09 /* CryptoRsaHashedKeyAlgorithm.h */; settings = {ATTRIBUTES = (Private, ); }; };
23022304 7C9ACAB81F3CF1AE00F3AA09 /* JSCryptoAesKeyAlgorithm.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C9ACAAA1F3CDB6300F3AA09 /* JSCryptoAesKeyAlgorithm.h */; };
23032305 7C9ACABA1F3CF1AE00F3AA09 /* JSCryptoEcKeyAlgorithm.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C9ACAAC1F3CDB9D00F3AA09 /* JSCryptoEcKeyAlgorithm.h */; };
23042306 7C9ACABC1F3CF1AE00F3AA09 /* JSCryptoHmacKeyAlgorithm.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C9ACAAF1F3CDB9F00F3AA09 /* JSCryptoHmacKeyAlgorithm.h */; };

46914693 E124748410AA161D00B79493 /* AuthenticationClient.h in Headers */ = {isa = PBXBuildFile; fileRef = E124748310AA161D00B79493 /* AuthenticationClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
46924694 E125F82C1822CFEC00D84CD9 /* CryptoAlgorithmSHA1.h in Headers */ = {isa = PBXBuildFile; fileRef = E125F82A1822CFEC00D84CD9 /* CryptoAlgorithmSHA1.h */; };
46934695 E125F8321822F11B00D84CD9 /* CryptoAlgorithmHMAC.h in Headers */ = {isa = PBXBuildFile; fileRef = E125F8301822F11B00D84CD9 /* CryptoAlgorithmHMAC.h */; };
4694  E125F8361822F18A00D84CD9 /* CryptoKeyHMAC.h in Headers */ = {isa = PBXBuildFile; fileRef = E125F8341822F18A00D84CD9 /* CryptoKeyHMAC.h */; };
4695  E125F8421824253A00D84CD9 /* CryptoAlgorithmAES_CBC.h in Headers */ = {isa = PBXBuildFile; fileRef = E125F8401824253A00D84CD9 /* CryptoAlgorithmAES_CBC.h */; };
4696  E125F84E1824289D00D84CD9 /* CryptoKeyAES.h in Headers */ = {isa = PBXBuildFile; fileRef = E125F84C1824289D00D84CD9 /* CryptoKeyAES.h */; };
 4696 E125F8361822F18A00D84CD9 /* CryptoKeyHMAC.h in Headers */ = {isa = PBXBuildFile; fileRef = E125F8341822F18A00D84CD9 /* CryptoKeyHMAC.h */; settings = {ATTRIBUTES = (Private, ); }; };
 4697 E125F8421824253A00D84CD9 /* CryptoAlgorithmAES_CBC.h in Headers */ = {isa = PBXBuildFile; fileRef = E125F8401824253A00D84CD9 /* CryptoAlgorithmAES_CBC.h */; settings = {ATTRIBUTES = (Private, ); }; };
 4698 E125F84E1824289D00D84CD9 /* CryptoKeyAES.h in Headers */ = {isa = PBXBuildFile; fileRef = E125F84C1824289D00D84CD9 /* CryptoKeyAES.h */; settings = {ATTRIBUTES = (Private, ); }; };
46974699 E12719C70EEEC16800F61213 /* NavigatorBase.h in Headers */ = {isa = PBXBuildFile; fileRef = E12719C60EEEC16800F61213 /* NavigatorBase.h */; };
46984700 E1271A0B0EEEC77A00F61213 /* WorkerNavigator.h in Headers */ = {isa = PBXBuildFile; fileRef = E1271A0A0EEEC77A00F61213 /* WorkerNavigator.h */; };
46994701 E1271A580EEECDE400F61213 /* JSWorkerNavigator.h in Headers */ = {isa = PBXBuildFile; fileRef = E1271A560EEECDE400F61213 /* JSWorkerNavigator.h */; };

47084710 E14F1C4514B5DAC600EA9009 /* HTMLFormControlElementWithState.h in Headers */ = {isa = PBXBuildFile; fileRef = E14F1C4314B5DAC600EA9009 /* HTMLFormControlElementWithState.h */; settings = {ATTRIBUTES = (Private, ); }; };
47094711 E152551516FD2350003D7ADB /* WebCoreResourceHandleAsOperationQueueDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = E152551316FD234F003D7ADB /* WebCoreResourceHandleAsOperationQueueDelegate.h */; };
47104712 E157A8E11817331C009F821D /* JSCryptoKey.h in Headers */ = {isa = PBXBuildFile; fileRef = E157A8DF1817331C009F821D /* JSCryptoKey.h */; };
4711  E157A8E518173A3A009F821D /* CryptoKey.h in Headers */ = {isa = PBXBuildFile; fileRef = E157A8E318173A3A009F821D /* CryptoKey.h */; };
 4713 E157A8E518173A3A009F821D /* CryptoKey.h in Headers */ = {isa = PBXBuildFile; fileRef = E157A8E318173A3A009F821D /* CryptoKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
47124714 E15A36D71104572000B7B639 /* XMLNSNames.h in Headers */ = {isa = PBXBuildFile; fileRef = E15A36D61104572000B7B639 /* XMLNSNames.h */; };
47134715 E15A36D91104572700B7B639 /* XMLNSNames.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E15A36D81104572700B7B639 /* XMLNSNames.cpp */; };
47144716 E15FF7D518C9553800FE4C87 /* KeypressCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = E15FF7D418C9553800FE4C87 /* KeypressCommand.h */; settings = {ATTRIBUTES = (Private, ); }; };

47174719 E16982551134629D00894115 /* ObjCRuntimeObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E16982541134629D00894115 /* ObjCRuntimeObject.h */; };
47184720 E16982601134636A00894115 /* ObjCRuntimeObject.mm in Sources */ = {isa = PBXBuildFile; fileRef = E169825F1134636A00894115 /* ObjCRuntimeObject.mm */; };
47194721 E16A84FA14C85CCC002977DF /* CSSBorderImage.h in Headers */ = {isa = PBXBuildFile; fileRef = E16A84F814C85CCC002977DF /* CSSBorderImage.h */; };
4720  E172AF6E180F24C600FBADB9 /* CryptoAlgorithm.h in Headers */ = {isa = PBXBuildFile; fileRef = E172AF6C180F24C600FBADB9 /* CryptoAlgorithm.h */; };
4721  E172AF70180F289500FBADB9 /* CryptoKeyUsage.h in Headers */ = {isa = PBXBuildFile; fileRef = E172AF6F180F289500FBADB9 /* CryptoKeyUsage.h */; };
 4722 E172AF6E180F24C600FBADB9 /* CryptoAlgorithm.h in Headers */ = {isa = PBXBuildFile; fileRef = E172AF6C180F24C600FBADB9 /* CryptoAlgorithm.h */; settings = {ATTRIBUTES = (Private, ); }; };
 4723 E172AF70180F289500FBADB9 /* CryptoKeyUsage.h in Headers */ = {isa = PBXBuildFile; fileRef = E172AF6F180F289500FBADB9 /* CryptoKeyUsage.h */; settings = {ATTRIBUTES = (Private, ); }; };
47224724 E172AF901811BC3700FBADB9 /* JSDOMPromiseDeferred.h in Headers */ = {isa = PBXBuildFile; fileRef = E172AF8E1811BC3700FBADB9 /* JSDOMPromiseDeferred.h */; settings = {ATTRIBUTES = (Private, ); }; };
47234725 E179F0DA1B9774FE00ED0A27 /* Internals.mm in Sources */ = {isa = PBXBuildFile; fileRef = E179F0D91B9774FE00ED0A27 /* Internals.mm */; };
47244726 E17B491616A9B094001C8839 /* TransitionEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = E17B491416A9B093001C8839 /* TransitionEvent.h */; };

47314733 E18823662031F59400B42DF3 /* VRPlatformManager.h in Headers */ = {isa = PBXBuildFile; fileRef = E18823612031F55B00B42DF3 /* VRPlatformManager.h */; settings = {ATTRIBUTES = (Private, ); }; };
47324734 E18C35441F71970C00FF632D /* WebArchiveResourceWebResourceHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = E18C35411F7196CD00FF632D /* WebArchiveResourceWebResourceHandler.h */; };
47334735 E18DF33518AAF12C00773E59 /* SerializedCryptoKeyWrap.h in Headers */ = {isa = PBXBuildFile; fileRef = E18DF33418AAF12C00773E59 /* SerializedCryptoKeyWrap.h */; settings = {ATTRIBUTES = (Private, ); }; };
4734  E19727161820549E00592D51 /* CryptoKeyType.h in Headers */ = {isa = PBXBuildFile; fileRef = E19727151820549E00592D51 /* CryptoKeyType.h */; };
 4736 E19727161820549E00592D51 /* CryptoKeyType.h in Headers */ = {isa = PBXBuildFile; fileRef = E19727151820549E00592D51 /* CryptoKeyType.h */; settings = {ATTRIBUTES = (Private, ); }; };
47354737 E19AC3EF1824DC7900349426 /* CryptoAlgorithmSHA224.h in Headers */ = {isa = PBXBuildFile; fileRef = E19AC3E71824DC7900349426 /* CryptoAlgorithmSHA224.h */; };
47364738 E19AC3F11824DC7900349426 /* CryptoAlgorithmSHA256.h in Headers */ = {isa = PBXBuildFile; fileRef = E19AC3E91824DC7900349426 /* CryptoAlgorithmSHA256.h */; };
47374739 E19AC3F31824DC7900349426 /* CryptoAlgorithmSHA384.h in Headers */ = {isa = PBXBuildFile; fileRef = E19AC3EB1824DC7900349426 /* CryptoAlgorithmSHA384.h */; };

47554757 E1C415DA0F655D6F0092D2FB /* CrossOriginPreflightResultCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E1C415D90F655D6F0092D2FB /* CrossOriginPreflightResultCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
47564758 E1C416120F6562FD0092D2FB /* CrossOriginAccessControl.h in Headers */ = {isa = PBXBuildFile; fileRef = E1C416110F6562FD0092D2FB /* CrossOriginAccessControl.h */; settings = {ATTRIBUTES = (Private, ); }; };
47574759 E1C4DE690EA75C1E0023CCD6 /* ActiveDOMObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E1C4DE680EA75C1E0023CCD6 /* ActiveDOMObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
4758  E1C657251816E69D00256CDD /* CryptoAlgorithmIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = E1C657241816E69D00256CDD /* CryptoAlgorithmIdentifier.h */; };
 4760 E1C657251816E69D00256CDD /* CryptoAlgorithmIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = E1C657241816E69D00256CDD /* CryptoAlgorithmIdentifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
47594761 E1C94AF9191303F000D5A893 /* BlobPart.h in Headers */ = {isa = PBXBuildFile; fileRef = E1C94AF7191303F000D5A893 /* BlobPart.h */; settings = {ATTRIBUTES = (Private, ); }; };
47604762 E1CAA5C60E8BD23600A73ECA /* JSWorker.h in Headers */ = {isa = PBXBuildFile; fileRef = E1CAA5C50E8BD23600A73ECA /* JSWorker.h */; };
47614763 E1CDE9221501916900862CC5 /* AsyncFileStream.h in Headers */ = {isa = PBXBuildFile; fileRef = E1CDE9211501916900862CC5 /* AsyncFileStream.h */; settings = {ATTRIBUTES = (Private, ); }; };

47684770 E1F80B8818317252007885C3 /* CryptoKeyPair.h in Headers */ = {isa = PBXBuildFile; fileRef = E1F80B8618317252007885C3 /* CryptoKeyPair.h */; settings = {ATTRIBUTES = (Private, ); }; };
47694771 E1F80B8E183172B5007885C3 /* JSCryptoKeyPair.h in Headers */ = {isa = PBXBuildFile; fileRef = E1F80B8C183172B5007885C3 /* JSCryptoKeyPair.h */; };
47704772 E1FE136B183FE1AB00892F13 /* CryptoAlgorithmRSA_OAEP.h in Headers */ = {isa = PBXBuildFile; fileRef = E1FE1369183FE1AB00892F13 /* CryptoAlgorithmRSA_OAEP.h */; };
4771  E1FE137518402A6700892F13 /* CommonCryptoUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = E1FE137318402A6700892F13 /* CommonCryptoUtilities.h */; };
 4773 E1FE137518402A6700892F13 /* CommonCryptoUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = E1FE137318402A6700892F13 /* CommonCryptoUtilities.h */; settings = {ATTRIBUTES = (Private, ); }; };
47724774 E1FE137B184D21BB00892F13 /* CryptoAlgorithmAES_KW.h in Headers */ = {isa = PBXBuildFile; fileRef = E1FE1379184D21BB00892F13 /* CryptoAlgorithmAES_KW.h */; };
47734775 E1FF57A30F01255B00891EBB /* ThreadGlobalData.h in Headers */ = {isa = PBXBuildFile; fileRef = E1FF57A20F01255B00891EBB /* ThreadGlobalData.h */; settings = {ATTRIBUTES = (Private, ); }; };
47744776 E1FF8F6D180DB5BE00132674 /* CryptoAlgorithmRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = E1FF8F6B180DB5BE00132674 /* CryptoAlgorithmRegistry.h */; };

87918793 57585969239F1EC700C74572 /* AuthenticatorResponse.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AuthenticatorResponse.cpp; sourceTree = "<group>"; };
87928794 5758596B239F284B00C74572 /* AuthenticatorAttestationResponse.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AuthenticatorAttestationResponse.cpp; sourceTree = "<group>"; };
87938795 5758596E239F397900C74572 /* AuthenticatorAssertionResponse.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = AuthenticatorAssertionResponse.cpp; sourceTree = "<group>"; };
 8796 5758597823A1FCE600C74572 /* Pin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Pin.cpp; sourceTree = "<group>"; };
 8797 5758597923A1FCF200C74572 /* Pin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Pin.h; sourceTree = "<group>"; };
87948798 5760824F20118D8D00116678 /* JSBasicCredentialCustom.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = JSBasicCredentialCustom.cpp; sourceTree = "<group>"; };
87958799 576082562011BE0200116678 /* JSAuthenticatorResponseCustom.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = JSAuthenticatorResponseCustom.cpp; sourceTree = "<group>"; };
87968800 576082702021513F00116678 /* AuthenticatorCoordinatorClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AuthenticatorCoordinatorClient.h; sourceTree = "<group>"; };

1998219986 578A4C0A2167D29600D08F34 /* FidoHidPacket.h */,
1998319987 573F533621680D150045587A /* FidoParsingUtils.cpp */,
1998419988 573F533521680D140045587A /* FidoParsingUtils.h */,
 19989 5758597823A1FCE600C74572 /* Pin.cpp */,
 19990 5758597923A1FCF200C74572 /* Pin.h */,
1998519991 57152B6A21CD995C000C37CA /* U2fCommandConstructor.cpp */,
1998619992 57152B6C21CD995C000C37CA /* U2fCommandConstructor.h */,
1998719993 57152B7B21DD8BA1000C37CA /* U2fResponseConverter.cpp */,

2940029406 E125F84E1824289D00D84CD9 /* CryptoKeyAES.h in Headers */,
2940129407 7C9ACA921F3CC0AA00F3AA09 /* CryptoKeyAlgorithm.h in Headers */,
2940229408 5750A9751E68D00000705C4A /* CryptoKeyEC.h in Headers */,
 29409 572576D623A8872B00909540 /* CryptoKeyFormat.h in Headers */,
2940329410 E125F8361822F18A00D84CD9 /* CryptoKeyHMAC.h in Headers */,
2940429411 E1F80B8818317252007885C3 /* CryptoKeyPair.h in Headers */,
2940529412 57E657DF1E71373A00F941CA /* CryptoKeyRaw.h in Headers */,

3170131708 1DBC1B562347B3D200B901AF /* PictureInPictureObserver.h in Headers */,
3170231709 1D2C82B7236A3F6A0055D6C5 /* PictureInPictureSupport.h in Headers */,
3170331710 1D2F8E062344752300993B68 /* PictureInPictureWindow.h in Headers */,
 31711 5758597C23A1FCF300C74572 /* Pin.h in Headers */,
3170431712 D0FF2A5E11F8C45A007E74E0 /* PingLoader.h in Headers */,
3170531713 CD7D33441C7A123F00041293 /* PixelBufferConformerCV.h in Headers */,
3170631714 CDEFA2281E7669E8000AE99C /* PlatformAudioData.h in Headers */,

Source/WebCore/crypto/CryptoAlgorithm.h

3131#include "CryptoKeyUsage.h"
3232#include "ExceptionOr.h"
3333#include "JsonWebKey.h"
34 #include "SubtleCrypto.h"
3534#include <wtf/Function.h>
3635#include <wtf/ThreadSafeRefCounted.h>
3736#include <wtf/Variant.h>

Source/WebCore/crypto/algorithms/CryptoAlgorithmAES_CBC.h

@@public:
4040 static constexpr CryptoAlgorithmIdentifier s_identifier = CryptoAlgorithmIdentifier::AES_CBC;
4141 static Ref<CryptoAlgorithm> create();
4242
 43 // 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>&);
 46
4347private:
4448 CryptoAlgorithmAES_CBC() = default;
4549 CryptoAlgorithmIdentifier identifier() const final;

@@private:
5054 void importKey(CryptoKeyFormat, KeyData&&, const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&) final;
5155 void exportKey(CryptoKeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&&) final;
5256 ExceptionOr<size_t> getKeyLength(const CryptoAlgorithmParameters&) final;
53 
54  static ExceptionOr<Vector<uint8_t>> platformEncrypt(const CryptoAlgorithmAesCbcCfbParams&, const CryptoKeyAES&, const Vector<uint8_t>&);
55  static ExceptionOr<Vector<uint8_t>> platformDecrypt(const CryptoAlgorithmAesCbcCfbParams&, const CryptoKeyAES&, const Vector<uint8_t>&);
5657};
5758
5859} // namespace WebCore

Source/WebCore/crypto/algorithms/CryptoAlgorithmECDH.h

@@public:
3939 static constexpr CryptoAlgorithmIdentifier s_identifier = CryptoAlgorithmIdentifier::ECDH;
4040 static Ref<CryptoAlgorithm> create();
4141
 42 // Operations can be performed directly.
 43 WEBCORE_EXPORT static Optional<Vector<uint8_t>> platformDeriveBits(const CryptoKeyEC&, const CryptoKeyEC&);
 44
4245private:
4346 CryptoAlgorithmECDH() = default;
4447 CryptoAlgorithmIdentifier identifier() const final;

@@private:
4750 void deriveBits(const CryptoAlgorithmParameters&, Ref<CryptoKey>&&, size_t length, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final;
4851 void importKey(CryptoKeyFormat, KeyData&&, const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&) final;
4952 void exportKey(CryptoKeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&&) final;
50 
51  static Optional<Vector<uint8_t>> platformDeriveBits(const CryptoKeyEC&, const CryptoKeyEC&);
5253};
5354
5455} // namespace WebCore

Source/WebCore/crypto/algorithms/CryptoAlgorithmHMAC.h

@@public:
3939 static constexpr CryptoAlgorithmIdentifier s_identifier = CryptoAlgorithmIdentifier::HMAC;
4040 static Ref<CryptoAlgorithm> create();
4141
 42 // Operations can be performed directly.
 43 static ExceptionOr<Vector<uint8_t>> platformSign(const CryptoKeyHMAC&, const Vector<uint8_t>&);
 44 static ExceptionOr<bool> platformVerify(const CryptoKeyHMAC&, const Vector<uint8_t>&, const Vector<uint8_t>&);
 45
4246private:
4347 CryptoAlgorithmHMAC() = default;
4448 CryptoAlgorithmIdentifier identifier() const final;

@@private:
4953 void importKey(CryptoKeyFormat, KeyData&&, const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&) final;
5054 void exportKey(CryptoKeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&&) final;
5155 ExceptionOr<size_t> getKeyLength(const CryptoAlgorithmParameters&) final;
52 
53  static ExceptionOr<Vector<uint8_t>> platformSign(const CryptoKeyHMAC&, const Vector<uint8_t>&);
54  static ExceptionOr<bool> platformVerify(const CryptoKeyHMAC&, const Vector<uint8_t>&, const Vector<uint8_t>&);
5556};
5657
5758} // namespace WebCore

Source/WebCore/crypto/keys/CryptoKeyAES.cpp

2828
2929#if ENABLE(WEB_CRYPTO)
3030
 31#include "CryptoAesKeyAlgorithm.h"
3132#include "CryptoAlgorithmAesKeyParams.h"
3233#include "CryptoAlgorithmRegistry.h"
3334#include "ExceptionOr.h"

Source/WebCore/crypto/keys/CryptoKeyAES.h

@@public:
5454 static bool isValidAESAlgorithm(CryptoAlgorithmIdentifier);
5555
5656 static RefPtr<CryptoKeyAES> generate(CryptoAlgorithmIdentifier, size_t lengthBits, bool extractable, CryptoKeyUsageBitmap);
57  static RefPtr<CryptoKeyAES> importRaw(CryptoAlgorithmIdentifier, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap);
 57 WEBCORE_EXPORT static RefPtr<CryptoKeyAES> importRaw(CryptoAlgorithmIdentifier, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap);
5858 using CheckAlgCallback = Function<bool(size_t, const String&)>;
5959 static RefPtr<CryptoKeyAES> importJwk(CryptoAlgorithmIdentifier, JsonWebKey&&, bool extractable, CryptoKeyUsageBitmap, CheckAlgCallback&&);
6060

Source/WebCore/crypto/keys/CryptoKeyEC.h

@@public:
6969 }
7070 virtual ~CryptoKeyEC() = default;
7171
72  static ExceptionOr<CryptoKeyPair> generatePair(CryptoAlgorithmIdentifier, const String& curve, bool extractable, CryptoKeyUsageBitmap);
73  static RefPtr<CryptoKeyEC> importRaw(CryptoAlgorithmIdentifier, const String& curve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap);
 72 WEBCORE_EXPORT static ExceptionOr<CryptoKeyPair> generatePair(CryptoAlgorithmIdentifier, const String& curve, bool extractable, CryptoKeyUsageBitmap);
 73 WEBCORE_EXPORT static RefPtr<CryptoKeyEC> importRaw(CryptoAlgorithmIdentifier, const String& curve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap);
7474 static RefPtr<CryptoKeyEC> importJwk(CryptoAlgorithmIdentifier, const String& curve, JsonWebKey&&, bool extractable, CryptoKeyUsageBitmap);
7575 static RefPtr<CryptoKeyEC> importSpki(CryptoAlgorithmIdentifier, const String& curve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap);
7676 static RefPtr<CryptoKeyEC> importPkcs8(CryptoAlgorithmIdentifier, const String& curve, Vector<uint8_t>&& keyData, bool extractable, CryptoKeyUsageBitmap);
7777
78  ExceptionOr<Vector<uint8_t>> exportRaw() const;
 78 WEBCORE_EXPORT ExceptionOr<Vector<uint8_t>> exportRaw() const;
7979 ExceptionOr<JsonWebKey> exportJwk() const;
8080 ExceptionOr<Vector<uint8_t>> exportSpki() const;
8181 ExceptionOr<Vector<uint8_t>> exportPkcs8() const;

Source/WebCore/crypto/mac/CryptoAlgorithmAES_CBCMac.cpp

@@static ExceptionOr<Vector<uint8_t>> transformAES_CBC(CCOperation operation, cons
6464
6565ExceptionOr<Vector<uint8_t>> CryptoAlgorithmAES_CBC::platformEncrypt(const CryptoAlgorithmAesCbcCfbParams& parameters, const CryptoKeyAES& key, const Vector<uint8_t>& plainText)
6666{
67  ASSERT(parameters.ivVector().size() == kCCBlockSizeAES128);
 67 ASSERT(parameters.ivVector().size() == kCCBlockSizeAES128 || parameters.ivVector().isEmpty());
6868 return transformAES_CBC(kCCEncrypt, parameters.ivVector(), key.key(), plainText);
6969}
7070
7171ExceptionOr<Vector<uint8_t>> CryptoAlgorithmAES_CBC::platformDecrypt(const CryptoAlgorithmAesCbcCfbParams& parameters, const CryptoKeyAES& key, const Vector<uint8_t>& cipherText)
7272{
73  ASSERT(parameters.ivVector().size() == kCCBlockSizeAES128);
 73 ASSERT(parameters.ivVector().size() == kCCBlockSizeAES128 || parameters.ivVector().isEmpty());
7474 return transformAES_CBC(kCCDecrypt, parameters.ivVector(), key.key(), cipherText);
7575}
7676

Source/WebCore/crypto/mac/CryptoKeyRSAMac.cpp

@@auto CryptoKeyRSA::algorithm() const -> KeyAlgorithm
201201 result.modulusLength = modulusLength;
202202 result.publicExponent = Uint8Array::tryCreate(publicExponent.data(), publicExponent.size());
203203 result.hash.name = CryptoAlgorithmRegistry::singleton().name(m_hash);
204  return result;
 204 return WTFMove(result);
205205 }
206206
207207 CryptoRsaKeyAlgorithm result;
208208 result.name = CryptoAlgorithmRegistry::singleton().name(algorithmIdentifier());
209209 result.modulusLength = modulusLength;
210210 result.publicExponent = Uint8Array::tryCreate(publicExponent.data(), publicExponent.size());
211  return result;
 211 return WTFMove(result);
212212}
213213
214214std::unique_ptr<CryptoKeyRSAComponents> CryptoKeyRSA::exportData() const

Tools/ChangeLog

 12019-12-17 Jiewen Tan <jiewen_tan@apple.com>
 2
 3 [WebAuthn] Implement coders for CTAP ClientPIN requests and responses
 4 https://bugs.webkit.org/show_bug.cgi?id=205376
 5 <rdar://problem/58034395>
 6
 7 Reviewed by NOBODY (OOPS!).
 8
 9 Adds API tests.
 10
 11 * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
 12 * TestWebKitAPI/Tests/WebCore/CtapPinTest.cpp: Added.
 13 (TestWebKitAPI::TEST):
 14 * TestWebKitAPI/Tests/WebCore/CtapRequestTest.cpp:
 15 (TestWebKitAPI::TEST):
 16 * TestWebKitAPI/Tests/WebCore/FidoTestData.h:
 17
1182019-12-11 Jonathan Bedard <jbedard@apple.com>
219
320 Python 3: Support serial ServerProcess tests

Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj

341341 573255A622139BC700396AE8 /* load-web-archive-1.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 573255A222139B8F00396AE8 /* load-web-archive-1.html */; };
342342 573255A722139BC700396AE8 /* load-web-archive-2.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 573255A322139B9000396AE8 /* load-web-archive-2.html */; };
343343 574F55D2204D47F0002948C6 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 574F55D0204D471C002948C6 /* Security.framework */; };
 344 5758597F23A2527A00C74572 /* CtapPinTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5758597E23A2527A00C74572 /* CtapPinTest.cpp */; };
344345 57599E211F07191900A3FB8C /* IndexedDBStructuredCloneBackwardCompatibility.mm in Sources */ = {isa = PBXBuildFile; fileRef = 57599E201F07191700A3FB8C /* IndexedDBStructuredCloneBackwardCompatibility.mm */; };
345346 57599E271F071AA000A3FB8C /* IndexedDBStructuredCloneBackwardCompatibility.sqlite3 in Copy Resources */ = {isa = PBXBuildFile; fileRef = 57599E241F07192C00A3FB8C /* IndexedDBStructuredCloneBackwardCompatibility.sqlite3 */; };
346347 57599E281F071AA000A3FB8C /* IndexedDBStructuredCloneBackwardCompatibility.sqlite3-shm in Copy Resources */ = {isa = PBXBuildFile; fileRef = 57599E261F07192C00A3FB8C /* IndexedDBStructuredCloneBackwardCompatibility.sqlite3-shm */; };

19011902 573255A422139B9000396AE8 /* helloworld.webarchive */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = helloworld.webarchive; sourceTree = "<group>"; };
19021903 5735F0251F3A4EA6000EE801 /* TestWebKitAPI-iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "TestWebKitAPI-iOS.entitlements"; sourceTree = "<group>"; };
19031904 574F55D0204D471C002948C6 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
 1905 5758597D23A2527A00C74572 /* CtapPinTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CtapPinTest.h; sourceTree = "<group>"; };
 1906 5758597E23A2527A00C74572 /* CtapPinTest.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CtapPinTest.cpp; sourceTree = "<group>"; };
19041907 57599E201F07191700A3FB8C /* IndexedDBStructuredCloneBackwardCompatibility.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = IndexedDBStructuredCloneBackwardCompatibility.mm; sourceTree = "<group>"; };
19051908 57599E231F07192C00A3FB8C /* IndexedDBStructuredCloneBackwardCompatibilityWrite.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = IndexedDBStructuredCloneBackwardCompatibilityWrite.html; sourceTree = "<group>"; };
19061909 57599E241F07192C00A3FB8C /* IndexedDBStructuredCloneBackwardCompatibility.sqlite3 */ = {isa = PBXFileReference; lastKnownFileType = file; path = IndexedDBStructuredCloneBackwardCompatibility.sqlite3; sourceTree = "<group>"; };

30923095 1C9EB8401E380DA1005C6442 /* ComplexTextController.cpp */,
30933096 7CB184C41AA3F2100066EDFD /* ContentExtensions.cpp */,
30943097 CD5451E919E41F9D0016936F /* CSSParser.cpp */,
 3098 5758597E23A2527A00C74572 /* CtapPinTest.cpp */,
 3099 5758597D23A2527A00C74572 /* CtapPinTest.h */,
30953100 572B403321769A88000AD43E /* CtapRequestTest.cpp */,
30963101 572B404321781B42000AD43E /* CtapResponseTest.cpp */,
30973102 260BA5781B1D2E7B004FA07C /* DFACombiner.cpp */,

45744579 7CCE7EAC1A411A3400447C4C /* Counters.cpp in Sources */,
45754580 7AEAD47F1E20116C00416EFE /* CrossPartitionFileSchemeAccess.mm in Sources */,
45764581 7CCE7EDB1A411A9200447C4C /* CSSParser.cpp in Sources */,
 4582 5758597F23A2527A00C74572 /* CtapPinTest.cpp in Sources */,
45774583 572B403421769A88000AD43E /* CtapRequestTest.cpp in Sources */,
45784584 572B404421781B43000AD43E /* CtapResponseTest.cpp in Sources */,
45794585 7AC7B57020D9BA5B002C09A0 /* CustomBundleObject.mm in Sources */,

Tools/TestWebKitAPI/Tests/WebCore/CtapPinTest.cpp

 1/*
 2 * Copyright (C) 2019 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27
 28#if ENABLE(WEB_AUTHN)
 29
 30#include "FidoTestData.h"
 31#include "PlatformUtilities.h"
 32#include <WebCore/CBORReader.h>
 33#include <WebCore/CBORValue.h>
 34#include <WebCore/CryptoAlgorithmAES_CBC.h>
 35#include <WebCore/CryptoAlgorithmAesCbcCfbParams.h>
 36#include <WebCore/CryptoAlgorithmECDH.h>
 37#include <WebCore/CryptoKeyAES.h>
 38#include <WebCore/CryptoKeyEC.h>
 39#include <WebCore/CryptoKeyHMAC.h>
 40#include <WebCore/FidoConstants.h>
 41#include <WebCore/Pin.h>
 42#include <WebCore/WebAuthenticationConstants.h>
 43#include <WebCore/WebAuthenticationUtils.h>
 44#include <wtf/text/Base64.h>
 45
 46namespace TestWebKitAPI {
 47using namespace WebCore;
 48using namespace cbor;
 49using namespace fido;
 50using namespace fido::pin;
 51
 52TEST(CtapPinTest, TestValidateAndConvertToUTF8)
 53{
 54 // Failure cases
 55 auto result = validateAndConvertToUTF8("123");
 56 EXPECT_FALSE(result);
 57 result = validateAndConvertToUTF8("");
 58 EXPECT_FALSE(result);
 59 result = validateAndConvertToUTF8("1234567812345678123456781234567812345678123456781234567812345678");
 60 EXPECT_FALSE(result);
 61
 62 // Success cases
 63 result = validateAndConvertToUTF8("1234");
 64 EXPECT_TRUE(result);
 65 EXPECT_EQ(result->length(), 4u);
 66 EXPECT_STREQ(result->data(), "1234");
 67
 68 result = validateAndConvertToUTF8("123456781234567812345678123456781234567812345678123456781234567");
 69 EXPECT_TRUE(result);
 70 EXPECT_EQ(result->length(), 63u);
 71 EXPECT_STREQ(result->data(), "123456781234567812345678123456781234567812345678123456781234567");
 72}
 73
 74TEST(CtapPinTest, TestRetriesRequest)
 75{
 76 auto result = encodeAsCBOR(RetriesRequest { });
 77 EXPECT_EQ(result.size(), sizeof(TestData::kCtapClientPinRetries));
 78 EXPECT_EQ(memcmp(result.data(), TestData::kCtapClientPinRetries, result.size()), 0);
 79}
 80
 81TEST(CtapPinTest, TestRetriesResponse)
 82{
 83 // Failure cases
 84 auto result = RetriesResponse::parse({ });
 85 EXPECT_FALSE(result);
 86
 87 const uint8_t testData1[] = { 0x05 }; // wrong response code
 88 result = RetriesResponse::parse(convertBytesToVector(testData1, sizeof(testData1)));
 89 EXPECT_FALSE(result);
 90
 91 const uint8_t testData2[] = { 0x00, 0x00 }; // wrong CBOR map
 92 result = RetriesResponse::parse(convertBytesToVector(testData2, sizeof(testData2)));
 93 EXPECT_FALSE(result);
 94
 95 result = RetriesResponse::parse(convertBytesToVector(TestData::kCtapClientPinTokenResponse, sizeof(TestData::kCtapClientPinTokenResponse))); // wrong response
 96 EXPECT_FALSE(result);
 97
 98 // Success cases
 99 result = RetriesResponse::parse(convertBytesToVector(TestData::kCtapClientPinRetriesResponse, sizeof(TestData::kCtapClientPinRetriesResponse)));
 100 EXPECT_TRUE(result);
 101 EXPECT_EQ(result->retries, 8);
 102}
 103
 104TEST(CtapPinTest, TestKeyAgreementRequest)
 105{
 106 auto result = encodeAsCBOR(KeyAgreementRequest { });
 107 EXPECT_EQ(result.size(), sizeof(TestData::kCtapClientPinKeyAgreement));
 108 EXPECT_EQ(memcmp(result.data(), TestData::kCtapClientPinKeyAgreement, result.size()), 0);
 109}
 110
 111TEST(CtapPinTest, TestKeyAgreementResponse)
 112{
 113 // Failure cases
 114 auto result = KeyAgreementResponse::parse({ });
 115 EXPECT_FALSE(result);
 116
 117 const uint8_t testData1[] = { 0x05 }; // wrong response code
 118 result = KeyAgreementResponse::parse(convertBytesToVector(testData1, sizeof(testData1)));
 119 EXPECT_FALSE(result);
 120
 121 const uint8_t testData2[] = { 0x00, 0x00 }; // wrong CBOR map
 122 result = KeyAgreementResponse::parse(convertBytesToVector(testData2, sizeof(testData2)));
 123 EXPECT_FALSE(result);
 124
 125 result = KeyAgreementResponse::parse(convertBytesToVector(TestData::kCtapClientPinTokenResponse, sizeof(TestData::kCtapClientPinTokenResponse))); // wrong response
 126 EXPECT_FALSE(result);
 127
 128 // Test COSE
 129 auto coseKey = encodeCOSEPublicKey(Vector<uint8_t>(65));
 130 coseKey[CBORValue(COSE::kty)] = CBORValue(0); // wrong kty
 131 auto coseResult = KeyAgreementResponse::parseFromCOSE(coseKey);
 132 EXPECT_FALSE(coseResult);
 133
 134 coseKey = encodeCOSEPublicKey(Vector<uint8_t>(65));
 135 coseKey[CBORValue(COSE::alg)] = CBORValue(0); // wrong alg
 136 coseResult = KeyAgreementResponse::parseFromCOSE(coseKey);
 137 EXPECT_FALSE(coseResult);
 138
 139 coseKey = encodeCOSEPublicKey(Vector<uint8_t>(65));
 140 coseKey[CBORValue(COSE::crv)] = CBORValue(0); // wrong crv
 141 coseResult = KeyAgreementResponse::parseFromCOSE(coseKey);
 142 EXPECT_FALSE(coseResult);
 143
 144 coseKey = encodeCOSEPublicKey(Vector<uint8_t>(65));
 145 coseKey[CBORValue(COSE::x)] = CBORValue(0); // wrong crv
 146 coseResult = KeyAgreementResponse::parseFromCOSE(coseKey);
 147 EXPECT_FALSE(coseResult);
 148
 149 coseKey = encodeCOSEPublicKey(Vector<uint8_t>(65));
 150 coseKey[CBORValue(COSE::y)] = CBORValue(0); // wrong crv
 151 coseResult = KeyAgreementResponse::parseFromCOSE(coseKey);
 152 EXPECT_FALSE(coseResult);
 153
 154 // Success cases
 155 result = KeyAgreementResponse::parse(convertBytesToVector(TestData::kCtapClientPinKeyAgreementResponse, sizeof(TestData::kCtapClientPinKeyAgreementResponse)));
 156 EXPECT_TRUE(result);
 157 auto exportedRawKey = result->peerKey->exportRaw();
 158 EXPECT_FALSE(exportedRawKey.hasException());
 159 Vector<uint8_t> expectedRawKey;
 160 expectedRawKey.reserveCapacity(65);
 161 expectedRawKey.append(0x04);
 162 expectedRawKey.append(TestData::kCtapClientPinKeyAgreementResponse + 14, 32); // X
 163 expectedRawKey.append(TestData::kCtapClientPinKeyAgreementResponse + 49, 32); // Y
 164 EXPECT_TRUE(exportedRawKey.returnValue() == expectedRawKey);
 165}
 166
 167TEST(CtapPinTest, TestTokenRequest)
 168{
 169 // Generate an EC key pair as the peer key.
 170 auto keyPairResult = CryptoKeyEC::generatePair(CryptoAlgorithmIdentifier::ECDH, "P-256", true, CryptoKeyUsageDeriveBits);
 171 ASSERT_FALSE(keyPairResult.hasException());
 172 auto keyPair = keyPairResult.releaseReturnValue();
 173
 174 CString pin = "1234";
 175
 176 auto token = TokenRequest::tryCreate(pin, downcast<CryptoKeyEC>(*keyPair.publicKey));
 177 EXPECT_TRUE(token);
 178 auto result = encodeAsCBOR(*token);
 179 EXPECT_EQ(result.size(), 120u);
 180 EXPECT_EQ(result[0], static_cast<uint8_t>(CtapRequestCommand::kAuthenticatorClientPin));
 181
 182 // Decode the CBOR binary to check if each field is encoded correctly.
 183 Vector<uint8_t> buffer;
 184 buffer.append(result.data() + 1, result.size() - 1);
 185 auto decodedResponse = cbor::CBORReader::read(buffer);
 186 EXPECT_TRUE(decodedResponse);
 187 EXPECT_TRUE(decodedResponse->isMap());
 188 const auto& responseMap = decodedResponse->getMap();
 189
 190 const auto& it1 = responseMap.find(CBORValue(static_cast<uint8_t>(RequestKey::kProtocol)));
 191 EXPECT_NE(it1, responseMap.end());
 192 EXPECT_EQ(it1->second.getInteger(), kProtocolVersion);
 193
 194 const auto& it2 = responseMap.find(CBORValue(static_cast<uint8_t>(RequestKey::kSubcommand)));
 195 EXPECT_NE(it2, responseMap.end());
 196 EXPECT_EQ(it2->second.getInteger(), static_cast<uint8_t>(Subcommand::kGetPinToken));
 197
 198 // COSE
 199 auto it = responseMap.find(CBORValue(static_cast<int>(RequestKey::kKeyAgreement)));
 200 EXPECT_TRUE(decodedResponse);
 201 EXPECT_TRUE(decodedResponse->isMap());
 202 const auto& coseKey = it->second.getMap();
 203
 204 const auto& it3 = coseKey.find(CBORValue(COSE::kty));
 205 EXPECT_NE(it3, coseKey.end());
 206 EXPECT_EQ(it3->second.getInteger(), COSE::EC2);
 207
 208 const auto& it4 = coseKey.find(CBORValue(COSE::alg));
 209 EXPECT_NE(it4, coseKey.end());
 210 EXPECT_EQ(it4->second.getInteger(), COSE::ECDH256);
 211
 212 const auto& it5 = coseKey.find(CBORValue(COSE::crv));
 213 EXPECT_NE(it5, coseKey.end());
 214 EXPECT_EQ(it5->second.getInteger(), COSE::P_256);
 215
 216 // Check the cose key.
 217 const auto& xIt = coseKey.find(CBORValue(-2));
 218 EXPECT_NE(xIt, coseKey.end());
 219 const auto& yIt = coseKey.find(CBORValue(-3));
 220 EXPECT_NE(yIt, coseKey.end());
 221 auto cosePublicKey = CryptoKeyEC::importRaw(CryptoAlgorithmIdentifier::ECDH, "P-256", encodeRawPublicKey(xIt->second.getByteString(), yIt->second.getByteString()), true, CryptoKeyUsageDeriveBits);
 222 EXPECT_TRUE(cosePublicKey);
 223
 224 // Check the encrypted Pin.
 225 auto sharedKeyResult = CryptoAlgorithmECDH::platformDeriveBits(downcast<CryptoKeyEC>(*keyPair.privateKey), *cosePublicKey);
 226 EXPECT_TRUE(sharedKeyResult);
 227 auto aesKey = CryptoKeyAES::importRaw(CryptoAlgorithmIdentifier::AES_CBC, WTFMove(*sharedKeyResult), true, CryptoKeyUsageDecrypt);
 228 EXPECT_TRUE(aesKey);
 229
 230 const auto& it6 = responseMap.find(CBORValue(static_cast<uint8_t>(RequestKey::kPinHashEnc)));
 231 EXPECT_NE(it6, responseMap.end());
 232 auto pinHashResult = CryptoAlgorithmAES_CBC::platformDecrypt({ }, *aesKey, it6->second.getByteString());
 233 EXPECT_FALSE(pinHashResult.hasException());
 234 auto pinHash = pinHashResult.releaseReturnValue();
 235 const uint8_t expectedPinHash[] = { 0x03, 0xac, 0x67, 0x42, 0x16, 0xf3, 0xe1, 0x5c, 0x76, 0x1e, 0xe1, 0xa5, 0xe2, 0x55, 0xf0, 0x67 };
 236 EXPECT_EQ(pinHash.size(), 16u);
 237 EXPECT_EQ(memcmp(pinHash.data(), expectedPinHash, pinHash.size()), 0);
 238}
 239
 240TEST(CtapPinTest, TestTokenResponse)
 241{
 242 const uint8_t sharedKeyData[] = {
 243 0x03, 0xac, 0x67, 0x42, 0x16, 0xf3, 0xe1, 0x5c,
 244 0x76, 0x1e, 0xe1, 0xa5, 0xe2, 0x55, 0xf0, 0x67,
 245 0x95, 0x36, 0x23, 0xc8, 0xb3, 0x88, 0xb4, 0x45,
 246 0x9e, 0x13, 0xf9, 0x78, 0xd7, 0xc8, 0x46, 0xf4, };
 247 auto sharedKey = CryptoKeyAES::importRaw(CryptoAlgorithmIdentifier::AES_CBC, convertBytesToVector(sharedKeyData, sizeof(sharedKeyData)), true, CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt);
 248 ASSERT_TRUE(sharedKey);
 249
 250 // Failure cases
 251 auto result = TokenResponse::parse(*sharedKey, { });
 252 EXPECT_FALSE(result);
 253
 254 const uint8_t testData1[] = { 0x05 }; // wrong response code
 255 result = TokenResponse::parse(*sharedKey, convertBytesToVector(testData1, sizeof(testData1)));
 256 EXPECT_FALSE(result);
 257
 258 const uint8_t testData2[] = { 0x00, 0x00 }; // wrong CBOR map
 259 result = TokenResponse::parse(*sharedKey, convertBytesToVector(testData2, sizeof(testData2)));
 260 EXPECT_FALSE(result);
 261
 262 result = TokenResponse::parse(*sharedKey, convertBytesToVector(TestData::kCtapClientPinKeyAgreementResponse, sizeof(TestData::kCtapClientPinKeyAgreementResponse))); // wrong response
 263 EXPECT_FALSE(result);
 264
 265 // Success cases
 266 result = TokenResponse::parse(*sharedKey, convertBytesToVector(TestData::kCtapClientPinTokenResponse, sizeof(TestData::kCtapClientPinTokenResponse)));
 267 EXPECT_TRUE(result);
 268 const uint8_t expectedToken[] = { 0x03, 0xac, 0x67, 0x42, 0x16, 0xf3, 0xe1, 0x5c, 0x76, 0x1e, 0xe1, 0xa5, 0xe2, 0x55, 0xf0, 0x67 };
 269 EXPECT_EQ(result->token().size(), 16u);
 270 EXPECT_EQ(memcmp(result->token().data(), expectedToken, result->token().size()), 0);
 271}
 272
 273TEST(CtapPinTest, TestPinAuth)
 274{
 275 // 1. Generate the token.
 276 const uint8_t sharedKeyData[] = {
 277 0x03, 0xac, 0x67, 0x42, 0x16, 0xf3, 0xe1, 0x5c,
 278 0x76, 0x1e, 0xe1, 0xa5, 0xe2, 0x55, 0xf0, 0x67,
 279 0x95, 0x36, 0x23, 0xc8, 0xb3, 0x88, 0xb4, 0x45,
 280 0x9e, 0x13, 0xf9, 0x78, 0xd7, 0xc8, 0x46, 0xf4, };
 281 auto sharedKey = CryptoKeyAES::importRaw(CryptoAlgorithmIdentifier::AES_CBC, convertBytesToVector(sharedKeyData, sizeof(sharedKeyData)), true, CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt);
 282 ASSERT_TRUE(sharedKey);
 283 auto result = TokenResponse::parse(*sharedKey, convertBytesToVector(TestData::kCtapClientPinTokenResponse, sizeof(TestData::kCtapClientPinTokenResponse)));
 284 ASSERT_TRUE(result);
 285
 286 // 2. Generate the pinAuth.
 287 auto pinAuth = result->pinAuth(convertBytesToVector(sharedKeyData, sizeof(sharedKeyData))); // sharedKeyData pretends to be clientDataHash
 288 const uint8_t expectedPinAuth[] = { 0xb3, 0xc2, 0x65, 0x1c, 0xfd, 0xc8, 0x42, 0xb4, 0x60, 0x16, 0xed, 0x20, 0x64, 0x53, 0xaf, 0x84 };
 289 EXPECT_EQ(pinAuth.size(), 16u);
 290 EXPECT_EQ(memcmp(pinAuth.data(), expectedPinAuth, pinAuth.size()), 0);
 291}
 292
 293} // namespace TestWebKitAPI
 294
 295#endif // ENABLE(WEB_AUTHN)

Tools/TestWebKitAPI/Tests/WebCore/CtapRequestTest.cpp

3232#if ENABLE(WEB_AUTHN)
3333
3434#include "FidoTestData.h"
 35#include "PlatformUtilities.h"
3536#include <WebCore/DeviceRequestConverter.h>
3637#include <WebCore/FidoConstants.h>
 38#include <WebCore/Pin.h>
3739#include <WebCore/PublicKeyCredentialCreationOptions.h>
3840#include <WebCore/PublicKeyCredentialRequestOptions.h>
3941#include <wtf/text/Base64.h>

@@TEST(CTAPRequestTest, TestConstructMakeCredentialRequestParam)
6769 EXPECT_EQ(memcmp(serializedData.data(), TestData::kCtapMakeCredentialRequest, serializedData.size()), 0);
6870}
6971
 72TEST(CTAPRequestTest, TestConstructMakeCredentialRequestParamWithPin)
 73{
 74 PublicKeyCredentialCreationOptions::RpEntity rp;
 75 rp.name = "Acme";
 76 rp.id = "acme.com";
 77
 78 PublicKeyCredentialCreationOptions::UserEntity user;
 79 user.name = "johnpsmith@example.com";
 80 user.icon = "https://pics.acme.com/00/p/aBjjjpqPb.png";
 81 user.idVector.append(TestData::kUserId, sizeof(TestData::kUserId));
 82 user.displayName = "John P. Smith";
 83
 84 Vector<PublicKeyCredentialCreationOptions::Parameters> params { { PublicKeyCredentialType::PublicKey, 7 }, { PublicKeyCredentialType::PublicKey, 257 } };
 85 PublicKeyCredentialCreationOptions::AuthenticatorSelectionCriteria selection { PublicKeyCredentialCreationOptions::AuthenticatorAttachment::Platform, true, UserVerificationRequirement::Preferred };
 86
 87 PinParameters pin;
 88 pin.protocol = pin::kProtocolVersion;
 89 pin.auth.append(TestData::kCtap2PinAuth, sizeof(TestData::kCtap2PinAuth));
 90
 91 PublicKeyCredentialCreationOptions options { rp, user, { }, params, WTF::nullopt, { }, selection, AttestationConveyancePreference::None, WTF::nullopt };
 92 Vector<uint8_t> hash;
 93 hash.append(TestData::kClientDataHash, sizeof(TestData::kClientDataHash));
 94 auto serializedData = encodeMakeCredenitalRequestAsCBOR(hash, options, AuthenticatorSupportedOptions::UserVerificationAvailability::kSupportedButNotConfigured, pin);
 95 EXPECT_EQ(serializedData.size(), sizeof(TestData::kCtapMakeCredentialRequestWithPin));
 96 EXPECT_EQ(memcmp(serializedData.data(), TestData::kCtapMakeCredentialRequestWithPin, serializedData.size()), 0);
 97}
 98
7099TEST(CTAPRequestTest, TestConstructGetAssertionRequest)
71100{
72101 PublicKeyCredentialRequestOptions options;

@@TEST(CTAPRequestTest, TestConstructGetAssertionRequest)
104133 EXPECT_EQ(memcmp(serializedData.data(), TestData::kTestComplexCtapGetAssertionRequest, serializedData.size()), 0);
105134}
106135
 136TEST(CTAPRequestTest, TestConstructGetAssertionRequestWithPin)
 137{
 138 PublicKeyCredentialRequestOptions options;
 139 options.rpId = "acme.com";
 140
 141 PublicKeyCredentialDescriptor descriptor1;
 142 descriptor1.type = PublicKeyCredentialType::PublicKey;
 143 const uint8_t id1[] = {
 144 0xf2, 0x20, 0x06, 0xde, 0x4f, 0x90, 0x5a, 0xf6, 0x8a, 0x43, 0x94,
 145 0x2f, 0x02, 0x4f, 0x2a, 0x5e, 0xce, 0x60, 0x3d, 0x9c, 0x6d, 0x4b,
 146 0x3d, 0xf8, 0xbe, 0x08, 0xed, 0x01, 0xfc, 0x44, 0x26, 0x46, 0xd0,
 147 0x34, 0x85, 0x8a, 0xc7, 0x5b, 0xed, 0x3f, 0xd5, 0x80, 0xbf, 0x98,
 148 0x08, 0xd9, 0x4f, 0xcb, 0xee, 0x82, 0xb9, 0xb2, 0xef, 0x66, 0x77,
 149 0xaf, 0x0a, 0xdc, 0xc3, 0x58, 0x52, 0xea, 0x6b, 0x9e };
 150 descriptor1.idVector.append(id1, sizeof(id1));
 151 options.allowCredentials.append(descriptor1);
 152
 153 PublicKeyCredentialDescriptor descriptor2;
 154 descriptor2.type = PublicKeyCredentialType::PublicKey;
 155 const uint8_t id2[] = {
 156 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
 157 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
 158 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
 159 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
 160 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
 161 descriptor2.idVector.append(id2, sizeof(id2));
 162 options.allowCredentials.append(descriptor2);
 163
 164 options.userVerification = UserVerificationRequirement::Required;
 165
 166 PinParameters pin;
 167 pin.protocol = pin::kProtocolVersion;
 168 pin.auth.append(TestData::kCtap2PinAuth, sizeof(TestData::kCtap2PinAuth));
 169
 170 Vector<uint8_t> hash;
 171 hash.append(TestData::kClientDataHash, sizeof(TestData::kClientDataHash));
 172 auto serializedData = encodeGetAssertionRequestAsCBOR(hash, options, AuthenticatorSupportedOptions::UserVerificationAvailability::kSupportedButNotConfigured, pin);
 173 EXPECT_EQ(serializedData.size(), sizeof(TestData::kTestComplexCtapGetAssertionRequestWithPin));
 174 EXPECT_EQ(memcmp(serializedData.data(), TestData::kTestComplexCtapGetAssertionRequestWithPin, serializedData.size()), 0);
 175}
 176
107177TEST(CTAPRequestTest, TestConstructCtapAuthenticatorRequestParam)
108178{
109179 static constexpr uint8_t kSerializedGetInfoCmd = 0x04;

Tools/TestWebKitAPI/Tests/WebCore/FidoTestData.h

@@constexpr uint8_t kCtapMakeCredentialRequest[] = {
525525 // key - "uv"
526526 0x62, 0x75, 0x76,
527527 // True(21)
528  0xf5};
 528 0xf5
 529};
 530
 531constexpr uint8_t kCtapMakeCredentialRequestWithPin[] = {
 532 // authenticatorMakeCredential command
 533 0x01,
 534 // map(7)
 535 0xa7,
 536 // key(1) - clientDataHash
 537 0x01,
 538 // bytes(32)
 539 0x58, 0x20, 0x68, 0x71, 0x34, 0x96, 0x82, 0x22, 0xec, 0x17, 0x20, 0x2e,
 540 0x42, 0x50, 0x5f, 0x8e, 0xd2, 0xb1, 0x6a, 0xe2, 0x2f, 0x16, 0xbb, 0x05,
 541 0xb8, 0x8c, 0x25, 0xdb, 0x9e, 0x60, 0x26, 0x45, 0xf1, 0x41,
 542 // key(2) - rp
 543 0x02,
 544 // map(2)
 545 0xa2,
 546 // key - "id"
 547 0x62, 0x69, 0x64,
 548 // value - "acme.com"
 549 0x68, 0x61, 0x63, 0x6d, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
 550 // key - "name"
 551 0x64, 0x6e, 0x61, 0x6d, 0x65,
 552 // value - "Acme"
 553 0x64, 0x41, 0x63, 0x6d, 0x65,
 554 // key(3) - user
 555 0x03,
 556 // map(4)
 557 0xa4,
 558 // key - "id"
 559 0x62, 0x69, 0x64,
 560 // value - user id
 561 0x48, 0x10, 0x98, 0x23, 0x72, 0x35, 0x40, 0x98, 0x72,
 562 // key - "icon"
 563 0x64, 0x69, 0x63, 0x6f, 0x6e,
 564 // value - "https://pics.acme.com/00/p/aBjjjpqPb.png"
 565 0x78, 0x28, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x70, 0x69,
 566 0x63, 0x73, 0x2e, 0x61, 0x63, 0x6d, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
 567 0x30, 0x30, 0x2f, 0x70, 0x2f, 0x61, 0x42, 0x6a, 0x6a, 0x6a, 0x70, 0x71,
 568 0x50, 0x62, 0x2e, 0x70, 0x6e, 0x67,
 569 // key - "name"
 570 0x64, 0x6e, 0x61, 0x6d, 0x65,
 571 // value - "johnpsmith@example.com"
 572 0x76, 0x6a, 0x6f, 0x68, 0x6e, 0x70, 0x73, 0x6d, 0x69, 0x74, 0x68, 0x40,
 573 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
 574 // key - "displayName"
 575 0x6b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65,
 576 // value - "John P. Smith"
 577 0x6d, 0x4a, 0x6f, 0x68, 0x6e, 0x20, 0x50, 0x2e, 0x20, 0x53, 0x6d, 0x69,
 578 0x74, 0x68,
 579 // key(4) - pubKeyCredParams
 580 0x04,
 581 // array(2)
 582 0x82,
 583 // map(2)
 584 0xa2,
 585 // key - "alg"
 586 0x63, 0x61, 0x6c, 0x67,
 587 // value - 7
 588 0x07,
 589 // key - "type"
 590 0x64, 0x74, 0x79, 0x70, 0x65,
 591 // value - "public-key"
 592 0x6a, 0x70, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x2D, 0x6B, 0x65, 0x79,
 593 // map(2)
 594 0xa2,
 595 // key - "alg"
 596 0x63, 0x61, 0x6c, 0x67,
 597 // value - 257
 598 0x19, 0x01, 0x01,
 599 // key - "type"
 600 0x64, 0x74, 0x79, 0x70, 0x65, // "type"
 601 // value - "public-key"
 602 0x6a, 0x70, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x2D, 0x6B, 0x65, 0x79,
 603 // key(7) - options
 604 0x07,
 605 // map(2)
 606 0xa2,
 607 // key - "rk"
 608 0x62, 0x72, 0x6b,
 609 // True(21)
 610 0xf5,
 611 // key - "uv"
 612 0x62, 0x75, 0x76,
 613 // True(21)
 614 0xf5,
 615 // key(8) - pinProtocol
 616 0x08,
 617 // value - 1
 618 0x01,
 619 // key(9) - pinAuth
 620 0x09,
 621 // bytes(16)
 622 0x50, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
 623 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
 624};
529625
530626constexpr uint8_t kTestComplexCtapGetAssertionRequest[] = {
531627 // authenticatorGetAssertion command

@@constexpr uint8_t kTestComplexCtapGetAssertionRequest[] = {
589685 0xf5,
590686};
591687
 688constexpr uint8_t kTestComplexCtapGetAssertionRequestWithPin[] = {
 689 // authenticatorGetAssertion command
 690 0x02,
 691 // map(6)
 692 0xa6,
 693 // key(01) -rpId
 694 0x01,
 695 // value - "acme.com"
 696 0x68, 0x61, 0x63, 0x6d, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
 697 // key(02) - client data hash
 698 0x02,
 699 // value - bytes(32)
 700 0x58, 0x20, 0x68, 0x71, 0x34, 0x96, 0x82, 0x22, 0xec, 0x17, 0x20, 0x2e,
 701 0x42, 0x50, 0x5f, 0x8e, 0xd2, 0xb1, 0x6a, 0xe2, 0x2f, 0x16, 0xbb, 0x05,
 702 0xb8, 0x8c, 0x25, 0xdb, 0x9e, 0x60, 0x26, 0x45, 0xf1, 0x41,
 703 // key(03) - allow list
 704 0x03,
 705 // value - array(2)
 706 0x82,
 707 // map(2)
 708 0xa2,
 709 // key - "id"
 710 0x62, 0x69, 0x64,
 711 // value - credential ID
 712 0x58, 0x40, 0xf2, 0x20, 0x06, 0xde, 0x4f, 0x90, 0x5a, 0xf6, 0x8a, 0x43,
 713 0x94, 0x2f, 0x02, 0x4f, 0x2a, 0x5e, 0xce, 0x60, 0x3d, 0x9c, 0x6d, 0x4b,
 714 0x3d, 0xf8, 0xbe, 0x08, 0xed, 0x01, 0xfc, 0x44, 0x26, 0x46, 0xd0, 0x34,
 715 0x85, 0x8a, 0xc7, 0x5b, 0xed, 0x3f, 0xd5, 0x80, 0xbf, 0x98, 0x08, 0xd9,
 716 0x4f, 0xcb, 0xee, 0x82, 0xb9, 0xb2, 0xef, 0x66, 0x77, 0xaf, 0x0a, 0xdc,
 717 0xc3, 0x58, 0x52, 0xea, 0x6b, 0x9e,
 718 // key - "type"
 719 0x64, 0x74, 0x79, 0x70, 0x65,
 720 // value - "public-key"
 721 0x6a, 0x70, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x2D, 0x6B, 0x65, 0x79,
 722 // map(2)
 723 0xa2,
 724 // key - "id"
 725 0x62, 0x69, 0x64,
 726 // value - credential ID
 727 0x58, 0x32, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
 728 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
 729 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
 730 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
 731 0x03, 0x03, 0x03, 0x03,
 732 // key - "type"
 733 0x64, 0x74, 0x79, 0x70, 0x65,
 734 // value - "public-key"
 735 0x6a, 0x70, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x2D, 0x6B, 0x65, 0x79,
 736 // unsigned(5) - options
 737 0x05,
 738 // map(2)
 739 0xa2,
 740 // key -"up"
 741 0x62, 0x75, 0x70,
 742 // value - True(21)
 743 0xf5,
 744 // key - "uv"
 745 0x62, 0x75, 0x76,
 746 // value - True(21)
 747 0xf5,
 748 // key(8) - pinProtocol
 749 0x08,
 750 // value - 1
 751 0x01,
 752 // key(9) - pinAuth
 753 0x09,
 754 // bytes(16)
 755 0x50, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
 756 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
 757};
 758
592759// CTAP responses --------------------------------------------------------------
593760
594761// A sample well formed response to CTAP AuthenticatorGetInfo request. Cross

@@constexpr uint8_t kDeviceGetAssertionResponse[] = {
8921059 0x01,
8931060};
8941061
 1062// CTAP PIN
 1063
 1064constexpr uint8_t kCtap2PinAuth[] = {
 1065 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
 1066 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
 1067};
 1068
 1069constexpr uint8_t kCtapClientPinRetries[] = {
 1070 // authenticatorClientPIN command
 1071 0x06,
 1072 // map(2)
 1073 0xa2,
 1074 // key(1) - pinProtocol
 1075 0x01,
 1076 // value - 1
 1077 0x01,
 1078 // key(2) - subCommand
 1079 0x02,
 1080 // value - 1(getRetries)
 1081 0x01,
 1082};
 1083
 1084constexpr uint8_t kCtapClientPinKeyAgreement[] = {
 1085 // authenticatorClientPIN command
 1086 0x06,
 1087 // map(2)
 1088 0xa2,
 1089 // key(1) - pinProtocol
 1090 0x01,
 1091 // value - 1
 1092 0x01,
 1093 // key(2) - subCommand
 1094 0x02,
 1095 // value - 2(getKeyAgreement)
 1096 0x02,
 1097};
 1098
 1099constexpr uint8_t kCtapClientPinTokenResponse[] = {
 1100 // Success
 1101 0x00,
 1102 // map(1)
 1103 0xa1,
 1104 // key(2) - pinToken
 1105 0x02,
 1106 // bytes(32)
 1107 0x58, 0x20,
 1108 // encrypted token
 1109 0x48, 0xb9, 0x5d, 0x3d, 0x9e, 0xee, 0xe5, 0x00, 0xab, 0x51, 0x13, 0x2b,
 1110 0x35, 0x77, 0x66, 0x5c, 0x41, 0x7a, 0x56, 0x3e, 0xb3, 0xe2, 0x3c, 0xb7,
 1111 0x6a, 0x37, 0xb3, 0xde, 0x57, 0x2b, 0xca, 0xaa,
 1112};
 1113
 1114constexpr uint8_t kCtapClientPinKeyAgreementResponse[] = {
 1115 // Success
 1116 0x00,
 1117 // map(1)
 1118 0xA1,
 1119 // key(1) - keyAgreement
 1120 0x01,
 1121 // Map(5)
 1122 0xA5,
 1123 // kty: EC key type
 1124 0x01, 0x02,
 1125 // alg: ECDH256 signature algorithm
 1126 0x03, 0x38, 0x18,
 1127 // crv: P-256 curve
 1128 0x20, 0x01,
 1129 // x-coordinate
 1130 0x21,
 1131 // Bytes(32)
 1132 0x58, 0x20,
 1133 // Byte array content
 1134 0xE8, 0x76, 0x25, 0x89, 0x6E, 0xE4, 0xE4, 0x6D, 0xC0, 0x32, 0x76, 0x6E,
 1135 0x80, 0x87, 0x96, 0x2F, 0x36, 0xDF, 0x9D, 0xFE, 0x8B, 0x56, 0x7F, 0x37,
 1136 0x63, 0x01, 0x5B, 0x19, 0x90, 0xA6, 0x0E, 0x14,
 1137 // y-coordinate
 1138 0x22,
 1139 // Bytes(32)
 1140 0x58, 0x20,
 1141 // Byte array content
 1142 0x27, 0xDE, 0x61, 0x2D, 0x66, 0x41, 0x8B, 0xDA, 0x19, 0x50, 0x58, 0x1E,
 1143 0xBC, 0x5C, 0x8C, 0x1D, 0xAD, 0x71, 0x0C, 0xB1, 0x4C, 0x22, 0xF8, 0xC9,
 1144 0x70, 0x45, 0xF4, 0x61, 0x2F, 0xB2, 0x0C, 0x91,
 1145};
 1146
 1147constexpr uint8_t kCtapClientPinRetriesResponse[] = {
 1148 // Success
 1149 0x00,
 1150 // map(1)
 1151 0xa1,
 1152 // key(3) - retries
 1153 0x03,
 1154 // value - 8
 1155 0x08,
 1156};
 1157
8951158} // namespace TestData
8961159
8971160} // namespace TestWebKitAPI