• 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),
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