blob: 0e701f8ea45fa59f38d8b8e71377bfd65248aae8 [file] [log] [blame]
// Copyright 2017 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_TPM_VENDOR_CMD_H_
#define U2FD_TPM_VENDOR_CMD_H_
#include <string>
#include <base/macros.h>
#include <trunks/cr50_headers/u2f.h>
#include <trunks/trunks_dbus_proxy.h>
namespace u2f {
// The TPM response code is all zero for success.
// Errors are a little complicated:
//
// Bits 31:12 must be zero.
//
// Bit 11 S=0 Error
// Bit 10 T=1 Vendor defined response code
// Bit 9 r=0 reserved
// Bit 8 V=1 Conforms to TPMv2 spec
// Bit 7 F=0 Conforms to Table 14, Format-Zero Response Codes
// Bits 6:0 num 128 possible failure reasons
const uint32_t kVendorRcErr = 0x00000500;
// Command not implemented on the firmware side.
const uint32_t kVendorRcNoSuchCommand = kVendorRcErr | 0x7f;
// Response was invalid (TPM response code was not available).
const uint32_t kVendorRcInvalidResponse = 0xffffffff;
// TpmVendorCommandProxy sends vendor commands to the TPM security chip
// by using the D-Bus connection to the trunksd daemon which communicates
// with the physical TPM through the kernel driver exposing /dev/tpm0.
class TpmVendorCommandProxy : public trunks::TrunksDBusProxy {
public:
TpmVendorCommandProxy();
TpmVendorCommandProxy(const TpmVendorCommandProxy&) = delete;
TpmVendorCommandProxy& operator=(const TpmVendorCommandProxy&) = delete;
~TpmVendorCommandProxy() override;
// Sends the VENDOR_CC_U2F_GENERATE command to cr50, and populates
// resp_out with the reply.
// Returns the TPM response code, or kVendorRcInvalidResponse if the
// response was invalid.
virtual uint32_t SendU2fGenerate(const struct u2f_generate_req& req,
u2f_generate_resp* resp_out);
virtual uint32_t SendU2fGenerate(const struct u2f_generate_req& req,
u2f_generate_versioned_resp* resp_out);
// Sends the VENDOR_CC_U2F_SIGN command to cr50, and populates
// resp_out with the reply.
// If U2F_SIGN_REQ specifies flags indicating a 'check-only' request,
// no response body will be returned from cr50, and so resp_out will
// not be populated. In this case resp_out may be set to nullptr.
// Returns the TPM response code, or kVendorRcInvalidResponse if the
// response was invalid.
virtual uint32_t SendU2fSign(const struct u2f_sign_req& req,
u2f_sign_resp* resp_out);
virtual uint32_t SendU2fSign(const struct u2f_sign_versioned_req& req,
u2f_sign_resp* resp_out);
// Sends the VENDOR_CC_U2F_ATTEST command to cr50, and populates
// resp_out with the reply.
// Returns the TPM response code, or kVendorRcInvalidResponse if the
// response was invalid.
virtual uint32_t SendU2fAttest(const struct u2f_attest_req& req,
u2f_attest_resp* resp_out);
// Retrieves the G2F certificate from vNVRAM in cr50 and writes it to
// cert_out. Note that the certificate read from vNVRAM may include
// several '0' bytes of padding at the end of the buffer. The length
// of the certificate can be determined by parsing it.
// Returns the TPM response code, or kVendorRcInvalidResponse if the
// response was invalid.
virtual uint32_t GetG2fCertificate(std::string* cert_out);
// Returns a reference to |lock_|.
virtual base::Lock& GetLock();
private:
// Sends the TPM command with vendor-specific command code |cc| and the
// payload in |input|, get the reply in |output|. Returns the TPM response
// code.
uint32_t VendorCommand(uint16_t cc,
const std::string& input,
std::string* output);
// Sends the TPM command with vendor-specific command code |cc| and the
// payload in |input|, get the reply in |output|. Returns the TPM response
// code, or kVendorRcInvalidResponse if the response code was
// TPM_RC_SUCCESS but the response was the wrong length for the specified
// output type.
template <typename Request, typename Response>
uint32_t VendorCommandStruct(uint16_t cc,
const Request& input,
Response* output);
template <typename Request>
uint32_t SendU2fSignGeneric(const Request& req, u2f_sign_resp* resp_out);
// Sends the VENDOR_CC_U2F_APDU command to the TPM with |req| as the
// ISO7816-4:2005 APDU data and writes in |resp| sent back by the TPM.
// Returns the TPM response code.
uint32_t SendU2fApdu(const std::string& req, std::string* resp_out);
// Retrieve and record in the log the individual attestation certificate.
void LogIndividualCertificate();
// A lock to ensure public SendU2fGenerate, SendU2fSign and SendU2fAttest are
// executed sequentially. Client code is responsible for acquiring the lock.
// TODO(louiscollard): Change to something more robust.
base::Lock lock_;
};
} // namespace u2f
#endif // U2FD_TPM_VENDOR_CMD_H_