1//
2// Copyright (C) 2015 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include "attestation/common/tpm_utility_v1.h"
18
19#include <base/files/file_path.h>
20#include <base/files/file_util.h>
21#include <base/logging.h>
22#include <base/memory/scoped_ptr.h>
23#include <base/stl_util.h>
24#include <crypto/scoped_openssl_types.h>
25#include <crypto/sha2.h>
26#include <openssl/rsa.h>
27#include <openssl/sha.h>
28#include <trousers/scoped_tss_type.h>
29#include <trousers/trousers.h>
30#include <trousers/tss.h>
31
32#define TPM_LOG(severity, result) \
33    LOG(severity) << "TPM error 0x" << std::hex << result \
34                  << " (" << Trspi_Error_String(result) << "): "
35
36using trousers::ScopedTssContext;
37using trousers::ScopedTssKey;
38using trousers::ScopedTssMemory;
39using trousers::ScopedTssPcrs;
40
41namespace {
42
43using ScopedByteArray = scoped_ptr<BYTE, base::FreeDeleter>;
44using ScopedTssEncryptedData = trousers::ScopedTssObject<TSS_HENCDATA>;
45using ScopedTssHash = trousers::ScopedTssObject<TSS_HHASH>;
46
47const char* kTpmTpmEnabledFile = "/sys/class/tpm/tpm0/device/enabled";
48const char* kMscTpmEnabledFile = "/sys/class/misc/tpm0/device/enabled";
49const char* kTpmTpmOwnedFile = "/sys/class/tpm/tpm0/device/owned";
50const char* kMscTpmOwnedFile = "/sys/class/misc/tpm0/device/owned";
51const unsigned int kWellKnownExponent = 65537;
52const unsigned char kSha256DigestInfo[] = {
53  0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
54  0x02, 0x01, 0x05, 0x00, 0x04, 0x20
55};
56
57std::string GetFirstByte(const char* file_name) {
58  std::string content;
59  base::ReadFileToString(base::FilePath(file_name), &content);
60  if (content.size() > 1) {
61    content.resize(1);
62  }
63  return content;
64}
65
66BYTE* StringAsTSSBuffer(std::string* s) {
67  return reinterpret_cast<BYTE*>(string_as_array(s));
68}
69
70std::string TSSBufferAsString(const BYTE* buffer, size_t length) {
71  return std::string(reinterpret_cast<const char*>(buffer), length);
72}
73
74}  // namespace
75
76namespace attestation {
77
78TpmUtilityV1::~TpmUtilityV1() {}
79
80bool TpmUtilityV1::Initialize() {
81  if (!ConnectContext(&context_handle_, &tpm_handle_)) {
82    LOG(ERROR) << __func__ << ": Failed to connect to the TPM.";
83    return false;
84  }
85  if (!IsTpmReady()) {
86    LOG(WARNING) << __func__ << ": TPM is not owned; attestation services will "
87                 << "not be available until ownership is taken.";
88  }
89  return true;
90}
91
92bool TpmUtilityV1::IsTpmReady() {
93  if (!is_ready_) {
94    if (base::PathExists(base::FilePath(kMscTpmEnabledFile))) {
95      is_ready_ = (GetFirstByte(kMscTpmEnabledFile) == "1" &&
96                   GetFirstByte(kMscTpmOwnedFile) == "1");
97    } else {
98      is_ready_ = (GetFirstByte(kTpmTpmEnabledFile) == "1" &&
99                   GetFirstByte(kTpmTpmOwnedFile) == "1");
100    }
101  }
102  return is_ready_;
103}
104
105bool TpmUtilityV1::ActivateIdentity(const std::string& delegate_blob,
106                                    const std::string& delegate_secret,
107                                    const std::string& identity_key_blob,
108                                    const std::string& asym_ca_contents,
109                                    const std::string& sym_ca_attestation,
110                                    std::string* credential) {
111  CHECK(credential);
112  if (!SetupSrk()) {
113    LOG(ERROR) << "SRK is not ready.";
114    return false;
115  }
116
117  // Connect to the TPM as the owner delegate.
118  ScopedTssContext context_handle;
119  TSS_HTPM tpm_handle;
120  if (!ConnectContextAsDelegate(delegate_blob, delegate_secret,
121                                &context_handle, &tpm_handle)) {
122    LOG(ERROR) << __func__ << ": Could not connect to the TPM.";
123    return false;
124  }
125  // Load the Storage Root Key.
126  TSS_RESULT result;
127  ScopedTssKey srk_handle(context_handle);
128  if (!LoadSrk(context_handle, &srk_handle)) {
129    LOG(ERROR) << __func__ << ": Failed to load SRK.";
130    return false;
131  }
132  // Load the AIK (which is wrapped by the SRK).
133  std::string mutable_identity_key_blob(identity_key_blob);
134  BYTE* identity_key_blob_buffer = StringAsTSSBuffer(
135      &mutable_identity_key_blob);
136  ScopedTssKey identity_key(context_handle);
137  result = Tspi_Context_LoadKeyByBlob(
138      context_handle,
139      srk_handle,
140      identity_key_blob.size(),
141      identity_key_blob_buffer,
142      identity_key.ptr());
143  if (TPM_ERROR(result)) {
144    TPM_LOG(ERROR, result) << __func__ << ": Failed to load AIK.";
145    return false;
146  }
147  std::string mutable_asym_ca_contents(asym_ca_contents);
148  BYTE* asym_ca_contents_buffer = StringAsTSSBuffer(&mutable_asym_ca_contents);
149  std::string mutable_sym_ca_attestation(sym_ca_attestation);
150  BYTE* sym_ca_attestation_buffer = StringAsTSSBuffer(
151      &mutable_sym_ca_attestation);
152  UINT32 credential_length = 0;
153  ScopedTssMemory credential_buffer(context_handle);
154  result = Tspi_TPM_ActivateIdentity(tpm_handle, identity_key,
155                                     asym_ca_contents.size(),
156                                     asym_ca_contents_buffer,
157                                     sym_ca_attestation.size(),
158                                     sym_ca_attestation_buffer,
159                                     &credential_length,
160                                     credential_buffer.ptr());
161  if (TPM_ERROR(result)) {
162    TPM_LOG(ERROR, result) << __func__ << ": Failed to activate identity.";
163    return false;
164  }
165  credential->assign(TSSBufferAsString(credential_buffer.value(),
166                                       credential_length));
167  return true;
168}
169
170bool TpmUtilityV1::CreateCertifiedKey(KeyType key_type,
171                                      KeyUsage key_usage,
172                                      const std::string& identity_key_blob,
173                                      const std::string& external_data,
174                                      std::string* key_blob,
175                                      std::string* public_key,
176                                      std::string* public_key_tpm_format,
177                                      std::string* key_info,
178                                      std::string* proof) {
179  CHECK(key_blob && public_key && public_key_tpm_format && key_info && proof);
180  if (!SetupSrk()) {
181    LOG(ERROR) << "SRK is not ready.";
182    return false;
183  }
184  if (key_type != KEY_TYPE_RSA) {
185    LOG(ERROR) << "Only RSA supported on TPM v1.2.";
186    return false;
187  }
188
189  // Load the AIK (which is wrapped by the SRK).
190  ScopedTssKey identity_key(context_handle_);
191  if (!LoadKeyFromBlob(identity_key_blob, context_handle_, srk_handle_,
192                       &identity_key)) {
193    LOG(ERROR) << __func__ << "Failed to load AIK.";
194    return false;
195  }
196
197  // Create a non-migratable RSA key.
198  ScopedTssKey key(context_handle_);
199  UINT32 tss_key_type = (key_usage == KEY_USAGE_SIGN) ? TSS_KEY_TYPE_SIGNING :
200                                                        TSS_KEY_TYPE_BIND;
201  UINT32 init_flags = tss_key_type |
202                      TSS_KEY_NOT_MIGRATABLE |
203                      TSS_KEY_VOLATILE |
204                      TSS_KEY_NO_AUTHORIZATION |
205                      TSS_KEY_SIZE_2048;
206  TSS_RESULT result = Tspi_Context_CreateObject(context_handle_,
207                                                TSS_OBJECT_TYPE_RSAKEY,
208                                                init_flags, key.ptr());
209  if (TPM_ERROR(result)) {
210    TPM_LOG(ERROR, result) << __func__ << ": Failed to create object.";
211    return false;
212  }
213  if (key_usage == KEY_USAGE_SIGN) {
214    result = Tspi_SetAttribUint32(key,
215                                  TSS_TSPATTRIB_KEY_INFO,
216                                  TSS_TSPATTRIB_KEYINFO_SIGSCHEME,
217                                  TSS_SS_RSASSAPKCS1V15_DER);
218  } else {
219    result = Tspi_SetAttribUint32(key,
220                                  TSS_TSPATTRIB_KEY_INFO,
221                                  TSS_TSPATTRIB_KEYINFO_ENCSCHEME,
222                                  TSS_ES_RSAESOAEP_SHA1_MGF1);
223  }
224  if (TPM_ERROR(result)) {
225    TPM_LOG(ERROR, result) << __func__ << ": Failed to set scheme.";
226    return false;
227  }
228  result = Tspi_Key_CreateKey(key, srk_handle_, 0);
229  if (TPM_ERROR(result)) {
230    TPM_LOG(ERROR, result) << __func__ << ": Failed to create key.";
231    return false;
232  }
233  result = Tspi_Key_LoadKey(key, srk_handle_);
234  if (TPM_ERROR(result)) {
235    TPM_LOG(ERROR, result) << __func__ << ": Failed to load key.";
236    return false;
237  }
238
239  // Certify the key.
240  TSS_VALIDATION validation;
241  memset(&validation, 0, sizeof(validation));
242  validation.ulExternalDataLength = external_data.size();
243  std::string mutable_external_data(external_data);
244  validation.rgbExternalData = StringAsTSSBuffer(&mutable_external_data);
245  result = Tspi_Key_CertifyKey(key, identity_key, &validation);
246  if (TPM_ERROR(result)) {
247    TPM_LOG(ERROR, result) << __func__ << ": Failed to certify key.";
248    return false;
249  }
250  ScopedTssMemory scoped_certified_data(0, validation.rgbData);
251  ScopedTssMemory scoped_proof(0, validation.rgbValidationData);
252
253  // Get the certified public key.
254  if (!GetDataAttribute(context_handle_,
255                        key,
256                        TSS_TSPATTRIB_KEY_BLOB,
257                        TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY,
258                        public_key_tpm_format)) {
259    LOG(ERROR) << __func__ << ": Failed to read public key.";
260    return false;
261  }
262  if (!ConvertPublicKeyToDER(*public_key_tpm_format, public_key)) {
263    return false;
264  }
265
266  // Get the certified key blob so we can load it later.
267  if (!GetDataAttribute(context_handle_,
268                        key,
269                        TSS_TSPATTRIB_KEY_BLOB,
270                        TSS_TSPATTRIB_KEYBLOB_BLOB,
271                        key_blob)) {
272    LOG(ERROR) << __func__ << ": Failed to read key blob.";
273    return false;
274  }
275
276  // Get the data that was certified.
277  key_info->assign(TSSBufferAsString(validation.rgbData,
278                                     validation.ulDataLength));
279
280  // Get the certification proof.
281  proof->assign(TSSBufferAsString(validation.rgbValidationData,
282                                  validation.ulValidationDataLength));
283  return true;
284}
285
286bool TpmUtilityV1::SealToPCR0(const std::string& data,
287                              std::string* sealed_data) {
288  CHECK(sealed_data);
289  if (!SetupSrk()) {
290    LOG(ERROR) << "SRK is not ready.";
291    return false;
292  }
293
294  // Create a PCRS object which holds the value of PCR0.
295  ScopedTssPcrs pcrs_handle(context_handle_);
296  TSS_RESULT result;
297  if (TPM_ERROR(result = Tspi_Context_CreateObject(context_handle_,
298                                                   TSS_OBJECT_TYPE_PCRS,
299                                                   TSS_PCRS_STRUCT_INFO,
300                                                   pcrs_handle.ptr()))) {
301    TPM_LOG(ERROR, result)
302        << __func__ << ": Error calling Tspi_Context_CreateObject";
303    return false;
304  }
305  UINT32 pcr_length = 0;
306  ScopedTssMemory pcr_value(context_handle_);
307  Tspi_TPM_PcrRead(tpm_handle_, 0, &pcr_length, pcr_value.ptr());
308  Tspi_PcrComposite_SetPcrValue(pcrs_handle, 0, pcr_length, pcr_value.value());
309
310  // Create a ENCDATA object to receive the sealed data.
311  ScopedTssKey encrypted_data_handle(context_handle_);
312  if (TPM_ERROR(result = Tspi_Context_CreateObject(
313      context_handle_,
314      TSS_OBJECT_TYPE_ENCDATA,
315      TSS_ENCDATA_SEAL,
316      encrypted_data_handle.ptr()))) {
317    TPM_LOG(ERROR, result)
318        << __func__ << ": Error calling Tspi_Context_CreateObject";
319    return false;
320  }
321
322  // Seal the given value with the SRK.
323  std::string mutable_data(data);
324  BYTE* data_buffer = StringAsTSSBuffer(&mutable_data);
325  if (TPM_ERROR(result = Tspi_Data_Seal(
326      encrypted_data_handle,
327      srk_handle_,
328      data.size(),
329      data_buffer,
330      pcrs_handle))) {
331    TPM_LOG(ERROR, result) << __func__ << ": Error calling Tspi_Data_Seal";
332    return false;
333  }
334
335  // Extract the sealed value.
336  ScopedTssMemory encrypted_data(context_handle_);
337  UINT32 encrypted_data_length = 0;
338  if (TPM_ERROR(result = Tspi_GetAttribData(encrypted_data_handle,
339                                            TSS_TSPATTRIB_ENCDATA_BLOB,
340                                            TSS_TSPATTRIB_ENCDATABLOB_BLOB,
341                                            &encrypted_data_length,
342                                            encrypted_data.ptr()))) {
343    TPM_LOG(ERROR, result) << __func__ << ": Error calling Tspi_GetAttribData";
344    return false;
345  }
346  sealed_data->assign(TSSBufferAsString(encrypted_data.value(),
347                                        encrypted_data_length));
348  return true;
349}
350
351bool TpmUtilityV1::Unseal(const std::string& sealed_data, std::string* data) {
352  CHECK(data);
353  if (!SetupSrk()) {
354    LOG(ERROR) << "SRK is not ready.";
355    return false;
356  }
357
358  // Create an ENCDATA object with the sealed value.
359  ScopedTssKey encrypted_data_handle(context_handle_);
360  TSS_RESULT result;
361  if (TPM_ERROR(result = Tspi_Context_CreateObject(
362      context_handle_,
363      TSS_OBJECT_TYPE_ENCDATA,
364      TSS_ENCDATA_SEAL,
365      encrypted_data_handle.ptr()))) {
366    TPM_LOG(ERROR, result)
367        << __func__ << ": Error calling Tspi_Context_CreateObject";
368    return false;
369  }
370
371  std::string mutable_sealed_data(sealed_data);
372  BYTE* sealed_data_buffer = StringAsTSSBuffer(&mutable_sealed_data);
373  if (TPM_ERROR(result = Tspi_SetAttribData(encrypted_data_handle,
374      TSS_TSPATTRIB_ENCDATA_BLOB,
375      TSS_TSPATTRIB_ENCDATABLOB_BLOB,
376      sealed_data.size(),
377      sealed_data_buffer))) {
378    TPM_LOG(ERROR, result) << __func__ << ": Error calling Tspi_SetAttribData";
379    return false;
380  }
381
382  // Unseal using the SRK.
383  ScopedTssMemory decrypted_data(context_handle_);
384  UINT32 decrypted_data_length = 0;
385  if (TPM_ERROR(result = Tspi_Data_Unseal(encrypted_data_handle,
386                                          srk_handle_,
387                                          &decrypted_data_length,
388                                          decrypted_data.ptr()))) {
389    TPM_LOG(ERROR, result) << __func__ << ": Error calling Tspi_Data_Unseal";
390    return false;
391  }
392  data->assign(TSSBufferAsString(decrypted_data.value(),
393                                 decrypted_data_length));
394  return true;
395}
396
397bool TpmUtilityV1::GetEndorsementPublicKey(std::string* public_key) {
398  // Get a handle to the EK public key.
399  ScopedTssKey ek_public_key_object(context_handle_);
400  TSS_RESULT result = Tspi_TPM_GetPubEndorsementKey(tpm_handle_, false, nullptr,
401                                                    ek_public_key_object.ptr());
402  if (TPM_ERROR(result)) {
403    TPM_LOG(ERROR, result) << __func__ << ": Failed to get key.";
404    return false;
405  }
406  // Get the public key in TPM_PUBKEY form.
407  std::string ek_public_key_blob;
408  if (!GetDataAttribute(context_handle_,
409                        ek_public_key_object,
410                        TSS_TSPATTRIB_KEY_BLOB,
411                        TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY,
412                        &ek_public_key_blob)) {
413    LOG(ERROR) << __func__ << ": Failed to read public key.";
414    return false;
415  }
416  // Get the public key in DER encoded form.
417  if (!ConvertPublicKeyToDER(ek_public_key_blob, public_key)) {
418    return false;
419  }
420  return true;
421}
422
423bool TpmUtilityV1::Unbind(const std::string& key_blob,
424                          const std::string& bound_data,
425                          std::string* data) {
426  CHECK(data);
427  if (!SetupSrk()) {
428    LOG(ERROR) << "SRK is not ready.";
429    return false;
430  }
431  ScopedTssKey key_handle(context_handle_);
432  if (!LoadKeyFromBlob(key_blob, context_handle_, srk_handle_, &key_handle)) {
433    return false;
434  }
435  TSS_RESULT result;
436  ScopedTssEncryptedData data_handle(context_handle_);
437  if (TPM_ERROR(result = Tspi_Context_CreateObject(context_handle_,
438                                                   TSS_OBJECT_TYPE_ENCDATA,
439                                                   TSS_ENCDATA_BIND,
440                                                   data_handle.ptr()))) {
441    TPM_LOG(ERROR, result) << __func__ << ": Tspi_Context_CreateObject failed.";
442    return false;
443  }
444  std::string mutable_bound_data(bound_data);
445  if (TPM_ERROR(result = Tspi_SetAttribData(
446      data_handle,
447      TSS_TSPATTRIB_ENCDATA_BLOB,
448      TSS_TSPATTRIB_ENCDATABLOB_BLOB,
449      bound_data.size(),
450      StringAsTSSBuffer(&mutable_bound_data)))) {
451    TPM_LOG(ERROR, result) << __func__ << ": Tspi_SetAttribData failed.";
452    return false;
453  }
454
455  ScopedTssMemory decrypted_data(context_handle_);
456  UINT32 length = 0;
457  if (TPM_ERROR(result = Tspi_Data_Unbind(data_handle, key_handle,
458                                          &length, decrypted_data.ptr()))) {
459    TPM_LOG(ERROR, result) << __func__ << ": Tspi_Data_Unbind failed.";
460    return false;
461  }
462  data->assign(TSSBufferAsString(decrypted_data.value(), length));
463  return true;
464}
465
466bool TpmUtilityV1::Sign(const std::string& key_blob,
467                        const std::string& data_to_sign,
468                        std::string* signature) {
469  CHECK(signature);
470  if (!SetupSrk()) {
471    LOG(ERROR) << "SRK is not ready.";
472    return false;
473  }
474  ScopedTssKey key_handle(context_handle_);
475  if (!LoadKeyFromBlob(key_blob, context_handle_, srk_handle_, &key_handle)) {
476    return false;
477  }
478  // Construct an ASN.1 DER DigestInfo.
479  std::string digest_to_sign(std::begin(kSha256DigestInfo),
480                             std::end(kSha256DigestInfo));
481  digest_to_sign += crypto::SHA256HashString(data_to_sign);
482  // Create a hash object to hold the digest.
483  ScopedTssHash hash_handle(context_handle_);
484  TSS_RESULT result = Tspi_Context_CreateObject(context_handle_,
485                                                TSS_OBJECT_TYPE_HASH,
486                                                TSS_HASH_OTHER,
487                                                hash_handle.ptr());
488  if (TPM_ERROR(result)) {
489    TPM_LOG(ERROR, result) << __func__ << ": Failed to create hash object.";
490    return false;
491  }
492  result = Tspi_Hash_SetHashValue(hash_handle,
493                                  digest_to_sign.size(),
494                                  StringAsTSSBuffer(&digest_to_sign));
495  if (TPM_ERROR(result)) {
496    TPM_LOG(ERROR, result) << __func__ << ": Failed to set hash data.";
497    return false;
498  }
499  UINT32 length = 0;
500  ScopedTssMemory buffer(context_handle_);
501  result = Tspi_Hash_Sign(hash_handle, key_handle, &length, buffer.ptr());
502  if (TPM_ERROR(result)) {
503    TPM_LOG(ERROR, result) << __func__ << ": Failed to generate signature.";
504    return false;
505  }
506  signature->assign(TSSBufferAsString(buffer.value(), length));
507  return true;
508}
509
510bool TpmUtilityV1::ConnectContext(ScopedTssContext* context, TSS_HTPM* tpm) {
511  *tpm = 0;
512  TSS_RESULT result;
513  if (TPM_ERROR(result = Tspi_Context_Create(context->ptr()))) {
514    TPM_LOG(ERROR, result) << __func__ << ": Error calling Tspi_Context_Create";
515    return false;
516  }
517  if (TPM_ERROR(result = Tspi_Context_Connect(*context, nullptr))) {
518    TPM_LOG(ERROR, result) << __func__
519                           << ": Error calling Tspi_Context_Connect";
520    return false;
521  }
522  if (TPM_ERROR(result = Tspi_Context_GetTpmObject(*context, tpm))) {
523    TPM_LOG(ERROR, result) << __func__
524                           << ": Error calling Tspi_Context_GetTpmObject";
525    return false;
526  }
527  return true;
528}
529
530bool TpmUtilityV1::ConnectContextAsDelegate(const std::string& delegate_blob,
531                                            const std::string& delegate_secret,
532                                            ScopedTssContext* context,
533                                            TSS_HTPM* tpm) {
534  *tpm = 0;
535  if (!ConnectContext(context, tpm)) {
536    return false;
537  }
538  TSS_RESULT result;
539  TSS_HPOLICY tpm_usage_policy;
540  if (TPM_ERROR(result = Tspi_GetPolicyObject(*tpm,
541                                              TSS_POLICY_USAGE,
542                                              &tpm_usage_policy))) {
543    TPM_LOG(ERROR, result) << __func__
544                           << ": Error calling Tspi_GetPolicyObject";
545    return false;
546  }
547  std::string mutable_delegate_secret(delegate_secret);
548  BYTE* secret_buffer = StringAsTSSBuffer(&mutable_delegate_secret);
549  if (TPM_ERROR(result = Tspi_Policy_SetSecret(tpm_usage_policy,
550                                               TSS_SECRET_MODE_PLAIN,
551                                               delegate_secret.size(),
552                                               secret_buffer))) {
553    TPM_LOG(ERROR, result) << __func__
554                           << ": Error calling Tspi_Policy_SetSecret";
555    return false;
556  }
557  std::string mutable_delegate_blob(delegate_blob);
558  BYTE* blob_buffer = StringAsTSSBuffer(&mutable_delegate_blob);
559  if (TPM_ERROR(result = Tspi_SetAttribData(
560      tpm_usage_policy,
561      TSS_TSPATTRIB_POLICY_DELEGATION_INFO,
562      TSS_TSPATTRIB_POLDEL_OWNERBLOB,
563      delegate_blob.size(),
564      blob_buffer))) {
565    TPM_LOG(ERROR, result) << __func__ << ": Error calling Tspi_SetAttribData";
566    return false;
567  }
568  return true;
569}
570
571bool TpmUtilityV1::SetupSrk() {
572  if (!IsTpmReady()) {
573    return false;
574  }
575  if (srk_handle_) {
576    return true;
577  }
578  srk_handle_.reset(context_handle_, 0);
579  if (!LoadSrk(context_handle_, &srk_handle_)) {
580    LOG(ERROR) << __func__ << ": Failed to load SRK.";
581    return false;
582  }
583  // In order to wrap a key with the SRK we need access to the SRK public key
584  // and we need to get it manually. Once it's in the key object, we don't need
585  // to do this again.
586  UINT32 length = 0;
587  ScopedTssMemory buffer(context_handle_);
588  TSS_RESULT result;
589  result = Tspi_Key_GetPubKey(srk_handle_, &length, buffer.ptr());
590  if (result != TSS_SUCCESS) {
591    TPM_LOG(INFO, result) << __func__ << ": Failed to read SRK public key.";
592    return false;
593  }
594  return true;
595}
596
597bool TpmUtilityV1::LoadSrk(TSS_HCONTEXT context_handle,
598                           ScopedTssKey* srk_handle) {
599  TSS_RESULT result;
600  TSS_UUID uuid = TSS_UUID_SRK;
601  if (TPM_ERROR(result = Tspi_Context_LoadKeyByUUID(context_handle,
602                                                    TSS_PS_TYPE_SYSTEM,
603                                                    uuid,
604                                                    srk_handle->ptr()))) {
605    TPM_LOG(ERROR, result) << __func__
606                           << ": Error calling Tspi_Context_LoadKeyByUUID";
607    return false;
608  }
609  // Check if the SRK wants a password.
610  UINT32 auth_usage;
611  if (TPM_ERROR(result = Tspi_GetAttribUint32(*srk_handle,
612                                              TSS_TSPATTRIB_KEY_INFO,
613                                              TSS_TSPATTRIB_KEYINFO_AUTHUSAGE,
614                                              &auth_usage))) {
615    TPM_LOG(ERROR, result) << __func__
616                           << ": Error calling Tspi_GetAttribUint32";
617    return false;
618  }
619  if (auth_usage) {
620    // Give it an empty password if needed.
621    TSS_HPOLICY usage_policy;
622    if (TPM_ERROR(result = Tspi_GetPolicyObject(*srk_handle,
623                                                TSS_POLICY_USAGE,
624                                                &usage_policy))) {
625    TPM_LOG(ERROR, result) << __func__
626                           << ": Error calling Tspi_GetPolicyObject";
627      return false;
628    }
629
630    BYTE empty_password[] = {};
631    if (TPM_ERROR(result = Tspi_Policy_SetSecret(usage_policy,
632                                                 TSS_SECRET_MODE_PLAIN,
633                                                 0, empty_password))) {
634      TPM_LOG(ERROR, result) << __func__
635                             << ": Error calling Tspi_Policy_SetSecret";
636      return false;
637    }
638  }
639  return true;
640}
641
642bool TpmUtilityV1::LoadKeyFromBlob(const std::string& key_blob,
643                                   TSS_HCONTEXT context_handle,
644                                   TSS_HKEY parent_key_handle,
645                                   ScopedTssKey* key_handle) {
646  std::string mutable_key_blob(key_blob);
647  BYTE* key_blob_buffer = StringAsTSSBuffer(&mutable_key_blob);
648  TSS_RESULT result = Tspi_Context_LoadKeyByBlob(
649      context_handle,
650      parent_key_handle,
651      key_blob.size(),
652      key_blob_buffer,
653      key_handle->ptr());
654  if (TPM_ERROR(result)) {
655    TPM_LOG(ERROR, result) << __func__ << ": Failed to load key by blob.";
656    return false;
657  }
658  return true;
659}
660
661bool TpmUtilityV1::GetDataAttribute(TSS_HCONTEXT context,
662                                    TSS_HOBJECT object,
663                                    TSS_FLAG flag,
664                                    TSS_FLAG sub_flag,
665                                    std::string* data) {
666  UINT32 length = 0;
667  ScopedTssMemory buffer(context);
668  TSS_RESULT result = Tspi_GetAttribData(object, flag, sub_flag, &length,
669                                         buffer.ptr());
670  if (TPM_ERROR(result)) {
671    TPM_LOG(ERROR, result) << __func__ << "Failed to read object attribute.";
672    return false;
673  }
674  data->assign(TSSBufferAsString(buffer.value(), length));
675  return true;
676}
677
678bool TpmUtilityV1::ConvertPublicKeyToDER(const std::string& public_key,
679                                         std::string* public_key_der) {
680  // Parse the serialized TPM_PUBKEY.
681  UINT64 offset = 0;
682  std::string mutable_public_key(public_key);
683  BYTE* buffer = StringAsTSSBuffer(&mutable_public_key);
684  TPM_PUBKEY parsed;
685  TSS_RESULT result = Trspi_UnloadBlob_PUBKEY(&offset, buffer, &parsed);
686  if (TPM_ERROR(result)) {
687    TPM_LOG(ERROR, result) << "Failed to parse TPM_PUBKEY.";
688    return false;
689  }
690  ScopedByteArray scoped_key(parsed.pubKey.key);
691  ScopedByteArray scoped_parms(parsed.algorithmParms.parms);
692  TPM_RSA_KEY_PARMS* parms =
693      reinterpret_cast<TPM_RSA_KEY_PARMS*>(parsed.algorithmParms.parms);
694  crypto::ScopedRSA rsa(RSA_new());
695  CHECK(rsa.get());
696  // Get the public exponent.
697  if (parms->exponentSize == 0) {
698    rsa.get()->e = BN_new();
699    CHECK(rsa.get()->e);
700    BN_set_word(rsa.get()->e, kWellKnownExponent);
701  } else {
702    rsa.get()->e = BN_bin2bn(parms->exponent, parms->exponentSize, nullptr);
703    CHECK(rsa.get()->e);
704  }
705  // Get the modulus.
706  rsa.get()->n = BN_bin2bn(parsed.pubKey.key, parsed.pubKey.keyLength, nullptr);
707  CHECK(rsa.get()->n);
708
709  // DER encode.
710  int der_length = i2d_RSAPublicKey(rsa.get(), nullptr);
711  if (der_length < 0) {
712    LOG(ERROR) << "Failed to DER-encode public key.";
713    return false;
714  }
715  public_key_der->resize(der_length);
716  unsigned char* der_buffer = reinterpret_cast<unsigned char*>(
717      string_as_array(public_key_der));
718  der_length = i2d_RSAPublicKey(rsa.get(), &der_buffer);
719  if (der_length < 0) {
720    LOG(ERROR) << "Failed to DER-encode public key.";
721    return false;
722  }
723  public_key_der->resize(der_length);
724  return true;
725}
726
727}  // namespace attestation
728