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 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 63 std::string HexEncode(const std::string& bytes) { 64 return base::HexEncode(bytes.data(), bytes.size()); 65 } 66 67 int Startup(const TrunksFactory& factory) { 68 factory.GetTpmUtility()->Shutdown(); 69 return factory.GetTpmUtility()->Startup(); 70 } 71 72 int Clear(const TrunksFactory& factory) { 73 return factory.GetTpmUtility()->Clear(); 74 } 75 76 int InitializeTpm(const TrunksFactory& factory) { 77 return factory.GetTpmUtility()->InitializeTpm(); 78 } 79 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 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 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 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 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 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