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
PolicySessionImpl(const TrunksFactory & factory)33 PolicySessionImpl::PolicySessionImpl(const TrunksFactory& factory)
34 : factory_(factory), session_type_(TPM_SE_POLICY) {
35 session_manager_ = factory_.GetSessionManager();
36 }
37
PolicySessionImpl(const TrunksFactory & factory,TPM_SE session_type)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
~PolicySessionImpl()44 PolicySessionImpl::~PolicySessionImpl() {
45 session_manager_->CloseSession();
46 }
47
GetDelegate()48 AuthorizationDelegate* PolicySessionImpl::GetDelegate() {
49 if (session_manager_->GetSessionHandle() == kUninitializedHandle) {
50 return nullptr;
51 }
52 return &hmac_delegate_;
53 }
54
StartBoundSession(TPMI_DH_ENTITY bind_entity,const std::string & bind_authorization_value,bool enable_encryption)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
StartUnboundSession(bool enable_encryption)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
GetDigest(std::string * digest)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
PolicyOR(const std::vector<std::string> & digests)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
PolicyPCR(uint32_t pcr_index,const std::string & pcr_value)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
PolicyCommandCode(TPM_CC command_code)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
PolicyAuthValue()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
PolicyRestart()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
SetEntityAuthorizationValue(const std::string & value)185 void PolicySessionImpl::SetEntityAuthorizationValue(const std::string& value) {
186 hmac_delegate_.set_entity_authorization_value(value);
187 }
188
189 } // namespace trunks
190