Commit 90c62574 authored by Martin Kreichgauer's avatar Martin Kreichgauer Committed by Commit Bot

fido: move the full clientDataJSON string into request classes

CtapMakeCredentialRequest and CtapGetAssertionRequest previously only
stored the hashed client data. This moves hashing out of
AuthenticatorImpl and into these request classes so that
FidoAuthenticator instances have access to the unhashed string if they
require (e.g. in the Windows WebAuthn API).

Bug: 898718
Change-Id: I4a08987a0be5d6ca07318d37f8c0bcc6c8612a06
Reviewed-on: https://chromium-review.googlesource.com/c/1300677
Commit-Queue: Martin Kreichgauer <martinkr@google.com>
Reviewed-by: default avatarJun Choi <hongjunchoi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#604148}
parent 2f6e7734
......@@ -203,7 +203,7 @@ bool IsAppIdAllowedForOrigin(const GURL& appid, const url::Origin& origin) {
}
device::CtapMakeCredentialRequest CreateCtapMakeCredentialRequest(
base::span<const uint8_t, device::kClientDataHashLength> client_data_hash,
const std::string& client_data_json,
const blink::mojom::PublicKeyCredentialCreationOptionsPtr& options,
bool is_individual_attestation) {
auto credential_params = mojo::ConvertTo<
......@@ -211,7 +211,7 @@ device::CtapMakeCredentialRequest CreateCtapMakeCredentialRequest(
options->public_key_parameters);
device::CtapMakeCredentialRequest make_credential_param(
client_data_hash,
client_data_json,
mojo::ConvertTo<device::PublicKeyCredentialRpEntity>(
options->relying_party),
mojo::ConvertTo<device::PublicKeyCredentialUserEntity>(options->user),
......@@ -228,12 +228,12 @@ device::CtapMakeCredentialRequest CreateCtapMakeCredentialRequest(
}
device::CtapGetAssertionRequest CreateCtapGetAssertionRequest(
base::span<const uint8_t, device::kClientDataHashLength> client_data_hash,
const std::string& client_data_json,
const blink::mojom::PublicKeyCredentialRequestOptionsPtr& options,
base::Optional<base::span<const uint8_t, device::kRpIdHashLength>>
alternative_application_parameter) {
device::CtapGetAssertionRequest request_parameter(options->relying_party_id,
client_data_hash);
client_data_json);
auto allowed_list =
mojo::ConvertTo<std::vector<device::PublicKeyCredentialDescriptor>>(
......@@ -257,15 +257,6 @@ device::CtapGetAssertionRequest CreateCtapGetAssertionRequest(
return request_parameter;
}
std::array<uint8_t, crypto::kSHA256Length> ConstructClientDataHash(
const std::string& client_data) {
// SHA-256 hash of the JSON data structure.
std::array<uint8_t, crypto::kSHA256Length> client_data_hash;
crypto::SHA256HashString(client_data, client_data_hash.data(),
client_data_hash.size());
return client_data_hash;
}
// The application parameter is the SHA-256 hash of the UTF-8 encoding of
// the application identity (i.e. relying_party_id) of the application
// requesting the registration.
......@@ -638,9 +629,8 @@ void AuthenticatorImpl::MakeCredential(
request_ = std::make_unique<device::MakeCredentialRequestHandler>(
connector_, transports_,
CreateCtapMakeCredentialRequest(
ConstructClientDataHash(client_data_json_), options,
individual_attestation),
CreateCtapMakeCredentialRequest(client_data_json_, options,
individual_attestation),
std::move(authenticator_selection_criteria),
base::BindOnce(&AuthenticatorImpl::OnRegisterResponse,
weak_factory_.GetWeakPtr()));
......@@ -730,15 +720,12 @@ void AuthenticatorImpl::GetAssertion(
if (!connector_)
connector_ = ServiceManagerConnection::GetForProcess()->GetConnector();
// Save client data to return with the authenticator response.
// TODO(kpaulhamus): Fetch and add the Token Binding ID public key used to
// communicate with the origin.
client_data_json_ = SerializeCollectedClientDataToJson(
client_data::kGetType, caller_origin, std::move(options->challenge));
auto ctap_request = CreateCtapGetAssertionRequest(
ConstructClientDataHash(client_data_json_), std::move(options),
alternative_application_parameter_);
auto ctap_request =
CreateCtapGetAssertionRequest(client_data_json_, std::move(options),
alternative_application_parameter_);
auto opt_platform_authenticator_info =
CreatePlatformAuthenticatorIfAvailableAndCheckIfCredentialExists(
......
......@@ -9,47 +9,18 @@
#include <utility>
#include "base/numerics/safe_conversions.h"
#include "components/cbor/reader.h"
#include "components/cbor/writer.h"
#include "device/fido/fido_constants.h"
#include "device/fido/fido_parsing_utils.h"
namespace device {
namespace {
bool AreGetAssertionRequestMapKeysCorrect(
const cbor::Value::MapValue& request_map) {
return std::all_of(request_map.begin(), request_map.end(),
[](const auto& param) {
if (!param.first.is_integer())
return false;
const auto& key = param.first.GetInteger();
return (key <= 7u || key >= 1u);
});
}
bool IsGetAssertionOptionMapFormatCorrect(
const cbor::Value::MapValue& option_map) {
return std::all_of(
option_map.begin(), option_map.end(), [](const auto& param) {
if (!param.first.is_string())
return false;
const auto& key = param.first.GetString();
return (key == kUserPresenceMapKey || key == kUserVerificationMapKey) &&
param.second.is_bool();
});
}
} // namespace
CtapGetAssertionRequest::CtapGetAssertionRequest(
std::string rp_id,
base::span<const uint8_t, kClientDataHashLength> client_data_hash)
CtapGetAssertionRequest::CtapGetAssertionRequest(std::string rp_id,
std::string client_data_json)
: rp_id_(std::move(rp_id)),
client_data_hash_(fido_parsing_utils::Materialize(client_data_hash)) {}
client_data_json_(std::move(client_data_json)),
client_data_hash_(
fido_parsing_utils::CreateSHA256Hash(client_data_json_)) {}
CtapGetAssertionRequest::CtapGetAssertionRequest(
const CtapGetAssertionRequest& that) = default;
......@@ -165,90 +136,4 @@ bool CtapGetAssertionRequest::CheckResponseRpIdHash(
response_rp_id_hash == *alternative_application_parameter_);
}
base::Optional<CtapGetAssertionRequest> ParseCtapGetAssertionRequest(
base::span<const uint8_t> request_bytes) {
const auto& cbor_request = cbor::Reader::Read(request_bytes);
if (!cbor_request || !cbor_request->is_map())
return base::nullopt;
const auto& request_map = cbor_request->GetMap();
if (!AreGetAssertionRequestMapKeysCorrect(request_map))
return base::nullopt;
const auto rp_id_it = request_map.find(cbor::Value(1));
if (rp_id_it == request_map.end() || !rp_id_it->second.is_string())
return base::nullopt;
const auto client_data_hash_it = request_map.find(cbor::Value(2));
if (client_data_hash_it == request_map.end() ||
!client_data_hash_it->second.is_bytestring())
return base::nullopt;
const auto client_data_hash =
base::make_span(client_data_hash_it->second.GetBytestring())
.subspan<0, kClientDataHashLength>();
CtapGetAssertionRequest request(rp_id_it->second.GetString(),
client_data_hash);
const auto allow_list_it = request_map.find(cbor::Value(3));
if (allow_list_it != request_map.end()) {
if (!allow_list_it->second.is_array())
return base::nullopt;
const auto& credential_descriptors = allow_list_it->second.GetArray();
std::vector<PublicKeyCredentialDescriptor> allow_list;
for (const auto& credential_descriptor : credential_descriptors) {
auto allowed_credential =
PublicKeyCredentialDescriptor::CreateFromCBORValue(
credential_descriptor);
if (!allowed_credential)
return base::nullopt;
allow_list.push_back(std::move(*allowed_credential));
}
request.SetAllowList(std::move(allow_list));
}
const auto option_it = request_map.find(cbor::Value(5));
if (option_it != request_map.end()) {
if (!option_it->second.is_map())
return base::nullopt;
const auto& option_map = option_it->second.GetMap();
if (!IsGetAssertionOptionMapFormatCorrect(option_map))
return base::nullopt;
const auto user_presence_option =
option_map.find(cbor::Value(kUserPresenceMapKey));
if (user_presence_option != option_map.end())
request.SetUserPresenceRequired(user_presence_option->second.GetBool());
const auto uv_option =
option_map.find(cbor::Value(kUserVerificationMapKey));
if (uv_option != option_map.end())
request.SetUserVerification(
uv_option->second.GetBool()
? UserVerificationRequirement::kRequired
: UserVerificationRequirement::kPreferred);
}
const auto pin_auth_it = request_map.find(cbor::Value(6));
if (pin_auth_it != request_map.end()) {
if (!pin_auth_it->second.is_bytestring())
return base::nullopt;
request.SetPinAuth(pin_auth_it->second.GetBytestring());
}
const auto pin_protocol_it = request_map.find(cbor::Value(7));
if (pin_protocol_it != request_map.end()) {
if (!pin_protocol_it->second.is_unsigned() ||
pin_protocol_it->second.GetUnsigned() >
std::numeric_limits<uint8_t>::max())
return base::nullopt;
request.SetPinProtocol(pin_auth_it->second.GetUnsigned());
}
return request;
}
} // namespace device
......@@ -7,6 +7,7 @@
#include <stdint.h>
#include <array>
#include <string>
#include <vector>
......@@ -25,9 +26,9 @@ namespace device {
// https://fidoalliance.org/specs/fido-v2.0-rd-20161004/fido-client-to-authenticator-protocol-v2.0-rd-20161004.html#authenticatorgetassertion
class COMPONENT_EXPORT(DEVICE_FIDO) CtapGetAssertionRequest {
public:
CtapGetAssertionRequest(
std::string rp_id,
base::span<const uint8_t, kClientDataHashLength> client_data_hash);
using ClientDataHash = std::array<uint8_t, kClientDataHashLength>;
CtapGetAssertionRequest(std::string rp_id, std::string client_data_json);
CtapGetAssertionRequest(const CtapGetAssertionRequest& that);
CtapGetAssertionRequest(CtapGetAssertionRequest&& that);
CtapGetAssertionRequest& operator=(const CtapGetAssertionRequest& other);
......@@ -58,6 +59,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) CtapGetAssertionRequest {
const std::array<uint8_t, kRpIdHashLength>& response_rp_id_hash);
const std::string& rp_id() const { return rp_id_; }
const std::string& client_data_json() const { return client_data_json_; }
const std::array<uint8_t, kClientDataHashLength>& client_data_hash() const {
return client_data_hash_;
}
......@@ -88,6 +90,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) CtapGetAssertionRequest {
private:
std::string rp_id_;
std::string client_data_json_;
std::array<uint8_t, kClientDataHashLength> client_data_hash_;
UserVerificationRequirement user_verification_ =
UserVerificationRequirement::kPreferred;
......@@ -101,10 +104,6 @@ class COMPONENT_EXPORT(DEVICE_FIDO) CtapGetAssertionRequest {
alternative_application_parameter_;
};
COMPONENT_EXPORT(DEVICE_FIDO)
base::Optional<CtapGetAssertionRequest> ParseCtapGetAssertionRequest(
base::span<const uint8_t> request_bytes);
} // namespace device
#endif // DEVICE_FIDO_CTAP_GET_ASSERTION_REQUEST_H_
......@@ -9,48 +9,20 @@
#include <utility>
#include "base/numerics/safe_conversions.h"
#include "components/cbor/reader.h"
#include "components/cbor/writer.h"
#include "device/fido/fido_constants.h"
#include "device/fido/fido_parsing_utils.h"
namespace device {
namespace {
bool AreMakeCredentialRequestMapKeysCorrect(
const cbor::Value::MapValue& request_map) {
return std::all_of(request_map.begin(), request_map.end(),
[](const auto& param) {
if (!param.first.is_integer())
return false;
const auto& key = param.first.GetInteger();
return (key <= 9u && key >= 1u);
});
}
bool IsMakeCredentialOptionMapFormatCorrect(
const cbor::Value::MapValue& option_map) {
return std::all_of(
option_map.begin(), option_map.end(), [](const auto& param) {
if (!param.first.is_string())
return false;
const auto& key = param.first.GetString();
return ((key == kResidentKeyMapKey || key == kUserVerificationMapKey) &&
param.second.is_bool());
});
}
} // namespace
CtapMakeCredentialRequest::CtapMakeCredentialRequest(
base::span<const uint8_t, kClientDataHashLength> client_data_hash,
std::string client_data_json,
PublicKeyCredentialRpEntity rp,
PublicKeyCredentialUserEntity user,
PublicKeyCredentialParams public_key_credential_params)
: client_data_hash_(fido_parsing_utils::Materialize(client_data_hash)),
: client_data_json_(std::move(client_data_json)),
client_data_hash_(
fido_parsing_utils::CreateSHA256Hash(client_data_json_)),
rp_(std::move(rp)),
user_(std::move(user)),
public_key_credential_params_(std::move(public_key_credential_params)) {}
......@@ -169,129 +141,4 @@ CtapMakeCredentialRequest& CtapMakeCredentialRequest::SetHmacSecret(
return *this;
}
base::Optional<CtapMakeCredentialRequest> ParseCtapMakeCredentialRequest(
base::span<const uint8_t> request_bytes) {
const auto& cbor_request = cbor::Reader::Read(request_bytes);
if (!cbor_request || !cbor_request->is_map())
return base::nullopt;
const auto& request_map = cbor_request->GetMap();
if (!AreMakeCredentialRequestMapKeysCorrect(request_map))
return base::nullopt;
const auto client_data_hash_it = request_map.find(cbor::Value(1));
if (client_data_hash_it == request_map.end() ||
!client_data_hash_it->second.is_bytestring())
return base::nullopt;
const auto client_data_hash =
base::make_span(client_data_hash_it->second.GetBytestring())
.subspan<0, kClientDataHashLength>();
const auto rp_entity_it = request_map.find(cbor::Value(2));
if (rp_entity_it == request_map.end() || !rp_entity_it->second.is_map())
return base::nullopt;
auto rp_entity =
PublicKeyCredentialRpEntity::CreateFromCBORValue(rp_entity_it->second);
if (!rp_entity)
return base::nullopt;
const auto user_entity_it = request_map.find(cbor::Value(3));
if (user_entity_it == request_map.end() || !user_entity_it->second.is_map())
return base::nullopt;
auto user_entity = PublicKeyCredentialUserEntity::CreateFromCBORValue(
user_entity_it->second);
if (!user_entity)
return base::nullopt;
const auto credential_params_it = request_map.find(cbor::Value(4));
if (credential_params_it == request_map.end())
return base::nullopt;
auto credential_params = PublicKeyCredentialParams::CreateFromCBORValue(
credential_params_it->second);
if (!credential_params)
return base::nullopt;
CtapMakeCredentialRequest request(client_data_hash, std::move(*rp_entity),
std::move(*user_entity),
std::move(*credential_params));
const auto exclude_list_it = request_map.find(cbor::Value(5));
if (exclude_list_it != request_map.end()) {
if (!exclude_list_it->second.is_array())
return base::nullopt;
const auto& credential_descriptors = exclude_list_it->second.GetArray();
std::vector<PublicKeyCredentialDescriptor> exclude_list;
for (const auto& credential_descriptor : credential_descriptors) {
auto excluded_credential =
PublicKeyCredentialDescriptor::CreateFromCBORValue(
credential_descriptor);
if (!excluded_credential)
return base::nullopt;
exclude_list.push_back(std::move(*excluded_credential));
}
request.SetExcludeList(std::move(exclude_list));
}
const auto extensions_it = request_map.find(cbor::Value(6));
if (extensions_it != request_map.end()) {
if (!extensions_it->second.is_map()) {
return base::nullopt;
}
const auto& extensions = extensions_it->second.GetMap();
const auto hmac_secret_it =
extensions.find(cbor::Value(kExtensionHmacSecret));
if (hmac_secret_it != extensions.end()) {
if (!hmac_secret_it->second.is_bool()) {
return base::nullopt;
}
request.SetHmacSecret(hmac_secret_it->second.GetBool());
}
}
const auto option_it = request_map.find(cbor::Value(7));
if (option_it != request_map.end()) {
if (!option_it->second.is_map())
return base::nullopt;
const auto& option_map = option_it->second.GetMap();
if (!IsMakeCredentialOptionMapFormatCorrect(option_map))
return base::nullopt;
const auto resident_key_option =
option_map.find(cbor::Value(kResidentKeyMapKey));
if (resident_key_option != option_map.end())
request.SetResidentKeySupported(resident_key_option->second.GetBool());
const auto uv_option =
option_map.find(cbor::Value(kUserVerificationMapKey));
if (uv_option != option_map.end())
request.SetUserVerificationRequired(uv_option->second.GetBool());
}
const auto pin_auth_it = request_map.find(cbor::Value(8));
if (pin_auth_it != request_map.end()) {
if (!pin_auth_it->second.is_bytestring())
return base::nullopt;
request.SetPinAuth(pin_auth_it->second.GetBytestring());
}
const auto pin_protocol_it = request_map.find(cbor::Value(9));
if (pin_protocol_it != request_map.end()) {
if (!pin_protocol_it->second.is_unsigned() ||
pin_protocol_it->second.GetUnsigned() >
std::numeric_limits<uint8_t>::max())
return base::nullopt;
request.SetPinProtocol(pin_auth_it->second.GetUnsigned());
}
return request;
}
} // namespace device
......@@ -27,8 +27,10 @@ namespace device {
// https://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-client-to-authenticator-protocol-v2.0-rd-20170927.html
class COMPONENT_EXPORT(DEVICE_FIDO) CtapMakeCredentialRequest {
public:
using ClientDataHash = std::array<uint8_t, kClientDataHashLength>;
CtapMakeCredentialRequest(
base::span<const uint8_t, kClientDataHashLength> client_data_hash,
std::string client_data_json,
PublicKeyCredentialRpEntity rp,
PublicKeyCredentialUserEntity user,
PublicKeyCredentialParams public_key_credential_params);
......@@ -54,6 +56,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) CtapMakeCredentialRequest {
bool is_individual_attestation);
CtapMakeCredentialRequest& SetHmacSecret(bool hmac_secret);
const std::string& client_data_json() const { return client_data_json_; }
const std::array<uint8_t, kClientDataHashLength>& client_data_hash() const {
return client_data_hash_;
}
......@@ -77,6 +80,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) CtapMakeCredentialRequest {
}
private:
std::string client_data_json_;
std::array<uint8_t, kClientDataHashLength> client_data_hash_;
PublicKeyCredentialRpEntity rp_;
PublicKeyCredentialUserEntity user_;
......@@ -93,10 +97,6 @@ class COMPONENT_EXPORT(DEVICE_FIDO) CtapMakeCredentialRequest {
base::Optional<uint8_t> pin_protocol_;
};
COMPONENT_EXPORT(DEVICE_FIDO)
base::Optional<CtapMakeCredentialRequest> ParseCtapMakeCredentialRequest(
base::span<const uint8_t> request_bytes);
} // namespace device
#endif // DEVICE_FIDO_CTAP_MAKE_CREDENTIAL_REQUEST_H_
......@@ -8,6 +8,7 @@
#include "device/fido/fido_constants.h"
#include "device/fido/fido_parsing_utils.h"
#include "device/fido/fido_test_data.h"
#include "device/fido/virtual_ctap2_device.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -26,7 +27,7 @@ TEST(CTAPRequestTest, TestConstructMakeCredentialRequestParam) {
.SetIconUrl(GURL("https://pics.acme.com/00/p/aBjjjpqPb.png"));
CtapMakeCredentialRequest make_credential_param(
test_data::kClientDataHash, std::move(rp), std::move(user),
test_data::kClientDataJson, std::move(rp), std::move(user),
PublicKeyCredentialParams({{CredentialType::kPublicKey, 7},
{CredentialType::kPublicKey, 257}}));
auto serialized_data = make_credential_param.SetResidentKeySupported(true)
......@@ -38,7 +39,7 @@ TEST(CTAPRequestTest, TestConstructMakeCredentialRequestParam) {
TEST(CTAPRequestTest, TestConstructGetAssertionRequest) {
CtapGetAssertionRequest get_assertion_req("acme.com",
test_data::kClientDataHash);
test_data::kClientDataJson);
std::vector<PublicKeyCredentialDescriptor> allowed_list;
allowed_list.push_back(PublicKeyCredentialDescriptor(
......@@ -80,39 +81,41 @@ TEST(CTAPRequestTest, TestConstructCtapAuthenticatorRequestParam) {
::testing::ElementsAre(kSerializedResetCmd));
}
TEST(CTAPRequestTest, ParseMakeCredentialRequestForVirtualCtapKey) {
const auto request = ParseCtapMakeCredentialRequest(
TEST(VirtualCtap2DeviceTest, ParseMakeCredentialRequestForVirtualCtapKey) {
const auto request_and_hash = ParseCtapMakeCredentialRequest(
base::make_span(test_data::kCtapMakeCredentialRequest).subspan(1));
ASSERT_TRUE(request);
EXPECT_THAT(request->client_data_hash(),
ASSERT_TRUE(request_and_hash);
auto request = std::get<0>(*request_and_hash);
auto client_data_hash = std::get<1>(*request_and_hash);
EXPECT_THAT(client_data_hash,
::testing::ElementsAreArray(test_data::kClientDataHash));
EXPECT_EQ(test_data::kRelyingPartyId, request->rp().rp_id());
EXPECT_EQ("Acme", request->rp().rp_name());
EXPECT_THAT(request->user().user_id(),
EXPECT_EQ(test_data::kRelyingPartyId, request.rp().rp_id());
EXPECT_EQ("Acme", request.rp().rp_name());
EXPECT_THAT(request.user().user_id(),
::testing::ElementsAreArray(test_data::kUserId));
ASSERT_TRUE(request->user().user_name());
EXPECT_EQ("johnpsmith@example.com", *request->user().user_name());
ASSERT_TRUE(request->user().user_display_name());
EXPECT_EQ("John P. Smith", *request->user().user_display_name());
ASSERT_TRUE(request->user().user_icon_url());
ASSERT_TRUE(request.user().user_name());
EXPECT_EQ("johnpsmith@example.com", *request.user().user_name());
ASSERT_TRUE(request.user().user_display_name());
EXPECT_EQ("John P. Smith", *request.user().user_display_name());
ASSERT_TRUE(request.user().user_icon_url());
EXPECT_EQ("https://pics.acme.com/00/p/aBjjjpqPb.png",
request->user().user_icon_url()->spec());
ASSERT_EQ(2u, request->public_key_credential_params()
request.user().user_icon_url()->spec());
ASSERT_EQ(2u, request.public_key_credential_params()
.public_key_credential_params()
.size());
EXPECT_EQ(7, request->public_key_credential_params()
EXPECT_EQ(7, request.public_key_credential_params()
.public_key_credential_params()
.at(0)
.algorithm);
EXPECT_EQ(257, request->public_key_credential_params()
EXPECT_EQ(257, request.public_key_credential_params()
.public_key_credential_params()
.at(1)
.algorithm);
EXPECT_TRUE(request->user_verification_required());
EXPECT_TRUE(request->resident_key_supported());
EXPECT_TRUE(request.user_verification_required());
EXPECT_TRUE(request.resident_key_supported());
}
TEST(CTAPRequestTest, ParseGetAssertionRequestForVirtualCtapKey) {
TEST(VirtualCtap2DeviceTest, ParseGetAssertionRequestForVirtualCtapKey) {
constexpr uint8_t kAllowedCredentialOne[] = {
0xf2, 0x20, 0x06, 0xde, 0x4f, 0x90, 0x5a, 0xf6, 0x8a, 0x43, 0x94,
0x2f, 0x02, 0x4f, 0x2a, 0x5e, 0xce, 0x60, 0x3d, 0x9c, 0x6d, 0x4b,
......@@ -127,22 +130,24 @@ TEST(CTAPRequestTest, ParseGetAssertionRequestForVirtualCtapKey) {
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
const auto request = ParseCtapGetAssertionRequest(
auto request_and_hash = ParseCtapGetAssertionRequest(
base::make_span(test_data::kTestComplexCtapGetAssertionRequest)
.subspan(1));
ASSERT_TRUE(request);
EXPECT_THAT(request->client_data_hash(),
ASSERT_TRUE(request_and_hash);
auto request = std::get<0>(*request_and_hash);
auto client_data_hash = std::get<1>(*request_and_hash);
EXPECT_THAT(client_data_hash,
::testing::ElementsAreArray(test_data::kClientDataHash));
EXPECT_EQ(test_data::kRelyingPartyId, request->rp_id());
EXPECT_EQ(test_data::kRelyingPartyId, request.rp_id());
EXPECT_EQ(UserVerificationRequirement::kRequired,
request->user_verification());
EXPECT_FALSE(request->user_presence_required());
ASSERT_TRUE(request->allow_list());
ASSERT_EQ(2u, request->allow_list()->size());
request.user_verification());
EXPECT_FALSE(request.user_presence_required());
ASSERT_TRUE(request.allow_list());
ASSERT_EQ(2u, request.allow_list()->size());
EXPECT_THAT(request->allow_list()->at(0).id(),
EXPECT_THAT(request.allow_list()->at(0).id(),
::testing::ElementsAreArray(kAllowedCredentialOne));
EXPECT_THAT(request->allow_list()->at(1).id(),
EXPECT_THAT(request.allow_list()->at(1).id(),
::testing::ElementsAreArray(kAllowedCredentialTwo));
}
} // namespace device
This diff is collapsed.
......@@ -56,14 +56,14 @@ class FidoGetAssertionHandlerTest : public ::testing::Test {
CtapGetAssertionRequest CreateTestRequestWithCableExtension() {
CtapGetAssertionRequest request(test_data::kRelyingPartyId,
test_data::kClientDataHash);
test_data::kClientDataJson);
request.SetCableExtension({});
return request;
}
std::unique_ptr<GetAssertionRequestHandler> CreateGetAssertionHandlerU2f() {
CtapGetAssertionRequest request(test_data::kRelyingPartyId,
test_data::kClientDataHash);
test_data::kClientDataJson);
request.SetAllowList(
{{CredentialType::kPublicKey,
fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle)}});
......@@ -72,7 +72,7 @@ class FidoGetAssertionHandlerTest : public ::testing::Test {
std::unique_ptr<GetAssertionRequestHandler> CreateGetAssertionHandlerCtap() {
CtapGetAssertionRequest request(test_data::kRelyingPartyId,
test_data::kClientDataHash);
test_data::kClientDataJson);
request.SetAllowList({{CredentialType::kPublicKey,
fido_parsing_utils::Materialize(
test_data::kTestGetAssertionCredentialId)}});
......@@ -183,7 +183,7 @@ class FidoGetAssertionHandlerTest : public ::testing::Test {
TEST_F(FidoGetAssertionHandlerTest, TransportAvailabilityInfo) {
auto request_handler =
CreateGetAssertionHandlerWithRequest(CtapGetAssertionRequest(
test_data::kRelyingPartyId, test_data::kClientDataHash));
test_data::kRelyingPartyId, test_data::kClientDataJson));
EXPECT_EQ(FidoRequestHandlerBase::RequestType::kGetAssertion,
request_handler->transport_availability_info().request_type);
......@@ -252,7 +252,7 @@ TEST_F(FidoGetAssertionHandlerTest, TestU2fSignWithoutCtapFlag) {
TEST_F(FidoGetAssertionHandlerTest, TestIncompatibleUserVerificationSetting) {
auto request = CtapGetAssertionRequest(test_data::kRelyingPartyId,
test_data::kClientDataHash);
test_data::kClientDataJson);
request.SetUserVerification(UserVerificationRequirement::kRequired);
auto request_handler =
CreateGetAssertionHandlerWithRequest(std::move(request));
......@@ -270,7 +270,7 @@ TEST_F(FidoGetAssertionHandlerTest, TestIncompatibleUserVerificationSetting) {
TEST_F(FidoGetAssertionHandlerTest,
TestU2fSignRequestWithUserVerificationRequired) {
auto request = CtapGetAssertionRequest(test_data::kRelyingPartyId,
test_data::kClientDataHash);
test_data::kClientDataJson);
request.SetAllowList(
{{CredentialType::kPublicKey,
fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle)}});
......@@ -289,7 +289,7 @@ TEST_F(FidoGetAssertionHandlerTest,
TEST_F(FidoGetAssertionHandlerTest, IncorrectRpIdHash) {
auto request_handler =
CreateGetAssertionHandlerWithRequest(CtapGetAssertionRequest(
test_data::kRelyingPartyId, test_data::kClientDataHash));
test_data::kRelyingPartyId, test_data::kClientDataJson));
discovery()->WaitForCallToStartAndSimulateSuccess();
auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation();
device->ExpectCtap2CommandAndRespondWith(
......@@ -306,7 +306,7 @@ TEST_F(FidoGetAssertionHandlerTest, IncorrectRpIdHash) {
// is not included in the allowed list.
TEST_F(FidoGetAssertionHandlerTest, InvalidCredential) {
CtapGetAssertionRequest request(test_data::kRelyingPartyId,
test_data::kClientDataHash);
test_data::kClientDataJson);
request.SetAllowList(
{{CredentialType::kPublicKey,
fido_parsing_utils::Materialize(test_data::kKeyHandleAlpha)}});
......@@ -332,7 +332,7 @@ TEST_F(FidoGetAssertionHandlerTest, IncorrectUserEntity) {
// Use a GetAssertion request with an empty allow list.
auto request_handler =
CreateGetAssertionHandlerWithRequest(CtapGetAssertionRequest(
test_data::kRelyingPartyId, test_data::kClientDataHash));
test_data::kRelyingPartyId, test_data::kClientDataJson));
discovery()->WaitForCallToStartAndSimulateSuccess();
auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation();
device->ExpectCtap2CommandAndRespondWith(
......@@ -408,7 +408,7 @@ TEST_F(FidoGetAssertionHandlerTest,
TEST_F(FidoGetAssertionHandlerTest,
CableDisabledIfAllowCredentialsListUndefinedButCableExtensionMissing) {
CtapGetAssertionRequest request(test_data::kRelyingPartyId,
test_data::kClientDataHash);
test_data::kClientDataJson);
ASSERT_FALSE(!!request.cable_extension());
EXPECT_CALL(*mock_adapter_, IsPresent()).WillOnce(::testing::Return(true));
auto request_handler =
......@@ -423,7 +423,7 @@ TEST_F(FidoGetAssertionHandlerTest,
TEST_F(FidoGetAssertionHandlerTest,
CableDisabledIfExplicitlyAllowedButCableExtensionMissing) {
CtapGetAssertionRequest request(test_data::kRelyingPartyId,
test_data::kClientDataHash);
test_data::kClientDataJson);
ASSERT_FALSE(!!request.cable_extension());
request.SetAllowList({
{CredentialType::kPublicKey,
......
......@@ -63,7 +63,7 @@ TEST_F(FidoGetAssertionTaskTest, TestGetAssertionSuccess) {
test_data::kTestGetAssertionResponse);
CtapGetAssertionRequest request_param(test_data::kRelyingPartyId,
test_data::kClientDataHash);
test_data::kClientDataJson);
request_param.SetAllowList({{CredentialType::kPublicKey,
fido_parsing_utils::Materialize(
test_data::kTestGetAssertionCredentialId)}});
......@@ -88,7 +88,7 @@ TEST_F(FidoGetAssertionTaskTest, TestU2fSignSuccess) {
test_data::kApduEncodedNoErrorSignResponse);
CtapGetAssertionRequest request_param(test_data::kRelyingPartyId,
test_data::kClientDataHash);
test_data::kClientDataJson);
request_param.SetAllowList(
{{CredentialType::kPublicKey,
fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle)}});
......@@ -110,7 +110,7 @@ TEST_F(FidoGetAssertionTaskTest, TestSignSuccessWithFake) {
auto hash = fido_parsing_utils::CreateSHA256Hash(public_key);
std::vector<uint8_t> key_handle(hash.begin(), hash.end());
CtapGetAssertionRequest request_param(test_data::kRelyingPartyId,
test_data::kClientDataHash);
test_data::kClientDataJson);
request_param.SetAllowList({{CredentialType::kPublicKey, key_handle}});
auto device = std::make_unique<VirtualCtap2Device>();
......@@ -162,7 +162,7 @@ TEST_F(FidoGetAssertionTaskTest, TestU2fSignWithoutFlag) {
test_data::kApduEncodedNoErrorSignResponse);
CtapGetAssertionRequest request_param(test_data::kRelyingPartyId,
test_data::kClientDataHash);
test_data::kClientDataJson);
request_param.SetAllowList(
{{CredentialType::kPublicKey,
fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle)}});
......@@ -185,7 +185,7 @@ TEST_F(FidoGetAssertionTaskTest, TestIncorrectGetAssertionResponse) {
auto task = std::make_unique<GetAssertionTask>(
device.get(),
CtapGetAssertionRequest(test_data::kRelyingPartyId,
test_data::kClientDataHash),
test_data::kClientDataJson),
get_assertion_callback_receiver().callback());
get_assertion_callback_receiver().WaitForCallback();
......@@ -196,7 +196,7 @@ TEST_F(FidoGetAssertionTaskTest, TestIncorrectGetAssertionResponse) {
TEST_F(FidoGetAssertionTaskTest, TestU2fSignRequestWithEmptyAllowedList) {
auto request = CtapGetAssertionRequest(test_data::kRelyingPartyId,
test_data::kClientDataHash);
test_data::kClientDataJson);
auto device = MockFidoDevice::MakeU2f();
device->ExpectRequestAndRespondWith(
......@@ -218,7 +218,7 @@ TEST_F(FidoGetAssertionTaskTest, TestU2fSignRequestWithEmptyAllowedList) {
// of valid credentials via silent authentication.
TEST_F(FidoGetAssertionTaskTest, TestSilentSignInWhenAppIdExtensionPresent) {
CtapGetAssertionRequest request(test_data::kRelyingPartyId,
test_data::kClientDataHash);
test_data::kClientDataJson);
std::vector<PublicKeyCredentialDescriptor> allowed_list;
allowed_list.push_back(PublicKeyCredentialDescriptor(
......@@ -245,7 +245,7 @@ TEST_F(FidoGetAssertionTaskTest, TestSilentSignInWhenAppIdExtensionPresent) {
TEST_F(FidoGetAssertionTaskTest, TestU2fFallbackForAppIdExtension) {
CtapGetAssertionRequest request(test_data::kRelyingPartyId,
test_data::kClientDataHash);
test_data::kClientDataJson);
std::vector<PublicKeyCredentialDescriptor> allowed_list;
allowed_list.push_back(PublicKeyCredentialDescriptor(
......@@ -287,7 +287,7 @@ TEST_F(FidoGetAssertionTaskTest, TestU2fFallbackForAppIdExtension) {
TEST_F(FidoGetAssertionTaskTest, TestAvoidSilentSignInForCtapOnlyDevice) {
CtapGetAssertionRequest request(test_data::kRelyingPartyId,
test_data::kClientDataHash);
test_data::kClientDataJson);
std::vector<PublicKeyCredentialDescriptor> allowed_list;
allowed_list.push_back(PublicKeyCredentialDescriptor(
......
......@@ -16,6 +16,7 @@
#include "device/base/features.h"
#include "device/fido/ctap_make_credential_request.h"
#include "device/fido/fido_constants.h"
#include "device/fido/fido_test_data.h"
#include "device/fido/mac/authenticator.h"
#include "device/fido/mac/authenticator_config.h"
#include "device/fido/mac/keychain.h"
......@@ -47,7 +48,6 @@ constexpr char kKeychainAccessGroup[] =
constexpr char kMetadataSecret[] = "supersecret";
constexpr char kOtherMetadataSecret[] = "reallynotsosecret";
constexpr std::array<uint8_t, kClientDataHashLength> kClientDataHash = {};
constexpr char kRpId[] = "rp.example.com";
const std::vector<uint8_t> kUserId = {10, 11, 12, 13, 14, 15};
......@@ -123,7 +123,7 @@ class BrowsingDataDeletionTest : public testing::Test {
protected:
CtapMakeCredentialRequest MakeRequest() {
return CtapMakeCredentialRequest(
kClientDataHash, PublicKeyCredentialRpEntity(kRpId),
test_data::kClientDataJson, PublicKeyCredentialRpEntity(kRpId),
PublicKeyCredentialUserEntity(kUserId),
PublicKeyCredentialParams(
{{PublicKeyCredentialParams::
......
......@@ -13,6 +13,7 @@
#include "base/test/scoped_task_environment.h"
#include "device/fido/fido_constants.h"
#include "device/fido/fido_test_data.h"
#include "device/fido/mac/make_credential_operation.h"
#include "device/fido/test_callback_receiver.h"
#include "testing/gmock/include/gmock/gmock.h"
......@@ -25,14 +26,13 @@ namespace {
using test::TestCallbackReceiver;
const std::array<uint8_t, kClientDataHashLength> kClientDataHash = {};
const std::string kRpId = "rp.example.com";
const std::vector<uint8_t> kUserId = {10, 11, 12, 13, 14, 15};
const char kKeychainAccessGroup[] =
"EQHXZ8M8AV.com.google.chrome.webauthn.test";
CtapGetAssertionRequest MakeTestRequest() {
return CtapGetAssertionRequest(kRpId, kClientDataHash);
return CtapGetAssertionRequest(kRpId, test_data::kClientDataJson);
}
bool MakeCredential() API_AVAILABLE(macos(10.12.2)) {
......@@ -40,7 +40,7 @@ bool MakeCredential() API_AVAILABLE(macos(10.12.2)) {
base::Optional<AuthenticatorMakeCredentialResponse>>
callback_receiver;
auto request = CtapMakeCredentialRequest(
kClientDataHash, PublicKeyCredentialRpEntity(kRpId),
test_data::kClientDataJson, PublicKeyCredentialRpEntity(kRpId),
PublicKeyCredentialUserEntity(kUserId),
PublicKeyCredentialParams(
{{PublicKeyCredentialParams::
......
......@@ -13,6 +13,7 @@
#include "base/test/scoped_task_environment.h"
#include "device/fido/fido_constants.h"
#include "device/fido/fido_test_data.h"
#include "device/fido/test_callback_receiver.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -24,7 +25,6 @@ namespace {
using test::TestCallbackReceiver;
const std::array<uint8_t, kClientDataHashLength> kClientDataHash = {};
const std::string kRpId = "rp.example.com";
const std::vector<uint8_t> kUserId = {10, 11, 12, 13, 14, 15};
const char kKeychainAccessGroup[] =
......@@ -32,7 +32,7 @@ const char kKeychainAccessGroup[] =
CtapMakeCredentialRequest MakeTestRequest() {
return CtapMakeCredentialRequest(
kClientDataHash, PublicKeyCredentialRpEntity(kRpId),
test_data::kClientDataJson, PublicKeyCredentialRpEntity(kRpId),
PublicKeyCredentialUserEntity(kUserId),
PublicKeyCredentialParams(
{{PublicKeyCredentialParams::
......
......@@ -73,7 +73,7 @@ class FidoMakeCredentialHandlerTest : public ::testing::Test {
std::vector<PublicKeyCredentialParams::CredentialInfo>(1));
auto request_parameter = CtapMakeCredentialRequest(
test_data::kClientDataHash, std::move(rp), std::move(user),
test_data::kClientDataJson, std::move(rp), std::move(user),
std::move(credential_params));
auto handler = std::make_unique<MakeCredentialRequestHandler>(
......
......@@ -52,7 +52,7 @@ class FidoMakeCredentialTaskTest : public testing::Test {
return std::make_unique<MakeCredentialTask>(
device,
CtapMakeCredentialRequest(
test_data::kClientDataHash, std::move(rp), std::move(user),
test_data::kClientDataJson, std::move(rp), std::move(user),
PublicKeyCredentialParams(
std::vector<PublicKeyCredentialParams::CredentialInfo>(1))),
callback_receiver_.callback());
......@@ -174,7 +174,7 @@ TEST_F(FidoMakeCredentialTaskTest, EnforceClientPinWhenUserVerificationSet) {
PublicKeyCredentialUserEntity user(
fido_parsing_utils::Materialize(test_data::kUserId));
auto request = CtapMakeCredentialRequest(
test_data::kClientDataHash, std::move(rp), std::move(user),
test_data::kClientDataJson, std::move(rp), std::move(user),
PublicKeyCredentialParams(
std::vector<PublicKeyCredentialParams::CredentialInfo>(1)));
request.SetUserVerificationRequired(true);
......
......@@ -29,13 +29,13 @@ CtapMakeCredentialRequest ConstructMakeCredentialRequest() {
.SetIconUrl(GURL("https://pics.acme.com/00/p/aBjjjpqPb.png"));
return CtapMakeCredentialRequest(
test_data::kClientDataHash, std::move(rp), std::move(user),
test_data::kClientDataJson, std::move(rp), std::move(user),
PublicKeyCredentialParams(PublicKeyCredentialParams(
std::vector<PublicKeyCredentialParams::CredentialInfo>(1))));
}
CtapGetAssertionRequest ConstructGetAssertionRequest() {
return CtapGetAssertionRequest("acme.com", test_data::kClientDataHash);
return CtapGetAssertionRequest("acme.com", test_data::kClientDataJson);
}
} // namespace
......@@ -120,7 +120,7 @@ TEST(U2fCommandConstructorTest, TestU2fRegisterCredentialAlgorithmRequirement) {
.SetIconUrl(GURL("https://pics.acme.com/00/p/aBjjjpqPb.png"));
CtapMakeCredentialRequest make_credential_param(
test_data::kClientDataHash, std::move(rp), std::move(user),
test_data::kClientDataJson, std::move(rp), std::move(user),
PublicKeyCredentialParams({{CredentialType::kPublicKey, -257}}));
EXPECT_FALSE(IsConvertibleToU2fRegisterCommand(make_credential_param));
......
......@@ -35,7 +35,7 @@ CtapMakeCredentialRequest CreateRegisterRequestWithRegisteredKeys(
fido_parsing_utils::Materialize(test_data::kUserId));
CtapMakeCredentialRequest request(
test_data::kClientDataHash, std::move(rp), std::move(user),
test_data::kClientDataJson, std::move(rp), std::move(user),
PublicKeyCredentialParams(
std::vector<PublicKeyCredentialParams::CredentialInfo>(1)));
request.SetExcludeList(std::move(registered_keys));
......
......@@ -38,7 +38,7 @@ class U2fSignOperationTest : public ::testing::Test {
CtapGetAssertionRequest CreateSignRequest(
std::vector<std::vector<uint8_t>> key_handles) {
CtapGetAssertionRequest request(test_data::kRelyingPartyId,
test_data::kClientDataHash);
test_data::kClientDataJson);
std::vector<PublicKeyCredentialDescriptor> allowed_list;
for (auto& key_handle : key_handles) {
......
This diff is collapsed.
......@@ -19,6 +19,8 @@
#include "device/fido/attested_credential_data.h"
#include "device/fido/authenticator_data.h"
#include "device/fido/authenticator_supported_options.h"
#include "device/fido/ctap_get_assertion_request.h"
#include "device/fido/ctap_make_credential_request.h"
#include "device/fido/fido_constants.h"
#include "device/fido/virtual_fido_device.h"
......@@ -60,6 +62,22 @@ class COMPONENT_EXPORT(DEVICE_FIDO) VirtualCtap2Device
DISALLOW_COPY_AND_ASSIGN(VirtualCtap2Device);
};
// Decodes a CBOR-encoded CTAP2 authenticatorMakeCredential request message. The
// request's client_data_json() value will be empty, and the hashed client data
// is returned separately.
COMPONENT_EXPORT(DEVICE_FIDO)
base::Optional<std::pair<CtapMakeCredentialRequest,
CtapMakeCredentialRequest::ClientDataHash>>
ParseCtapMakeCredentialRequest(base::span<const uint8_t> request_bytes);
// Decodes a CBOR-encoded CTAP2 authenticatorGetAssertion request message. The
// request's client_data_json() value will be empty, and the hashed client data
// is returned separately.
COMPONENT_EXPORT(DEVICE_FIDO)
base::Optional<
std::pair<CtapGetAssertionRequest, CtapGetAssertionRequest::ClientDataHash>>
ParseCtapGetAssertionRequest(base::span<const uint8_t> request_bytes);
} // namespace device
#endif // DEVICE_FIDO_VIRTUAL_CTAP2_DEVICE_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment