Home | History | Annotate | Download | only in trunks
      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 "trunks/trunks_client_test.h"
     18 
     19 #include <algorithm>
     20 #include <map>
     21 #include <memory>
     22 #include <string>
     23 #include <vector>
     24 
     25 #include <base/callback.h>
     26 #include <base/logging.h>
     27 #include <base/stl_util.h>
     28 #include <brillo/bind_lambda.h>
     29 #include <crypto/openssl_util.h>
     30 #include <crypto/scoped_openssl_types.h>
     31 #include <crypto/sha2.h>
     32 #include <openssl/bn.h>
     33 #include <openssl/err.h>
     34 #include <openssl/rsa.h>
     35 
     36 #include "trunks/authorization_delegate.h"
     37 #include "trunks/error_codes.h"
     38 #include "trunks/hmac_session.h"
     39 #include "trunks/policy_session.h"
     40 #include "trunks/scoped_key_handle.h"
     41 #include "trunks/tpm_constants.h"
     42 #include "trunks/tpm_generated.h"
     43 #include "trunks/tpm_state.h"
     44 #include "trunks/tpm_utility.h"
     45 #include "trunks/trunks_factory_impl.h"
     46 
     47 namespace {
     48 
     49 std::string GetOpenSSLError() {
     50   BIO* bio = BIO_new(BIO_s_mem());
     51   ERR_print_errors(bio);
     52   char* data = nullptr;
     53   int data_len = BIO_get_mem_data(bio, &data);
     54   std::string error_string(data, data_len);
     55   BIO_free(bio);
     56   return error_string;
     57 }
     58 
     59 }  // namespace
     60 
     61 namespace trunks {
     62 
     63 TrunksClientTest::TrunksClientTest(const TrunksFactory& factory)
     64     : factory_(factory) {
     65   crypto::EnsureOpenSSLInit();
     66 }
     67 
     68 TrunksClientTest::~TrunksClientTest() {}
     69 
     70 bool TrunksClientTest::RNGTest() {
     71   std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
     72   std::unique_ptr<HmacSession> session = factory_.GetHmacSession();
     73   if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
     74     LOG(ERROR) << "Error starting hmac session.";
     75     return false;
     76   }
     77   std::string entropy_data("entropy_data");
     78   std::string random_data;
     79   size_t num_bytes = 70;
     80   TPM_RC result = utility->StirRandom(entropy_data, session->GetDelegate());
     81   if (result != TPM_RC_SUCCESS) {
     82     LOG(ERROR) << "Error stirring TPM RNG: " << GetErrorString(result);
     83     return false;
     84   }
     85   result =
     86       utility->GenerateRandom(num_bytes, session->GetDelegate(), &random_data);
     87   if (result != TPM_RC_SUCCESS) {
     88     LOG(ERROR) << "Error getting random bytes from TPM: "
     89                << GetErrorString(result);
     90     return false;
     91   }
     92   if (num_bytes != random_data.size()) {
     93     LOG(ERROR) << "Error not enough random bytes received.";
     94     return false;
     95   }
     96   return true;
     97 }
     98 
     99 bool TrunksClientTest::SignTest() {
    100   std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
    101   std::unique_ptr<HmacSession> session = factory_.GetHmacSession();
    102   if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
    103     LOG(ERROR) << "Error starting hmac session.";
    104     return false;
    105   }
    106   std::string key_authorization("sign");
    107   std::string key_blob;
    108   TPM_RC result = utility->CreateRSAKeyPair(
    109       TpmUtility::AsymmetricKeyUsage::kSignKey, 2048, 0x10001,
    110       key_authorization, "", false,  // use_only_policy_authorization
    111       kNoCreationPCR, session->GetDelegate(), &key_blob, nullptr);
    112   if (result != TPM_RC_SUCCESS) {
    113     LOG(ERROR) << "Error creating signing key: " << GetErrorString(result);
    114     return false;
    115   }
    116   TPM_HANDLE signing_key;
    117   result = utility->LoadKey(key_blob, session->GetDelegate(), &signing_key);
    118   if (result != TPM_RC_SUCCESS) {
    119     LOG(ERROR) << "Error loading signing key: " << GetErrorString(result);
    120   }
    121   ScopedKeyHandle scoped_key(factory_, signing_key);
    122   session->SetEntityAuthorizationValue(key_authorization);
    123   std::string signature;
    124   result =
    125       utility->Sign(signing_key, TPM_ALG_NULL, TPM_ALG_NULL,
    126                     std::string(32, 'a'), session->GetDelegate(), &signature);
    127   if (result != TPM_RC_SUCCESS) {
    128     LOG(ERROR) << "Error using key to sign: " << GetErrorString(result);
    129     return false;
    130   }
    131   result = utility->Verify(signing_key, TPM_ALG_NULL, TPM_ALG_NULL,
    132                            std::string(32, 'a'), signature, nullptr);
    133   if (result != TPM_RC_SUCCESS) {
    134     LOG(ERROR) << "Error using key to verify: " << GetErrorString(result);
    135     return false;
    136   }
    137   return true;
    138 }
    139 
    140 bool TrunksClientTest::DecryptTest() {
    141   std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
    142   std::unique_ptr<HmacSession> session = factory_.GetHmacSession();
    143   if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
    144     LOG(ERROR) << "Error starting hmac session.";
    145     return false;
    146   }
    147   std::string key_authorization("decrypt");
    148   std::string key_blob;
    149   TPM_RC result = utility->CreateRSAKeyPair(
    150       TpmUtility::AsymmetricKeyUsage::kDecryptKey, 2048, 0x10001,
    151       key_authorization, "", false,  // use_only_policy_authorization
    152       kNoCreationPCR, session->GetDelegate(), &key_blob, nullptr);
    153   if (result != TPM_RC_SUCCESS) {
    154     LOG(ERROR) << "Error creating decrypt key: " << GetErrorString(result);
    155     return false;
    156   }
    157   TPM_HANDLE decrypt_key;
    158   result = utility->LoadKey(key_blob, session->GetDelegate(), &decrypt_key);
    159   if (result != TPM_RC_SUCCESS) {
    160     LOG(ERROR) << "Error loading decrypt key: " << GetErrorString(result);
    161   }
    162   ScopedKeyHandle scoped_key(factory_, decrypt_key);
    163   return PerformRSAEncrpytAndDecrpyt(scoped_key.get(), key_authorization,
    164                                      session.get());
    165 }
    166 
    167 bool TrunksClientTest::ImportTest() {
    168   std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
    169   std::unique_ptr<HmacSession> session = factory_.GetHmacSession();
    170   if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
    171     LOG(ERROR) << "Error starting hmac session.";
    172     return false;
    173   }
    174   std::string modulus;
    175   std::string prime_factor;
    176   GenerateRSAKeyPair(&modulus, &prime_factor, nullptr);
    177   std::string key_blob;
    178   std::string key_authorization("import");
    179   TPM_RC result = utility->ImportRSAKey(
    180       TpmUtility::AsymmetricKeyUsage::kDecryptAndSignKey, modulus, 0x10001,
    181       prime_factor, key_authorization, session->GetDelegate(), &key_blob);
    182   if (result != TPM_RC_SUCCESS) {
    183     LOG(ERROR) << "Error importing key into TPM: " << GetErrorString(result);
    184     return false;
    185   }
    186   TPM_HANDLE key_handle;
    187   result = utility->LoadKey(key_blob, session->GetDelegate(), &key_handle);
    188   if (result != TPM_RC_SUCCESS) {
    189     LOG(ERROR) << "Error loading key into TPM: " << GetErrorString(result);
    190     return false;
    191   }
    192   ScopedKeyHandle scoped_key(factory_, key_handle);
    193   return PerformRSAEncrpytAndDecrpyt(scoped_key.get(), key_authorization,
    194                                      session.get());
    195 }
    196 
    197 bool TrunksClientTest::AuthChangeTest() {
    198   std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
    199   std::unique_ptr<HmacSession> session = factory_.GetHmacSession();
    200   if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
    201     LOG(ERROR) << "Error starting hmac session.";
    202     return false;
    203   }
    204   std::string key_authorization("new_pass");
    205   std::string key_blob;
    206   TPM_RC result = utility->CreateRSAKeyPair(
    207       TpmUtility::AsymmetricKeyUsage::kDecryptKey, 2048, 0x10001, "old_pass",
    208       "", false,  // use_only_policy_authorization
    209       kNoCreationPCR, session->GetDelegate(), &key_blob, nullptr);
    210   if (result != TPM_RC_SUCCESS) {
    211     LOG(ERROR) << "Error creating change auth key: " << GetErrorString(result);
    212     return false;
    213   }
    214   TPM_HANDLE key_handle;
    215   result = utility->LoadKey(key_blob, session->GetDelegate(), &key_handle);
    216   if (result != TPM_RC_SUCCESS) {
    217     LOG(ERROR) << "Error loading change auth key: " << GetErrorString(result);
    218   }
    219   ScopedKeyHandle scoped_key(factory_, key_handle);
    220   session->SetEntityAuthorizationValue("old_pass");
    221   result = utility->ChangeKeyAuthorizationData(
    222       key_handle, key_authorization, session->GetDelegate(), &key_blob);
    223   if (result != TPM_RC_SUCCESS) {
    224     LOG(ERROR) << "Error changing auth data: " << GetErrorString(result);
    225     return false;
    226   }
    227   session->SetEntityAuthorizationValue("");
    228   result = utility->LoadKey(key_blob, session->GetDelegate(), &key_handle);
    229   if (result != TPM_RC_SUCCESS) {
    230     LOG(ERROR) << "Error reloading key: " << GetErrorString(result);
    231     return false;
    232   }
    233   scoped_key.reset(key_handle);
    234   return PerformRSAEncrpytAndDecrpyt(scoped_key.get(), key_authorization,
    235                                      session.get());
    236 }
    237 
    238 bool TrunksClientTest::VerifyKeyCreationTest() {
    239   std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
    240   std::unique_ptr<HmacSession> session = factory_.GetHmacSession();
    241   if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
    242     LOG(ERROR) << "Error starting hmac session.";
    243     return false;
    244   }
    245   std::string key_blob;
    246   std::string creation_blob;
    247   session->SetEntityAuthorizationValue("");
    248   TPM_RC result = utility->CreateRSAKeyPair(
    249       TpmUtility::AsymmetricKeyUsage::kDecryptKey, 2048, 0x10001, "", "",
    250       false,  // use_only_policy_authorization
    251       kNoCreationPCR, session->GetDelegate(), &key_blob, &creation_blob);
    252   if (result != TPM_RC_SUCCESS) {
    253     LOG(ERROR) << "Error creating certify key: " << GetErrorString(result);
    254     return false;
    255   }
    256   std::string alternate_key_blob;
    257   result = utility->CreateRSAKeyPair(
    258       TpmUtility::AsymmetricKeyUsage::kDecryptKey, 2048, 0x10001, "", "",
    259       false,  // use_only_policy_authorization
    260       kNoCreationPCR, session->GetDelegate(), &alternate_key_blob, nullptr);
    261   if (result != TPM_RC_SUCCESS) {
    262     LOG(ERROR) << "Error creating alternate key: " << GetErrorString(result);
    263     return false;
    264   }
    265   TPM_HANDLE key_handle;
    266   result = utility->LoadKey(key_blob, session->GetDelegate(), &key_handle);
    267   if (result != TPM_RC_SUCCESS) {
    268     LOG(ERROR) << "Error loading certify key: " << GetErrorString(result);
    269     return false;
    270   }
    271   TPM_HANDLE alternate_key_handle;
    272   result = utility->LoadKey(alternate_key_blob, session->GetDelegate(),
    273                             &alternate_key_handle);
    274   if (result != TPM_RC_SUCCESS) {
    275     LOG(ERROR) << "Error loading alternate key: " << GetErrorString(result);
    276     return false;
    277   }
    278   ScopedKeyHandle certify_key(factory_, key_handle);
    279   ScopedKeyHandle alternate_key(factory_, alternate_key_handle);
    280   result = utility->CertifyCreation(certify_key.get(), creation_blob);
    281   if (result != TPM_RC_SUCCESS) {
    282     LOG(ERROR) << "Error certifying key: " << GetErrorString(result);
    283     return false;
    284   }
    285   result = utility->CertifyCreation(alternate_key.get(), creation_blob);
    286   if (result == TPM_RC_SUCCESS) {
    287     LOG(ERROR) << "Error alternate key certified with wrong creation data.";
    288     return false;
    289   }
    290   return true;
    291 }
    292 
    293 bool TrunksClientTest::SealedDataTest() {
    294   std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
    295   std::unique_ptr<HmacSession> session = factory_.GetHmacSession();
    296   if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
    297     LOG(ERROR) << "Error starting hmac session.";
    298     return false;
    299   }
    300   int pcr_index = 5;
    301   std::string policy_digest;
    302   TPM_RC result =
    303       utility->GetPolicyDigestForPcrValue(pcr_index, "", &policy_digest);
    304   if (result != TPM_RC_SUCCESS) {
    305     LOG(ERROR) << "Error getting policy_digest: " << GetErrorString(result);
    306     return false;
    307   }
    308   std::string data_to_seal("seal_data");
    309   std::string sealed_data;
    310   result = utility->SealData(data_to_seal, policy_digest,
    311                              session->GetDelegate(), &sealed_data);
    312   if (result != TPM_RC_SUCCESS) {
    313     LOG(ERROR) << "Error creating Sealed Object: " << GetErrorString(result);
    314     return false;
    315   }
    316   std::unique_ptr<PolicySession> policy_session = factory_.GetPolicySession();
    317   result = policy_session->StartUnboundSession(false);
    318   if (result != TPM_RC_SUCCESS) {
    319     LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
    320     return false;
    321   }
    322   result = policy_session->PolicyPCR(pcr_index, "");
    323   if (result != TPM_RC_SUCCESS) {
    324     LOG(ERROR) << "Error restricting policy to pcr value: "
    325                << GetErrorString(result);
    326     return false;
    327   }
    328   std::string unsealed_data;
    329   result = utility->UnsealData(sealed_data, policy_session->GetDelegate(),
    330                                &unsealed_data);
    331   if (result != TPM_RC_SUCCESS) {
    332     LOG(ERROR) << "Error unsealing object: " << GetErrorString(result);
    333     return false;
    334   }
    335   if (data_to_seal != unsealed_data) {
    336     LOG(ERROR) << "Error unsealed data from TPM does not match original data.";
    337     return false;
    338   }
    339   result = utility->ExtendPCR(pcr_index, "extend", session->GetDelegate());
    340   if (result != TPM_RC_SUCCESS) {
    341     LOG(ERROR) << "Error extending pcr: " << GetErrorString(result);
    342     return false;
    343   }
    344   result = policy_session->PolicyPCR(pcr_index, "");
    345   if (result != TPM_RC_SUCCESS) {
    346     LOG(ERROR) << "Error restricting policy to pcr value: "
    347                << GetErrorString(result);
    348     return false;
    349   }
    350   result = utility->UnsealData(sealed_data, policy_session->GetDelegate(),
    351                                &unsealed_data);
    352   if (result == TPM_RC_SUCCESS) {
    353     LOG(ERROR) << "Error object was unsealed with wrong policy_digest.";
    354     return false;
    355   }
    356   return true;
    357 }
    358 
    359 bool TrunksClientTest::PCRTest() {
    360   std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
    361   std::unique_ptr<HmacSession> session = factory_.GetHmacSession();
    362   if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
    363     LOG(ERROR) << "Error starting hmac session.";
    364     return false;
    365   }
    366   // We are using PCR 2 because it is currently not used by ChromeOS.
    367   uint32_t pcr_index = 2;
    368   std::string extend_data("data");
    369   std::string old_data;
    370   TPM_RC result = utility->ReadPCR(pcr_index, &old_data);
    371   if (result != TPM_RC_SUCCESS) {
    372     LOG(ERROR) << "Error reading from PCR: " << GetErrorString(result);
    373     return false;
    374   }
    375   result = utility->ExtendPCR(pcr_index, extend_data, session->GetDelegate());
    376   if (result != TPM_RC_SUCCESS) {
    377     LOG(ERROR) << "Error extending PCR value: " << GetErrorString(result);
    378     return false;
    379   }
    380   std::string pcr_data;
    381   result = utility->ReadPCR(pcr_index, &pcr_data);
    382   if (result != TPM_RC_SUCCESS) {
    383     LOG(ERROR) << "Error reading from PCR: " << GetErrorString(result);
    384     return false;
    385   }
    386   std::string hashed_extend_data = crypto::SHA256HashString(extend_data);
    387   std::string expected_pcr_data =
    388       crypto::SHA256HashString(old_data + hashed_extend_data);
    389   if (pcr_data.compare(expected_pcr_data) != 0) {
    390     LOG(ERROR) << "PCR data does not match expected value.";
    391     return false;
    392   }
    393   return true;
    394 }
    395 
    396 bool TrunksClientTest::PolicyAuthValueTest() {
    397   std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
    398   std::unique_ptr<PolicySession> trial_session = factory_.GetTrialSession();
    399   TPM_RC result;
    400   result = trial_session->StartUnboundSession(true);
    401   if (result != TPM_RC_SUCCESS) {
    402     LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
    403     return false;
    404   }
    405   result = trial_session->PolicyAuthValue();
    406   if (result != TPM_RC_SUCCESS) {
    407     LOG(ERROR) << "Error restricting policy to auth value knowledge: "
    408                << GetErrorString(result);
    409     return false;
    410   }
    411   std::string policy_digest;
    412   result = trial_session->GetDigest(&policy_digest);
    413   if (result != TPM_RC_SUCCESS) {
    414     LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result);
    415     return false;
    416   }
    417   // Now that we have the digest, we can close the trial session and use hmac.
    418   trial_session.reset();
    419 
    420   std::unique_ptr<HmacSession> hmac_session = factory_.GetHmacSession();
    421   result = hmac_session->StartUnboundSession(true);
    422   if (result != TPM_RC_SUCCESS) {
    423     LOG(ERROR) << "Error starting hmac session: " << GetErrorString(result);
    424     return false;
    425   }
    426 
    427   std::string key_blob;
    428   result = utility->CreateRSAKeyPair(
    429       TpmUtility::AsymmetricKeyUsage::kDecryptAndSignKey, 2048, 0x10001,
    430       "password", policy_digest, true,  // use_only_policy_authorization
    431       kNoCreationPCR, hmac_session->GetDelegate(), &key_blob, nullptr);
    432   if (result != TPM_RC_SUCCESS) {
    433     LOG(ERROR) << "Error creating RSA key: " << GetErrorString(result);
    434     return false;
    435   }
    436 
    437   TPM_HANDLE key_handle;
    438   result = utility->LoadKey(key_blob, hmac_session->GetDelegate(), &key_handle);
    439   if (result != TPM_RC_SUCCESS) {
    440     LOG(ERROR) << "Error loading RSA key: " << GetErrorString(result);
    441     return false;
    442   }
    443   ScopedKeyHandle scoped_key(factory_, key_handle);
    444 
    445   // Now we can reset the hmac_session.
    446   hmac_session.reset();
    447 
    448   std::unique_ptr<PolicySession> policy_session = factory_.GetPolicySession();
    449   result = policy_session->StartUnboundSession(false);
    450   if (result != TPM_RC_SUCCESS) {
    451     LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
    452     return false;
    453   }
    454   result = policy_session->PolicyAuthValue();
    455   if (result != TPM_RC_SUCCESS) {
    456     LOG(ERROR) << "Error restricting policy to auth value knowledge: "
    457                << GetErrorString(result);
    458     return false;
    459   }
    460   std::string signature;
    461   policy_session->SetEntityAuthorizationValue("password");
    462   result = utility->Sign(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL,
    463                          std::string(32, 0), policy_session->GetDelegate(),
    464                          &signature);
    465   if (result != TPM_RC_SUCCESS) {
    466     LOG(ERROR) << "Error signing using RSA key: " << GetErrorString(result);
    467     return false;
    468   }
    469   result = utility->Verify(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL,
    470                            std::string(32, 0), signature, nullptr);
    471   if (result != TPM_RC_SUCCESS) {
    472     LOG(ERROR) << "Error verifying using RSA key: " << GetErrorString(result);
    473     return false;
    474   }
    475   std::string ciphertext;
    476   result =
    477       utility->AsymmetricEncrypt(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL,
    478                                  "plaintext", nullptr, &ciphertext);
    479   if (result != TPM_RC_SUCCESS) {
    480     LOG(ERROR) << "Error encrypting using RSA key: " << GetErrorString(result);
    481     return false;
    482   }
    483   result = policy_session->PolicyAuthValue();
    484   if (result != TPM_RC_SUCCESS) {
    485     LOG(ERROR) << "Error restricting policy to auth value knowledge: "
    486                << GetErrorString(result);
    487     return false;
    488   }
    489   std::string plaintext;
    490   policy_session->SetEntityAuthorizationValue("password");
    491   result = utility->AsymmetricDecrypt(
    492       scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL, ciphertext,
    493       policy_session->GetDelegate(), &plaintext);
    494   if (result != TPM_RC_SUCCESS) {
    495     LOG(ERROR) << "Error encrypting using RSA key: " << GetErrorString(result);
    496     return false;
    497   }
    498   if (plaintext.compare("plaintext") != 0) {
    499     LOG(ERROR) << "Plaintext changed after encrypt + decrypt.";
    500     return false;
    501   }
    502   return true;
    503 }
    504 
    505 bool TrunksClientTest::PolicyAndTest() {
    506   std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
    507   std::unique_ptr<PolicySession> trial_session = factory_.GetTrialSession();
    508   TPM_RC result;
    509   result = trial_session->StartUnboundSession(true);
    510   if (result != TPM_RC_SUCCESS) {
    511     LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
    512     return false;
    513   }
    514   result = trial_session->PolicyCommandCode(TPM_CC_Sign);
    515   if (result != TPM_RC_SUCCESS) {
    516     LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    517     return false;
    518   }
    519   uint32_t pcr_index = 2;
    520   std::string pcr_value;
    521   result = utility->ReadPCR(pcr_index, &pcr_value);
    522   if (result != TPM_RC_SUCCESS) {
    523     LOG(ERROR) << "Error reading pcr: " << GetErrorString(result);
    524     return false;
    525   }
    526   std::string pcr_extend_data("extend");
    527   std::string next_pcr_value;
    528   std::string hashed_extend_data = crypto::SHA256HashString(pcr_extend_data);
    529   next_pcr_value = crypto::SHA256HashString(pcr_value + hashed_extend_data);
    530 
    531   result = trial_session->PolicyPCR(pcr_index, next_pcr_value);
    532   if (result != TPM_RC_SUCCESS) {
    533     LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    534     return false;
    535   }
    536   std::string policy_digest;
    537   result = trial_session->GetDigest(&policy_digest);
    538   if (result != TPM_RC_SUCCESS) {
    539     LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result);
    540     return false;
    541   }
    542   // Now that we have the digest, we can close the trial session and use hmac.
    543   trial_session.reset();
    544 
    545   std::unique_ptr<HmacSession> hmac_session = factory_.GetHmacSession();
    546   result = hmac_session->StartUnboundSession(true);
    547   if (result != TPM_RC_SUCCESS) {
    548     LOG(ERROR) << "Error starting hmac session: " << GetErrorString(result);
    549     return false;
    550   }
    551   std::string key_authorization("password");
    552   std::string key_blob;
    553   // This key is created with a policy that dictates it can only be used
    554   // when pcr 2 remains unchanged, and when the command is TPM2_Sign.
    555   result = utility->CreateRSAKeyPair(
    556       TpmUtility::AsymmetricKeyUsage::kDecryptAndSignKey, 2048, 0x10001,
    557       key_authorization, policy_digest, true,  // use_only_policy_authorization
    558       kNoCreationPCR, hmac_session->GetDelegate(), &key_blob, nullptr);
    559   if (result != TPM_RC_SUCCESS) {
    560     LOG(ERROR) << "Error creating RSA key: " << GetErrorString(result);
    561     return false;
    562   }
    563   TPM_HANDLE key_handle;
    564   result = utility->LoadKey(key_blob, hmac_session->GetDelegate(), &key_handle);
    565   if (result != TPM_RC_SUCCESS) {
    566     LOG(ERROR) << "Error loading RSA key: " << GetErrorString(result);
    567     return false;
    568   }
    569   ScopedKeyHandle scoped_key(factory_, key_handle);
    570 
    571   // Now we can reset the hmac_session.
    572   hmac_session.reset();
    573 
    574   std::unique_ptr<PolicySession> policy_session = factory_.GetPolicySession();
    575   result = policy_session->StartUnboundSession(false);
    576   if (result != TPM_RC_SUCCESS) {
    577     LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
    578     return false;
    579   }
    580   result = policy_session->PolicyCommandCode(TPM_CC_Sign);
    581   if (result != TPM_RC_SUCCESS) {
    582     LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    583     return false;
    584   }
    585   result = policy_session->PolicyPCR(pcr_index, "");
    586   if (result != TPM_RC_SUCCESS) {
    587     LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    588     return false;
    589   }
    590   std::string signature;
    591   policy_session->SetEntityAuthorizationValue(key_authorization);
    592   // Signing with this key when pcr 2 is unchanged fails.
    593   result = utility->Sign(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL,
    594                          std::string(32, 'a'), policy_session->GetDelegate(),
    595                          &signature);
    596   if (GetFormatOneError(result) != TPM_RC_POLICY_FAIL) {
    597     LOG(ERROR) << "Error using key to sign: " << GetErrorString(result);
    598     return false;
    599   }
    600   std::unique_ptr<AuthorizationDelegate> delegate =
    601       factory_.GetPasswordAuthorization("");
    602   result = utility->ExtendPCR(pcr_index, pcr_extend_data, delegate.get());
    603   if (result != TPM_RC_SUCCESS) {
    604     LOG(ERROR) << "Error extending pcr: " << GetErrorString(result);
    605     return false;
    606   }
    607   // we have to restart the session because we changed the pcr values.
    608   result = policy_session->StartUnboundSession(false);
    609   if (result != TPM_RC_SUCCESS) {
    610     LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
    611     return false;
    612   }
    613   result = policy_session->PolicyCommandCode(TPM_CC_Sign);
    614   if (result != TPM_RC_SUCCESS) {
    615     LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    616     return false;
    617   }
    618   result = policy_session->PolicyPCR(pcr_index, "");
    619   if (result != TPM_RC_SUCCESS) {
    620     LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    621     return false;
    622   }
    623   policy_session->SetEntityAuthorizationValue(key_authorization);
    624   // Signing with this key when pcr 2 is changed succeeds.
    625   result = utility->Sign(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL,
    626                          std::string(32, 'a'), policy_session->GetDelegate(),
    627                          &signature);
    628   if (result != TPM_RC_SUCCESS) {
    629     LOG(ERROR) << "Error using key to sign: " << GetErrorString(result);
    630     return false;
    631   }
    632   result = utility->Verify(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL,
    633                            std::string(32, 'a'), signature, nullptr);
    634   if (result != TPM_RC_SUCCESS) {
    635     LOG(ERROR) << "Error using key to verify: " << GetErrorString(result);
    636     return false;
    637   }
    638   std::string ciphertext;
    639   result = utility->AsymmetricEncrypt(key_handle, TPM_ALG_NULL, TPM_ALG_NULL,
    640                                       "plaintext", nullptr, &ciphertext);
    641   if (result != TPM_RC_SUCCESS) {
    642     LOG(ERROR) << "Error using key to encrypt: " << GetErrorString(result);
    643     return false;
    644   }
    645   result = policy_session->PolicyCommandCode(TPM_CC_Sign);
    646   if (result != TPM_RC_SUCCESS) {
    647     LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    648     return false;
    649   }
    650   result = policy_session->PolicyPCR(pcr_index, "");
    651   if (result != TPM_RC_SUCCESS) {
    652     LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    653     return false;
    654   }
    655   std::string plaintext;
    656   policy_session->SetEntityAuthorizationValue(key_authorization);
    657   // This call is not authorized with the policy, because its command code
    658   // is not TPM_CC_SIGN. It should fail with TPM_RC_POLICY_CC.
    659   result = utility->AsymmetricDecrypt(key_handle, TPM_ALG_NULL, TPM_ALG_NULL,
    660                                       ciphertext, policy_session->GetDelegate(),
    661                                       &plaintext);
    662   if (GetFormatOneError(result) != TPM_RC_POLICY_CC) {
    663     LOG(ERROR) << "Error: " << GetErrorString(result);
    664     return false;
    665   }
    666   return true;
    667 }
    668 
    669 bool TrunksClientTest::PolicyOrTest() {
    670   std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
    671   std::unique_ptr<PolicySession> trial_session = factory_.GetTrialSession();
    672   TPM_RC result;
    673   // Specify a policy that asserts either TPM_CC_RSA_Encrypt or
    674   // TPM_CC_RSA_Decrypt. A key created under this policy can only be used
    675   // to encrypt or decrypt.
    676   result = trial_session->StartUnboundSession(true);
    677   if (result != TPM_RC_SUCCESS) {
    678     LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
    679     return false;
    680   }
    681   result = trial_session->PolicyCommandCode(TPM_CC_Sign);
    682   if (result != TPM_RC_SUCCESS) {
    683     LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    684     return false;
    685   }
    686   std::string sign_digest;
    687   result = trial_session->GetDigest(&sign_digest);
    688   if (result != TPM_RC_SUCCESS) {
    689     LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result);
    690     return false;
    691   }
    692   result = trial_session->StartUnboundSession(true);
    693   if (result != TPM_RC_SUCCESS) {
    694     LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
    695     return false;
    696   }
    697   result = trial_session->PolicyCommandCode(TPM_CC_RSA_Decrypt);
    698   if (result != TPM_RC_SUCCESS) {
    699     LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    700     return false;
    701   }
    702   std::string decrypt_digest;
    703   result = trial_session->GetDigest(&decrypt_digest);
    704   if (result != TPM_RC_SUCCESS) {
    705     LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result);
    706     return false;
    707   }
    708   std::vector<std::string> digests;
    709   digests.push_back(sign_digest);
    710   digests.push_back(decrypt_digest);
    711   result = trial_session->PolicyOR(digests);
    712   if (result != TPM_RC_SUCCESS) {
    713     LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    714     return false;
    715   }
    716   std::string policy_digest;
    717   result = trial_session->GetDigest(&policy_digest);
    718   if (result != TPM_RC_SUCCESS) {
    719     LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result);
    720     return false;
    721   }
    722   // Now that we have the digest, we can close the trial session and use hmac.
    723   trial_session.reset();
    724 
    725   std::unique_ptr<HmacSession> hmac_session = factory_.GetHmacSession();
    726   result = hmac_session->StartUnboundSession(true);
    727   if (result != TPM_RC_SUCCESS) {
    728     LOG(ERROR) << "Error starting hmac session: " << GetErrorString(result);
    729     return false;
    730   }
    731   std::string key_authorization("password");
    732   std::string key_blob;
    733   // This key is created with a policy that specifies that it can only be used
    734   // for encrypt and decrypt operations.
    735   result = utility->CreateRSAKeyPair(
    736       TpmUtility::AsymmetricKeyUsage::kDecryptAndSignKey, 2048, 0x10001,
    737       key_authorization, policy_digest, true,  // use_only_policy_authorization
    738       kNoCreationPCR, hmac_session->GetDelegate(), &key_blob, nullptr);
    739   if (result != TPM_RC_SUCCESS) {
    740     LOG(ERROR) << "Error creating RSA key: " << GetErrorString(result);
    741     return false;
    742   }
    743   TPM_HANDLE key_handle;
    744   result = utility->LoadKey(key_blob, hmac_session->GetDelegate(), &key_handle);
    745   if (result != TPM_RC_SUCCESS) {
    746     LOG(ERROR) << "Error loading RSA key: " << GetErrorString(result);
    747     return false;
    748   }
    749   ScopedKeyHandle scoped_key(factory_, key_handle);
    750 
    751   // Now we can reset the hmac_session.
    752   hmac_session.reset();
    753 
    754   std::unique_ptr<PolicySession> policy_session = factory_.GetPolicySession();
    755   result = policy_session->StartUnboundSession(false);
    756   if (result != TPM_RC_SUCCESS) {
    757     LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
    758     return false;
    759   }
    760   std::string ciphertext;
    761   result = utility->AsymmetricEncrypt(key_handle, TPM_ALG_NULL, TPM_ALG_NULL,
    762                                       "plaintext", nullptr, &ciphertext);
    763   if (result != TPM_RC_SUCCESS) {
    764     LOG(ERROR) << "Error using key to encrypt: " << GetErrorString(result);
    765     return false;
    766   }
    767   result = policy_session->PolicyCommandCode(TPM_CC_RSA_Decrypt);
    768   if (result != TPM_RC_SUCCESS) {
    769     LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    770     return false;
    771   }
    772   result = policy_session->PolicyOR(digests);
    773   if (result != TPM_RC_SUCCESS) {
    774     LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    775     return false;
    776   }
    777   std::string plaintext;
    778   policy_session->SetEntityAuthorizationValue(key_authorization);
    779   // We can freely use the key for decryption.
    780   result = utility->AsymmetricDecrypt(key_handle, TPM_ALG_NULL, TPM_ALG_NULL,
    781                                       ciphertext, policy_session->GetDelegate(),
    782                                       &plaintext);
    783   if (result != TPM_RC_SUCCESS) {
    784     LOG(ERROR) << "Error using key to decrypt: " << GetErrorString(result);
    785     return false;
    786   }
    787   if (plaintext.compare("plaintext") != 0) {
    788     LOG(ERROR) << "Plaintext changed after encrypt + decrypt.";
    789     return false;
    790   }
    791   result = policy_session->PolicyCommandCode(TPM_CC_Sign);
    792   if (result != TPM_RC_SUCCESS) {
    793     LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    794     return false;
    795   }
    796   result = policy_session->PolicyOR(digests);
    797   if (result != TPM_RC_SUCCESS) {
    798     LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    799     return false;
    800   }
    801   std::string signature;
    802   policy_session->SetEntityAuthorizationValue(key_authorization);
    803   // However signing with a key only authorized for encrypt/decrypt should
    804   // fail with TPM_RC_POLICY_CC.
    805   result = utility->Sign(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL,
    806                          std::string(32, 'a'), policy_session->GetDelegate(),
    807                          &signature);
    808   if (result != TPM_RC_SUCCESS) {
    809     LOG(ERROR) << "Error using key to sign: " << GetErrorString(result);
    810     return false;
    811   }
    812   return true;
    813 }
    814 
    815 bool TrunksClientTest::NvramTest(const std::string& owner_password) {
    816   std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
    817   std::unique_ptr<HmacSession> session = factory_.GetHmacSession();
    818   TPM_RC result = session->StartUnboundSession(true /* enable encryption */);
    819   if (result != TPM_RC_SUCCESS) {
    820     LOG(ERROR) << "Error starting hmac session: " << GetErrorString(result);
    821     return false;
    822   }
    823   uint32_t index = 1;
    824   session->SetEntityAuthorizationValue(owner_password);
    825   std::string nv_data("nv_data");
    826   TPMA_NV attributes = TPMA_NV_OWNERWRITE | TPMA_NV_AUTHREAD |
    827                        TPMA_NV_WRITE_STCLEAR | TPMA_NV_READ_STCLEAR;
    828   result = utility->DefineNVSpace(index, nv_data.size(), attributes, "", "",
    829                                   session->GetDelegate());
    830   if (result != TPM_RC_SUCCESS) {
    831     LOG(ERROR) << "Error defining nvram: " << GetErrorString(result);
    832     return false;
    833   }
    834   // Setup auto-cleanup of the NVRAM space.
    835   auto cleanup = [](HmacSession* session, const std::string& owner_password,
    836                     TpmUtility* utility, uint32_t index) {
    837     session->SetEntityAuthorizationValue(owner_password);
    838     TPM_RC result = utility->DestroyNVSpace(index, session->GetDelegate());
    839     if (result != TPM_RC_SUCCESS) {
    840       LOG(ERROR) << "Error destroying nvram: " << GetErrorString(result);
    841     }
    842   };
    843   class Scoper {
    844    public:
    845     explicit Scoper(const base::Closure& callback) : callback_(callback) {}
    846     ~Scoper() {
    847       if (!cancel_)
    848         callback_.Run();
    849     }
    850     void Cancel() { cancel_ = true; }
    851 
    852    private:
    853     base::Closure callback_;
    854     bool cancel_ = false;
    855   } scoper(base::Bind(cleanup, base::Unretained(session.get()), owner_password,
    856                       base::Unretained(utility.get()), index));
    857 
    858   session->SetEntityAuthorizationValue(owner_password);
    859   result = utility->WriteNVSpace(index, 0, nv_data, true /*owner*/,
    860                                  false /*extend*/, session->GetDelegate());
    861   if (result != TPM_RC_SUCCESS) {
    862     LOG(ERROR) << "Error writing nvram: " << GetErrorString(result);
    863     return false;
    864   }
    865   std::string new_nvdata;
    866   session->SetEntityAuthorizationValue("");
    867   result = utility->ReadNVSpace(index, 0, nv_data.size(), false /*owner*/,
    868                                 &new_nvdata, session->GetDelegate());
    869   if (result != TPM_RC_SUCCESS) {
    870     LOG(ERROR) << "Error reading nvram: " << GetErrorString(result);
    871     return false;
    872   }
    873   if (nv_data.compare(new_nvdata) != 0) {
    874     LOG(ERROR) << "NV space had different data than was written.";
    875     return false;
    876   }
    877   session->SetEntityAuthorizationValue(owner_password);
    878   result = utility->LockNVSpace(index, false /*lock_read*/, true /*lock_write*/,
    879                                 false /*owner*/, session->GetDelegate());
    880   if (result != TPM_RC_SUCCESS) {
    881     LOG(ERROR) << "Error locking nvram write: " << GetErrorString(result);
    882     return false;
    883   }
    884   session->SetEntityAuthorizationValue("");
    885   result = utility->ReadNVSpace(index, 0, nv_data.size(), false /*owner*/,
    886                                 &new_nvdata, session->GetDelegate());
    887   if (result != TPM_RC_SUCCESS) {
    888     LOG(ERROR) << "Error reading nvram: " << GetErrorString(result);
    889     return false;
    890   }
    891   if (nv_data.compare(new_nvdata) != 0) {
    892     LOG(ERROR) << "NV space had different data than was written.";
    893     return false;
    894   }
    895   session->SetEntityAuthorizationValue(owner_password);
    896   result = utility->WriteNVSpace(index, 0, nv_data, true /*owner*/,
    897                                  false /*extend*/, session->GetDelegate());
    898   if (result == TPM_RC_SUCCESS) {
    899     LOG(ERROR) << "Wrote nvram after locking!";
    900     return false;
    901   }
    902   result = utility->LockNVSpace(index, true /*lock_read*/, false /*lock_write*/,
    903                                 true /*owner*/, session->GetDelegate());
    904   if (result != TPM_RC_SUCCESS) {
    905     LOG(ERROR) << "Error locking nvram read: " << GetErrorString(result);
    906     return false;
    907   }
    908   result = utility->ReadNVSpace(index, 0, nv_data.size(), false /*owner*/,
    909                                 &new_nvdata, session->GetDelegate());
    910   if (result == TPM_RC_SUCCESS) {
    911     LOG(ERROR) << "Read nvram after locking!";
    912     return false;
    913   }
    914   return true;
    915 }
    916 
    917 bool TrunksClientTest::ManyKeysTest() {
    918   const size_t kNumKeys = 20;
    919   std::vector<std::unique_ptr<ScopedKeyHandle>> key_handles;
    920   std::map<TPM_HANDLE, std::string> public_key_map;
    921   for (size_t i = 0; i < kNumKeys; ++i) {
    922     std::unique_ptr<ScopedKeyHandle> key_handle(new ScopedKeyHandle(factory_));
    923     std::string public_key;
    924     if (!LoadSigningKey(key_handle.get(), &public_key)) {
    925       LOG(ERROR) << "Error loading key " << i << " into TPM.";
    926     }
    927     public_key_map[key_handle->get()] = public_key;
    928     key_handles.push_back(std::move(key_handle));
    929   }
    930   CHECK_EQ(key_handles.size(), kNumKeys);
    931   CHECK_EQ(public_key_map.size(), kNumKeys);
    932   std::unique_ptr<AuthorizationDelegate> delegate =
    933       factory_.GetPasswordAuthorization("");
    934   for (size_t i = 0; i < kNumKeys; ++i) {
    935     const ScopedKeyHandle& key_handle = *key_handles[i];
    936     const std::string& public_key = public_key_map[key_handle.get()];
    937     if (!SignAndVerify(key_handle, public_key, delegate.get())) {
    938       LOG(ERROR) << "Error signing with key " << i;
    939     }
    940   }
    941   std::random_shuffle(key_handles.begin(), key_handles.end());
    942   for (size_t i = 0; i < kNumKeys; ++i) {
    943     const ScopedKeyHandle& key_handle = *key_handles[i];
    944     const std::string& public_key = public_key_map[key_handle.get()];
    945     if (!SignAndVerify(key_handle, public_key, delegate.get())) {
    946       LOG(ERROR) << "Error signing with shuffled key " << i;
    947     }
    948   }
    949   return true;
    950 }
    951 
    952 bool TrunksClientTest::ManySessionsTest() {
    953   const size_t kNumSessions = 20;
    954   std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
    955   std::vector<std::unique_ptr<HmacSession>> sessions;
    956   for (size_t i = 0; i < kNumSessions; ++i) {
    957     std::unique_ptr<HmacSession> session(factory_.GetHmacSession().release());
    958     TPM_RC result = session->StartUnboundSession(true /* enable encryption */);
    959     if (result != TPM_RC_SUCCESS) {
    960       LOG(ERROR) << "Error starting hmac session " << i << ": "
    961                  << GetErrorString(result);
    962       return false;
    963     }
    964     sessions.push_back(std::move(session));
    965   }
    966   CHECK_EQ(sessions.size(), kNumSessions);
    967   ScopedKeyHandle key_handle(factory_);
    968   std::string public_key;
    969   if (!LoadSigningKey(&key_handle, &public_key)) {
    970     return false;
    971   }
    972   for (size_t i = 0; i < kNumSessions; ++i) {
    973     if (!SignAndVerify(key_handle, public_key, sessions[i]->GetDelegate())) {
    974       LOG(ERROR) << "Error signing with hmac session " << i;
    975     }
    976   }
    977   std::random_shuffle(sessions.begin(), sessions.end());
    978   for (size_t i = 0; i < kNumSessions; ++i) {
    979     if (!SignAndVerify(key_handle, public_key, sessions[i]->GetDelegate())) {
    980       LOG(ERROR) << "Error signing with shuffled hmac session " << i;
    981     }
    982   }
    983   return true;
    984 }
    985 
    986 bool TrunksClientTest::PerformRSAEncrpytAndDecrpyt(
    987     TPM_HANDLE key_handle,
    988     const std::string& key_authorization,
    989     HmacSession* session) {
    990   std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
    991   std::string ciphertext;
    992   session->SetEntityAuthorizationValue("");
    993   TPM_RC result = utility->AsymmetricEncrypt(
    994       key_handle, TPM_ALG_NULL, TPM_ALG_NULL, "plaintext",
    995       session->GetDelegate(), &ciphertext);
    996   if (result != TPM_RC_SUCCESS) {
    997     LOG(ERROR) << "Error using key to encrypt: " << GetErrorString(result);
    998     return false;
    999   }
   1000   std::string plaintext;
   1001   session->SetEntityAuthorizationValue(key_authorization);
   1002   result = utility->AsymmetricDecrypt(key_handle, TPM_ALG_NULL, TPM_ALG_NULL,
   1003                                       ciphertext, session->GetDelegate(),
   1004                                       &plaintext);
   1005   if (result != TPM_RC_SUCCESS) {
   1006     LOG(ERROR) << "Error using key to decrypt: " << GetErrorString(result);
   1007     return false;
   1008   }
   1009   if (plaintext.compare("plaintext") != 0) {
   1010     LOG(ERROR) << "Plaintext changed after encrypt + decrypt.";
   1011     return false;
   1012   }
   1013   return true;
   1014 }
   1015 
   1016 void TrunksClientTest::GenerateRSAKeyPair(std::string* modulus,
   1017                                           std::string* prime_factor,
   1018                                           std::string* public_key) {
   1019 #if defined(OPENSSL_IS_BORINGSSL)
   1020   crypto::ScopedRSA rsa(RSA_new());
   1021   crypto::ScopedBIGNUM exponent(BN_new());
   1022   CHECK(BN_set_word(exponent.get(), RSA_F4));
   1023   CHECK(RSA_generate_key_ex(rsa.get(), 2048, exponent.get(), nullptr))
   1024       << "Failed to generate RSA key: " << GetOpenSSLError();
   1025 #else
   1026   crypto::ScopedRSA rsa(RSA_generate_key(2048, 0x10001, nullptr, nullptr));
   1027   CHECK(rsa.get());
   1028 #endif
   1029   modulus->resize(BN_num_bytes(rsa.get()->n), 0);
   1030   BN_bn2bin(rsa.get()->n,
   1031             reinterpret_cast<unsigned char*>(string_as_array(modulus)));
   1032   prime_factor->resize(BN_num_bytes(rsa.get()->p), 0);
   1033   BN_bn2bin(rsa.get()->p,
   1034             reinterpret_cast<unsigned char*>(string_as_array(prime_factor)));
   1035   if (public_key) {
   1036     unsigned char* buffer = NULL;
   1037     int length = i2d_RSAPublicKey(rsa.get(), &buffer);
   1038     CHECK_GT(length, 0);
   1039     crypto::ScopedOpenSSLBytes scoped_buffer(buffer);
   1040     public_key->assign(reinterpret_cast<char*>(buffer), length);
   1041   }
   1042 }
   1043 
   1044 bool TrunksClientTest::VerifyRSASignature(const std::string& public_key,
   1045                                           const std::string& data,
   1046                                           const std::string& signature) {
   1047   auto asn1_ptr = reinterpret_cast<const unsigned char*>(public_key.data());
   1048   crypto::ScopedRSA rsa(
   1049       d2i_RSAPublicKey(nullptr, &asn1_ptr, public_key.size()));
   1050   CHECK(rsa.get());
   1051   std::string digest = crypto::SHA256HashString(data);
   1052   auto digest_buffer = reinterpret_cast<const unsigned char*>(digest.data());
   1053   std::string mutable_signature(signature);
   1054   unsigned char* signature_buffer =
   1055       reinterpret_cast<unsigned char*>(string_as_array(&mutable_signature));
   1056   return (RSA_verify(NID_sha256, digest_buffer, digest.size(), signature_buffer,
   1057                      signature.size(), rsa.get()) == 1);
   1058 }
   1059 
   1060 bool TrunksClientTest::LoadSigningKey(ScopedKeyHandle* key_handle,
   1061                                       std::string* public_key) {
   1062   std::string modulus;
   1063   std::string prime_factor;
   1064   GenerateRSAKeyPair(&modulus, &prime_factor, public_key);
   1065   std::string key_blob;
   1066   std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
   1067   TPM_RC result = utility->ImportRSAKey(
   1068       TpmUtility::AsymmetricKeyUsage::kSignKey, modulus, 0x10001, prime_factor,
   1069       "",  // password
   1070       factory_.GetPasswordAuthorization("").get(), &key_blob);
   1071   if (result != TPM_RC_SUCCESS) {
   1072     LOG(ERROR) << "ImportRSAKey: " << GetErrorString(result);
   1073     return false;
   1074   }
   1075   TPM_HANDLE raw_key_handle;
   1076   result = utility->LoadKey(
   1077       key_blob, factory_.GetPasswordAuthorization("").get(), &raw_key_handle);
   1078   if (result != TPM_RC_SUCCESS) {
   1079     LOG(ERROR) << "LoadKey: " << GetErrorString(result);
   1080     return false;
   1081   }
   1082   key_handle->reset(raw_key_handle);
   1083   return true;
   1084 }
   1085 
   1086 bool TrunksClientTest::SignAndVerify(const ScopedKeyHandle& key_handle,
   1087                                      const std::string& public_key,
   1088                                      AuthorizationDelegate* delegate) {
   1089   std::string signature;
   1090   std::string data_to_sign("sign_this");
   1091   std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
   1092   TPM_RC result =
   1093       utility->Sign(key_handle.get(), TPM_ALG_RSASSA, TPM_ALG_SHA256,
   1094                     data_to_sign, delegate, &signature);
   1095   if (result != TPM_RC_SUCCESS) {
   1096     LOG(ERROR) << "Sign: " << GetErrorString(result);
   1097     return false;
   1098   }
   1099   if (!VerifyRSASignature(public_key, data_to_sign, signature)) {
   1100     LOG(ERROR) << "Signature verification failed: " << GetOpenSSLError();
   1101     return false;
   1102   }
   1103   return true;
   1104 }
   1105 
   1106 }  // namespace trunks
   1107