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