blob: ce0cf3d5cd7ef318acec47ea1144a2dcee9c3c79 [file] [log] [blame]
// Copyright 2021 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef U2FD_U2F_COMMAND_PROCESSOR_VENDOR_H_
#define U2FD_U2F_COMMAND_PROCESSOR_VENDOR_H_
#include <functional>
#include <memory>
#include <optional>
#include <vector>
#include <base/containers/span.h>
#include <brillo/dbus/dbus_method_response.h>
#include <brillo/secure_blob.h>
#include <libhwsec/frontend/u2fd/vendor_frontend.h>
#include <u2f/proto_bindings/u2f_interface.pb.h>
#include "u2fd/client/user_state.h"
#include "u2fd/u2f_command_processor.h"
#include "u2fd/webauthn_handler.h"
namespace u2f {
class U2fCommandProcessorVendor : public U2fCommandProcessor {
public:
// |u2f_frontend| - libhwsec class to deal with U2f vendor commands.
// |request_presence| - callback for performing other platform tasks when
// expecting the user to press the power button.
U2fCommandProcessorVendor(
std::unique_ptr<hwsec::U2fVendorFrontend> u2f_frontend,
std::function<void()> request_presence);
U2fCommandProcessorVendor(const U2fCommandProcessorVendor&) = delete;
U2fCommandProcessorVendor& operator=(const U2fCommandProcessorVendor&) =
delete;
~U2fCommandProcessorVendor() override {}
// Runs a U2F_GENERATE command to create a new key handle, and stores the key
// handle in |credential_id| and the public key in |credential_public_key|.
// The flag in the U2F_GENERATE command is set according to
// |presence_requirement|.
MakeCredentialResponse::MakeCredentialStatus U2fGenerate(
const std::vector<uint8_t>& rp_id_hash,
const brillo::SecureBlob& credential_secret,
PresenceRequirement presence_requirement,
bool uv_compatible,
const brillo::Blob* auth_time_secret_hash,
std::vector<uint8_t>* credential_id,
CredentialPublicKey* credential_public_key,
std::vector<uint8_t>* credential_key_blob) override;
// Runs a U2F_SIGN command to check that credential_id is valid, and if so,
// sign |hash_to_sign| and store the signature in |signature|.
// The flag in the U2F_SIGN command is set according to
// |presence_requirement|.
// |rp_id_hash| must be exactly 32 bytes.
GetAssertionResponse::GetAssertionStatus U2fSign(
const std::vector<uint8_t>& rp_id_hash,
const std::vector<uint8_t>& hash_to_sign,
const std::vector<uint8_t>& credential_id,
const brillo::SecureBlob& credential_secret,
const std::vector<uint8_t>* credential_key_blob,
PresenceRequirement presence_requirement,
std::vector<uint8_t>* signature) override;
// Runs a U2F_SIGN command with "check only" flag to check whether
// |credential_id| is a key handle owned by this device tied to |rp_id_hash|.
HasCredentialsResponse::HasCredentialsStatus U2fSignCheckOnly(
const std::vector<uint8_t>& rp_id_hash,
const std::vector<uint8_t>& credential_id,
const brillo::SecureBlob& credential_secret,
const std::vector<uint8_t>* credential_key_blob) override;
// Run a U2F_ATTEST command to sign data using the cr50 individual attestation
// certificate.
MakeCredentialResponse::MakeCredentialStatus G2fAttest(
const std::vector<uint8_t>& rp_id_hash,
const brillo::SecureBlob& credential_secret,
const std::vector<uint8_t>& challenge,
const std::vector<uint8_t>& credential_public_key,
const std::vector<uint8_t>& credential_id,
std::vector<uint8_t>* cert_out,
std::vector<uint8_t>* signature_out) override;
// Use a random software key to sign the data.
bool G2fSoftwareAttest(const std::vector<uint8_t>& rp_id_hash,
const std::vector<uint8_t>& challenge,
const std::vector<uint8_t>& credential_public_key,
const std::vector<uint8_t>& credential_id,
std::vector<uint8_t>* cert_out,
std::vector<uint8_t>* signature_out) override;
CoseAlgorithmIdentifier GetAlgorithm() override;
hwsec::StatusOr<int> CallAndWaitForPresenceForTest(
std::function<hwsec::StatusOr<int>()> fn);
private:
friend class U2fCommandProcessorVendorTest;
// Repeatedly sends u2f_generate request to the TPM if there's no presence.
MakeCredentialResponse::MakeCredentialStatus SendU2fGenerateWaitForPresence(
bool is_up_only,
const std::vector<uint8_t>& rp_id_hash,
const brillo::SecureBlob& credential_secret,
const std::optional<std::vector<uint8_t>>& auth_time_secret_hash,
std::vector<uint8_t>* credential_id,
CredentialPublicKey* credential_public_key);
// Repeatedly sends u2f_sign request to the TPM if there's no presence.
GetAssertionResponse::GetAssertionStatus SendU2fSignWaitForPresence(
bool is_up_only,
const std::vector<uint8_t>& rp_id_hash,
const brillo::SecureBlob& credential_secret,
const std::optional<brillo::SecureBlob>& auth_time_secret,
const std::vector<uint8_t>& hash_to_sign,
const std::vector<uint8_t>& key_handle,
std::vector<uint8_t>* signature);
// Prompts the user for presence through |request_presence_| and calls |fn|
// repeatedly until success or timeout.
template <typename T, typename F>
hwsec::StatusOr<T> CallAndWaitForPresence(F fn);
static std::vector<uint8_t> EncodeCredentialPublicKeyInCBOR(
base::span<const uint8_t> x, base::span<const uint8_t> y);
std::optional<std::vector<uint8_t>> GetG2fCert();
hwsec::StatusOr<hwsec::u2f::Config> GetConfig();
std::optional<hwsec::u2f::Config> config_ = std::nullopt;
std::unique_ptr<hwsec::U2fVendorFrontend> u2f_frontend_;
std::function<void()> request_presence_;
};
} // namespace u2f
#endif // U2FD_U2F_COMMAND_PROCESSOR_VENDOR_H_