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