Home | History | Annotate | Download | only in common
      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 
     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 
     66 BYTE* StringAsTSSBuffer(std::string* s) {
     67   return reinterpret_cast<BYTE*>(string_as_array(s));
     68 }
     69 
     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 
     78 TpmUtilityV1::~TpmUtilityV1() {}
     79 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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