Home | History | Annotate | Download | only in server
      1 //
      2 // Copyright (C) 2015 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 #include "tpm_manager/server/tpm_initializer_impl.h"
     18 
     19 #include <string>
     20 
     21 #include <base/logging.h>
     22 #include <base/stl_util.h>
     23 #include <trousers/scoped_tss_type.h>
     24 
     25 #include "tpm_manager/server/local_data_store.h"
     26 #include "tpm_manager/server/tpm_connection.h"
     27 #include "tpm_manager/common/tpm_manager_constants.h"
     28 #include "tpm_manager/server/tpm_status.h"
     29 #include "tpm_manager/server/tpm_util.h"
     30 
     31 namespace {
     32 
     33 // Don't use directly, use GetDefaultOwnerPassword().
     34 const char kDefaultOwnerPassword[] = TSS_WELL_KNOWN_SECRET;
     35 const size_t kDefaultPasswordSize = 20;
     36 const int kMaxOwnershipTimeoutRetries = 5;
     37 const char* kWellKnownSrkSecret = "well_known_srk_secret";
     38 
     39 std::string GetDefaultOwnerPassword() {
     40   return std::string(kDefaultOwnerPassword, kDefaultPasswordSize);
     41 }
     42 
     43 }  // namespace
     44 
     45 namespace tpm_manager {
     46 
     47 TpmInitializerImpl::TpmInitializerImpl(LocalDataStore* local_data_store,
     48                                        TpmStatus* tpm_status)
     49     : local_data_store_(local_data_store), tpm_status_(tpm_status) {}
     50 
     51 bool TpmInitializerImpl::InitializeTpm() {
     52   if (tpm_status_->IsTpmOwned() && !TestTpmAuth(GetDefaultOwnerPassword())) {
     53     // Tpm is already owned, so we do not need to do anything.
     54     VLOG(1) << "Tpm already owned.";
     55     return true;
     56   }
     57   TpmConnection connection(GetDefaultOwnerPassword());
     58   if (!InitializeEndorsementKey(&connection) || !TakeOwnership(&connection) ||
     59       !InitializeSrk(&connection)) {
     60     return false;
     61   }
     62   std::string owner_password;
     63   if (!openssl_util_.GetRandomBytes(kDefaultPasswordSize, &owner_password)) {
     64     return false;
     65   }
     66   LocalData local_data;
     67   local_data.clear_owner_dependency();
     68   for (auto value : kInitialTpmOwnerDependencies) {
     69     local_data.add_owner_dependency(value);
     70   }
     71   local_data.set_owner_password(owner_password);
     72   if (!local_data_store_->Write(local_data)) {
     73     LOG(ERROR) << "Error saving local data.";
     74     return false;
     75   }
     76   if (!ChangeOwnerPassword(&connection, owner_password)) {
     77     return false;
     78   }
     79   return true;
     80 }
     81 
     82 void TpmInitializerImpl::VerifiedBootHelper() {
     83   // Nothing to do.
     84 }
     85 
     86 bool TpmInitializerImpl::ResetDictionaryAttackLock() {
     87   LOG(WARNING) << __func__ << ": Not implemented.";
     88   return false;
     89 }
     90 
     91 bool TpmInitializerImpl::InitializeEndorsementKey(TpmConnection* connection) {
     92   trousers::ScopedTssKey local_key_handle(connection->GetContext());
     93   TSS_RESULT result = Tspi_TPM_GetPubEndorsementKey(
     94       connection->GetTpm(), false, nullptr, local_key_handle.ptr());
     95   if (TPM_ERROR(result) == TPM_SUCCESS) {
     96     // In this case the EK already exists, so we can return true here.
     97     VLOG(1) << "EK already exists.";
     98     return true;
     99   }
    100   // At this point the EK does not exist, so we create it.
    101   TSS_FLAG init_flags = TSS_KEY_TYPE_LEGACY | TSS_KEY_SIZE_2048;
    102   if (TPM_ERROR(result = Tspi_Context_CreateObject(
    103                     connection->GetContext(), TSS_OBJECT_TYPE_RSAKEY,
    104                     init_flags, local_key_handle.ptr()))) {
    105     TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
    106     return false;
    107   }
    108   if (TPM_ERROR(result = Tspi_TPM_CreateEndorsementKey(
    109                     connection->GetTpm(), local_key_handle, NULL))) {
    110     TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_CreateEndorsementKey";
    111     return false;
    112   }
    113   return true;
    114 }
    115 
    116 bool TpmInitializerImpl::TakeOwnership(TpmConnection* connection) {
    117   if (TestTpmAuth(GetDefaultOwnerPassword())) {
    118     VLOG(1) << "The Tpm already has the default owner password.";
    119     return true;
    120   }
    121   TSS_RESULT result;
    122   trousers::ScopedTssKey srk_handle(connection->GetContext());
    123   TSS_FLAG init_flags = TSS_KEY_TSP_SRK | TSS_KEY_AUTHORIZATION;
    124   if (TPM_ERROR(result = Tspi_Context_CreateObject(
    125                     connection->GetContext(), TSS_OBJECT_TYPE_RSAKEY,
    126                     init_flags, srk_handle.ptr()))) {
    127     TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
    128     return false;
    129   }
    130   TSS_HPOLICY srk_usage_policy;
    131   if (TPM_ERROR(result = Tspi_GetPolicyObject(srk_handle, TSS_POLICY_USAGE,
    132                                               &srk_usage_policy))) {
    133     TPM_LOG(ERROR, result) << "Error calling Tspi_GetPolicyObject";
    134     return false;
    135   }
    136   if (TPM_ERROR(result = Tspi_Policy_SetSecret(
    137                     srk_usage_policy, TSS_SECRET_MODE_PLAIN,
    138                     strlen(kWellKnownSrkSecret),
    139                     const_cast<BYTE*>(
    140                         reinterpret_cast<const BYTE*>(kWellKnownSrkSecret))))) {
    141     TPM_LOG(ERROR, result) << "Error calling Tspi_Policy_SetSecret";
    142     return false;
    143   }
    144   // Tspi_TPM_TakeOwnership can potentially take a long time to complete,
    145   // so we retry if there is a timeout in any layer. I chose 5, because the
    146   // longest TakeOwnership call that I have seen took ~2min, and the default
    147   // TSS timeout is 30s. This means that after 5 calls, it is quite likely that
    148   // this call will succeed.
    149   int retry_count = 0;
    150   do {
    151     result = Tspi_TPM_TakeOwnership(connection->GetTpm(), srk_handle, 0);
    152     retry_count++;
    153   } while (((result == TDDL_E_TIMEOUT) ||
    154             (result == (TSS_LAYER_TDDL | TDDL_E_TIMEOUT)) ||
    155             (result == (TSS_LAYER_TDDL | TDDL_E_IOERROR))) &&
    156            (retry_count < kMaxOwnershipTimeoutRetries));
    157   if (result) {
    158     TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_TakeOwnership, attempts: "
    159                            << retry_count;
    160     return false;
    161   }
    162   return true;
    163 }
    164 
    165 bool TpmInitializerImpl::InitializeSrk(TpmConnection* connection) {
    166   TSS_RESULT result;
    167   trousers::ScopedTssKey srk_handle(connection->GetContext());
    168   TSS_UUID SRK_UUID = TSS_UUID_SRK;
    169   if (TPM_ERROR(result = Tspi_Context_LoadKeyByUUID(
    170                     connection->GetContext(), TSS_PS_TYPE_SYSTEM, SRK_UUID,
    171                     srk_handle.ptr()))) {
    172     TPM_LOG(ERROR, result) << "Error calling Tspi_Context_LoadKeyByUUID";
    173     return false;
    174   }
    175 
    176   trousers::ScopedTssPolicy policy_handle(connection->GetContext());
    177   if (TPM_ERROR(result = Tspi_Context_CreateObject(
    178                     connection->GetContext(), TSS_OBJECT_TYPE_POLICY,
    179                     TSS_POLICY_USAGE, policy_handle.ptr()))) {
    180     TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
    181     return false;
    182   }
    183   BYTE new_password[0];
    184   if (TPM_ERROR(result = Tspi_Policy_SetSecret(
    185                     policy_handle, TSS_SECRET_MODE_PLAIN, 0, new_password))) {
    186     TPM_LOG(ERROR, result) << "Error calling Tspi_Policy_SetSecret";
    187     return false;
    188   }
    189 
    190   if (TPM_ERROR(result = Tspi_ChangeAuth(srk_handle, connection->GetTpm(),
    191                                          policy_handle))) {
    192     TPM_LOG(ERROR, result) << "Error calling Tspi_ChangeAuth";
    193     return false;
    194   }
    195   TSS_BOOL is_srk_restricted = false;
    196   if (TPM_ERROR(result = Tspi_TPM_GetStatus(connection->GetTpm(),
    197                                             TSS_TPMSTATUS_DISABLEPUBSRKREAD,
    198                                             &is_srk_restricted))) {
    199     TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetStatus";
    200     return false;
    201   }
    202   // If the SRK is restricted, we unrestrict it.
    203   if (is_srk_restricted) {
    204     if (TPM_ERROR(result = Tspi_TPM_SetStatus(connection->GetTpm(),
    205                                               TSS_TPMSTATUS_DISABLEPUBSRKREAD,
    206                                               false))) {
    207       TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_SetStatus";
    208       return false;
    209     }
    210   }
    211   return true;
    212 }
    213 
    214 bool TpmInitializerImpl::ChangeOwnerPassword(
    215     TpmConnection* connection,
    216     const std::string& owner_password) {
    217   TSS_RESULT result;
    218   trousers::ScopedTssPolicy policy_handle(connection->GetContext());
    219   if (TPM_ERROR(result = Tspi_Context_CreateObject(
    220                     connection->GetContext(), TSS_OBJECT_TYPE_POLICY,
    221                     TSS_POLICY_USAGE, policy_handle.ptr()))) {
    222     TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
    223     return false;
    224   }
    225   std::string mutable_owner_password(owner_password);
    226   if (TPM_ERROR(result = Tspi_Policy_SetSecret(
    227                     policy_handle, TSS_SECRET_MODE_PLAIN, owner_password.size(),
    228                     reinterpret_cast<BYTE*>(
    229                         string_as_array(&mutable_owner_password))))) {
    230     TPM_LOG(ERROR, result) << "Error calling Tspi_Policy_SetSecret";
    231     return false;
    232   }
    233 
    234   if (TPM_ERROR(result =
    235                     Tspi_ChangeAuth(connection->GetTpm(), 0, policy_handle))) {
    236     TPM_LOG(ERROR, result) << "Error calling Tspi_ChangeAuth";
    237     return false;
    238   }
    239 
    240   return true;
    241 }
    242 
    243 bool TpmInitializerImpl::TestTpmAuth(const std::string& owner_password) {
    244   TpmConnection connection(owner_password);
    245   TSS_HTPM tpm_handle = connection.GetTpm();
    246   if (tpm_handle == 0) {
    247     return false;
    248   }
    249   // Call Tspi_TPM_GetStatus to test the |owner_password| provided.
    250   TSS_RESULT result;
    251   TSS_BOOL current_status = false;
    252   if (TPM_ERROR(result = Tspi_TPM_GetStatus(tpm_handle, TSS_TPMSTATUS_DISABLED,
    253                                             &current_status))) {
    254     return false;
    255   }
    256   return true;
    257 }
    258 
    259 }  // namespace tpm_manager
    260