// 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/authenticator_get_assertion_response.h" #include #include "components/cbor/values.h" #include "components/cbor/writer.h" #include "components/device_event_log/device_event_log.h" #include "device/fido/authenticator_data.h" #include "device/fido/fido_parsing_utils.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/boringssl/src/include/openssl/ecdsa.h" namespace device { namespace { constexpr size_t kFlagIndex = 0; constexpr size_t kFlagLength = 1; constexpr size_t kCounterIndex = 1; constexpr size_t kCounterLength = 4; constexpr size_t kSignatureIndex = 5; } // namespace // static absl::optional AuthenticatorGetAssertionResponse::CreateFromU2fSignResponse( base::span relying_party_id_hash, base::span u2f_data, base::span key_handle) { if (u2f_data.size() <= kSignatureIndex) return absl::nullopt; if (key_handle.empty()) return absl::nullopt; auto flags = u2f_data.subspan()[0]; if (flags & (static_cast(AuthenticatorData::Flag::kExtensionDataIncluded) | static_cast(AuthenticatorData::Flag::kAttestation))) { // U2F responses cannot assert CTAP2 features. return absl::nullopt; } auto counter = u2f_data.subspan(); AuthenticatorData authenticator_data(relying_party_id_hash, flags, counter, absl::nullopt); auto signature = fido_parsing_utils::Materialize(u2f_data.subspan(kSignatureIndex)); bssl::UniquePtr parsed_sig( ECDSA_SIG_from_bytes(signature.data(), signature.size())); if (!parsed_sig) { FIDO_LOG(ERROR) << "Rejecting U2F assertion response with invalid signature"; return absl::nullopt; } AuthenticatorGetAssertionResponse response(std::move(authenticator_data), std::move(signature)); response.credential = PublicKeyCredentialDescriptor( CredentialType::kPublicKey, fido_parsing_utils::Materialize(key_handle)); return std::move(response); } AuthenticatorGetAssertionResponse::AuthenticatorGetAssertionResponse( AuthenticatorData authenticator_data, std::vector signature) : authenticator_data(std::move(authenticator_data)), signature(std::move(signature)) {} AuthenticatorGetAssertionResponse::AuthenticatorGetAssertionResponse( AuthenticatorGetAssertionResponse&& that) = default; AuthenticatorGetAssertionResponse& AuthenticatorGetAssertionResponse::operator=( AuthenticatorGetAssertionResponse&& other) = default; AuthenticatorGetAssertionResponse::~AuthenticatorGetAssertionResponse() = default; } // namespace device