tpm_utility_impl.cc revision 4dc4629c415e7ca90ff146d7bb75b5646ecd8b17
1//
2// Copyright (C) 2014 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/tpm_utility_impl.h"
18
19#include <base/logging.h>
20#include <base/memory/scoped_ptr.h>
21#include <base/sha1.h>
22#include <base/stl_util.h>
23#include <crypto/openssl_util.h>
24#include <crypto/secure_hash.h>
25#include <crypto/sha2.h>
26#include <openssl/aes.h>
27#include <openssl/rand.h>
28
29#include "trunks/authorization_delegate.h"
30#include "trunks/blob_parser.h"
31#include "trunks/error_codes.h"
32#include "trunks/hmac_authorization_delegate.h"
33#include "trunks/hmac_session.h"
34#include "trunks/policy_session.h"
35#include "trunks/scoped_key_handle.h"
36#include "trunks/tpm_constants.h"
37#include "trunks/tpm_state.h"
38#include "trunks/trunks_factory.h"
39
40namespace {
41
42const char kPlatformPassword[] = "cros-platform";
43const char kWellKnownPassword[] = "cros-password";
44const size_t kMaxPasswordLength = 32;
45// The below maximum is defined in TPM 2.0 Library Spec Part 2 Section 13.1
46const uint32_t kMaxNVSpaceIndex = (1 << 24) - 1;
47
48// Returns a serialized representation of the unmodified handle. This is useful
49// for predefined handle values, like TPM_RH_OWNER. For details on what types of
50// handles use this name formula see Table 3 in the TPM 2.0 Library Spec Part 1
51// (Section 16 - Names).
52std::string NameFromHandle(trunks::TPM_HANDLE handle) {
53  std::string name;
54  trunks::Serialize_TPM_HANDLE(handle, &name);
55  return name;
56}
57
58std::string HashString(const std::string& plaintext,
59                       trunks::TPM_ALG_ID hash_alg) {
60  switch (hash_alg) {
61    case trunks::TPM_ALG_SHA1:
62      return base::SHA1HashString(plaintext);
63    case trunks::TPM_ALG_SHA256:
64      return crypto::SHA256HashString(plaintext);
65  }
66  NOTREACHED();
67  return std::string();
68}
69
70}  // namespace
71
72namespace trunks {
73
74TpmUtilityImpl::TpmUtilityImpl(const TrunksFactory& factory)
75    : factory_(factory) {
76  crypto::EnsureOpenSSLInit();
77}
78
79TpmUtilityImpl::~TpmUtilityImpl() {}
80
81TPM_RC TpmUtilityImpl::Startup() {
82  TPM_RC result = TPM_RC_SUCCESS;
83  Tpm* tpm = factory_.GetTpm();
84  result = tpm->StartupSync(TPM_SU_CLEAR, nullptr);
85  // Ignore TPM_RC_INITIALIZE, that means it was already started.
86  if (result && result != TPM_RC_INITIALIZE) {
87    LOG(ERROR) << __func__ << ": " << GetErrorString(result);
88    return result;
89  }
90  result = tpm->SelfTestSync(YES /* Full test. */, nullptr);
91  if (result) {
92    LOG(ERROR) << __func__ << ": " << GetErrorString(result);
93    return result;
94  }
95  return TPM_RC_SUCCESS;
96}
97
98TPM_RC TpmUtilityImpl::Clear() {
99  TPM_RC result = TPM_RC_SUCCESS;
100  scoped_ptr<AuthorizationDelegate> password_delegate(
101      factory_.GetPasswordAuthorization(""));
102  result = factory_.GetTpm()->ClearSync(TPM_RH_PLATFORM,
103                                        NameFromHandle(TPM_RH_PLATFORM),
104                                        password_delegate.get());
105  // If there was an error in the initialization, platform auth is in a bad
106  // state.
107  if (result == TPM_RC_AUTH_MISSING) {
108    scoped_ptr<AuthorizationDelegate> authorization(
109        factory_.GetPasswordAuthorization(kPlatformPassword));
110    result = factory_.GetTpm()->ClearSync(
111        TPM_RH_PLATFORM, NameFromHandle(TPM_RH_PLATFORM), authorization.get());
112  }
113  if (GetFormatOneError(result) == TPM_RC_BAD_AUTH) {
114    LOG(INFO) << "Clear failed because of BAD_AUTH. This probably means "
115              << "that the TPM was already initialized.";
116    return result;
117  }
118  if (result) {
119    LOG(ERROR) << "Failed to clear the TPM: " << GetErrorString(result);
120  }
121  return result;
122}
123
124void TpmUtilityImpl::Shutdown() {
125  TPM_RC return_code = factory_.GetTpm()->ShutdownSync(TPM_SU_CLEAR, nullptr);
126  if (return_code && return_code != TPM_RC_INITIALIZE) {
127    // This should not happen, but if it does, there is nothing we can do.
128    LOG(ERROR) << "Error shutting down: " << GetErrorString(return_code);
129  }
130}
131
132TPM_RC TpmUtilityImpl::InitializeTpm() {
133  TPM_RC result = TPM_RC_SUCCESS;
134  scoped_ptr<TpmState> tpm_state(factory_.GetTpmState());
135  result = tpm_state->Initialize();
136  if (result) {
137    LOG(ERROR) << __func__ << ": " << GetErrorString(result);
138    return result;
139  }
140  // Warn about various unexpected conditions.
141  if (!tpm_state->WasShutdownOrderly()) {
142    LOG(WARNING) << "WARNING: The last TPM shutdown was not orderly.";
143  }
144  if (tpm_state->IsInLockout()) {
145    LOG(WARNING) << "WARNING: The TPM is currently in lockout.";
146  }
147
148  // We expect the firmware has already locked down the platform hierarchy. If
149  // it hasn't, do it now.
150  if (tpm_state->IsPlatformHierarchyEnabled()) {
151    scoped_ptr<AuthorizationDelegate> empty_password(
152        factory_.GetPasswordAuthorization(""));
153    result = SetHierarchyAuthorization(TPM_RH_PLATFORM, kPlatformPassword,
154                                       empty_password.get());
155    if (GetFormatOneError(result) == TPM_RC_BAD_AUTH) {
156      // Most likely the platform password has already been set.
157      result = TPM_RC_SUCCESS;
158    }
159    if (result != TPM_RC_SUCCESS) {
160      LOG(ERROR) << __func__ << ": " << GetErrorString(result);
161      return result;
162    }
163    result = AllocatePCR(kPlatformPassword);
164    if (result != TPM_RC_SUCCESS) {
165      LOG(ERROR) << __func__ << ": " << GetErrorString(result);
166      return result;
167    }
168    scoped_ptr<AuthorizationDelegate> authorization(
169        factory_.GetPasswordAuthorization(kPlatformPassword));
170    result = DisablePlatformHierarchy(authorization.get());
171    if (result != TPM_RC_SUCCESS) {
172      LOG(ERROR) << __func__ << ": " << GetErrorString(result);
173      return result;
174    }
175  }
176  return TPM_RC_SUCCESS;
177}
178
179TPM_RC TpmUtilityImpl::AllocatePCR(const std::string& platform_password) {
180  TPM_RC result;
181  TPMI_YES_NO more_data = YES;
182  TPMS_CAPABILITY_DATA capability_data;
183  result = factory_.GetTpm()->GetCapabilitySync(
184      TPM_CAP_PCRS, 0 /*property (not used)*/, 1 /*property_count*/, &more_data,
185      &capability_data, nullptr /*authorization_delegate*/);
186  if (result != TPM_RC_SUCCESS) {
187    LOG(ERROR) << "Error querying PCRs: " << GetErrorString(result);
188    return result;
189  }
190  TPML_PCR_SELECTION& existing_pcrs = capability_data.data.assigned_pcr;
191  bool sha256_needed = true;
192  std::vector<TPMI_ALG_HASH> pcr_banks_to_remove;
193  for (uint32_t i = 0; i < existing_pcrs.count; ++i) {
194    if (existing_pcrs.pcr_selections[i].hash == TPM_ALG_SHA256) {
195      sha256_needed = false;
196    } else {
197      pcr_banks_to_remove.push_back(existing_pcrs.pcr_selections[i].hash);
198    }
199  }
200  if (!sha256_needed && pcr_banks_to_remove.empty()) {
201    return TPM_RC_SUCCESS;
202  }
203  TPML_PCR_SELECTION pcr_allocation;
204  memset(&pcr_allocation, 0, sizeof(pcr_allocation));
205  if (sha256_needed) {
206    pcr_allocation.pcr_selections[pcr_allocation.count].hash = TPM_ALG_SHA256;
207    pcr_allocation.pcr_selections[pcr_allocation.count].sizeof_select =
208        PCR_SELECT_MIN;
209    for (int i = 0; i < PCR_SELECT_MIN; ++i) {
210      pcr_allocation.pcr_selections[pcr_allocation.count].pcr_select[i] = 0xff;
211    }
212    ++pcr_allocation.count;
213  }
214  for (auto pcr_type : pcr_banks_to_remove) {
215    pcr_allocation.pcr_selections[pcr_allocation.count].hash = pcr_type;
216    pcr_allocation.pcr_selections[pcr_allocation.count].sizeof_select =
217        PCR_SELECT_MAX;
218    ++pcr_allocation.count;
219  }
220  scoped_ptr<AuthorizationDelegate> platform_delegate(
221      factory_.GetPasswordAuthorization(platform_password));
222  TPMI_YES_NO allocation_success;
223  uint32_t max_pcr;
224  uint32_t size_needed;
225  uint32_t size_available;
226  result = factory_.GetTpm()->PCR_AllocateSync(
227      TPM_RH_PLATFORM, NameFromHandle(TPM_RH_PLATFORM), pcr_allocation,
228      &allocation_success, &max_pcr, &size_needed, &size_available,
229      platform_delegate.get());
230  if (result != TPM_RC_SUCCESS) {
231    LOG(ERROR) << "Error allocating PCRs: " << GetErrorString(result);
232    return result;
233  }
234  if (allocation_success != YES) {
235    LOG(ERROR) << "PCR allocation unsuccessful.";
236    return TPM_RC_FAILURE;
237  }
238  return TPM_RC_SUCCESS;
239}
240
241TPM_RC TpmUtilityImpl::TakeOwnership(const std::string& owner_password,
242                                     const std::string& endorsement_password,
243                                     const std::string& lockout_password) {
244  // First we set the storage hierarchy authorization to the well know default
245  // password.
246  TPM_RC result = TPM_RC_SUCCESS;
247  result = SetKnownOwnerPassword(kWellKnownPassword);
248  if (result != TPM_RC_SUCCESS) {
249    LOG(ERROR) << "Error injecting known password: " << GetErrorString(result);
250    return result;
251  }
252
253  result = CreateStorageRootKeys(kWellKnownPassword);
254  if (result) {
255    LOG(ERROR) << "Error creating SRKs: " << GetErrorString(result);
256    return result;
257  }
258  result = CreateSaltingKey(kWellKnownPassword);
259  if (result) {
260    LOG(ERROR) << "Error creating salting key: " << GetErrorString(result);
261    return result;
262  }
263
264  scoped_ptr<HmacSession> session = factory_.GetHmacSession();
265  result = session->StartUnboundSession(true);
266  if (result != TPM_RC_SUCCESS) {
267    LOG(ERROR) << "Error initializing AuthorizationSession: "
268               << GetErrorString(result);
269    return result;
270  }
271  scoped_ptr<TpmState> tpm_state(factory_.GetTpmState());
272  result = tpm_state->Initialize();
273  session->SetEntityAuthorizationValue("");
274  session->SetFutureAuthorizationValue(endorsement_password);
275  if (!tpm_state->IsEndorsementPasswordSet()) {
276    result = SetHierarchyAuthorization(TPM_RH_ENDORSEMENT, endorsement_password,
277                                       session->GetDelegate());
278    if (result) {
279      LOG(ERROR) << __func__ << ": " << GetErrorString(result);
280      return result;
281    }
282  }
283  session->SetFutureAuthorizationValue(lockout_password);
284  if (!tpm_state->IsLockoutPasswordSet()) {
285    result = SetHierarchyAuthorization(TPM_RH_LOCKOUT, lockout_password,
286                                       session->GetDelegate());
287    if (result) {
288      LOG(ERROR) << __func__ << ": " << GetErrorString(result);
289      return result;
290    }
291  }
292  // We take ownership of owner hierarchy last.
293  session->SetEntityAuthorizationValue(kWellKnownPassword);
294  session->SetFutureAuthorizationValue(owner_password);
295  result = SetHierarchyAuthorization(TPM_RH_OWNER, owner_password,
296                                     session->GetDelegate());
297  if ((GetFormatOneError(result) == TPM_RC_BAD_AUTH) &&
298      tpm_state->IsOwnerPasswordSet()) {
299    LOG(WARNING) << "Error changing owner password. This probably because "
300                 << "ownership is already taken.";
301    return TPM_RC_SUCCESS;
302  } else if (result != TPM_RC_SUCCESS) {
303    LOG(ERROR) << "Error changing owner authorization: "
304               << GetErrorString(result);
305    return result;
306  }
307  return TPM_RC_SUCCESS;
308}
309
310TPM_RC TpmUtilityImpl::StirRandom(const std::string& entropy_data,
311                                  AuthorizationDelegate* delegate) {
312  std::string digest = crypto::SHA256HashString(entropy_data);
313  TPM2B_SENSITIVE_DATA random_bytes = Make_TPM2B_SENSITIVE_DATA(digest);
314  return factory_.GetTpm()->StirRandomSync(random_bytes, delegate);
315}
316
317TPM_RC TpmUtilityImpl::GenerateRandom(size_t num_bytes,
318                                      AuthorizationDelegate* delegate,
319                                      std::string* random_data) {
320  CHECK(random_data);
321  size_t bytes_left = num_bytes;
322  random_data->clear();
323  TPM_RC rc;
324  TPM2B_DIGEST digest;
325  while (bytes_left > 0) {
326    rc = factory_.GetTpm()->GetRandomSync(bytes_left, &digest, delegate);
327    if (rc) {
328      LOG(ERROR) << "Error getting random data from tpm.";
329      return rc;
330    }
331    random_data->append(StringFrom_TPM2B_DIGEST(digest));
332    bytes_left -= digest.size;
333  }
334  CHECK_EQ(random_data->size(), num_bytes);
335  return TPM_RC_SUCCESS;
336}
337
338TPM_RC TpmUtilityImpl::ExtendPCR(int pcr_index,
339                                 const std::string& extend_data,
340                                 AuthorizationDelegate* delegate) {
341  if (pcr_index < 0 || pcr_index >= IMPLEMENTATION_PCR) {
342    LOG(ERROR) << "Using a PCR index that isnt implemented.";
343    return TPM_RC_FAILURE;
344  }
345  TPM_HANDLE pcr_handle = HR_PCR + pcr_index;
346  std::string pcr_name = NameFromHandle(pcr_handle);
347  TPML_DIGEST_VALUES digests;
348  digests.count = 1;
349  digests.digests[0].hash_alg = TPM_ALG_SHA256;
350  crypto::SHA256HashString(extend_data, digests.digests[0].digest.sha256,
351                           crypto::kSHA256Length);
352  return factory_.GetTpm()->PCR_ExtendSync(pcr_handle, pcr_name, digests,
353                                           delegate);
354}
355
356TPM_RC TpmUtilityImpl::ReadPCR(int pcr_index, std::string* pcr_value) {
357  TPML_PCR_SELECTION pcr_select_in;
358  uint32_t pcr_update_counter;
359  TPML_PCR_SELECTION pcr_select_out;
360  TPML_DIGEST pcr_values;
361  // This process of selecting pcrs is highlighted in TPM 2.0 Library Spec
362  // Part 2 (Section 10.5 - PCR structures).
363  uint8_t pcr_select_index = pcr_index / 8;
364  uint8_t pcr_select_byte = 1 << (pcr_index % 8);
365  pcr_select_in.count = 1;
366  pcr_select_in.pcr_selections[0].hash = TPM_ALG_SHA256;
367  pcr_select_in.pcr_selections[0].sizeof_select = PCR_SELECT_MIN;
368  pcr_select_in.pcr_selections[0].pcr_select[pcr_select_index] =
369      pcr_select_byte;
370
371  TPM_RC rc =
372      factory_.GetTpm()->PCR_ReadSync(pcr_select_in, &pcr_update_counter,
373                                      &pcr_select_out, &pcr_values, nullptr);
374  if (rc) {
375    LOG(INFO) << "Error trying to read a pcr: " << GetErrorString(rc);
376    return rc;
377  }
378  if (pcr_select_out.count != 1 ||
379      pcr_select_out.pcr_selections[0].sizeof_select < (pcr_select_index + 1) ||
380      pcr_select_out.pcr_selections[0].pcr_select[pcr_select_index] !=
381          pcr_select_byte) {
382    LOG(ERROR) << "TPM did not return the requested PCR";
383    return TPM_RC_FAILURE;
384  }
385  CHECK_GE(pcr_values.count, 1U);
386  pcr_value->assign(StringFrom_TPM2B_DIGEST(pcr_values.digests[0]));
387  return TPM_RC_SUCCESS;
388}
389
390TPM_RC TpmUtilityImpl::AsymmetricEncrypt(TPM_HANDLE key_handle,
391                                         TPM_ALG_ID scheme,
392                                         TPM_ALG_ID hash_alg,
393                                         const std::string& plaintext,
394                                         AuthorizationDelegate* delegate,
395                                         std::string* ciphertext) {
396  TPMT_RSA_DECRYPT in_scheme;
397  if (hash_alg == TPM_ALG_NULL) {
398    hash_alg = TPM_ALG_SHA256;
399  }
400  if (scheme == TPM_ALG_RSAES) {
401    in_scheme.scheme = TPM_ALG_RSAES;
402  } else if (scheme == TPM_ALG_OAEP || scheme == TPM_ALG_NULL) {
403    in_scheme.scheme = TPM_ALG_OAEP;
404    in_scheme.details.oaep.hash_alg = hash_alg;
405  } else {
406    LOG(ERROR) << "Invalid Signing scheme used.";
407    return SAPI_RC_BAD_PARAMETER;
408  }
409
410  TPMT_PUBLIC public_area;
411  TPM_RC result = GetKeyPublicArea(key_handle, &public_area);
412  if (result != TPM_RC_SUCCESS) {
413    LOG(ERROR) << "Error finding public area for: " << key_handle;
414    return result;
415  } else if (public_area.type != TPM_ALG_RSA) {
416    LOG(ERROR) << "Key handle given is not an RSA key";
417    return SAPI_RC_BAD_PARAMETER;
418  } else if ((public_area.object_attributes & kDecrypt) == 0) {
419    LOG(ERROR) << "Key handle given is not a decryption key";
420    return SAPI_RC_BAD_PARAMETER;
421  }
422  if ((public_area.object_attributes & kRestricted) != 0) {
423    LOG(ERROR) << "Cannot use RSAES for encryption with a restricted key";
424    return SAPI_RC_BAD_PARAMETER;
425  }
426  std::string key_name;
427  result = ComputeKeyName(public_area, &key_name);
428  if (result != TPM_RC_SUCCESS) {
429    LOG(ERROR) << "Error computing key name for: " << key_handle;
430    return result;
431  }
432
433  TPM2B_DATA label;
434  label.size = 0;
435  TPM2B_PUBLIC_KEY_RSA in_message = Make_TPM2B_PUBLIC_KEY_RSA(plaintext);
436  TPM2B_PUBLIC_KEY_RSA out_message;
437  result = factory_.GetTpm()->RSA_EncryptSync(key_handle, key_name, in_message,
438                                              in_scheme, label, &out_message,
439                                              delegate);
440  if (result != TPM_RC_SUCCESS) {
441    LOG(ERROR) << "Error performing RSA encrypt: " << GetErrorString(result);
442    return result;
443  }
444  ciphertext->assign(StringFrom_TPM2B_PUBLIC_KEY_RSA(out_message));
445  return TPM_RC_SUCCESS;
446}
447
448TPM_RC TpmUtilityImpl::AsymmetricDecrypt(TPM_HANDLE key_handle,
449                                         TPM_ALG_ID scheme,
450                                         TPM_ALG_ID hash_alg,
451                                         const std::string& ciphertext,
452                                         AuthorizationDelegate* delegate,
453                                         std::string* plaintext) {
454  TPMT_RSA_DECRYPT in_scheme;
455  if (hash_alg == TPM_ALG_NULL) {
456    hash_alg = TPM_ALG_SHA256;
457  }
458  if (scheme == TPM_ALG_RSAES) {
459    in_scheme.scheme = TPM_ALG_RSAES;
460  } else if (scheme == TPM_ALG_OAEP || scheme == TPM_ALG_NULL) {
461    in_scheme.scheme = TPM_ALG_OAEP;
462    in_scheme.details.oaep.hash_alg = hash_alg;
463  } else {
464    LOG(ERROR) << "Invalid Signing scheme used.";
465    return SAPI_RC_BAD_PARAMETER;
466  }
467  TPM_RC result;
468  if (delegate == nullptr) {
469    result = SAPI_RC_INVALID_SESSIONS;
470    LOG(ERROR) << "This method needs a valid authorization delegate: "
471               << GetErrorString(result);
472    return result;
473  }
474  TPMT_PUBLIC public_area;
475  result = GetKeyPublicArea(key_handle, &public_area);
476  if (result) {
477    LOG(ERROR) << "Error finding public area for: " << key_handle;
478    return result;
479  } else if (public_area.type != TPM_ALG_RSA) {
480    LOG(ERROR) << "Key handle given is not an RSA key";
481    return SAPI_RC_BAD_PARAMETER;
482  } else if ((public_area.object_attributes & kDecrypt) == 0) {
483    LOG(ERROR) << "Key handle given is not a decryption key";
484    return SAPI_RC_BAD_PARAMETER;
485  }
486  if ((public_area.object_attributes & kRestricted) != 0) {
487    LOG(ERROR) << "Cannot use RSAES for encryption with a restricted key";
488    return SAPI_RC_BAD_PARAMETER;
489  }
490  std::string key_name;
491  result = ComputeKeyName(public_area, &key_name);
492  if (result) {
493    LOG(ERROR) << "Error computing key name for: " << key_handle;
494    return result;
495  }
496
497  TPM2B_DATA label;
498  label.size = 0;
499  TPM2B_PUBLIC_KEY_RSA in_message = Make_TPM2B_PUBLIC_KEY_RSA(ciphertext);
500  TPM2B_PUBLIC_KEY_RSA out_message;
501  result = factory_.GetTpm()->RSA_DecryptSync(key_handle, key_name, in_message,
502                                              in_scheme, label, &out_message,
503                                              delegate);
504  if (result) {
505    LOG(ERROR) << "Error performing RSA decrypt: " << GetErrorString(result);
506    return result;
507  }
508  plaintext->assign(StringFrom_TPM2B_PUBLIC_KEY_RSA(out_message));
509  return TPM_RC_SUCCESS;
510}
511
512TPM_RC TpmUtilityImpl::Sign(TPM_HANDLE key_handle,
513                            TPM_ALG_ID scheme,
514                            TPM_ALG_ID hash_alg,
515                            const std::string& plaintext,
516                            AuthorizationDelegate* delegate,
517                            std::string* signature) {
518  TPMT_SIG_SCHEME in_scheme;
519  if (hash_alg == TPM_ALG_NULL) {
520    hash_alg = TPM_ALG_SHA256;
521  }
522  if (scheme == TPM_ALG_RSAPSS) {
523    in_scheme.scheme = TPM_ALG_RSAPSS;
524    in_scheme.details.rsapss.hash_alg = hash_alg;
525  } else if (scheme == TPM_ALG_RSASSA || scheme == TPM_ALG_NULL) {
526    in_scheme.scheme = TPM_ALG_RSASSA;
527    in_scheme.details.rsassa.hash_alg = hash_alg;
528  } else {
529    LOG(ERROR) << "Invalid Signing scheme used.";
530    return SAPI_RC_BAD_PARAMETER;
531  }
532  TPM_RC result;
533  if (delegate == nullptr) {
534    result = SAPI_RC_INVALID_SESSIONS;
535    LOG(ERROR) << "This method needs a valid authorization delegate: "
536               << GetErrorString(result);
537    return result;
538  }
539  TPMT_PUBLIC public_area;
540  result = GetKeyPublicArea(key_handle, &public_area);
541  if (result) {
542    LOG(ERROR) << "Error finding public area for: " << key_handle;
543    return result;
544  } else if (public_area.type != TPM_ALG_RSA) {
545    LOG(ERROR) << "Key handle given is not an RSA key";
546    return SAPI_RC_BAD_PARAMETER;
547  } else if ((public_area.object_attributes & kSign) == 0) {
548    LOG(ERROR) << "Key handle given is not a signging key";
549    return SAPI_RC_BAD_PARAMETER;
550  } else if ((public_area.object_attributes & kRestricted) != 0) {
551    LOG(ERROR) << "Key handle references a restricted key";
552    return SAPI_RC_BAD_PARAMETER;
553  }
554
555  std::string key_name;
556  result = ComputeKeyName(public_area, &key_name);
557  if (result) {
558    LOG(ERROR) << "Error computing key name for: " << key_handle;
559    return result;
560  }
561  std::string digest = HashString(plaintext, hash_alg);
562  TPM2B_DIGEST tpm_digest = Make_TPM2B_DIGEST(digest);
563  TPMT_SIGNATURE signature_out;
564  TPMT_TK_HASHCHECK validation;
565  validation.tag = TPM_ST_HASHCHECK;
566  validation.hierarchy = TPM_RH_NULL;
567  validation.digest.size = 0;
568  result =
569      factory_.GetTpm()->SignSync(key_handle, key_name, tpm_digest, in_scheme,
570                                  validation, &signature_out, delegate);
571  if (result) {
572    LOG(ERROR) << "Error signing digest: " << GetErrorString(result);
573    return result;
574  }
575  if (scheme == TPM_ALG_RSAPSS) {
576    signature->resize(signature_out.signature.rsapss.sig.size);
577    signature->assign(
578        StringFrom_TPM2B_PUBLIC_KEY_RSA(signature_out.signature.rsapss.sig));
579  } else {
580    signature->resize(signature_out.signature.rsassa.sig.size);
581    signature->assign(
582        StringFrom_TPM2B_PUBLIC_KEY_RSA(signature_out.signature.rsassa.sig));
583  }
584  return TPM_RC_SUCCESS;
585}
586
587TPM_RC TpmUtilityImpl::Verify(TPM_HANDLE key_handle,
588                              TPM_ALG_ID scheme,
589                              TPM_ALG_ID hash_alg,
590                              const std::string& plaintext,
591                              const std::string& signature,
592                              AuthorizationDelegate* delegate) {
593  TPMT_PUBLIC public_area;
594  TPM_RC return_code = GetKeyPublicArea(key_handle, &public_area);
595  if (return_code) {
596    LOG(ERROR) << "Error finding public area for: " << key_handle;
597    return return_code;
598  } else if (public_area.type != TPM_ALG_RSA) {
599    LOG(ERROR) << "Key handle given is not an RSA key";
600    return SAPI_RC_BAD_PARAMETER;
601  } else if ((public_area.object_attributes & kSign) == 0) {
602    LOG(ERROR) << "Key handle given is not a signing key";
603    return SAPI_RC_BAD_PARAMETER;
604  } else if ((public_area.object_attributes & kRestricted) != 0) {
605    LOG(ERROR) << "Cannot use RSAPSS for signing with a restricted key";
606    return SAPI_RC_BAD_PARAMETER;
607  }
608  if (hash_alg == TPM_ALG_NULL) {
609    hash_alg = TPM_ALG_SHA256;
610  }
611
612  TPMT_SIGNATURE signature_in;
613  if (scheme == TPM_ALG_RSAPSS) {
614    signature_in.sig_alg = TPM_ALG_RSAPSS;
615    signature_in.signature.rsapss.hash = hash_alg;
616    signature_in.signature.rsapss.sig = Make_TPM2B_PUBLIC_KEY_RSA(signature);
617  } else if (scheme == TPM_ALG_NULL || scheme == TPM_ALG_RSASSA) {
618    signature_in.sig_alg = TPM_ALG_RSASSA;
619    signature_in.signature.rsassa.hash = hash_alg;
620    signature_in.signature.rsassa.sig = Make_TPM2B_PUBLIC_KEY_RSA(signature);
621  } else {
622    LOG(ERROR) << "Invalid scheme used to verify signature.";
623    return SAPI_RC_BAD_PARAMETER;
624  }
625  std::string key_name;
626  TPMT_TK_VERIFIED verified;
627  std::string digest = HashString(plaintext, hash_alg);
628  TPM2B_DIGEST tpm_digest = Make_TPM2B_DIGEST(digest);
629  return_code = factory_.GetTpm()->VerifySignatureSync(
630      key_handle, key_name, tpm_digest, signature_in, &verified, delegate);
631  if (return_code == TPM_RC_SIGNATURE) {
632    LOG(WARNING) << "Incorrect signature for given digest.";
633    return TPM_RC_SIGNATURE;
634  } else if (return_code && return_code != TPM_RC_SIGNATURE) {
635    LOG(ERROR) << "Error verifying signature: " << GetErrorString(return_code);
636    return return_code;
637  }
638  return TPM_RC_SUCCESS;
639}
640
641TPM_RC TpmUtilityImpl::CertifyCreation(TPM_HANDLE key_handle,
642                                       const std::string& creation_blob) {
643  TPM2B_CREATION_DATA creation_data;
644  TPM2B_DIGEST creation_hash;
645  TPMT_TK_CREATION creation_ticket;
646  if (!factory_.GetBlobParser()->ParseCreationBlob(
647          creation_blob, &creation_data, &creation_hash, &creation_ticket)) {
648    LOG(ERROR) << "Error parsing CreationBlob.";
649    return SAPI_RC_BAD_PARAMETER;
650  }
651  TPM2B_DATA qualifying_data;
652  qualifying_data.size = 0;
653  TPMT_SIG_SCHEME in_scheme;
654  in_scheme.scheme = TPM_ALG_NULL;
655  TPM2B_ATTEST certify_info;
656  TPMT_SIGNATURE signature;
657  scoped_ptr<AuthorizationDelegate> delegate =
658      factory_.GetPasswordAuthorization("");
659  TPM_RC result = factory_.GetTpm()->CertifyCreationSync(
660      TPM_RH_NULL, "", key_handle, "", qualifying_data, creation_hash,
661      in_scheme, creation_ticket, &certify_info, &signature, delegate.get());
662  if (result != TPM_RC_SUCCESS) {
663    LOG(ERROR) << "Error certifying key creation: " << GetErrorString(result);
664    return result;
665  }
666  return TPM_RC_SUCCESS;
667}
668
669TPM_RC TpmUtilityImpl::ChangeKeyAuthorizationData(
670    TPM_HANDLE key_handle,
671    const std::string& new_password,
672    AuthorizationDelegate* delegate,
673    std::string* key_blob) {
674  TPM_RC result;
675  if (delegate == nullptr) {
676    result = SAPI_RC_INVALID_SESSIONS;
677    LOG(ERROR) << "This method needs a valid authorization delegate: "
678               << GetErrorString(result);
679    return result;
680  }
681  std::string key_name;
682  std::string parent_name;
683  result = GetKeyName(key_handle, &key_name);
684  if (result != TPM_RC_SUCCESS) {
685    LOG(ERROR) << "Error getting Key name for key_handle: "
686               << GetErrorString(result);
687    return result;
688  }
689  result = GetKeyName(kRSAStorageRootKey, &parent_name);
690  if (result != TPM_RC_SUCCESS) {
691    LOG(ERROR) << "Error getting Key name for RSA-SRK: "
692               << GetErrorString(result);
693    return result;
694  }
695  TPM2B_AUTH new_auth = Make_TPM2B_DIGEST(new_password);
696  TPM2B_PRIVATE new_private_data;
697  new_private_data.size = 0;
698  result = factory_.GetTpm()->ObjectChangeAuthSync(
699      key_handle, key_name, kRSAStorageRootKey, parent_name, new_auth,
700      &new_private_data, delegate);
701  if (result != TPM_RC_SUCCESS) {
702    LOG(ERROR) << "Error changing object authorization data: "
703               << GetErrorString(result);
704    return result;
705  }
706  if (key_blob) {
707    TPMT_PUBLIC public_data;
708    result = GetKeyPublicArea(key_handle, &public_data);
709    if (result != TPM_RC_SUCCESS) {
710      return result;
711    }
712    if (!factory_.GetBlobParser()->SerializeKeyBlob(
713            Make_TPM2B_PUBLIC(public_data), new_private_data, key_blob)) {
714      return SAPI_RC_BAD_TCTI_STRUCTURE;
715    }
716  }
717  return TPM_RC_SUCCESS;
718}
719
720TPM_RC TpmUtilityImpl::ImportRSAKey(AsymmetricKeyUsage key_type,
721                                    const std::string& modulus,
722                                    uint32_t public_exponent,
723                                    const std::string& prime_factor,
724                                    const std::string& password,
725                                    AuthorizationDelegate* delegate,
726                                    std::string* key_blob) {
727  TPM_RC result;
728  if (delegate == nullptr) {
729    result = SAPI_RC_INVALID_SESSIONS;
730    LOG(ERROR) << "This method needs a valid authorization delegate: "
731               << GetErrorString(result);
732    return result;
733  }
734  std::string parent_name;
735  result = GetKeyName(kRSAStorageRootKey, &parent_name);
736  if (result != TPM_RC_SUCCESS) {
737    LOG(ERROR) << "Error getting Key name for RSA-SRK: "
738               << GetErrorString(result);
739    return result;
740  }
741  TPMT_PUBLIC public_area = CreateDefaultPublicArea(TPM_ALG_RSA);
742  public_area.object_attributes = kUserWithAuth | kNoDA;
743  switch (key_type) {
744    case AsymmetricKeyUsage::kDecryptKey:
745      public_area.object_attributes |= kDecrypt;
746      break;
747    case AsymmetricKeyUsage::kSignKey:
748      public_area.object_attributes |= kSign;
749      break;
750    case AsymmetricKeyUsage::kDecryptAndSignKey:
751      public_area.object_attributes |= (kSign | kDecrypt);
752      break;
753  }
754  public_area.parameters.rsa_detail.key_bits = modulus.size() * 8;
755  public_area.parameters.rsa_detail.exponent = public_exponent;
756  public_area.unique.rsa = Make_TPM2B_PUBLIC_KEY_RSA(modulus);
757  TPM2B_DATA encryption_key;
758  encryption_key.size = kAesKeySize;
759  CHECK_EQ(RAND_bytes(encryption_key.buffer, encryption_key.size), 1)
760      << "Error generating a cryptographically random Aes Key.";
761  TPM2B_PUBLIC public_data = Make_TPM2B_PUBLIC(public_area);
762  TPM2B_ENCRYPTED_SECRET in_sym_seed = Make_TPM2B_ENCRYPTED_SECRET("");
763  TPMT_SYM_DEF_OBJECT symmetric_alg;
764  symmetric_alg.algorithm = TPM_ALG_AES;
765  symmetric_alg.key_bits.aes = kAesKeySize * 8;
766  symmetric_alg.mode.aes = TPM_ALG_CFB;
767  TPMT_SENSITIVE in_sensitive;
768  in_sensitive.sensitive_type = TPM_ALG_RSA;
769  in_sensitive.auth_value = Make_TPM2B_DIGEST(password);
770  in_sensitive.seed_value = Make_TPM2B_DIGEST("");
771  in_sensitive.sensitive.rsa = Make_TPM2B_PRIVATE_KEY_RSA(prime_factor);
772  TPM2B_PRIVATE private_data;
773  result = EncryptPrivateData(in_sensitive, public_area, &private_data,
774                              &encryption_key);
775  if (result != TPM_RC_SUCCESS) {
776    LOG(ERROR) << "Error creating encrypted private struct: "
777               << GetErrorString(result);
778    return result;
779  }
780  TPM2B_PRIVATE tpm_private_data;
781  tpm_private_data.size = 0;
782  result = factory_.GetTpm()->ImportSync(
783      kRSAStorageRootKey, parent_name, encryption_key, public_data,
784      private_data, in_sym_seed, symmetric_alg, &tpm_private_data, delegate);
785  if (result != TPM_RC_SUCCESS) {
786    LOG(ERROR) << "Error importing key: " << GetErrorString(result);
787    return result;
788  }
789  if (key_blob) {
790    if (!factory_.GetBlobParser()->SerializeKeyBlob(
791            public_data, tpm_private_data, key_blob)) {
792      return SAPI_RC_BAD_TCTI_STRUCTURE;
793    }
794  }
795  return TPM_RC_SUCCESS;
796}
797
798TPM_RC TpmUtilityImpl::CreateRSAKeyPair(AsymmetricKeyUsage key_type,
799                                        int modulus_bits,
800                                        uint32_t public_exponent,
801                                        const std::string& password,
802                                        const std::string& policy_digest,
803                                        bool use_only_policy_authorization,
804                                        int creation_pcr_index,
805                                        AuthorizationDelegate* delegate,
806                                        std::string* key_blob,
807                                        std::string* creation_blob) {
808  CHECK(key_blob);
809  TPM_RC result;
810  if (delegate == nullptr) {
811    result = SAPI_RC_INVALID_SESSIONS;
812    LOG(ERROR) << "This method needs a valid authorization delegate: "
813               << GetErrorString(result);
814    return result;
815  }
816  std::string parent_name;
817  result = GetKeyName(kRSAStorageRootKey, &parent_name);
818  if (result != TPM_RC_SUCCESS) {
819    LOG(ERROR) << "Error getting Key name for RSA-SRK: "
820               << GetErrorString(result);
821    return result;
822  }
823  TPMT_PUBLIC public_area = CreateDefaultPublicArea(TPM_ALG_RSA);
824  public_area.auth_policy = Make_TPM2B_DIGEST(policy_digest);
825  public_area.object_attributes |=
826      (kSensitiveDataOrigin | kUserWithAuth | kNoDA);
827  switch (key_type) {
828    case AsymmetricKeyUsage::kDecryptKey:
829      public_area.object_attributes |= kDecrypt;
830      break;
831    case AsymmetricKeyUsage::kSignKey:
832      public_area.object_attributes |= kSign;
833      break;
834    case AsymmetricKeyUsage::kDecryptAndSignKey:
835      public_area.object_attributes |= (kSign | kDecrypt);
836      break;
837  }
838  if (use_only_policy_authorization && !policy_digest.empty()) {
839    public_area.object_attributes |= kAdminWithPolicy;
840    public_area.object_attributes &= (~kUserWithAuth);
841  }
842  public_area.parameters.rsa_detail.key_bits = modulus_bits;
843  public_area.parameters.rsa_detail.exponent = public_exponent;
844  TPML_PCR_SELECTION creation_pcrs = {};
845  if (creation_pcr_index == kNoCreationPCR) {
846    creation_pcrs.count = 0;
847  } else if (creation_pcr_index < 0 ||
848             creation_pcr_index > (PCR_SELECT_MIN * 8)) {
849    LOG(ERROR) << "Creation PCR index is not within the allocated bank.";
850    return SAPI_RC_BAD_PARAMETER;
851  } else {
852    creation_pcrs.count = 1;
853    creation_pcrs.pcr_selections[0].hash = TPM_ALG_SHA256;
854    creation_pcrs.pcr_selections[0].sizeof_select = PCR_SELECT_MIN;
855    creation_pcrs.pcr_selections[0].pcr_select[creation_pcr_index / 8] =
856        1 << (creation_pcr_index % 8);
857  }
858  TPMS_SENSITIVE_CREATE sensitive;
859  sensitive.user_auth = Make_TPM2B_DIGEST(password);
860  sensitive.data = Make_TPM2B_SENSITIVE_DATA("");
861  TPM2B_SENSITIVE_CREATE sensitive_create =
862      Make_TPM2B_SENSITIVE_CREATE(sensitive);
863  TPM2B_DATA outside_info = Make_TPM2B_DATA("");
864  TPM2B_PUBLIC out_public;
865  out_public.size = 0;
866  TPM2B_PRIVATE out_private;
867  out_private.size = 0;
868  TPM2B_CREATION_DATA creation_data;
869  TPM2B_DIGEST creation_hash;
870  TPMT_TK_CREATION creation_ticket;
871  result = factory_.GetTpm()->CreateSync(
872      kRSAStorageRootKey, parent_name, sensitive_create,
873      Make_TPM2B_PUBLIC(public_area), outside_info, creation_pcrs, &out_private,
874      &out_public, &creation_data, &creation_hash, &creation_ticket, delegate);
875  if (result != TPM_RC_SUCCESS) {
876    LOG(ERROR) << "Error creating RSA key: " << GetErrorString(result);
877    return result;
878  }
879  if (!factory_.GetBlobParser()->SerializeKeyBlob(out_public, out_private,
880                                                  key_blob)) {
881    return SAPI_RC_BAD_TCTI_STRUCTURE;
882  }
883  if (creation_blob) {
884    if (!factory_.GetBlobParser()->SerializeCreationBlob(
885            creation_data, creation_hash, creation_ticket, creation_blob)) {
886      return SAPI_RC_BAD_TCTI_STRUCTURE;
887    }
888  }
889  return TPM_RC_SUCCESS;
890}
891
892TPM_RC TpmUtilityImpl::LoadKey(const std::string& key_blob,
893                               AuthorizationDelegate* delegate,
894                               TPM_HANDLE* key_handle) {
895  CHECK(key_handle);
896  TPM_RC result;
897  if (delegate == nullptr) {
898    result = SAPI_RC_INVALID_SESSIONS;
899    LOG(ERROR) << "This method needs a valid authorization delegate: "
900               << GetErrorString(result);
901    return result;
902  }
903  std::string parent_name;
904  result = GetKeyName(kRSAStorageRootKey, &parent_name);
905  if (result != TPM_RC_SUCCESS) {
906    LOG(ERROR) << "Error getting parent key name: " << GetErrorString(result);
907    return result;
908  }
909  TPM2B_PUBLIC in_public;
910  TPM2B_PRIVATE in_private;
911  if (!factory_.GetBlobParser()->ParseKeyBlob(key_blob, &in_public,
912                                              &in_private)) {
913    return SAPI_RC_BAD_TCTI_STRUCTURE;
914  }
915  TPM2B_NAME key_name;
916  key_name.size = 0;
917  result =
918      factory_.GetTpm()->LoadSync(kRSAStorageRootKey, parent_name, in_private,
919                                  in_public, key_handle, &key_name, delegate);
920  if (result != TPM_RC_SUCCESS) {
921    LOG(ERROR) << "Error loading key: " << GetErrorString(result);
922    return result;
923  }
924  return TPM_RC_SUCCESS;
925}
926
927TPM_RC TpmUtilityImpl::GetKeyName(TPM_HANDLE handle, std::string* name) {
928  CHECK(name);
929  TPM_RC result;
930  TPMT_PUBLIC public_data;
931  result = GetKeyPublicArea(handle, &public_data);
932  if (result != TPM_RC_SUCCESS) {
933    LOG(ERROR) << "Error fetching public info: " << GetErrorString(result);
934    return result;
935  }
936  result = ComputeKeyName(public_data, name);
937  if (result != TPM_RC_SUCCESS) {
938    LOG(ERROR) << "Error computing key name: " << GetErrorString(result);
939    return TPM_RC_SUCCESS;
940  }
941  return TPM_RC_SUCCESS;
942}
943
944TPM_RC TpmUtilityImpl::GetKeyPublicArea(TPM_HANDLE handle,
945                                        TPMT_PUBLIC* public_data) {
946  CHECK(public_data);
947  TPM2B_NAME out_name;
948  TPM2B_PUBLIC public_area;
949  TPM2B_NAME qualified_name;
950  std::string handle_name;  // Unused
951  TPM_RC return_code = factory_.GetTpm()->ReadPublicSync(
952      handle, handle_name, &public_area, &out_name, &qualified_name, nullptr);
953  if (return_code) {
954    LOG(ERROR) << "Error getting public area for object: " << handle;
955    return return_code;
956  }
957  *public_data = public_area.public_area;
958  return TPM_RC_SUCCESS;
959}
960
961TPM_RC TpmUtilityImpl::SealData(const std::string& data_to_seal,
962                                const std::string& policy_digest,
963                                AuthorizationDelegate* delegate,
964                                std::string* sealed_data) {
965  CHECK(sealed_data);
966  TPM_RC result;
967  if (delegate == nullptr) {
968    result = SAPI_RC_INVALID_SESSIONS;
969    LOG(ERROR) << "This method needs a valid authorization delegate: "
970               << GetErrorString(result);
971    return result;
972  }
973  std::string parent_name;
974  result = GetKeyName(kRSAStorageRootKey, &parent_name);
975  if (result != TPM_RC_SUCCESS) {
976    LOG(ERROR) << "Error getting Key name for RSA-SRK: "
977               << GetErrorString(result);
978    return result;
979  }
980  // We seal data to the TPM by creating a KEYEDHASH object with sign and
981  // decrypt attributes disabled.
982  TPMT_PUBLIC public_area = CreateDefaultPublicArea(TPM_ALG_KEYEDHASH);
983  public_area.auth_policy = Make_TPM2B_DIGEST(policy_digest);
984  public_area.object_attributes = kAdminWithPolicy | kNoDA;
985  public_area.unique.keyed_hash.size = 0;
986  TPML_PCR_SELECTION creation_pcrs = {};
987  TPMS_SENSITIVE_CREATE sensitive;
988  sensitive.user_auth = Make_TPM2B_DIGEST("");
989  sensitive.data = Make_TPM2B_SENSITIVE_DATA(data_to_seal);
990  TPM2B_SENSITIVE_CREATE sensitive_create =
991      Make_TPM2B_SENSITIVE_CREATE(sensitive);
992  TPM2B_DATA outside_info = Make_TPM2B_DATA("");
993  TPM2B_PUBLIC out_public;
994  out_public.size = 0;
995  TPM2B_PRIVATE out_private;
996  out_private.size = 0;
997  TPM2B_CREATION_DATA creation_data;
998  TPM2B_DIGEST creation_hash;
999  TPMT_TK_CREATION creation_ticket;
1000  result = factory_.GetTpm()->CreateSync(
1001      kRSAStorageRootKey, parent_name, sensitive_create,
1002      Make_TPM2B_PUBLIC(public_area), outside_info, creation_pcrs, &out_private,
1003      &out_public, &creation_data, &creation_hash, &creation_ticket, delegate);
1004  if (result != TPM_RC_SUCCESS) {
1005    LOG(ERROR) << "Error creating sealed object: " << GetErrorString(result);
1006    return result;
1007  }
1008  if (!factory_.GetBlobParser()->SerializeKeyBlob(out_public, out_private,
1009                                                  sealed_data)) {
1010    return SAPI_RC_BAD_TCTI_STRUCTURE;
1011  }
1012  return TPM_RC_SUCCESS;
1013}
1014
1015TPM_RC TpmUtilityImpl::UnsealData(const std::string& sealed_data,
1016                                  AuthorizationDelegate* delegate,
1017                                  std::string* unsealed_data) {
1018  CHECK(unsealed_data);
1019  TPM_RC result;
1020  if (delegate == nullptr) {
1021    result = SAPI_RC_INVALID_SESSIONS;
1022    LOG(ERROR) << "This method needs a valid authorization delegate: "
1023               << GetErrorString(result);
1024    return result;
1025  }
1026  TPM_HANDLE object_handle;
1027  scoped_ptr<AuthorizationDelegate> password_delegate =
1028      factory_.GetPasswordAuthorization("");
1029  result = LoadKey(sealed_data, password_delegate.get(), &object_handle);
1030  if (result != TPM_RC_SUCCESS) {
1031    LOG(ERROR) << "Error loading sealed object: " << GetErrorString(result);
1032    return result;
1033  }
1034  ScopedKeyHandle sealed_object(factory_, object_handle);
1035  std::string object_name;
1036  result = GetKeyName(sealed_object.get(), &object_name);
1037  if (result != TPM_RC_SUCCESS) {
1038    LOG(ERROR) << "Error getting object name: " << GetErrorString(result);
1039    return result;
1040  }
1041  TPM2B_SENSITIVE_DATA out_data;
1042  result = factory_.GetTpm()->UnsealSync(sealed_object.get(), object_name,
1043                                         &out_data, delegate);
1044  if (result != TPM_RC_SUCCESS) {
1045    LOG(ERROR) << "Error unsealing object: " << GetErrorString(result);
1046    return result;
1047  }
1048  *unsealed_data = StringFrom_TPM2B_SENSITIVE_DATA(out_data);
1049  return TPM_RC_SUCCESS;
1050}
1051
1052TPM_RC TpmUtilityImpl::StartSession(HmacSession* session) {
1053  TPM_RC result = session->StartUnboundSession(true /* enable_encryption */);
1054  if (result != TPM_RC_SUCCESS) {
1055    LOG(ERROR) << "Error starting unbound session: " << GetErrorString(result);
1056    return result;
1057  }
1058  session->SetEntityAuthorizationValue("");
1059  return TPM_RC_SUCCESS;
1060}
1061
1062TPM_RC TpmUtilityImpl::GetPolicyDigestForPcrValue(int pcr_index,
1063                                                  const std::string& pcr_value,
1064                                                  std::string* policy_digest) {
1065  CHECK(policy_digest);
1066  scoped_ptr<PolicySession> session = factory_.GetTrialSession();
1067  TPM_RC result = session->StartUnboundSession(false);
1068  if (result != TPM_RC_SUCCESS) {
1069    LOG(ERROR) << "Error starting unbound trial session: "
1070               << GetErrorString(result);
1071    return result;
1072  }
1073  std::string mutable_pcr_value;
1074  if (pcr_value.empty()) {
1075    result = ReadPCR(pcr_index, &mutable_pcr_value);
1076    if (result != TPM_RC_SUCCESS) {
1077      LOG(ERROR) << "Error reading pcr_value: " << GetErrorString(result);
1078      return result;
1079    }
1080  } else {
1081    mutable_pcr_value = pcr_value;
1082  }
1083  result = session->PolicyPCR(pcr_index, mutable_pcr_value);
1084  if (result != TPM_RC_SUCCESS) {
1085    LOG(ERROR) << "Error restricting policy to PCR value: "
1086               << GetErrorString(result);
1087    return result;
1088  }
1089  result = session->GetDigest(policy_digest);
1090  if (result != TPM_RC_SUCCESS) {
1091    LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result);
1092    return result;
1093  }
1094  return TPM_RC_SUCCESS;
1095}
1096
1097TPM_RC TpmUtilityImpl::DefineNVSpace(uint32_t index,
1098                                     size_t num_bytes,
1099                                     AuthorizationDelegate* delegate) {
1100  TPM_RC result;
1101  if (num_bytes > MAX_NV_INDEX_SIZE) {
1102    result = SAPI_RC_BAD_SIZE;
1103    LOG(ERROR) << "Cannot define non-volatile space of given size: "
1104               << GetErrorString(result);
1105    return result;
1106  }
1107  if (index > kMaxNVSpaceIndex) {
1108    result = SAPI_RC_BAD_PARAMETER;
1109    LOG(ERROR) << "Cannot define non-volatile space with the given index: "
1110               << GetErrorString(result);
1111    return result;
1112  }
1113  if (delegate == nullptr) {
1114    result = SAPI_RC_INVALID_SESSIONS;
1115    LOG(ERROR) << "This method needs a valid authorization delegate: "
1116               << GetErrorString(result);
1117    return result;
1118  }
1119  uint32_t nv_index = NV_INDEX_FIRST + index;
1120  TPMS_NV_PUBLIC public_data;
1121  public_data.nv_index = nv_index;
1122  public_data.name_alg = TPM_ALG_SHA256;
1123  // We define the following attributes for NVSpaces created:
1124  // TPMA_NV_NO_DA: Dictionary attack does not trigger on authorization errors.
1125  // TPMA_NV_OWNERWRITE: Owner authorization must be provided on write actions.
1126  // TPMA_NV_WRITEDEFINE: NVSpace is write lockable, and lock persists across
1127  //                      reboot.
1128  // TPMA_NV_AUTHREAD: The index authValue (default: "") can be used to
1129  //                   authorize read actions.
1130  public_data.attributes = TPMA_NV_NO_DA | TPMA_NV_OWNERWRITE |
1131                           TPMA_NV_WRITEDEFINE | TPMA_NV_AUTHREAD;
1132  public_data.auth_policy = Make_TPM2B_DIGEST("");
1133  public_data.data_size = num_bytes;
1134  TPM2B_AUTH authorization = Make_TPM2B_DIGEST("");
1135  TPM2B_NV_PUBLIC public_area = Make_TPM2B_NV_PUBLIC(public_data);
1136  result = factory_.GetTpm()->NV_DefineSpaceSync(
1137      TPM_RH_OWNER, NameFromHandle(TPM_RH_OWNER), authorization, public_area,
1138      delegate);
1139  if (result != TPM_RC_SUCCESS) {
1140    LOG(ERROR) << "Error defining non-volatile space: "
1141               << GetErrorString(result);
1142    return result;
1143  }
1144  nvram_public_area_map_[index] = public_data;
1145  return TPM_RC_SUCCESS;
1146}
1147
1148TPM_RC TpmUtilityImpl::DestroyNVSpace(uint32_t index,
1149                                      AuthorizationDelegate* delegate) {
1150  TPM_RC result;
1151  if (index > kMaxNVSpaceIndex) {
1152    result = SAPI_RC_BAD_PARAMETER;
1153    LOG(ERROR) << "Cannot undefine non-volatile space with the given index: "
1154               << GetErrorString(result);
1155    return result;
1156  }
1157  if (delegate == nullptr) {
1158    result = SAPI_RC_INVALID_SESSIONS;
1159    LOG(ERROR) << "This method needs a valid authorization delegate: "
1160               << GetErrorString(result);
1161    return result;
1162  }
1163  std::string nv_name;
1164  result = GetNVSpaceName(index, &nv_name);
1165  if (result != TPM_RC_SUCCESS) {
1166    return result;
1167  }
1168  uint32_t nv_index = NV_INDEX_FIRST + index;
1169  result = factory_.GetTpm()->NV_UndefineSpaceSync(
1170      TPM_RH_OWNER, NameFromHandle(TPM_RH_OWNER), nv_index, nv_name, delegate);
1171  if (result != TPM_RC_SUCCESS) {
1172    LOG(ERROR) << "Error undefining non-volatile space: "
1173               << GetErrorString(result);
1174    return result;
1175  }
1176  nvram_public_area_map_.erase(index);
1177  return TPM_RC_SUCCESS;
1178}
1179
1180TPM_RC TpmUtilityImpl::LockNVSpace(uint32_t index,
1181                                   AuthorizationDelegate* delegate) {
1182  TPM_RC result;
1183  if (index > kMaxNVSpaceIndex) {
1184    result = SAPI_RC_BAD_PARAMETER;
1185    LOG(ERROR) << "Cannot lock non-volatile space with the given index: "
1186               << GetErrorString(result);
1187    return result;
1188  }
1189  if (delegate == nullptr) {
1190    result = SAPI_RC_INVALID_SESSIONS;
1191    LOG(ERROR) << "This method needs a valid authorization delegate: "
1192               << GetErrorString(result);
1193    return result;
1194  }
1195  std::string nv_name;
1196  result = GetNVSpaceName(index, &nv_name);
1197  if (result != TPM_RC_SUCCESS) {
1198    return result;
1199  }
1200  uint32_t nv_index = NV_INDEX_FIRST + index;
1201  result = factory_.GetTpm()->NV_WriteLockSync(
1202      TPM_RH_OWNER, NameFromHandle(TPM_RH_OWNER), nv_index, nv_name, delegate);
1203  if (result != TPM_RC_SUCCESS) {
1204    LOG(ERROR) << "Error locking non-volatile spaces: "
1205               << GetErrorString(result);
1206    return result;
1207  }
1208  auto it = nvram_public_area_map_.find(index);
1209  if (it != nvram_public_area_map_.end()) {
1210    it->second.attributes |= TPMA_NV_WRITELOCKED;
1211  }
1212  return TPM_RC_SUCCESS;
1213}
1214
1215TPM_RC TpmUtilityImpl::WriteNVSpace(uint32_t index,
1216                                    uint32_t offset,
1217                                    const std::string& nvram_data,
1218                                    AuthorizationDelegate* delegate) {
1219  TPM_RC result;
1220  if (nvram_data.size() > MAX_NV_BUFFER_SIZE) {
1221    result = SAPI_RC_BAD_SIZE;
1222    LOG(ERROR) << "Insufficient buffer for non-volatile write: "
1223               << GetErrorString(result);
1224    return result;
1225  }
1226  if (index > kMaxNVSpaceIndex) {
1227    result = SAPI_RC_BAD_PARAMETER;
1228    LOG(ERROR) << "Cannot write to non-volatile space with the given index: "
1229               << GetErrorString(result);
1230    return result;
1231  }
1232  if (delegate == nullptr) {
1233    result = SAPI_RC_INVALID_SESSIONS;
1234    LOG(ERROR) << "This method needs a valid authorization delegate: "
1235               << GetErrorString(result);
1236    return result;
1237  }
1238  std::string nv_name;
1239  result = GetNVSpaceName(index, &nv_name);
1240  if (result != TPM_RC_SUCCESS) {
1241    return result;
1242  }
1243  uint32_t nv_index = NV_INDEX_FIRST + index;
1244  result = factory_.GetTpm()->NV_WriteSync(
1245      TPM_RH_OWNER, NameFromHandle(TPM_RH_OWNER), nv_index, nv_name,
1246      Make_TPM2B_MAX_NV_BUFFER(nvram_data), offset, delegate);
1247  if (result != TPM_RC_SUCCESS) {
1248    LOG(ERROR) << "Error writing to non-volatile space: "
1249               << GetErrorString(result);
1250    return result;
1251  }
1252  auto it = nvram_public_area_map_.find(index);
1253  if (it != nvram_public_area_map_.end()) {
1254    it->second.attributes |= TPMA_NV_WRITTEN;
1255  }
1256  return TPM_RC_SUCCESS;
1257}
1258
1259TPM_RC TpmUtilityImpl::ReadNVSpace(uint32_t index,
1260                                   uint32_t offset,
1261                                   size_t num_bytes,
1262                                   std::string* nvram_data,
1263                                   AuthorizationDelegate* delegate) {
1264  TPM_RC result;
1265  if (num_bytes > MAX_NV_BUFFER_SIZE) {
1266    result = SAPI_RC_BAD_SIZE;
1267    LOG(ERROR) << "Insufficient buffer for non-volatile read: "
1268               << GetErrorString(result);
1269    return result;
1270  }
1271  if (index > kMaxNVSpaceIndex) {
1272    result = SAPI_RC_BAD_PARAMETER;
1273    LOG(ERROR) << "Cannot read from non-volatile space with the given index: "
1274               << GetErrorString(result);
1275    return result;
1276  }
1277  if (delegate == nullptr) {
1278    result = SAPI_RC_INVALID_SESSIONS;
1279    LOG(ERROR) << "This method needs a valid authorization delegate: "
1280               << GetErrorString(result);
1281    return result;
1282  }
1283  std::string nv_name;
1284  result = GetNVSpaceName(index, &nv_name);
1285  if (result != TPM_RC_SUCCESS) {
1286    return result;
1287  }
1288  uint32_t nv_index = NV_INDEX_FIRST + index;
1289  TPM2B_MAX_NV_BUFFER data_buffer;
1290  data_buffer.size = 0;
1291  result =
1292      factory_.GetTpm()->NV_ReadSync(nv_index, nv_name, nv_index, nv_name,
1293                                     num_bytes, offset, &data_buffer, delegate);
1294  if (result != TPM_RC_SUCCESS) {
1295    LOG(ERROR) << "Error reading from non-volatile space: "
1296               << GetErrorString(result);
1297    return result;
1298  }
1299  nvram_data->assign(StringFrom_TPM2B_MAX_NV_BUFFER(data_buffer));
1300  return TPM_RC_SUCCESS;
1301}
1302
1303TPM_RC TpmUtilityImpl::GetNVSpaceName(uint32_t index, std::string* name) {
1304  TPM_RC result;
1305  if (index > kMaxNVSpaceIndex) {
1306    result = SAPI_RC_BAD_PARAMETER;
1307    LOG(ERROR) << "Cannot read from non-volatile space with the given index: "
1308               << GetErrorString(result);
1309    return result;
1310  }
1311  TPMS_NV_PUBLIC nv_public_data;
1312  result = GetNVSpacePublicArea(index, &nv_public_data);
1313  if (result != TPM_RC_SUCCESS) {
1314    return result;
1315  }
1316  result = ComputeNVSpaceName(nv_public_data, name);
1317  if (result != TPM_RC_SUCCESS) {
1318    return result;
1319  }
1320  return TPM_RC_SUCCESS;
1321}
1322
1323TPM_RC TpmUtilityImpl::GetNVSpacePublicArea(uint32_t index,
1324                                            TPMS_NV_PUBLIC* public_data) {
1325  TPM_RC result;
1326  if (index > kMaxNVSpaceIndex) {
1327    result = SAPI_RC_BAD_PARAMETER;
1328    LOG(ERROR) << "Cannot read from non-volatile space with the given index: "
1329               << GetErrorString(result);
1330    return result;
1331  }
1332  auto it = nvram_public_area_map_.find(index);
1333  if (it != nvram_public_area_map_.end()) {
1334    *public_data = it->second;
1335    return TPM_RC_SUCCESS;
1336  }
1337  TPM2B_NAME nvram_name;
1338  TPM2B_NV_PUBLIC public_area;
1339  public_area.nv_public.nv_index = 0;
1340  uint32_t nv_index = NV_INDEX_FIRST + index;
1341  result = factory_.GetTpm()->NV_ReadPublicSync(nv_index, "", &public_area,
1342                                                &nvram_name, nullptr);
1343  if (result != TPM_RC_SUCCESS) {
1344    LOG(ERROR) << "Error reading non-volatile space public information: "
1345               << GetErrorString(result);
1346    return result;
1347  }
1348  *public_data = public_area.nv_public;
1349  nvram_public_area_map_[index] = public_area.nv_public;
1350  return TPM_RC_SUCCESS;
1351}
1352
1353TPM_RC TpmUtilityImpl::SetKnownOwnerPassword(
1354    const std::string& known_owner_password) {
1355  scoped_ptr<TpmState> tpm_state(factory_.GetTpmState());
1356  TPM_RC result = tpm_state->Initialize();
1357  if (result) {
1358    LOG(ERROR) << __func__ << ": " << GetErrorString(result);
1359    return result;
1360  }
1361  scoped_ptr<AuthorizationDelegate> delegate =
1362      factory_.GetPasswordAuthorization("");
1363  if (tpm_state->IsOwnerPasswordSet()) {
1364    LOG(INFO) << "Owner password is already set. "
1365              << "This is normal if ownership is already taken.";
1366    return TPM_RC_SUCCESS;
1367  }
1368  result = SetHierarchyAuthorization(TPM_RH_OWNER, known_owner_password,
1369                                     delegate.get());
1370  if (result) {
1371    LOG(ERROR) << "Error setting storage hierarchy authorization "
1372               << "to its default value: " << GetErrorString(result);
1373    return result;
1374  }
1375  return TPM_RC_SUCCESS;
1376}
1377
1378TPM_RC TpmUtilityImpl::CreateStorageRootKeys(
1379    const std::string& owner_password) {
1380  TPM_RC result = TPM_RC_SUCCESS;
1381  scoped_ptr<TpmState> tpm_state(factory_.GetTpmState());
1382  result = tpm_state->Initialize();
1383  if (result) {
1384    LOG(ERROR) << __func__ << ": " << GetErrorString(result);
1385    return result;
1386  }
1387  Tpm* tpm = factory_.GetTpm();
1388  TPML_PCR_SELECTION creation_pcrs;
1389  creation_pcrs.count = 0;
1390  TPMS_SENSITIVE_CREATE sensitive;
1391  sensitive.user_auth = Make_TPM2B_DIGEST("");
1392  sensitive.data = Make_TPM2B_SENSITIVE_DATA("");
1393  TPM_HANDLE object_handle;
1394  TPM2B_CREATION_DATA creation_data;
1395  TPM2B_DIGEST creation_digest;
1396  TPMT_TK_CREATION creation_ticket;
1397  TPM2B_NAME object_name;
1398  object_name.size = 0;
1399  scoped_ptr<AuthorizationDelegate> delegate =
1400      factory_.GetPasswordAuthorization(owner_password);
1401  if (tpm_state->IsRSASupported()) {
1402    bool exists = false;
1403    result = DoesPersistentKeyExist(kRSAStorageRootKey, &exists);
1404    if (result) {
1405      return result;
1406    }
1407    if (!exists) {
1408      TPMT_PUBLIC public_area = CreateDefaultPublicArea(TPM_ALG_RSA);
1409      public_area.object_attributes |= (kSensitiveDataOrigin | kUserWithAuth |
1410                                        kNoDA | kRestricted | kDecrypt);
1411      public_area.parameters.rsa_detail.symmetric.algorithm = TPM_ALG_AES;
1412      public_area.parameters.rsa_detail.symmetric.key_bits.aes = 128;
1413      public_area.parameters.rsa_detail.symmetric.mode.aes = TPM_ALG_CFB;
1414      TPM2B_PUBLIC rsa_public_area = Make_TPM2B_PUBLIC(public_area);
1415      result = tpm->CreatePrimarySync(
1416          TPM_RH_OWNER, NameFromHandle(TPM_RH_OWNER),
1417          Make_TPM2B_SENSITIVE_CREATE(sensitive), rsa_public_area,
1418          Make_TPM2B_DATA(""), creation_pcrs, &object_handle, &rsa_public_area,
1419          &creation_data, &creation_digest, &creation_ticket, &object_name,
1420          delegate.get());
1421      if (result) {
1422        LOG(ERROR) << __func__ << ": " << GetErrorString(result);
1423        return result;
1424      }
1425      ScopedKeyHandle rsa_key(factory_, object_handle);
1426      // This will make the key persistent.
1427      result = tpm->EvictControlSync(TPM_RH_OWNER, NameFromHandle(TPM_RH_OWNER),
1428                                     object_handle,
1429                                     StringFrom_TPM2B_NAME(object_name),
1430                                     kRSAStorageRootKey, delegate.get());
1431      if (result != TPM_RC_SUCCESS) {
1432        LOG(ERROR) << __func__ << ": " << GetErrorString(result);
1433        return result;
1434      }
1435      LOG(INFO) << "Created RSA SRK.";
1436    } else {
1437      LOG(INFO) << "Skip RSA SRK because it already exists.";
1438    }
1439  } else {
1440    LOG(INFO) << "Skip RSA SRK because RSA is not supported.";
1441  }
1442
1443  // Do it again for ECC.
1444  if (tpm_state->IsRSASupported()) {
1445    bool exists = false;
1446    result = DoesPersistentKeyExist(kECCStorageRootKey, &exists);
1447    if (result) {
1448      return result;
1449    }
1450    if (!exists) {
1451      TPMT_PUBLIC public_area = CreateDefaultPublicArea(TPM_ALG_ECC);
1452      public_area.object_attributes |= (kSensitiveDataOrigin | kUserWithAuth |
1453                                        kNoDA | kRestricted | kDecrypt);
1454      public_area.parameters.ecc_detail.symmetric.algorithm = TPM_ALG_AES;
1455      public_area.parameters.ecc_detail.symmetric.key_bits.aes = 128;
1456      public_area.parameters.ecc_detail.symmetric.mode.aes = TPM_ALG_CFB;
1457      TPM2B_PUBLIC ecc_public_area = Make_TPM2B_PUBLIC(public_area);
1458      result = tpm->CreatePrimarySync(
1459          TPM_RH_OWNER, NameFromHandle(TPM_RH_OWNER),
1460          Make_TPM2B_SENSITIVE_CREATE(sensitive), ecc_public_area,
1461          Make_TPM2B_DATA(""), creation_pcrs, &object_handle, &ecc_public_area,
1462          &creation_data, &creation_digest, &creation_ticket, &object_name,
1463          delegate.get());
1464      if (result) {
1465        LOG(ERROR) << __func__ << ": " << GetErrorString(result);
1466        return result;
1467      }
1468      ScopedKeyHandle ecc_key(factory_, object_handle);
1469      // This will make the key persistent.
1470      result = tpm->EvictControlSync(TPM_RH_OWNER, NameFromHandle(TPM_RH_OWNER),
1471                                     object_handle,
1472                                     StringFrom_TPM2B_NAME(object_name),
1473                                     kECCStorageRootKey, delegate.get());
1474      if (result != TPM_RC_SUCCESS) {
1475        LOG(ERROR) << __func__ << ": " << GetErrorString(result);
1476        return result;
1477      }
1478      LOG(INFO) << "Created ECC SRK.";
1479    } else {
1480      LOG(INFO) << "Skip ECC SRK because it already exists.";
1481    }
1482  } else {
1483    LOG(INFO) << "Skip ECC SRK because ECC is not supported.";
1484  }
1485  return TPM_RC_SUCCESS;
1486}
1487
1488TPM_RC TpmUtilityImpl::CreateSaltingKey(const std::string& owner_password) {
1489  bool exists = false;
1490  TPM_RC result = DoesPersistentKeyExist(kSaltingKey, &exists);
1491  if (result != TPM_RC_SUCCESS) {
1492    return result;
1493  }
1494  if (exists) {
1495    LOG(INFO) << "Salting key already exists.";
1496    return TPM_RC_SUCCESS;
1497  }
1498  std::string parent_name;
1499  result = GetKeyName(kRSAStorageRootKey, &parent_name);
1500  if (result != TPM_RC_SUCCESS) {
1501    LOG(ERROR) << "Error getting Key name for RSA-SRK: "
1502               << GetErrorString(result);
1503    return result;
1504  }
1505  TPMT_PUBLIC public_area = CreateDefaultPublicArea(TPM_ALG_RSA);
1506  public_area.name_alg = TPM_ALG_SHA256;
1507  public_area.object_attributes |=
1508      kSensitiveDataOrigin | kUserWithAuth | kNoDA | kDecrypt;
1509  TPML_PCR_SELECTION creation_pcrs;
1510  creation_pcrs.count = 0;
1511  TPMS_SENSITIVE_CREATE sensitive;
1512  sensitive.user_auth = Make_TPM2B_DIGEST("");
1513  sensitive.data = Make_TPM2B_SENSITIVE_DATA("");
1514  TPM2B_SENSITIVE_CREATE sensitive_create =
1515      Make_TPM2B_SENSITIVE_CREATE(sensitive);
1516  TPM2B_DATA outside_info = Make_TPM2B_DATA("");
1517
1518  TPM2B_PRIVATE out_private;
1519  out_private.size = 0;
1520  TPM2B_PUBLIC out_public;
1521  out_public.size = 0;
1522  TPM2B_CREATION_DATA creation_data;
1523  TPM2B_DIGEST creation_hash;
1524  TPMT_TK_CREATION creation_ticket;
1525  // TODO(usanghi): MITM vulnerability with SaltingKey creation.
1526  // Currently we cannot verify the key returned by the TPM.
1527  // crbug.com/442331
1528  scoped_ptr<AuthorizationDelegate> delegate =
1529      factory_.GetPasswordAuthorization("");
1530  result = factory_.GetTpm()->CreateSync(
1531      kRSAStorageRootKey, parent_name, sensitive_create,
1532      Make_TPM2B_PUBLIC(public_area), outside_info, creation_pcrs, &out_private,
1533      &out_public, &creation_data, &creation_hash, &creation_ticket,
1534      delegate.get());
1535  if (result != TPM_RC_SUCCESS) {
1536    LOG(ERROR) << "Error creating salting key: " << GetErrorString(result);
1537    return result;
1538  }
1539  TPM2B_NAME key_name;
1540  key_name.size = 0;
1541  TPM_HANDLE key_handle;
1542  result = factory_.GetTpm()->LoadSync(kRSAStorageRootKey, parent_name,
1543                                       out_private, out_public, &key_handle,
1544                                       &key_name, delegate.get());
1545  if (result != TPM_RC_SUCCESS) {
1546    LOG(ERROR) << "Error loading salting key: " << GetErrorString(result);
1547    return result;
1548  }
1549  ScopedKeyHandle key(factory_, key_handle);
1550  scoped_ptr<AuthorizationDelegate> owner_delegate =
1551      factory_.GetPasswordAuthorization(owner_password);
1552  result = factory_.GetTpm()->EvictControlSync(
1553      TPM_RH_OWNER, NameFromHandle(TPM_RH_OWNER), key_handle,
1554      StringFrom_TPM2B_NAME(key_name), kSaltingKey, owner_delegate.get());
1555  if (result != TPM_RC_SUCCESS) {
1556    LOG(ERROR) << __func__ << ": " << GetErrorString(result);
1557    return result;
1558  }
1559  return TPM_RC_SUCCESS;
1560}
1561
1562TPMT_PUBLIC TpmUtilityImpl::CreateDefaultPublicArea(TPM_ALG_ID key_alg) {
1563  TPMT_PUBLIC public_area;
1564  public_area.name_alg = TPM_ALG_SHA256;
1565  public_area.auth_policy = Make_TPM2B_DIGEST("");
1566  public_area.object_attributes = kFixedTPM | kFixedParent;
1567  if (key_alg == TPM_ALG_RSA) {
1568    public_area.type = TPM_ALG_RSA;
1569    public_area.parameters.rsa_detail.scheme.scheme = TPM_ALG_NULL;
1570    public_area.parameters.rsa_detail.symmetric.algorithm = TPM_ALG_NULL;
1571    public_area.parameters.rsa_detail.key_bits = 2048;
1572    public_area.parameters.rsa_detail.exponent = 0;
1573    public_area.unique.rsa = Make_TPM2B_PUBLIC_KEY_RSA("");
1574  } else if (key_alg == TPM_ALG_ECC) {
1575    public_area.type = TPM_ALG_ECC;
1576    public_area.parameters.ecc_detail.curve_id = TPM_ECC_NIST_P256;
1577    public_area.parameters.ecc_detail.kdf.scheme = TPM_ALG_NULL;
1578    public_area.unique.ecc.x = Make_TPM2B_ECC_PARAMETER("");
1579    public_area.unique.ecc.y = Make_TPM2B_ECC_PARAMETER("");
1580  } else if (key_alg == TPM_ALG_KEYEDHASH) {
1581    public_area.type = TPM_ALG_KEYEDHASH;
1582    public_area.parameters.keyed_hash_detail.scheme.scheme = TPM_ALG_NULL;
1583  } else {
1584    LOG(WARNING) << "Unrecognized key_type. Not filling parameters.";
1585  }
1586  return public_area;
1587}
1588
1589TPM_RC TpmUtilityImpl::SetHierarchyAuthorization(
1590    TPMI_RH_HIERARCHY_AUTH hierarchy,
1591    const std::string& password,
1592    AuthorizationDelegate* authorization) {
1593  if (password.size() > kMaxPasswordLength) {
1594    LOG(ERROR) << "Hierarchy passwords can be at most " << kMaxPasswordLength
1595               << " bytes. Current password length is: " << password.size();
1596    return SAPI_RC_BAD_SIZE;
1597  }
1598  return factory_.GetTpm()->HierarchyChangeAuthSync(
1599      hierarchy, NameFromHandle(hierarchy), Make_TPM2B_DIGEST(password),
1600      authorization);
1601}
1602
1603TPM_RC TpmUtilityImpl::DisablePlatformHierarchy(
1604    AuthorizationDelegate* authorization) {
1605  return factory_.GetTpm()->HierarchyControlSync(
1606      TPM_RH_PLATFORM,  // The authorizing entity.
1607      NameFromHandle(TPM_RH_PLATFORM),
1608      TPM_RH_PLATFORM,  // The target hierarchy.
1609      0,                // Disable.
1610      authorization);
1611}
1612
1613TPM_RC TpmUtilityImpl::ComputeKeyName(const TPMT_PUBLIC& public_area,
1614                                      std::string* object_name) {
1615  CHECK(object_name);
1616  if (public_area.type == TPM_ALG_ERROR) {
1617    // We do not compute a name for empty public area.
1618    object_name->clear();
1619    return TPM_RC_SUCCESS;
1620  }
1621  std::string serialized_public_area;
1622  TPM_RC result = Serialize_TPMT_PUBLIC(public_area, &serialized_public_area);
1623  if (result != TPM_RC_SUCCESS) {
1624    LOG(ERROR) << "Error serializing public area: " << GetErrorString(result);
1625    return result;
1626  }
1627  std::string serialized_name_alg;
1628  result = Serialize_TPM_ALG_ID(TPM_ALG_SHA256, &serialized_name_alg);
1629  if (result != TPM_RC_SUCCESS) {
1630    LOG(ERROR) << "Error serializing public area: " << GetErrorString(result);
1631    return result;
1632  }
1633  object_name->assign(serialized_name_alg +
1634                      crypto::SHA256HashString(serialized_public_area));
1635  return TPM_RC_SUCCESS;
1636}
1637
1638TPM_RC TpmUtilityImpl::ComputeNVSpaceName(const TPMS_NV_PUBLIC& nv_public_area,
1639                                          std::string* nv_name) {
1640  CHECK(nv_name);
1641  if ((nv_public_area.nv_index & NV_INDEX_FIRST) == 0) {
1642    // If the index is not an nvram index, we do not compute a name.
1643    nv_name->clear();
1644    return TPM_RC_SUCCESS;
1645  }
1646  std::string serialized_public_area;
1647  TPM_RC result =
1648      Serialize_TPMS_NV_PUBLIC(nv_public_area, &serialized_public_area);
1649  if (result != TPM_RC_SUCCESS) {
1650    LOG(ERROR) << "Error serializing public area: " << GetErrorString(result);
1651    return result;
1652  }
1653  std::string serialized_name_alg;
1654  result = Serialize_TPM_ALG_ID(TPM_ALG_SHA256, &serialized_name_alg);
1655  if (result != TPM_RC_SUCCESS) {
1656    LOG(ERROR) << "Error serializing public area: " << GetErrorString(result);
1657    return result;
1658  }
1659  nv_name->assign(serialized_name_alg +
1660                  crypto::SHA256HashString(serialized_public_area));
1661  return TPM_RC_SUCCESS;
1662}
1663
1664TPM_RC TpmUtilityImpl::EncryptPrivateData(const TPMT_SENSITIVE& sensitive_area,
1665                                          const TPMT_PUBLIC& public_area,
1666                                          TPM2B_PRIVATE* encrypted_private_data,
1667                                          TPM2B_DATA* encryption_key) {
1668  TPM2B_SENSITIVE sensitive_data = Make_TPM2B_SENSITIVE(sensitive_area);
1669  std::string serialized_sensitive_data;
1670  TPM_RC result =
1671      Serialize_TPM2B_SENSITIVE(sensitive_data, &serialized_sensitive_data);
1672  if (result != TPM_RC_SUCCESS) {
1673    LOG(ERROR) << "Error serializing sensitive data: "
1674               << GetErrorString(result);
1675    return result;
1676  }
1677  std::string object_name;
1678  result = ComputeKeyName(public_area, &object_name);
1679  if (result != TPM_RC_SUCCESS) {
1680    LOG(ERROR) << "Error computing object name: " << GetErrorString(result);
1681    return result;
1682  }
1683  TPM2B_DIGEST inner_integrity = Make_TPM2B_DIGEST(
1684      crypto::SHA256HashString(serialized_sensitive_data + object_name));
1685  std::string serialized_inner_integrity;
1686  result = Serialize_TPM2B_DIGEST(inner_integrity, &serialized_inner_integrity);
1687  if (result != TPM_RC_SUCCESS) {
1688    LOG(ERROR) << "Error serializing inner integrity: "
1689               << GetErrorString(result);
1690    return result;
1691  }
1692  std::string unencrypted_private_data =
1693      serialized_inner_integrity + serialized_sensitive_data;
1694  AES_KEY key;
1695  AES_set_encrypt_key(encryption_key->buffer, kAesKeySize * 8, &key);
1696  std::string private_data_string(unencrypted_private_data.size(), 0);
1697  int iv_in = 0;
1698  unsigned char iv[MAX_AES_BLOCK_SIZE_BYTES] = {0};
1699  AES_cfb128_encrypt(
1700      reinterpret_cast<const unsigned char*>(unencrypted_private_data.data()),
1701      reinterpret_cast<unsigned char*>(string_as_array(&private_data_string)),
1702      unencrypted_private_data.size(), &key, iv, &iv_in, AES_ENCRYPT);
1703  *encrypted_private_data = Make_TPM2B_PRIVATE(private_data_string);
1704  if (result != TPM_RC_SUCCESS) {
1705    LOG(ERROR) << "Error making private area: " << GetErrorString(result);
1706    return result;
1707  }
1708  return TPM_RC_SUCCESS;
1709}
1710
1711TPM_RC TpmUtilityImpl::DoesPersistentKeyExist(TPMI_DH_PERSISTENT key_handle,
1712                                              bool* exists) {
1713  TPM_RC result;
1714  TPMI_YES_NO more_data = YES;
1715  TPMS_CAPABILITY_DATA capability_data;
1716  result = factory_.GetTpm()->GetCapabilitySync(
1717      TPM_CAP_HANDLES, key_handle, 1 /*property_count*/, &more_data,
1718      &capability_data, nullptr /*authorization_delegate*/);
1719  if (result != TPM_RC_SUCCESS) {
1720    LOG(ERROR) << __func__
1721               << ": Error querying handles: " << GetErrorString(result);
1722    return result;
1723  }
1724  TPML_HANDLE& handles = capability_data.data.handles;
1725  *exists = (handles.count == 1 && handles.handle[0] == key_handle);
1726  return TPM_RC_SUCCESS;
1727}
1728
1729}  // namespace trunks
1730