Home | History | Annotate | Download | only in trunks
      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