blob: fd334a837ab2b8ec0e5496d308bec1b1c684d748 [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.
#include "cryptohome/tpm.h"
#include <base/command_line.h>
#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include <inttypes.h>
#include <libhwsec-foundation/tpm/tpm_version.h>
#include <string>
#include "cryptohome/crypto/sha.h"
#if USE_TPM2
#include "cryptohome/tpm2_impl.h"
#endif
#if USE_TPM1
#include "cryptohome/tpm_impl.h"
#endif
#include "cryptohome/stub_tpm.h"
namespace cryptohome {
namespace {
constexpr TpmKeyHandle kInvalidKeyHandle = 0;
}
Tpm* Tpm::singleton_ = NULL;
base::Lock Tpm::singleton_lock_;
ScopedKeyHandle::ScopedKeyHandle()
: tpm_(nullptr), handle_(kInvalidKeyHandle) {}
ScopedKeyHandle::~ScopedKeyHandle() {
if (tpm_ != nullptr && handle_ != kInvalidKeyHandle) {
tpm_->CloseHandle(handle_);
}
}
TpmKeyHandle ScopedKeyHandle::value() {
return handle_;
}
TpmKeyHandle ScopedKeyHandle::release() {
TpmKeyHandle return_handle = handle_;
tpm_ = nullptr;
handle_ = kInvalidKeyHandle;
return return_handle;
}
void ScopedKeyHandle::reset(Tpm* tpm, TpmKeyHandle handle) {
if ((tpm_ != tpm) || (handle_ != handle)) {
if ((tpm_ != nullptr) && (handle_ != kInvalidKeyHandle)) {
tpm_->CloseHandle(handle_);
}
tpm_ = tpm;
handle_ = handle;
}
}
bool ScopedKeyHandle::has_value() {
return tpm_ != nullptr && handle_ != kInvalidKeyHandle;
}
int Tpm::TpmVersionInfo::GetFingerprint() const {
// The exact encoding doesn't matter as long as its unambiguous, stable and
// contains all information present in the version fields.
std::string encoded_parameters =
base::StringPrintf("%08" PRIx32 "%016" PRIx64 "%08" PRIx32 "%08" PRIx32
"%016" PRIx64 "%016zx",
family, spec_level, manufacturer, tpm_model,
firmware_version, vendor_specific.size());
encoded_parameters.append(vendor_specific);
brillo::SecureBlob hash = Sha256(
brillo::SecureBlob(encoded_parameters.begin(), encoded_parameters.end()));
// Return the first 31 bits from |hash|.
int result = hash[0] | hash[1] << 8 | hash[2] << 16 | hash[3] << 24;
return result & 0x7fffffff;
}
Tpm* Tpm::GetSingleton() {
// TODO(fes): Replace with a better atomic operation
singleton_lock_.Acquire();
if (!singleton_) {
TPM_SELECT_BEGIN;
TPM2_SECTION({ singleton_ = new Tpm2Impl(); });
TPM1_SECTION({ singleton_ = new TpmImpl(); });
OTHER_TPM_SECTION({
LOG(WARNING) << "Unknown TPM";
singleton_ = new StubTpm();
});
TPM_SELECT_END;
}
singleton_lock_.Release();
return singleton_;
}
} // namespace cryptohome