123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- // 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 "device/fido/fido_constants.h"
- #include "device/fido/fido_parsing_utils.h"
- namespace device {
- bool IsConvertibleToU2fRegisterCommand(
- const CtapMakeCredentialRequest& request) {
- if (request.user_verification == UserVerificationRequirement::kRequired ||
- request.resident_key_required)
- 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::kEs256);
- });
- }
- bool ShouldPreferCTAP2EvenIfItNeedsAPIN(
- const CtapMakeCredentialRequest& request) {
- return request.hmac_secret ||
- // U2F devices can only support |kEnterpriseApprovedByBrowser| so
- // |kEnterpriseIfRPListedOnAuthenticator| should go over CTAP2.
- request.attestation_preference ==
- AttestationConveyancePreference::
- kEnterpriseIfRPListedOnAuthenticator;
- }
- bool IsConvertibleToU2fSignCommand(const CtapGetAssertionRequest& request) {
- return request.user_verification != UserVerificationRequirement::kRequired &&
- !request.allow_list.empty();
- }
- absl::optional<std::vector<uint8_t>> ConvertToU2fRegisterCommand(
- const CtapMakeCredentialRequest& request) {
- if (!IsConvertibleToU2fRegisterCommand(request))
- return absl::nullopt;
- if (request.pin_auth && request.pin_auth->size() == 0) {
- // An empty pin_auth in CTAP2 indicates that the device should just wait
- // for a touch.
- return ConstructBogusU2fRegistrationCommand();
- }
- const bool is_individual_attestation =
- request.attestation_preference ==
- AttestationConveyancePreference::kEnterpriseApprovedByBrowser;
- return ConstructU2fRegisterCommand(
- fido_parsing_utils::CreateSHA256Hash(request.rp.id),
- request.client_data_hash, is_individual_attestation);
- }
- absl::optional<std::vector<uint8_t>> ConvertToU2fSignCommandWithBogusChallenge(
- const CtapMakeCredentialRequest& request,
- base::span<const uint8_t> key_handle) {
- return ConstructU2fSignCommand(
- fido_parsing_utils::CreateSHA256Hash(request.rp.id),
- kBogusChallenge, key_handle);
- }
- absl::optional<std::vector<uint8_t>> ConvertToU2fSignCommand(
- const CtapGetAssertionRequest& request,
- ApplicationParameterType application_parameter_type,
- base::span<const uint8_t> key_handle) {
- if (!IsConvertibleToU2fSignCommand(request))
- return absl::nullopt;
- const auto& application_parameter =
- application_parameter_type == ApplicationParameterType::kPrimary
- ? fido_parsing_utils::CreateSHA256Hash(request.rp_id)
- : request.alternative_application_parameter.value_or(
- std::array<uint8_t, kRpIdHashLength>());
- return ConstructU2fSignCommand(application_parameter,
- request.client_data_hash, key_handle);
- }
- std::vector<uint8_t> ConstructU2fRegisterCommand(
- base::span<const uint8_t, kU2fApplicationParamLength> application_parameter,
- base::span<const uint8_t, kU2fChallengeParamLength> challenge_parameter,
- bool is_individual_attestation) {
- std::vector<uint8_t> data;
- data.reserve(kU2fChallengeParamLength + kU2fApplicationParamLength);
- 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();
- }
- absl::optional<std::vector<uint8_t>> ConstructU2fSignCommand(
- base::span<const uint8_t, kU2fApplicationParamLength> application_parameter,
- base::span<const uint8_t, kU2fChallengeParamLength> challenge_parameter,
- base::span<const uint8_t> key_handle) {
- if (key_handle.size() > kMaxKeyHandleLength) {
- return absl::nullopt;
- }
- std::vector<uint8_t> data;
- data.reserve(kU2fChallengeParamLength + kU2fApplicationParamLength + 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(kP1TupRequiredConsumed);
- command.set_data(std::move(data));
- command.set_response_length(apdu::ApduCommand::kApduMaxResponseLength);
- return command.GetEncodedCommand();
- }
- std::vector<uint8_t> ConstructBogusU2fRegistrationCommand() {
- return ConstructU2fRegisterCommand(kBogusAppParam, kBogusChallenge);
- }
- } // namespace device
|