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