Commit 85b28723 authored by Jun Choi's avatar Jun Choi Committed by Commit Bot

Implement logic to extract U2F parameters

Implement anonymous set of functions that extract U2F request commands
from WebAuthN style Ctap{MakeCredential GetAssertion} Request.

Bug: 798573
Change-Id: I3431b0769db20b39a2e590d5a7d4136a3a920fe8
Reviewed-on: https://chromium-review.googlesource.com/1018739
Commit-Queue: Jun Choi <hongjunchoi@chromium.org>
Reviewed-by: default avatarJan Wilken Dörrie <jdoerrie@chromium.org>
Cr-Commit-Position: refs/heads/master@{#553754}
parent 74b0a582
...@@ -79,6 +79,7 @@ test("device_unittests") { ...@@ -79,6 +79,7 @@ test("device_unittests") {
"fido/make_credential_handler_unittest.cc", "fido/make_credential_handler_unittest.cc",
"fido/make_credential_task_unittest.cc", "fido/make_credential_task_unittest.cc",
"fido/test_callback_receiver_unittest.cc", "fido/test_callback_receiver_unittest.cc",
"fido/u2f_command_constructor_unittest.cc",
"fido/u2f_register_unittest.cc", "fido/u2f_register_unittest.cc",
"fido/u2f_request_unittest.cc", "fido/u2f_request_unittest.cc",
"fido/u2f_sign_unittest.cc", "fido/u2f_sign_unittest.cc",
......
...@@ -91,6 +91,8 @@ component("fido") { ...@@ -91,6 +91,8 @@ component("fido") {
"public_key_credential_user_entity.h", "public_key_credential_user_entity.h",
"response_data.cc", "response_data.cc",
"response_data.h", "response_data.h",
"u2f_command_constructor.cc",
"u2f_command_constructor.h",
"u2f_register.cc", "u2f_register.cc",
"u2f_register.h", "u2f_register.h",
"u2f_request.cc", "u2f_request.cc",
......
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#include "device/fido/ctap_get_assertion_request.h" #include "device/fido/ctap_get_assertion_request.h"
#include "device/fido/ctap_make_credential_request.h" #include "device/fido/ctap_make_credential_request.h"
#include "device/fido/fido_constants.h" #include "device/fido/fido_constants.h"
#include "device/fido/fido_parsing_utils.h"
#include "device/fido/fido_test_data.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -14,16 +16,6 @@ namespace device { ...@@ -14,16 +16,6 @@ namespace device {
// Leveraging example 4 of section 6.1 of the spec // Leveraging example 4 of section 6.1 of the spec
// https://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-client-to-authenticator-protocol-v2.0-rd-20170927.html // https://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-client-to-authenticator-protocol-v2.0-rd-20170927.html
TEST(CTAPRequestTest, TestConstructMakeCredentialRequestParam) { TEST(CTAPRequestTest, TestConstructMakeCredentialRequestParam) {
static constexpr uint8_t kClientDataHash[] = {
0x68, 0x71, 0x34, 0x96, 0x82, 0x22, 0xec, 0x17, 0x20, 0x2e, 0x42,
0x50, 0x5f, 0x8e, 0xd2, 0xb1, 0x6a, 0xe2, 0x2f, 0x16, 0xbb, 0x05,
0xb8, 0x8c, 0x25, 0xdb, 0x9e, 0x60, 0x26, 0x45, 0xf1, 0x41};
static constexpr uint8_t kUserId[] = {
0x30, 0x82, 0x01, 0x93, 0x30, 0x82, 0x01, 0x38, 0xa0, 0x03, 0x02,
0x01, 0x02, 0x30, 0x82, 0x01, 0x93, 0x30, 0x82, 0x01, 0x38, 0xa0,
0x03, 0x02, 0x01, 0x02, 0x30, 0x82, 0x01, 0x93, 0x30, 0x82};
static constexpr uint8_t kSerializedRequest[] = { static constexpr uint8_t kSerializedRequest[] = {
// clang-format off // clang-format off
0x01, // authenticatorMakeCredential command 0x01, // authenticatorMakeCredential command
...@@ -50,10 +42,8 @@ TEST(CTAPRequestTest, TestConstructMakeCredentialRequestParam) { ...@@ -50,10 +42,8 @@ TEST(CTAPRequestTest, TestConstructMakeCredentialRequestParam) {
0xa4, // map(4) 0xa4, // map(4)
0x62, // text(2) 0x62, // text(2)
0x69, 0x64, // "id" 0x69, 0x64, // "id"
0x58, 0x20, // bytes(32) - user id 0x48, // bytes(8) - user id
0x30, 0x82, 0x01, 0x93, 0x30, 0x82, 0x01, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x10, 0x98, 0x23, 0x72, 0x35, 0x40, 0x98, 0x72,
0x02, 0x30, 0x82, 0x01, 0x93, 0x30, 0x82, 0x01, 0x38, 0xa0, 0x03, 0x02,
0x01, 0x02, 0x30, 0x82, 0x01, 0x93, 0x30, 0x82,
0x64, // text(4) 0x64, // text(4)
0x69, 0x63, 0x6f, 0x6e, // "icon" 0x69, 0x63, 0x6f, 0x6e, // "icon"
0x78, 0x28, // text(40) 0x78, 0x28, // text(40)
...@@ -112,13 +102,13 @@ TEST(CTAPRequestTest, TestConstructMakeCredentialRequestParam) { ...@@ -112,13 +102,13 @@ TEST(CTAPRequestTest, TestConstructMakeCredentialRequestParam) {
rp.SetRpName("Acme"); rp.SetRpName("Acme");
PublicKeyCredentialUserEntity user( PublicKeyCredentialUserEntity user(
std::vector<uint8_t>(kUserId, std::end(kUserId))); fido_parsing_utils::Materialize(test_data::kUserId));
user.SetUserName("johnpsmith@example.com") user.SetUserName("johnpsmith@example.com")
.SetDisplayName("John P. Smith") .SetDisplayName("John P. Smith")
.SetIconUrl(GURL("https://pics.acme.com/00/p/aBjjjpqPb.png")); .SetIconUrl(GURL("https://pics.acme.com/00/p/aBjjjpqPb.png"));
CtapMakeCredentialRequest make_credential_param( CtapMakeCredentialRequest make_credential_param(
std::vector<uint8_t>(kClientDataHash, std::end(kClientDataHash)), fido_parsing_utils::Materialize(test_data::kClientDataHash),
std::move(rp), std::move(user), std::move(rp), std::move(user),
PublicKeyCredentialParams({{CredentialType::kPublicKey, 7}, PublicKeyCredentialParams({{CredentialType::kPublicKey, 7},
{CredentialType::kPublicKey, 257}})); {CredentialType::kPublicKey, 257}}));
...@@ -129,11 +119,6 @@ TEST(CTAPRequestTest, TestConstructMakeCredentialRequestParam) { ...@@ -129,11 +119,6 @@ TEST(CTAPRequestTest, TestConstructMakeCredentialRequestParam) {
} }
TEST(CTAPRequestTest, TestConstructGetAssertionRequest) { TEST(CTAPRequestTest, TestConstructGetAssertionRequest) {
static constexpr uint8_t kClientDataHash[] = {
0x68, 0x71, 0x34, 0x96, 0x82, 0x22, 0xec, 0x17, 0x20, 0x2e, 0x42,
0x50, 0x5f, 0x8e, 0xd2, 0xb1, 0x6a, 0xe2, 0x2f, 0x16, 0xbb, 0x05,
0xb8, 0x8c, 0x25, 0xdb, 0x9e, 0x60, 0x26, 0x45, 0xf1, 0x41};
static constexpr uint8_t kSerializedRequest[] = { static constexpr uint8_t kSerializedRequest[] = {
// clang-format off // clang-format off
0x02, // authenticatorGetAssertion command 0x02, // authenticatorGetAssertion command
...@@ -198,8 +183,7 @@ TEST(CTAPRequestTest, TestConstructGetAssertionRequest) { ...@@ -198,8 +183,7 @@ TEST(CTAPRequestTest, TestConstructGetAssertionRequest) {
}; };
CtapGetAssertionRequest get_assertion_req( CtapGetAssertionRequest get_assertion_req(
"acme.com", "acme.com", fido_parsing_utils::Materialize(test_data::kClientDataHash));
std::vector<uint8_t>(kClientDataHash, std::end(kClientDataHash)));
std::vector<PublicKeyCredentialDescriptor> allowed_list; std::vector<PublicKeyCredentialDescriptor> allowed_list;
allowed_list.push_back(PublicKeyCredentialDescriptor( allowed_list.push_back(PublicKeyCredentialDescriptor(
......
...@@ -212,6 +212,19 @@ enum class UserVerificationRequirement { ...@@ -212,6 +212,19 @@ enum class UserVerificationRequirement {
kDiscouraged, kDiscouraged,
}; };
// Enumerates the two types of application parameter values used: the
// "primary" value is the hash of the relying party ID[1] and is always
// provided. The "alternative" value is the hash of a U2F AppID, specified in
// an extension[2], for compatibility with keys that were registered with the
// old API.
//
// [1] https://w3c.github.io/webauthn/#rp-id
// [2] https://w3c.github.io/webauthn/#sctn-appid-extension
enum class ApplicationParameterType {
kPrimary,
kAlternative,
};
// Parameters for fake U2F registration used to check for user presence. // Parameters for fake U2F registration used to check for user presence.
COMPONENT_EXPORT(DEVICE_FIDO) COMPONENT_EXPORT(DEVICE_FIDO)
extern const std::array<uint8_t, 32> kBogusAppParam; extern const std::array<uint8_t, 32> kBogusAppParam;
......
...@@ -28,6 +28,13 @@ constexpr uint8_t kApplicationParameter[] = { ...@@ -28,6 +28,13 @@ constexpr uint8_t kApplicationParameter[] = {
0x7B, 0xCF, 0x01, 0x3D, 0xE9, 0x6D, 0x4E, 0xFB, 0x17, 0xDE, 0x7B, 0xCF, 0x01, 0x3D, 0xE9, 0x6D, 0x4E, 0xFB, 0x17, 0xDE,
}; };
constexpr uint8_t kClientDataHash[] = {
0x68, 0x71, 0x34, 0x96, 0x82, 0x22, 0xec, 0x17, 0x20, 0x2e, 0x42,
0x50, 0x5f, 0x8e, 0xd2, 0xb1, 0x6a, 0xe2, 0x2f, 0x16, 0xbb, 0x05,
0xb8, 0x8c, 0x25, 0xdb, 0x9e, 0x60, 0x26, 0x45, 0xf1, 0x41};
constexpr uint8_t kUserId[] = {0x10, 0x98, 0x23, 0x72, 0x35, 0x40, 0x98, 0x72};
constexpr char kRelyingPartyId[] = "example.com"; constexpr char kRelyingPartyId[] = "example.com";
constexpr uint8_t kU2fRegisterCommandApduWithIndividualAttestation[] = { constexpr uint8_t kU2fRegisterCommandApduWithIndividualAttestation[] = {
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "device/fido/u2f_command_constructor.h"
#include <string>
#include <utility>
#include "components/apdu/apdu_command.h"
#include "crypto/sha2.h"
#include "device/fido/fido_parsing_utils.h"
namespace device {
namespace {
std::vector<uint8_t> CreateHash(const std::string& data) {
std::vector<uint8_t> hashed_data(crypto::kSHA256Length);
crypto::SHA256HashString(data, hashed_data.data(), hashed_data.size());
return hashed_data;
}
} // namespace
bool IsConvertibleToU2fRegisterCommand(
const CtapMakeCredentialRequest& request) {
if (request.user_verification_required() || request.resident_key_supported())
return false;
const auto& public_key_credential_info =
request.public_key_credential_params().public_key_credential_params();
return std::any_of(
public_key_credential_info.begin(), public_key_credential_info.end(),
[](const auto& credential_info) {
return credential_info.algorithm ==
base::strict_cast<int>(CoseAlgorithmIdentifier::kCoseEs256);
});
}
bool IsConvertibleToU2fSignCommand(const CtapGetAssertionRequest& request) {
const auto& allow_list = request.allow_list();
return request.user_verification() !=
UserVerificationRequirement::kRequired &&
allow_list && !allow_list->empty();
}
base::Optional<std::vector<uint8_t>> ConvertToU2fRegisterCommand(
const CtapMakeCredentialRequest& request) {
if (!IsConvertibleToU2fRegisterCommand(request))
return base::nullopt;
return ConstructU2fRegisterCommand(CreateHash(request.rp().rp_id()),
request.client_data_hash());
}
base::Optional<std::vector<uint8_t>> ConvertToU2fSignCommand(
const CtapGetAssertionRequest& request,
ApplicationParameterType application_parameter_type,
base::span<const uint8_t> key_handle,
bool check_only) {
if (!IsConvertibleToU2fSignCommand(request))
return base::nullopt;
auto application_parameter =
application_parameter_type == ApplicationParameterType::kPrimary
? CreateHash(request.rp_id())
: std::vector<uint8_t>();
return ConstructU2fSignCommand(std::move(application_parameter),
request.client_data_hash(), key_handle,
check_only);
}
base::Optional<std::vector<uint8_t>> ConstructU2fRegisterCommand(
base::span<const uint8_t> application_parameter,
base::span<const uint8_t> challenge_parameter,
bool is_individual_attestation) {
if (application_parameter.size() != kU2fParameterLength ||
challenge_parameter.size() != kU2fParameterLength) {
return base::nullopt;
}
std::vector<uint8_t> data;
data.reserve(challenge_parameter.size() + application_parameter.size());
fido_parsing_utils::Append(&data, challenge_parameter);
fido_parsing_utils::Append(&data, application_parameter);
apdu::ApduCommand command;
command.set_ins(base::strict_cast<uint8_t>(U2fApduInstruction::kRegister));
command.set_p1(kP1TupRequiredConsumed |
(is_individual_attestation ? kP1IndividualAttestation : 0));
command.set_data(std::move(data));
command.set_response_length(apdu::ApduCommand::kApduMaxResponseLength);
return command.GetEncodedCommand();
}
base::Optional<std::vector<uint8_t>> ConstructU2fSignCommand(
base::span<const uint8_t> application_parameter,
base::span<const uint8_t> challenge_parameter,
base::span<const uint8_t> key_handle,
bool check_only) {
if (application_parameter.size() != kU2fParameterLength ||
challenge_parameter.size() != kU2fParameterLength ||
key_handle.size() > kMaxKeyHandleLength) {
return base::nullopt;
}
std::vector<uint8_t> data;
data.reserve(challenge_parameter.size() + application_parameter.size() + 1 +
key_handle.size());
fido_parsing_utils::Append(&data, challenge_parameter);
fido_parsing_utils::Append(&data, application_parameter);
data.push_back(static_cast<uint8_t>(key_handle.size()));
fido_parsing_utils::Append(&data, key_handle);
apdu::ApduCommand command;
command.set_ins(base::strict_cast<uint8_t>(U2fApduInstruction::kSign));
command.set_p1(check_only ? kP1CheckOnly : kP1TupRequiredConsumed);
command.set_data(std::move(data));
command.set_response_length(apdu::ApduCommand::kApduMaxResponseLength);
return command.GetEncodedCommand();
}
} // namespace device
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef DEVICE_FIDO_U2F_COMMAND_CONSTRUCTOR_H_
#define DEVICE_FIDO_U2F_COMMAND_CONSTRUCTOR_H_
#include <stdint.h>
#include <vector>
#include "base/component_export.h"
#include "base/containers/span.h"
#include "base/optional.h"
#include "device/fido/ctap_get_assertion_request.h"
#include "device/fido/ctap_make_credential_request.h"
#include "device/fido/fido_constants.h"
namespace device {
// Checks whether the request can be translated to valid U2F request
// parameter. Namely, U2F request does not support resident key and
// user verification, and ES256 algorithm must be used for public key
// credential.
// https://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-client-to-authenticator-protocol-v2.0-rd-20170927.html#using-the-ctap2-authenticatormakecredential-command-with-ctap1-u2f-authenticators
COMPONENT_EXPORT(DEVICE_FIDO)
bool IsConvertibleToU2fRegisterCommand(
const CtapMakeCredentialRequest& request);
// Checks whether user verification is not required and that allow list is
// not empty.
// https://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-client-to-authenticator-protocol-v2.0-rd-20170927.html#using-the-ctap2-authenticatorgetassertion-command-with-ctap1-u2f-authenticators
COMPONENT_EXPORT(DEVICE_FIDO)
bool IsConvertibleToU2fSignCommand(const CtapGetAssertionRequest& request);
// Extracts APDU encoded U2F register command from CtapMakeCredentialRequest.
COMPONENT_EXPORT(DEVICE_FIDO)
base::Optional<std::vector<uint8_t>> ConvertToU2fRegisterCommand(
const CtapMakeCredentialRequest& request);
// Extracts APDU encoded U2F sign command from CtapGetAssertionRequest.
COMPONENT_EXPORT(DEVICE_FIDO)
base::Optional<std::vector<uint8_t>> ConvertToU2fSignCommand(
const CtapGetAssertionRequest& request,
ApplicationParameterType application_parameter_type,
base::span<const uint8_t> key_handle,
bool check_only = false);
// TODO(hongjunchoi): Move this logic inside ConvertToU2fRegisterCommand()
// once U2fRegister is removed.
COMPONENT_EXPORT(DEVICE_FIDO)
base::Optional<std::vector<uint8_t>> ConstructU2fRegisterCommand(
base::span<const uint8_t> application_parameter,
base::span<const uint8_t> challenge_parameter,
bool is_individual_attestation = false);
// TODO(hongjunchoi): Move this logic inside ConvertToU2fSignCommand() once
// U2fSign is deleted.
COMPONENT_EXPORT(DEVICE_FIDO)
base::Optional<std::vector<uint8_t>> ConstructU2fSignCommand(
base::span<const uint8_t> application_parameter,
base::span<const uint8_t> challenge_parameter,
base::span<const uint8_t> key_handle,
bool check_only = false);
} // namespace device
#endif // DEVICE_FIDO_U2F_COMMAND_CONSTRUCTOR_H_
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "device/fido/u2f_command_constructor.h"
#include <utility>
#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/fido_parsing_utils.h"
#include "device/fido/fido_test_data.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace device {
TEST(U2fCommandConstructorTest, TestConvertCtapMakeCredentialToU2fRegister) {
PublicKeyCredentialRpEntity rp("acme.com");
rp.SetRpName("acme.com");
PublicKeyCredentialUserEntity user(
fido_parsing_utils::Materialize(test_data::kUserId));
user.SetUserName("johnpsmith@example.com")
.SetDisplayName("John P. Smith")
.SetIconUrl(GURL("https://pics.acme.com/00/p/aBjjjpqPb.png"));
CtapMakeCredentialRequest make_credential_param(
fido_parsing_utils::Materialize(test_data::kClientDataHash),
std::move(rp), std::move(user),
PublicKeyCredentialParams({{CredentialType::kPublicKey, -7},
{CredentialType::kPublicKey, -257}}));
EXPECT_TRUE(IsConvertibleToU2fRegisterCommand(make_credential_param));
const auto u2f_register_command =
ConvertToU2fRegisterCommand(make_credential_param);
ASSERT_TRUE(u2f_register_command);
EXPECT_THAT(*u2f_register_command,
::testing::ElementsAreArray(test_data::kU2fRegisterCommandApdu));
}
TEST(U2fCommandConstructorTest, TestU2fRegisterCredentialAlgorithmRequirement) {
PublicKeyCredentialRpEntity rp("acme.com");
rp.SetRpName("acme.com");
PublicKeyCredentialUserEntity user(
fido_parsing_utils::Materialize(test_data::kUserId));
user.SetUserName("johnpsmith@example.com")
.SetDisplayName("John P. Smith")
.SetIconUrl(GURL("https://pics.acme.com/00/p/aBjjjpqPb.png"));
CtapMakeCredentialRequest make_credential_param(
fido_parsing_utils::Materialize(test_data::kClientDataHash),
std::move(rp), std::move(user),
PublicKeyCredentialParams({{CredentialType::kPublicKey, -257}}));
EXPECT_FALSE(IsConvertibleToU2fRegisterCommand(make_credential_param));
}
TEST(U2fCommandConstructorTest, TestU2fRegisterUserVerificationRequirement) {
PublicKeyCredentialRpEntity rp("acme.com");
rp.SetRpName("acme.com");
PublicKeyCredentialUserEntity user(
fido_parsing_utils::Materialize(test_data::kUserId));
user.SetUserName("johnpsmith@example.com")
.SetDisplayName("John P. Smith")
.SetIconUrl(GURL("https://pics.acme.com/00/p/aBjjjpqPb.png"));
CtapMakeCredentialRequest make_credential_param(
fido_parsing_utils::Materialize(test_data::kClientDataHash),
std::move(rp), std::move(user),
PublicKeyCredentialParams({{CredentialType::kPublicKey, -7}}));
make_credential_param.SetUserVerificationRequired(true);
EXPECT_FALSE(IsConvertibleToU2fRegisterCommand(make_credential_param));
}
TEST(U2fCommandConstructorTest, TestU2fRegisterResidentKeyRequirement) {
PublicKeyCredentialRpEntity rp("acme.com");
rp.SetRpName("acme.com");
PublicKeyCredentialUserEntity user(
fido_parsing_utils::Materialize(test_data::kUserId));
user.SetUserName("johnpsmith@example.com")
.SetDisplayName("John P. Smith")
.SetIconUrl(GURL("https://pics.acme.com/00/p/aBjjjpqPb.png"));
CtapMakeCredentialRequest make_credential_param(
fido_parsing_utils::Materialize(test_data::kClientDataHash),
std::move(rp), std::move(user),
PublicKeyCredentialParams({{CredentialType::kPublicKey, -7}}));
make_credential_param.SetResidentKeySupported(true);
EXPECT_FALSE(IsConvertibleToU2fRegisterCommand(make_credential_param));
}
TEST(U2fCommandConstructorTest, TestConvertCtapGetAssertionToU2fSignRequest) {
CtapGetAssertionRequest get_assertion_req(
"acme.com", fido_parsing_utils::Materialize(test_data::kClientDataHash));
std::vector<PublicKeyCredentialDescriptor> allowed_list;
allowed_list.push_back(PublicKeyCredentialDescriptor(
kPublicKey,
fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle)));
get_assertion_req.SetAllowList(std::move(allowed_list));
const auto u2f_sign_command = ConvertToU2fSignCommand(
get_assertion_req, ApplicationParameterType::kPrimary,
fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle));
EXPECT_TRUE(IsConvertibleToU2fSignCommand(get_assertion_req));
ASSERT_TRUE(u2f_sign_command);
EXPECT_THAT(*u2f_sign_command,
::testing::ElementsAreArray(test_data::kU2fSignCommandApdu));
}
TEST(U2fCommandConstructorTest, TestU2fSignAllowListRequirement) {
CtapGetAssertionRequest get_assertion_req(
"acme.com", fido_parsing_utils::Materialize(test_data::kClientDataHash));
EXPECT_FALSE(IsConvertibleToU2fSignCommand(get_assertion_req));
}
TEST(U2fCommandConstructorTest, TestU2fSignUserVerificationRequirement) {
CtapGetAssertionRequest get_assertion_req(
"acme.com", fido_parsing_utils::Materialize(test_data::kClientDataHash));
std::vector<PublicKeyCredentialDescriptor> allowed_list;
allowed_list.push_back(PublicKeyCredentialDescriptor(
kPublicKey,
fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle)));
get_assertion_req.SetAllowList(std::move(allowed_list));
get_assertion_req.SetUserVerification(UserVerificationRequirement::kRequired);
EXPECT_FALSE(IsConvertibleToU2fSignCommand(get_assertion_req));
}
} // namespace device
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "build/build_config.h" #include "build/build_config.h"
#include "components/apdu/apdu_command.h" #include "components/apdu/apdu_command.h"
#include "components/apdu/apdu_response.h" #include "components/apdu/apdu_response.h"
#include "device/fido/u2f_command_constructor.h"
#include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/cpp/connector.h"
namespace device { namespace device {
...@@ -83,40 +84,14 @@ base::Optional<std::vector<uint8_t>> U2fRequest::GetU2fSignApduCommand( ...@@ -83,40 +84,14 @@ base::Optional<std::vector<uint8_t>> U2fRequest::GetU2fSignApduCommand(
const std::vector<uint8_t>& application_parameter, const std::vector<uint8_t>& application_parameter,
const std::vector<uint8_t>& key_handle, const std::vector<uint8_t>& key_handle,
bool is_check_only_sign) const { bool is_check_only_sign) const {
if (application_parameter.size() != kU2fParameterLength || return ConstructU2fSignCommand(application_parameter, challenge_digest_,
challenge_digest_.size() != kU2fParameterLength || key_handle, is_check_only_sign);
key_handle.size() > kMaxKeyHandleLength) {
return base::nullopt;
}
apdu::ApduCommand command;
std::vector<uint8_t> data(challenge_digest_.begin(), challenge_digest_.end());
data.insert(data.end(), application_parameter.begin(),
application_parameter.end());
data.push_back(static_cast<uint8_t>(key_handle.size()));
data.insert(data.end(), key_handle.begin(), key_handle.end());
command.set_ins(base::strict_cast<uint8_t>(U2fApduInstruction::kSign));
command.set_p1(is_check_only_sign ? kP1CheckOnly : kP1TupRequiredConsumed);
command.set_data(data);
command.set_response_length(apdu::ApduCommand::kApduMaxResponseLength);
return command.GetEncodedCommand();
} }
base::Optional<std::vector<uint8_t>> U2fRequest::GetU2fRegisterApduCommand( base::Optional<std::vector<uint8_t>> U2fRequest::GetU2fRegisterApduCommand(
bool is_individual_attestation) const { bool is_individual_attestation) const {
if (application_parameter_.size() != kU2fParameterLength || return ConstructU2fRegisterCommand(application_parameter_, challenge_digest_,
challenge_digest_.size() != kU2fParameterLength) { is_individual_attestation);
return base::nullopt;
}
apdu::ApduCommand command;
std::vector<uint8_t> data(challenge_digest_.begin(), challenge_digest_.end());
data.insert(data.end(), application_parameter_.begin(),
application_parameter_.end());
command.set_ins(base::strict_cast<uint8_t>(U2fApduInstruction::kRegister));
command.set_p1(kP1TupRequiredConsumed |
(is_individual_attestation ? kP1IndividualAttestation : 0));
command.set_data(data);
command.set_response_length(apdu::ApduCommand::kApduMaxResponseLength);
return command.GetEncodedCommand();
} }
void U2fRequest::Transition() { void U2fRequest::Transition() {
......
...@@ -49,19 +49,6 @@ class COMPONENT_EXPORT(DEVICE_FIDO) U2fSign : public U2fRequest { ...@@ -49,19 +49,6 @@ class COMPONENT_EXPORT(DEVICE_FIDO) U2fSign : public U2fRequest {
~U2fSign() override; ~U2fSign() override;
private: private:
// Enumerates the two types of |application_parameter| values used: the
// "primary" value is the hash of the relying party ID[1] and is always
// provided. The "alternative" value is the hash of a U2F AppID, specified in
// an extension[2], for compatibility with keys that were registered with the
// old API.
//
// [1] https://w3c.github.io/webauthn/#rp-id
// [2] https://w3c.github.io/webauthn/#sctn-appid-extension
enum class ApplicationParameterType {
kPrimary,
kAlternative,
};
void TryDevice() override; void TryDevice() override;
void OnTryDevice(std::vector<std::vector<uint8_t>>::const_iterator it, void OnTryDevice(std::vector<std::vector<uint8_t>>::const_iterator it,
ApplicationParameterType application_parameter_type, ApplicationParameterType application_parameter_type,
......
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