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 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 58 int Startup(TrunksFactory* factory) { 59 factory->GetTpmUtility()->Shutdown(); 60 return factory->GetTpmUtility()->Startup(); 61 } 62 63 int Clear(TrunksFactory* factory) { 64 return factory->GetTpmUtility()->Clear(); 65 } 66 67 int InitializeTpm(TrunksFactory* factory) { 68 return factory->GetTpmUtility()->InitializeTpm(); 69 } 70 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 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 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 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