blob: b25336f0e8b461fc01da0397372f9218c67de258 [file] [log] [blame]
// Copyright 2015 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Contains the implementation of class Tpm
#include "cryptohome/tpm2_impl.h"
#include <string>
#include <base/logging.h>
#include <crypto/scoped_openssl_types.h>
#include <openssl/rsa.h>
#include <trunks/authorization_delegate.h>
#include <trunks/blob_parser.h>
#include <trunks/error_codes.h>
#include <trunks/policy_session.h>
#include <trunks/tpm_constants.h>
#include <trunks/tpm_generated.h>
#include <trunks/trunks_factory.h>
#include <trunks/trunks_factory_impl.h>
#include <trunks/trunks_proxy.h>
#include "cryptohome/cryptolib.h"
using chromeos::SecureBlob;
using trunks::GetErrorString;
using trunks::TPM_RC;
using trunks::TPM_RC_SUCCESS;
using trunks::TrunksFactory;
namespace cryptohome {
Tpm2Impl::Tpm2Impl()
: trunks_factory_(new trunks::TrunksFactoryImpl()),
tpm_state_(trunks_factory_->GetTpmState()),
trunks_utility_(trunks_factory_->GetTpmUtility()) {}
Tpm2Impl::Tpm2Impl(TrunksFactory* factory)
: trunks_factory_(factory),
tpm_state_(trunks_factory_->GetTpmState()),
trunks_utility_(trunks_factory_->GetTpmUtility()) {}
Tpm2Impl::~Tpm2Impl() {}
bool Tpm2Impl::GetOwnerPassword(chromeos::Blob* owner_password) {
if (!owner_password_.empty()) {
owner_password->assign(owner_password_.begin(), owner_password_.end());
} else {
owner_password->clear();
}
return true;
}
void Tpm2Impl::SetOwnerPassword(const SecureBlob& owner_password) {
SecureBlob tmp(owner_password);
owner_password_.swap(tmp);
}
bool Tpm2Impl::PerformEnabledOwnedCheck(bool* enabled, bool* owned) {
TPM_RC result = tpm_state_->Initialize();
if (result != TPM_RC_SUCCESS) {
if (enabled) {
*enabled = false;
}
if (owned) {
*owned = false;
}
LOG(ERROR) << "Error getting tpm status for owned check: "
<< GetErrorString(result);
return false;
}
if (enabled) {
*enabled = tpm_state_->IsEnabled();
}
if (owned) {
*owned = tpm_state_->IsOwned();
}
return true;
}
bool Tpm2Impl::GetRandomData(size_t length, chromeos::Blob* data) {
CHECK(data);
std::string random_data;
TPM_RC result = trunks_utility_->GenerateRandom(length,
nullptr, // No authorization.
&random_data);
if ((result != TPM_RC_SUCCESS) || (random_data.size() != length)) {
LOG(ERROR) << "Error getting random data: " << GetErrorString(result);
return false;
}
data->assign(random_data.begin(), random_data.end());
return true;
}
bool Tpm2Impl::DefineLockOnceNvram(uint32_t index, size_t length) {
if (owner_password_.empty()) {
LOG(ERROR) << "Defining NVram needs owner_password.";
return false;
}
scoped_ptr<trunks::HmacSession> session = trunks_factory_->GetHmacSession();
TPM_RC result = session->StartUnboundSession(true /* Enable encryption */);
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error starting a session: " << GetErrorString(result);
return false;
}
session->SetEntityAuthorizationValue(owner_password_.to_string());
result = trunks_utility_->DefineNVSpace(index, length,
session->GetDelegate());
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error defining NVram space: " << GetErrorString(result);
return false;
}
return true;
}
bool Tpm2Impl::DestroyNvram(uint32_t index) {
if (owner_password_.empty()) {
LOG(ERROR) << "Destroying NVram needs owner_password.";
return false;
}
scoped_ptr<trunks::HmacSession> session = trunks_factory_->GetHmacSession();
TPM_RC result = session->StartUnboundSession(true /* Enable encryption */);
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error starting a session: " << GetErrorString(result);
return false;
}
session->SetEntityAuthorizationValue(owner_password_.to_string());
result = trunks_utility_->DestroyNVSpace(index, session->GetDelegate());
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error destroying NVram space: " << GetErrorString(result);
return false;
}
return true;
}
bool Tpm2Impl::WriteNvram(uint32_t index, const SecureBlob& blob) {
if (owner_password_.empty()) {
LOG(ERROR) << "Writing NVram needs owner_password.";
return false;
}
scoped_ptr<trunks::HmacSession> session = trunks_factory_->GetHmacSession();
TPM_RC result = session->StartUnboundSession(true /* Enable encryption */);
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error starting a session: " << GetErrorString(result);
return false;
}
session->SetEntityAuthorizationValue(owner_password_.to_string());
result = trunks_utility_->WriteNVSpace(index,
0, // offset
blob.to_string(),
session->GetDelegate());
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error writing to NVSpace: " << GetErrorString(result);
return false;
}
session->SetEntityAuthorizationValue("");
result = trunks_utility_->LockNVSpace(index, session->GetDelegate());
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error locking NVSpace: " << GetErrorString(result);
return false;
}
return true;
}
bool Tpm2Impl::ReadNvram(uint32_t index, SecureBlob* blob) {
scoped_ptr<trunks::HmacSession> session = trunks_factory_->GetHmacSession();
TPM_RC result = session->StartUnboundSession(true /* Enable encryption */);
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error starting a session: " << GetErrorString(result);
return false;
}
session->SetEntityAuthorizationValue("");
std::string nvram_data;
result = trunks_utility_->ReadNVSpace(index,
0, // offset
GetNvramSize(index),
&nvram_data,
session->GetDelegate());
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error reading from nvram: " << GetErrorString(result);
return false;
}
blob->assign(nvram_data.begin(), nvram_data.end());
return true;
}
bool Tpm2Impl::IsNvramDefined(uint32_t index) {
trunks::TPMS_NV_PUBLIC nvram_public;
TPM_RC result = trunks_utility_->GetNVSpacePublicArea(index, &nvram_public);
if (trunks::GetFormatOneError(result) == trunks::TPM_RC_HANDLE) {
return false;
} else if (result == TPM_RC_SUCCESS) {
return true;
} else {
LOG(ERROR) << "Error reading NV space for index " << index
<< " with error: " << GetErrorString(result);
}
return false;
}
bool Tpm2Impl::IsNvramLocked(uint32_t index) {
trunks::TPMS_NV_PUBLIC nvram_public;
TPM_RC result = trunks_utility_->GetNVSpacePublicArea(index, &nvram_public);
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error reading NV space for index " << index
<< " with error: " << GetErrorString(result);
return false;
}
return (nvram_public.attributes & trunks::TPMA_NV_WRITELOCKED) != 0;
}
unsigned int Tpm2Impl::GetNvramSize(uint32_t index) {
trunks::TPMS_NV_PUBLIC nvram_public;
TPM_RC result = trunks_utility_->GetNVSpacePublicArea(index, &nvram_public);
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error reading NV space for index " << index
<< " with error: " << GetErrorString(result);
return 0;
}
return nvram_public.data_size;
}
bool Tpm2Impl::IsEndorsementKeyAvailable() {
LOG(FATAL) << "Not Implemented.";
return false;
}
bool Tpm2Impl::CreateEndorsementKey() {
LOG(FATAL) << "Not Implemented.";
return false;
}
bool Tpm2Impl::GetEndorsementPublicKey(SecureBlob* ek_public_key) {
LOG(FATAL) << "Not Implemented.";
return false;
}
bool Tpm2Impl::GetEndorsementCredential(SecureBlob* credential) {
LOG(FATAL) << "Not Implemented.";
return false;
}
bool Tpm2Impl::MakeIdentity(SecureBlob* identity_public_key_der,
SecureBlob* identity_public_key,
SecureBlob* identity_key_blob,
SecureBlob* identity_binding,
SecureBlob* identity_label,
SecureBlob* pca_public_key,
SecureBlob* endorsement_credential,
SecureBlob* platform_credential,
SecureBlob* conformance_credential) {
LOG(FATAL) << "Not Implemented.";
return false;
}
bool Tpm2Impl::QuotePCR(int pcr_index,
const SecureBlob& identity_key_blob,
const SecureBlob& external_data,
SecureBlob* pcr_value,
SecureBlob* quoted_data,
SecureBlob* quote) {
LOG(FATAL) << "Not Implemented.";
return false;
}
bool Tpm2Impl::SealToPCR0(const chromeos::Blob& value,
chromeos::Blob* sealed_value) {
std::string policy_digest;
TPM_RC result = trunks_utility_->GetPolicyDigestForPcrValue(0, "",
&policy_digest);
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result);
return false;
}
scoped_ptr<trunks::HmacSession> session = trunks_factory_->GetHmacSession();
if (trunks_utility_->StartSession(session.get()) != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error starting hmac session.";
return false;
}
std::string data_to_seal(value.begin(), value.end());
std::string sealed_data;
result = trunks_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;
}
sealed_value->assign(sealed_data.begin(), sealed_data.end());
return true;
}
bool Tpm2Impl::Unseal(const chromeos::Blob& sealed_value,
chromeos::Blob* value) {
scoped_ptr<trunks::PolicySession> policy_session =
trunks_factory_->GetPolicySession();
TPM_RC result = policy_session->StartUnboundSession(false);
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
return false;
}
result = policy_session->PolicyPCR(0, "");
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error restricting policy to pcr 0: "
<< GetErrorString(result);
return false;
}
std::string sealed_data(sealed_value.begin(), sealed_value.end());
std::string unsealed_data;
result = trunks_utility_->UnsealData(sealed_data,
policy_session->GetDelegate(),
&unsealed_data);
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error unsealing object: " << GetErrorString(result);
return false;
}
value->assign(unsealed_data.begin(), unsealed_data.end());
return true;
}
bool Tpm2Impl::CreateCertifiedKey(const SecureBlob& identity_key_blob,
const SecureBlob& external_data,
SecureBlob* certified_public_key,
SecureBlob* certified_public_key_der,
SecureBlob* certified_key_blob,
SecureBlob* certified_key_info,
SecureBlob* certified_key_proof) {
LOG(FATAL) << "Not Implemented.";
return false;
}
bool Tpm2Impl::CreateDelegate(const SecureBlob& identity_key_blob,
SecureBlob* delegate_blob,
SecureBlob* delegate_secret) {
LOG(FATAL) << "Not Implemented.";
return false;
}
bool Tpm2Impl::ActivateIdentity(const SecureBlob& delegate_blob,
const SecureBlob& delegate_secret,
const SecureBlob& identity_key_blob,
const SecureBlob& encrypted_asym_ca,
const SecureBlob& encrypted_sym_ca,
SecureBlob* identity_credential) {
LOG(FATAL) << "Not Implemented.";
return false;
}
bool Tpm2Impl::TakeOwnership(int max_timeout_tries,
const SecureBlob& owner_password) {
LOG(FATAL) << "Not Implemented.";
return false;
}
bool Tpm2Impl::InitializeSrk(const SecureBlob& owner_password) {
LOG(FATAL) << "Not Implemented.";
return false;
}
bool Tpm2Impl::ChangeOwnerPassword(const SecureBlob& previous_owner_password,
const SecureBlob& owner_password) {
LOG(FATAL) << "Not Implemented.";
return false;
}
bool Tpm2Impl::TestTpmAuth(const SecureBlob& owner_password) {
LOG(FATAL) << "Not Implemented.";
return false;
}
bool Tpm2Impl::IsTransient(TpmRetryAction retry_action) {
LOG(FATAL) << "Not Implemented.";
return false;
}
bool Tpm2Impl::Sign(const SecureBlob& key_blob,
const SecureBlob& input,
int bound_pcr_index,
SecureBlob* signature) {
trunks::AuthorizationDelegate* delegate;
scoped_ptr<trunks::PolicySession> policy_session;
scoped_ptr<trunks::HmacSession> hmac_session;
TPM_RC result;
if (bound_pcr_index >= 0) {
policy_session = trunks_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(bound_pcr_index, "");
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error creating PCR policy: " << GetErrorString(result);
return false;
}
delegate = policy_session->GetDelegate();
} else {
hmac_session = trunks_factory_->GetHmacSession();
result = hmac_session->StartUnboundSession(true);
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error starting hmac session: " << GetErrorString(result);
return false;
}
hmac_session->SetEntityAuthorizationValue("");
delegate = hmac_session->GetDelegate();
}
ScopedKeyHandle handle;
TpmRetryAction retry = LoadWrappedKey(key_blob, &handle);
if (retry != kTpmRetryNone) {
LOG(ERROR) << "Error loading pcr bound key.";
return false;
}
std::string tpm_signature;
result = trunks_utility_->Sign(handle.value(),
trunks::TPM_ALG_RSASSA,
trunks::TPM_ALG_SHA256,
input.to_string(),
delegate,
&tpm_signature);
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error signing: " << GetErrorString(result);
return false;
}
signature->assign(tpm_signature.begin(), tpm_signature.end());
return true;
}
bool Tpm2Impl::CreatePCRBoundKey(int pcr_index,
const SecureBlob& pcr_value,
SecureBlob* key_blob,
SecureBlob* public_key_der,
SecureBlob* creation_blob) {
CHECK(key_blob) << "No key blob argument provided.";
CHECK(creation_blob) << "No creation blob argument provided.";
std::string policy_digest;
TPM_RC result = trunks_utility_->GetPolicyDigestForPcrValue(
pcr_index, pcr_value.to_string(), &policy_digest);
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result);
return false;
}
std::string tpm_key_blob;
std::string tpm_creation_blob;
scoped_ptr<trunks::AuthorizationDelegate> delegate =
trunks_factory_->GetPasswordAuthorization("");
result = trunks_utility_->CreateRSAKeyPair(
trunks::TpmUtility::kSignKey,
kDefaultTpmRsaModulusSize,
kDefaultTpmPublicExponent,
"", // No authorization
policy_digest,
true, // use_only_policy_authorization
pcr_index,
delegate.get(),
&tpm_key_blob,
&tpm_creation_blob /* No creation_blob */);
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error creating a pcr bound key: " << GetErrorString(result);
return false;
}
key_blob->assign(tpm_key_blob.begin(), tpm_key_blob.end());
creation_blob->assign(tpm_creation_blob.begin(), tpm_creation_blob.end());
// if |public_key_der| is present, create and assign it.
if (public_key_der) {
trunks::TPM2B_PUBLIC public_data;
trunks::TPM2B_PRIVATE private_data;
if (!trunks_factory_->GetBlobParser()->ParseKeyBlob(key_blob->to_string(),
&public_data,
&private_data)) {
return false;
}
if (!PublicAreaToPublicKeyDER(public_data.public_area, public_key_der)) {
return false;
}
}
return true;
}
bool Tpm2Impl::VerifyPCRBoundKey(int pcr_index,
const SecureBlob& pcr_value,
const SecureBlob& key_blob,
const SecureBlob& creation_blob) {
// First we verify that the PCR were in a known good state at the time of
// Key creation.
trunks::TPM2B_CREATION_DATA creation_data;
trunks::TPM2B_DIGEST creation_hash;
trunks::TPMT_TK_CREATION creation_ticket;
if (!trunks_factory_->GetBlobParser()->ParseCreationBlob(
creation_blob.to_string(), &creation_data,
&creation_hash, &creation_ticket)) {
LOG(ERROR) << "Error parsing creation_blob.";
return false;
}
trunks::TPML_PCR_SELECTION& pcr_select =
creation_data.creation_data.pcr_select;
if (pcr_select.count != 1) {
LOG(ERROR) << "Creation data missing creation PCR value.";
return false;
}
if (pcr_select.pcr_selections[0].hash !=
trunks::TPM_ALG_SHA256) {
LOG(ERROR) << "Creation PCR extended with wrong hash algorithm.";
return false;
}
if (pcr_select.pcr_selections[0].pcr_select[pcr_index / 8] !=
(1 << (pcr_index % 8))) {
LOG(ERROR) << "Incorrect creation PCR specified.";
return false;
}
SecureBlob expected_pcr_digest = CryptoLib::Sha256(pcr_value);
if (creation_data.creation_data.pcr_digest.size !=
expected_pcr_digest.size()) {
LOG(ERROR) << "Incorrect PCR digest size.";
return false;
}
if (memcmp(creation_data.creation_data.pcr_digest.buffer,
expected_pcr_digest.data(), expected_pcr_digest.size()) != 0) {
LOG(ERROR) << "Incorrect PCR digest value.";
return false;
}
// Then we certify that the key was created by the TPM.
ScopedKeyHandle scoped_handle;
if (LoadWrappedKey(key_blob, &scoped_handle) != Tpm::kTpmRetryNone) {
return false;
}
TPM_RC result = trunks_utility_->CertifyCreation(scoped_handle.value(),
creation_blob.to_string());
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error certifying that key was created by TPM: "
<< trunks::GetErrorString(result);
return false;
}
// Finally we verify that the key's policy_digest is the expected value.
scoped_ptr<trunks::PolicySession> trial_session =
trunks_factory_->GetTrialSession();
result = trial_session->StartUnboundSession(true);
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error starting a trial session: " << GetErrorString(result);
return false;
}
result = trial_session->PolicyPCR(pcr_index, pcr_value.to_string());
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error restricting trial policy to pcr value: "
<< 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;
}
trunks::TPMT_PUBLIC public_area;
result = trunks_utility_->GetKeyPublicArea(scoped_handle.value(),
&public_area);
if (result != TPM_RC_SUCCESS) {
return false;
}
if (public_area.auth_policy.size != policy_digest.size()) {
LOG(ERROR) << "Key auth policy and policy digest are of different length.";
return false;
} else if (memcmp(public_area.auth_policy.buffer,
policy_digest.data(),
policy_digest.size()) != 0) {
LOG(ERROR) << "Key auth policy is different from policy digest.";
return false;
} else if (public_area.object_attributes & trunks::kUserWithAuth) {
LOG(ERROR) << "Key authorization is not restricted to policy.";
return false;
}
return true;
}
bool Tpm2Impl::ExtendPCR(int pcr_index, const SecureBlob& extension) {
scoped_ptr<trunks::AuthorizationDelegate> delegate =
trunks_factory_->GetPasswordAuthorization("");
TPM_RC result = trunks_utility_->ExtendPCR(pcr_index,
extension.to_string(),
delegate.get());
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error extending PCR: " << GetErrorString(result);
return false;
}
return true;
}
bool Tpm2Impl::ReadPCR(int pcr_index, SecureBlob* pcr_value) {
CHECK(pcr_value);
std::string pcr_digest;
TPM_RC result = trunks_utility_->ReadPCR(pcr_index, &pcr_digest);
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error reading from PCR: " << GetErrorString(result);
return false;
}
pcr_value->assign(pcr_digest.begin(), pcr_digest.end());
return true;
}
bool Tpm2Impl::WrapRsaKey(const SecureBlob& public_modulus,
const SecureBlob& prime_factor,
SecureBlob* wrapped_key) {
std::string key_blob;
scoped_ptr<trunks::AuthorizationDelegate> delegate =
trunks_factory_->GetPasswordAuthorization("");
TPM_RC result = trunks_utility_->ImportRSAKey(
trunks::TpmUtility::kDecryptKey,
public_modulus.to_string(),
kDefaultTpmPublicExponent,
prime_factor.to_string(),
"", // No authorization,
delegate.get(),
&key_blob);
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error creating SRK wrapped key: " << GetErrorString(result);
return false;
}
wrapped_key->assign(key_blob.begin(), key_blob.end());
return true;
}
Tpm::TpmRetryAction Tpm2Impl::LoadWrappedKey(const SecureBlob& wrapped_key,
ScopedKeyHandle* key_handle) {
CHECK(key_handle);
trunks::TPM_HANDLE handle;
scoped_ptr<trunks::AuthorizationDelegate> delegate =
trunks_factory_->GetPasswordAuthorization("");
TPM_RC result = trunks_utility_->LoadKey(wrapped_key.to_string(),
delegate.get(),
&handle);
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error loading SRK wrapped key: " << GetErrorString(result);
return Tpm::kTpmRetryFailNoRetry;
}
key_handle->reset(this, handle);
return Tpm::kTpmRetryNone;
}
bool Tpm2Impl::LegacyLoadCryptohomeKey(ScopedKeyHandle* key_handle,
SecureBlob* key_blob) {
LOG(ERROR) << "This functionality is not available in TPM2.0.";
return false;
}
void Tpm2Impl::CloseHandle(TpmKeyHandle key_handle) {
TPM_RC result = trunks_factory_->GetTpm()->FlushContextSync(key_handle,
nullptr);
if (result != TPM_RC_SUCCESS) {
LOG(WARNING) << "Error flushing tpm handle " << key_handle << ": "
<< GetErrorString(result);
}
}
Tpm::TpmRetryAction Tpm2Impl::EncryptBlob(TpmKeyHandle key_handle,
const SecureBlob& plaintext,
const SecureBlob& key,
SecureBlob* ciphertext) {
CHECK(ciphertext);
std::string tpm_ciphertext;
TPM_RC result = trunks_utility_->AsymmetricEncrypt(key_handle,
trunks::TPM_ALG_OAEP,
trunks::TPM_ALG_SHA256,
plaintext.to_string(),
nullptr,
&tpm_ciphertext);
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error encrypting plaintext: " << GetErrorString(result);
return Tpm::kTpmRetryFailNoRetry;
}
if (!CryptoLib::ObscureRSAMessage(SecureBlob(tpm_ciphertext),
key, ciphertext)) {
LOG(ERROR) << "Error obscuring tpm encrypted blob.";
return Tpm::kTpmRetryFailNoRetry;
}
return Tpm::kTpmRetryNone;
}
Tpm::TpmRetryAction Tpm2Impl::DecryptBlob(TpmKeyHandle key_handle,
const SecureBlob& ciphertext,
const SecureBlob& key,
SecureBlob* plaintext) {
CHECK(plaintext);
SecureBlob local_data;
if (!CryptoLib::UnobscureRSAMessage(ciphertext, key, &local_data)) {
LOG(ERROR) << "Error unobscureing message.";
return Tpm::kTpmRetryFailNoRetry;
}
scoped_ptr<trunks::AuthorizationDelegate> delegate =
trunks_factory_->GetPasswordAuthorization("");
std::string tpm_plaintext;
TPM_RC result = trunks_utility_->AsymmetricDecrypt(key_handle,
trunks::TPM_ALG_OAEP,
trunks::TPM_ALG_SHA256,
local_data.to_string(),
delegate.get(),
&tpm_plaintext);
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error encrypting plaintext: " << GetErrorString(result);
return Tpm::kTpmRetryFailNoRetry;
}
plaintext->assign(tpm_plaintext.begin(), tpm_plaintext.end());
return Tpm::kTpmRetryNone;
}
Tpm::TpmRetryAction Tpm2Impl::GetPublicKeyHash(TpmKeyHandle key_handle,
SecureBlob* hash) {
CHECK(hash);
trunks::TPMT_PUBLIC public_data;
TPM_RC result = trunks_utility_->GetKeyPublicArea(key_handle, &public_data);
if (result != TPM_RC_SUCCESS) {
LOG(ERROR) << "Error getting key public area: " << GetErrorString(result);
return Tpm::kTpmRetryFailNoRetry;
}
std::string public_modulus =
trunks::StringFrom_TPM2B_PUBLIC_KEY_RSA(public_data.unique.rsa);
*hash = CryptoLib::Sha256(SecureBlob(public_modulus));
return Tpm::kTpmRetryNone;
}
void Tpm2Impl::GetStatus(TpmKeyHandle key, TpmStatusInfo* status) {
LOG(FATAL) << "Not Implemented.";
}
bool Tpm2Impl::GetDictionaryAttackInfo(int* counter,
int* threshold,
bool* lockout,
int* seconds_remaining) {
LOG(FATAL) << "Not Implemented.";
return false;
}
bool Tpm2Impl::ResetDictionaryAttackMitigation(
const SecureBlob& delegate_blob,
const SecureBlob& delegate_secret) {
LOG(FATAL) << "Not Implemented.";
return false;
}
bool Tpm2Impl::PublicAreaToPublicKeyDER(const trunks::TPMT_PUBLIC& public_area,
chromeos::SecureBlob* public_key_der) {
crypto::ScopedRSA rsa(RSA_new());
rsa.get()->e = BN_new();
CHECK(rsa.get()->e) << "Error setting exponent for RSA.";
BN_set_word(rsa.get()->e, kDefaultTpmPublicExponent);
rsa.get()->n = BN_bin2bn(public_area.unique.rsa.buffer,
public_area.unique.rsa.size,
nullptr);
CHECK(rsa.get()->n) << "Error setting modulus for RSA.";
int der_length = i2d_RSAPublicKey(rsa.get(), nullptr);
if (der_length < 0) {
LOG(ERROR) << "Failed to get DER-encoded public key length.";
return false;
}
public_key_der->resize(der_length);
unsigned char* der_buffer = public_key_der->data();
der_length = i2d_RSAPublicKey(rsa.get(), &der_buffer);
if (der_length < 0) {
LOG(ERROR) << "Failed to DER-encode public key.";
return false;
}
return true;
}
} // namespace cryptohome