blob: c712546432c8e1ef2d83f166058bb97ad77382c4 [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_U2FHID_H_
6#define U2FD_U2FHID_H_
7
8#include <memory>
9#include <string>
10#include <vector>
11
12#include <base/timer/timer.h>
13#include <brillo/errors/error.h>
Louis Collard255ca582019-05-24 12:54:33 +080014#include <metrics/metrics_library.h>
Louis Collard10ac9e92019-02-23 18:34:45 +080015#include <trunks/cr50_headers/u2f.h>
Vincent Palatinc6c7e4e2017-06-15 15:45:05 +020016
17#include "u2fd/hid_interface.h"
Louis Collard10ac9e92019-02-23 18:34:45 +080018#include "u2fd/u2f_adpu.h"
Louis Collardf59aa942019-02-25 17:50:14 +080019#include "u2fd/user_state.h"
Vincent Palatinc6c7e4e2017-06-15 15:45:05 +020020
21namespace u2f {
22
Andrey Pronin34c6faf2018-08-14 14:37:26 -070023constexpr uint32_t kDefaultVendorId = 0x18d1;
24constexpr uint32_t kDefaultProductId = 0x502c;
25
26// Mandatory length of the U2F HID report.
27constexpr size_t kU2fReportSize = 64;
28
29// HID frame CMD/SEQ byte definitions.
30constexpr uint8_t kFrameTypeMask = 0x80;
31constexpr uint8_t kFrameTypeInit = 0x80;
32// when bit 7 is not set, the frame type is CONTinuation.
33
34// INIT command parameters
35constexpr uint32_t kCidBroadcast = -1U;
36constexpr size_t kInitNonceSize = 8;
37
38constexpr uint8_t kCapFlagWink = 0x01;
39constexpr uint8_t kCapFlagLock = 0x02;
40
41constexpr size_t kMaxPayloadSize = (64 - 7 + 128 * (64 - 5)); // 7609 bytes
42
Vincent Palatinc6c7e4e2017-06-15 15:45:05 +020043// U2fHid emulates U2FHID protocol on top of the TPM U2F implementation.
44// The object reads the HID report sent by the HIDInterface passed to the
45// constructor, parses it and extracts the U2FHID command. If this is a U2F
46// message, finally sends the raw U2F APDU to the |transmit_func| callback
47// passed to the constructor. It returns the final result (response APDU or
48// error code) inside an HID report through the HIDInterface.
49class U2fHid {
50 public:
Andrey Pronin34c6faf2018-08-14 14:37:26 -070051 // U2FHID Command codes
52 enum class U2fHidCommand : uint8_t {
53 kPing = 1,
54 kMsg = 3,
55 kLock = 4,
56 kVendorSysInfo = 5,
57 kInit = 6,
58 kWink = 8,
59 kError = 0x3f,
60 };
61
62 // U2FHID error codes
63 enum class U2fHidError : uint8_t {
64 kNone = 0,
65 kInvalidCmd = 1,
66 kInvalidPar = 2,
67 kInvalidLen = 3,
68 kInvalidSeq = 4,
69 kMsgTimeout = 5,
70 kChannelBusy = 6,
71 kLockRequired = 10,
72 kInvalidCid = 11,
73 kOther = 127,
74 };
75
Vincent Palatinc6c7e4e2017-06-15 15:45:05 +020076 // Callback to send the raw U2F APDU in |req| and get the corresponding
77 // response APDU in |resp|.
Louis Collard10ac9e92019-02-23 18:34:45 +080078 using TpmAdpuCallback =
Louis Collard3925fc92019-02-26 18:43:22 +080079 base::Callback<uint32_t(const std::string& req, std::string* resp)>;
Louis Collard10ac9e92019-02-23 18:34:45 +080080 // Callback to run the VENDOR_CC_U2F_GENERATE command.
81 using TpmGenerateCallback = base::Callback<uint32_t(
82 const U2F_GENERATE_REQ& req, U2F_GENERATE_RESP* resp)>;
83 // Callback to run the VENDOR_CC_U2F_SIGN command.
84 using TpmSignCallback =
85 base::Callback<uint32_t(const U2F_SIGN_REQ& req, U2F_SIGN_RESP* resp)>;
86 // Callback to run the VENDOR_CC_U2F_ATTEST command.
87 using TpmAttestCallback = base::Callback<uint32_t(const U2F_ATTEST_REQ& req,
88 U2F_ATTEST_RESP* resp)>;
89 // Callback to retrieve the G2F certificate.
90 using TpmG2fCertCallback = base::Callback<uint32_t(std::string* cert_out)>;
Vincent Palatinc6c7e4e2017-06-15 15:45:05 +020091 // Callback to disable the power button for |in_timeout_internal| when using
92 // it as physical presence for U2F.
93 using IgnoreButtonCallback = base::Callback<bool(
94 int64_t in_timeout_internal, brillo::ErrorPtr* error, int timeout)>;
Louis Collardbdb261f2019-03-25 20:30:10 +080095 // Callback to notify the UI that the wink command has been sent.
96 using WinkCallback = base::Callback<void()>;
Vincent Palatinc6c7e4e2017-06-15 15:45:05 +020097
Louis Collard10ac9e92019-02-23 18:34:45 +080098 // TODO(louiscollard): Pass TpmVendorCommandProxy rather than individual
99 // callbacks.
Vincent Palatinc6c7e4e2017-06-15 15:45:05 +0200100 U2fHid(std::unique_ptr<HidInterface> hid,
Louis Collard10ac9e92019-02-23 18:34:45 +0800101 const bool g2f_mode,
Louis Collard243acd62019-04-25 15:42:57 +0800102 const bool legacy_kh_fallback,
Louis Collard10ac9e92019-02-23 18:34:45 +0800103 const TpmGenerateCallback& generate_fn,
104 const TpmSignCallback& sign_fn,
105 const TpmAttestCallback& attest_fn,
106 const TpmG2fCertCallback& g2f_cert_fn,
Louis Collardf59aa942019-02-25 17:50:14 +0800107 const IgnoreButtonCallback& ignore_button_func,
Louis Collardbdb261f2019-03-25 20:30:10 +0800108 const WinkCallback& wink_fn,
Louis Collardf59aa942019-02-25 17:50:14 +0800109 std::unique_ptr<UserState> user_state);
Vincent Palatinc6c7e4e2017-06-15 15:45:05 +0200110 ~U2fHid();
111 bool Init();
112
Vincent Palatinc6c7e4e2017-06-15 15:45:05 +0200113 private:
Vincent Palatinc6c7e4e2017-06-15 15:45:05 +0200114 // U2FHID protocol commands implementation.
115 void CmdInit(uint32_t cid, const std::string& payload);
116 int CmdLock(std::string* resp);
117 int CmdMsg(std::string* resp);
118 int CmdPing(std::string* resp);
Vincent Palatin828bfe92018-04-05 15:14:44 +0200119 int CmdSysInfo(std::string* resp);
Vincent Palatinc6c7e4e2017-06-15 15:45:05 +0200120 int CmdWink(std::string* resp);
121
122 // Fully resets the state of the possibly on-going U2FHID transaction.
123 void ClearTransaction();
124
125 // Sends back a U2FHID report with just the |errcode| error code inside
126 // on channel |cid|.
127 // If |clear| is set, clear the transaction state at the same time.
128 void ReturnError(U2fHidError errcode, uint32_t cid, bool clear);
129
130 // Called when we reach the deadline for the on-going transaction.
131 void TransactionTimeout();
132
133 // Called when we reach the deadline for an unreleased channel lock.
134 void LockTimeout();
135
136 // Sends back a U2FHID report indicating success and carrying the response
137 // payload |resp|.
138 void ReturnResponse(const std::string& resp);
139
Louis Collard10ac9e92019-02-23 18:34:45 +0800140 // Sends back a U2FHID report indicating failure and carrying a response
141 // code.
142 void ReturnFailureResponse(uint16_t sw);
143
144 // Ignores power button presses for 10 seconds.
145 void IgnorePowerButton();
146
Vincent Palatinc6c7e4e2017-06-15 15:45:05 +0200147 // Executes the action requested by the command contained in the current
148 // transaction.
149 void ExecuteCmd();
150
151 // Parses the HID report contained in |report| and append the content to the
152 // current U2FHID transaction or create a new one.
153 void ProcessReport(const std::string& report);
154
Louis Collard10ac9e92019-02-23 18:34:45 +0800155 // U2F message handler implementations.
156 //////
157
Louis Collard10ac9e92019-02-23 18:34:45 +0800158 // Processes the ADPU and builds a response locally, making using of cr50
159 // vendor commands where necessary.
160 int ProcessMsg(std::string* resp);
161
162 // Process a U2F_REGISTER ADPU.
163 int ProcessU2fRegister(U2fRegisterRequestAdpu request, std::string* resp);
164 // Process a U2F_AUTHENTICATE ADPU.
165 int ProcessU2fAuthenticate(U2fAuthenticateRequestAdpu request,
166 std::string* resp);
167
168 // Wrapper functions for cr50 U2F vendor commands.
169 //////
170
171 // Run a U2F_GENERATE command to create a new key handle.
172 int DoU2fGenerate(const std::vector<uint8_t>& app_id,
173 std::vector<uint8_t>* pub_key,
174 std::vector<uint8_t>* key_handle);
175 // Run a U2F_SIGN command to sign a hash using an existing key handle.
176 int DoU2fSign(const std::vector<uint8_t>& app_id,
177 const std::vector<uint8_t>& key_handle,
178 const std::vector<uint8_t>& hash,
179 std::vector<uint8_t>* signature);
Louis Collard69429352019-03-07 10:57:09 +0800180 // Run a U2F_SIGN command to check if a key handle is valid.
181 int DoU2fSignCheckOnly(const std::vector<uint8_t>& app_id,
182 const std::vector<uint8_t>& key_handle);
Louis Collard10ac9e92019-02-23 18:34:45 +0800183 // Run a U2F_ATTEST command to sign data using the cr50 individual attestation
184 // certificate.
185 int DoG2fAttest(const std::vector<uint8_t>& data,
186 uint8_t format,
187 std::vector<uint8_t>* sig_out);
188 // Returns the cr50 individual attestation certificate.
189 const std::vector<uint8_t>& GetG2fCert();
190
Louis Collard10ac9e92019-02-23 18:34:45 +0800191
Vincent Palatinc6c7e4e2017-06-15 15:45:05 +0200192 std::unique_ptr<HidInterface> hid_;
Louis Collard10ac9e92019-02-23 18:34:45 +0800193 const bool g2f_mode_;
Louis Collard243acd62019-04-25 15:42:57 +0800194 const bool legacy_kh_fallback_;
Louis Collard10ac9e92019-02-23 18:34:45 +0800195 TpmGenerateCallback tpm_generate_;
196 TpmSignCallback tpm_sign_;
197 TpmAttestCallback tpm_attest_;
198 TpmG2fCertCallback tpm_g2f_cert_;
Vincent Palatinc6c7e4e2017-06-15 15:45:05 +0200199 IgnoreButtonCallback ignore_button_;
Louis Collardbdb261f2019-03-25 20:30:10 +0800200 WinkCallback wink_;
Vincent Palatinc6c7e4e2017-06-15 15:45:05 +0200201 uint32_t free_cid_;
202 uint32_t locked_cid_;
203 base::OneShotTimer lock_timeout_;
Louis Collardf59aa942019-02-25 17:50:14 +0800204 std::unique_ptr<UserState> user_state_;
Louis Collard255ca582019-05-24 12:54:33 +0800205 MetricsLibrary metrics_;
Vincent Palatinc6c7e4e2017-06-15 15:45:05 +0200206
Vincent Palatinc6c7e4e2017-06-15 15:45:05 +0200207 class HidPacket;
208 class HidMessage;
209 struct Transaction;
210
211 std::unique_ptr<Transaction> transaction_;
212
213 DISALLOW_COPY_AND_ASSIGN(U2fHid);
214};
215
216} // namespace u2f
217
218#endif // U2FD_U2FHID_H_