1 //
2 // Copyright (C) 2014 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 // trunks_client is a command line tool that supports various TPM operations. It
18 // does not provide direct access to the trunksd D-Bus interface.
19
20 #include <stdio.h>
21 #include <memory>
22 #include <string>
23
24 #include <base/command_line.h>
25 #include <base/logging.h>
26 #include <base/strings/string_number_conversions.h>
27 #include <brillo/syslog_logging.h>
28
29 #include "trunks/error_codes.h"
30 #include "trunks/hmac_session.h"
31 #include "trunks/password_authorization_delegate.h"
32 #include "trunks/policy_session.h"
33 #include "trunks/scoped_key_handle.h"
34 #include "trunks/tpm_state.h"
35 #include "trunks/tpm_utility.h"
36 #include "trunks/trunks_client_test.h"
37 #include "trunks/trunks_factory_impl.h"
38
39 namespace {
40
41 using trunks::CommandTransceiver;
42 using trunks::TrunksFactory;
43 using trunks::TrunksFactoryImpl;
44
PrintUsage()45 void PrintUsage() {
46 puts("Options:");
47 puts(" --allocate_pcr - Configures PCR 0-15 under the SHA256 bank.");
48 puts(" --clear - Clears the TPM. Use before initializing the TPM.");
49 puts(" --help - Prints this message.");
50 puts(" --init_tpm - Initializes a TPM as CrOS firmware does.");
51 puts(" --own - Takes ownership of the TPM with the provided password.");
52 puts(" --owner_password - used to provide an owner password");
53 puts(" --regression_test - Runs some basic regression tests. If");
54 puts(" owner_password is supplied, it runs tests that");
55 puts(" need owner permissions.");
56 puts(" --startup - Performs startup and self-tests.");
57 puts(" --status - Prints TPM status information.");
58 puts(" --stress_test - Runs some basic stress tests.");
59 puts(" --read_pcr --index=<N> - Reads a PCR and prints the value.");
60 puts(" --extend_pcr --index=<N> --value=<value> - Extends a PCR.");
61 }
62
HexEncode(const std::string & bytes)63 std::string HexEncode(const std::string& bytes) {
64 return base::HexEncode(bytes.data(), bytes.size());
65 }
66
Startup(const TrunksFactory & factory)67 int Startup(const TrunksFactory& factory) {
68 factory.GetTpmUtility()->Shutdown();
69 return factory.GetTpmUtility()->Startup();
70 }
71
Clear(const TrunksFactory & factory)72 int Clear(const TrunksFactory& factory) {
73 return factory.GetTpmUtility()->Clear();
74 }
75
InitializeTpm(const TrunksFactory & factory)76 int InitializeTpm(const TrunksFactory& factory) {
77 return factory.GetTpmUtility()->InitializeTpm();
78 }
79
AllocatePCR(const TrunksFactory & factory)80 int AllocatePCR(const TrunksFactory& factory) {
81 trunks::TPM_RC result;
82 result = factory.GetTpmUtility()->AllocatePCR("");
83 if (result != trunks::TPM_RC_SUCCESS) {
84 LOG(ERROR) << "Error allocating PCR:" << trunks::GetErrorString(result);
85 return result;
86 }
87 factory.GetTpmUtility()->Shutdown();
88 return factory.GetTpmUtility()->Startup();
89 }
90
TakeOwnership(const std::string & owner_password,const TrunksFactory & factory)91 int TakeOwnership(const std::string& owner_password,
92 const TrunksFactory& factory) {
93 trunks::TPM_RC rc;
94 rc = factory.GetTpmUtility()->TakeOwnership(owner_password, owner_password,
95 owner_password);
96 if (rc) {
97 LOG(ERROR) << "Error taking ownership: " << trunks::GetErrorString(rc);
98 return rc;
99 }
100 return 0;
101 }
102
DumpStatus(const TrunksFactory & factory)103 int DumpStatus(const TrunksFactory& factory) {
104 std::unique_ptr<trunks::TpmState> state = factory.GetTpmState();
105 trunks::TPM_RC result = state->Initialize();
106 if (result != trunks::TPM_RC_SUCCESS) {
107 LOG(ERROR) << "Failed to read TPM state: "
108 << trunks::GetErrorString(result);
109 return result;
110 }
111 printf("Owner password set: %s\n",
112 state->IsOwnerPasswordSet() ? "true" : "false");
113 printf("Endorsement password set: %s\n",
114 state->IsEndorsementPasswordSet() ? "true" : "false");
115 printf("Lockout password set: %s\n",
116 state->IsLockoutPasswordSet() ? "true" : "false");
117 printf("Ownership status: %s\n", state->IsOwned() ? "true" : "false");
118 printf("In lockout: %s\n", state->IsInLockout() ? "true" : "false");
119 printf("Platform hierarchy enabled: %s\n",
120 state->IsPlatformHierarchyEnabled() ? "true" : "false");
121 printf("Storage hierarchy enabled: %s\n",
122 state->IsStorageHierarchyEnabled() ? "true" : "false");
123 printf("Endorsement hierarchy enabled: %s\n",
124 state->IsEndorsementHierarchyEnabled() ? "true" : "false");
125 printf("Is Tpm enabled: %s\n", state->IsEnabled() ? "true" : "false");
126 printf("Was shutdown orderly: %s\n",
127 state->WasShutdownOrderly() ? "true" : "false");
128 printf("Is RSA supported: %s\n", state->IsRSASupported() ? "true" : "false");
129 printf("Is ECC supported: %s\n", state->IsECCSupported() ? "true" : "false");
130 printf("Lockout Counter: %u\n", state->GetLockoutCounter());
131 printf("Lockout Threshold: %u\n", state->GetLockoutThreshold());
132 printf("Lockout Interval: %u\n", state->GetLockoutInterval());
133 printf("Lockout Recovery: %u\n", state->GetLockoutRecovery());
134 return 0;
135 }
136
ReadPCR(const TrunksFactory & factory,int index)137 int ReadPCR(const TrunksFactory& factory, int index) {
138 std::unique_ptr<trunks::TpmUtility> tpm_utility = factory.GetTpmUtility();
139 std::string value;
140 trunks::TPM_RC result = tpm_utility->ReadPCR(index, &value);
141 if (result) {
142 LOG(ERROR) << "ReadPCR: " << trunks::GetErrorString(result);
143 return result;
144 }
145 printf("PCR Value: %s\n", HexEncode(value).c_str());
146 return 0;
147 }
148
ExtendPCR(const TrunksFactory & factory,int index,const std::string & value)149 int ExtendPCR(const TrunksFactory& factory,
150 int index,
151 const std::string& value) {
152 std::unique_ptr<trunks::TpmUtility> tpm_utility = factory.GetTpmUtility();
153 trunks::TPM_RC result = tpm_utility->ExtendPCR(index, value, nullptr);
154 if (result) {
155 LOG(ERROR) << "ExtendPCR: " << trunks::GetErrorString(result);
156 return result;
157 }
158 return 0;
159 }
160
161 } // namespace
162
main(int argc,char ** argv)163 int main(int argc, char** argv) {
164 base::CommandLine::Init(argc, argv);
165 brillo::InitLog(brillo::kLogToStderr);
166 base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
167 if (cl->HasSwitch("help")) {
168 puts("Trunks Client: A command line tool to access the TPM.");
169 PrintUsage();
170 return 0;
171 }
172
173 TrunksFactoryImpl factory;
174 CHECK(factory.Initialize()) << "Failed to initialize trunks factory.";
175
176 if (cl->HasSwitch("status")) {
177 return DumpStatus(factory);
178 }
179 if (cl->HasSwitch("startup")) {
180 return Startup(factory);
181 }
182 if (cl->HasSwitch("clear")) {
183 return Clear(factory);
184 }
185 if (cl->HasSwitch("init_tpm")) {
186 return InitializeTpm(factory);
187 }
188 if (cl->HasSwitch("allocate_pcr")) {
189 return AllocatePCR(factory);
190 }
191
192 if (cl->HasSwitch("own")) {
193 return TakeOwnership(cl->GetSwitchValueASCII("owner_password"), factory);
194 }
195 if (cl->HasSwitch("regression_test")) {
196 trunks::TrunksClientTest test(factory);
197 LOG(INFO) << "Running RNG test.";
198 if (!test.RNGTest()) {
199 LOG(ERROR) << "Error running RNGtest.";
200 return -1;
201 }
202 LOG(INFO) << "Running RSA key tests.";
203 if (!test.SignTest()) {
204 LOG(ERROR) << "Error running SignTest.";
205 return -1;
206 }
207 if (!test.DecryptTest()) {
208 LOG(ERROR) << "Error running DecryptTest.";
209 return -1;
210 }
211 if (!test.ImportTest()) {
212 LOG(ERROR) << "Error running ImportTest.";
213 return -1;
214 }
215 if (!test.AuthChangeTest()) {
216 LOG(ERROR) << "Error running AuthChangeTest.";
217 return -1;
218 }
219 if (!test.VerifyKeyCreationTest()) {
220 LOG(ERROR) << "Error running VerifyKeyCreationTest.";
221 return -1;
222 }
223 LOG(INFO) << "Running Sealed Data test.";
224 if (!test.SealedDataTest()) {
225 LOG(ERROR) << "Error running SealedDataTest.";
226 return -1;
227 }
228 LOG(INFO) << "Running PCR test.";
229 if (!test.PCRTest()) {
230 LOG(ERROR) << "Error running PCRTest.";
231 return -1;
232 }
233 LOG(INFO) << "Running policy tests.";
234 if (!test.PolicyAuthValueTest()) {
235 LOG(ERROR) << "Error running PolicyAuthValueTest.";
236 return -1;
237 }
238 if (!test.PolicyAndTest()) {
239 LOG(ERROR) << "Error running PolicyAndTest.";
240 return -1;
241 }
242 if (!test.PolicyOrTest()) {
243 LOG(ERROR) << "Error running PolicyOrTest.";
244 return -1;
245 }
246 if (cl->HasSwitch("owner_password")) {
247 std::string owner_password = cl->GetSwitchValueASCII("owner_password");
248 LOG(INFO) << "Running NVRAM test.";
249 if (!test.NvramTest(owner_password)) {
250 LOG(ERROR) << "Error running NvramTest.";
251 return -1;
252 }
253 }
254 LOG(INFO) << "All tests were run successfully.";
255 return 0;
256 }
257 if (cl->HasSwitch("stress_test")) {
258 LOG(INFO) << "Running stress tests.";
259 trunks::TrunksClientTest test(factory);
260 if (!test.ManyKeysTest()) {
261 LOG(ERROR) << "Error running ManyKeysTest.";
262 return -1;
263 }
264 if (!test.ManySessionsTest()) {
265 LOG(ERROR) << "Error running ManySessionsTest.";
266 return -1;
267 }
268 return 0;
269 }
270 if (cl->HasSwitch("read_pcr") && cl->HasSwitch("index")) {
271 return ReadPCR(factory, atoi(cl->GetSwitchValueASCII("index").c_str()));
272 }
273 if (cl->HasSwitch("extend_pcr") && cl->HasSwitch("index") &&
274 cl->HasSwitch("value")) {
275 return ExtendPCR(factory, atoi(cl->GetSwitchValueASCII("index").c_str()),
276 cl->GetSwitchValueASCII("value"));
277 }
278 puts("Invalid options!");
279 PrintUsage();
280 return -1;
281 }
282