blob: dd6f214ef94a4b460220e76afecda72dd519f2a6 [file] [log] [blame]
// Copyright 2019 The Chromium OS 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 U2FD_U2F_MSG_HANDLER_H_
#define U2FD_U2F_MSG_HANDLER_H_
#include <functional>
#include <memory>
#include <string>
#include <vector>
#include <attestation/proto_bindings/interface.pb.h>
#include <base/optional.h>
#include <metrics/metrics_library.h>
#include "u2fd/allowlisting_util.h"
#include "u2fd/tpm_vendor_cmd.h"
#include "u2fd/u2f_adpu.h"
#include "u2fd/user_state.h"
namespace u2f {
// Processes incoming U2F messages, and produces corresponding responses.
class U2fMessageHandler {
public:
// Constructs a new message handler. Does not take ownership of proxy or
// metrics, both of which must outlive this instance.
U2fMessageHandler(std::unique_ptr<AllowlistingUtil> allowlisting_util,
std::function<void()> request_user_presence,
UserState* user_state,
TpmVendorCommandProxy* proxy,
MetricsLibraryInterface* metrics,
bool allow_legacy_kh_sign,
bool allow_g2f_attestation);
// Processes the ADPU and builds a response locally, making using of cr50
// vendor commands where necessary.
U2fResponseAdpu ProcessMsg(const std::string& request);
private:
// Process a U2F_REGISTER ADPU.
U2fResponseAdpu ProcessU2fRegister(const U2fRegisterRequestAdpu& request);
// Process a U2F_AUTHENTICATE ADPU.
U2fResponseAdpu ProcessU2fAuthenticate(
const U2fAuthenticateRequestAdpu& request);
// Status for execution of a cr50 command. Includes status of preparation
// of the request, actual execution of the cr50 command, and any processing
// of the response.
enum class Cr50CmdStatus : uint32_t {
// Cr50 return codes, map to vendor_cmd_rc in tpm_vendor_cmds.h
kSuccess = 0,
kNotAllowed = 0x507,
kPasswordRequired = 0x50a,
// Errors that occur in u2fd while processing requests/responses.
kInvalidState = 0x580,
kInvalidResponseData,
};
// Wrapper functions for cr50 U2F vendor commands.
// Run a U2F_GENERATE command to create a new key handle.
Cr50CmdStatus DoU2fGenerate(const std::vector<uint8_t>& app_id,
std::vector<uint8_t>* pub_key,
std::vector<uint8_t>* key_handle);
// Run a U2F_SIGN command to sign a hash using an existing key handle.
Cr50CmdStatus DoU2fSign(const std::vector<uint8_t>& app_id,
const std::vector<uint8_t>& key_handle,
const std::vector<uint8_t>& hash,
std::vector<uint8_t>* signature);
// Run a U2F_SIGN command to check if a key handle is valid.
Cr50CmdStatus DoU2fSignCheckOnly(const std::vector<uint8_t>& app_id,
const std::vector<uint8_t>& key_handle);
// Run a U2F_ATTEST command to sign data using the cr50 individual attestation
// certificate. Returns true on success.
Cr50CmdStatus DoG2fAttest(const std::vector<uint8_t>& data,
uint8_t format,
std::vector<uint8_t>* sig_out);
// Retrieves the G2F certificate from cr50. Returns nullopt on failure.
base::Optional<std::vector<uint8_t>> GetG2fCert();
// Builds an empty U2F response with the specified status code.
U2fResponseAdpu BuildEmptyResponse(uint16_t sw);
// Builds an empty U2F response with a U2F status code corresponding to the
// specified cr50 status.
U2fResponseAdpu BuildErrorResponse(Cr50CmdStatus status);
std::unique_ptr<AllowlistingUtil> allowlisting_util_;
std::function<void()> request_user_presence_;
UserState* user_state_;
TpmVendorCommandProxy* proxy_;
MetricsLibraryInterface* metrics_;
const bool allow_legacy_kh_sign_;
const bool allow_g2f_attestation_;
};
} // namespace u2f
#endif // U2FD_U2F_MSG_HANDLER_H_