1bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi//
2bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// Copyright (C) 2014 The Android Open Source Project
3bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi//
4bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// Licensed under the Apache License, Version 2.0 (the "License");
5bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// you may not use this file except in compliance with the License.
6bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// You may obtain a copy of the License at
7bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi//
8bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi//      http://www.apache.org/licenses/LICENSE-2.0
9bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi//
10bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// Unless required by applicable law or agreed to in writing, software
11bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// distributed under the License is distributed on an "AS IS" BASIS,
12bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// See the License for the specific language governing permissions and
14bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi// limitations under the License.
15bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi//
16c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn
17c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn#include "trunks/tpm_utility_impl.h"
18c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn
1930c921db09d27768acc1ea0d8b6a9c8e814f931aLuis Hector Chavez#include <memory>
2030c921db09d27768acc1ea0d8b6a9c8e814f931aLuis Hector Chavez
21c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn#include <base/logging.h>
22887ccbcc4db5fa0b5221018296aa49b86a5ac26fUtkarsh Sanghi#include <base/sha1.h>
23e31034f28641c9bc3e5576cab6d2c7d918bb427cUtkarsh Sanghi#include <base/stl_util.h>
2487b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn#include <crypto/openssl_util.h>
25e31034f28641c9bc3e5576cab6d2c7d918bb427cUtkarsh Sanghi#include <crypto/secure_hash.h>
26e31034f28641c9bc3e5576cab6d2c7d918bb427cUtkarsh Sanghi#include <crypto/sha2.h>
2733ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi#include <openssl/aes.h>
2833ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi#include <openssl/rand.h>
29c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn
30c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn#include "trunks/authorization_delegate.h"
310ebbc58fe6d45378a5b502c33eb1c4289fd8b05bUtkarsh Sanghi#include "trunks/blob_parser.h"
3203d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn#include "trunks/error_codes.h"
3333ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi#include "trunks/hmac_authorization_delegate.h"
34ff7f2da556b21253a52abbc82e7cf7bee54a850eUtkarsh Sanghi#include "trunks/hmac_session.h"
35a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi#include "trunks/policy_session.h"
362ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi#include "trunks/scoped_key_handle.h"
3739dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi#include "trunks/tpm_constants.h"
38c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn#include "trunks/tpm_state.h"
39c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn#include "trunks/trunks_factory.h"
40c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn
41c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahnnamespace {
42c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn
43c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahnconst char kPlatformPassword[] = "cros-platform";
442ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghiconst char kWellKnownPassword[] = "cros-password";
45e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghiconst size_t kMaxPasswordLength = 32;
4639dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi// The below maximum is defined in TPM 2.0 Library Spec Part 2 Section 13.1
474dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahnconst uint32_t kMaxNVSpaceIndex = (1 << 24) - 1;
48c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn
49c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn// Returns a serialized representation of the unmodified handle. This is useful
50c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn// for predefined handle values, like TPM_RH_OWNER. For details on what types of
51c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn// handles use this name formula see Table 3 in the TPM 2.0 Library Spec Part 1
52c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn// (Section 16 - Names).
53c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahnstd::string NameFromHandle(trunks::TPM_HANDLE handle) {
54c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn  std::string name;
55c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn  trunks::Serialize_TPM_HANDLE(handle, &name);
56c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn  return name;
57c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn}
58c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn
59887ccbcc4db5fa0b5221018296aa49b86a5ac26fUtkarsh Sanghistd::string HashString(const std::string& plaintext,
60887ccbcc4db5fa0b5221018296aa49b86a5ac26fUtkarsh Sanghi                       trunks::TPM_ALG_ID hash_alg) {
61e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi  switch (hash_alg) {
62e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi    case trunks::TPM_ALG_SHA1:
63887ccbcc4db5fa0b5221018296aa49b86a5ac26fUtkarsh Sanghi      return base::SHA1HashString(plaintext);
64e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi    case trunks::TPM_ALG_SHA256:
65887ccbcc4db5fa0b5221018296aa49b86a5ac26fUtkarsh Sanghi      return crypto::SHA256HashString(plaintext);
66e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi  }
67e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi  NOTREACHED();
68887ccbcc4db5fa0b5221018296aa49b86a5ac26fUtkarsh Sanghi  return std::string();
69e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi}
70e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi
71c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn}  // namespace
72c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn
73c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahnnamespace trunks {
74c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn
75c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren KrahnTpmUtilityImpl::TpmUtilityImpl(const TrunksFactory& factory)
7687b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn    : factory_(factory) {
7787b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn  crypto::EnsureOpenSSLInit();
7887b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn}
79c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn
804dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren KrahnTpmUtilityImpl::~TpmUtilityImpl() {}
81c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn
8203d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren KrahnTPM_RC TpmUtilityImpl::Startup() {
8303d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn  TPM_RC result = TPM_RC_SUCCESS;
8403d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn  Tpm* tpm = factory_.GetTpm();
85c04decde2a6e9b74395f402818852e752534254bUtkarsh Sanghi  result = tpm->StartupSync(TPM_SU_CLEAR, nullptr);
8603d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn  // Ignore TPM_RC_INITIALIZE, that means it was already started.
8703d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn  if (result && result != TPM_RC_INITIALIZE) {
8803d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn    LOG(ERROR) << __func__ << ": " << GetErrorString(result);
8903d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn    return result;
9003d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn  }
91c04decde2a6e9b74395f402818852e752534254bUtkarsh Sanghi  result = tpm->SelfTestSync(YES /* Full test. */, nullptr);
9203d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn  if (result) {
9303d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn    LOG(ERROR) << __func__ << ": " << GetErrorString(result);
9403d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn    return result;
9503d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn  }
9603d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn  return TPM_RC_SUCCESS;
9703d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn}
9803d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn
99d75dcae8a010d1ced7554dd25a440bee350a2d06Utkarsh SanghiTPM_RC TpmUtilityImpl::Clear() {
100d75dcae8a010d1ced7554dd25a440bee350a2d06Utkarsh Sanghi  TPM_RC result = TPM_RC_SUCCESS;
10130c921db09d27768acc1ea0d8b6a9c8e814f931aLuis Hector Chavez  std::unique_ptr<AuthorizationDelegate> password_delegate(
102d75dcae8a010d1ced7554dd25a440bee350a2d06Utkarsh Sanghi      factory_.GetPasswordAuthorization(""));
103d75dcae8a010d1ced7554dd25a440bee350a2d06Utkarsh Sanghi  result = factory_.GetTpm()->ClearSync(TPM_RH_PLATFORM,
104d75dcae8a010d1ced7554dd25a440bee350a2d06Utkarsh Sanghi                                        NameFromHandle(TPM_RH_PLATFORM),
105d75dcae8a010d1ced7554dd25a440bee350a2d06Utkarsh Sanghi                                        password_delegate.get());
106d75dcae8a010d1ced7554dd25a440bee350a2d06Utkarsh Sanghi  // If there was an error in the initialization, platform auth is in a bad
107d75dcae8a010d1ced7554dd25a440bee350a2d06Utkarsh Sanghi  // state.
108d75dcae8a010d1ced7554dd25a440bee350a2d06Utkarsh Sanghi  if (result == TPM_RC_AUTH_MISSING) {
10930c921db09d27768acc1ea0d8b6a9c8e814f931aLuis Hector Chavez    std::unique_ptr<AuthorizationDelegate> authorization(
110d75dcae8a010d1ced7554dd25a440bee350a2d06Utkarsh Sanghi        factory_.GetPasswordAuthorization(kPlatformPassword));
1114dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn    result = factory_.GetTpm()->ClearSync(
1124dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn        TPM_RH_PLATFORM, NameFromHandle(TPM_RH_PLATFORM), authorization.get());
113d75dcae8a010d1ced7554dd25a440bee350a2d06Utkarsh Sanghi  }
114d75dcae8a010d1ced7554dd25a440bee350a2d06Utkarsh Sanghi  if (GetFormatOneError(result) == TPM_RC_BAD_AUTH) {
115b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(INFO) << __func__
116b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn              << ": Clear failed because of BAD_AUTH. This probably means "
117d75dcae8a010d1ced7554dd25a440bee350a2d06Utkarsh Sanghi              << "that the TPM was already initialized.";
118d75dcae8a010d1ced7554dd25a440bee350a2d06Utkarsh Sanghi    return result;
119d75dcae8a010d1ced7554dd25a440bee350a2d06Utkarsh Sanghi  }
120d75dcae8a010d1ced7554dd25a440bee350a2d06Utkarsh Sanghi  if (result) {
121b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
122b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Failed to clear the TPM: " << GetErrorString(result);
123d75dcae8a010d1ced7554dd25a440bee350a2d06Utkarsh Sanghi  }
124d75dcae8a010d1ced7554dd25a440bee350a2d06Utkarsh Sanghi  return result;
125d75dcae8a010d1ced7554dd25a440bee350a2d06Utkarsh Sanghi}
126d75dcae8a010d1ced7554dd25a440bee350a2d06Utkarsh Sanghi
127e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghivoid TpmUtilityImpl::Shutdown() {
128c04decde2a6e9b74395f402818852e752534254bUtkarsh Sanghi  TPM_RC return_code = factory_.GetTpm()->ShutdownSync(TPM_SU_CLEAR, nullptr);
129e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi  if (return_code && return_code != TPM_RC_INITIALIZE) {
130e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi    // This should not happen, but if it does, there is nothing we can do.
131b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
132b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error shutting down: " << GetErrorString(return_code);
133e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi  }
134e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi}
135e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi
136c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren KrahnTPM_RC TpmUtilityImpl::InitializeTpm() {
137c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn  TPM_RC result = TPM_RC_SUCCESS;
13830c921db09d27768acc1ea0d8b6a9c8e814f931aLuis Hector Chavez  std::unique_ptr<TpmState> tpm_state(factory_.GetTpmState());
139c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn  result = tpm_state->Initialize();
140c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn  if (result) {
14103d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn    LOG(ERROR) << __func__ << ": " << GetErrorString(result);
142c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn    return result;
143c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn  }
144c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn  // Warn about various unexpected conditions.
145c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn  if (!tpm_state->WasShutdownOrderly()) {
146b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(WARNING) << __func__
147b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn                 << ": WARNING: The last TPM shutdown was not orderly.";
148c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn  }
149c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn  if (tpm_state->IsInLockout()) {
150b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(WARNING) << __func__ << ": WARNING: The TPM is currently in lockout.";
151c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn  }
152c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn
153c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn  // We expect the firmware has already locked down the platform hierarchy. If
154c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn  // it hasn't, do it now.
155c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn  if (tpm_state->IsPlatformHierarchyEnabled()) {
15630c921db09d27768acc1ea0d8b6a9c8e814f931aLuis Hector Chavez    std::unique_ptr<AuthorizationDelegate> empty_password(
15752e2a45f585fbe34032eae5b094a092afdf217caDarren Krahn        factory_.GetPasswordAuthorization(""));
1584dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn    result = SetHierarchyAuthorization(TPM_RH_PLATFORM, kPlatformPassword,
15952e2a45f585fbe34032eae5b094a092afdf217caDarren Krahn                                       empty_password.get());
16052e2a45f585fbe34032eae5b094a092afdf217caDarren Krahn    if (GetFormatOneError(result) == TPM_RC_BAD_AUTH) {
16152e2a45f585fbe34032eae5b094a092afdf217caDarren Krahn      // Most likely the platform password has already been set.
16252e2a45f585fbe34032eae5b094a092afdf217caDarren Krahn      result = TPM_RC_SUCCESS;
16352e2a45f585fbe34032eae5b094a092afdf217caDarren Krahn    }
164e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh Sanghi    if (result != TPM_RC_SUCCESS) {
165e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh Sanghi      LOG(ERROR) << __func__ << ": " << GetErrorString(result);
166e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh Sanghi      return result;
167e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh Sanghi    }
168e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh Sanghi    result = AllocatePCR(kPlatformPassword);
169e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh Sanghi    if (result != TPM_RC_SUCCESS) {
17003d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn      LOG(ERROR) << __func__ << ": " << GetErrorString(result);
171c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn      return result;
172c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn    }
17330c921db09d27768acc1ea0d8b6a9c8e814f931aLuis Hector Chavez    std::unique_ptr<AuthorizationDelegate> authorization(
174c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn        factory_.GetPasswordAuthorization(kPlatformPassword));
175c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn    result = DisablePlatformHierarchy(authorization.get());
176e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh Sanghi    if (result != TPM_RC_SUCCESS) {
17703d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn      LOG(ERROR) << __func__ << ": " << GetErrorString(result);
178c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn      return result;
179c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn    }
180c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn  }
181c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn  return TPM_RC_SUCCESS;
182c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn}
183c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn
184e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh SanghiTPM_RC TpmUtilityImpl::AllocatePCR(const std::string& platform_password) {
185e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh Sanghi  TPM_RC result;
186db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn  TPMI_YES_NO more_data = YES;
187db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn  TPMS_CAPABILITY_DATA capability_data;
188db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn  result = factory_.GetTpm()->GetCapabilitySync(
189db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn      TPM_CAP_PCRS, 0 /*property (not used)*/, 1 /*property_count*/, &more_data,
190db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn      &capability_data, nullptr /*authorization_delegate*/);
191db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn  if (result != TPM_RC_SUCCESS) {
192b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
193b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error querying PCRs: " << GetErrorString(result);
194db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn    return result;
195db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn  }
196db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn  TPML_PCR_SELECTION& existing_pcrs = capability_data.data.assigned_pcr;
197db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn  bool sha256_needed = true;
198db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn  std::vector<TPMI_ALG_HASH> pcr_banks_to_remove;
199db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn  for (uint32_t i = 0; i < existing_pcrs.count; ++i) {
200db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn    if (existing_pcrs.pcr_selections[i].hash == TPM_ALG_SHA256) {
201db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn      sha256_needed = false;
202db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn    } else {
203db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn      pcr_banks_to_remove.push_back(existing_pcrs.pcr_selections[i].hash);
204db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn    }
205db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn  }
206db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn  if (!sha256_needed && pcr_banks_to_remove.empty()) {
207db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn    return TPM_RC_SUCCESS;
208db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn  }
209e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh Sanghi  TPML_PCR_SELECTION pcr_allocation;
210db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn  memset(&pcr_allocation, 0, sizeof(pcr_allocation));
211db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn  if (sha256_needed) {
212db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn    pcr_allocation.pcr_selections[pcr_allocation.count].hash = TPM_ALG_SHA256;
213db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn    pcr_allocation.pcr_selections[pcr_allocation.count].sizeof_select =
214db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn        PCR_SELECT_MIN;
215db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn    for (int i = 0; i < PCR_SELECT_MIN; ++i) {
216db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn      pcr_allocation.pcr_selections[pcr_allocation.count].pcr_select[i] = 0xff;
217db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn    }
218db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn    ++pcr_allocation.count;
219db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn  }
220db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn  for (auto pcr_type : pcr_banks_to_remove) {
221db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn    pcr_allocation.pcr_selections[pcr_allocation.count].hash = pcr_type;
222db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn    pcr_allocation.pcr_selections[pcr_allocation.count].sizeof_select =
223db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn        PCR_SELECT_MAX;
224db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn    ++pcr_allocation.count;
225db30790da11248905f8dca02a933ebbdcf9e3ff9Darren Krahn  }
22630c921db09d27768acc1ea0d8b6a9c8e814f931aLuis Hector Chavez  std::unique_ptr<AuthorizationDelegate> platform_delegate(
227e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh Sanghi      factory_.GetPasswordAuthorization(platform_password));
228e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh Sanghi  TPMI_YES_NO allocation_success;
229e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh Sanghi  uint32_t max_pcr;
230e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh Sanghi  uint32_t size_needed;
231e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh Sanghi  uint32_t size_available;
2324dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  result = factory_.GetTpm()->PCR_AllocateSync(
2334dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      TPM_RH_PLATFORM, NameFromHandle(TPM_RH_PLATFORM), pcr_allocation,
2344dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      &allocation_success, &max_pcr, &size_needed, &size_available,
2354dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      platform_delegate.get());
236e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
237b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
238b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error allocating PCRs: " << GetErrorString(result);
239e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh Sanghi    return result;
240e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh Sanghi  }
241e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh Sanghi  if (allocation_success != YES) {
242b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": PCR allocation unsuccessful.";
243e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh Sanghi    return TPM_RC_FAILURE;
244e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh Sanghi  }
245e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh Sanghi  return TPM_RC_SUCCESS;
246e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh Sanghi}
247e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh Sanghi
2482ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh SanghiTPM_RC TpmUtilityImpl::TakeOwnership(const std::string& owner_password,
2492ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi                                     const std::string& endorsement_password,
2502ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi                                     const std::string& lockout_password) {
2512ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi  // First we set the storage hierarchy authorization to the well know default
2522ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi  // password.
25366d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  TPM_RC result = TPM_RC_SUCCESS;
25466d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  result = SetKnownOwnerPassword(kWellKnownPassword);
25566d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
256b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error injecting known password: "
257b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << GetErrorString(result);
2582ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi    return result;
2592ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi  }
26066d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi
2612ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi  result = CreateStorageRootKeys(kWellKnownPassword);
2622ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi  if (result) {
263b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
264b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error creating SRKs: " << GetErrorString(result);
2652ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi    return result;
2662ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi  }
2672ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi  result = CreateSaltingKey(kWellKnownPassword);
2682ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi  if (result) {
269b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
270b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error creating salting key: " << GetErrorString(result);
2712ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi    return result;
2722ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi  }
27366d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi
27430c921db09d27768acc1ea0d8b6a9c8e814f931aLuis Hector Chavez  std::unique_ptr<HmacSession> session = factory_.GetHmacSession();
2752ff7e22ba2ef3bb7ce2747b1b9706dd242ef9284Utkarsh Sanghi  result = session->StartUnboundSession(true);
2762ff7e22ba2ef3bb7ce2747b1b9706dd242ef9284Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
277b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error initializing AuthorizationSession: "
2782ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi               << GetErrorString(result);
2792ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi    return result;
2802ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi  }
28130c921db09d27768acc1ea0d8b6a9c8e814f931aLuis Hector Chavez  std::unique_ptr<TpmState> tpm_state(factory_.GetTpmState());
2822ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi  result = tpm_state->Initialize();
2832ff7e22ba2ef3bb7ce2747b1b9706dd242ef9284Utkarsh Sanghi  session->SetEntityAuthorizationValue("");
2842ff7e22ba2ef3bb7ce2747b1b9706dd242ef9284Utkarsh Sanghi  session->SetFutureAuthorizationValue(endorsement_password);
2852ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi  if (!tpm_state->IsEndorsementPasswordSet()) {
2864dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn    result = SetHierarchyAuthorization(TPM_RH_ENDORSEMENT, endorsement_password,
2872ff7e22ba2ef3bb7ce2747b1b9706dd242ef9284Utkarsh Sanghi                                       session->GetDelegate());
2882ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi    if (result) {
2892ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi      LOG(ERROR) << __func__ << ": " << GetErrorString(result);
2902ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi      return result;
2912ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi    }
2922ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi  }
2932ff7e22ba2ef3bb7ce2747b1b9706dd242ef9284Utkarsh Sanghi  session->SetFutureAuthorizationValue(lockout_password);
2942ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi  if (!tpm_state->IsLockoutPasswordSet()) {
2954dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn    result = SetHierarchyAuthorization(TPM_RH_LOCKOUT, lockout_password,
2962ff7e22ba2ef3bb7ce2747b1b9706dd242ef9284Utkarsh Sanghi                                       session->GetDelegate());
2972ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi    if (result) {
2982ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi      LOG(ERROR) << __func__ << ": " << GetErrorString(result);
2992ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi      return result;
3002ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi    }
3012ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi  }
30266d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  // We take ownership of owner hierarchy last.
30366d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  session->SetEntityAuthorizationValue(kWellKnownPassword);
30466d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  session->SetFutureAuthorizationValue(owner_password);
3054dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  result = SetHierarchyAuthorization(TPM_RH_OWNER, owner_password,
30666d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi                                     session->GetDelegate());
30766d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  if ((GetFormatOneError(result) == TPM_RC_BAD_AUTH) &&
30866d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi      tpm_state->IsOwnerPasswordSet()) {
309b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(WARNING) << __func__
310b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn                 << ": Error changing owner password. This probably because "
31166d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi                 << "ownership is already taken.";
31266d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi    return TPM_RC_SUCCESS;
31366d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  } else if (result != TPM_RC_SUCCESS) {
314b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error changing owner authorization: "
3150f46c15b948ee17f5668c332a25a0dbaecb2cc47Utkarsh Sanghi               << GetErrorString(result);
3160f46c15b948ee17f5668c332a25a0dbaecb2cc47Utkarsh Sanghi    return result;
3170f46c15b948ee17f5668c332a25a0dbaecb2cc47Utkarsh Sanghi  }
3180f46c15b948ee17f5668c332a25a0dbaecb2cc47Utkarsh Sanghi  return TPM_RC_SUCCESS;
3190f46c15b948ee17f5668c332a25a0dbaecb2cc47Utkarsh Sanghi}
3200f46c15b948ee17f5668c332a25a0dbaecb2cc47Utkarsh Sanghi
3218b2bf63478b292937f85b3b0e215882af461a999Utkarsh SanghiTPM_RC TpmUtilityImpl::StirRandom(const std::string& entropy_data,
3225d3b9451ae2e912aefed0669dd50b2a777ea0ab2Utkarsh Sanghi                                  AuthorizationDelegate* delegate) {
323e31034f28641c9bc3e5576cab6d2c7d918bb427cUtkarsh Sanghi  std::string digest = crypto::SHA256HashString(entropy_data);
324e31034f28641c9bc3e5576cab6d2c7d918bb427cUtkarsh Sanghi  TPM2B_SENSITIVE_DATA random_bytes = Make_TPM2B_SENSITIVE_DATA(digest);
3258b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  return factory_.GetTpm()->StirRandomSync(random_bytes, delegate);
326e31034f28641c9bc3e5576cab6d2c7d918bb427cUtkarsh Sanghi}
327e31034f28641c9bc3e5576cab6d2c7d918bb427cUtkarsh Sanghi
32835af244e7cf856a02e46ec8f186f36c53582757dUtkarsh SanghiTPM_RC TpmUtilityImpl::GenerateRandom(size_t num_bytes,
3295d3b9451ae2e912aefed0669dd50b2a777ea0ab2Utkarsh Sanghi                                      AuthorizationDelegate* delegate,
330e31034f28641c9bc3e5576cab6d2c7d918bb427cUtkarsh Sanghi                                      std::string* random_data) {
3318b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  CHECK(random_data);
33235af244e7cf856a02e46ec8f186f36c53582757dUtkarsh Sanghi  size_t bytes_left = num_bytes;
333e31034f28641c9bc3e5576cab6d2c7d918bb427cUtkarsh Sanghi  random_data->clear();
334e31034f28641c9bc3e5576cab6d2c7d918bb427cUtkarsh Sanghi  TPM_RC rc;
335e31034f28641c9bc3e5576cab6d2c7d918bb427cUtkarsh Sanghi  TPM2B_DIGEST digest;
336e31034f28641c9bc3e5576cab6d2c7d918bb427cUtkarsh Sanghi  while (bytes_left > 0) {
3374dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn    rc = factory_.GetTpm()->GetRandomSync(bytes_left, &digest, delegate);
338e31034f28641c9bc3e5576cab6d2c7d918bb427cUtkarsh Sanghi    if (rc) {
339b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn      LOG(ERROR) << __func__ << ": Error getting random data from tpm.";
340e31034f28641c9bc3e5576cab6d2c7d918bb427cUtkarsh Sanghi      return rc;
341e31034f28641c9bc3e5576cab6d2c7d918bb427cUtkarsh Sanghi    }
342e31034f28641c9bc3e5576cab6d2c7d918bb427cUtkarsh Sanghi    random_data->append(StringFrom_TPM2B_DIGEST(digest));
343e31034f28641c9bc3e5576cab6d2c7d918bb427cUtkarsh Sanghi    bytes_left -= digest.size;
344e31034f28641c9bc3e5576cab6d2c7d918bb427cUtkarsh Sanghi  }
345e31034f28641c9bc3e5576cab6d2c7d918bb427cUtkarsh Sanghi  CHECK_EQ(random_data->size(), num_bytes);
346e31034f28641c9bc3e5576cab6d2c7d918bb427cUtkarsh Sanghi  return TPM_RC_SUCCESS;
347e31034f28641c9bc3e5576cab6d2c7d918bb427cUtkarsh Sanghi}
348e31034f28641c9bc3e5576cab6d2c7d918bb427cUtkarsh Sanghi
349579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh SanghiTPM_RC TpmUtilityImpl::ExtendPCR(int pcr_index,
3508b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi                                 const std::string& extend_data,
3515d3b9451ae2e912aefed0669dd50b2a777ea0ab2Utkarsh Sanghi                                 AuthorizationDelegate* delegate) {
352579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi  if (pcr_index < 0 || pcr_index >= IMPLEMENTATION_PCR) {
353b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Using a PCR index that isn't implemented.";
354579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi    return TPM_RC_FAILURE;
355579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi  }
356579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi  TPM_HANDLE pcr_handle = HR_PCR + pcr_index;
357579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi  std::string pcr_name = NameFromHandle(pcr_handle);
358579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi  TPML_DIGEST_VALUES digests;
359579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi  digests.count = 1;
360579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi  digests.digests[0].hash_alg = TPM_ALG_SHA256;
3614dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  crypto::SHA256HashString(extend_data, digests.digests[0].digest.sha256,
362579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi                           crypto::kSHA256Length);
363b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  std::unique_ptr<AuthorizationDelegate> empty_password_delegate =
364b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn      factory_.GetPasswordAuthorization("");
365b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  if (!delegate) {
366b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    delegate = empty_password_delegate.get();
367b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  }
3684dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  return factory_.GetTpm()->PCR_ExtendSync(pcr_handle, pcr_name, digests,
3698b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi                                           delegate);
370579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi}
371579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi
372579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh SanghiTPM_RC TpmUtilityImpl::ReadPCR(int pcr_index, std::string* pcr_value) {
373579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi  TPML_PCR_SELECTION pcr_select_in;
374579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi  uint32_t pcr_update_counter;
375579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi  TPML_PCR_SELECTION pcr_select_out;
376579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi  TPML_DIGEST pcr_values;
377579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi  // This process of selecting pcrs is highlighted in TPM 2.0 Library Spec
378579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi  // Part 2 (Section 10.5 - PCR structures).
379579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi  uint8_t pcr_select_index = pcr_index / 8;
380579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi  uint8_t pcr_select_byte = 1 << (pcr_index % 8);
381579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi  pcr_select_in.count = 1;
382579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi  pcr_select_in.pcr_selections[0].hash = TPM_ALG_SHA256;
383e7eb2bf306af6e8408cd77125861542d19e5ec6dUtkarsh Sanghi  pcr_select_in.pcr_selections[0].sizeof_select = PCR_SELECT_MIN;
384579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi  pcr_select_in.pcr_selections[0].pcr_select[pcr_select_index] =
385579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi      pcr_select_byte;
386579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi
3874dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  TPM_RC rc =
3884dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      factory_.GetTpm()->PCR_ReadSync(pcr_select_in, &pcr_update_counter,
3894dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                                      &pcr_select_out, &pcr_values, nullptr);
390579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi  if (rc) {
391b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(INFO) << __func__
392b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn              << ": Error trying to read a pcr: " << GetErrorString(rc);
393579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi    return rc;
394579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi  }
395579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi  if (pcr_select_out.count != 1 ||
3964dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      pcr_select_out.pcr_selections[0].sizeof_select < (pcr_select_index + 1) ||
397579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi      pcr_select_out.pcr_selections[0].pcr_select[pcr_select_index] !=
3984dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn          pcr_select_byte) {
399b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": TPM did not return the requested PCR";
400579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi    return TPM_RC_FAILURE;
401579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi  }
40235af244e7cf856a02e46ec8f186f36c53582757dUtkarsh Sanghi  CHECK_GE(pcr_values.count, 1U);
403579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi  pcr_value->assign(StringFrom_TPM2B_DIGEST(pcr_values.digests[0]));
404579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi  return TPM_RC_SUCCESS;
405579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi}
406579dd8a934c684f2e2a34d9aa2f67953320428acUtkarsh Sanghi
407b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh SanghiTPM_RC TpmUtilityImpl::AsymmetricEncrypt(TPM_HANDLE key_handle,
408b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi                                         TPM_ALG_ID scheme,
4099dc77fecdb2446da134b9b2901173bb4dcf5e5e4Utkarsh Sanghi                                         TPM_ALG_ID hash_alg,
410b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi                                         const std::string& plaintext,
4115d3b9451ae2e912aefed0669dd50b2a777ea0ab2Utkarsh Sanghi                                         AuthorizationDelegate* delegate,
412b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi                                         std::string* ciphertext) {
4139dc77fecdb2446da134b9b2901173bb4dcf5e5e4Utkarsh Sanghi  TPMT_RSA_DECRYPT in_scheme;
4149dc77fecdb2446da134b9b2901173bb4dcf5e5e4Utkarsh Sanghi  if (hash_alg == TPM_ALG_NULL) {
415e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi    hash_alg = TPM_ALG_SHA256;
4169dc77fecdb2446da134b9b2901173bb4dcf5e5e4Utkarsh Sanghi  }
4179dc77fecdb2446da134b9b2901173bb4dcf5e5e4Utkarsh Sanghi  if (scheme == TPM_ALG_RSAES) {
4189dc77fecdb2446da134b9b2901173bb4dcf5e5e4Utkarsh Sanghi    in_scheme.scheme = TPM_ALG_RSAES;
4199dc77fecdb2446da134b9b2901173bb4dcf5e5e4Utkarsh Sanghi  } else if (scheme == TPM_ALG_OAEP || scheme == TPM_ALG_NULL) {
4209dc77fecdb2446da134b9b2901173bb4dcf5e5e4Utkarsh Sanghi    in_scheme.scheme = TPM_ALG_OAEP;
421e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi    in_scheme.details.oaep.hash_alg = hash_alg;
4229dc77fecdb2446da134b9b2901173bb4dcf5e5e4Utkarsh Sanghi  } else {
423b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Invalid Signing scheme used.";
4249dc77fecdb2446da134b9b2901173bb4dcf5e5e4Utkarsh Sanghi    return SAPI_RC_BAD_PARAMETER;
4259dc77fecdb2446da134b9b2901173bb4dcf5e5e4Utkarsh Sanghi  }
4269dc77fecdb2446da134b9b2901173bb4dcf5e5e4Utkarsh Sanghi
4278b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  TPMT_PUBLIC public_area;
4288b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  TPM_RC result = GetKeyPublicArea(key_handle, &public_area);
4298b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
430b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error finding public area for: " << key_handle;
4318b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi    return result;
4328b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  } else if (public_area.type != TPM_ALG_RSA) {
433b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Key handle given is not an RSA key";
434b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi    return SAPI_RC_BAD_PARAMETER;
4358b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  } else if ((public_area.object_attributes & kDecrypt) == 0) {
436b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Key handle given is not a decryption key";
437b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi    return SAPI_RC_BAD_PARAMETER;
438b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi  }
4398b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  if ((public_area.object_attributes & kRestricted) != 0) {
440b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
441b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Cannot use RSAES for encryption with a restricted key";
442b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi    return SAPI_RC_BAD_PARAMETER;
443b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi  }
444b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi  std::string key_name;
4458b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  result = ComputeKeyName(public_area, &key_name);
4468b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
447b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error computing key name for: " << key_handle;
4488b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi    return result;
4498b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  }
450b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi
451b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi  TPM2B_DATA label;
452b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi  label.size = 0;
453b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi  TPM2B_PUBLIC_KEY_RSA in_message = Make_TPM2B_PUBLIC_KEY_RSA(plaintext);
454b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi  TPM2B_PUBLIC_KEY_RSA out_message;
4554dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  result = factory_.GetTpm()->RSA_EncryptSync(key_handle, key_name, in_message,
4564dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                                              in_scheme, label, &out_message,
4578b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi                                              delegate);
4588b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
459b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
460b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error performing RSA encrypt: " << GetErrorString(result);
4618b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi    return result;
462b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi  }
463b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi  ciphertext->assign(StringFrom_TPM2B_PUBLIC_KEY_RSA(out_message));
464b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi  return TPM_RC_SUCCESS;
465b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi}
466b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi
467b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh SanghiTPM_RC TpmUtilityImpl::AsymmetricDecrypt(TPM_HANDLE key_handle,
468b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi                                         TPM_ALG_ID scheme,
4699dc77fecdb2446da134b9b2901173bb4dcf5e5e4Utkarsh Sanghi                                         TPM_ALG_ID hash_alg,
470b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi                                         const std::string& ciphertext,
4715d3b9451ae2e912aefed0669dd50b2a777ea0ab2Utkarsh Sanghi                                         AuthorizationDelegate* delegate,
472b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi                                         std::string* plaintext) {
4739dc77fecdb2446da134b9b2901173bb4dcf5e5e4Utkarsh Sanghi  TPMT_RSA_DECRYPT in_scheme;
4749dc77fecdb2446da134b9b2901173bb4dcf5e5e4Utkarsh Sanghi  if (hash_alg == TPM_ALG_NULL) {
475e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi    hash_alg = TPM_ALG_SHA256;
4769dc77fecdb2446da134b9b2901173bb4dcf5e5e4Utkarsh Sanghi  }
4779dc77fecdb2446da134b9b2901173bb4dcf5e5e4Utkarsh Sanghi  if (scheme == TPM_ALG_RSAES) {
4789dc77fecdb2446da134b9b2901173bb4dcf5e5e4Utkarsh Sanghi    in_scheme.scheme = TPM_ALG_RSAES;
4799dc77fecdb2446da134b9b2901173bb4dcf5e5e4Utkarsh Sanghi  } else if (scheme == TPM_ALG_OAEP || scheme == TPM_ALG_NULL) {
4809dc77fecdb2446da134b9b2901173bb4dcf5e5e4Utkarsh Sanghi    in_scheme.scheme = TPM_ALG_OAEP;
481e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi    in_scheme.details.oaep.hash_alg = hash_alg;
4829dc77fecdb2446da134b9b2901173bb4dcf5e5e4Utkarsh Sanghi  } else {
483b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Invalid Signing scheme used.";
4849dc77fecdb2446da134b9b2901173bb4dcf5e5e4Utkarsh Sanghi    return SAPI_RC_BAD_PARAMETER;
4859dc77fecdb2446da134b9b2901173bb4dcf5e5e4Utkarsh Sanghi  }
4861ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi  TPM_RC result;
487c04decde2a6e9b74395f402818852e752534254bUtkarsh Sanghi  if (delegate == nullptr) {
4881ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi    result = SAPI_RC_INVALID_SESSIONS;
489b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
490b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": This method needs a valid authorization delegate: "
4911ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi               << GetErrorString(result);
4921ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi    return result;
4931ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi  }
4948b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  TPMT_PUBLIC public_area;
4951ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi  result = GetKeyPublicArea(key_handle, &public_area);
4961ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi  if (result) {
497b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error finding public area for: " << key_handle;
4981ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi    return result;
4998b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  } else if (public_area.type != TPM_ALG_RSA) {
500b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Key handle given is not an RSA key";
501b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi    return SAPI_RC_BAD_PARAMETER;
5028b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  } else if ((public_area.object_attributes & kDecrypt) == 0) {
503b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Key handle given is not a decryption key";
504b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi    return SAPI_RC_BAD_PARAMETER;
505b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi  }
5068b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  if ((public_area.object_attributes & kRestricted) != 0) {
507b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
508b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Cannot use RSAES for encryption with a restricted key";
509b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi    return SAPI_RC_BAD_PARAMETER;
510b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi  }
511b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi  std::string key_name;
5128b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  result = ComputeKeyName(public_area, &key_name);
5131ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi  if (result) {
514b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error computing key name for: " << key_handle;
5151ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi    return result;
516b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi  }
517b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi
518b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi  TPM2B_DATA label;
519b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi  label.size = 0;
520b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi  TPM2B_PUBLIC_KEY_RSA in_message = Make_TPM2B_PUBLIC_KEY_RSA(ciphertext);
521b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi  TPM2B_PUBLIC_KEY_RSA out_message;
5224dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  result = factory_.GetTpm()->RSA_DecryptSync(key_handle, key_name, in_message,
5234dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                                              in_scheme, label, &out_message,
5245d3b9451ae2e912aefed0669dd50b2a777ea0ab2Utkarsh Sanghi                                              delegate);
5251ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi  if (result) {
526b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
527b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error performing RSA decrypt: " << GetErrorString(result);
5281ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi    return result;
529b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi  }
530b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi  plaintext->assign(StringFrom_TPM2B_PUBLIC_KEY_RSA(out_message));
531b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi  return TPM_RC_SUCCESS;
532b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi}
533b3ba5e0b579a5462c7137cf49b49cc9a78d87944Utkarsh Sanghi
534748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh SanghiTPM_RC TpmUtilityImpl::Sign(TPM_HANDLE key_handle,
535748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi                            TPM_ALG_ID scheme,
536748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi                            TPM_ALG_ID hash_alg,
537887ccbcc4db5fa0b5221018296aa49b86a5ac26fUtkarsh Sanghi                            const std::string& plaintext,
5385d3b9451ae2e912aefed0669dd50b2a777ea0ab2Utkarsh Sanghi                            AuthorizationDelegate* delegate,
539748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi                            std::string* signature) {
540748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  TPMT_SIG_SCHEME in_scheme;
541748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  if (hash_alg == TPM_ALG_NULL) {
542e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi    hash_alg = TPM_ALG_SHA256;
543e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi  }
544748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  if (scheme == TPM_ALG_RSAPSS) {
545748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi    in_scheme.scheme = TPM_ALG_RSAPSS;
546e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi    in_scheme.details.rsapss.hash_alg = hash_alg;
547748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  } else if (scheme == TPM_ALG_RSASSA || scheme == TPM_ALG_NULL) {
548748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi    in_scheme.scheme = TPM_ALG_RSASSA;
549e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi    in_scheme.details.rsassa.hash_alg = hash_alg;
550748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  } else {
551b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Invalid Signing scheme used.";
552748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi    return SAPI_RC_BAD_PARAMETER;
553748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  }
5541ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi  TPM_RC result;
555c04decde2a6e9b74395f402818852e752534254bUtkarsh Sanghi  if (delegate == nullptr) {
5561ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi    result = SAPI_RC_INVALID_SESSIONS;
557b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
558b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": This method needs a valid authorization delegate: "
5591ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi               << GetErrorString(result);
5601ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi    return result;
5611ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi  }
5628b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  TPMT_PUBLIC public_area;
5631ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi  result = GetKeyPublicArea(key_handle, &public_area);
5641ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi  if (result) {
565b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error finding public area for: " << key_handle;
5661ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi    return result;
5678b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  } else if (public_area.type != TPM_ALG_RSA) {
568b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Key handle given is not an RSA key";
569748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi    return SAPI_RC_BAD_PARAMETER;
5708b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  } else if ((public_area.object_attributes & kSign) == 0) {
571b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Key handle given is not a signging key";
572748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi    return SAPI_RC_BAD_PARAMETER;
5738b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  } else if ((public_area.object_attributes & kRestricted) != 0) {
574b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Key handle references a restricted key";
575748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi    return SAPI_RC_BAD_PARAMETER;
576748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  }
577748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi
578748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  std::string key_name;
5798b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  result = ComputeKeyName(public_area, &key_name);
5801ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi  if (result) {
581b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error computing key name for: " << key_handle;
5821ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi    return result;
583748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  }
584887ccbcc4db5fa0b5221018296aa49b86a5ac26fUtkarsh Sanghi  std::string digest = HashString(plaintext, hash_alg);
585748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  TPM2B_DIGEST tpm_digest = Make_TPM2B_DIGEST(digest);
586748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  TPMT_SIGNATURE signature_out;
587748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  TPMT_TK_HASHCHECK validation;
588748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  validation.tag = TPM_ST_HASHCHECK;
589e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi  validation.hierarchy = TPM_RH_NULL;
590748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  validation.digest.size = 0;
5914dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  result =
5924dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      factory_.GetTpm()->SignSync(key_handle, key_name, tpm_digest, in_scheme,
5934dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                                  validation, &signature_out, delegate);
5941ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi  if (result) {
595b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
596b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error signing digest: " << GetErrorString(result);
5971ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi    return result;
598748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  }
599748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  if (scheme == TPM_ALG_RSAPSS) {
600748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi    signature->resize(signature_out.signature.rsapss.sig.size);
6014dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn    signature->assign(
6024dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn        StringFrom_TPM2B_PUBLIC_KEY_RSA(signature_out.signature.rsapss.sig));
603748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  } else {
604748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi    signature->resize(signature_out.signature.rsassa.sig.size);
6054dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn    signature->assign(
6064dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn        StringFrom_TPM2B_PUBLIC_KEY_RSA(signature_out.signature.rsassa.sig));
607748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  }
608748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  return TPM_RC_SUCCESS;
609748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi}
610748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi
611748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh SanghiTPM_RC TpmUtilityImpl::Verify(TPM_HANDLE key_handle,
612748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi                              TPM_ALG_ID scheme,
613748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi                              TPM_ALG_ID hash_alg,
614887ccbcc4db5fa0b5221018296aa49b86a5ac26fUtkarsh Sanghi                              const std::string& plaintext,
6156f68562edf5f66006c08de24d558732d6a389631Utkarsh Sanghi                              const std::string& signature,
6166f68562edf5f66006c08de24d558732d6a389631Utkarsh Sanghi                              AuthorizationDelegate* delegate) {
6178b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  TPMT_PUBLIC public_area;
618748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  TPM_RC return_code = GetKeyPublicArea(key_handle, &public_area);
619748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  if (return_code) {
620b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error finding public area for: " << key_handle;
621748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi    return return_code;
6228b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  } else if (public_area.type != TPM_ALG_RSA) {
623b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Key handle given is not an RSA key";
624748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi    return SAPI_RC_BAD_PARAMETER;
6258b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  } else if ((public_area.object_attributes & kSign) == 0) {
626b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Key handle given is not a signing key";
627748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi    return SAPI_RC_BAD_PARAMETER;
6288b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  } else if ((public_area.object_attributes & kRestricted) != 0) {
629b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
630b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Cannot use RSAPSS for signing with a restricted key";
631748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi    return SAPI_RC_BAD_PARAMETER;
632748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  }
633748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  if (hash_alg == TPM_ALG_NULL) {
634e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi    hash_alg = TPM_ALG_SHA256;
635e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi  }
636e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi
637e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi  TPMT_SIGNATURE signature_in;
638748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  if (scheme == TPM_ALG_RSAPSS) {
639748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi    signature_in.sig_alg = TPM_ALG_RSAPSS;
640e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi    signature_in.signature.rsapss.hash = hash_alg;
641748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi    signature_in.signature.rsapss.sig = Make_TPM2B_PUBLIC_KEY_RSA(signature);
642748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  } else if (scheme == TPM_ALG_NULL || scheme == TPM_ALG_RSASSA) {
643748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi    signature_in.sig_alg = TPM_ALG_RSASSA;
644e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi    signature_in.signature.rsassa.hash = hash_alg;
645748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi    signature_in.signature.rsassa.sig = Make_TPM2B_PUBLIC_KEY_RSA(signature);
646748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  } else {
647b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Invalid scheme used to verify signature.";
648748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi    return SAPI_RC_BAD_PARAMETER;
649748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  }
650748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  std::string key_name;
651748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  TPMT_TK_VERIFIED verified;
652887ccbcc4db5fa0b5221018296aa49b86a5ac26fUtkarsh Sanghi  std::string digest = HashString(plaintext, hash_alg);
653748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  TPM2B_DIGEST tpm_digest = Make_TPM2B_DIGEST(digest);
6544dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  return_code = factory_.GetTpm()->VerifySignatureSync(
6554dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      key_handle, key_name, tpm_digest, signature_in, &verified, delegate);
656748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  if (return_code == TPM_RC_SIGNATURE) {
657b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(WARNING) << __func__ << ": Incorrect signature for given digest.";
658748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi    return TPM_RC_SIGNATURE;
659748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  } else if (return_code && return_code != TPM_RC_SIGNATURE) {
660b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error verifying signature: "
661b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << GetErrorString(return_code);
662748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi    return return_code;
663748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  }
664748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi  return TPM_RC_SUCCESS;
665748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi}
666748f7d68284813a78b883f9c05988f6de535fc8aUtkarsh Sanghi
667fded77411da5ef66dff7389e49f40900c19d510cUtkarsh SanghiTPM_RC TpmUtilityImpl::CertifyCreation(TPM_HANDLE key_handle,
668fded77411da5ef66dff7389e49f40900c19d510cUtkarsh Sanghi                                       const std::string& creation_blob) {
669fded77411da5ef66dff7389e49f40900c19d510cUtkarsh Sanghi  TPM2B_CREATION_DATA creation_data;
670fded77411da5ef66dff7389e49f40900c19d510cUtkarsh Sanghi  TPM2B_DIGEST creation_hash;
671fded77411da5ef66dff7389e49f40900c19d510cUtkarsh Sanghi  TPMT_TK_CREATION creation_ticket;
6724dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  if (!factory_.GetBlobParser()->ParseCreationBlob(
6734dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn          creation_blob, &creation_data, &creation_hash, &creation_ticket)) {
674b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error parsing CreationBlob.";
675fded77411da5ef66dff7389e49f40900c19d510cUtkarsh Sanghi    return SAPI_RC_BAD_PARAMETER;
676fded77411da5ef66dff7389e49f40900c19d510cUtkarsh Sanghi  }
677fded77411da5ef66dff7389e49f40900c19d510cUtkarsh Sanghi  TPM2B_DATA qualifying_data;
678fded77411da5ef66dff7389e49f40900c19d510cUtkarsh Sanghi  qualifying_data.size = 0;
679fded77411da5ef66dff7389e49f40900c19d510cUtkarsh Sanghi  TPMT_SIG_SCHEME in_scheme;
680fded77411da5ef66dff7389e49f40900c19d510cUtkarsh Sanghi  in_scheme.scheme = TPM_ALG_NULL;
681fded77411da5ef66dff7389e49f40900c19d510cUtkarsh Sanghi  TPM2B_ATTEST certify_info;
682fded77411da5ef66dff7389e49f40900c19d510cUtkarsh Sanghi  TPMT_SIGNATURE signature;
68330c921db09d27768acc1ea0d8b6a9c8e814f931aLuis Hector Chavez  std::unique_ptr<AuthorizationDelegate> delegate =
684fded77411da5ef66dff7389e49f40900c19d510cUtkarsh Sanghi      factory_.GetPasswordAuthorization("");
6854dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  TPM_RC result = factory_.GetTpm()->CertifyCreationSync(
6864dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      TPM_RH_NULL, "", key_handle, "", qualifying_data, creation_hash,
6874dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      in_scheme, creation_ticket, &certify_info, &signature, delegate.get());
688fded77411da5ef66dff7389e49f40900c19d510cUtkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
689b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
690b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error certifying key creation: " << GetErrorString(result);
691fded77411da5ef66dff7389e49f40900c19d510cUtkarsh Sanghi    return result;
692fded77411da5ef66dff7389e49f40900c19d510cUtkarsh Sanghi  }
693fded77411da5ef66dff7389e49f40900c19d510cUtkarsh Sanghi  return TPM_RC_SUCCESS;
694fded77411da5ef66dff7389e49f40900c19d510cUtkarsh Sanghi}
695fded77411da5ef66dff7389e49f40900c19d510cUtkarsh Sanghi
69633ca033c9665b8496f3491037403ae1574a54227Utkarsh SanghiTPM_RC TpmUtilityImpl::ChangeKeyAuthorizationData(
69733ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi    TPM_HANDLE key_handle,
69833ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi    const std::string& new_password,
6995d3b9451ae2e912aefed0669dd50b2a777ea0ab2Utkarsh Sanghi    AuthorizationDelegate* delegate,
70033ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi    std::string* key_blob) {
7011ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi  TPM_RC result;
702c04decde2a6e9b74395f402818852e752534254bUtkarsh Sanghi  if (delegate == nullptr) {
7031ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi    result = SAPI_RC_INVALID_SESSIONS;
704b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
705b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": This method needs a valid authorization delegate: "
7061ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi               << GetErrorString(result);
7071ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi    return result;
7081ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi  }
70933ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  std::string key_name;
71033ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  std::string parent_name;
7111ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi  result = GetKeyName(key_handle, &key_name);
71233ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
713b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error getting Key name for key_handle: "
71433ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi               << GetErrorString(result);
71533ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi    return result;
71633ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  }
71733ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  result = GetKeyName(kRSAStorageRootKey, &parent_name);
71833ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
719b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error getting Key name for RSA-SRK: "
72033ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi               << GetErrorString(result);
72133ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi    return result;
72233ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  }
72333ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  TPM2B_AUTH new_auth = Make_TPM2B_DIGEST(new_password);
72433ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  TPM2B_PRIVATE new_private_data;
72533ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  new_private_data.size = 0;
7264dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  result = factory_.GetTpm()->ObjectChangeAuthSync(
7274dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      key_handle, key_name, kRSAStorageRootKey, parent_name, new_auth,
7284dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      &new_private_data, delegate);
72933ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
730b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error changing object authorization data: "
73133ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi               << GetErrorString(result);
73233ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi    return result;
73333ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  }
73433ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  if (key_blob) {
7358b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi    TPMT_PUBLIC public_data;
73633ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi    result = GetKeyPublicArea(key_handle, &public_data);
73733ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi    if (result != TPM_RC_SUCCESS) {
73833ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi      return result;
73933ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi    }
7400ebbc58fe6d45378a5b502c33eb1c4289fd8b05bUtkarsh Sanghi    if (!factory_.GetBlobParser()->SerializeKeyBlob(
7414dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn            Make_TPM2B_PUBLIC(public_data), new_private_data, key_blob)) {
7420ebbc58fe6d45378a5b502c33eb1c4289fd8b05bUtkarsh Sanghi      return SAPI_RC_BAD_TCTI_STRUCTURE;
74333ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi    }
74433ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  }
74533ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  return TPM_RC_SUCCESS;
74633ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi}
74733ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi
74833ca033c9665b8496f3491037403ae1574a54227Utkarsh SanghiTPM_RC TpmUtilityImpl::ImportRSAKey(AsymmetricKeyUsage key_type,
74933ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi                                    const std::string& modulus,
75033ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi                                    uint32_t public_exponent,
75133ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi                                    const std::string& prime_factor,
75233ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi                                    const std::string& password,
7535d3b9451ae2e912aefed0669dd50b2a777ea0ab2Utkarsh Sanghi                                    AuthorizationDelegate* delegate,
75433ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi                                    std::string* key_blob) {
7551ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi  TPM_RC result;
756c04decde2a6e9b74395f402818852e752534254bUtkarsh Sanghi  if (delegate == nullptr) {
7571ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi    result = SAPI_RC_INVALID_SESSIONS;
758b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
759b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": This method needs a valid authorization delegate: "
7601ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi               << GetErrorString(result);
7611ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi    return result;
7621ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi  }
76333ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  std::string parent_name;
7641ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi  result = GetKeyName(kRSAStorageRootKey, &parent_name);
76533ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
766b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error getting Key name for RSA-SRK: "
76733ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi               << GetErrorString(result);
76833ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi    return result;
76933ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  }
77033ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  TPMT_PUBLIC public_area = CreateDefaultPublicArea(TPM_ALG_RSA);
77133ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  public_area.object_attributes = kUserWithAuth | kNoDA;
77233ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  switch (key_type) {
77333ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi    case AsymmetricKeyUsage::kDecryptKey:
77433ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi      public_area.object_attributes |= kDecrypt;
77533ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi      break;
77633ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi    case AsymmetricKeyUsage::kSignKey:
77733ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi      public_area.object_attributes |= kSign;
77833ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi      break;
77933ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi    case AsymmetricKeyUsage::kDecryptAndSignKey:
78033ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi      public_area.object_attributes |= (kSign | kDecrypt);
78133ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi      break;
78233ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  }
78333ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  public_area.parameters.rsa_detail.key_bits = modulus.size() * 8;
78433ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  public_area.parameters.rsa_detail.exponent = public_exponent;
78533ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  public_area.unique.rsa = Make_TPM2B_PUBLIC_KEY_RSA(modulus);
78633ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  TPM2B_DATA encryption_key;
78733ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  encryption_key.size = kAesKeySize;
7884dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  CHECK_EQ(RAND_bytes(encryption_key.buffer, encryption_key.size), 1)
7894dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      << "Error generating a cryptographically random Aes Key.";
79033ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  TPM2B_PUBLIC public_data = Make_TPM2B_PUBLIC(public_area);
79133ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  TPM2B_ENCRYPTED_SECRET in_sym_seed = Make_TPM2B_ENCRYPTED_SECRET("");
79233ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  TPMT_SYM_DEF_OBJECT symmetric_alg;
79333ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  symmetric_alg.algorithm = TPM_ALG_AES;
79433ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  symmetric_alg.key_bits.aes = kAesKeySize * 8;
79533ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  symmetric_alg.mode.aes = TPM_ALG_CFB;
79633ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  TPMT_SENSITIVE in_sensitive;
79733ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  in_sensitive.sensitive_type = TPM_ALG_RSA;
79833ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  in_sensitive.auth_value = Make_TPM2B_DIGEST(password);
79933ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  in_sensitive.seed_value = Make_TPM2B_DIGEST("");
80033ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  in_sensitive.sensitive.rsa = Make_TPM2B_PRIVATE_KEY_RSA(prime_factor);
80133ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  TPM2B_PRIVATE private_data;
8024dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  result = EncryptPrivateData(in_sensitive, public_area, &private_data,
8034dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                              &encryption_key);
80433ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
805b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error creating encrypted private struct: "
80633ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi               << GetErrorString(result);
80733ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi    return result;
80833ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  }
80933ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  TPM2B_PRIVATE tpm_private_data;
81033ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  tpm_private_data.size = 0;
8114dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  result = factory_.GetTpm()->ImportSync(
8124dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      kRSAStorageRootKey, parent_name, encryption_key, public_data,
8134dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      private_data, in_sym_seed, symmetric_alg, &tpm_private_data, delegate);
81433ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
815b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
816b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error importing key: " << GetErrorString(result);
81733ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi    return result;
81833ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  }
81933ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  if (key_blob) {
8200ebbc58fe6d45378a5b502c33eb1c4289fd8b05bUtkarsh Sanghi    if (!factory_.GetBlobParser()->SerializeKeyBlob(
8214dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn            public_data, tpm_private_data, key_blob)) {
8220ebbc58fe6d45378a5b502c33eb1c4289fd8b05bUtkarsh Sanghi      return SAPI_RC_BAD_TCTI_STRUCTURE;
82333ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi    }
82433ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  }
82533ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  return TPM_RC_SUCCESS;
82633ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi}
82733ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi
8286465502c740d2599d95e09232c744f6d2ed54505Utkarsh SanghiTPM_RC TpmUtilityImpl::CreateRSAKeyPair(AsymmetricKeyUsage key_type,
8296465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi                                        int modulus_bits,
8306465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi                                        uint32_t public_exponent,
8316465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi                                        const std::string& password,
832fc942a5ffc967b7b2b206aee8b91b3bae1933382Utkarsh Sanghi                                        const std::string& policy_digest,
8336ea135676cf391fac45b0051242ccac935c8bc62Utkarsh Sanghi                                        bool use_only_policy_authorization,
8340ebbc58fe6d45378a5b502c33eb1c4289fd8b05bUtkarsh Sanghi                                        int creation_pcr_index,
8355d3b9451ae2e912aefed0669dd50b2a777ea0ab2Utkarsh Sanghi                                        AuthorizationDelegate* delegate,
836a5a2f2ea49e0085bf8d7f6f2b6e7cd624d710c01Utkarsh Sanghi                                        std::string* key_blob,
837a5a2f2ea49e0085bf8d7f6f2b6e7cd624d710c01Utkarsh Sanghi                                        std::string* creation_blob) {
8386465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  CHECK(key_blob);
8391ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi  TPM_RC result;
840c04decde2a6e9b74395f402818852e752534254bUtkarsh Sanghi  if (delegate == nullptr) {
8411ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi    result = SAPI_RC_INVALID_SESSIONS;
842b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
843b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": This method needs a valid authorization delegate: "
8441ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi               << GetErrorString(result);
8451ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi    return result;
8461ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi  }
84782b03cf80cbe7ab5d5edb2cb46d245721e993a68Utkarsh Sanghi  std::string parent_name;
8481ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi  result = GetKeyName(kRSAStorageRootKey, &parent_name);
8496465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
850b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error getting Key name for RSA-SRK: "
8516465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi               << GetErrorString(result);
8526465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi    return result;
85382b03cf80cbe7ab5d5edb2cb46d245721e993a68Utkarsh Sanghi  }
8542ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi  TPMT_PUBLIC public_area = CreateDefaultPublicArea(TPM_ALG_RSA);
855fc942a5ffc967b7b2b206aee8b91b3bae1933382Utkarsh Sanghi  public_area.auth_policy = Make_TPM2B_DIGEST(policy_digest);
8562ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi  public_area.object_attributes |=
8572ee32a9d61896f544d87ecee24dc25cc33c9ebb3Utkarsh Sanghi      (kSensitiveDataOrigin | kUserWithAuth | kNoDA);
85882b03cf80cbe7ab5d5edb2cb46d245721e993a68Utkarsh Sanghi  switch (key_type) {
85982b03cf80cbe7ab5d5edb2cb46d245721e993a68Utkarsh Sanghi    case AsymmetricKeyUsage::kDecryptKey:
860e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi      public_area.object_attributes |= kDecrypt;
86182b03cf80cbe7ab5d5edb2cb46d245721e993a68Utkarsh Sanghi      break;
86282b03cf80cbe7ab5d5edb2cb46d245721e993a68Utkarsh Sanghi    case AsymmetricKeyUsage::kSignKey:
863e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi      public_area.object_attributes |= kSign;
86482b03cf80cbe7ab5d5edb2cb46d245721e993a68Utkarsh Sanghi      break;
86582b03cf80cbe7ab5d5edb2cb46d245721e993a68Utkarsh Sanghi    case AsymmetricKeyUsage::kDecryptAndSignKey:
866e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi      public_area.object_attributes |= (kSign | kDecrypt);
86782b03cf80cbe7ab5d5edb2cb46d245721e993a68Utkarsh Sanghi      break;
86882b03cf80cbe7ab5d5edb2cb46d245721e993a68Utkarsh Sanghi  }
8696ea135676cf391fac45b0051242ccac935c8bc62Utkarsh Sanghi  if (use_only_policy_authorization && !policy_digest.empty()) {
8706ea135676cf391fac45b0051242ccac935c8bc62Utkarsh Sanghi    public_area.object_attributes |= kAdminWithPolicy;
8716ea135676cf391fac45b0051242ccac935c8bc62Utkarsh Sanghi    public_area.object_attributes &= (~kUserWithAuth);
8726ea135676cf391fac45b0051242ccac935c8bc62Utkarsh Sanghi  }
8736465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  public_area.parameters.rsa_detail.key_bits = modulus_bits;
8746465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  public_area.parameters.rsa_detail.exponent = public_exponent;
8750ebbc58fe6d45378a5b502c33eb1c4289fd8b05bUtkarsh Sanghi  TPML_PCR_SELECTION creation_pcrs = {};
8760ebbc58fe6d45378a5b502c33eb1c4289fd8b05bUtkarsh Sanghi  if (creation_pcr_index == kNoCreationPCR) {
8770ebbc58fe6d45378a5b502c33eb1c4289fd8b05bUtkarsh Sanghi    creation_pcrs.count = 0;
8780ebbc58fe6d45378a5b502c33eb1c4289fd8b05bUtkarsh Sanghi  } else if (creation_pcr_index < 0 ||
8790ebbc58fe6d45378a5b502c33eb1c4289fd8b05bUtkarsh Sanghi             creation_pcr_index > (PCR_SELECT_MIN * 8)) {
880b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
881b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Creation PCR index is not within the allocated bank.";
8820ebbc58fe6d45378a5b502c33eb1c4289fd8b05bUtkarsh Sanghi    return SAPI_RC_BAD_PARAMETER;
8830ebbc58fe6d45378a5b502c33eb1c4289fd8b05bUtkarsh Sanghi  } else {
8840ebbc58fe6d45378a5b502c33eb1c4289fd8b05bUtkarsh Sanghi    creation_pcrs.count = 1;
8850ebbc58fe6d45378a5b502c33eb1c4289fd8b05bUtkarsh Sanghi    creation_pcrs.pcr_selections[0].hash = TPM_ALG_SHA256;
8860ebbc58fe6d45378a5b502c33eb1c4289fd8b05bUtkarsh Sanghi    creation_pcrs.pcr_selections[0].sizeof_select = PCR_SELECT_MIN;
8870ebbc58fe6d45378a5b502c33eb1c4289fd8b05bUtkarsh Sanghi    creation_pcrs.pcr_selections[0].pcr_select[creation_pcr_index / 8] =
8880ebbc58fe6d45378a5b502c33eb1c4289fd8b05bUtkarsh Sanghi        1 << (creation_pcr_index % 8);
8890ebbc58fe6d45378a5b502c33eb1c4289fd8b05bUtkarsh Sanghi  }
890e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi  TPMS_SENSITIVE_CREATE sensitive;
891e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi  sensitive.user_auth = Make_TPM2B_DIGEST(password);
892e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi  sensitive.data = Make_TPM2B_SENSITIVE_DATA("");
8934dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  TPM2B_SENSITIVE_CREATE sensitive_create =
8944dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      Make_TPM2B_SENSITIVE_CREATE(sensitive);
89582b03cf80cbe7ab5d5edb2cb46d245721e993a68Utkarsh Sanghi  TPM2B_DATA outside_info = Make_TPM2B_DATA("");
89682b03cf80cbe7ab5d5edb2cb46d245721e993a68Utkarsh Sanghi  TPM2B_PUBLIC out_public;
8976465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  out_public.size = 0;
8986465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  TPM2B_PRIVATE out_private;
8996465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  out_private.size = 0;
90082b03cf80cbe7ab5d5edb2cb46d245721e993a68Utkarsh Sanghi  TPM2B_CREATION_DATA creation_data;
90182b03cf80cbe7ab5d5edb2cb46d245721e993a68Utkarsh Sanghi  TPM2B_DIGEST creation_hash;
90282b03cf80cbe7ab5d5edb2cb46d245721e993a68Utkarsh Sanghi  TPMT_TK_CREATION creation_ticket;
9034dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  result = factory_.GetTpm()->CreateSync(
9044dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      kRSAStorageRootKey, parent_name, sensitive_create,
9054dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      Make_TPM2B_PUBLIC(public_area), outside_info, creation_pcrs, &out_private,
9064dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      &out_public, &creation_data, &creation_hash, &creation_ticket, delegate);
9076465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
908b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
909b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error creating RSA key: " << GetErrorString(result);
9106465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi    return result;
91182b03cf80cbe7ab5d5edb2cb46d245721e993a68Utkarsh Sanghi  }
9124dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  if (!factory_.GetBlobParser()->SerializeKeyBlob(out_public, out_private,
9134dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                                                  key_blob)) {
9140ebbc58fe6d45378a5b502c33eb1c4289fd8b05bUtkarsh Sanghi    return SAPI_RC_BAD_TCTI_STRUCTURE;
91582b03cf80cbe7ab5d5edb2cb46d245721e993a68Utkarsh Sanghi  }
916a5a2f2ea49e0085bf8d7f6f2b6e7cd624d710c01Utkarsh Sanghi  if (creation_blob) {
9170ebbc58fe6d45378a5b502c33eb1c4289fd8b05bUtkarsh Sanghi    if (!factory_.GetBlobParser()->SerializeCreationBlob(
9184dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn            creation_data, creation_hash, creation_ticket, creation_blob)) {
9190ebbc58fe6d45378a5b502c33eb1c4289fd8b05bUtkarsh Sanghi      return SAPI_RC_BAD_TCTI_STRUCTURE;
920a5a2f2ea49e0085bf8d7f6f2b6e7cd624d710c01Utkarsh Sanghi    }
921a5a2f2ea49e0085bf8d7f6f2b6e7cd624d710c01Utkarsh Sanghi  }
92282b03cf80cbe7ab5d5edb2cb46d245721e993a68Utkarsh Sanghi  return TPM_RC_SUCCESS;
92382b03cf80cbe7ab5d5edb2cb46d245721e993a68Utkarsh Sanghi}
92482b03cf80cbe7ab5d5edb2cb46d245721e993a68Utkarsh Sanghi
9256465502c740d2599d95e09232c744f6d2ed54505Utkarsh SanghiTPM_RC TpmUtilityImpl::LoadKey(const std::string& key_blob,
9265d3b9451ae2e912aefed0669dd50b2a777ea0ab2Utkarsh Sanghi                               AuthorizationDelegate* delegate,
9276465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi                               TPM_HANDLE* key_handle) {
9280ebbc58fe6d45378a5b502c33eb1c4289fd8b05bUtkarsh Sanghi  CHECK(key_handle);
9291ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi  TPM_RC result;
930c04decde2a6e9b74395f402818852e752534254bUtkarsh Sanghi  if (delegate == nullptr) {
9311ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi    result = SAPI_RC_INVALID_SESSIONS;
932b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
933b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": This method needs a valid authorization delegate: "
9341ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi               << GetErrorString(result);
9351ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi    return result;
9361ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi  }
9376465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  std::string parent_name;
9381ef82e4a52abc91d0e8db12500c2da0d8c21f62cUtkarsh Sanghi  result = GetKeyName(kRSAStorageRootKey, &parent_name);
9396465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
940b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
941b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error getting parent key name: " << GetErrorString(result);
9426465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi    return result;
9436465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  }
9446465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  TPM2B_PUBLIC in_public;
9456465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  TPM2B_PRIVATE in_private;
9464dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  if (!factory_.GetBlobParser()->ParseKeyBlob(key_blob, &in_public,
9474dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                                              &in_private)) {
9480ebbc58fe6d45378a5b502c33eb1c4289fd8b05bUtkarsh Sanghi    return SAPI_RC_BAD_TCTI_STRUCTURE;
9496465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  }
9506465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  TPM2B_NAME key_name;
9516465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  key_name.size = 0;
9524dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  result =
9534dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      factory_.GetTpm()->LoadSync(kRSAStorageRootKey, parent_name, in_private,
9544dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                                  in_public, key_handle, &key_name, delegate);
9556465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
956b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error loading key: " << GetErrorString(result);
9576465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi    return result;
9586465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  }
9596465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  return TPM_RC_SUCCESS;
9601c4ff198686b6330dd863f872f52e8efd1a94e3dUtkarsh Sanghi}
9611c4ff198686b6330dd863f872f52e8efd1a94e3dUtkarsh Sanghi
9621c4ff198686b6330dd863f872f52e8efd1a94e3dUtkarsh SanghiTPM_RC TpmUtilityImpl::GetKeyName(TPM_HANDLE handle, std::string* name) {
9638b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  CHECK(name);
9648b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  TPM_RC result;
9658b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  TPMT_PUBLIC public_data;
9668b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  result = GetKeyPublicArea(handle, &public_data);
9678b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
968b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
969b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error fetching public info: " << GetErrorString(result);
9708b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi    return result;
9718b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  }
9728b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  result = ComputeKeyName(public_data, name);
9738b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
974b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
975b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error computing key name: " << GetErrorString(result);
9768b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi    return TPM_RC_SUCCESS;
9771c4ff198686b6330dd863f872f52e8efd1a94e3dUtkarsh Sanghi  }
9781c4ff198686b6330dd863f872f52e8efd1a94e3dUtkarsh Sanghi  return TPM_RC_SUCCESS;
9791c4ff198686b6330dd863f872f52e8efd1a94e3dUtkarsh Sanghi}
9801c4ff198686b6330dd863f872f52e8efd1a94e3dUtkarsh Sanghi
9811c4ff198686b6330dd863f872f52e8efd1a94e3dUtkarsh SanghiTPM_RC TpmUtilityImpl::GetKeyPublicArea(TPM_HANDLE handle,
9828b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi                                        TPMT_PUBLIC* public_data) {
9831c4ff198686b6330dd863f872f52e8efd1a94e3dUtkarsh Sanghi  CHECK(public_data);
9841c4ff198686b6330dd863f872f52e8efd1a94e3dUtkarsh Sanghi  TPM2B_NAME out_name;
9858b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  TPM2B_PUBLIC public_area;
9861c4ff198686b6330dd863f872f52e8efd1a94e3dUtkarsh Sanghi  TPM2B_NAME qualified_name;
9871c4ff198686b6330dd863f872f52e8efd1a94e3dUtkarsh Sanghi  std::string handle_name;  // Unused
9884dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  TPM_RC return_code = factory_.GetTpm()->ReadPublicSync(
9894dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      handle, handle_name, &public_area, &out_name, &qualified_name, nullptr);
9901c4ff198686b6330dd863f872f52e8efd1a94e3dUtkarsh Sanghi  if (return_code) {
991b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
992b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error getting public area for object: " << handle;
9931c4ff198686b6330dd863f872f52e8efd1a94e3dUtkarsh Sanghi    return return_code;
9941c4ff198686b6330dd863f872f52e8efd1a94e3dUtkarsh Sanghi  }
9958b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  *public_data = public_area.public_area;
9961c4ff198686b6330dd863f872f52e8efd1a94e3dUtkarsh Sanghi  return TPM_RC_SUCCESS;
9971c4ff198686b6330dd863f872f52e8efd1a94e3dUtkarsh Sanghi}
9981c4ff198686b6330dd863f872f52e8efd1a94e3dUtkarsh Sanghi
999a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh SanghiTPM_RC TpmUtilityImpl::SealData(const std::string& data_to_seal,
1000a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi                                const std::string& policy_digest,
1001a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi                                AuthorizationDelegate* delegate,
1002a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi                                std::string* sealed_data) {
1003a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  CHECK(sealed_data);
1004a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  TPM_RC result;
1005a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  if (delegate == nullptr) {
1006a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi    result = SAPI_RC_INVALID_SESSIONS;
1007b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1008b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": This method needs a valid authorization delegate: "
1009a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi               << GetErrorString(result);
1010a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi    return result;
1011a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  }
1012a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  std::string parent_name;
1013a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  result = GetKeyName(kRSAStorageRootKey, &parent_name);
1014a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1015b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error getting Key name for RSA-SRK: "
1016a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi               << GetErrorString(result);
1017a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi    return result;
1018a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  }
1019a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  // We seal data to the TPM by creating a KEYEDHASH object with sign and
1020a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  // decrypt attributes disabled.
1021a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  TPMT_PUBLIC public_area = CreateDefaultPublicArea(TPM_ALG_KEYEDHASH);
1022a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  public_area.auth_policy = Make_TPM2B_DIGEST(policy_digest);
1023a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  public_area.object_attributes = kAdminWithPolicy | kNoDA;
1024a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  public_area.unique.keyed_hash.size = 0;
1025a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  TPML_PCR_SELECTION creation_pcrs = {};
1026a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  TPMS_SENSITIVE_CREATE sensitive;
1027a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  sensitive.user_auth = Make_TPM2B_DIGEST("");
1028a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  sensitive.data = Make_TPM2B_SENSITIVE_DATA(data_to_seal);
10294dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  TPM2B_SENSITIVE_CREATE sensitive_create =
10304dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      Make_TPM2B_SENSITIVE_CREATE(sensitive);
1031a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  TPM2B_DATA outside_info = Make_TPM2B_DATA("");
1032a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  TPM2B_PUBLIC out_public;
1033a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  out_public.size = 0;
1034a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  TPM2B_PRIVATE out_private;
1035a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  out_private.size = 0;
1036a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  TPM2B_CREATION_DATA creation_data;
1037a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  TPM2B_DIGEST creation_hash;
1038a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  TPMT_TK_CREATION creation_ticket;
10394dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  result = factory_.GetTpm()->CreateSync(
10404dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      kRSAStorageRootKey, parent_name, sensitive_create,
10414dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      Make_TPM2B_PUBLIC(public_area), outside_info, creation_pcrs, &out_private,
10424dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      &out_public, &creation_data, &creation_hash, &creation_ticket, delegate);
1043a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1044b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1045b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error creating sealed object: " << GetErrorString(result);
1046a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi    return result;
1047a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  }
10484dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  if (!factory_.GetBlobParser()->SerializeKeyBlob(out_public, out_private,
10494dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                                                  sealed_data)) {
1050a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi    return SAPI_RC_BAD_TCTI_STRUCTURE;
1051a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  }
1052a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  return TPM_RC_SUCCESS;
1053a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi}
1054a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi
1055a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh SanghiTPM_RC TpmUtilityImpl::UnsealData(const std::string& sealed_data,
1056a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi                                  AuthorizationDelegate* delegate,
1057a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi                                  std::string* unsealed_data) {
1058a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  CHECK(unsealed_data);
1059a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  TPM_RC result;
1060a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  if (delegate == nullptr) {
1061a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi    result = SAPI_RC_INVALID_SESSIONS;
1062b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1063b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": This method needs a valid authorization delegate: "
1064a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi               << GetErrorString(result);
1065a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi    return result;
1066a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  }
1067a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  TPM_HANDLE object_handle;
106830c921db09d27768acc1ea0d8b6a9c8e814f931aLuis Hector Chavez  std::unique_ptr<AuthorizationDelegate> password_delegate =
1069a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi      factory_.GetPasswordAuthorization("");
1070a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  result = LoadKey(sealed_data, password_delegate.get(), &object_handle);
1071a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1072b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1073b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error loading sealed object: " << GetErrorString(result);
1074a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi    return result;
1075a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  }
1076a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  ScopedKeyHandle sealed_object(factory_, object_handle);
1077a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  std::string object_name;
1078a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  result = GetKeyName(sealed_object.get(), &object_name);
1079a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1080b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1081b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error getting object name: " << GetErrorString(result);
1082a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi    return result;
1083a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  }
1084a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  TPM2B_SENSITIVE_DATA out_data;
1085a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  result = factory_.GetTpm()->UnsealSync(sealed_object.get(), object_name,
1086a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi                                         &out_data, delegate);
1087a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1088b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1089b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error unsealing object: " << GetErrorString(result);
1090a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi    return result;
1091a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  }
1092a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  *unsealed_data = StringFrom_TPM2B_SENSITIVE_DATA(out_data);
1093a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  return TPM_RC_SUCCESS;
1094a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi}
1095a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi
1096a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh SanghiTPM_RC TpmUtilityImpl::StartSession(HmacSession* session) {
10974dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  TPM_RC result = session->StartUnboundSession(true /* enable_encryption */);
1098a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1099b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error starting unbound session: "
1100b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << GetErrorString(result);
1101a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi    return result;
1102a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  }
1103a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  session->SetEntityAuthorizationValue("");
1104a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  return TPM_RC_SUCCESS;
1105a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi}
1106a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi
1107a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh SanghiTPM_RC TpmUtilityImpl::GetPolicyDigestForPcrValue(int pcr_index,
1108a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi                                                  const std::string& pcr_value,
1109a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi                                                  std::string* policy_digest) {
1110a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  CHECK(policy_digest);
111130c921db09d27768acc1ea0d8b6a9c8e814f931aLuis Hector Chavez  std::unique_ptr<PolicySession> session = factory_.GetTrialSession();
1112a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  TPM_RC result = session->StartUnboundSession(false);
1113a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1114b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error starting unbound trial session: "
1115a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi               << GetErrorString(result);
1116a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi    return result;
1117a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  }
1118a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  std::string mutable_pcr_value;
1119a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  if (pcr_value.empty()) {
1120a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi    result = ReadPCR(pcr_index, &mutable_pcr_value);
1121a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi    if (result != TPM_RC_SUCCESS) {
1122b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn      LOG(ERROR) << __func__
1123b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn                 << ": Error reading pcr_value: " << GetErrorString(result);
1124a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi      return result;
1125a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi    }
1126a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  } else {
1127a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi    mutable_pcr_value = pcr_value;
1128a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  }
1129a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  result = session->PolicyPCR(pcr_index, mutable_pcr_value);
1130a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1131b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error restricting policy to PCR value: "
1132a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi               << GetErrorString(result);
1133a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi    return result;
1134a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  }
1135a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  result = session->GetDigest(policy_digest);
1136a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1137b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1138b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error getting policy digest: " << GetErrorString(result);
1139a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi    return result;
1140a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  }
1141a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  return TPM_RC_SUCCESS;
1142a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi}
1143a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi
114439dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh SanghiTPM_RC TpmUtilityImpl::DefineNVSpace(uint32_t index,
114539dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi                                     size_t num_bytes,
1146b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn                                     TPMA_NV attributes,
1147b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn                                     const std::string& authorization_value,
1148b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn                                     const std::string& policy_digest,
11495d3b9451ae2e912aefed0669dd50b2a777ea0ab2Utkarsh Sanghi                                     AuthorizationDelegate* delegate) {
115039dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  TPM_RC result;
115139dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  if (num_bytes > MAX_NV_INDEX_SIZE) {
115239dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    result = SAPI_RC_BAD_SIZE;
1153b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1154b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Cannot define non-volatile space of given size: "
115539dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi               << GetErrorString(result);
115639dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
115739dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
115839dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  if (index > kMaxNVSpaceIndex) {
115939dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    result = SAPI_RC_BAD_PARAMETER;
1160b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1161b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Cannot define non-volatile space with the given index: "
116239dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi               << GetErrorString(result);
116339dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
116439dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
1165c04decde2a6e9b74395f402818852e752534254bUtkarsh Sanghi  if (delegate == nullptr) {
116639dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    result = SAPI_RC_INVALID_SESSIONS;
1167b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1168b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": This method needs a valid authorization delegate: "
116939dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi               << GetErrorString(result);
117039dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
117139dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
117239dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  uint32_t nv_index = NV_INDEX_FIRST + index;
117339dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  TPMS_NV_PUBLIC public_data;
117439dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  public_data.nv_index = nv_index;
117539dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  public_data.name_alg = TPM_ALG_SHA256;
1176b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  public_data.attributes = attributes;
1177b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  public_data.auth_policy = Make_TPM2B_DIGEST(policy_digest);
117839dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  public_data.data_size = num_bytes;
1179b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  TPM2B_AUTH authorization = Make_TPM2B_DIGEST(authorization_value);
118039dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  TPM2B_NV_PUBLIC public_area = Make_TPM2B_NV_PUBLIC(public_data);
118139dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  result = factory_.GetTpm()->NV_DefineSpaceSync(
11824dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      TPM_RH_OWNER, NameFromHandle(TPM_RH_OWNER), authorization, public_area,
11835d3b9451ae2e912aefed0669dd50b2a777ea0ab2Utkarsh Sanghi      delegate);
118439dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1185b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error defining non-volatile space: "
118639dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi               << GetErrorString(result);
118739dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
118839dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
11896537cf15412f04bda9fc1a80f7209d55c955c61fUtkarsh Sanghi  nvram_public_area_map_[index] = public_data;
119039dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  return TPM_RC_SUCCESS;
119139dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi}
119239dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi
119339dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh SanghiTPM_RC TpmUtilityImpl::DestroyNVSpace(uint32_t index,
11945d3b9451ae2e912aefed0669dd50b2a777ea0ab2Utkarsh Sanghi                                      AuthorizationDelegate* delegate) {
119539dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  TPM_RC result;
119639dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  if (index > kMaxNVSpaceIndex) {
119739dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    result = SAPI_RC_BAD_PARAMETER;
1198b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1199b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Cannot undefine non-volatile space with the given index: "
120039dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi               << GetErrorString(result);
120139dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
120239dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
1203c04decde2a6e9b74395f402818852e752534254bUtkarsh Sanghi  if (delegate == nullptr) {
120439dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    result = SAPI_RC_INVALID_SESSIONS;
1205b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1206b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": This method needs a valid authorization delegate: "
120739dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi               << GetErrorString(result);
120839dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
120939dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
121039dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  std::string nv_name;
121139dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  result = GetNVSpaceName(index, &nv_name);
121239dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
121339dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
121439dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
121539dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  uint32_t nv_index = NV_INDEX_FIRST + index;
121639dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  result = factory_.GetTpm()->NV_UndefineSpaceSync(
12174dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      TPM_RH_OWNER, NameFromHandle(TPM_RH_OWNER), nv_index, nv_name, delegate);
121839dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1219b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error undefining non-volatile space: "
122039dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi               << GetErrorString(result);
122139dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
122239dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
12236537cf15412f04bda9fc1a80f7209d55c955c61fUtkarsh Sanghi  nvram_public_area_map_.erase(index);
122439dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  return TPM_RC_SUCCESS;
122539dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi}
122639dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi
122739dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh SanghiTPM_RC TpmUtilityImpl::LockNVSpace(uint32_t index,
1228b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn                                   bool lock_read,
1229b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn                                   bool lock_write,
1230b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn                                   bool using_owner_authorization,
12315d3b9451ae2e912aefed0669dd50b2a777ea0ab2Utkarsh Sanghi                                   AuthorizationDelegate* delegate) {
123239dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  TPM_RC result;
123339dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  if (index > kMaxNVSpaceIndex) {
123439dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    result = SAPI_RC_BAD_PARAMETER;
1235b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1236b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Cannot lock non-volatile space with the given index: "
123739dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi               << GetErrorString(result);
123839dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
123939dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
124039dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  std::string nv_name;
124139dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  result = GetNVSpaceName(index, &nv_name);
124239dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
124339dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
124439dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
124539dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  uint32_t nv_index = NV_INDEX_FIRST + index;
1246b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  TPMI_RH_NV_AUTH auth_target = nv_index;
1247b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  std::string auth_target_name = nv_name;
1248b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  if (using_owner_authorization) {
1249b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    auth_target = TPM_RH_OWNER;
1250b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    auth_target_name = NameFromHandle(TPM_RH_OWNER);
125139dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
12526537cf15412f04bda9fc1a80f7209d55c955c61fUtkarsh Sanghi  auto it = nvram_public_area_map_.find(index);
1253b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  if (lock_read) {
1254b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    result = factory_.GetTpm()->NV_ReadLockSync(auth_target, auth_target_name,
1255b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn                                                nv_index, nv_name, delegate);
1256b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    if (result != TPM_RC_SUCCESS) {
1257b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn      LOG(ERROR) << __func__ << ": Error locking non-volatile space read: "
1258b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn                 << GetErrorString(result);
1259b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn      return result;
1260b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    }
1261b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    if (it != nvram_public_area_map_.end()) {
1262b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn      it->second.attributes |= TPMA_NV_READLOCKED;
1263b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    }
1264b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  }
1265b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  if (lock_write) {
1266b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    result = factory_.GetTpm()->NV_WriteLockSync(auth_target, auth_target_name,
1267b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn                                                 nv_index, nv_name, delegate);
1268b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    if (result != TPM_RC_SUCCESS) {
1269b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn      LOG(ERROR) << __func__ << ": Error locking non-volatile space write: "
1270b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn                 << GetErrorString(result);
1271b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn      return result;
1272b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    }
1273b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    if (it != nvram_public_area_map_.end()) {
1274b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn      it->second.attributes |= TPMA_NV_WRITELOCKED;
1275b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    }
12766537cf15412f04bda9fc1a80f7209d55c955c61fUtkarsh Sanghi  }
127739dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  return TPM_RC_SUCCESS;
127839dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi}
127939dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi
128039dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh SanghiTPM_RC TpmUtilityImpl::WriteNVSpace(uint32_t index,
128139dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi                                    uint32_t offset,
128239dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi                                    const std::string& nvram_data,
1283b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn                                    bool using_owner_authorization,
1284b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn                                    bool extend,
12855d3b9451ae2e912aefed0669dd50b2a777ea0ab2Utkarsh Sanghi                                    AuthorizationDelegate* delegate) {
128639dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  TPM_RC result;
128739dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  if (nvram_data.size() > MAX_NV_BUFFER_SIZE) {
128839dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    result = SAPI_RC_BAD_SIZE;
1289b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Insufficient buffer for non-volatile write: "
129039dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi               << GetErrorString(result);
129139dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
129239dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
129339dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  if (index > kMaxNVSpaceIndex) {
129439dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    result = SAPI_RC_BAD_PARAMETER;
1295b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1296b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Cannot write to non-volatile space with the given index: "
129739dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi               << GetErrorString(result);
129839dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
129939dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
130039dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  std::string nv_name;
130139dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  result = GetNVSpaceName(index, &nv_name);
130239dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
130339dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
130439dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
130539dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  uint32_t nv_index = NV_INDEX_FIRST + index;
1306b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  TPMI_RH_NV_AUTH auth_target = nv_index;
1307b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  std::string auth_target_name = nv_name;
1308b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  if (using_owner_authorization) {
1309b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    auth_target = TPM_RH_OWNER;
1310b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    auth_target_name = NameFromHandle(TPM_RH_OWNER);
1311b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  }
1312b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  if (extend) {
1313b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    result = factory_.GetTpm()->NV_ExtendSync(
1314b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn        auth_target, auth_target_name, nv_index, nv_name,
1315b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn        Make_TPM2B_MAX_NV_BUFFER(nvram_data), delegate);
1316b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  } else {
1317b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    result = factory_.GetTpm()->NV_WriteSync(
1318b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn        auth_target, auth_target_name, nv_index, nv_name,
1319b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn        Make_TPM2B_MAX_NV_BUFFER(nvram_data), offset, delegate);
1320b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  }
132139dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1322b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error writing to non-volatile space: "
132339dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi               << GetErrorString(result);
132439dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
132539dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
13266537cf15412f04bda9fc1a80f7209d55c955c61fUtkarsh Sanghi  auto it = nvram_public_area_map_.find(index);
13276537cf15412f04bda9fc1a80f7209d55c955c61fUtkarsh Sanghi  if (it != nvram_public_area_map_.end()) {
13286537cf15412f04bda9fc1a80f7209d55c955c61fUtkarsh Sanghi    it->second.attributes |= TPMA_NV_WRITTEN;
13296537cf15412f04bda9fc1a80f7209d55c955c61fUtkarsh Sanghi  }
133039dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  return TPM_RC_SUCCESS;
133139dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi}
133239dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi
133339dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh SanghiTPM_RC TpmUtilityImpl::ReadNVSpace(uint32_t index,
133439dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi                                   uint32_t offset,
133539dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi                                   size_t num_bytes,
1336b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn                                   bool using_owner_authorization,
133739dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi                                   std::string* nvram_data,
13385d3b9451ae2e912aefed0669dd50b2a777ea0ab2Utkarsh Sanghi                                   AuthorizationDelegate* delegate) {
133939dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  TPM_RC result;
134039dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  if (num_bytes > MAX_NV_BUFFER_SIZE) {
134139dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    result = SAPI_RC_BAD_SIZE;
1342b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Insufficient buffer for non-volatile read: "
134339dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi               << GetErrorString(result);
134439dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
134539dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
134639dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  if (index > kMaxNVSpaceIndex) {
134739dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    result = SAPI_RC_BAD_PARAMETER;
1348b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1349b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Cannot read from non-volatile space with the given index: "
135039dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi               << GetErrorString(result);
135139dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
135239dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
135339dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  std::string nv_name;
135439dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  result = GetNVSpaceName(index, &nv_name);
135539dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
135639dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
135739dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
135839dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  uint32_t nv_index = NV_INDEX_FIRST + index;
1359b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  TPMI_RH_NV_AUTH auth_target = nv_index;
1360b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  std::string auth_target_name = nv_name;
1361b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  if (using_owner_authorization) {
1362b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    auth_target = TPM_RH_OWNER;
1363b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    auth_target_name = NameFromHandle(TPM_RH_OWNER);
1364b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  }
136539dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  TPM2B_MAX_NV_BUFFER data_buffer;
136639dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  data_buffer.size = 0;
1367b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  result = factory_.GetTpm()->NV_ReadSync(auth_target, auth_target_name,
1368b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn                                          nv_index, nv_name, num_bytes, offset,
1369b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn                                          &data_buffer, delegate);
137039dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1371b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error reading from non-volatile space: "
137239dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi               << GetErrorString(result);
137339dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
137439dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
137539dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  nvram_data->assign(StringFrom_TPM2B_MAX_NV_BUFFER(data_buffer));
137639dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  return TPM_RC_SUCCESS;
137739dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi}
137839dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi
137939dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh SanghiTPM_RC TpmUtilityImpl::GetNVSpaceName(uint32_t index, std::string* name) {
138039dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  TPM_RC result;
138139dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  if (index > kMaxNVSpaceIndex) {
138239dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    result = SAPI_RC_BAD_PARAMETER;
1383b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1384b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Cannot read from non-volatile space with the given index: "
138539dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi               << GetErrorString(result);
138639dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
138739dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
138839dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  TPMS_NV_PUBLIC nv_public_data;
138939dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  result = GetNVSpacePublicArea(index, &nv_public_data);
139039dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
139139dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
139239dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
139339dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  result = ComputeNVSpaceName(nv_public_data, name);
139439dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
139539dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
139639dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
139739dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  return TPM_RC_SUCCESS;
139839dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi}
139939dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi
140039dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh SanghiTPM_RC TpmUtilityImpl::GetNVSpacePublicArea(uint32_t index,
140139dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi                                            TPMS_NV_PUBLIC* public_data) {
140239dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  TPM_RC result;
140339dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  if (index > kMaxNVSpaceIndex) {
140439dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    result = SAPI_RC_BAD_PARAMETER;
1405b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1406b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Cannot read from non-volatile space with the given index: "
140739dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi               << GetErrorString(result);
140839dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
140939dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
14106537cf15412f04bda9fc1a80f7209d55c955c61fUtkarsh Sanghi  auto it = nvram_public_area_map_.find(index);
14116537cf15412f04bda9fc1a80f7209d55c955c61fUtkarsh Sanghi  if (it != nvram_public_area_map_.end()) {
14126537cf15412f04bda9fc1a80f7209d55c955c61fUtkarsh Sanghi    *public_data = it->second;
14136537cf15412f04bda9fc1a80f7209d55c955c61fUtkarsh Sanghi    return TPM_RC_SUCCESS;
14146537cf15412f04bda9fc1a80f7209d55c955c61fUtkarsh Sanghi  }
141539dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  TPM2B_NAME nvram_name;
141639dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  TPM2B_NV_PUBLIC public_area;
141739dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  public_area.nv_public.nv_index = 0;
141839dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  uint32_t nv_index = NV_INDEX_FIRST + index;
14194dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  result = factory_.GetTpm()->NV_ReadPublicSync(nv_index, "", &public_area,
14204dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                                                &nvram_name, nullptr);
142139dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1422b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1423b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error reading non-volatile space public information: "
142439dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi               << GetErrorString(result);
142539dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
142639dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
142739dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  *public_data = public_area.nv_public;
14286537cf15412f04bda9fc1a80f7209d55c955c61fUtkarsh Sanghi  nvram_public_area_map_[index] = public_area.nv_public;
142939dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  return TPM_RC_SUCCESS;
143039dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi}
143139dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi
1432b180754b429c078cbc99175a6059a8b5d0491002Darren KrahnTPM_RC TpmUtilityImpl::ListNVSpaces(std::vector<uint32_t>* index_list) {
1433b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  TPM_RC result;
1434b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  TPMI_YES_NO more_data = YES;
1435b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  TPMS_CAPABILITY_DATA capability_data;
1436b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  TPM_HANDLE handle_base = HR_NV_INDEX;
1437b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  while (more_data == YES) {
1438b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    result = factory_.GetTpm()->GetCapabilitySync(
1439b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn        TPM_CAP_HANDLES, handle_base, MAX_CAP_HANDLES, &more_data,
1440b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn        &capability_data, nullptr /*authorization_delegate*/);
1441b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    if (result != TPM_RC_SUCCESS) {
1442b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn      LOG(ERROR) << __func__
1443b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn                 << ": Error querying NV spaces: " << GetErrorString(result);
1444b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn      return result;
1445b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    }
1446b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    if (capability_data.capability != TPM_CAP_HANDLES) {
1447b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn      LOG(ERROR) << __func__ << ": Invalid capability type.";
1448b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn      return SAPI_RC_MALFORMED_RESPONSE;
1449b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    }
1450b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    TPML_HANDLE& handles = capability_data.data.handles;
1451b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    for (uint32_t i = 0; i < handles.count; ++i) {
1452b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn      index_list->push_back(handles.handle[i] & HR_HANDLE_MASK);
1453b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn      handle_base = handles.handle[i] + 1;
1454b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    }
1455b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  }
1456b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  return TPM_RC_SUCCESS;
1457b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn}
1458b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn
1459b180754b429c078cbc99175a6059a8b5d0491002Darren KrahnTPM_RC TpmUtilityImpl::SetDictionaryAttackParameters(
1460b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    uint32_t max_tries,
1461b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    uint32_t recovery_time,
1462b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    uint32_t lockout_recovery,
1463b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    AuthorizationDelegate* delegate) {
1464b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  return factory_.GetTpm()->DictionaryAttackParametersSync(
1465b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn      TPM_RH_LOCKOUT, NameFromHandle(TPM_RH_LOCKOUT), max_tries, recovery_time,
1466b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn      lockout_recovery, delegate);
1467b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn}
1468b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn
1469b180754b429c078cbc99175a6059a8b5d0491002Darren KrahnTPM_RC TpmUtilityImpl::ResetDictionaryAttackLock(
1470b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    AuthorizationDelegate* delegate) {
1471b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn  return factory_.GetTpm()->DictionaryAttackLockResetSync(
1472b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn      TPM_RH_LOCKOUT, NameFromHandle(TPM_RH_LOCKOUT), delegate);
1473b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn}
1474b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn
147566d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh SanghiTPM_RC TpmUtilityImpl::SetKnownOwnerPassword(
147666d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi    const std::string& known_owner_password) {
147730c921db09d27768acc1ea0d8b6a9c8e814f931aLuis Hector Chavez  std::unique_ptr<TpmState> tpm_state(factory_.GetTpmState());
147866d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  TPM_RC result = tpm_state->Initialize();
147966d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  if (result) {
148066d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi    LOG(ERROR) << __func__ << ": " << GetErrorString(result);
148166d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi    return result;
148266d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  }
148330c921db09d27768acc1ea0d8b6a9c8e814f931aLuis Hector Chavez  std::unique_ptr<AuthorizationDelegate> delegate =
148466d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi      factory_.GetPasswordAuthorization("");
148566d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  if (tpm_state->IsOwnerPasswordSet()) {
1486b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(INFO) << __func__ << ": Owner password is already set. "
148766d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi              << "This is normal if ownership is already taken.";
148866d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi    return TPM_RC_SUCCESS;
148966d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  }
14904dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  result = SetHierarchyAuthorization(TPM_RH_OWNER, known_owner_password,
149166d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi                                     delegate.get());
149266d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  if (result) {
1493b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error setting storage hierarchy authorization "
149466d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi               << "to its default value: " << GetErrorString(result);
149566d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi    return result;
149666d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  }
149766d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  return TPM_RC_SUCCESS;
149866d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi}
149966d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi
150066d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh SanghiTPM_RC TpmUtilityImpl::CreateStorageRootKeys(
150166d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi    const std::string& owner_password) {
150266d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  TPM_RC result = TPM_RC_SUCCESS;
150330c921db09d27768acc1ea0d8b6a9c8e814f931aLuis Hector Chavez  std::unique_ptr<TpmState> tpm_state(factory_.GetTpmState());
150466d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  result = tpm_state->Initialize();
150566d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  if (result) {
150666d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi    LOG(ERROR) << __func__ << ": " << GetErrorString(result);
150766d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi    return result;
150866d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  }
150966d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  Tpm* tpm = factory_.GetTpm();
151066d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  TPML_PCR_SELECTION creation_pcrs;
151166d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  creation_pcrs.count = 0;
151266d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  TPMS_SENSITIVE_CREATE sensitive;
151366d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  sensitive.user_auth = Make_TPM2B_DIGEST("");
151466d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  sensitive.data = Make_TPM2B_SENSITIVE_DATA("");
151566d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  TPM_HANDLE object_handle;
151666d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  TPM2B_CREATION_DATA creation_data;
151766d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  TPM2B_DIGEST creation_digest;
151866d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  TPMT_TK_CREATION creation_ticket;
151966d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  TPM2B_NAME object_name;
152066d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  object_name.size = 0;
152130c921db09d27768acc1ea0d8b6a9c8e814f931aLuis Hector Chavez  std::unique_ptr<AuthorizationDelegate> delegate =
152266d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi      factory_.GetPasswordAuthorization(owner_password);
152387b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn  if (tpm_state->IsRSASupported()) {
152487b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn    bool exists = false;
152587b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn    result = DoesPersistentKeyExist(kRSAStorageRootKey, &exists);
152666d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi    if (result) {
152766d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi      return result;
152866d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi    }
152987b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn    if (!exists) {
153087b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn      TPMT_PUBLIC public_area = CreateDefaultPublicArea(TPM_ALG_RSA);
15314dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      public_area.object_attributes |= (kSensitiveDataOrigin | kUserWithAuth |
15324dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                                        kNoDA | kRestricted | kDecrypt);
153387b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn      public_area.parameters.rsa_detail.symmetric.algorithm = TPM_ALG_AES;
153487b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn      public_area.parameters.rsa_detail.symmetric.key_bits.aes = 128;
153587b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn      public_area.parameters.rsa_detail.symmetric.mode.aes = TPM_ALG_CFB;
153687b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn      TPM2B_PUBLIC rsa_public_area = Make_TPM2B_PUBLIC(public_area);
15374dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      result = tpm->CreatePrimarySync(
15384dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn          TPM_RH_OWNER, NameFromHandle(TPM_RH_OWNER),
15394dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn          Make_TPM2B_SENSITIVE_CREATE(sensitive), rsa_public_area,
15404dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn          Make_TPM2B_DATA(""), creation_pcrs, &object_handle, &rsa_public_area,
15414dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn          &creation_data, &creation_digest, &creation_ticket, &object_name,
15424dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn          delegate.get());
154387b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn      if (result) {
154487b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn        LOG(ERROR) << __func__ << ": " << GetErrorString(result);
154587b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn        return result;
154687b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn      }
154787b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn      ScopedKeyHandle rsa_key(factory_, object_handle);
154887b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn      // This will make the key persistent.
15494dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      result = tpm->EvictControlSync(TPM_RH_OWNER, NameFromHandle(TPM_RH_OWNER),
155087b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn                                     object_handle,
155187b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn                                     StringFrom_TPM2B_NAME(object_name),
15524dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                                     kRSAStorageRootKey, delegate.get());
155387b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn      if (result != TPM_RC_SUCCESS) {
155487b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn        LOG(ERROR) << __func__ << ": " << GetErrorString(result);
155587b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn        return result;
155687b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn      }
1557b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn      LOG(INFO) << __func__ << ": Created RSA SRK.";
155887b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn    } else {
1559b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn      LOG(INFO) << __func__ << ": Skip RSA SRK because it already exists.";
156066d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi    }
156166d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  } else {
1562b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(INFO) << __func__ << ": Skip RSA SRK because RSA is not supported.";
156366d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  }
156466d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi
156566d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  // Do it again for ECC.
156687b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn  if (tpm_state->IsRSASupported()) {
156787b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn    bool exists = false;
156887b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn    result = DoesPersistentKeyExist(kECCStorageRootKey, &exists);
156966d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi    if (result) {
157066d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi      return result;
157166d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi    }
157287b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn    if (!exists) {
157387b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn      TPMT_PUBLIC public_area = CreateDefaultPublicArea(TPM_ALG_ECC);
15744dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      public_area.object_attributes |= (kSensitiveDataOrigin | kUserWithAuth |
15754dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                                        kNoDA | kRestricted | kDecrypt);
157687b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn      public_area.parameters.ecc_detail.symmetric.algorithm = TPM_ALG_AES;
157787b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn      public_area.parameters.ecc_detail.symmetric.key_bits.aes = 128;
157887b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn      public_area.parameters.ecc_detail.symmetric.mode.aes = TPM_ALG_CFB;
157987b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn      TPM2B_PUBLIC ecc_public_area = Make_TPM2B_PUBLIC(public_area);
15804dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      result = tpm->CreatePrimarySync(
15814dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn          TPM_RH_OWNER, NameFromHandle(TPM_RH_OWNER),
15824dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn          Make_TPM2B_SENSITIVE_CREATE(sensitive), ecc_public_area,
15834dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn          Make_TPM2B_DATA(""), creation_pcrs, &object_handle, &ecc_public_area,
15844dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn          &creation_data, &creation_digest, &creation_ticket, &object_name,
15854dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn          delegate.get());
158687b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn      if (result) {
158787b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn        LOG(ERROR) << __func__ << ": " << GetErrorString(result);
158887b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn        return result;
158987b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn      }
159087b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn      ScopedKeyHandle ecc_key(factory_, object_handle);
159187b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn      // This will make the key persistent.
15924dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      result = tpm->EvictControlSync(TPM_RH_OWNER, NameFromHandle(TPM_RH_OWNER),
159387b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn                                     object_handle,
159487b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn                                     StringFrom_TPM2B_NAME(object_name),
15954dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                                     kECCStorageRootKey, delegate.get());
159687b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn      if (result != TPM_RC_SUCCESS) {
159787b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn        LOG(ERROR) << __func__ << ": " << GetErrorString(result);
159887b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn        return result;
159987b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn      }
1600b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn      LOG(INFO) << __func__ << ": Created ECC SRK.";
160187b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn    } else {
1602b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn      LOG(INFO) << __func__ << ": Skip ECC SRK because it already exists.";
160366d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi    }
160466d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  } else {
1605b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(INFO) << __func__ << ": Skip ECC SRK because ECC is not supported.";
160666d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  }
160766d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  return TPM_RC_SUCCESS;
160866d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi}
160966d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi
161066d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh SanghiTPM_RC TpmUtilityImpl::CreateSaltingKey(const std::string& owner_password) {
161187b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn  bool exists = false;
161287b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn  TPM_RC result = DoesPersistentKeyExist(kSaltingKey, &exists);
161387b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn  if (result != TPM_RC_SUCCESS) {
161466d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi    return result;
161566d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  }
161687b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn  if (exists) {
1617b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(INFO) << __func__ << ": Salting key already exists.";
161887b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn    return TPM_RC_SUCCESS;
161987b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn  }
162066d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  std::string parent_name;
162166d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  result = GetKeyName(kRSAStorageRootKey, &parent_name);
162266d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1623b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error getting Key name for RSA-SRK: "
162466d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi               << GetErrorString(result);
162566d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi    return result;
162666d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  }
162787b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn  TPMT_PUBLIC public_area = CreateDefaultPublicArea(TPM_ALG_RSA);
162812a12083abb8fc9b1bd9ac69e2be983bb7227818Jocelyn Bohr  public_area.name_alg = TPM_ALG_SHA256;
162966d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  public_area.object_attributes |=
163066d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi      kSensitiveDataOrigin | kUserWithAuth | kNoDA | kDecrypt;
163166d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  TPML_PCR_SELECTION creation_pcrs;
163266d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  creation_pcrs.count = 0;
163366d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  TPMS_SENSITIVE_CREATE sensitive;
163466d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  sensitive.user_auth = Make_TPM2B_DIGEST("");
163566d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  sensitive.data = Make_TPM2B_SENSITIVE_DATA("");
16364dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  TPM2B_SENSITIVE_CREATE sensitive_create =
16374dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      Make_TPM2B_SENSITIVE_CREATE(sensitive);
163866d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  TPM2B_DATA outside_info = Make_TPM2B_DATA("");
163966d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi
164066d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  TPM2B_PRIVATE out_private;
164166d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  out_private.size = 0;
164266d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  TPM2B_PUBLIC out_public;
164366d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  out_public.size = 0;
164466d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  TPM2B_CREATION_DATA creation_data;
164566d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  TPM2B_DIGEST creation_hash;
164666d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  TPMT_TK_CREATION creation_ticket;
164766d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  // TODO(usanghi): MITM vulnerability with SaltingKey creation.
164866d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  // Currently we cannot verify the key returned by the TPM.
164966d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  // crbug.com/442331
165030c921db09d27768acc1ea0d8b6a9c8e814f931aLuis Hector Chavez  std::unique_ptr<AuthorizationDelegate> delegate =
165166d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi      factory_.GetPasswordAuthorization("");
16524dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  result = factory_.GetTpm()->CreateSync(
16534dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      kRSAStorageRootKey, parent_name, sensitive_create,
16544dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      Make_TPM2B_PUBLIC(public_area), outside_info, creation_pcrs, &out_private,
16554dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      &out_public, &creation_data, &creation_hash, &creation_ticket,
16564dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      delegate.get());
165766d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1658b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1659b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error creating salting key: " << GetErrorString(result);
166066d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi    return result;
166166d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  }
166266d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  TPM2B_NAME key_name;
166366d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  key_name.size = 0;
166466d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  TPM_HANDLE key_handle;
16654dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  result = factory_.GetTpm()->LoadSync(kRSAStorageRootKey, parent_name,
16664dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                                       out_private, out_public, &key_handle,
16674dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn                                       &key_name, delegate.get());
166866d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1669b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1670b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error loading salting key: " << GetErrorString(result);
167166d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi    return result;
167266d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  }
167366d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  ScopedKeyHandle key(factory_, key_handle);
167430c921db09d27768acc1ea0d8b6a9c8e814f931aLuis Hector Chavez  std::unique_ptr<AuthorizationDelegate> owner_delegate =
167566d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi      factory_.GetPasswordAuthorization(owner_password);
16764dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  result = factory_.GetTpm()->EvictControlSync(
16774dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      TPM_RH_OWNER, NameFromHandle(TPM_RH_OWNER), key_handle,
16784dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      StringFrom_TPM2B_NAME(key_name), kSaltingKey, owner_delegate.get());
167966d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
168066d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi    LOG(ERROR) << __func__ << ": " << GetErrorString(result);
168166d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi    return result;
168266d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  }
168366d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi  return TPM_RC_SUCCESS;
168466d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi}
168566d0d268e571647ca99a2bdf4835d967449d7ddeUtkarsh Sanghi
16866465502c740d2599d95e09232c744f6d2ed54505Utkarsh SanghiTPMT_PUBLIC TpmUtilityImpl::CreateDefaultPublicArea(TPM_ALG_ID key_alg) {
16876465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  TPMT_PUBLIC public_area;
16886465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  public_area.name_alg = TPM_ALG_SHA256;
16896465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  public_area.auth_policy = Make_TPM2B_DIGEST("");
16906465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  public_area.object_attributes = kFixedTPM | kFixedParent;
16916465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  if (key_alg == TPM_ALG_RSA) {
16926465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi    public_area.type = TPM_ALG_RSA;
16936465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi    public_area.parameters.rsa_detail.scheme.scheme = TPM_ALG_NULL;
16946465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi    public_area.parameters.rsa_detail.symmetric.algorithm = TPM_ALG_NULL;
16956465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi    public_area.parameters.rsa_detail.key_bits = 2048;
16966465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi    public_area.parameters.rsa_detail.exponent = 0;
16976465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi    public_area.unique.rsa = Make_TPM2B_PUBLIC_KEY_RSA("");
16986465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  } else if (key_alg == TPM_ALG_ECC) {
16996465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi    public_area.type = TPM_ALG_ECC;
17006465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi    public_area.parameters.ecc_detail.curve_id = TPM_ECC_NIST_P256;
1701f5b84250f024416a2bf47b088ea79a22cba1240eUtkarsh Sanghi    public_area.parameters.ecc_detail.kdf.scheme = TPM_ALG_NULL;
17026465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi    public_area.unique.ecc.x = Make_TPM2B_ECC_PARAMETER("");
17036465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi    public_area.unique.ecc.y = Make_TPM2B_ECC_PARAMETER("");
1704a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi  } else if (key_alg == TPM_ALG_KEYEDHASH) {
1705a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi    public_area.type = TPM_ALG_KEYEDHASH;
1706a6e332ee7f5fe52c1291d961dbeda975c8272044Utkarsh Sanghi    public_area.parameters.keyed_hash_detail.scheme.scheme = TPM_ALG_NULL;
17076465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  } else {
1708b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(WARNING) << __func__
1709b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn                 << ": Unrecognized key_type. Not filling parameters.";
17106465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  }
17116465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi  return public_area;
17126465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi}
17136465502c740d2599d95e09232c744f6d2ed54505Utkarsh Sanghi
171452e2a45f585fbe34032eae5b094a092afdf217caDarren KrahnTPM_RC TpmUtilityImpl::SetHierarchyAuthorization(
171552e2a45f585fbe34032eae5b094a092afdf217caDarren Krahn    TPMI_RH_HIERARCHY_AUTH hierarchy,
171652e2a45f585fbe34032eae5b094a092afdf217caDarren Krahn    const std::string& password,
171752e2a45f585fbe34032eae5b094a092afdf217caDarren Krahn    AuthorizationDelegate* authorization) {
1718e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi  if (password.size() > kMaxPasswordLength) {
1719b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Hierarchy passwords can be at most "
1720b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << kMaxPasswordLength
1721e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi               << " bytes. Current password length is: " << password.size();
1722e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi    return SAPI_RC_BAD_SIZE;
1723e8b9a556d4561617747fed4ee5ced70fce9a4392Utkarsh Sanghi  }
172452e2a45f585fbe34032eae5b094a092afdf217caDarren Krahn  return factory_.GetTpm()->HierarchyChangeAuthSync(
17254dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      hierarchy, NameFromHandle(hierarchy), Make_TPM2B_DIGEST(password),
172652e2a45f585fbe34032eae5b094a092afdf217caDarren Krahn      authorization);
1727c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn}
1728c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn
1729c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren KrahnTPM_RC TpmUtilityImpl::DisablePlatformHierarchy(
1730c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn    AuthorizationDelegate* authorization) {
1731c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn  return factory_.GetTpm()->HierarchyControlSync(
1732c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn      TPM_RH_PLATFORM,  // The authorizing entity.
1733c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn      NameFromHandle(TPM_RH_PLATFORM),
1734c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn      TPM_RH_PLATFORM,  // The target hierarchy.
17354dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      0,                // Disable.
1736c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn      authorization);
1737c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn}
1738c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn
173933ca033c9665b8496f3491037403ae1574a54227Utkarsh SanghiTPM_RC TpmUtilityImpl::ComputeKeyName(const TPMT_PUBLIC& public_area,
174033ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi                                      std::string* object_name) {
17418b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  CHECK(object_name);
17428b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  if (public_area.type == TPM_ALG_ERROR) {
17438b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi    // We do not compute a name for empty public area.
17448b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi    object_name->clear();
17458b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi    return TPM_RC_SUCCESS;
17468b2bf63478b292937f85b3b0e215882af461a999Utkarsh Sanghi  }
174733ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  std::string serialized_public_area;
174833ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  TPM_RC result = Serialize_TPMT_PUBLIC(public_area, &serialized_public_area);
174933ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1750b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1751b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error serializing public area: " << GetErrorString(result);
175233ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi    return result;
175380c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn  }
175433ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  std::string serialized_name_alg;
175533ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  result = Serialize_TPM_ALG_ID(TPM_ALG_SHA256, &serialized_name_alg);
175633ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1757b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1758b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error serializing public area: " << GetErrorString(result);
175933ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi    return result;
176080c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn  }
176133ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  object_name->assign(serialized_name_alg +
176233ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi                      crypto::SHA256HashString(serialized_public_area));
176333ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  return TPM_RC_SUCCESS;
176433ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi}
176533ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi
176639dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh SanghiTPM_RC TpmUtilityImpl::ComputeNVSpaceName(const TPMS_NV_PUBLIC& nv_public_area,
176739dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi                                          std::string* nv_name) {
176839dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  CHECK(nv_name);
176939dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  if ((nv_public_area.nv_index & NV_INDEX_FIRST) == 0) {
177039dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    // If the index is not an nvram index, we do not compute a name.
177139dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    nv_name->clear();
177239dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return TPM_RC_SUCCESS;
177339dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
177439dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  std::string serialized_public_area;
17754dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  TPM_RC result =
17764dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      Serialize_TPMS_NV_PUBLIC(nv_public_area, &serialized_public_area);
177739dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1778b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1779b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error serializing public area: " << GetErrorString(result);
178039dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
178139dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
178239dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  std::string serialized_name_alg;
178339dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  result = Serialize_TPM_ALG_ID(TPM_ALG_SHA256, &serialized_name_alg);
178439dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1785b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1786b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error serializing public area: " << GetErrorString(result);
178739dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi    return result;
178839dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  }
178939dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  nv_name->assign(serialized_name_alg +
179039dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi                  crypto::SHA256HashString(serialized_public_area));
179139dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi  return TPM_RC_SUCCESS;
179239dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi}
179339dd58452d7fe3ebe93490a6239a76b385bd676dUtkarsh Sanghi
179433ca033c9665b8496f3491037403ae1574a54227Utkarsh SanghiTPM_RC TpmUtilityImpl::EncryptPrivateData(const TPMT_SENSITIVE& sensitive_area,
179533ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi                                          const TPMT_PUBLIC& public_area,
179633ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi                                          TPM2B_PRIVATE* encrypted_private_data,
179733ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi                                          TPM2B_DATA* encryption_key) {
179833ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  TPM2B_SENSITIVE sensitive_data = Make_TPM2B_SENSITIVE(sensitive_area);
179933ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  std::string serialized_sensitive_data;
18004dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  TPM_RC result =
18014dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      Serialize_TPM2B_SENSITIVE(sensitive_data, &serialized_sensitive_data);
180233ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1803b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error serializing sensitive data: "
180433ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi               << GetErrorString(result);
180533ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi    return result;
180680c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn  }
180733ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  std::string object_name;
180833ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  result = ComputeKeyName(public_area, &object_name);
180933ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1810b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1811b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error computing object name: " << GetErrorString(result);
181233ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi    return result;
181380c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn  }
18144dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  TPM2B_DIGEST inner_integrity = Make_TPM2B_DIGEST(
18154dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      crypto::SHA256HashString(serialized_sensitive_data + object_name));
181633ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  std::string serialized_inner_integrity;
181733ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  result = Serialize_TPM2B_DIGEST(inner_integrity, &serialized_inner_integrity);
181833ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1819b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__ << ": Error serializing inner integrity: "
182033ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi               << GetErrorString(result);
182133ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi    return result;
182280c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn  }
18234dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn  std::string unencrypted_private_data =
18244dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      serialized_inner_integrity + serialized_sensitive_data;
182533ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  AES_KEY key;
182633ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  AES_set_encrypt_key(encryption_key->buffer, kAesKeySize * 8, &key);
182733ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  std::string private_data_string(unencrypted_private_data.size(), 0);
182833ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  int iv_in = 0;
182933ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  unsigned char iv[MAX_AES_BLOCK_SIZE_BYTES] = {0};
183033ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  AES_cfb128_encrypt(
18314dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      reinterpret_cast<const unsigned char*>(unencrypted_private_data.data()),
18324dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      reinterpret_cast<unsigned char*>(string_as_array(&private_data_string)),
18334dc4629c415e7ca90ff146d7bb75b5646ecd8b17Darren Krahn      unencrypted_private_data.size(), &key, iv, &iv_in, AES_ENCRYPT);
183433ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  *encrypted_private_data = Make_TPM2B_PRIVATE(private_data_string);
183533ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  if (result != TPM_RC_SUCCESS) {
1836b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn    LOG(ERROR) << __func__
1837b180754b429c078cbc99175a6059a8b5d0491002Darren Krahn               << ": Error making private area: " << GetErrorString(result);
183833ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi    return result;
183980c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn  }
184033ca033c9665b8496f3491037403ae1574a54227Utkarsh Sanghi  return TPM_RC_SUCCESS;
184180c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn}
184280c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn
184387b642d428ca28ff81b97ab0617f2c04d8605683Darren KrahnTPM_RC TpmUtilityImpl::DoesPersistentKeyExist(TPMI_DH_PERSISTENT key_handle,
184487b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn                                              bool* exists) {
184587b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn  TPM_RC result;
184687b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn  TPMI_YES_NO more_data = YES;
184787b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn  TPMS_CAPABILITY_DATA capability_data;
184887b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn  result = factory_.GetTpm()->GetCapabilitySync(
184987b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn      TPM_CAP_HANDLES, key_handle, 1 /*property_count*/, &more_data,
185087b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn      &capability_data, nullptr /*authorization_delegate*/);
185187b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn  if (result != TPM_RC_SUCCESS) {
185287b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn    LOG(ERROR) << __func__
185387b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn               << ": Error querying handles: " << GetErrorString(result);
185487b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn    return result;
185587b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn  }
185687b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn  TPML_HANDLE& handles = capability_data.data.handles;
185787b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn  *exists = (handles.count == 1 && handles.handle[0] == key_handle);
185887b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn  return TPM_RC_SUCCESS;
185987b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn}
186087b642d428ca28ff81b97ab0617f2c04d8605683Darren Krahn
1861c364caa9d091baae8eeb9144a6abf69e1fcabb39Darren Krahn}  // namespace trunks
1862