blob: 95894f158356f841ce0f52f60c288b7996967087 [file] [log] [blame]
// Copyright (c) 2012 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 "chaps/tpm_utility_impl.h"
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <base/basictypes.h>
#include <base/logging.h>
#include <base/synchronization/lock.h>
#include <chromeos/utility.h>
#include <openssl/rand.h>
#include <trousers/scoped_tss_type.h>
#include <trousers/tss.h>
#include "chaps/chaps_utility.h"
using base::AutoLock;
using chromeos::SecureBlob;
using trousers::ScopedTssContext;
using trousers::ScopedTssKey;
using trousers::ScopedTssObject;
using trousers::ScopedTssPolicy;
using std::hex;
using std::map;
using std::set;
using std::string;
using std::stringstream;
namespace chaps {
// TSSEncryptedData wraps a TSS encrypted data object. The underlying TSS object
// will be closed when this object falls out of scope.
typedef ScopedTssObject<TSS_HENCDATA> ScopedTssEncData;
class TSSEncryptedData {
public:
explicit TSSEncryptedData(TSS_HCONTEXT context)
: context_(context), handle_(context) {}
bool Create() {
TSS_RESULT result = Tspi_Context_CreateObject(context_,
TSS_OBJECT_TYPE_ENCDATA,
TSS_ENCDATA_BIND,
handle_.ptr());
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Context_CreateObject - "
<< TPMUtilityImpl::ResultToString(result);
return false;
}
return true;
}
bool GetData(string* data) {
UINT32 length = 0;
BYTE* buffer = NULL;
TSS_RESULT result = Tspi_GetAttribData(handle_,
TSS_TSPATTRIB_ENCDATA_BLOB,
TSS_TSPATTRIB_ENCDATABLOB_BLOB,
&length,
&buffer);
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_GetAttribData(ENCDATA_BLOB) - "
<< TPMUtilityImpl::ResultToString(result);
return false;
}
*data = ConvertByteBufferToString(buffer, length);
Tspi_Context_FreeMemory(context_, buffer);
return true;
}
bool SetData(const string& data) {
TSS_RESULT result = Tspi_SetAttribData(
handle_,
TSS_TSPATTRIB_ENCDATA_BLOB,
TSS_TSPATTRIB_ENCDATABLOB_BLOB,
data.length(),
ConvertStringToByteBuffer(data.data()));
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_SetAttribData(ENCDATA_BLOB) - "
<< TPMUtilityImpl::ResultToString(result);
return false;
}
return true;
}
operator TSS_HENCDATA() {
return handle_;
}
private:
TSS_HCONTEXT context_;
ScopedTssObject<TSS_HENCDATA> handle_;
DISALLOW_COPY_AND_ASSIGN(TSSEncryptedData);
};
// TSSHash wraps a TSS hash object. The underlying TSS object will be closed
// when this object falls out of scope.
class TSSHash {
public:
explicit TSSHash(TSS_HCONTEXT context)
: context_(context), handle_(context) {}
bool Create(const string& value) {
TSS_RESULT result = Tspi_Context_CreateObject(context_,
TSS_OBJECT_TYPE_HASH,
TSS_HASH_OTHER,
handle_.ptr());
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Context_CreateObject - "
<< TPMUtilityImpl::ResultToString(result);
return false;
}
result = Tspi_Hash_SetHashValue(handle_,
value.length(),
ConvertStringToByteBuffer(value.data()));
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Hash_SetHashValue - "
<< TPMUtilityImpl::ResultToString(result);
return false;
}
return true;
}
operator TSS_HHASH() {
return handle_;
}
private:
TSS_HCONTEXT context_;
ScopedTssObject<TSS_HHASH> handle_;
DISALLOW_COPY_AND_ASSIGN(TSSHash);
};
TPMUtilityImpl::TPMUtilityImpl(const string& srk_auth_data)
: is_initialized_(false),
is_srk_ready_(false),
default_policy_(0),
srk_(0),
srk_auth_data_(srk_auth_data),
srk_public_loaded_(false),
default_exponent_("\x1\x0\x1", 3),
last_handle_(0) {}
TPMUtilityImpl::~TPMUtilityImpl() {
LOG(INFO) << "Unloading keys for all slots.";
map<int, HandleInfo>::iterator it;
set<int>::iterator it2;
for (it = slot_handles_.begin(); it != slot_handles_.end(); ++it) {
set<int>* slot_handles = &it->second.handles_;
for (it2 = slot_handles->begin(); it2 != slot_handles->end(); ++it2) {
Tspi_Key_UnloadKey(GetTssHandle(*it2));
Tspi_Context_CloseObject(tsp_context_, GetTssHandle(*it2));
}
}
// These can't use ScopedTssObject because they must be closed before the
// context (tsp_context_) closes.
if (srk_)
Tspi_Context_CloseObject(tsp_context_, srk_);
if (default_policy_)
Tspi_Context_CloseObject(tsp_context_, default_policy_);
}
bool TPMUtilityImpl::Init() {
if (is_initialized_)
return true;
VLOG(1) << "TPMUtilityImpl::Init enter";
AutoLock lock(lock_);
TSS_RESULT result = TSS_SUCCESS;
result = Tspi_Context_Create(tsp_context_.ptr());
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Context_Create - " << ResultToString(result);
return false;
}
result = Tspi_Context_Connect(tsp_context_, NULL);
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Context_Connect - " << ResultToString(result);
return false;
}
// Get the default policy so we can compare against it later.
result = Tspi_Context_GetDefaultPolicy(tsp_context_, &default_policy_);
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Context_GetDefaultPolicy - " << ResultToString(result);
return false;
}
VLOG(1) << "TPMUtilityImpl::Init success";
is_initialized_ = true;
return true;
}
bool TPMUtilityImpl::InitSRK() {
if (!is_initialized_)
return false;
if (is_srk_ready_)
return true;
VLOG(1) << "TPMUtilityImpl::InitSRK enter";
// Load the SRK and assign it a usage policy with authorization data.
TSS_RESULT result = TSS_SUCCESS;
TSS_UUID uuid = TSS_UUID_SRK;
result = Tspi_Context_LoadKeyByUUID(tsp_context_,
TSS_PS_TYPE_SYSTEM,
uuid,
&srk_);
if (result != TSS_SUCCESS) {
if (result == (TSS_LAYER_TCS | TSS_E_PS_KEY_NOTFOUND)) {
LOG(WARNING) << "SRK does not exist - this is normal when the TPM is not "
<< "yet owned.";
} else {
LOG(ERROR) << "Tspi_Context_LoadKeyByUUID - " << ResultToString(result);
}
return false;
}
ScopedTssPolicy srk_policy(tsp_context_);
result = Tspi_Context_CreateObject(tsp_context_,
TSS_OBJECT_TYPE_POLICY,
TSS_POLICY_USAGE,
srk_policy.ptr());
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Context_CreateObject - " << ResultToString(result);
return false;
}
if (srk_auth_data_.empty()) {
result = Tspi_Policy_SetSecret(srk_policy, TSS_SECRET_MODE_PLAIN, 0, NULL);
} else {
LOG(INFO) << "Using non-empty secret for SRK policy.";
result = Tspi_Policy_SetSecret(
srk_policy,
TSS_SECRET_MODE_PLAIN,
srk_auth_data_.length(),
ConvertStringToByteBuffer(srk_auth_data_.data()));
}
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Policy_SetSecret - " << ResultToString(result);
return false;
}
result = Tspi_Policy_AssignToObject(srk_policy.release(), srk_);
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Policy_AssignToObject - " << ResultToString(result);
return false;
}
VLOG(1) << "TPMUtilityImpl::InitSRK success";
is_srk_ready_ = true;
return true;
}
bool TPMUtilityImpl::Authenticate(int slot_id,
const SecureBlob& auth_data,
const string& auth_key_blob,
const string& encrypted_master_key,
SecureBlob* master_key) {
VLOG(1) << "TPMUtilityImpl::Authenticate enter";
int key_handle = 0;
if (!LoadKey(slot_id, auth_key_blob, auth_data, &key_handle))
return false;
string master_key_str;
if (!Unbind(key_handle, encrypted_master_key, &master_key_str))
return false;
*master_key = SecureBlob(master_key_str.data(), master_key_str.length());
ClearString(&master_key_str);
VLOG(1) << "TPMUtilityImpl::Authenticate success";
return true;
}
bool TPMUtilityImpl::ChangeAuthData(int slot_id,
const SecureBlob& old_auth_data,
const SecureBlob& new_auth_data,
const string& old_auth_key_blob,
string* new_auth_key_blob) {
VLOG(1) << "TPMUtilityImpl::ChangeAuthData enter";
int key_handle = 0;
if (!LoadKey(slot_id, old_auth_key_blob, old_auth_data, &key_handle))
return false;
// Make sure the old auth data is ok.
string encrypted, decrypted;
if (!Bind(key_handle, "testdata", &encrypted))
return false;
if (!Unbind(key_handle, encrypted, &decrypted))
return false;
// Change the secret.
AutoLock lock(lock_);
TSS_RESULT result = TSS_SUCCESS;
ScopedTssPolicy policy(tsp_context_);
result = Tspi_Context_CreateObject(tsp_context_,
TSS_OBJECT_TYPE_POLICY,
TSS_POLICY_USAGE,
policy.ptr());
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Context_CreateObject - " << ResultToString(result);
return false;
}
result = Tspi_Policy_SetSecret(policy,
TSS_SECRET_MODE_SHA1,
new_auth_data.size(),
const_cast<BYTE*>(&new_auth_data.front()));
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Policy_SetSecret - " << ResultToString(result);
return false;
}
result = Tspi_ChangeAuth(GetTssHandle(key_handle), srk_, policy.release());
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_ChangeAuth - " << ResultToString(result);
return false;
}
if (!GetKeyBlob(GetTssHandle(key_handle), new_auth_key_blob))
return false;
VLOG(1) << "TPMUtilityImpl::ChangeAuthData success";
return true;
}
bool TPMUtilityImpl::GenerateRandom(int num_bytes, string* random_data) {
VLOG(1) << "TPMUtilityImpl::GenerateRandom enter";
AutoLock lock(lock_);
if (!InitSRK())
return false;
TSS_RESULT result = TSS_SUCCESS;
TSS_HTPM tpm;
BYTE *random_bytes = NULL;
result = Tspi_Context_GetTpmObject(tsp_context_, &tpm);
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Context_GetTpmObject - " << ResultToString(result);
return false;
}
result = Tspi_TPM_GetRandom(tpm, num_bytes, &random_bytes);
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_TPM_GetRandom - " << ResultToString(result);
return false;
}
*random_data = ConvertByteBufferToString(random_bytes, num_bytes);
Tspi_Context_FreeMemory(tsp_context_, random_bytes);
VLOG(1) << "TPMUtilityImpl::GenerateRandom success";
return true;
}
bool TPMUtilityImpl::StirRandom(const string& entropy_data) {
VLOG(1) << "TPMUtilityImpl::StirRandom enter";
AutoLock lock(lock_);
if (!InitSRK())
return false;
TSS_RESULT result = TSS_SUCCESS;
TSS_HTPM tpm;
result = Tspi_Context_GetTpmObject(tsp_context_, &tpm);
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Context_GetTpmObject - " << ResultToString(result);
return false;
}
result = Tspi_TPM_StirRandom(tpm,
entropy_data.length(),
ConvertStringToByteBuffer(entropy_data.data()));
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_TPM_StirRandom - " << ResultToString(result);
return false;
}
VLOG(1) << "TPMUtilityImpl::StirRandom success";
return true;
}
bool TPMUtilityImpl::GenerateKey(int slot,
int modulus_bits,
const string& public_exponent,
const SecureBlob& auth_data,
string* key_blob,
int* key_handle) {
VLOG(1) << "TPMUtilityImpl::GenerateKey enter";
AutoLock lock(lock_);
if (!InitSRK())
return false;
TSS_RESULT result = TSS_SUCCESS;
ScopedTssKey key(tsp_context_);
result = Tspi_Context_CreateObject(tsp_context_,
TSS_OBJECT_TYPE_RSAKEY,
GetKeyFlags(modulus_bits),
key.ptr());
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Context_CreateObject - " << ResultToString(result);
return false;
}
if (public_exponent != default_exponent_) {
LOG(WARNING) << "Non-Default Public Exponent: "
<< PrintIntVector(ConvertByteStringToVector(public_exponent));
result = Tspi_SetAttribData(
key,
TSS_TSPATTRIB_RSAKEY_INFO,
TSS_TSPATTRIB_KEYINFO_RSA_EXPONENT,
public_exponent.length(),
ConvertStringToByteBuffer(public_exponent.data()));
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_SetAttribData(EXPONENT) - " << ResultToString(result);
return false;
}
}
if (!CreateKeyPolicy(key, auth_data, false))
return false;
result = Tspi_Key_CreateKey(key, srk_, 0);
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Key_CreateKey - " << ResultToString(result);
return false;
}
result = Tspi_Key_LoadKey(key, srk_);
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Key_LoadKey - " << ResultToString(result);
return false;
}
if (!GetKeyBlob(key, key_blob))
return false;
*key_handle = CreateHandle(slot, key.release(), *key_blob, auth_data);
VLOG(1) << "TPMUtilityImpl::GenerateKey success";
return true;
}
bool TPMUtilityImpl::GetPublicKey(int key_handle,
string* public_exponent,
string* modulus) {
VLOG(1) << "TPMUtilityImpl::GetPublicKey enter";
AutoLock lock(lock_);
if (!InitSRK())
return false;
if (!GetKeyAttributeData(GetTssHandle(key_handle),
TSS_TSPATTRIB_RSAKEY_INFO,
TSS_TSPATTRIB_KEYINFO_RSA_EXPONENT,
public_exponent))
return false;
if (!GetKeyAttributeData(GetTssHandle(key_handle),
TSS_TSPATTRIB_RSAKEY_INFO,
TSS_TSPATTRIB_KEYINFO_RSA_MODULUS,
modulus))
return false;
VLOG(1) << "TPMUtilityImpl::GetPublicKey success";
return true;
}
bool TPMUtilityImpl::WrapKey(int slot,
const string& public_exponent,
const string& modulus,
const string& prime_factor,
const SecureBlob& auth_data,
string* key_blob,
int* key_handle) {
VLOG(1) << "TPMUtilityImpl::WrapKey enter";
AutoLock lock(lock_);
if (!InitSRK())
return false;
if (!GetSRKPublicKey())
return false;
ScopedTssKey key(tsp_context_);
TSS_RESULT result = Tspi_Context_CreateObject(
tsp_context_,
TSS_OBJECT_TYPE_RSAKEY,
GetKeyFlags(modulus.length() * 8),
key.ptr());
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Context_CreateObject - " << ResultToString(result);
return false;
}
if (public_exponent != default_exponent_) {
LOG(WARNING) << "Non-Default Public Exponent: "
<< PrintIntVector(ConvertByteStringToVector(public_exponent));
result = Tspi_SetAttribData(
key,
TSS_TSPATTRIB_RSAKEY_INFO,
TSS_TSPATTRIB_KEYINFO_RSA_EXPONENT,
public_exponent.length(),
ConvertStringToByteBuffer(public_exponent.data()));
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_SetAttribData(EXPONENT) - " << ResultToString(result);
return false;
}
}
result = Tspi_SetAttribData(key,
TSS_TSPATTRIB_RSAKEY_INFO,
TSS_TSPATTRIB_KEYINFO_RSA_MODULUS,
modulus.length(),
ConvertStringToByteBuffer(modulus.data()));
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_SetAttribData(MODULUS) - " << ResultToString(result);
return false;
}
// The private parameter here is one of the prime factors (p or q). The reason
// is that they are half the size of the modulus and from one factor (and the
// modulus) the entire private key can be derived. The small size allows the
// key to be wrapped in a single operation by another key of the same size.
// See TPM_STORE_ASYMKEY in TPM Main Part 2 v1.2 r116 section 10.6 page 92.
result = Tspi_SetAttribData(key,
TSS_TSPATTRIB_KEY_BLOB,
TSS_TSPATTRIB_KEYBLOB_PRIVATE_KEY,
prime_factor.length(),
ConvertStringToByteBuffer(prime_factor.data()));
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_SetAttribData(FACTOR) - " << ResultToString(result);
return false;
}
if (!CreateKeyPolicy(key, auth_data, false))
return false;
result = Tspi_Key_WrapKey(key, srk_, 0);
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Key_WrapKey - " << ResultToString(result);
return false;
}
result = Tspi_Key_LoadKey(key, srk_);
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Key_LoadKey - " << ResultToString(result);
return false;
}
if (!GetKeyBlob(key, key_blob))
return false;
*key_handle = CreateHandle(slot, key.release(), *key_blob, auth_data);
VLOG(1) << "TPMUtilityImpl::WrapKey success";
return true;
}
bool TPMUtilityImpl::LoadKey(int slot,
const string& key_blob,
const SecureBlob& auth_data,
int* key_handle) {
// Use the SRK as the parent. This is the normal case.
return LoadKeyWithParent(slot, key_blob, auth_data, srk_, key_handle);
}
bool TPMUtilityImpl::LoadKeyWithParent(int slot,
const string& key_blob,
const SecureBlob& auth_data,
int parent_key_handle,
int* key_handle) {
AutoLock lock(lock_);
if (!InitSRK())
return false;
if (IsAlreadyLoaded(slot, key_blob, key_handle))
return true;
VLOG(1) << "TPMUtilityImpl::LoadKeyWithParent enter";
ScopedTssKey key(tsp_context_);
if (!LoadKeyInternal(GetTssHandle(parent_key_handle), key_blob, auth_data,
key.ptr()))
return false;
*key_handle = CreateHandle(slot, key.release(), key_blob, auth_data);
VLOG(1) << "TPMUtilityImpl::LoadKeyWithParent success";
return true;
}
void TPMUtilityImpl::UnloadKeysForSlot(int slot) {
VLOG(1) << "TPMUtilityImpl::UnloadKeysForSlot enter";
AutoLock lock(lock_);
if (!InitSRK())
return;
set<int>* handles = &slot_handles_[slot].handles_;
set<int>::iterator it;
for (it = handles->begin(); it != handles->end(); ++it) {
Tspi_Key_UnloadKey(GetTssHandle(*it));
Tspi_Context_CloseObject(tsp_context_, GetTssHandle(*it));
}
slot_handles_.erase(slot);
LOG(INFO) << "Unloaded keys for slot " << slot;
VLOG(1) << "TPMUtilityImpl::UnloadKeysForSlot success";
}
bool TPMUtilityImpl::Bind(int key_handle,
const string& input,
string* output) {
VLOG(1) << "TPMUtilityImpl::Bind enter";
AutoLock lock(lock_);
if (!InitSRK())
return false;
TSSEncryptedData encrypted(tsp_context_);
if (!encrypted.Create())
return false;
TSS_RESULT result = Tspi_Data_Bind(encrypted,
GetTssHandle(key_handle),
input.length(),
ConvertStringToByteBuffer(input.data()));
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Data_Bind - " << ResultToString(result);
return false;
}
if (!encrypted.GetData(output))
return false;
VLOG(1) << "TPMUtilityImpl::Bind success";
return true;
}
bool TPMUtilityImpl::Unbind(int key_handle,
const string& input,
string* output) {
VLOG(1) << "TPMUtilityImpl::Unbind enter";
AutoLock lock(lock_);
if (!InitSRK())
return false;
TSSEncryptedData encrypted(tsp_context_);
if (!encrypted.Create())
return false;
if (!encrypted.SetData(input))
return false;
UINT32 length = 0;
BYTE* buffer = NULL;
TSS_RESULT result = Tspi_Data_Unbind(encrypted, GetTssHandle(key_handle),
&length, &buffer);
if (result == (TSS_LAYER_TCS | TCS_E_KM_LOADFAILED)) {
// On some TPMs, the TCS layer will fail to reload a key that has been
// evicted. If this occurs, we can attempt to reload the key manually and
// then try the operation again.
LOG(WARNING) << "TCS load failure: attempting to reload key.";
if (!ReloadKey(key_handle))
return false;
result = Tspi_Data_Unbind(encrypted, GetTssHandle(key_handle), &length,
&buffer);
}
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Data_Unbind - " << ResultToString(result);
return false;
}
*output = ConvertByteBufferToString(buffer, length);
Tspi_Context_FreeMemory(tsp_context_, buffer);
VLOG(1) << "TPMUtilityImpl::Unbind success";
return true;
}
bool TPMUtilityImpl::Sign(int key_handle,
const string& input,
string* signature) {
VLOG(1) << "TPMUtilityImpl::Sign enter";
AutoLock lock(lock_);
if (!InitSRK())
return false;
TSSHash hash(tsp_context_);
if (!hash.Create(input))
return false;
UINT32 length = 0;
BYTE* buffer = NULL;
TSS_RESULT result = Tspi_Hash_Sign(hash, GetTssHandle(key_handle), &length,
&buffer);
if (result == (TSS_LAYER_TCS | TCS_E_KM_LOADFAILED)) {
// On some TPMs, the TCS layer will fail to reload a key that has been
// evicted. If this occurs, we can attempt to reload the key manually and
// then try the operation again.
LOG(WARNING) << "TCS load failure: attempting to reload key.";
if (!ReloadKey(key_handle))
return false;
result = Tspi_Hash_Sign(hash, GetTssHandle(key_handle), &length, &buffer);
}
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Hash_Sign - " << ResultToString(result);
return false;
}
*signature = ConvertByteBufferToString(buffer, length);
Tspi_Context_FreeMemory(tsp_context_, buffer);
VLOG(1) << "TPMUtilityImpl::Sign success";
return true;
}
bool TPMUtilityImpl::Verify(int key_handle,
const string& input,
const string& signature) {
VLOG(1) << "TPMUtilityImpl::Verify enter";
AutoLock lock(lock_);
if (!InitSRK())
return false;
TSSHash hash(tsp_context_);
if (!hash.Create(input))
return false;
TSS_RESULT result = Tspi_Hash_VerifySignature(
hash,
GetTssHandle(key_handle),
signature.length(),
ConvertStringToByteBuffer(signature.data()));
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Hash_VerifySignature - " << ResultToString(result);
return false;
}
VLOG(1) << "TPMUtilityImpl::Verify success";
return true;
}
bool TPMUtilityImpl::IsSRKReady() {
VLOG(1) << "TPMUtilityImpl::IsSRKReady";
AutoLock lock(lock_);
return InitSRK();
}
int TPMUtilityImpl::CreateHandle(int slot,
TSS_HKEY key,
const string& key_blob,
const SecureBlob& auth_data) {
int handle = ++last_handle_;
HandleInfo* handle_info = &slot_handles_[slot];
handle_info->handles_.insert(handle);
handle_info->blob_handle_[key_blob] = handle;
KeyInfo* key_info = &handle_info_[handle];
key_info->tss_handle = key;
key_info->blob = key_blob;
key_info->auth_data = auth_data;
return handle;
}
bool TPMUtilityImpl::CreateKeyPolicy(TSS_HKEY key,
const SecureBlob& auth_data,
bool auth_only) {
ScopedTssPolicy policy(tsp_context_);
TSS_RESULT result = Tspi_Context_CreateObject(tsp_context_,
TSS_OBJECT_TYPE_POLICY,
TSS_POLICY_USAGE,
policy.ptr());
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Context_CreateObject - " << ResultToString(result);
return false;
}
if (auth_data.empty()) {
result = Tspi_Policy_SetSecret(policy, TSS_SECRET_MODE_NONE, 0, NULL);
} else {
result = Tspi_Policy_SetSecret(policy,
TSS_SECRET_MODE_SHA1,
auth_data.size(),
const_cast<BYTE*>(&auth_data.front()));
}
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Policy_SetSecret - " << ResultToString(result);
return false;
}
if (!auth_only) {
result = Tspi_SetAttribUint32(key,
TSS_TSPATTRIB_KEY_INFO,
TSS_TSPATTRIB_KEYINFO_ENCSCHEME,
TSS_ES_RSAESPKCSV15);
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_SetAttribUint(ENCSCHEME) - "
<< ResultToString(result);
return false;
}
result = Tspi_SetAttribUint32(key,
TSS_TSPATTRIB_KEY_INFO,
TSS_TSPATTRIB_KEYINFO_SIGSCHEME,
TSS_SS_RSASSAPKCS1V15_DER);
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_SetAttribUint(SIGSCHEME) - "
<< ResultToString(result);
return false;
}
ScopedTssPolicy migration_policy(tsp_context_);
result = Tspi_Context_CreateObject(tsp_context_,
TSS_OBJECT_TYPE_POLICY,
TSS_POLICY_MIGRATION,
migration_policy.ptr());
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_SetAttribUint(SIGSCHEME) - "
<< ResultToString(result);
return false;
}
// We need to set a migration policy but we don't want the key to be
// migratable. We'll set random authorization data and then discard it.
const int kSha1OutputBytes = 20;
unsigned char discard[kSha1OutputBytes];
RAND_bytes(discard, kSha1OutputBytes);
result = Tspi_Policy_SetSecret(migration_policy,
TSS_SECRET_MODE_SHA1,
kSha1OutputBytes,
discard);
chromeos::SecureMemset(discard, 0, kSha1OutputBytes);
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Policy_SetSecret - " << ResultToString(result);
return false;
}
result = Tspi_Policy_AssignToObject(migration_policy.release(), key);
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Policy_AssignToObject - " << ResultToString(result);
return false;
}
}
result = Tspi_Policy_AssignToObject(policy.release(), key);
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Policy_AssignToObject - " << ResultToString(result);
return false;
}
return true;
}
bool TPMUtilityImpl::GetKeyAttributeData(TSS_HKEY key,
TSS_FLAG flag,
TSS_FLAG sub_flag,
string* data) {
UINT32 length = 0;
BYTE* buffer = NULL;
TSS_RESULT result = Tspi_GetAttribData(key, flag, sub_flag, &length, &buffer);
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_GetAttribData(" << flag << ", " << sub_flag << ") - "
<< ResultToString(result);
return false;
}
*data = ConvertByteBufferToString(buffer, length);
Tspi_Context_FreeMemory(tsp_context_, buffer);
return true;
}
bool TPMUtilityImpl::GetKeyBlob(TSS_HKEY key, string* blob) {
return GetKeyAttributeData(key,
TSS_TSPATTRIB_KEY_BLOB,
TSS_TSPATTRIB_KEYBLOB_BLOB,
blob);
}
TSS_FLAG TPMUtilityImpl::GetKeyFlags(int modulus_bits) {
// We want the keys we create / wrap to be capable of signing and binding.
// This means we need to use the 'legacy' key type. Keys of this type are
// migratable by definition. See TCG Architecture Overview 1.4: 4.2.7.2.
TSS_FLAG flags = TSS_KEY_TYPE_LEGACY |
TSS_KEY_AUTHORIZATION |
TSS_KEY_MIGRATABLE;
if (modulus_bits == TSS_KEY_SIZEVAL_512BIT) {
flags |= TSS_KEY_SIZE_512;
} else if (modulus_bits == TSS_KEY_SIZEVAL_1024BIT) {
flags |= TSS_KEY_SIZE_1024;
} else if (modulus_bits == TSS_KEY_SIZEVAL_2048BIT) {
flags |= TSS_KEY_SIZE_2048;
} else if (modulus_bits == TSS_KEY_SIZEVAL_4096BIT) {
flags |= TSS_KEY_SIZE_4096;
} else if (modulus_bits == TSS_KEY_SIZEVAL_8192BIT) {
flags |= TSS_KEY_SIZE_8192;
} else if (modulus_bits == TSS_KEY_SIZEVAL_16384BIT) {
flags |= TSS_KEY_SIZE_16384;
} else {
flags |= TSS_KEY_SIZE_DEFAULT;
}
return flags;
}
bool TPMUtilityImpl::GetSRKPublicKey() {
// In order to wrap a key with the SRK we need access to the SRK public key
// and we need to get it manually. Once it's in the key object, we don't need
// to do this again.
if (!srk_public_loaded_) {
UINT32 length = 0;
BYTE *buffer = NULL;
TSS_RESULT result = Tspi_Key_GetPubKey(srk_, &length, &buffer);
if (result != TSS_SUCCESS) {
if (result == TPM_E_INVALID_KEYHANDLE) {
LOG(ERROR) << "The TPM is not configured to allow reading the public "
<< "SRK. Use 'tpm_restrictsrk -a' to allow this.";
} else {
LOG(ERROR) << "Tspi_Key_GetPubKey - " << ResultToString(result);
}
return false;
}
Tspi_Context_FreeMemory(tsp_context_, buffer);
srk_public_loaded_ = true;
}
return true;
}
TSS_HKEY TPMUtilityImpl::GetTssHandle(int key_handle) {
if (static_cast<TSS_HKEY>(key_handle) == srk_)
return srk_;
map<int, KeyInfo>::iterator it = handle_info_.find(key_handle);
if (it == handle_info_.end())
return 0;
return it->second.tss_handle;
}
bool TPMUtilityImpl::IsAlreadyLoaded(int slot,
const string& key_blob,
int* key_handle) {
HandleInfo* handle_info = &slot_handles_[slot];
map<string, int>::iterator it = handle_info->blob_handle_.find(key_blob);
if (it == handle_info->blob_handle_.end())
return false;
*key_handle = it->second;
return true;
}
bool TPMUtilityImpl::LoadKeyInternal(TSS_HKEY parent,
const string& key_blob,
const SecureBlob& auth_data,
TSS_HKEY* key) {
TSS_RESULT result = Tspi_Context_LoadKeyByBlob(
tsp_context_,
parent,
key_blob.length(),
ConvertStringToByteBuffer(key_blob.data()),
key);
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Context_LoadKeyByBlob - " << ResultToString(result);
return false;
}
TSS_HPOLICY policy;
result = Tspi_GetPolicyObject(*key, TSS_POLICY_USAGE, &policy);
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_GetPolicyObject - " << ResultToString(result);
return false;
}
if (policy == default_policy_) {
if (!CreateKeyPolicy(*key, auth_data, true))
return false;
} else if (auth_data.empty()) {
result = Tspi_Policy_SetSecret(policy, TSS_SECRET_MODE_NONE, 0, NULL);
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Policy_SetSecret - " << ResultToString(result);
return false;
}
} else {
result = Tspi_Policy_SetSecret(policy,
TSS_SECRET_MODE_SHA1,
auth_data.size(),
const_cast<BYTE*>(&auth_data.front()));
if (result != TSS_SUCCESS) {
LOG(ERROR) << "Tspi_Policy_SetSecret - " << ResultToString(result);
return false;
}
}
return true;
}
bool TPMUtilityImpl::ReloadKey(int key_handle) {
KeyInfo* key_info = &handle_info_[key_handle];
// Unload the current handle.
Tspi_Key_UnloadKey(key_info->tss_handle);
Tspi_Context_CloseObject(tsp_context_, key_info->tss_handle);
key_info->tss_handle = 0;
// Load the same key blob again.
ScopedTssKey scoped_key(tsp_context_);
if (!LoadKeyInternal(srk_, key_info->blob, key_info->auth_data,
scoped_key.ptr())) {
LOG(ERROR) << "Failed to reload key.";
return false;
}
key_info->tss_handle = scoped_key.release();
return true;
}
string TPMUtilityImpl::ResultToString(TSS_RESULT result) {
if (result == TSS_SUCCESS)
return "TSS_SUCCESS";
TSS_RESULT layer = ERROR_LAYER(result);
TSS_RESULT code = ERROR_CODE(result);
if (layer == TSS_LAYER_TPM) {
switch (code) {
case TPM_E_AUTHFAIL: return "TPM_E_AUTHFAIL";
case TPM_E_BADINDEX: return "TPM_E_BADINDEX";
case TPM_E_BAD_PARAMETER: return "TPM_E_BAD_PARAMETER";
case TPM_E_AUDITFAILURE: return "TPM_E_AUDITFAILURE";
case TPM_E_CLEAR_DISABLED: return "TPM_E_CLEAR_DISABLED";
case TPM_E_DEACTIVATED: return "TPM_E_DEACTIVATED";
case TPM_E_DISABLED: return "TPM_E_DISABLED";
case TPM_E_DISABLED_CMD: return "TPM_E_DISABLED_CMD";
case TPM_E_FAIL: return "TPM_E_FAIL";
case TPM_E_BAD_ORDINAL: return "TPM_E_BAD_ORDINAL";
case TPM_E_INSTALL_DISABLED: return "TPM_E_INSTALL_DISABLED";
case TPM_E_INVALID_KEYHANDLE: return "TPM_E_INVALID_KEYHANDLE";
case TPM_E_KEYNOTFOUND: return "TPM_E_KEYNOTFOUND";
case TPM_E_INAPPROPRIATE_ENC: return "TPM_E_INAPPROPRIATE_ENC";
case TPM_E_MIGRATEFAIL: return "TPM_E_MIGRATEFAIL";
case TPM_E_INVALID_PCR_INFO: return "TPM_E_INVALID_PCR_INFO";
case TPM_E_NOSPACE: return "TPM_E_NOSPACE";
case TPM_E_NOSRK: return "TPM_E_NOSRK";
case TPM_E_NOTSEALED_BLOB: return "TPM_E_NOTSEALED_BLOB";
case TPM_E_OWNER_SET: return "TPM_E_OWNER_SET";
case TPM_E_RESOURCES: return "TPM_E_RESOURCES";
case TPM_E_SHORTRANDOM: return "TPM_E_SHORTRANDOM";
case TPM_E_SIZE: return "TPM_E_SIZE";
case TPM_E_WRONGPCRVAL: return "TPM_E_WRONGPCRVAL";
case TPM_E_BAD_PARAM_SIZE: return "TPM_E_BAD_PARAM_SIZE";
case TPM_E_SHA_THREAD: return "TPM_E_SHA_THREAD";
case TPM_E_SHA_ERROR: return "TPM_E_SHA_ERROR";
case TPM_E_FAILEDSELFTEST: return "TPM_E_FAILEDSELFTEST";
case TPM_E_AUTH2FAIL: return "TPM_E_AUTH2FAIL";
case TPM_E_BADTAG: return "TPM_E_BADTAG";
case TPM_E_IOERROR: return "TPM_E_IOERROR";
case TPM_E_ENCRYPT_ERROR: return "TPM_E_ENCRYPT_ERROR";
case TPM_E_DECRYPT_ERROR: return "TPM_E_DECRYPT_ERROR";
case TPM_E_INVALID_AUTHHANDLE: return "TPM_E_INVALID_AUTHHANDLE";
case TPM_E_NO_ENDORSEMENT: return "TPM_E_NO_ENDORSEMENT";
case TPM_E_INVALID_KEYUSAGE: return "TPM_E_INVALID_KEYUSAGE";
case TPM_E_WRONG_ENTITYTYPE: return "TPM_E_WRONG_ENTITYTYPE";
case TPM_E_INVALID_POSTINIT: return "TPM_E_INVALID_POSTINIT";
case TPM_E_INAPPROPRIATE_SIG: return "TPM_E_INAPPROPRIATE_SIG";
case TPM_E_BAD_KEY_PROPERTY: return "TPM_E_BAD_KEY_PROPERTY";
case TPM_E_BAD_MIGRATION: return "TPM_E_BAD_MIGRATION";
case TPM_E_BAD_SCHEME: return "TPM_E_BAD_SCHEME";
case TPM_E_BAD_DATASIZE: return "TPM_E_BAD_DATASIZE";
case TPM_E_BAD_MODE: return "TPM_E_BAD_MODE";
case TPM_E_BAD_PRESENCE: return "TPM_E_BAD_PRESENCE";
case TPM_E_BAD_VERSION: return "TPM_E_BAD_VERSION";
case TPM_E_NO_WRAP_TRANSPORT: return "TPM_E_NO_WRAP_TRANSPORT";
case TPM_E_AUDITFAIL_UNSUCCESSFUL: return "TPM_E_AUDITFAIL_UNSUCCESSFUL";
case TPM_E_AUDITFAIL_SUCCESSFUL: return "TPM_E_AUDITFAIL_SUCCESSFUL";
case TPM_E_NOTRESETABLE: return "TPM_E_NOTRESETABLE";
case TPM_E_NOTLOCAL: return "TPM_E_NOTLOCAL";
case TPM_E_BAD_TYPE: return "TPM_E_BAD_TYPE";
case TPM_E_INVALID_RESOURCE: return "TPM_E_INVALID_RESOURCE";
case TPM_E_NOTFIPS: return "TPM_E_NOTFIPS";
case TPM_E_INVALID_FAMILY: return "TPM_E_INVALID_FAMILY";
case TPM_E_NO_NV_PERMISSION: return "TPM_E_NO_NV_PERMISSION";
case TPM_E_REQUIRES_SIGN: return "TPM_E_REQUIRES_SIGN";
case TPM_E_KEY_NOTSUPPORTED: return "TPM_E_KEY_NOTSUPPORTED";
case TPM_E_AUTH_CONFLICT: return "TPM_E_AUTH_CONFLICT";
case TPM_E_AREA_LOCKED: return "TPM_E_AREA_LOCKED";
case TPM_E_BAD_LOCALITY: return "TPM_E_BAD_LOCALITY";
case TPM_E_READ_ONLY: return "TPM_E_READ_ONLY";
case TPM_E_PER_NOWRITE: return "TPM_E_PER_NOWRITE";
case TPM_E_FAMILYCOUNT: return "TPM_E_FAMILYCOUNT";
case TPM_E_WRITE_LOCKED: return "TPM_E_WRITE_LOCKED";
case TPM_E_BAD_ATTRIBUTES: return "TPM_E_BAD_ATTRIBUTES";
case TPM_E_INVALID_STRUCTURE: return "TPM_E_INVALID_STRUCTURE";
case TPM_E_KEY_OWNER_CONTROL: return "TPM_E_KEY_OWNER_CONTROL";
case TPM_E_BAD_COUNTER: return "TPM_E_BAD_COUNTER";
case TPM_E_NOT_FULLWRITE: return "TPM_E_NOT_FULLWRITE";
case TPM_E_CONTEXT_GAP: return "TPM_E_CONTEXT_GAP";
case TPM_E_MAXNVWRITES: return "TPM_E_MAXNVWRITES";
case TPM_E_NOOPERATOR: return "TPM_E_NOOPERATOR";
case TPM_E_RESOURCEMISSING: return "TPM_E_RESOURCEMISSING";
case TPM_E_DELEGATE_LOCK: return "TPM_E_DELEGATE_LOCK";
case TPM_E_DELEGATE_FAMILY: return "TPM_E_DELEGATE_FAMILY";
case TPM_E_DELEGATE_ADMIN: return "TPM_E_DELEGATE_ADMIN";
case TPM_E_TRANSPORT_NOTEXCLUSIVE: return "TPM_E_TRANSPORT_NOTEXCLUSIVE";
case TPM_E_OWNER_CONTROL: return "TPM_E_OWNER_CONTROL";
case TPM_E_DAA_RESOURCES: return "TPM_E_DAA_RESOURCES";
case TPM_E_DAA_INPUT_DATA0: return "TPM_E_DAA_INPUT_DATA0";
case TPM_E_DAA_INPUT_DATA1: return "TPM_E_DAA_INPUT_DATA1";
case TPM_E_DAA_ISSUER_SETTINGS: return "TPM_E_DAA_ISSUER_SETTINGS";
case TPM_E_DAA_TPM_SETTINGS: return "TPM_E_DAA_TPM_SETTINGS";
case TPM_E_DAA_STAGE: return "TPM_E_DAA_STAGE";
case TPM_E_DAA_ISSUER_VALIDITY: return "TPM_E_DAA_ISSUER_VALIDITY";
case TPM_E_DAA_WRONG_W: return "TPM_E_DAA_WRONG_W";
case TPM_E_BAD_HANDLE: return "TPM_E_BAD_HANDLE";
case TPM_E_BAD_DELEGATE: return "TPM_E_BAD_DELEGATE";
case TPM_E_BADCONTEXT: return "TPM_E_BADCONTEXT";
case TPM_E_TOOMANYCONTEXTS: return "TPM_E_TOOMANYCONTEXTS";
case TPM_E_MA_TICKET_SIGNATURE: return "TPM_E_MA_TICKET_SIGNATURE";
case TPM_E_MA_DESTINATION: return "TPM_E_MA_DESTINATION";
case TPM_E_MA_SOURCE: return "TPM_E_MA_SOURCE";
case TPM_E_MA_AUTHORITY: return "TPM_E_MA_AUTHORITY";
case TPM_E_PERMANENTEK: return "TPM_E_PERMANENTEK";
case TPM_E_BAD_SIGNATURE: return "TPM_E_BAD_SIGNATURE";
case TPM_E_NOCONTEXTSPACE: return "TPM_E_NOCONTEXTSPACE";
case TPM_E_RETRY: return "TPM_E_RETRY";
case TPM_E_NEEDS_SELFTEST: return "TPM_E_NEEDS_SELFTEST";
case TPM_E_DOING_SELFTEST: return "TPM_E_DOING_SELFTEST";
case TPM_E_DEFEND_LOCK_RUNNING: return "TPM_E_DEFEND_LOCK_RUNNING";
}
} else if (layer == TSS_LAYER_TDDL) {
switch (code) {
case TDDL_E_FAIL: return "TDDL_E_FAIL";
case TDDL_E_TIMEOUT: return "TDDL_E_TIMEOUT";
case TDDL_E_ALREADY_OPENED: return "TDDL_E_ALREADY_OPENED";
case TDDL_E_ALREADY_CLOSED: return "TDDL_E_ALREADY_CLOSED";
case TDDL_E_INSUFFICIENT_BUFFER: return "TDDL_E_INSUFFICIENT_BUFFER";
case TDDL_E_COMMAND_COMPLETED: return "TDDL_E_COMMAND_COMPLETED";
case TDDL_E_COMMAND_ABORTED: return "TDDL_E_COMMAND_ABORTED";
case TDDL_E_IOERROR: return "TDDL_E_IOERROR";
case TDDL_E_BADTAG: return "TDDL_E_BADTAG";
case TDDL_E_COMPONENT_NOT_FOUND: return "TDDL_E_COMPONENT_NOT_FOUND";
}
} else if (layer == TSS_LAYER_TCS) {
switch (code) {
case TCS_E_INVALID_CONTEXTHANDLE: return "TCS_E_INVALID_CONTEXTHANDLE";
case TCS_E_INVALID_KEYHANDLE: return "TCS_E_INVALID_KEYHANDLE";
case TCS_E_INVALID_AUTHHANDLE: return "TCS_E_INVALID_AUTHHANDLE";
case TCS_E_INVALID_AUTHSESSION: return "TCS_E_INVALID_AUTHSESSION";
case TCS_E_INVALID_KEY: return "TCS_E_INVALID_KEY";
case TCS_E_KEY_MISMATCH: return "TCS_E_KEY_MISMATCH";
case TCS_E_KM_LOADFAILED: return "TCS_E_KM_LOADFAILED";
case TCS_E_KEY_CONTEXT_RELOAD: return "TCS_E_KEY_CONTEXT_RELOAD";
case TCS_E_BAD_INDEX: return "TCS_E_BAD_INDEX";
case TCS_E_KEY_ALREADY_REGISTERED: return "TCS_E_KEY_ALREADY_REGISTERED";
case TCS_E_BAD_PARAMETER: return "TCS_E_BAD_PARAMETER";
case TCS_E_OUTOFMEMORY: return "TCS_E_OUTOFMEMORY";
case TCS_E_NOTIMPL: return "TCS_E_NOTIMPL";
case TCS_E_INTERNAL_ERROR: return "TCS_E_INTERNAL_ERROR";
}
} else if (layer == TSS_LAYER_TSP) {
switch (code) {
case TSS_E_FAIL: return "TSS_E_FAIL";
case TSS_E_BAD_PARAMETER: return "TSS_E_BAD_PARAMETER";
case TSS_E_INTERNAL_ERROR: return "TSS_E_INTERNAL_ERROR";
case TSS_E_OUTOFMEMORY: return "TSS_E_OUTOFMEMORY";
case TSS_E_NOTIMPL: return "TSS_E_NOTIMPL";
case TSS_E_KEY_ALREADY_REGISTERED: return "TSS_E_KEY_ALREADY_REGISTERED";
case TSS_E_TPM_UNEXPECTED: return "TSS_E_TPM_UNEXPECTED";
case TSS_E_COMM_FAILURE: return "TSS_E_COMM_FAILURE";
case TSS_E_TIMEOUT: return "TSS_E_TIMEOUT";
case TSS_E_TPM_UNSUPPORTED_FEATURE:
return "TSS_E_TPM_UNSUPPORTED_FEATURE";
case TSS_E_CANCELED: return "TSS_E_CANCELED";
case TSS_E_PS_KEY_NOTFOUND: return "TSS_E_PS_KEY_NOTFOUND";
case TSS_E_PS_KEY_EXISTS: return "TSS_E_PS_KEY_EXISTS";
case TSS_E_PS_BAD_KEY_STATE: return "TSS_E_PS_BAD_KEY_STATE";
case TSS_E_INVALID_OBJECT_TYPE: return "TSS_E_INVALID_OBJECT_TYPE";
case TSS_E_NO_CONNECTION: return "TSS_E_NO_CONNECTION";
case TSS_E_CONNECTION_FAILED: return "TSS_E_CONNECTION_FAILED";
case TSS_E_CONNECTION_BROKEN: return "TSS_E_CONNECTION_BROKEN";
case TSS_E_HASH_INVALID_ALG: return "TSS_E_HASH_INVALID_ALG";
case TSS_E_HASH_INVALID_LENGTH: return "TSS_E_HASH_INVALID_LENGTH";
case TSS_E_HASH_NO_DATA: return "TSS_E_HASH_NO_DATA";
case TSS_E_INVALID_ATTRIB_FLAG: return "TSS_E_INVALID_ATTRIB_FLAG";
case TSS_E_INVALID_ATTRIB_SUBFLAG: return "TSS_E_INVALID_ATTRIB_SUBFLAG";
case TSS_E_INVALID_ATTRIB_DATA: return "TSS_E_INVALID_ATTRIB_DATA";
case TSS_E_INVALID_OBJECT_INITFLAG:
return "TSS_E_INVALID_OBJECT_INITFLAG";
case TSS_E_NO_PCRS_SET: return "TSS_E_NO_PCRS_SET";
case TSS_E_KEY_NOT_LOADED: return "TSS_E_KEY_NOT_LOADED";
case TSS_E_KEY_NOT_SET: return "TSS_E_KEY_NOT_SET";
case TSS_E_VALIDATION_FAILED: return "TSS_E_VALIDATION_FAILED";
case TSS_E_TSP_AUTHREQUIRED: return "TSS_E_TSP_AUTHREQUIRED";
case TSS_E_TSP_AUTH2REQUIRED: return "TSS_E_TSP_AUTH2REQUIRED";
case TSS_E_TSP_AUTHFAIL: return "TSS_E_TSP_AUTHFAIL";
case TSS_E_TSP_AUTH2FAIL: return "TSS_E_TSP_AUTH2FAIL";
case TSS_E_KEY_NO_MIGRATION_POLICY:
return "TSS_E_KEY_NO_MIGRATION_POLICY";
case TSS_E_POLICY_NO_SECRET: return "TSS_E_POLICY_NO_SECRET";
case TSS_E_INVALID_OBJ_ACCESS: return "TSS_E_INVALID_OBJ_ACCESS";
case TSS_E_INVALID_ENCSCHEME: return "TSS_E_INVALID_ENCSCHEME";
case TSS_E_INVALID_SIGSCHEME: return "TSS_E_INVALID_SIGSCHEME";
case TSS_E_ENC_INVALID_LENGTH: return "TSS_E_ENC_INVALID_LENGTH";
case TSS_E_ENC_NO_DATA: return "TSS_E_ENC_NO_DATA";
case TSS_E_ENC_INVALID_TYPE: return "TSS_E_ENC_INVALID_TYPE";
case TSS_E_INVALID_KEYUSAGE: return "TSS_E_INVALID_KEYUSAGE";
case TSS_E_VERIFICATION_FAILED: return "TSS_E_VERIFICATION_FAILED";
case TSS_E_HASH_NO_IDENTIFIER: return "TSS_E_HASH_NO_IDENTIFIER";
case TSS_E_INVALID_HANDLE: return "TSS_E_INVALID_HANDLE";
case TSS_E_SILENT_CONTEXT: return "TSS_E_SILENT_CONTEXT";
case TSS_E_EK_CHECKSUM: return "TSS_E_EK_CHECKSUM";
case TSS_E_DELEGATION_NOTSET: return "TSS_E_DELEGATION_NOTSET";
case TSS_E_DELFAMILY_NOTFOUND: return "TSS_E_DELFAMILY_NOTFOUND";
case TSS_E_DELFAMILY_ROWEXISTS: return "TSS_E_DELFAMILY_ROWEXISTS";
case TSS_E_VERSION_MISMATCH: return "TSS_E_VERSION_MISMATCH";
case TSS_E_DAA_AR_DECRYPTION_ERROR:
return "TSS_E_DAA_AR_DECRYPTION_ERROR";
case TSS_E_DAA_AUTHENTICATION_ERROR:
return "TSS_E_DAA_AUTHENTICATION_ERROR";
case TSS_E_DAA_CHALLENGE_RESPONSE_ERROR:
return "TSS_E_DAA_CHALLENGE_RESPONSE_ERROR";
case TSS_E_DAA_CREDENTIAL_PROOF_ERROR:
return "TSS_E_DAA_CREDENTIAL_PROOF_ERROR";
case TSS_E_DAA_CREDENTIAL_REQUEST_PROOF_ERROR:
return "TSS_E_DAA_CREDENTIAL_REQUEST_PROOF_ERROR";
case TSS_E_DAA_ISSUER_KEY_ERROR: return "TSS_E_DAA_ISSUER_KEY_ERROR";
case TSS_E_DAA_PSEUDONYM_ERROR: return "TSS_E_DAA_PSEUDONYM_ERROR";
case TSS_E_INVALID_RESOURCE: return "TSS_E_INVALID_RESOURCE";
case TSS_E_NV_AREA_EXIST: return "TSS_E_NV_AREA_EXIST";
case TSS_E_NV_AREA_NOT_EXIST: return "TSS_E_NV_AREA_NOT_EXIST";
case TSS_E_TSP_TRANS_AUTHFAIL: return "TSS_E_TSP_TRANS_AUTHFAIL";
case TSS_E_TSP_TRANS_AUTHREQUIRED: return "TSS_E_TSP_TRANS_AUTHREQUIRED";
case TSS_E_TSP_TRANS_NOTEXCLUSIVE: return "TSS_E_TSP_TRANS_NOTEXCLUSIVE";
case TSS_E_TSP_TRANS_FAIL: return "TSS_E_TSP_TRANS_FAIL";
case TSS_E_TSP_TRANS_NO_PUBKEY: return "TSS_E_TSP_TRANS_NO_PUBKEY";
case TSS_E_NO_ACTIVE_COUNTER: return "TSS_E_NO_ACTIVE_COUNTER";
}
}
// Unknown value, just give the hex numeric value.
stringstream ss;
ss << "0x" << hex << result;
return ss.str();
}
} // namespace chaps