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 <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