• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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