blob: 0e701f8ea45fa59f38d8b8e71377bfd65248aae8 [file] [log] [blame]
Vincent Palatinc6c7e4e2017-06-15 15:45:05 +02001// Copyright 2017 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef U2FD_TPM_VENDOR_CMD_H_
6#define U2FD_TPM_VENDOR_CMD_H_
7
8#include <string>
9
10#include <base/macros.h>
Louis Collard3925fc92019-02-26 18:43:22 +080011#include <trunks/cr50_headers/u2f.h>
12#include <trunks/trunks_dbus_proxy.h>
Vincent Palatinc6c7e4e2017-06-15 15:45:05 +020013
14namespace u2f {
15
16// The TPM response code is all zero for success.
17// Errors are a little complicated:
18//
19// Bits 31:12 must be zero.
20//
21// Bit 11 S=0 Error
22// Bit 10 T=1 Vendor defined response code
23// Bit 9 r=0 reserved
24// Bit 8 V=1 Conforms to TPMv2 spec
25// Bit 7 F=0 Conforms to Table 14, Format-Zero Response Codes
26// Bits 6:0 num 128 possible failure reasons
27const uint32_t kVendorRcErr = 0x00000500;
28// Command not implemented on the firmware side.
29const uint32_t kVendorRcNoSuchCommand = kVendorRcErr | 0x7f;
Louis Collard3925fc92019-02-26 18:43:22 +080030// Response was invalid (TPM response code was not available).
31const uint32_t kVendorRcInvalidResponse = 0xffffffff;
Vincent Palatinc6c7e4e2017-06-15 15:45:05 +020032
33// TpmVendorCommandProxy sends vendor commands to the TPM security chip
34// by using the D-Bus connection to the trunksd daemon which communicates
35// with the physical TPM through the kernel driver exposing /dev/tpm0.
36class TpmVendorCommandProxy : public trunks::TrunksDBusProxy {
37 public:
38 TpmVendorCommandProxy();
Qijiang Fan6bc59e12020-11-11 02:51:06 +090039 TpmVendorCommandProxy(const TpmVendorCommandProxy&) = delete;
40 TpmVendorCommandProxy& operator=(const TpmVendorCommandProxy&) = delete;
41
Vincent Palatinc6c7e4e2017-06-15 15:45:05 +020042 ~TpmVendorCommandProxy() override;
43
Louis Collard3925fc92019-02-26 18:43:22 +080044 // Sends the VENDOR_CC_U2F_GENERATE command to cr50, and populates
45 // resp_out with the reply.
46 // Returns the TPM response code, or kVendorRcInvalidResponse if the
47 // response was invalid.
Yicheng Li519a56d2020-09-17 19:16:31 +000048 virtual uint32_t SendU2fGenerate(const struct u2f_generate_req& req,
Louis Collardbe159282020-02-12 15:29:56 +080049 u2f_generate_resp* resp_out);
Yicheng Li5ca11f52020-05-14 16:49:48 -070050 virtual uint32_t SendU2fGenerate(const struct u2f_generate_req& req,
51 u2f_generate_versioned_resp* resp_out);
Louis Collard3925fc92019-02-26 18:43:22 +080052
53 // Sends the VENDOR_CC_U2F_SIGN command to cr50, and populates
54 // resp_out with the reply.
Louis Collard69429352019-03-07 10:57:09 +080055 // If U2F_SIGN_REQ specifies flags indicating a 'check-only' request,
56 // no response body will be returned from cr50, and so resp_out will
57 // not be populated. In this case resp_out may be set to nullptr.
Louis Collard3925fc92019-02-26 18:43:22 +080058 // Returns the TPM response code, or kVendorRcInvalidResponse if the
59 // response was invalid.
Louis Collardbe159282020-02-12 15:29:56 +080060 virtual uint32_t SendU2fSign(const struct u2f_sign_req& req,
61 u2f_sign_resp* resp_out);
Yicheng Li5ca11f52020-05-14 16:49:48 -070062 virtual uint32_t SendU2fSign(const struct u2f_sign_versioned_req& req,
63 u2f_sign_resp* resp_out);
Louis Collard3925fc92019-02-26 18:43:22 +080064
65 // Sends the VENDOR_CC_U2F_ATTEST command to cr50, and populates
66 // resp_out with the reply.
67 // Returns the TPM response code, or kVendorRcInvalidResponse if the
68 // response was invalid.
Louis Collardbe159282020-02-12 15:29:56 +080069 virtual uint32_t SendU2fAttest(const struct u2f_attest_req& req,
70 u2f_attest_resp* resp_out);
Louis Collard3925fc92019-02-26 18:43:22 +080071
72 // Retrieves the G2F certificate from vNVRAM in cr50 and writes it to
73 // cert_out. Note that the certificate read from vNVRAM may include
74 // several '0' bytes of padding at the end of the buffer. The length
75 // of the certificate can be determined by parsing it.
76 // Returns the TPM response code, or kVendorRcInvalidResponse if the
77 // response was invalid.
Louis Collard3857fa82019-08-30 14:56:57 +080078 virtual uint32_t GetG2fCertificate(std::string* cert_out);
Louis Collard3925fc92019-02-26 18:43:22 +080079
Yicheng Lic03ac7e2019-12-09 16:13:26 -080080 // Returns a reference to |lock_|.
81 virtual base::Lock& GetLock();
82
Vincent Palatinc6c7e4e2017-06-15 15:45:05 +020083 private:
84 // Sends the TPM command with vendor-specific command code |cc| and the
85 // payload in |input|, get the reply in |output|. Returns the TPM response
86 // code.
87 uint32_t VendorCommand(uint16_t cc,
88 const std::string& input,
89 std::string* output);
90
Louis Collard3925fc92019-02-26 18:43:22 +080091 // Sends the TPM command with vendor-specific command code |cc| and the
92 // payload in |input|, get the reply in |output|. Returns the TPM response
93 // code, or kVendorRcInvalidResponse if the response code was
94 // TPM_RC_SUCCESS but the response was the wrong length for the specified
95 // output type.
96 template <typename Request, typename Response>
97 uint32_t VendorCommandStruct(uint16_t cc,
98 const Request& input,
99 Response* output);
100
Yicheng Li5ca11f52020-05-14 16:49:48 -0700101 template <typename Request>
102 uint32_t SendU2fSignGeneric(const Request& req, u2f_sign_resp* resp_out);
103
Louis Collardac2158c2019-08-15 16:59:16 +0800104 // Sends the VENDOR_CC_U2F_APDU command to the TPM with |req| as the
105 // ISO7816-4:2005 APDU data and writes in |resp| sent back by the TPM.
106 // Returns the TPM response code.
107 uint32_t SendU2fApdu(const std::string& req, std::string* resp_out);
108
Vincent Palatin7b899562017-09-27 11:07:14 +0200109 // Retrieve and record in the log the individual attestation certificate.
110 void LogIndividualCertificate();
111
Yicheng Lic03ac7e2019-12-09 16:13:26 -0800112 // A lock to ensure public SendU2fGenerate, SendU2fSign and SendU2fAttest are
113 // executed sequentially. Client code is responsible for acquiring the lock.
114 // TODO(louiscollard): Change to something more robust.
115 base::Lock lock_;
Vincent Palatinc6c7e4e2017-06-15 15:45:05 +0200116};
117
118} // namespace u2f
119
120#endif // U2FD_TPM_VENDOR_CMD_H_