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 #include "trunks/tpm_state_impl.h"
     18 
     19 #include <base/logging.h>
     20 
     21 #include "trunks/error_codes.h"
     22 #include "trunks/tpm_generated.h"
     23 #include "trunks/trunks_factory.h"
     24 
     25 namespace {
     26 
     27 // From definition of TPMA_PERMANENT.
     28 const trunks::TPMA_PERMANENT kOwnerAuthSetMask = 1U;
     29 const trunks::TPMA_PERMANENT kEndorsementAuthSetMask = 1U << 1;
     30 const trunks::TPMA_PERMANENT kLockoutAuthSetMask = 1U << 2;
     31 const trunks::TPMA_PERMANENT kInLockoutMask = 1U << 9;
     32 
     33 // From definition of TPMA_STARTUP_CLEAR.
     34 const trunks::TPMA_STARTUP_CLEAR kPlatformHierarchyMask = 1U;
     35 const trunks::TPMA_STARTUP_CLEAR kStorageHierarchyMask = 1U << 1;
     36 const trunks::TPMA_STARTUP_CLEAR kEndorsementHierarchyMask = 1U << 2;
     37 const trunks::TPMA_STARTUP_CLEAR kOrderlyShutdownMask = 1U << 31;
     38 
     39 // From definition of TPMA_ALGORITHM
     40 const trunks::TPMA_ALGORITHM kAsymmetricAlgMask = 1U;
     41 
     42 }  // namespace
     43 
     44 namespace trunks {
     45 
     46 TpmStateImpl::TpmStateImpl(const TrunksFactory& factory)
     47     : factory_(factory),
     48       initialized_(false),
     49       permanent_flags_(0),
     50       startup_clear_flags_(0),
     51       rsa_flags_(0),
     52       ecc_flags_(0) {
     53 }
     54 
     55 TpmStateImpl::~TpmStateImpl() {}
     56 
     57 TPM_RC TpmStateImpl::Initialize() {
     58   TPM_RC result = GetTpmProperty(TPM_PT_PERMANENT, &permanent_flags_);
     59   if (result != TPM_RC_SUCCESS) {
     60     LOG(ERROR) << "Error getting permanent flags: " << GetErrorString(result);
     61     return result;
     62   }
     63   result = GetTpmProperty(TPM_PT_STARTUP_CLEAR, &startup_clear_flags_);
     64   if (result != TPM_RC_SUCCESS) {
     65     LOG(ERROR) << "Error getting startup flags: " << GetErrorString(result);
     66     return result;
     67   }
     68   result = GetTpmProperty(TPM_PT_LOCKOUT_COUNTER, &lockout_counter_);
     69   if (result != TPM_RC_SUCCESS) {
     70     LOG(ERROR) << "Error getting lockout counter: " << GetErrorString(result);
     71     return result;
     72   }
     73   result = GetTpmProperty(TPM_PT_MAX_AUTH_FAIL, &lockout_threshold_);
     74   if (result != TPM_RC_SUCCESS) {
     75     LOG(ERROR) << "Error getting lockout threshold: " << GetErrorString(result);
     76     return result;
     77   }
     78   result = GetTpmProperty(TPM_PT_LOCKOUT_INTERVAL, &lockout_interval_);
     79   if (result != TPM_RC_SUCCESS) {
     80     LOG(ERROR) << "Error getting lockout interval: " << GetErrorString(result);
     81     return result;
     82   }
     83   result = GetTpmProperty(TPM_PT_LOCKOUT_RECOVERY, &lockout_recovery_);
     84   if (result != TPM_RC_SUCCESS) {
     85     LOG(ERROR) << "Error getting lockout recovery: " << GetErrorString(result);
     86     return result;
     87   }
     88 
     89   TPMI_YES_NO more_data;
     90   TPMS_CAPABILITY_DATA capability_data;
     91   result = factory_.GetTpm()->GetCapabilitySync(TPM_CAP_ALGS,
     92                                                 TPM_ALG_RSA,
     93                                                 1,  // There is only one value.
     94                                                 &more_data,
     95                                                 &capability_data,
     96                                                 nullptr);
     97   if (result) {
     98     LOG(ERROR) << __func__ << ": " << GetErrorString(result);
     99     return result;
    100   }
    101   if (capability_data.capability != TPM_CAP_ALGS ||
    102       capability_data.data.algorithms.count != 1) {
    103     LOG(ERROR) << __func__ << ": Unexpected capability data.";
    104     return SAPI_RC_MALFORMED_RESPONSE;
    105   }
    106   if (capability_data.data.algorithms.alg_properties[0].alg == TPM_ALG_RSA) {
    107     rsa_flags_ =
    108         capability_data.data.algorithms.alg_properties[0].alg_properties;
    109   }
    110   result = factory_.GetTpm()->GetCapabilitySync(TPM_CAP_ALGS,
    111                                                 TPM_ALG_ECC,
    112                                                 1,  // There is only one value.
    113                                                 &more_data,
    114                                                 &capability_data,
    115                                                 nullptr);
    116   if (result) {
    117     LOG(ERROR) << __func__ << ": " << GetErrorString(result);
    118     return result;
    119   }
    120   if (capability_data.capability != TPM_CAP_ALGS ||
    121       capability_data.data.algorithms.count != 1) {
    122     LOG(ERROR) << __func__ << ": Unexpected capability data.";
    123     return SAPI_RC_MALFORMED_RESPONSE;
    124   }
    125   if (capability_data.data.algorithms.alg_properties[0].alg == TPM_ALG_ECC) {
    126     ecc_flags_ =
    127         capability_data.data.algorithms.alg_properties[0].alg_properties;
    128   }
    129   initialized_ = true;
    130   return TPM_RC_SUCCESS;
    131 }
    132 
    133 bool TpmStateImpl::IsOwnerPasswordSet() {
    134   CHECK(initialized_);
    135   return ((permanent_flags_ & kOwnerAuthSetMask) == kOwnerAuthSetMask);
    136 }
    137 
    138 bool TpmStateImpl::IsEndorsementPasswordSet() {
    139   CHECK(initialized_);
    140   return ((permanent_flags_ & kEndorsementAuthSetMask) ==
    141           kEndorsementAuthSetMask);
    142 }
    143 
    144 bool TpmStateImpl::IsLockoutPasswordSet() {
    145   CHECK(initialized_);
    146   return ((permanent_flags_ & kLockoutAuthSetMask) == kLockoutAuthSetMask);
    147 }
    148 
    149 bool TpmStateImpl::IsOwned() {
    150   return (IsOwnerPasswordSet() &&
    151           IsEndorsementPasswordSet() &&
    152           IsLockoutPasswordSet());
    153 }
    154 
    155 bool TpmStateImpl::IsInLockout() {
    156   CHECK(initialized_);
    157   return ((permanent_flags_ & kInLockoutMask) == kInLockoutMask);
    158 }
    159 
    160 bool TpmStateImpl::IsPlatformHierarchyEnabled() {
    161   CHECK(initialized_);
    162   return ((startup_clear_flags_ & kPlatformHierarchyMask) ==
    163       kPlatformHierarchyMask);
    164 }
    165 
    166 bool TpmStateImpl::IsStorageHierarchyEnabled() {
    167   CHECK(initialized_);
    168   return ((startup_clear_flags_ & kStorageHierarchyMask) ==
    169       kStorageHierarchyMask);
    170 }
    171 
    172 bool TpmStateImpl::IsEndorsementHierarchyEnabled() {
    173   CHECK(initialized_);
    174   return ((startup_clear_flags_ & kEndorsementHierarchyMask) ==
    175       kEndorsementHierarchyMask);
    176 }
    177 
    178 bool TpmStateImpl::IsEnabled() {
    179   return (!IsPlatformHierarchyEnabled() &&
    180           IsStorageHierarchyEnabled() &&
    181           IsEndorsementHierarchyEnabled());
    182 }
    183 
    184 bool TpmStateImpl::WasShutdownOrderly() {
    185   CHECK(initialized_);
    186   return ((startup_clear_flags_ & kOrderlyShutdownMask) ==
    187       kOrderlyShutdownMask);
    188 }
    189 
    190 bool TpmStateImpl::IsRSASupported() {
    191   CHECK(initialized_);
    192   return ((rsa_flags_ & kAsymmetricAlgMask) == kAsymmetricAlgMask);
    193 }
    194 
    195 bool TpmStateImpl::IsECCSupported() {
    196   CHECK(initialized_);
    197   return ((ecc_flags_ & kAsymmetricAlgMask) == kAsymmetricAlgMask);
    198 }
    199 
    200 uint32_t TpmStateImpl::GetLockoutCounter() {
    201   CHECK(initialized_);
    202   return lockout_counter_;
    203 }
    204 
    205 uint32_t TpmStateImpl::GetLockoutThreshold() {
    206   CHECK(initialized_);
    207   return lockout_threshold_;
    208 }
    209 
    210 uint32_t TpmStateImpl::GetLockoutInterval() {
    211   CHECK(initialized_);
    212   return lockout_interval_;
    213 }
    214 
    215 uint32_t TpmStateImpl::GetLockoutRecovery() {
    216   CHECK(initialized_);
    217   return lockout_recovery_;
    218 }
    219 
    220 TPM_RC TpmStateImpl::GetTpmProperty(uint32_t property,
    221                                     uint32_t* value) {
    222   CHECK(value);
    223   TPMI_YES_NO more_data;
    224   TPMS_CAPABILITY_DATA capability_data;
    225   TPM_RC result = factory_.GetTpm()->GetCapabilitySync(TPM_CAP_TPM_PROPERTIES,
    226                                                        property,
    227                                                        1,  // Only one property.
    228                                                        &more_data,
    229                                                        &capability_data,
    230                                                        nullptr);
    231   if (result != TPM_RC_SUCCESS) {
    232     LOG(ERROR) << __func__ << ": " << GetErrorString(result);
    233     return result;
    234   }
    235   if (capability_data.capability != TPM_CAP_TPM_PROPERTIES ||
    236       capability_data.data.tpm_properties.count != 1 ||
    237       capability_data.data.tpm_properties.tpm_property[0].property !=
    238       property) {
    239     LOG(ERROR) << __func__ << ": Unexpected capability data.";
    240     return SAPI_RC_MALFORMED_RESPONSE;
    241   }
    242   *value = capability_data.data.tpm_properties.tpm_property[0].value;
    243   return TPM_RC_SUCCESS;
    244 }
    245 
    246 }  // namespace trunks
    247