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 <string>
22
23 #include <base/command_line.h>
24 #include <base/logging.h>
25 #include <brillo/syslog_logging.h>
26
27 #include "trunks/error_codes.h"
28 #include "trunks/hmac_session.h"
29 #include "trunks/password_authorization_delegate.h"
30 #include "trunks/policy_session.h"
31 #include "trunks/scoped_key_handle.h"
32 #include "trunks/tpm_state.h"
33 #include "trunks/tpm_utility.h"
34 #include "trunks/trunks_client_test.h"
35 #include "trunks/trunks_factory_impl.h"
36
37 namespace {
38
39 using trunks::CommandTransceiver;
40 using trunks::TrunksFactory;
41
PrintUsage()42 void PrintUsage() {
43 puts("Options:");
44 puts(" --allocate_pcr - Configures PCR 0-15 under the SHA256 bank.");
45 puts(" --clear - Clears the TPM. Use before initializing the TPM.");
46 puts(" --help - Prints this message.");
47 puts(" --init_tpm - Initializes a TPM as CrOS firmware does.");
48 puts(" --own - Takes ownership of the TPM with the provided password.");
49 puts(" --owner_password - used to provide an owner password");
50 puts(" --regression_test - Runs some basic regression tests. If");
51 puts(" owner_password is supplied, it runs tests that");
52 puts(" need owner permissions.");
53 puts(" --startup - Performs startup and self-tests.");
54 puts(" --status - Prints TPM status information.");
55 puts(" --stress_test - Runs some basic stress tests.");
56 }
57
Startup(TrunksFactory * factory)58 int Startup(TrunksFactory* factory) {
59 factory->GetTpmUtility()->Shutdown();
60 return factory->GetTpmUtility()->Startup();
61 }
62
Clear(TrunksFactory * factory)63 int Clear(TrunksFactory* factory) {
64 return factory->GetTpmUtility()->Clear();
65 }
66
InitializeTpm(TrunksFactory * factory)67 int InitializeTpm(TrunksFactory* factory) {
68 return factory->GetTpmUtility()->InitializeTpm();
69 }
70
AllocatePCR(TrunksFactory * factory)71 int AllocatePCR(TrunksFactory* factory) {
72 trunks::TPM_RC result;
73 result = factory->GetTpmUtility()->AllocatePCR("");
74 if (result != trunks::TPM_RC_SUCCESS) {
75 LOG(ERROR) << "Error allocating PCR:" << trunks::GetErrorString(result);
76 return result;
77 }
78 factory->GetTpmUtility()->Shutdown();
79 return factory->GetTpmUtility()->Startup();
80 }
81
TakeOwnership(const std::string & owner_password,TrunksFactory * factory)82 int TakeOwnership(const std::string& owner_password, TrunksFactory* factory) {
83 trunks::TPM_RC rc;
84 rc = factory->GetTpmUtility()->TakeOwnership(owner_password,
85 owner_password,
86 owner_password);
87 if (rc) {
88 LOG(ERROR) << "Error taking ownership: " << trunks::GetErrorString(rc);
89 return rc;
90 }
91 return 0;
92 }
93
DumpStatus(TrunksFactory * factory)94 int DumpStatus(TrunksFactory* factory) {
95 scoped_ptr<trunks::TpmState> state = factory->GetTpmState();
96 trunks::TPM_RC result = state->Initialize();
97 if (result != trunks::TPM_RC_SUCCESS) {
98 LOG(ERROR) << "Failed to read TPM state: "
99 << trunks::GetErrorString(result);
100 return result;
101 }
102 printf("Owner password set: %s\n",
103 state->IsOwnerPasswordSet() ? "true" : "false");
104 printf("Endorsement password set: %s\n",
105 state->IsEndorsementPasswordSet() ? "true" : "false");
106 printf("Lockout password set: %s\n",
107 state->IsLockoutPasswordSet() ? "true" : "false");
108 printf("Ownership status: %s\n",
109 state->IsOwned() ? "true" : "false");
110 printf("In lockout: %s\n",
111 state->IsInLockout() ? "true" : "false");
112 printf("Platform hierarchy enabled: %s\n",
113 state->IsPlatformHierarchyEnabled() ? "true" : "false");
114 printf("Storage hierarchy enabled: %s\n",
115 state->IsStorageHierarchyEnabled() ? "true" : "false");
116 printf("Endorsement hierarchy enabled: %s\n",
117 state->IsEndorsementHierarchyEnabled() ? "true" : "false");
118 printf("Is Tpm enabled: %s\n",
119 state->IsEnabled() ? "true" : "false");
120 printf("Was shutdown orderly: %s\n",
121 state->WasShutdownOrderly() ? "true" : "false");
122 printf("Is RSA supported: %s\n",
123 state->IsRSASupported() ? "true" : "false");
124 printf("Is ECC supported: %s\n",
125 state->IsECCSupported() ? "true" : "false");
126 printf("Lockout Counter: %u\n", state->GetLockoutCounter());
127 printf("Lockout Threshold: %u\n", state->GetLockoutThreshold());
128 printf("Lockout Interval: %u\n", state->GetLockoutInterval());
129 printf("Lockout Recovery: %u\n", state->GetLockoutRecovery());
130 return 0;
131 }
132
133 } // namespace
134
main(int argc,char ** argv)135 int main(int argc, char **argv) {
136 base::CommandLine::Init(argc, argv);
137 brillo::InitLog(brillo::kLogToStderr);
138 base::CommandLine *cl = base::CommandLine::ForCurrentProcess();
139 if (cl->HasSwitch("help")) {
140 puts("Trunks Client: A command line tool to access the TPM.");
141 PrintUsage();
142 return 0;
143 }
144
145 scoped_ptr<TrunksFactory> factory = scoped_ptr<TrunksFactory>(
146 new trunks::TrunksFactoryImpl(true /* failure_is_fatal */));
147
148 if (cl->HasSwitch("status")) {
149 return DumpStatus(factory.get());
150 }
151 if (cl->HasSwitch("startup")) {
152 return Startup(factory.get());
153 }
154 if (cl->HasSwitch("clear")) {
155 return Clear(factory.get());
156 }
157 if (cl->HasSwitch("init_tpm")) {
158 return InitializeTpm(factory.get());
159 }
160 if (cl->HasSwitch("allocate_pcr")) {
161 return AllocatePCR(factory.get());
162 }
163
164 if (cl->HasSwitch("own")) {
165 return TakeOwnership(cl->GetSwitchValueASCII("owner_password"),
166 factory.get());
167 }
168 if (cl->HasSwitch("regression_test")) {
169 trunks::TrunksClientTest test;
170 LOG(INFO) << "Running RNG test.";
171 if (!test.RNGTest()) {
172 LOG(ERROR) << "Error running RNGtest.";
173 return -1;
174 }
175 LOG(INFO) << "Running RSA key tests.";
176 if (!test.SignTest()) {
177 LOG(ERROR) << "Error running SignTest.";
178 return -1;
179 }
180 if (!test.DecryptTest()) {
181 LOG(ERROR) << "Error running DecryptTest.";
182 return -1;
183 }
184 if (!test.ImportTest()) {
185 LOG(ERROR) << "Error running ImportTest.";
186 return -1;
187 }
188 if (!test.AuthChangeTest()) {
189 LOG(ERROR) << "Error running AuthChangeTest.";
190 return -1;
191 }
192 if (!test.VerifyKeyCreationTest()) {
193 LOG(ERROR) << "Error running VerifyKeyCreationTest.";
194 return -1;
195 }
196 LOG(INFO) << "Running Sealed Data test.";
197 if (!test.SealedDataTest()) {
198 LOG(ERROR) << "Error running SealedDataTest.";
199 return -1;
200 }
201 LOG(INFO) << "Running PCR test.";
202 if (!test.PCRTest()) {
203 LOG(ERROR) << "Error running PCRTest.";
204 return -1;
205 }
206 LOG(INFO) << "Running policy tests.";
207 if (!test.PolicyAuthValueTest()) {
208 LOG(ERROR) << "Error running PolicyAuthValueTest.";
209 return -1;
210 }
211 if (!test.PolicyAndTest()) {
212 LOG(ERROR) << "Error running PolicyAndTest.";
213 return -1;
214 }
215 if (!test.PolicyOrTest()) {
216 LOG(ERROR) << "Error running PolicyOrTest.";
217 return -1;
218 }
219 if (cl->HasSwitch("owner_password")) {
220 std::string owner_password = cl->GetSwitchValueASCII("owner_password");
221 LOG(INFO) << "Running NVRAM test.";
222 if (!test.NvramTest(owner_password)) {
223 LOG(ERROR) << "Error running NvramTest.";
224 return -1;
225 }
226 }
227 LOG(INFO) << "All tests were run successfully.";
228 return 0;
229 }
230 if (cl->HasSwitch("stress_test")) {
231 LOG(INFO) << "Running stress tests.";
232 trunks::TrunksClientTest test;
233 if (!test.ManyKeysTest()) {
234 LOG(ERROR) << "Error running ManyKeysTest.";
235 return -1;
236 }
237 if (!test.ManySessionsTest()) {
238 LOG(ERROR) << "Error running ManySessionsTest.";
239 return -1;
240 }
241 return 0;
242 }
243 puts("Invalid options!");
244 PrintUsage();
245 return -1;
246 }
247