• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2015 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include "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 
36 using trousers::ScopedTssContext;
37 using trousers::ScopedTssKey;
38 using trousers::ScopedTssMemory;
39 using trousers::ScopedTssPcrs;
40 
41 namespace {
42 
43 using ScopedByteArray = scoped_ptr<BYTE, base::FreeDeleter>;
44 using ScopedTssEncryptedData = trousers::ScopedTssObject<TSS_HENCDATA>;
45 using ScopedTssHash = trousers::ScopedTssObject<TSS_HHASH>;
46 
47 const char* kTpmTpmEnabledFile = "/sys/class/tpm/tpm0/device/enabled";
48 const char* kMscTpmEnabledFile = "/sys/class/misc/tpm0/device/enabled";
49 const char* kTpmTpmOwnedFile = "/sys/class/tpm/tpm0/device/owned";
50 const char* kMscTpmOwnedFile = "/sys/class/misc/tpm0/device/owned";
51 const unsigned int kWellKnownExponent = 65537;
52 const 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 
GetFirstByte(const char * file_name)57 std::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 
StringAsTSSBuffer(std::string * s)66 BYTE* StringAsTSSBuffer(std::string* s) {
67   return reinterpret_cast<BYTE*>(string_as_array(s));
68 }
69 
TSSBufferAsString(const BYTE * buffer,size_t length)70 std::string TSSBufferAsString(const BYTE* buffer, size_t length) {
71   return std::string(reinterpret_cast<const char*>(buffer), length);
72 }
73 
74 }  // namespace
75 
76 namespace attestation {
77 
~TpmUtilityV1()78 TpmUtilityV1::~TpmUtilityV1() {}
79 
Initialize()80 bool 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 
IsTpmReady()92 bool 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 
ActivateIdentity(const std::string & delegate_blob,const std::string & delegate_secret,const std::string & identity_key_blob,const std::string & asym_ca_contents,const std::string & sym_ca_attestation,std::string * credential)105 bool 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 
CreateCertifiedKey(KeyType key_type,KeyUsage key_usage,const std::string & identity_key_blob,const std::string & external_data,std::string * key_blob,std::string * public_key,std::string * public_key_tpm_format,std::string * key_info,std::string * proof)170 bool 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 
SealToPCR0(const std::string & data,std::string * sealed_data)286 bool 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 
Unseal(const std::string & sealed_data,std::string * data)351 bool 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 
GetEndorsementPublicKey(std::string * public_key)397 bool 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 
Unbind(const std::string & key_blob,const std::string & bound_data,std::string * data)423 bool 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 
Sign(const std::string & key_blob,const std::string & data_to_sign,std::string * signature)466 bool 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 
ConnectContext(ScopedTssContext * context,TSS_HTPM * tpm)510 bool 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 
ConnectContextAsDelegate(const std::string & delegate_blob,const std::string & delegate_secret,ScopedTssContext * context,TSS_HTPM * tpm)530 bool 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 
SetupSrk()571 bool 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 
LoadSrk(TSS_HCONTEXT context_handle,ScopedTssKey * srk_handle)597 bool 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 
LoadKeyFromBlob(const std::string & key_blob,TSS_HCONTEXT context_handle,TSS_HKEY parent_key_handle,ScopedTssKey * key_handle)642 bool 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 
GetDataAttribute(TSS_HCONTEXT context,TSS_HOBJECT object,TSS_FLAG flag,TSS_FLAG sub_flag,std::string * data)661 bool 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 
ConvertPublicKeyToDER(const std::string & public_key,std::string * public_key_der)678 bool 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