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