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/tpm2_nvram_impl.h"
     18 
     19 #include <memory>
     20 #include <string>
     21 
     22 #include <base/logging.h>
     23 #include <trunks/error_codes.h>
     24 #include <trunks/tpm_constants.h>
     25 #include <trunks/tpm_utility.h>
     26 #include <trunks/trunks_factory_impl.h>
     27 
     28 namespace tpm_manager {
     29 
     30 using trunks::GetErrorString;
     31 using trunks::TPM_RC;
     32 using trunks::TPM_RC_SUCCESS;
     33 
     34 Tpm2NvramImpl::Tpm2NvramImpl(LocalDataStore* local_data_store)
     35     : trunks_factory_(new trunks::TrunksFactoryImpl()),
     36       local_data_store_(local_data_store),
     37       initialized_(false),
     38       trunks_session_(trunks_factory_->GetHmacSession()),
     39       trunks_utility_(trunks_factory_->GetTpmUtility()) {}
     40 
     41 Tpm2NvramImpl::Tpm2NvramImpl(std::unique_ptr<trunks::TrunksFactory> factory,
     42                              LocalDataStore* local_data_store)
     43     : trunks_factory_(std::move(factory)),
     44       local_data_store_(local_data_store),
     45       initialized_(false),
     46       trunks_session_(trunks_factory_->GetHmacSession()),
     47       trunks_utility_(trunks_factory_->GetTpmUtility()) {}
     48 
     49 bool Tpm2NvramImpl::Initialize() {
     50   if (initialized_) {
     51     return true;
     52   }
     53   TPM_RC result = trunks_utility_->StartSession(trunks_session_.get());
     54   if (result != TPM_RC_SUCCESS) {
     55     LOG(ERROR) << "Error starting an authorization session with trunks: "
     56                << GetErrorString(result);
     57     return false;
     58   }
     59   LocalData local_data;
     60   if (!local_data_store_->Read(&local_data)) {
     61     LOG(ERROR) << "Error reading local tpm data.";
     62     return false;
     63   }
     64   if (!local_data.owner_password().empty()) {
     65     owner_password_.assign(local_data.owner_password());
     66     initialized_ = true;
     67   }
     68   return true;
     69 }
     70 
     71 bool Tpm2NvramImpl::InitializeWithOwnerPassword() {
     72   if (!Initialize()) {
     73     return false;
     74   }
     75   if (owner_password_.empty()) {
     76     LOG(ERROR) << "Error owner password not available.";
     77     return false;
     78   }
     79   trunks_session_->SetEntityAuthorizationValue(owner_password_);
     80   return true;
     81 }
     82 
     83 bool Tpm2NvramImpl::DefineNvram(uint32_t index, size_t length) {
     84   if (!InitializeWithOwnerPassword()) {
     85     return false;
     86   }
     87   TPM_RC result = trunks_utility_->DefineNVSpace(
     88       index, length, trunks_session_->GetDelegate());
     89   if (result != TPM_RC_SUCCESS) {
     90     LOG(ERROR) << "Error defining nvram space: " << GetErrorString(result);
     91     return false;
     92   }
     93   return true;
     94 }
     95 
     96 bool Tpm2NvramImpl::DestroyNvram(uint32_t index) {
     97   if (!InitializeWithOwnerPassword()) {
     98     return false;
     99   }
    100   TPM_RC result = trunks_utility_->DestroyNVSpace(
    101       index, trunks_session_->GetDelegate());
    102   if (result != TPM_RC_SUCCESS) {
    103     LOG(ERROR) << "Error destroying nvram space:" << GetErrorString(result);
    104     return false;
    105   }
    106   return true;
    107 }
    108 
    109 bool Tpm2NvramImpl::WriteNvram(uint32_t index, const std::string& data) {
    110   if (!InitializeWithOwnerPassword()) {
    111     return false;
    112   }
    113   TPM_RC result = trunks_utility_->WriteNVSpace(index,
    114                                                 0,  // offset
    115                                                 data,
    116                                                 trunks_session_->GetDelegate());
    117   if (result != TPM_RC_SUCCESS) {
    118     LOG(ERROR) << "Error writing to nvram space: " << GetErrorString(result);
    119     return false;
    120   }
    121   result = trunks_utility_->LockNVSpace(index, trunks_session_->GetDelegate());
    122   if (result != TPM_RC_SUCCESS) {
    123     LOG(ERROR) << "Error locking nvram space: " << GetErrorString(result);
    124     return false;
    125   }
    126   return true;
    127 }
    128 
    129 bool Tpm2NvramImpl::ReadNvram(uint32_t index, std::string* data) {
    130   if (!Initialize()) {
    131     return false;
    132   }
    133   size_t nvram_size;
    134   if (!GetNvramSize(index, &nvram_size)) {
    135     LOG(ERROR) << "Error getting size of nvram space.";
    136     return false;
    137   }
    138   trunks_session_->SetEntityAuthorizationValue("");
    139   TPM_RC result = trunks_utility_->ReadNVSpace(index,
    140                                                0,  // offset
    141                                                nvram_size,
    142                                                data,
    143                                                trunks_session_->GetDelegate());
    144   if (result != TPM_RC_SUCCESS) {
    145     LOG(ERROR) << "Error reading nvram space: " << GetErrorString(result);
    146     return false;
    147   }
    148   return true;
    149 }
    150 
    151 bool Tpm2NvramImpl::IsNvramDefined(uint32_t index, bool* defined) {
    152   trunks::TPMS_NV_PUBLIC nvram_public;
    153   TPM_RC result = trunks_utility_->GetNVSpacePublicArea(index, &nvram_public);
    154   if (trunks::GetFormatOneError(result) == trunks::TPM_RC_HANDLE) {
    155     *defined = false;
    156   } else if (result == TPM_RC_SUCCESS) {
    157     *defined = true;
    158   } else {
    159     LOG(ERROR) << "Error reading NV space for index " << index
    160                << " with error: " << GetErrorString(result);
    161     return false;
    162   }
    163   return true;
    164 }
    165 
    166 bool Tpm2NvramImpl::IsNvramLocked(uint32_t index, bool* locked) {
    167   trunks::TPMS_NV_PUBLIC nvram_public;
    168   TPM_RC result = trunks_utility_->GetNVSpacePublicArea(index, &nvram_public);
    169   if (result != TPM_RC_SUCCESS) {
    170     LOG(ERROR) << "Error reading NV space for index " << index
    171                << " with error: " << GetErrorString(result);
    172     return false;
    173   }
    174   *locked = ((nvram_public.attributes & trunks::TPMA_NV_WRITELOCKED) != 0);
    175   return true;
    176 }
    177 
    178 bool Tpm2NvramImpl::GetNvramSize(uint32_t index, size_t* size) {
    179   trunks::TPMS_NV_PUBLIC nvram_public;
    180   TPM_RC result = trunks_utility_->GetNVSpacePublicArea(index, &nvram_public);
    181   if (result != TPM_RC_SUCCESS) {
    182     LOG(ERROR) << "Error reading NV space for index " << index
    183                << " with error: " << GetErrorString(result);
    184     return false;
    185   }
    186   *size = nvram_public.data_size;
    187   return true;
    188 }
    189 
    190 }  // namespace tpm_manager
    191