| // |
| // Copyright (C) 2015 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| |
| #include "trunks/trunks_client_test.h" |
| |
| #include <algorithm> |
| #include <map> |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include <base/callback.h> |
| #include <base/logging.h> |
| #include <base/stl_util.h> |
| #include <brillo/bind_lambda.h> |
| #include <crypto/openssl_util.h> |
| #include <crypto/scoped_openssl_types.h> |
| #include <crypto/sha2.h> |
| #include <openssl/bn.h> |
| #include <openssl/err.h> |
| #include <openssl/rsa.h> |
| |
| #include "trunks/authorization_delegate.h" |
| #include "trunks/error_codes.h" |
| #include "trunks/hmac_session.h" |
| #include "trunks/policy_session.h" |
| #include "trunks/scoped_key_handle.h" |
| #include "trunks/tpm_constants.h" |
| #include "trunks/tpm_generated.h" |
| #include "trunks/tpm_state.h" |
| #include "trunks/tpm_utility.h" |
| #include "trunks/trunks_factory_impl.h" |
| |
| namespace { |
| |
| std::string GetOpenSSLError() { |
| BIO* bio = BIO_new(BIO_s_mem()); |
| ERR_print_errors(bio); |
| char* data = nullptr; |
| int data_len = BIO_get_mem_data(bio, &data); |
| std::string error_string(data, data_len); |
| BIO_free(bio); |
| return error_string; |
| } |
| |
| } // namespace |
| |
| namespace trunks { |
| |
| TrunksClientTest::TrunksClientTest(const TrunksFactory& factory) |
| : factory_(factory) { |
| crypto::EnsureOpenSSLInit(); |
| } |
| |
| TrunksClientTest::~TrunksClientTest() {} |
| |
| bool TrunksClientTest::RNGTest() { |
| std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility(); |
| std::unique_ptr<HmacSession> session = factory_.GetHmacSession(); |
| if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting hmac session."; |
| return false; |
| } |
| std::string entropy_data("entropy_data"); |
| std::string random_data; |
| size_t num_bytes = 70; |
| TPM_RC result = utility->StirRandom(entropy_data, session->GetDelegate()); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error stirring TPM RNG: " << GetErrorString(result); |
| return false; |
| } |
| result = |
| utility->GenerateRandom(num_bytes, session->GetDelegate(), &random_data); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error getting random bytes from TPM: " |
| << GetErrorString(result); |
| return false; |
| } |
| if (num_bytes != random_data.size()) { |
| LOG(ERROR) << "Error not enough random bytes received."; |
| return false; |
| } |
| return true; |
| } |
| |
| bool TrunksClientTest::SignTest() { |
| std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility(); |
| std::unique_ptr<HmacSession> session = factory_.GetHmacSession(); |
| if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting hmac session."; |
| return false; |
| } |
| std::string key_authorization("sign"); |
| std::string key_blob; |
| TPM_RC result = utility->CreateRSAKeyPair( |
| TpmUtility::AsymmetricKeyUsage::kSignKey, 2048, 0x10001, |
| key_authorization, "", false, // use_only_policy_authorization |
| kNoCreationPCR, session->GetDelegate(), &key_blob, nullptr); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error creating signing key: " << GetErrorString(result); |
| return false; |
| } |
| TPM_HANDLE signing_key; |
| result = utility->LoadKey(key_blob, session->GetDelegate(), &signing_key); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error loading signing key: " << GetErrorString(result); |
| } |
| ScopedKeyHandle scoped_key(factory_, signing_key); |
| session->SetEntityAuthorizationValue(key_authorization); |
| std::string signature; |
| result = |
| utility->Sign(signing_key, TPM_ALG_NULL, TPM_ALG_NULL, |
| std::string(32, 'a'), session->GetDelegate(), &signature); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error using key to sign: " << GetErrorString(result); |
| return false; |
| } |
| result = utility->Verify(signing_key, TPM_ALG_NULL, TPM_ALG_NULL, |
| std::string(32, 'a'), signature, nullptr); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error using key to verify: " << GetErrorString(result); |
| return false; |
| } |
| return true; |
| } |
| |
| bool TrunksClientTest::DecryptTest() { |
| std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility(); |
| std::unique_ptr<HmacSession> session = factory_.GetHmacSession(); |
| if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting hmac session."; |
| return false; |
| } |
| std::string key_authorization("decrypt"); |
| std::string key_blob; |
| TPM_RC result = utility->CreateRSAKeyPair( |
| TpmUtility::AsymmetricKeyUsage::kDecryptKey, 2048, 0x10001, |
| key_authorization, "", false, // use_only_policy_authorization |
| kNoCreationPCR, session->GetDelegate(), &key_blob, nullptr); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error creating decrypt key: " << GetErrorString(result); |
| return false; |
| } |
| TPM_HANDLE decrypt_key; |
| result = utility->LoadKey(key_blob, session->GetDelegate(), &decrypt_key); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error loading decrypt key: " << GetErrorString(result); |
| } |
| ScopedKeyHandle scoped_key(factory_, decrypt_key); |
| return PerformRSAEncrpytAndDecrpyt(scoped_key.get(), key_authorization, |
| session.get()); |
| } |
| |
| bool TrunksClientTest::ImportTest() { |
| std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility(); |
| std::unique_ptr<HmacSession> session = factory_.GetHmacSession(); |
| if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting hmac session."; |
| return false; |
| } |
| std::string modulus; |
| std::string prime_factor; |
| GenerateRSAKeyPair(&modulus, &prime_factor, nullptr); |
| std::string key_blob; |
| std::string key_authorization("import"); |
| TPM_RC result = utility->ImportRSAKey( |
| TpmUtility::AsymmetricKeyUsage::kDecryptAndSignKey, modulus, 0x10001, |
| prime_factor, key_authorization, session->GetDelegate(), &key_blob); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error importing key into TPM: " << GetErrorString(result); |
| return false; |
| } |
| TPM_HANDLE key_handle; |
| result = utility->LoadKey(key_blob, session->GetDelegate(), &key_handle); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error loading key into TPM: " << GetErrorString(result); |
| return false; |
| } |
| ScopedKeyHandle scoped_key(factory_, key_handle); |
| return PerformRSAEncrpytAndDecrpyt(scoped_key.get(), key_authorization, |
| session.get()); |
| } |
| |
| bool TrunksClientTest::AuthChangeTest() { |
| std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility(); |
| std::unique_ptr<HmacSession> session = factory_.GetHmacSession(); |
| if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting hmac session."; |
| return false; |
| } |
| std::string key_authorization("new_pass"); |
| std::string key_blob; |
| TPM_RC result = utility->CreateRSAKeyPair( |
| TpmUtility::AsymmetricKeyUsage::kDecryptKey, 2048, 0x10001, "old_pass", |
| "", false, // use_only_policy_authorization |
| kNoCreationPCR, session->GetDelegate(), &key_blob, nullptr); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error creating change auth key: " << GetErrorString(result); |
| return false; |
| } |
| TPM_HANDLE key_handle; |
| result = utility->LoadKey(key_blob, session->GetDelegate(), &key_handle); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error loading change auth key: " << GetErrorString(result); |
| } |
| ScopedKeyHandle scoped_key(factory_, key_handle); |
| session->SetEntityAuthorizationValue("old_pass"); |
| result = utility->ChangeKeyAuthorizationData( |
| key_handle, key_authorization, session->GetDelegate(), &key_blob); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error changing auth data: " << GetErrorString(result); |
| return false; |
| } |
| session->SetEntityAuthorizationValue(""); |
| result = utility->LoadKey(key_blob, session->GetDelegate(), &key_handle); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error reloading key: " << GetErrorString(result); |
| return false; |
| } |
| scoped_key.reset(key_handle); |
| return PerformRSAEncrpytAndDecrpyt(scoped_key.get(), key_authorization, |
| session.get()); |
| } |
| |
| bool TrunksClientTest::VerifyKeyCreationTest() { |
| std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility(); |
| std::unique_ptr<HmacSession> session = factory_.GetHmacSession(); |
| if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting hmac session."; |
| return false; |
| } |
| std::string key_blob; |
| std::string creation_blob; |
| session->SetEntityAuthorizationValue(""); |
| TPM_RC result = utility->CreateRSAKeyPair( |
| TpmUtility::AsymmetricKeyUsage::kDecryptKey, 2048, 0x10001, "", "", |
| false, // use_only_policy_authorization |
| kNoCreationPCR, session->GetDelegate(), &key_blob, &creation_blob); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error creating certify key: " << GetErrorString(result); |
| return false; |
| } |
| std::string alternate_key_blob; |
| result = utility->CreateRSAKeyPair( |
| TpmUtility::AsymmetricKeyUsage::kDecryptKey, 2048, 0x10001, "", "", |
| false, // use_only_policy_authorization |
| kNoCreationPCR, session->GetDelegate(), &alternate_key_blob, nullptr); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error creating alternate key: " << GetErrorString(result); |
| return false; |
| } |
| TPM_HANDLE key_handle; |
| result = utility->LoadKey(key_blob, session->GetDelegate(), &key_handle); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error loading certify key: " << GetErrorString(result); |
| return false; |
| } |
| TPM_HANDLE alternate_key_handle; |
| result = utility->LoadKey(alternate_key_blob, session->GetDelegate(), |
| &alternate_key_handle); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error loading alternate key: " << GetErrorString(result); |
| return false; |
| } |
| ScopedKeyHandle certify_key(factory_, key_handle); |
| ScopedKeyHandle alternate_key(factory_, alternate_key_handle); |
| result = utility->CertifyCreation(certify_key.get(), creation_blob); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error certifying key: " << GetErrorString(result); |
| return false; |
| } |
| result = utility->CertifyCreation(alternate_key.get(), creation_blob); |
| if (result == TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error alternate key certified with wrong creation data."; |
| return false; |
| } |
| return true; |
| } |
| |
| bool TrunksClientTest::SealedDataTest() { |
| std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility(); |
| std::unique_ptr<HmacSession> session = factory_.GetHmacSession(); |
| if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting hmac session."; |
| return false; |
| } |
| int pcr_index = 5; |
| std::string policy_digest; |
| TPM_RC result = |
| utility->GetPolicyDigestForPcrValue(pcr_index, "", &policy_digest); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error getting policy_digest: " << GetErrorString(result); |
| return false; |
| } |
| std::string data_to_seal("seal_data"); |
| std::string sealed_data; |
| result = utility->SealData(data_to_seal, policy_digest, |
| session->GetDelegate(), &sealed_data); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error creating Sealed Object: " << GetErrorString(result); |
| return false; |
| } |
| std::unique_ptr<PolicySession> policy_session = factory_.GetPolicySession(); |
| result = policy_session->StartUnboundSession(false); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting policy session: " << GetErrorString(result); |
| return false; |
| } |
| result = policy_session->PolicyPCR(pcr_index, ""); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error restricting policy to pcr value: " |
| << GetErrorString(result); |
| return false; |
| } |
| std::string unsealed_data; |
| result = utility->UnsealData(sealed_data, policy_session->GetDelegate(), |
| &unsealed_data); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error unsealing object: " << GetErrorString(result); |
| return false; |
| } |
| if (data_to_seal != unsealed_data) { |
| LOG(ERROR) << "Error unsealed data from TPM does not match original data."; |
| return false; |
| } |
| result = utility->ExtendPCR(pcr_index, "extend", session->GetDelegate()); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error extending pcr: " << GetErrorString(result); |
| return false; |
| } |
| result = policy_session->PolicyPCR(pcr_index, ""); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error restricting policy to pcr value: " |
| << GetErrorString(result); |
| return false; |
| } |
| result = utility->UnsealData(sealed_data, policy_session->GetDelegate(), |
| &unsealed_data); |
| if (result == TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error object was unsealed with wrong policy_digest."; |
| return false; |
| } |
| return true; |
| } |
| |
| bool TrunksClientTest::PCRTest() { |
| std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility(); |
| std::unique_ptr<HmacSession> session = factory_.GetHmacSession(); |
| if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting hmac session."; |
| return false; |
| } |
| // We are using PCR 2 because it is currently not used by ChromeOS. |
| uint32_t pcr_index = 2; |
| std::string extend_data("data"); |
| std::string old_data; |
| TPM_RC result = utility->ReadPCR(pcr_index, &old_data); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error reading from PCR: " << GetErrorString(result); |
| return false; |
| } |
| result = utility->ExtendPCR(pcr_index, extend_data, session->GetDelegate()); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error extending PCR value: " << GetErrorString(result); |
| return false; |
| } |
| std::string pcr_data; |
| result = utility->ReadPCR(pcr_index, &pcr_data); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error reading from PCR: " << GetErrorString(result); |
| return false; |
| } |
| std::string hashed_extend_data = crypto::SHA256HashString(extend_data); |
| std::string expected_pcr_data = |
| crypto::SHA256HashString(old_data + hashed_extend_data); |
| if (pcr_data.compare(expected_pcr_data) != 0) { |
| LOG(ERROR) << "PCR data does not match expected value."; |
| return false; |
| } |
| return true; |
| } |
| |
| bool TrunksClientTest::PolicyAuthValueTest() { |
| std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility(); |
| std::unique_ptr<PolicySession> trial_session = factory_.GetTrialSession(); |
| TPM_RC result; |
| result = trial_session->StartUnboundSession(true); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting policy session: " << GetErrorString(result); |
| return false; |
| } |
| result = trial_session->PolicyAuthValue(); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error restricting policy to auth value knowledge: " |
| << GetErrorString(result); |
| return false; |
| } |
| std::string policy_digest; |
| result = trial_session->GetDigest(&policy_digest); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result); |
| return false; |
| } |
| // Now that we have the digest, we can close the trial session and use hmac. |
| trial_session.reset(); |
| |
| std::unique_ptr<HmacSession> hmac_session = factory_.GetHmacSession(); |
| result = hmac_session->StartUnboundSession(true); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting hmac session: " << GetErrorString(result); |
| return false; |
| } |
| |
| std::string key_blob; |
| result = utility->CreateRSAKeyPair( |
| TpmUtility::AsymmetricKeyUsage::kDecryptAndSignKey, 2048, 0x10001, |
| "password", policy_digest, true, // use_only_policy_authorization |
| kNoCreationPCR, hmac_session->GetDelegate(), &key_blob, nullptr); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error creating RSA key: " << GetErrorString(result); |
| return false; |
| } |
| |
| TPM_HANDLE key_handle; |
| result = utility->LoadKey(key_blob, hmac_session->GetDelegate(), &key_handle); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error loading RSA key: " << GetErrorString(result); |
| return false; |
| } |
| ScopedKeyHandle scoped_key(factory_, key_handle); |
| |
| // Now we can reset the hmac_session. |
| hmac_session.reset(); |
| |
| std::unique_ptr<PolicySession> policy_session = factory_.GetPolicySession(); |
| result = policy_session->StartUnboundSession(false); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting policy session: " << GetErrorString(result); |
| return false; |
| } |
| result = policy_session->PolicyAuthValue(); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error restricting policy to auth value knowledge: " |
| << GetErrorString(result); |
| return false; |
| } |
| std::string signature; |
| policy_session->SetEntityAuthorizationValue("password"); |
| result = utility->Sign(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL, |
| std::string(32, 0), policy_session->GetDelegate(), |
| &signature); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error signing using RSA key: " << GetErrorString(result); |
| return false; |
| } |
| result = utility->Verify(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL, |
| std::string(32, 0), signature, nullptr); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error verifying using RSA key: " << GetErrorString(result); |
| return false; |
| } |
| std::string ciphertext; |
| result = |
| utility->AsymmetricEncrypt(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL, |
| "plaintext", nullptr, &ciphertext); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error encrypting using RSA key: " << GetErrorString(result); |
| return false; |
| } |
| result = policy_session->PolicyAuthValue(); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error restricting policy to auth value knowledge: " |
| << GetErrorString(result); |
| return false; |
| } |
| std::string plaintext; |
| policy_session->SetEntityAuthorizationValue("password"); |
| result = utility->AsymmetricDecrypt( |
| scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL, ciphertext, |
| policy_session->GetDelegate(), &plaintext); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error encrypting using RSA key: " << GetErrorString(result); |
| return false; |
| } |
| if (plaintext.compare("plaintext") != 0) { |
| LOG(ERROR) << "Plaintext changed after encrypt + decrypt."; |
| return false; |
| } |
| return true; |
| } |
| |
| bool TrunksClientTest::PolicyAndTest() { |
| std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility(); |
| std::unique_ptr<PolicySession> trial_session = factory_.GetTrialSession(); |
| TPM_RC result; |
| result = trial_session->StartUnboundSession(true); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting policy session: " << GetErrorString(result); |
| return false; |
| } |
| result = trial_session->PolicyCommandCode(TPM_CC_Sign); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); |
| return false; |
| } |
| uint32_t pcr_index = 2; |
| std::string pcr_value; |
| result = utility->ReadPCR(pcr_index, &pcr_value); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error reading pcr: " << GetErrorString(result); |
| return false; |
| } |
| std::string pcr_extend_data("extend"); |
| std::string next_pcr_value; |
| std::string hashed_extend_data = crypto::SHA256HashString(pcr_extend_data); |
| next_pcr_value = crypto::SHA256HashString(pcr_value + hashed_extend_data); |
| |
| result = trial_session->PolicyPCR(pcr_index, next_pcr_value); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); |
| return false; |
| } |
| std::string policy_digest; |
| result = trial_session->GetDigest(&policy_digest); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result); |
| return false; |
| } |
| // Now that we have the digest, we can close the trial session and use hmac. |
| trial_session.reset(); |
| |
| std::unique_ptr<HmacSession> hmac_session = factory_.GetHmacSession(); |
| result = hmac_session->StartUnboundSession(true); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting hmac session: " << GetErrorString(result); |
| return false; |
| } |
| std::string key_authorization("password"); |
| std::string key_blob; |
| // This key is created with a policy that dictates it can only be used |
| // when pcr 2 remains unchanged, and when the command is TPM2_Sign. |
| result = utility->CreateRSAKeyPair( |
| TpmUtility::AsymmetricKeyUsage::kDecryptAndSignKey, 2048, 0x10001, |
| key_authorization, policy_digest, true, // use_only_policy_authorization |
| kNoCreationPCR, hmac_session->GetDelegate(), &key_blob, nullptr); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error creating RSA key: " << GetErrorString(result); |
| return false; |
| } |
| TPM_HANDLE key_handle; |
| result = utility->LoadKey(key_blob, hmac_session->GetDelegate(), &key_handle); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error loading RSA key: " << GetErrorString(result); |
| return false; |
| } |
| ScopedKeyHandle scoped_key(factory_, key_handle); |
| |
| // Now we can reset the hmac_session. |
| hmac_session.reset(); |
| |
| std::unique_ptr<PolicySession> policy_session = factory_.GetPolicySession(); |
| result = policy_session->StartUnboundSession(false); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting policy session: " << GetErrorString(result); |
| return false; |
| } |
| result = policy_session->PolicyCommandCode(TPM_CC_Sign); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); |
| return false; |
| } |
| result = policy_session->PolicyPCR(pcr_index, ""); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); |
| return false; |
| } |
| std::string signature; |
| policy_session->SetEntityAuthorizationValue(key_authorization); |
| // Signing with this key when pcr 2 is unchanged fails. |
| result = utility->Sign(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL, |
| std::string(32, 'a'), policy_session->GetDelegate(), |
| &signature); |
| if (GetFormatOneError(result) != TPM_RC_POLICY_FAIL) { |
| LOG(ERROR) << "Error using key to sign: " << GetErrorString(result); |
| return false; |
| } |
| std::unique_ptr<AuthorizationDelegate> delegate = |
| factory_.GetPasswordAuthorization(""); |
| result = utility->ExtendPCR(pcr_index, pcr_extend_data, delegate.get()); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error extending pcr: " << GetErrorString(result); |
| return false; |
| } |
| // we have to restart the session because we changed the pcr values. |
| result = policy_session->StartUnboundSession(false); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting policy session: " << GetErrorString(result); |
| return false; |
| } |
| result = policy_session->PolicyCommandCode(TPM_CC_Sign); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); |
| return false; |
| } |
| result = policy_session->PolicyPCR(pcr_index, ""); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); |
| return false; |
| } |
| policy_session->SetEntityAuthorizationValue(key_authorization); |
| // Signing with this key when pcr 2 is changed succeeds. |
| result = utility->Sign(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL, |
| std::string(32, 'a'), policy_session->GetDelegate(), |
| &signature); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error using key to sign: " << GetErrorString(result); |
| return false; |
| } |
| result = utility->Verify(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL, |
| std::string(32, 'a'), signature, nullptr); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error using key to verify: " << GetErrorString(result); |
| return false; |
| } |
| std::string ciphertext; |
| result = utility->AsymmetricEncrypt(key_handle, TPM_ALG_NULL, TPM_ALG_NULL, |
| "plaintext", nullptr, &ciphertext); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error using key to encrypt: " << GetErrorString(result); |
| return false; |
| } |
| result = policy_session->PolicyCommandCode(TPM_CC_Sign); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); |
| return false; |
| } |
| result = policy_session->PolicyPCR(pcr_index, ""); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); |
| return false; |
| } |
| std::string plaintext; |
| policy_session->SetEntityAuthorizationValue(key_authorization); |
| // This call is not authorized with the policy, because its command code |
| // is not TPM_CC_SIGN. It should fail with TPM_RC_POLICY_CC. |
| result = utility->AsymmetricDecrypt(key_handle, TPM_ALG_NULL, TPM_ALG_NULL, |
| ciphertext, policy_session->GetDelegate(), |
| &plaintext); |
| if (GetFormatOneError(result) != TPM_RC_POLICY_CC) { |
| LOG(ERROR) << "Error: " << GetErrorString(result); |
| return false; |
| } |
| return true; |
| } |
| |
| bool TrunksClientTest::PolicyOrTest() { |
| std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility(); |
| std::unique_ptr<PolicySession> trial_session = factory_.GetTrialSession(); |
| TPM_RC result; |
| // Specify a policy that asserts either TPM_CC_RSA_Encrypt or |
| // TPM_CC_RSA_Decrypt. A key created under this policy can only be used |
| // to encrypt or decrypt. |
| result = trial_session->StartUnboundSession(true); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting policy session: " << GetErrorString(result); |
| return false; |
| } |
| result = trial_session->PolicyCommandCode(TPM_CC_Sign); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); |
| return false; |
| } |
| std::string sign_digest; |
| result = trial_session->GetDigest(&sign_digest); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result); |
| return false; |
| } |
| result = trial_session->StartUnboundSession(true); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting policy session: " << GetErrorString(result); |
| return false; |
| } |
| result = trial_session->PolicyCommandCode(TPM_CC_RSA_Decrypt); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); |
| return false; |
| } |
| std::string decrypt_digest; |
| result = trial_session->GetDigest(&decrypt_digest); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result); |
| return false; |
| } |
| std::vector<std::string> digests; |
| digests.push_back(sign_digest); |
| digests.push_back(decrypt_digest); |
| result = trial_session->PolicyOR(digests); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); |
| return false; |
| } |
| std::string policy_digest; |
| result = trial_session->GetDigest(&policy_digest); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result); |
| return false; |
| } |
| // Now that we have the digest, we can close the trial session and use hmac. |
| trial_session.reset(); |
| |
| std::unique_ptr<HmacSession> hmac_session = factory_.GetHmacSession(); |
| result = hmac_session->StartUnboundSession(true); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting hmac session: " << GetErrorString(result); |
| return false; |
| } |
| std::string key_authorization("password"); |
| std::string key_blob; |
| // This key is created with a policy that specifies that it can only be used |
| // for encrypt and decrypt operations. |
| result = utility->CreateRSAKeyPair( |
| TpmUtility::AsymmetricKeyUsage::kDecryptAndSignKey, 2048, 0x10001, |
| key_authorization, policy_digest, true, // use_only_policy_authorization |
| kNoCreationPCR, hmac_session->GetDelegate(), &key_blob, nullptr); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error creating RSA key: " << GetErrorString(result); |
| return false; |
| } |
| TPM_HANDLE key_handle; |
| result = utility->LoadKey(key_blob, hmac_session->GetDelegate(), &key_handle); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error loading RSA key: " << GetErrorString(result); |
| return false; |
| } |
| ScopedKeyHandle scoped_key(factory_, key_handle); |
| |
| // Now we can reset the hmac_session. |
| hmac_session.reset(); |
| |
| std::unique_ptr<PolicySession> policy_session = factory_.GetPolicySession(); |
| result = policy_session->StartUnboundSession(false); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting policy session: " << GetErrorString(result); |
| return false; |
| } |
| std::string ciphertext; |
| result = utility->AsymmetricEncrypt(key_handle, TPM_ALG_NULL, TPM_ALG_NULL, |
| "plaintext", nullptr, &ciphertext); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error using key to encrypt: " << GetErrorString(result); |
| return false; |
| } |
| result = policy_session->PolicyCommandCode(TPM_CC_RSA_Decrypt); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); |
| return false; |
| } |
| result = policy_session->PolicyOR(digests); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); |
| return false; |
| } |
| std::string plaintext; |
| policy_session->SetEntityAuthorizationValue(key_authorization); |
| // We can freely use the key for decryption. |
| result = utility->AsymmetricDecrypt(key_handle, TPM_ALG_NULL, TPM_ALG_NULL, |
| ciphertext, policy_session->GetDelegate(), |
| &plaintext); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error using key to decrypt: " << GetErrorString(result); |
| return false; |
| } |
| if (plaintext.compare("plaintext") != 0) { |
| LOG(ERROR) << "Plaintext changed after encrypt + decrypt."; |
| return false; |
| } |
| result = policy_session->PolicyCommandCode(TPM_CC_Sign); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); |
| return false; |
| } |
| result = policy_session->PolicyOR(digests); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error restricting policy: " << GetErrorString(result); |
| return false; |
| } |
| std::string signature; |
| policy_session->SetEntityAuthorizationValue(key_authorization); |
| // However signing with a key only authorized for encrypt/decrypt should |
| // fail with TPM_RC_POLICY_CC. |
| result = utility->Sign(scoped_key.get(), TPM_ALG_NULL, TPM_ALG_NULL, |
| std::string(32, 'a'), policy_session->GetDelegate(), |
| &signature); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error using key to sign: " << GetErrorString(result); |
| return false; |
| } |
| return true; |
| } |
| |
| bool TrunksClientTest::NvramTest(const std::string& owner_password) { |
| std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility(); |
| std::unique_ptr<HmacSession> session = factory_.GetHmacSession(); |
| TPM_RC result = session->StartUnboundSession(true /* enable encryption */); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting hmac session: " << GetErrorString(result); |
| return false; |
| } |
| uint32_t index = 1; |
| session->SetEntityAuthorizationValue(owner_password); |
| std::string nv_data("nv_data"); |
| TPMA_NV attributes = TPMA_NV_OWNERWRITE | TPMA_NV_AUTHREAD | |
| TPMA_NV_WRITE_STCLEAR | TPMA_NV_READ_STCLEAR; |
| result = utility->DefineNVSpace(index, nv_data.size(), attributes, "", "", |
| session->GetDelegate()); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error defining nvram: " << GetErrorString(result); |
| return false; |
| } |
| // Setup auto-cleanup of the NVRAM space. |
| auto cleanup = [](HmacSession* session, const std::string& owner_password, |
| TpmUtility* utility, uint32_t index) { |
| session->SetEntityAuthorizationValue(owner_password); |
| TPM_RC result = utility->DestroyNVSpace(index, session->GetDelegate()); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error destroying nvram: " << GetErrorString(result); |
| } |
| }; |
| class Scoper { |
| public: |
| explicit Scoper(const base::Closure& callback) : callback_(callback) {} |
| ~Scoper() { |
| if (!cancel_) |
| callback_.Run(); |
| } |
| void Cancel() { cancel_ = true; } |
| |
| private: |
| base::Closure callback_; |
| bool cancel_ = false; |
| } scoper(base::Bind(cleanup, base::Unretained(session.get()), owner_password, |
| base::Unretained(utility.get()), index)); |
| |
| session->SetEntityAuthorizationValue(owner_password); |
| result = utility->WriteNVSpace(index, 0, nv_data, true /*owner*/, |
| false /*extend*/, session->GetDelegate()); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error writing nvram: " << GetErrorString(result); |
| return false; |
| } |
| std::string new_nvdata; |
| session->SetEntityAuthorizationValue(""); |
| result = utility->ReadNVSpace(index, 0, nv_data.size(), false /*owner*/, |
| &new_nvdata, session->GetDelegate()); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error reading nvram: " << GetErrorString(result); |
| return false; |
| } |
| if (nv_data.compare(new_nvdata) != 0) { |
| LOG(ERROR) << "NV space had different data than was written."; |
| return false; |
| } |
| session->SetEntityAuthorizationValue(owner_password); |
| result = utility->LockNVSpace(index, false /*lock_read*/, true /*lock_write*/, |
| false /*owner*/, session->GetDelegate()); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error locking nvram write: " << GetErrorString(result); |
| return false; |
| } |
| session->SetEntityAuthorizationValue(""); |
| result = utility->ReadNVSpace(index, 0, nv_data.size(), false /*owner*/, |
| &new_nvdata, session->GetDelegate()); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error reading nvram: " << GetErrorString(result); |
| return false; |
| } |
| if (nv_data.compare(new_nvdata) != 0) { |
| LOG(ERROR) << "NV space had different data than was written."; |
| return false; |
| } |
| session->SetEntityAuthorizationValue(owner_password); |
| result = utility->WriteNVSpace(index, 0, nv_data, true /*owner*/, |
| false /*extend*/, session->GetDelegate()); |
| if (result == TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Wrote nvram after locking!"; |
| return false; |
| } |
| result = utility->LockNVSpace(index, true /*lock_read*/, false /*lock_write*/, |
| true /*owner*/, session->GetDelegate()); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error locking nvram read: " << GetErrorString(result); |
| return false; |
| } |
| result = utility->ReadNVSpace(index, 0, nv_data.size(), false /*owner*/, |
| &new_nvdata, session->GetDelegate()); |
| if (result == TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Read nvram after locking!"; |
| return false; |
| } |
| return true; |
| } |
| |
| bool TrunksClientTest::ManyKeysTest() { |
| const size_t kNumKeys = 20; |
| std::vector<std::unique_ptr<ScopedKeyHandle>> key_handles; |
| std::map<TPM_HANDLE, std::string> public_key_map; |
| for (size_t i = 0; i < kNumKeys; ++i) { |
| std::unique_ptr<ScopedKeyHandle> key_handle(new ScopedKeyHandle(factory_)); |
| std::string public_key; |
| if (!LoadSigningKey(key_handle.get(), &public_key)) { |
| LOG(ERROR) << "Error loading key " << i << " into TPM."; |
| } |
| public_key_map[key_handle->get()] = public_key; |
| key_handles.push_back(std::move(key_handle)); |
| } |
| CHECK_EQ(key_handles.size(), kNumKeys); |
| CHECK_EQ(public_key_map.size(), kNumKeys); |
| std::unique_ptr<AuthorizationDelegate> delegate = |
| factory_.GetPasswordAuthorization(""); |
| for (size_t i = 0; i < kNumKeys; ++i) { |
| const ScopedKeyHandle& key_handle = *key_handles[i]; |
| const std::string& public_key = public_key_map[key_handle.get()]; |
| if (!SignAndVerify(key_handle, public_key, delegate.get())) { |
| LOG(ERROR) << "Error signing with key " << i; |
| } |
| } |
| std::random_shuffle(key_handles.begin(), key_handles.end()); |
| for (size_t i = 0; i < kNumKeys; ++i) { |
| const ScopedKeyHandle& key_handle = *key_handles[i]; |
| const std::string& public_key = public_key_map[key_handle.get()]; |
| if (!SignAndVerify(key_handle, public_key, delegate.get())) { |
| LOG(ERROR) << "Error signing with shuffled key " << i; |
| } |
| } |
| return true; |
| } |
| |
| bool TrunksClientTest::ManySessionsTest() { |
| const size_t kNumSessions = 20; |
| std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility(); |
| std::vector<std::unique_ptr<HmacSession>> sessions; |
| for (size_t i = 0; i < kNumSessions; ++i) { |
| std::unique_ptr<HmacSession> session(factory_.GetHmacSession().release()); |
| TPM_RC result = session->StartUnboundSession(true /* enable encryption */); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error starting hmac session " << i << ": " |
| << GetErrorString(result); |
| return false; |
| } |
| sessions.push_back(std::move(session)); |
| } |
| CHECK_EQ(sessions.size(), kNumSessions); |
| ScopedKeyHandle key_handle(factory_); |
| std::string public_key; |
| if (!LoadSigningKey(&key_handle, &public_key)) { |
| return false; |
| } |
| for (size_t i = 0; i < kNumSessions; ++i) { |
| if (!SignAndVerify(key_handle, public_key, sessions[i]->GetDelegate())) { |
| LOG(ERROR) << "Error signing with hmac session " << i; |
| } |
| } |
| std::random_shuffle(sessions.begin(), sessions.end()); |
| for (size_t i = 0; i < kNumSessions; ++i) { |
| if (!SignAndVerify(key_handle, public_key, sessions[i]->GetDelegate())) { |
| LOG(ERROR) << "Error signing with shuffled hmac session " << i; |
| } |
| } |
| return true; |
| } |
| |
| bool TrunksClientTest::PerformRSAEncrpytAndDecrpyt( |
| TPM_HANDLE key_handle, |
| const std::string& key_authorization, |
| HmacSession* session) { |
| std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility(); |
| std::string ciphertext; |
| session->SetEntityAuthorizationValue(""); |
| TPM_RC result = utility->AsymmetricEncrypt( |
| key_handle, TPM_ALG_NULL, TPM_ALG_NULL, "plaintext", |
| session->GetDelegate(), &ciphertext); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error using key to encrypt: " << GetErrorString(result); |
| return false; |
| } |
| std::string plaintext; |
| session->SetEntityAuthorizationValue(key_authorization); |
| result = utility->AsymmetricDecrypt(key_handle, TPM_ALG_NULL, TPM_ALG_NULL, |
| ciphertext, session->GetDelegate(), |
| &plaintext); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Error using key to decrypt: " << GetErrorString(result); |
| return false; |
| } |
| if (plaintext.compare("plaintext") != 0) { |
| LOG(ERROR) << "Plaintext changed after encrypt + decrypt."; |
| return false; |
| } |
| return true; |
| } |
| |
| void TrunksClientTest::GenerateRSAKeyPair(std::string* modulus, |
| std::string* prime_factor, |
| std::string* public_key) { |
| #if defined(OPENSSL_IS_BORINGSSL) |
| crypto::ScopedRSA rsa(RSA_new()); |
| crypto::ScopedBIGNUM exponent(BN_new()); |
| CHECK(BN_set_word(exponent.get(), RSA_F4)); |
| CHECK(RSA_generate_key_ex(rsa.get(), 2048, exponent.get(), nullptr)) |
| << "Failed to generate RSA key: " << GetOpenSSLError(); |
| #else |
| crypto::ScopedRSA rsa(RSA_generate_key(2048, 0x10001, nullptr, nullptr)); |
| CHECK(rsa.get()); |
| #endif |
| modulus->resize(BN_num_bytes(rsa.get()->n), 0); |
| BN_bn2bin(rsa.get()->n, |
| reinterpret_cast<unsigned char*>(string_as_array(modulus))); |
| prime_factor->resize(BN_num_bytes(rsa.get()->p), 0); |
| BN_bn2bin(rsa.get()->p, |
| reinterpret_cast<unsigned char*>(string_as_array(prime_factor))); |
| if (public_key) { |
| unsigned char* buffer = NULL; |
| int length = i2d_RSAPublicKey(rsa.get(), &buffer); |
| CHECK_GT(length, 0); |
| crypto::ScopedOpenSSLBytes scoped_buffer(buffer); |
| public_key->assign(reinterpret_cast<char*>(buffer), length); |
| } |
| } |
| |
| bool TrunksClientTest::VerifyRSASignature(const std::string& public_key, |
| const std::string& data, |
| const std::string& signature) { |
| auto asn1_ptr = reinterpret_cast<const unsigned char*>(public_key.data()); |
| crypto::ScopedRSA rsa( |
| d2i_RSAPublicKey(nullptr, &asn1_ptr, public_key.size())); |
| CHECK(rsa.get()); |
| std::string digest = crypto::SHA256HashString(data); |
| auto digest_buffer = reinterpret_cast<const unsigned char*>(digest.data()); |
| std::string mutable_signature(signature); |
| unsigned char* signature_buffer = |
| reinterpret_cast<unsigned char*>(string_as_array(&mutable_signature)); |
| return (RSA_verify(NID_sha256, digest_buffer, digest.size(), signature_buffer, |
| signature.size(), rsa.get()) == 1); |
| } |
| |
| bool TrunksClientTest::LoadSigningKey(ScopedKeyHandle* key_handle, |
| std::string* public_key) { |
| std::string modulus; |
| std::string prime_factor; |
| GenerateRSAKeyPair(&modulus, &prime_factor, public_key); |
| std::string key_blob; |
| std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility(); |
| TPM_RC result = utility->ImportRSAKey( |
| TpmUtility::AsymmetricKeyUsage::kSignKey, modulus, 0x10001, prime_factor, |
| "", // password |
| factory_.GetPasswordAuthorization("").get(), &key_blob); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "ImportRSAKey: " << GetErrorString(result); |
| return false; |
| } |
| TPM_HANDLE raw_key_handle; |
| result = utility->LoadKey( |
| key_blob, factory_.GetPasswordAuthorization("").get(), &raw_key_handle); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "LoadKey: " << GetErrorString(result); |
| return false; |
| } |
| key_handle->reset(raw_key_handle); |
| return true; |
| } |
| |
| bool TrunksClientTest::SignAndVerify(const ScopedKeyHandle& key_handle, |
| const std::string& public_key, |
| AuthorizationDelegate* delegate) { |
| std::string signature; |
| std::string data_to_sign("sign_this"); |
| std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility(); |
| TPM_RC result = |
| utility->Sign(key_handle.get(), TPM_ALG_RSASSA, TPM_ALG_SHA256, |
| data_to_sign, delegate, &signature); |
| if (result != TPM_RC_SUCCESS) { |
| LOG(ERROR) << "Sign: " << GetErrorString(result); |
| return false; |
| } |
| if (!VerifyRSASignature(public_key, data_to_sign, signature)) { |
| LOG(ERROR) << "Signature verification failed: " << GetOpenSSLError(); |
| return false; |
| } |
| return true; |
| } |
| |
| } // namespace trunks |