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 31namespace trunks { 32 33PolicySessionImpl::PolicySessionImpl(const TrunksFactory& factory) 34 : factory_(factory), 35 session_type_(TPM_SE_POLICY) { 36 session_manager_ = factory_.GetSessionManager(); 37} 38 39PolicySessionImpl::PolicySessionImpl(const TrunksFactory& factory, 40 TPM_SE session_type) 41 : factory_(factory), 42 session_type_(session_type) { 43 session_manager_ = factory_.GetSessionManager(); 44} 45 46PolicySessionImpl::~PolicySessionImpl() { 47 session_manager_->CloseSession(); 48} 49 50AuthorizationDelegate* PolicySessionImpl::GetDelegate() { 51 if (session_manager_->GetSessionHandle() == kUninitializedHandle) { 52 return nullptr; 53 } 54 return &hmac_delegate_; 55} 56 57TPM_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 71TPM_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 77TPM_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 93TPM_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 116TPM_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 152TPM_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 166TPM_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 180void PolicySessionImpl::SetEntityAuthorizationValue(const std::string& value) { 181 hmac_delegate_.set_entity_authorization_value(value); 182} 183 184} // namespace trunks 185