Vincent Palatin | c6c7e4e | 2017-06-15 15:45:05 +0200 | [diff] [blame] | 1 | // 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 Collard | 3925fc9 | 2019-02-26 18:43:22 +0800 | [diff] [blame] | 11 | #include <trunks/cr50_headers/u2f.h> |
| 12 | #include <trunks/trunks_dbus_proxy.h> |
Vincent Palatin | c6c7e4e | 2017-06-15 15:45:05 +0200 | [diff] [blame] | 13 | |
| 14 | namespace 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 |
| 27 | const uint32_t kVendorRcErr = 0x00000500; |
| 28 | // Command not implemented on the firmware side. |
| 29 | const uint32_t kVendorRcNoSuchCommand = kVendorRcErr | 0x7f; |
Louis Collard | 3925fc9 | 2019-02-26 18:43:22 +0800 | [diff] [blame] | 30 | // Response was invalid (TPM response code was not available). |
| 31 | const uint32_t kVendorRcInvalidResponse = 0xffffffff; |
Vincent Palatin | c6c7e4e | 2017-06-15 15:45:05 +0200 | [diff] [blame] | 32 | |
| 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. |
| 36 | class TpmVendorCommandProxy : public trunks::TrunksDBusProxy { |
| 37 | public: |
| 38 | TpmVendorCommandProxy(); |
Qijiang Fan | 6bc59e1 | 2020-11-11 02:51:06 +0900 | [diff] [blame] | 39 | TpmVendorCommandProxy(const TpmVendorCommandProxy&) = delete; |
| 40 | TpmVendorCommandProxy& operator=(const TpmVendorCommandProxy&) = delete; |
| 41 | |
Vincent Palatin | c6c7e4e | 2017-06-15 15:45:05 +0200 | [diff] [blame] | 42 | ~TpmVendorCommandProxy() override; |
| 43 | |
Louis Collard | 3925fc9 | 2019-02-26 18:43:22 +0800 | [diff] [blame] | 44 | // 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 Li | 519a56d | 2020-09-17 19:16:31 +0000 | [diff] [blame] | 48 | virtual uint32_t SendU2fGenerate(const struct u2f_generate_req& req, |
Louis Collard | be15928 | 2020-02-12 15:29:56 +0800 | [diff] [blame] | 49 | u2f_generate_resp* resp_out); |
Yicheng Li | 5ca11f5 | 2020-05-14 16:49:48 -0700 | [diff] [blame] | 50 | virtual uint32_t SendU2fGenerate(const struct u2f_generate_req& req, |
| 51 | u2f_generate_versioned_resp* resp_out); |
Louis Collard | 3925fc9 | 2019-02-26 18:43:22 +0800 | [diff] [blame] | 52 | |
| 53 | // Sends the VENDOR_CC_U2F_SIGN command to cr50, and populates |
| 54 | // resp_out with the reply. |
Louis Collard | 6942935 | 2019-03-07 10:57:09 +0800 | [diff] [blame] | 55 | // 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 Collard | 3925fc9 | 2019-02-26 18:43:22 +0800 | [diff] [blame] | 58 | // Returns the TPM response code, or kVendorRcInvalidResponse if the |
| 59 | // response was invalid. |
Louis Collard | be15928 | 2020-02-12 15:29:56 +0800 | [diff] [blame] | 60 | virtual uint32_t SendU2fSign(const struct u2f_sign_req& req, |
| 61 | u2f_sign_resp* resp_out); |
Yicheng Li | 5ca11f5 | 2020-05-14 16:49:48 -0700 | [diff] [blame] | 62 | virtual uint32_t SendU2fSign(const struct u2f_sign_versioned_req& req, |
| 63 | u2f_sign_resp* resp_out); |
Louis Collard | 3925fc9 | 2019-02-26 18:43:22 +0800 | [diff] [blame] | 64 | |
| 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 Collard | be15928 | 2020-02-12 15:29:56 +0800 | [diff] [blame] | 69 | virtual uint32_t SendU2fAttest(const struct u2f_attest_req& req, |
| 70 | u2f_attest_resp* resp_out); |
Louis Collard | 3925fc9 | 2019-02-26 18:43:22 +0800 | [diff] [blame] | 71 | |
| 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 Collard | 3857fa8 | 2019-08-30 14:56:57 +0800 | [diff] [blame] | 78 | virtual uint32_t GetG2fCertificate(std::string* cert_out); |
Louis Collard | 3925fc9 | 2019-02-26 18:43:22 +0800 | [diff] [blame] | 79 | |
Yicheng Li | c03ac7e | 2019-12-09 16:13:26 -0800 | [diff] [blame] | 80 | // Returns a reference to |lock_|. |
| 81 | virtual base::Lock& GetLock(); |
| 82 | |
Vincent Palatin | c6c7e4e | 2017-06-15 15:45:05 +0200 | [diff] [blame] | 83 | 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 Collard | 3925fc9 | 2019-02-26 18:43:22 +0800 | [diff] [blame] | 91 | // 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 Li | 5ca11f5 | 2020-05-14 16:49:48 -0700 | [diff] [blame] | 101 | template <typename Request> |
| 102 | uint32_t SendU2fSignGeneric(const Request& req, u2f_sign_resp* resp_out); |
| 103 | |
Louis Collard | ac2158c | 2019-08-15 16:59:16 +0800 | [diff] [blame] | 104 | // 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 Palatin | 7b89956 | 2017-09-27 11:07:14 +0200 | [diff] [blame] | 109 | // Retrieve and record in the log the individual attestation certificate. |
| 110 | void LogIndividualCertificate(); |
| 111 | |
Yicheng Li | c03ac7e | 2019-12-09 16:13:26 -0800 | [diff] [blame] | 112 | // 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 Palatin | c6c7e4e | 2017-06-15 15:45:05 +0200 | [diff] [blame] | 116 | }; |
| 117 | |
| 118 | } // namespace u2f |
| 119 | |
| 120 | #endif // U2FD_TPM_VENDOR_CMD_H_ |