Home | History | Annotate | Download | only in trunks
      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 "trunks/policy_session_impl.h"
     18 
     19 #include <string>
     20 #include <vector>
     21 
     22 #include <base/logging.h>
     23 #include <base/macros.h>
     24 #include <base/stl_util.h>
     25 #include <crypto/sha2.h>
     26 #include <openssl/rand.h>
     27 
     28 #include "trunks/error_codes.h"
     29 #include "trunks/tpm_generated.h"
     30 
     31 namespace trunks {
     32 
     33 PolicySessionImpl::PolicySessionImpl(const TrunksFactory& factory)
     34     : factory_(factory),
     35       session_type_(TPM_SE_POLICY) {
     36   session_manager_ = factory_.GetSessionManager();
     37 }
     38 
     39 PolicySessionImpl::PolicySessionImpl(const TrunksFactory& factory,
     40                                      TPM_SE session_type)
     41     : factory_(factory),
     42       session_type_(session_type) {
     43   session_manager_ = factory_.GetSessionManager();
     44 }
     45 
     46 PolicySessionImpl::~PolicySessionImpl() {
     47   session_manager_->CloseSession();
     48 }
     49 
     50 AuthorizationDelegate* PolicySessionImpl::GetDelegate() {
     51   if (session_manager_->GetSessionHandle() == kUninitializedHandle) {
     52     return nullptr;
     53   }
     54   return &hmac_delegate_;
     55 }
     56 
     57 TPM_RC PolicySessionImpl::StartBoundSession(
     58     TPMI_DH_ENTITY bind_entity,
     59     const std::string& bind_authorization_value,
     60     bool enable_encryption) {
     61   hmac_delegate_.set_use_entity_authorization_for_encryption_only(true);
     62   if (session_type_ != TPM_SE_POLICY && session_type_ != TPM_SE_TRIAL) {
     63     LOG(ERROR) << "Cannot start a session of that type.";
     64     return SAPI_RC_INVALID_SESSIONS;
     65   }
     66   return session_manager_->StartSession(session_type_, bind_entity,
     67                                         bind_authorization_value,
     68                                         enable_encryption, &hmac_delegate_);
     69 }
     70 
     71 TPM_RC PolicySessionImpl::StartUnboundSession(bool enable_encryption) {
     72   // Just like a HmacAuthorizationSession, an unbound policy session is just
     73   // a session bound to TPM_RH_NULL.
     74   return StartBoundSession(TPM_RH_NULL, "", enable_encryption);
     75 }
     76 
     77 TPM_RC PolicySessionImpl::GetDigest(std::string* digest) {
     78   CHECK(digest);
     79   TPM2B_DIGEST policy_digest;
     80   TPM_RC result = factory_.GetTpm()->PolicyGetDigestSync(
     81       session_manager_->GetSessionHandle(),
     82       "",  // No name is needed for this command, as it does no authorization.
     83       &policy_digest,
     84       nullptr);
     85   if (result != TPM_RC_SUCCESS) {
     86     LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result);
     87     return result;
     88   }
     89   *digest = StringFrom_TPM2B_DIGEST(policy_digest);
     90   return TPM_RC_SUCCESS;
     91 }
     92 
     93 TPM_RC PolicySessionImpl::PolicyOR(const std::vector<std::string>& digests) {
     94   if (digests.size() >= arraysize(TPML_DIGEST::digests)) {
     95     LOG(ERROR) << "TPM2.0 Spec only allows for up to 8 digests.";
     96     return SAPI_RC_BAD_PARAMETER;
     97   }
     98   TPML_DIGEST tpm_digests;
     99   tpm_digests.count = digests.size();
    100   for (size_t i = 0; i < digests.size(); i++) {
    101     tpm_digests.digests[i] = Make_TPM2B_DIGEST(digests[i]);
    102   }
    103   TPM_RC result = factory_.GetTpm()->PolicyORSync(
    104       session_manager_->GetSessionHandle(),
    105       "",  // No policy name is needed as we do no authorization checks.
    106       tpm_digests,
    107       nullptr);
    108   if (result != TPM_RC_SUCCESS) {
    109     LOG(ERROR) << "Error performing PolicyOR: " << GetErrorString(result);
    110     return result;
    111   }
    112 
    113   return TPM_RC_SUCCESS;
    114 }
    115 
    116 TPM_RC PolicySessionImpl::PolicyPCR(uint32_t pcr_index,
    117                                     const std::string& pcr_value) {
    118   TPML_PCR_SELECTION pcr_select;
    119   memset(&pcr_select, 0, sizeof(TPML_PCR_SELECTION));
    120   // This process of selecting pcrs is highlighted in TPM 2.0 Library Spec
    121   // Part 2 (Section 10.5 - PCR structures).
    122   uint8_t pcr_select_index = pcr_index / 8;
    123   uint8_t pcr_select_byte = 1 << (pcr_index % 8);
    124   pcr_select.count = 1;
    125   pcr_select.pcr_selections[0].hash = TPM_ALG_SHA256;
    126   pcr_select.pcr_selections[0].sizeof_select = PCR_SELECT_MIN;
    127   pcr_select.pcr_selections[0].pcr_select[pcr_select_index] = pcr_select_byte;
    128   TPM2B_DIGEST pcr_digest;
    129   if (pcr_value.empty()) {
    130     if (session_type_ == TPM_SE_TRIAL) {
    131       LOG(ERROR) << "Trial sessions have to define a PCR value.";
    132       return SAPI_RC_BAD_PARAMETER;
    133     }
    134     pcr_digest = Make_TPM2B_DIGEST("");
    135   } else {
    136     pcr_digest = Make_TPM2B_DIGEST(crypto::SHA256HashString(pcr_value));
    137   }
    138 
    139   TPM_RC result = factory_.GetTpm()->PolicyPCRSync(
    140       session_manager_->GetSessionHandle(),
    141       "",  // No policy name is needed as we do no authorization checks.
    142       pcr_digest,
    143       pcr_select,
    144       nullptr);
    145   if (result != TPM_RC_SUCCESS) {
    146     LOG(ERROR) << "Error performing PolicyPCR: " << GetErrorString(result);
    147     return result;
    148   }
    149   return TPM_RC_SUCCESS;
    150 }
    151 
    152 TPM_RC PolicySessionImpl::PolicyCommandCode(TPM_CC command_code) {
    153   TPM_RC result = factory_.GetTpm()->PolicyCommandCodeSync(
    154       session_manager_->GetSessionHandle(),
    155       "",  // No policy name is needed as we do no authorization checks.
    156       command_code,
    157       nullptr);
    158   if (result != TPM_RC_SUCCESS) {
    159     LOG(ERROR) << "Error performing PolicyCommandCode: "
    160                << GetErrorString(result);
    161     return result;
    162   }
    163   return TPM_RC_SUCCESS;
    164 }
    165 
    166 TPM_RC PolicySessionImpl::PolicyAuthValue() {
    167   TPM_RC result = factory_.GetTpm()->PolicyAuthValueSync(
    168       session_manager_->GetSessionHandle(),
    169       "",  // No policy name is needed as we do no authorization checks.
    170       nullptr);
    171   if (result != TPM_RC_SUCCESS) {
    172     LOG(ERROR) << "Error performing PolicyAuthValue: "
    173                << GetErrorString(result);
    174     return result;
    175   }
    176   hmac_delegate_.set_use_entity_authorization_for_encryption_only(false);
    177   return TPM_RC_SUCCESS;
    178 }
    179 
    180 void PolicySessionImpl::SetEntityAuthorizationValue(const std::string& value) {
    181   hmac_delegate_.set_entity_authorization_value(value);
    182 }
    183 
    184 }  // namespace trunks
    185